• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

Nepomuk-Core

  • sources
  • kde-4.12
  • kdelibs
  • nepomuk-core
  • libnepomukcore
  • resource
resourcedata.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Nepomuk KDE project.
3  * Copyright (C) 2006-2010 Sebastian Trueg <trueg@kde.org>
4  * Copyright (C) 2010-2012 Vishesh Handa <handa.vish@gmail.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 
22 #include "resourcedata.h"
23 #include "resourcemanager.h"
24 #include "resourcemanager_p.h"
25 #include "resource.h"
26 #include "tools.h"
27 #include "nie.h"
28 #include "nfo.h"
29 #include "pimo.h"
30 #include "nepomukmainmodel.h"
31 #include "class.h"
32 #include "resourcewatcher.h"
33 #include "dbustypes.h"
34 
35 #include <Soprano/Statement>
36 #include <Soprano/StatementIterator>
37 #include <Soprano/QueryResultIterator>
38 #include <Soprano/NodeIterator>
39 #include <Soprano/Model>
40 #include <Soprano/Vocabulary/RDFS>
41 #include <Soprano/Vocabulary/RDF>
42 #include <Soprano/Vocabulary/Xesam>
43 #include <Soprano/Vocabulary/NAO>
44 
45 #include <QtCore/QFile>
46 #include <QtCore/QDateTime>
47 #include <QtCore/QMutexLocker>
48 #include <QtCore/QFileInfo>
49 
50 #include <kdebug.h>
51 #include <kurl.h>
52 #include <kcomponentdata.h>
53 
54 #include <kdbusconnectionpool.h>
55 #include <QtDBus/QDBusMessage>
56 
57 using namespace Soprano;
58 
59 #define MAINMODEL (m_rm->m_manager->mainModel())
60 
61 using namespace Soprano::Vocabulary;
62 using namespace Nepomuk2::Vocabulary;
63 
64 Nepomuk2::ResourceData::ResourceData( const QUrl& uri, const QUrl& kickOffUri, const QUrl& type, ResourceManagerPrivate* rm )
65  : m_uri(uri),
66  m_type(type.isEmpty() ? RDFS::Resource() : type),
67  m_dataMutex(QMutex::Recursive),
68  m_cacheDirty(false),
69  m_addedToWatcher(false),
70  m_watchEnabled(false),
71  m_rm(rm)
72 {
73  if( !uri.isEmpty() ) {
74  m_cacheDirty = true;
75 
76  QMutexLocker locker(&m_rm->mutex);
77  m_rm->m_initializedData.insert( uri, this );
78  }
79 
80  if( !kickOffUri.isEmpty() ) {
81  if( kickOffUri.scheme().isEmpty() ) {
82  m_naoIdentifier = kickOffUri.toString();
83  m_cache.insert( NAO::identifier(), m_naoIdentifier );
84 
85  QMutexLocker locker(&m_rm->mutex);
86  m_rm->m_identifierKickOff.insert(m_naoIdentifier, this);
87  }
88  else {
89  m_nieUrl = kickOffUri;
90  if( m_nieUrl.isLocalFile() ) {
91  // Point to the actual file in the case of a system link
92  QFileInfo fileInfo(m_nieUrl.toLocalFile());
93  if( fileInfo.isSymLink() )
94  m_nieUrl = KUrl::fromLocalFile( fileInfo.canonicalFilePath() );
95  }
96  m_cache.insert( NIE::url(), m_nieUrl );
97 
98  QMutexLocker locker(&m_rm->mutex);
99  m_rm->m_urlKickOff.insert(m_nieUrl, this);
100  }
101  }
102 }
103 
104 
105 Nepomuk2::ResourceData::~ResourceData()
106 {
107  resetAll();
108 }
109 
110 
111 bool Nepomuk2::ResourceData::isFile()
112 {
113  QMutexLocker lock(&m_dataMutex);
114  return( m_uri.scheme() == QLatin1String("file") ||
115  m_nieUrl.scheme() == QLatin1String("file") ||
116  hasProperty( RDF::type(), NFO::FileDataObject() ) );
117  // The hasProperty should be const - It shouldn't load the entire cache. Maybe
118 }
119 
120 
121 QUrl Nepomuk2::ResourceData::uri() const
122 {
123  QMutexLocker lock(&m_dataMutex);
124  return m_uri;
125 }
126 
127 
128 QUrl Nepomuk2::ResourceData::type()
129 {
130  QUrl mainType = RDFS::Resource();
131 
132  if( !load() )
133  return mainType;
134 
135  QMutexLocker lock(&m_dataMutex);
136  QList<QUrl> types = m_cache.value(RDF::type()).toUrlList();
137  foreach(const QUrl& t, types) {
138  Types::Class currentTypeClass = mainType;
139  Types::Class storedTypeClass = t;
140 
141  // Keep the type that is further down the hierarchy
142  if ( storedTypeClass.isSubClassOf( currentTypeClass ) ) {
143  mainType = storedTypeClass.uri();
144  }
145  else {
146  // This is a little convenience hack since the user is most likely
147  // more interested in the file content than the actual file
148  // the same is true for nie:DataObject vs. nie:InformationElement
149  Types::Class nieInformationElementClass( NIE::InformationElement() );
150  Types::Class nieDataObjectClass( NIE::DataObject() );
151  if( ( currentTypeClass == nieDataObjectClass ||
152  currentTypeClass.isSubClassOf( nieDataObjectClass ) ) &&
153  ( storedTypeClass == nieInformationElementClass ||
154  storedTypeClass.isSubClassOf( nieInformationElementClass ) ) ) {
155  mainType = storedTypeClass.uri();
156  }
157  }
158  }
159 
160  return mainType;
161 }
162 
163 
164 void Nepomuk2::ResourceData::resetAll()
165 {
166  QMutexLocker rmMutexLocker(&m_rm->mutex);
167  QMutexLocker locker(&m_dataMutex);
168  // remove us from all caches (store() will re-insert us later if necessary)
169 
170  // IMPORTANT:
171  // Remove from the kickOffList before removing from the resource watcher
172  // This is required cause otherwise the Resource::fromResourceUri creates a new
173  // resource which is correctly identified to the ResourceData (this), and it is
174  // then deleted, which calls resetAll and this cycle continues.
175  const QString nao = m_cache.value(NAO::identifier()).toString();
176  m_rm->m_identifierKickOff.remove( nao );
177  const QUrl nieUrl = m_cache.value(NIE::url()).toUrl();
178  m_rm->m_urlKickOff.remove( nieUrl );
179 
180  if( !m_uri.isEmpty() ) {
181  m_rm->m_initializedData.remove( m_uri );
182  removeFromWatcher();
183  }
184 
185  // reset all variables
186  m_uri.clear();
187  m_nieUrl.clear();
188  m_naoIdentifier.clear();
189  m_cache.clear();
190  m_cacheDirty = false;
191  m_type = RDFS::Resource();
192 }
193 
194 
195 QHash<QUrl, Nepomuk2::Variant> Nepomuk2::ResourceData::allProperties()
196 {
197  if( !load() )
198  return QHash<QUrl, Nepomuk2::Variant>();
199  else {
200  QMutexLocker lock(&m_dataMutex);
201  return m_cache;
202  }
203 }
204 
205 
206 bool Nepomuk2::ResourceData::hasProperty( const QUrl& uri )
207 {
208  if( !load() )
209  return false;
210 
211  QMutexLocker lock(&m_dataMutex);
212  QHash<QUrl, Variant>::const_iterator it = m_cache.constFind( uri );
213  if( it == m_cache.constEnd() )
214  return false;
215 
216  return true;
217 }
218 
219 
220 bool Nepomuk2::ResourceData::hasProperty( const QUrl& p, const Variant& v )
221 {
222  if( !load() )
223  return false;
224 
225  QMutexLocker lock(&m_dataMutex);
226  QHash<QUrl, Variant>::const_iterator it = m_cache.constFind( p );
227  if( it == m_cache.constEnd() )
228  return false;
229 
230  QList<Variant> thisVals = it.value().toVariantList();
231  QList<Variant> vals = v.toVariantList();
232  Q_FOREACH( const Variant& val, vals ) {
233  if( !thisVals.contains(val) )
234  return false;
235  }
236  return true;
237 }
238 
239 
240 Nepomuk2::Variant Nepomuk2::ResourceData::property( const QUrl& uri )
241 {
242  if( !load() )
243  return Variant();
244 
245  // we need to protect the reading, too. load my be triggered from another thread's
246  // connection to a Soprano statement signal
247  QMutexLocker lock(&m_dataMutex);
248 
249  QHash<QUrl, Variant>::const_iterator it = m_cache.constFind( uri );
250  if ( it == m_cache.constEnd() ) {
251  return Variant();
252  }
253  else {
254  return *it;
255  }
256 }
257 
258 
259 bool Nepomuk2::ResourceData::store()
260 {
261  QMutexLocker lock(&m_dataMutex);
262 
263  if ( m_uri.isEmpty() ) {
264  QList<QUrl> types;
265  if ( m_nieUrl.isValid() && m_nieUrl.isLocalFile() ) {
266  types << NFO::FileDataObject();
267  if( QFileInfo(m_nieUrl.toLocalFile()).isDir() )
268  types << NFO::Folder();
269  }
270  types << m_type;
271 
272  QDBusMessage msg = QDBusMessage::createMethodCall( QLatin1String("org.kde.NepomukStorage"),
273  QLatin1String("/datamanagement"),
274  QLatin1String("org.kde.nepomuk.DataManagement"),
275  QLatin1String("createResource") );
276 
277  msg.setArguments( QVariantList()
278  << DBus::convertUriList(types)
279  << QString() << QString()
280  << KGlobal::mainComponent().componentName() );
281 
282  QDBusConnection bus = KDBusConnectionPool::threadConnection();
283  QDBusMessage reply = bus.call( msg );
284  if( reply.type() == QDBusMessage::ErrorMessage ) {
285  //TODO: Set the error somehow
286  kWarning() << reply.errorMessage();
287  return false;
288  }
289  else {
290  m_uri = reply.arguments().at(0).toUrl();
291 
292  QList<Soprano::Node> nodes = MAINMODEL->listStatements( m_uri, RDF::type(), QUrl() )
293  .iterateObjects().allNodes();
294  QList<QUrl> types;
295  foreach(const Soprano::Node& node, nodes)
296  types << node.uri();
297  m_cache.insert(RDF::type(), types);
298  }
299  if( !m_naoIdentifier.isEmpty() ) {
300  setProperty( NAO::identifier(), m_naoIdentifier );
301  setProperty( NAO::prefLabel(), m_naoIdentifier );
302  m_naoIdentifier.clear();
303  }
304  if( !m_nieUrl.isEmpty() ) {
305  setProperty( NIE::url(), m_nieUrl );
306  m_nieUrl.clear();
307  }
308 
309  addToWatcher();
310  lock.unlock();
311  QMutexLocker rmlock(&m_rm->mutex);
312  // Add us to the initialized data, i.e. make us "valid"
313  //Note: once m_uri is non-empty, it doesn't change
314  m_rm->m_initializedData.insert( m_uri, this );
315 
316  }
317 
318  return true;
319 }
320 
321 // Caller must hold m_dataMutex
322 void Nepomuk2::ResourceData::addToWatcher()
323 {
324  if( m_watchEnabled && !m_addedToWatcher && !m_uri.isEmpty() ) {
325  //Obey the locking rules: the rm mutex gets locked before the dataMutex.
326  m_dataMutex.unlock();
327  //It is safe to use m_uri with dataMutex unlocked because it is only modified to set it,
328  //and we check it is non-empty before calling addToWatcher.
329  m_rm->addToWatcher( m_uri );
330  m_dataMutex.lock();
331  m_addedToWatcher = true;
332  }
333 }
334 
335 void Nepomuk2::ResourceData::removeFromWatcher()
336 {
337  if( m_addedToWatcher ) {
338  //Obey the locking rules: the rm mutex gets locked before the dataMutex.
339  m_dataMutex.unlock();
340  m_rm->removeFromWatcher( m_uri );
341  m_dataMutex.lock();
342  m_addedToWatcher = false;
343  }
344 }
345 
346 
347 bool Nepomuk2::ResourceData::load()
348 {
349  QMutexLocker lock(&m_dataMutex);
350  if (!m_cacheDirty) {
351  // Fast path: nothing to do.
352  return true;
353  }
354  if ( !m_uri.isValid() )
355  return false;
356 
357  const QString oldNaoIdentifier = m_cache[NAO::identifier()].toString();
358  const QUrl oldNieUrl = m_cache[NIE::url()].toUrl();
359 
360  m_cache.clear();
361  addToWatcher();
362 
363  //
364  // We exclude properties that are part of the inference graph
365  // It would only pollute the user interface
366  //
367  Soprano::QueryResultIterator it = MAINMODEL->executeQuery(QString("select distinct ?p ?o where { "
368  "%1 ?p ?o . }").arg(Soprano::Node::resourceToN3(m_uri)),
369  Soprano::Query::QueryLanguageSparqlNoInference);
370  while ( it.next() ) {
371  QUrl p = it["p"].uri();
372  m_cache[p].append( Variant::fromNode( it["o"] ) );
373  }
374 
375  const QString newNaoIdentifier = m_cache.value(NAO::identifier()).toString();
376  const QUrl newNieUrl = m_cache.value(NIE::url()).toUrl();
377  m_cacheDirty = false;
378 
379  lock.unlock();
380 
381  QMutexLocker rmlock(&m_rm->mutex); // for updating the lists. Must be locked first
382  updateIdentifierLists( oldNaoIdentifier, newNaoIdentifier );
383  updateUrlLists( oldNieUrl, newNieUrl );
384 
385  return true;
386 }
387 
388 
389 void Nepomuk2::ResourceData::setProperty( const QUrl& uri, const Nepomuk2::Variant& value )
390 {
391  Q_ASSERT( uri.isValid() );
392 
393  if( store() ) {
394  // step 0: make sure this resource is in the store
395 
396  // update the store
397  QVariantList varList;
398  foreach( const Variant& var, value.toVariantList() ) {
399  // make sure resource values are identified and in the store
400  if( var.simpleType() == qMetaTypeId<Resource>() ) {
401  Resource res = var.toResource();
402  res.determineFinalResourceData();
403  res.m_data->store();
404 
405  varList << res.uri();
406  }
407  else {
408  varList << var.variant();
409  }
410  }
411 
412  QMutexLocker lock(&m_dataMutex);
413  // update the store
414  QDBusMessage msg = QDBusMessage::createMethodCall( QLatin1String("org.kde.NepomukStorage"),
415  QLatin1String("/datamanagement"),
416  QLatin1String("org.kde.nepomuk.DataManagement"),
417  QLatin1String("setProperty") );
418 
419  msg.setArguments( QVariantList()
420  << DBus::convertUriList(QList<QUrl>() << m_uri)
421  << DBus::convertUri(uri)
422  << QVariant(DBus::normalizeVariantList(varList))
423  << KGlobal::mainComponent().componentName() );
424 
425  QDBusConnection bus = KDBusConnectionPool::threadConnection();
426  QDBusMessage reply = bus.call( msg );
427  if( reply.type() == QDBusMessage::ErrorMessage ) {
428  //TODO: Set the error somehow
429  kWarning() << reply.errorMessage();
430  return;
431  }
432 
433  const Nepomuk2::Variant oldvalue = m_cache.value(uri);
434  // update the cache for now
435  if( value.isValid() )
436  m_cache[uri] = value;
437  else
438  m_cache.remove(uri);
439  lock.unlock();
440  // update the kickofflists
441  updateKickOffLists( uri, oldvalue, value );
442  }
443 }
444 
445 
446 void Nepomuk2::ResourceData::addProperty( const QUrl& uri, const Nepomuk2::Variant& value )
447 {
448  Q_ASSERT( uri.isValid() );
449 
450  if( value.isValid() && store() ) {
451  // step 0: make sure this resource is in the store
452 
453  // update the store
454  QVariantList varList;
455  foreach( const Nepomuk2::Variant var, value.toVariantList() ) {
456  // make sure resource values are in the store
457  if( var.simpleType() == qMetaTypeId<Resource>() ) {
458  Resource res = var.toResource();
459  res.determineFinalResourceData();
460  res.m_data->store();
461 
462  varList << res.uri();
463  }
464  else {
465  varList << var.variant();
466  }
467  }
468 
469  QMutexLocker lock(&m_dataMutex);
470  QDBusMessage msg = QDBusMessage::createMethodCall( QLatin1String("org.kde.NepomukStorage"),
471  QLatin1String("/datamanagement"),
472  QLatin1String("org.kde.nepomuk.DataManagement"),
473  QLatin1String("addProperty") );
474  msg.setArguments( QVariantList()
475  << DBus::convertUriList(QList<QUrl>() << m_uri)
476  << DBus::convertUri(uri)
477  << QVariant(DBus::normalizeVariantList(varList))
478  << KGlobal::mainComponent().componentName() );
479 
480  QDBusConnection bus = KDBusConnectionPool::threadConnection();
481  QDBusMessage reply = bus.call( msg );
482  if( reply.type() == QDBusMessage::ErrorMessage ) {
483  //TODO: Set the error somehow
484  kWarning() << reply.errorMessage();
485  return;
486  }
487 
488  const Nepomuk2::Variant oldvalue = m_cache.value(uri);
489  // update the cache for now
490  if( value.isValid() )
491  m_cache[uri].append(value);
492  lock.unlock();
493  // update the kickofflists
494  updateKickOffLists( uri, oldvalue, value );
495  }
496 }
497 
498 
499 void Nepomuk2::ResourceData::removeProperty( const QUrl& uri )
500 {
501  Q_ASSERT( uri.isValid() );
502  QMutexLocker lock(&m_dataMutex);
503 
504  if( !m_uri.isEmpty() ) {
505  QDBusMessage msg = QDBusMessage::createMethodCall( QLatin1String("org.kde.NepomukStorage"),
506  QLatin1String("/datamanagement"),
507  QLatin1String("org.kde.nepomuk.DataManagement"),
508  QLatin1String("removeProperties") );
509  msg.setArguments( QVariantList()
510  << DBus::convertUri(m_uri)
511  << DBus::convertUri(uri)
512  << KGlobal::mainComponent().componentName() );
513 
514  QDBusConnection bus = KDBusConnectionPool::threadConnection();
515  QDBusMessage reply = bus.call( msg );
516  if( reply.type() == QDBusMessage::ErrorMessage ) {
517  //TODO: Set the error somehow
518  kWarning() << reply.errorMessage();
519  return;
520  }
521 
522  const Nepomuk2::Variant oldvalue = m_cache.value(uri);
523  // Update the cache
524  m_cache.remove( uri );
525  // update the kickofflists
526  lock.unlock();
527  updateKickOffLists( uri, oldvalue, Variant() );
528  }
529 }
530 
531 
532 void Nepomuk2::ResourceData::remove( bool recursive )
533 {
534  Q_UNUSED(recursive)
535  QMutexLocker lock(&m_dataMutex);
536 
537  if( !m_uri.isEmpty() ) {
538  QDBusMessage msg = QDBusMessage::createMethodCall( QLatin1String("org.kde.NepomukStorage"),
539  QLatin1String("/datamanagement"),
540  QLatin1String("org.kde.nepomuk.DataManagement"),
541  QLatin1String("removeResources") );
542  msg.setArguments( QVariantList()
543  << DBus::convertUriList(QList<QUrl>() << m_uri)
544  << 0 /* no flags */
545  << KGlobal::mainComponent().componentName());
546 
547  QDBusConnection bus = KDBusConnectionPool::threadConnection();
548  QDBusMessage reply = bus.call( msg );
549  if( reply.type() == QDBusMessage::ErrorMessage ) {
550  //TODO: Set the error somehow
551  kWarning() << reply.errorMessage();
552  return;
553  }
554  }
555 
556  resetAll();
557 }
558 
559 
560 bool Nepomuk2::ResourceData::exists()
561 {
562  QMutexLocker lock(&m_dataMutex);
563  if( m_uri.isValid() ) {
564  const QString query = QString::fromLatin1("ask { %1 ?p ?o . }")
565  .arg( Soprano::Node::resourceToN3(m_uri) );
566  return MAINMODEL->executeQuery( query, Soprano::Query::QueryLanguageSparql ).boolValue();
567  }
568  else {
569  return false;
570  }
571 }
572 
573 
574 bool Nepomuk2::ResourceData::isValid() const
575 {
576  QMutexLocker lock(&m_dataMutex);
577  return !m_uri.isEmpty() || !m_nieUrl.isEmpty() || !m_naoIdentifier.isEmpty();
578 }
579 
580 void Nepomuk2::ResourceData::determineUri()
581 {
582  QMutexLocker lock(&m_dataMutex);
583  if( !m_uri.isEmpty() ) {
584  return;
585  }
586 
587  // We have the following possible situations:
588  // 1. m_uri is already valid
589  // -> simple, nothing to do
590  //
591  // 2. m_uri is not valid
592  // -> we need to determine the URI
593  //
594  // 2.1. m_kickoffUri is valid
595  // 2.1.1. it is a file URL
596  // 2.1.1.1. it is nie:url for r
597  // -> use r as m_uri
598  // 2.1.1.2. it points to a file on a removable device for which we have a filex:/ URL
599  // -> use the r in r nie:url filex:/...
600  // 2.1.1.3. it is a file which is not an object in some nie:url relation
601  // -> create new random m_uri and use kickoffUriOrId() as m_nieUrl
602  // 2.1.2. it is a resource URI
603  // -> use it as m_uri
604  //
605  // 2.2. m_kickOffUri is not valid
606  // 2.2.1. m_kickOffUri is a nao:identifier for r
607  // -> use r as m_uri
608  //
609 
610  Soprano::Model* model = MAINMODEL;
611 
612  if( !m_naoIdentifier.isEmpty() ) {
613  //
614  // Not valid. Checking for nao:identifier
615  //
616  QString query = QString::fromLatin1("select distinct ?r where { ?r %1 %2. } LIMIT 1")
617  .arg( Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::identifier()) )
618  .arg( Soprano::Node::literalToN3( m_naoIdentifier ) );
619 
620  Soprano::QueryResultIterator it = model->executeQuery( query, Soprano::Query::QueryLanguageSparql );
621  if( it.next() ) {
622  m_uri = it["r"].uri();
623  it.close();
624  }
625  }
626  else {
627  //
628  // In one query determine if the URI is already used as resource URI or as
629  // nie:url
630  //
631  QString query = QString::fromLatin1("select distinct ?r ?o where { "
632  "{ ?r %1 %2 . FILTER(?r!=%2) . } "
633  "UNION "
634  "{ %2 ?p ?o . } "
635  "} LIMIT 1")
636  .arg( Soprano::Node::resourceToN3( Nepomuk2::Vocabulary::NIE::url() ) )
637  .arg( Soprano::Node::resourceToN3( m_nieUrl ) );
638  Soprano::QueryResultIterator it = model->executeQuery( query, Soprano::Query::QueryLanguageSparql );
639  if( it.next() ) {
640  QUrl uri = it["r"].uri();
641  if( uri.isEmpty() ) {
642  // FIXME: Find a way to avoid this
643  // The url is actually the uri - legacy data
644  m_uri = m_nieUrl;
645  }
646  else {
647  m_uri = uri;
648  }
649  }
650  }
651 
652  //
653  // Move us to the final data hash now that the URI is known
654  //
655  if( !m_uri.isEmpty() ) {
656  lock.unlock(); // respect mutex order
657  QMutexLocker locker(&m_rm->mutex);
658  lock.relock();
659  m_cacheDirty = true;
660  ResourceDataHash::iterator it = m_rm->m_initializedData.find(m_uri);
661  if( it == m_rm->m_initializedData.end() ) {
662  m_rm->m_initializedData.insert( m_uri, this );
663  }
664  else {
665  ResourceData* foundData = it.value();
666 
667  // in case we get an already existing one we update all instances
668  // using the old ResourceData to avoid the overhead of calling
669  // determineUri over and over
670  Q_FOREACH (Resource* res, m_resources) {
671  res->m_data = foundData; // this can include our caller
672  this->deref( res );
673  foundData->ref( res );
674  }
675  }
676  }
677 }
678 
679 
680 void Nepomuk2::ResourceData::invalidateCache()
681 {
682  QMutexLocker lock(&m_dataMutex);
683  m_cacheDirty = true;
684 }
685 
686 
687 bool Nepomuk2::ResourceData::operator==( const ResourceData& other ) const
688 {
689  if( this == &other )
690  return true;
691 
692  // TODO: Maybe we shouldn't check if the identifier and url are same.
693  return( m_uri == other.m_uri &&
694  m_naoIdentifier == other.m_naoIdentifier &&
695  m_nieUrl == other.m_nieUrl );
696 }
697 
698 
699 QDebug Nepomuk2::ResourceData::operator<<( QDebug dbg ) const
700 {
701  dbg << QString::fromLatin1("[uri: %1; url: %2, identifier: %3, ref: %4]")
702  .arg( m_uri.url(),
703  m_nieUrl.url(),
704  m_naoIdentifier )
705  .arg( m_ref );
706 
707  return dbg;
708 }
709 
710 
711 QDebug operator<<( QDebug dbg, const Nepomuk2::ResourceData& data )
712 {
713  return data.operator<<( dbg );
714 }
715 
716 void Nepomuk2::ResourceData::updateUrlLists(const QUrl& oldUrl, const QUrl& newUrl)
717 {
718  if ( !oldUrl.isEmpty() ) {
719  m_rm->m_urlKickOff.remove( oldUrl );
720  }
721 
722  if( !newUrl.isEmpty() ) {
723  m_rm->m_urlKickOff.insert( newUrl, this );
724  }
725 }
726 
727 void Nepomuk2::ResourceData::updateIdentifierLists(const QString& oldIdentifier, const QString& newIdentifier)
728 {
729  if ( !oldIdentifier.isEmpty() ) {
730  m_rm->m_identifierKickOff.remove( oldIdentifier );
731  }
732 
733  if( !newIdentifier.isEmpty() ) {
734  m_rm->m_identifierKickOff.insert( newIdentifier, this );
735  }
736 }
737 
738 // Be very careful never to call this when m_dataMutex is held,
739 // unless the RM mutex was taken first, because the RM mutex must be taken
740 // before the dataMutex.
741 void Nepomuk2::ResourceData::updateKickOffLists(const QUrl& uri, const Nepomuk2::Variant &oldvalue, const Nepomuk2::Variant& newvalue)
742 {
743  if( uri == NIE::url() || uri == NAO::identifier() ){
744  QMutexLocker rmlock(&m_rm->mutex);
745  if( uri == NIE::url() )
746  updateUrlLists( oldvalue.toUrl(), newvalue.toUrl() );
747  else if( uri == NAO::identifier() )
748  updateIdentifierLists( oldvalue.toString(), newvalue.toString() );
749  }
750 }
751 
752 namespace {
753  // Returns true if the variant list was modified
754  bool removeInvalidValues(QList<Nepomuk2::Variant>& vList) {
755  bool modified = false;
756  foreach(const Nepomuk2::Variant& var, vList) {
757  if( var.isResource() && !var.toResource().isValid() ) {
758  vList.removeAll(var);
759  modified = true;
760  }
761  }
762 
763  return modified;
764  }
765 }
766 // Since propertyRemoved and propertyAdded are called from the ResourceManager with the RM mutex already locked,
767 // it is ok for them to call updateKickOffLists while the dataMutex is locked.
768 void Nepomuk2::ResourceData::propertyRemoved( const Types::Property &prop, const QVariant &value_ )
769 {
770  QMutexLocker lock(&m_dataMutex);
771  const Variant value(value_);
772  QList<Variant> vl = m_cache.value(prop.uri()).toVariantList();
773 
774  // Remove all invalid values
775  if( removeInvalidValues(vl) ) {
776  m_cache[prop.uri()] = vl;
777  }
778 
779  if( vl.contains(value) ) {
780  //
781  // Remove that element and and also remove all empty elements
782  // This is required because the value maybe have been a resource
783  // which has now been deleted, and no longer has a value
784  QMutableListIterator<Variant> it(vl);
785  while( it.hasNext() ) {
786  Variant var = it.next();
787  if( (var.isResource() && var.toUrl().isEmpty()) || var == value )
788  it.remove();
789  }
790  if(vl.isEmpty()) {
791  updateKickOffLists(prop.uri(), m_cache.value(prop.uri()), Variant());
792  m_cache.remove(prop.uri());
793  }
794  else {
795  // The kickoff properties (nao:identifier and nie:url) both have a cardinality of 1
796  // If we have more than one value, then the properties must not be any of them
797  if( vl.size() == 1 )
798  updateKickOffLists(prop.uri(), m_cache.value(prop.uri()), vl.first());
799  m_cache[prop.uri()] = vl;
800  }
801  }
802 }
803 
804 void Nepomuk2::ResourceData::propertyAdded( const Types::Property &prop, const QVariant &value )
805 {
806  QMutexLocker lock(&m_dataMutex);
807  const Variant var(value);
808  const Variant oldvalue = m_cache.value(prop.uri());
809  if( !oldvalue.toVariantList().contains(var) ) {
810  m_cache[prop.uri()].append(var);
811  }
812  updateKickOffLists(prop.uri(), oldvalue, var);
813 }
814 
815 void Nepomuk2::ResourceData::setWatchEnabled(bool status)
816 {
817  QMutexLocker lock(&m_dataMutex);
818  if( m_watchEnabled != status ) {
819  m_watchEnabled = status;
820  if( status )
821  addToWatcher();
822  else
823  removeFromWatcher();
824  }
825 }
826 
827 bool Nepomuk2::ResourceData::watchEnabled()
828 {
829  QMutexLocker lock(&m_dataMutex);
830  return m_watchEnabled;
831 }
class.h
Nepomuk2::ResourceData::updateKickOffLists
void updateKickOffLists(const QUrl &uri, const Variant &oldvariant, const Variant &newvariant)
Updates ResourceManagerPrivate's list.
Definition: resourcedata.cpp:741
Nepomuk2::ResourceData::isFile
bool isFile()
Tries to determine if this resource represents a file by examining the type and the uri...
Definition: resourcedata.cpp:111
Nepomuk2::Variant::toUrl
QUrl toUrl() const
Convert into a QUrl value.
Definition: variant.cpp:893
Nepomuk2::Types::Entity::uri
QUrl uri() const
The URI of the resource.
Definition: entity.cpp:175
Nepomuk2::DBus::normalizeVariantList
QVariantList normalizeVariantList(const QVariantList &l)
Replaces KUrl with QUrl for DBus marshalling.
Definition: dbustypes.cpp:46
Nepomuk2::ResourceData::removeProperty
void removeProperty(const QUrl &uri)
Definition: resourcedata.cpp:499
Nepomuk2::ResourceData::allProperties
QHash< QUrl, Variant > allProperties()
Definition: resourcedata.cpp:195
Nepomuk2::ResourceData::setWatchEnabled
void setWatchEnabled(bool status)
Definition: resourcedata.cpp:815
Nepomuk2::ResourceData::setProperty
void setProperty(const QUrl &uri, const Variant &value)
Set a property.
Definition: resourcedata.cpp:389
QHash
Nepomuk2::operator<<
QDataStream & operator<<(QDataStream &, const Nepomuk2::SimpleResource &)
Definition: simpleresource.cpp:307
Nepomuk2::DBus::convertUriList
QStringList convertUriList(const QList< QUrl > &uris)
Definition: dbustypes.cpp:38
Nepomuk2::ResourceData::property
Variant property(const QUrl &uri)
Definition: resourcedata.cpp:240
Nepomuk2::ResourceData::remove
void remove(bool recursive=true)
Remove this resource data from the store completely.
Definition: resourcedata.cpp:532
Nepomuk2::ResourceData::exists
bool exists()
This method only works with a proper URI, i.e.
Definition: resourcedata.cpp:560
Nepomuk2::Resource::isValid
bool isValid() const
Definition: resource.cpp:334
Nepomuk2::ResourceData::propertyAdded
void propertyAdded(const Types::Property &prop, const QVariant &value)
Definition: resourcedata.cpp:804
Nepomuk2::ResourceData::load
bool load()
Definition: resourcedata.cpp:347
Nepomuk2::Variant::variant
QVariant variant() const
Definition: variant.cpp:1454
Nepomuk2::Variant::toVariantList
QList< Variant > toVariantList() const
Convert a Variant to a list of Variants.
Definition: variant.cpp:1173
Nepomuk2::Variant
The Nepomuk Variant extends over QVariant by introducing direct support for Resource embedding...
Definition: variant.h:65
Nepomuk2::ResourceData::addProperty
void addProperty(const QUrl &uri, const Variant &value)
Definition: resourcedata.cpp:446
Nepomuk2::ResourceData::store
bool store()
Makes sure the resource is present in the RDF store.
Definition: resourcedata.cpp:259
Nepomuk2::ResourceData::hasProperty
bool hasProperty(const QUrl &uri)
Definition: resourcedata.cpp:206
Nepomuk2::Variant::toResource
Resource toResource() const
Convert into a Resource value.
Definition: variant.cpp:908
Nepomuk2::Variant::fromNode
static Variant fromNode(const Soprano::Node &node)
Create a Variant object from a Soprano::Node.
Definition: variant.cpp:1364
MAINMODEL
#define MAINMODEL
Definition: resourcedata.cpp:59
Nepomuk2::ResourceData::watchEnabled
bool watchEnabled()
Definition: resourcedata.cpp:827
Nepomuk2::DBus::convertUri
QString convertUri(const QUrl &uri)
Definition: dbustypes.cpp:33
Nepomuk2::Types::Class
A Class is a resource of type rdf:Class.
Definition: class.h:49
resource.h
Nepomuk2::ResourceData::type
QUrl type()
Definition: resourcedata.cpp:128
Nepomuk2::Types::Property
A property is a resource of type rdf:Property which relates a domain with a range.
Definition: libnepomukcore/types/property.h:52
Nepomuk2::Types::Class::isSubClassOf
bool isSubClassOf(const Class &other)
Check if this class is derived from another class.
Definition: class.cpp:490
Nepomuk2::ResourceData::invalidateCache
void invalidateCache()
Definition: resourcedata.cpp:680
resourcemanager.h
Nepomuk2::ResourceData::isValid
bool isValid() const
Definition: resourcedata.cpp:574
resourcedata.h
Nepomuk2::ResourceData::determineUri
void determineUri()
Searches for the resource in the Nepomuk store using m_kickoffId and m_kickoffUri.
Definition: resourcedata.cpp:580
Nepomuk2::Variant::simpleType
int simpleType() const
Definition: variant.cpp:1314
Nepomuk2::ResourceData::~ResourceData
~ResourceData()
Definition: resourcedata.cpp:105
Nepomuk2::ResourceData::resetAll
void resetAll()
Will reset this instance to 0 as if constructed without parameters Used by remove() and deleteData() ...
Definition: resourcedata.cpp:164
nepomukmainmodel.h
Nepomuk2::ResourceData::propertyRemoved
void propertyRemoved(const Types::Property &prop, const QVariant &value)
Called by ResourceManager (with the RM mutex locked)
Definition: resourcedata.cpp:768
Nepomuk2::ResourceData::ResourceData
ResourceData(const QUrl &uri, const QUrl &kickOffUri, const QUrl &type_, ResourceManagerPrivate *rm)
Definition: resourcedata.cpp:64
Nepomuk2::ResourceData::operator<<
QDebug operator<<(QDebug dbg) const
Definition: resourcedata.cpp:699
tools.h
Nepomuk2::setProperty
KJob * setProperty(const QList< QUrl > &resources, const QUrl &property, const QVariantList &values, const KComponentData &component=KGlobal::mainComponent())
Set the values of a property for one or more resources.
Definition: datamanagement.cpp:48
Nepomuk2::Variant::toString
QString toString() const
The toString() method is a little more powerful than other toXXX methods since it actually converts a...
Definition: variant.cpp:827
Nepomuk2::Resource
Resource is the central object type in Nepomuk.
Definition: resource.h:93
resourcewatcher.h
Nepomuk2::Variant::append
void append(int i)
Append i to this variant.
Definition: variant.cpp:462
Nepomuk2::Variant::isResource
bool isResource() const
Definition: variant.cpp:674
Nepomuk2::Resource::uri
QUrl uri() const
The URI of the resource, uniquely identifying it.
Definition: resource.cpp:166
Nepomuk2::Variant::isValid
bool isValid() const
Definition: variant.cpp:1460
Nepomuk2::ResourceData::ref
bool ref(Nepomuk2::Resource *res)
Definition: resourcedata.h:48
Nepomuk2::ResourceData::uri
QUrl uri() const
The URI of the resource.
Definition: resourcedata.cpp:121
Nepomuk2::ResourceData::operator==
bool operator==(const ResourceData &other) const
Compares the properties of two ResourceData objects taking into account the Deleted flag...
Definition: resourcedata.cpp:687
dbustypes.h
Nepomuk2::ResourceData
Definition: resourcedata.h:42
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:48:08 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Nepomuk-Core

Skip menu "Nepomuk-Core"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal