31 #include <QtCore/QTimer>
32 #include <QtCore/QFile>
34 #include <Soprano/Model>
35 #include <Soprano/QueryResultIterator>
36 #include <Soprano/Vocabulary/NAO>
44 #include <KServiceTypeTrader>
46 using namespace Nepomuk2;
47 using namespace Nepomuk2::Vocabulary;
48 using namespace Soprano::Vocabulary;
59 return i18n(
"Removing legacy data");
65 void CrappyInferenceData::execute()
69 model->removeContext(QUrl::fromEncoded(
"urn:crappyinference:inferredtriples"));
70 model->removeContext(QUrl::fromEncoded(
"urn:crappyinference2:inferredtriples"));
71 model->removeContext(QUrl::fromEncoded(
"nepomuk:/ctx/typevisibility"));
81 return i18n(
"Removing empty tags");
87 void EmptyTagCleaner::execute()
89 QString query = QString::fromLatin1(
"select ?r where { ?r a %1 . FILTER NOT EXISTS { ?r %2 ?i . } }")
90 .arg( Soprano::Node::resourceToN3( NAO::Tag() ),
91 Soprano::Node::resourceToN3( NAO::identifier() ) );
94 Soprano::QueryResultIterator it = model->executeQuery( query, Soprano::Query::QueryLanguageSparql );
95 QList<QUrl> deleteList;
97 deleteList << it[0].uri();
99 if( !deleteList.isEmpty() && !shouldQuit() ) {
111 explicit DuplicateMergingJob(
const QUrl& type,
const QUrl& prop,
QObject* parent = 0);
119 DuplicateMergingJob::DuplicateMergingJob(
const QUrl& type,
const QUrl& prop,
QObject* parent)
126 void DuplicateMergingJob::execute()
128 QString query = QString::fromLatin1(
"select distinct ?i where { ?r a %1 . ?r %2 ?i . }")
129 .arg( Soprano::Node::resourceToN3( m_type ),
130 Soprano::Node::resourceToN3( m_prop ) );
133 Soprano::QueryResultIterator it = model->executeQuery( query, Soprano::Query::QueryLanguageSparql );
134 while( it.next() && !shouldQuit() ) {
135 QString query = QString::fromLatin1(
"select distinct ?r where { ?r a %1 . ?r %2 %3 . }")
136 .arg( Soprano::Node::resourceToN3( m_type ),
137 Soprano::Node::resourceToN3( m_prop ),
139 Soprano::QueryResultIterator iter = model->executeQuery( query, Soprano::Query::QueryLanguageSparqlNoInference );
141 QList<QUrl> resourcesToMerge;
143 resourcesToMerge << iter[0].uri();
145 if( resourcesToMerge.size() <= 1 )
148 if( resourcesToMerge.size() > 10 && !shouldQuit() ) {
150 QList<QUrl> list = resourcesToMerge.mid( 0, 10 );
151 resourcesToMerge = resourcesToMerge.mid( 10 );
156 kError() << job->errorString();
162 class DuplicateTagCleaner :
public DuplicateMergingJob {
164 explicit DuplicateTagCleaner(
QObject* parent = 0)
165 : DuplicateMergingJob(NAO::
Tag(), NAO::identifier(), parent) {}
168 return i18n(
"Merging duplicate tags");
173 class DuplicateFileCleaner :
public DuplicateMergingJob {
175 explicit DuplicateFileCleaner(
QObject* parent = 0)
176 : DuplicateMergingJob(NFO::FileDataObject(), NIE::url(), parent) {}
179 return i18n(
"Merging duplicate file metadata");
183 class DuplicateIconCleaner :
public DuplicateMergingJob {
185 explicit DuplicateIconCleaner(
QObject* parent = 0)
186 : DuplicateMergingJob(NAO::FreeDesktopIcon(), NAO::iconName(), parent) {}
189 return i18n(
"Merging duplicate icons");
199 explicit AkonadiMigrationJob(
QObject* parent = 0)
203 return i18n(
"Porting legacy Akonadi data");
210 void AkonadiMigrationJob::execute()
212 const QUrl akonadiDataObject(
"http://akonadi-project.org/ontologies/aneo#AkonadiDataObject");
214 QLatin1String query(
"select distinct ?r where { ?r ?p ?o. FILTER(REGEX(STR(?r), '^akonadi')). }");
217 Soprano::QueryResultIterator it = model->executeQuery( query, Soprano::Query::QueryLanguageSparql );
218 while( it.next() && !shouldQuit() ) {
222 if( cjob->error() ) {
223 kDebug() << cjob->errorString();
227 kDebug() << cjob->
resourceUri() <<
" " << it[0].uri();
231 kDebug() << job->errorString();
238 kDebug() << job->errorString();
250 explicit DuplicateContactJob(
QObject* parent = 0)
254 return i18n(
"Merging duplicate contacts");
257 virtual void execute();
260 void DuplicateContactJob::execute()
262 QLatin1String contactQuery(
"select distinct ?fn where { ?r a nco:Contact ; nco:fullname ?fn . }");
265 Soprano::QueryResultIterator it = model->executeQuery( contactQuery, Soprano::Query::QueryLanguageSparql );
266 while( it.next() && !shouldQuit() ) {
267 const QString name( it[0].literal().toString() );
272 kDebug() <<
"Looking for " << name;
274 QString query = QString::fromLatin1(
"select ?r where { ?r a nco:Contact ; nco:fullname %1 . }")
275 .arg( Soprano::Node::literalToN3( name ) );
277 Soprano::QueryResultIterator it = model->executeQuery( query, Soprano::Query::QueryLanguageSparql );
278 QSet<QUrl> contactToMerge;
279 while( it.next() && !shouldQuit() ) {
280 const QUrl resUri = it[0].uri();
281 QString propQuery = QString::fromLatin1(
"select ?p ?o where { %1 ?p ?o . }")
282 .arg( Soprano::Node::resourceToN3( resUri ) );
283 Soprano::QueryResultIterator qit = model->executeQuery( query, Soprano::Query::QueryLanguageSparqlNoInference );
284 bool isCandiate =
true;
286 while( qit.next() && !shouldQuit() ) {
287 const QUrl prop = qit[0].uri();
290 if( prop == NAO::lastModified() || prop == NAO::created() )
293 if( prop == NCO::fullname() )
304 contactToMerge << resUri;
310 if( contactToMerge.size() > 1 && !shouldQuit() ) {
311 kDebug() <<
"Merging " << contactToMerge.size() <<
" contacts for " << name;
315 kError() << job->errorString();
326 explicit DuplicateStatementJob(
QObject* parent = 0)
330 return i18n(
"Removing duplicate metadata");
337 void DuplicateStatementJob::execute()
339 QLatin1String query(
"select ?r ?p ?o where { graph ?g1 { ?r ?p ?o. } "
340 " graph ?g2 { ?r ?p ?o. } FILTER( ?g1 != ?g2 ) . }");
343 Soprano::QueryResultIterator it = model->executeQuery( query, Soprano::Query::QueryLanguageSparqlNoInference );
344 while( it.next() && !shouldQuit() ) {
345 Soprano::Statement st( it[
"r"], it[
"p"], it[
"o"] );
348 QString query = QString::fromLatin1(
"select ?g where { graph ?g { %1 %2 %3 . } }")
349 .arg( st.subject().toN3(), st.predicate().toN3(), st.object().toN3() );
350 Soprano::QueryResultIterator it = model->executeQuery( query, Soprano::Query::QueryLanguageSparqlNoInference );
354 graphs << it[0].uri();
358 for(
int i=1; i<graphs.size() && !shouldQuit(); i++ ) {
359 Soprano::Statement statement( st );
360 statement.setContext( graphs[i] );
362 kDebug() << statement;
363 model->removeAllStatements( statement );
368 class InvalidFileResourcesJob :
public CleaningJob {
370 explicit InvalidFileResourcesJob(
QObject* parent = 0)
374 return i18n(
"Cleaning invalid file metadata");
377 virtual void execute();
380 void InvalidFileResourcesJob::execute()
385 QLatin1String query(
"select distinct ?r where { ?r a nfo:FileDataObject. FILTER NOT EXISTS {"
386 " ?r nie:url ?url . } }");
389 Soprano::QueryResultIterator it = model->executeQuery( query, Soprano::Query::QueryLanguageSparql );
391 QList<QUrl> deleteList;
392 while( it.next() && !shouldQuit() ) {
393 deleteList << it[0].uri();
395 if( deleteList.size() > 10 ) {
396 kDebug() << deleteList;
403 if( !deleteList.isEmpty() ) {
443 explicit InvalidResourcesJob(
QObject* parent = 0)
447 return i18n(
"Cleaning invalid resources");
450 virtual void execute();
453 void InvalidResourcesJob::execute()
456 QLatin1String query(
"select distinct ?r where { ?r ?p ?o . FILTER NOT EXISTS { ?r a ?t . } }");
459 Soprano::QueryResultIterator it = model->executeQuery( query, Soprano::Query::QueryLanguageSparqlNoInference );
461 QList<QUrl> deleteList;
462 while( it.next() && !shouldQuit() ) {
463 deleteList << it[0].uri();
465 if( deleteList.size() > 10 ) {
466 kDebug() << deleteList;
473 if( !deleteList.isEmpty() ) {
482 explicit InvalidStatementsJob(
QObject* parent = 0)
486 return i18n(
"Cleaning invalid statements");
489 virtual void execute();
492 void InvalidStatementsJob::execute()
495 QString query = QString::fromLatin1(
"select distinct ?r ?p where { ?p nrl:maxCardinality %1 ."
496 " ?r ?p ?o1 , ?o2 . FILTER( ?o1 != ?o2 ) . }")
497 .arg( Soprano::Node::literalToN3( Soprano::LiteralValue(1) ) );
500 Soprano::QueryResultIterator it = model->executeQuery( query, Soprano::Query::QueryLanguageSparqlNoInference );
502 while( it.next() && !shouldQuit() ) {
503 Soprano::Statement st( it[0], it[1], Soprano::Node() );
507 QString query = QString::fromLatin1(
"select ?o ?g where { graph ?g { %1 %2 ?o . } "
508 "?g nao:created ?c . } ORDER BY ASC(?c) LIMIT 1")
509 .arg( st.subject().toN3(), st.predicate().toN3() );
510 Soprano::QueryResultIterator iter = model->executeQuery( query, Soprano::Query::QueryLanguageSparqlNoInference );
512 st.setObject( iter[0] );
513 st.setContext( iter[1] );
517 model->removeAllStatements( st.subject(), st.predicate(), Soprano::Node() );
518 model->addStatement( st );
530 QList<CleaningJob*> list;
531 list <<
new CrappyInferenceData();
532 list <<
new EmptyTagCleaner();
533 list <<
new DuplicateTagCleaner();
534 list <<
new DuplicateFileCleaner();
535 list <<
new DuplicateIconCleaner();
536 list <<
new AkonadiMigrationJob();
537 list <<
new DuplicateStatementJob();
538 list <<
new DuplicateContactJob();
539 list <<
new InvalidFileResourcesJob();
540 list <<
new InvalidResourcesJob();
541 list <<
new InvalidStatementsJob();
544 KService::List plugins = KServiceTypeTrader::self()->query(
"NepomukCleaningJob" );
545 for( KService::List::const_iterator it = plugins.constBegin(); it != plugins.constEnd(); it++ ) {
546 KService::Ptr service = *it;
554 kError() <<
"Could not create Cleaning job: " << service->library();
562 #include "cleaningjobs.moc"
virtual QString jobName()=0
QUrl resourceUri() const
The returned resource URI.
KJob * mergeResources(const QUrl &resource1, const QUrl &resource2, const KComponentData &component=KGlobal::mainComponent())
Merge two resources into one.
A Tag can be assigned to any Thing.
A property is a resource of type rdf:Property which relates a domain with a range.
static ResourceManager * instance()
Job returned by Nepomuk2::createResource().
KJob * removeResources(const QList< QUrl > &resources, Nepomuk2::RemovalFlags flags=Nepomuk2::NoRemovalFlags, const KComponentData &component=KGlobal::mainComponent())
Completely remove resources from the database.
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.
QList< CleaningJob * > allJobs()
CreateResourceJob * createResource(const QList< QUrl > &types, const QString &label, const QString &description, const KComponentData &component=KGlobal::mainComponent())
Create a new resource.
Soprano::Model * mainModel()
Retrieve the main data storage model.