~ubuntu-branches/ubuntu/precise/kde-runtime/precise-proposed

« back to all changes in this revision

Viewing changes to nepomuk/services/backupsync/lib/resourceidentifier.cpp

  • Committer: Package Import Robot
  • Author(s): Philip Muškovac
  • Date: 2012-03-30 21:36:32 UTC
  • mfrom: (1.1.10)
  • Revision ID: package-import@ubuntu.com-20120330213632-xsvx5vu8qg50aui7
Tags: 4:4.8.2-0ubuntu1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
#include <Soprano/Statement>
32
32
#include <Soprano/Graph>
33
33
#include <Soprano/Node>
 
34
#include <Soprano/BindingSet>
34
35
#include <Soprano/StatementIterator>
35
36
#include <Soprano/QueryResultIterator>
36
37
#include <Soprano/Model>
176
177
        return false;
177
178
    }
178
179
 
179
 
    QString query;
180
 
 
181
180
    QStringList identifyingProperties;
182
181
    QHash<KUrl, Soprano::Node> identifyingPropertiesHash;
183
182
 
184
183
    QHash< KUrl, Soprano::Node >::const_iterator it = res.constBegin();
185
184
    QHash< KUrl, Soprano::Node >::const_iterator constEnd = res.constEnd();
 
185
    QList<Soprano::Node> requiredTypes;
186
186
    for( ; it != constEnd; it++ ) {
187
187
        const QUrl & prop = it.key();
188
188
 
189
189
        // Special handling for rdf:type
190
190
        if( prop == RDF::type() ) {
191
 
            query += QString::fromLatin1(" ?r a %1 . ").arg( it.value().toN3() );
 
191
            requiredTypes << it.value().uri();
192
192
            continue;
193
193
        }
194
194
 
219
219
        return false;
220
220
    }
221
221
 
 
222
 
 
223
    // construct the identification query
 
224
    QString query = QLatin1String("select distinct ?r where { ");
 
225
 
222
226
    //
223
227
    // Optimization:
224
228
    // If there is only one identifying property using all that optional and filter stuff
235
239
                           QString::number( numIdentifyingProperties++ ) );
236
240
        }
237
241
 
238
 
        // Make sure atleast one of the identification properties has been matched
 
242
        // Make sure at least one of the identification properties has been matched
239
243
        // by adding filter( bound(?o1) || bound(?o2) ... )
240
244
        query += QString::fromLatin1("filter( ");
241
245
        for( int i=0; i<numIdentifyingProperties-1; i++ ) {
247
251
        query += QString::fromLatin1("?r %1 %2 . ").arg(Soprano::Node::resourceToN3(identifyingPropertiesHash.constBegin().key()),
248
252
                                                         identifyingPropertiesHash.constBegin().value().toN3());
249
253
    }
250
 
    query += QLatin1String("}");
251
 
 
252
 
    // Construct the entire query
253
 
    QString queryBegin = QString::fromLatin1("select distinct ?r count(?p) as ?cnt "
254
 
    "where { ?r ?p ?o. filter( ?p in (%1) ).")
255
 
    .arg( identifyingProperties.join(",") );
256
 
 
257
 
    query = queryBegin + query + QString::fromLatin1(" order by desc(?cnt)");
258
 
 
259
 
    kDebug() << query;
260
 
 
261
 
    //
262
 
    // Only store the results which have the maximum score
263
 
    //
264
 
    QSet<KUrl> results;
265
 
    int score = -1;
 
254
 
 
255
    //
 
256
    // For performance reasons we add a limit even though this could mean that we
 
257
    // miss a resource to identify since we check the types below.
 
258
    //
 
259
    query += QLatin1String("} LIMIT 100");
 
260
 
 
261
 
 
262
    //
 
263
    // Fetch a score for each result.
 
264
    // We do this in a separate query for performance reasons.
 
265
    //
 
266
    QMultiHash<int, KUrl> resultsScoreHash;
 
267
    int maxScore = -1;
266
268
    Soprano::QueryResultIterator qit = d->m_model->executeQuery( query, Soprano::Query::QueryLanguageSparql );
267
269
    while( qit.next() ) {
268
 
        //kDebug() << "RESULT: " << qit["r"] << " " << qit["cnt"];
269
 
 
270
 
        int count = qit["cnt"].literal().toInt();
271
 
        if( score == -1 ) {
272
 
            score = count;
273
 
        }
274
 
        else if( count < score )
275
 
            break;
276
 
 
277
 
        results << qit["r"].uri();
 
270
        const Soprano::Node r(qit["r"]);
 
271
 
 
272
        //
 
273
        // Check the type requirements. Experiments have shown this to mean a substantial
 
274
        // performance boost as compared to doing it in the main query.
 
275
        //
 
276
        if(!requiredTypes.isEmpty() ) {
 
277
            query = QLatin1String("ask where { ");
 
278
            foreach(const Soprano::Node& type, requiredTypes) {
 
279
                query += QString::fromLatin1("%1 a %2 . ").arg(r.toN3(), type.toN3());
 
280
            }
 
281
            query += QLatin1String("}");
 
282
            if(!d->m_model->executeQuery(query, Soprano::Query::QueryLanguageSparql).boolValue()) {
 
283
                continue;
 
284
            }
 
285
        }
 
286
 
 
287
 
 
288
        const int score = d->m_model->executeQuery(QString::fromLatin1("select count(?p) as ?cnt where { "
 
289
                                                                       "%1 ?p ?o. filter( ?p in (%2) ) . }")
 
290
                                                   .arg( r.toN3(),
 
291
                                                         identifyingProperties.join(",") ),
 
292
                                                   Soprano::Query::QueryLanguageSparql)
 
293
                          .allBindings().first()["cnt"].literal().toInt();
 
294
 
 
295
        if( maxScore < score ) {
 
296
            maxScore = score;
 
297
        }
 
298
 
 
299
        resultsScoreHash.insert(score, r.uri());
278
300
    }
279
301
 
 
302
    //
 
303
    // Only get the results which have the maximum score
 
304
    //
 
305
    QSet<KUrl> results = QSet<KUrl>::fromList(resultsScoreHash.values(maxScore));
 
306
 
 
307
 
280
308
    //kDebug() << "Got " << results.size() << " results";
281
309
    if( results.empty() )
282
310
        return false;
283
311
 
284
312
    KUrl newUri;
285
 
    if( results.size() == 1 )
 
313
    if( results.size() == 1 ) {
286
314
        newUri = *results.begin();
 
315
    }
287
316
    else {
288
317
        kDebug() << "DUPLICATE RESULTS!";
289
318
        newUri = duplicateMatch( res.uri(), results );