~ubuntu-branches/ubuntu/natty/kde4libs/natty-proposed

« back to all changes in this revision

Viewing changes to nepomuk/query/queryparser.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell, Jonathan Riddell, Scott Kitterman
  • Date: 2011-01-21 11:32:24 UTC
  • mfrom: (1.14.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20110121113224-c9tebdkklj5u3awu
Tags: 4:4.6.0-0ubuntu1~ppa1
[ Jonathan Riddell ]
* New upstream release
* Reluctantly add kcm_ssl to kdelibs5-plugins, this should be in kdebase

[ Scott Kitterman ]
* Update libkatepartinterfaces4.symbols and libkdecore5.symbols for 4.5.95
  and confirm symbols on all architectures with pkgkde-symbolshelper
  - Thanks to Jonathan Thomas for verifying the missing symbols

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
   This file is part of the Nepomuk KDE project.
3
 
   Copyright (C) 2007-2010 Sebastian Trueg <trueg@kde.org>
 
3
   Copyright (C) 2007-2011 Sebastian Trueg <trueg@kde.org>
4
4
 
5
5
   This library is free software; you can redistribute it and/or
6
6
   modify it under the terms of the GNU Library General Public
130
130
        }
131
131
    }
132
132
 
133
 
    Soprano::LiteralValue createLiteral( const QString& s_, bool globbing ) {
134
 
        bool hadQuotes = false;
135
 
        QString s = stripQuotes( s_, &hadQuotes );
 
133
    Soprano::LiteralValue createLiteral( const QString& s, bool globbing ) {
 
134
        // 1. check if it is a number
 
135
        QString clearString(s);
 
136
        clearString.remove(QLatin1Char('\''));
 
137
        clearString.remove(QLatin1Char('"'));
136
138
        bool b = false;
137
 
        int i = s.toInt( &b );
 
139
        int i = clearString.toInt( &b );
138
140
        if ( b )
139
141
            return Soprano::LiteralValue( i );
140
 
        double d = s.toDouble( &b );
 
142
        double d = clearString.toDouble( &b );
141
143
        if ( b )
142
144
            return Soprano::LiteralValue( d );
143
145
 
 
146
        // 2. no number - continue with the original string
 
147
 
 
148
        // no globbing if we have quotes or if there already is a wildcard
 
149
        if ( s[0] == QLatin1Char('\'') ||
 
150
             s[0] == QLatin1Char('\"') ) {
 
151
            return s;
 
152
        }
 
153
 
144
154
        //
145
155
        // we can only do query term globbing for strings longer than 3 chars
146
156
        //
147
 
        if( !hadQuotes && globbing && s.length() > 3 && !s.endsWith('*') && !s.endsWith('?') )
 
157
        if( globbing && s.length() > 3 && !s.endsWith('*') && !s.endsWith('?') )
148
158
            return QString(s + '*');
149
159
        else
150
160
            return s;
250
260
                                               Nepomuk::Query::ComparisonTerm::Regexp );
251
261
    }
252
262
 
 
263
    /**
 
264
     * Merging literal terms is an optimization which is based on the assumption that most
 
265
     * users want to search for the full text terms they enter in the value of the same
 
266
     * property.
 
267
     * Since merging two literals "foo" and "bar" into one term "foo AND bar" effectively
 
268
     * changes the result set (the former allows that "foo" occurs in a property value
 
269
     * different from "bar" while the latter forces them to occur in the same.)
 
270
     * But the resulting query is much faster.
 
271
     */
 
272
    Nepomuk::Query::Term mergeLiteralTerms( const Nepomuk::Query::Term& term )
 
273
    {
 
274
        if( term.isAndTerm() ) {
 
275
            AndTerm mergedTerm;
 
276
            QStringList fullTextTerms;
 
277
            Q_FOREACH( const Term& st, term.toAndTerm().subTerms() ) {
 
278
                if( st.isLiteralTerm() ) {
 
279
                    fullTextTerms << st.toLiteralTerm().value().toString();
 
280
                }
 
281
                else {
 
282
                    mergedTerm.addSubTerm( st );
 
283
                }
 
284
            }
 
285
            mergedTerm.addSubTerm( LiteralTerm( fullTextTerms.join( QString::fromLatin1(" AND ") ) ) );
 
286
            return mergedTerm.optimized();
 
287
        }
 
288
        else {
 
289
            return term;
 
290
        }
 
291
    }
 
292
 
253
293
#ifndef Q_CC_MSVC
254
294
#warning Make the parser handle different data, time, and datetime encodings as well as suffixes like MB or GB
255
295
#endif
461
501
    bool inAndBlock = false;
462
502
 
463
503
    int pos = 0;
 
504
 
 
505
    // create local copies of the regexps for thread safety purposes
 
506
    const QRegExp resourceRx = s_resourceRx;
 
507
    const QRegExp propertyRx = s_propertyRx;
 
508
    const QRegExp fieldFieldRx = s_fieldFieldRx;
 
509
    const QRegExp fieldRx = s_fieldRx;
 
510
    const QRegExp plainTermRx = s_plainTermRx;
 
511
 
464
512
    while ( pos < query.length() ) {
465
513
        // skip whitespace
466
514
        while ( pos < query.length() && query[pos].isSpace() ) {
471
519
        Term term;
472
520
 
473
521
        if ( pos < query.length() ) {
474
 
            if ( s_resourceRx.indexIn( query, pos ) == pos ) {
475
 
                kDebug() << "matched resource term at" << pos << s_resourceRx.cap( 0 );
476
 
                term = ComparisonTerm( tryToBeIntelligentAboutParsingUrl( s_resourceRx.cap( 2 ) ),
477
 
                                       ResourceTerm( tryToBeIntelligentAboutParsingUrl( s_resourceRx.cap( 3 ) ) ),
 
522
            if ( resourceRx.indexIn( query, pos ) == pos ) {
 
523
                kDebug() << "matched resource term at" << pos << resourceRx.cap( 0 );
 
524
                term = ComparisonTerm( tryToBeIntelligentAboutParsingUrl( resourceRx.cap( 2 ) ),
 
525
                                       ResourceTerm( tryToBeIntelligentAboutParsingUrl( resourceRx.cap( 3 ) ) ),
478
526
                                       ComparisonTerm::Equal );
479
 
                if ( !positiveTerm(s_resourceRx.cap( 1 ) ) ) {
 
527
                if ( !positiveTerm( resourceRx.cap( 1 ) ) ) {
480
528
                    term = NegationTerm::negateTerm( term );
481
529
                }
482
 
                pos += s_resourceRx.matchedLength();
 
530
                pos += resourceRx.matchedLength();
483
531
            }
484
532
 
485
 
            else if ( s_propertyRx.indexIn( query, pos ) == pos ) {
486
 
                kDebug() << "matched property term at" << pos << s_propertyRx.cap( 0 );
 
533
            else if ( propertyRx.indexIn( query, pos ) == pos ) {
 
534
                kDebug() << "matched property term at" << pos << propertyRx.cap( 0 );
487
535
                ComparisonTerm ct;
488
 
                ct.setProperty( tryToBeIntelligentAboutParsingUrl( s_propertyRx.cap( 2 ) ) );
489
 
                ct.setSubTerm( LiteralTerm( createLiteral( s_propertyRx.cap( 4 ), flags&QueryTermGlobbing ) ) );
490
 
                QString comparator = s_propertyRx.cap( 3 );
 
536
                ct.setProperty( tryToBeIntelligentAboutParsingUrl( propertyRx.cap( 2 ) ) );
 
537
                ct.setSubTerm( LiteralTerm( createLiteral( propertyRx.cap( 4 ), flags&QueryTermGlobbing ) ) );
 
538
                QString comparator = propertyRx.cap( 3 );
491
539
                ct.setComparator( fieldTypeRelationFromString( comparator ) );
492
 
                pos += s_propertyRx.matchedLength();
 
540
                pos += propertyRx.matchedLength();
493
541
 
494
 
                if ( !positiveTerm(s_propertyRx.cap( 1 ) ) ) {
 
542
                if ( !positiveTerm(propertyRx.cap( 1 ) ) ) {
495
543
                    term = NegationTerm::negateTerm( ct );
496
544
                }
497
545
                else {
499
547
                }
500
548
            }
501
549
 
502
 
            else if ( s_fieldFieldRx.indexIn( query, pos ) == pos ) {
 
550
            else if ( fieldFieldRx.indexIn( query, pos ) == pos ) {
503
551
                kDebug() << "matched field field term at" << pos
504
 
                         << s_fieldFieldRx.cap( 0 )
505
 
                         << s_fieldFieldRx.cap( 2 )
506
 
                         << s_fieldFieldRx.cap( 4 )
507
 
                         << s_fieldFieldRx.cap( 5 )
508
 
                         << s_fieldFieldRx.cap( 7 )
509
 
                         << s_fieldFieldRx.cap( 8 );
 
552
                         << fieldFieldRx.cap( 0 )
 
553
                         << fieldFieldRx.cap( 2 )
 
554
                         << fieldFieldRx.cap( 4 )
 
555
                         << fieldFieldRx.cap( 5 )
 
556
                         << fieldFieldRx.cap( 7 )
 
557
                         << fieldFieldRx.cap( 8 );
510
558
                ComparisonTerm ct;
511
 
                ct.setProperty( QUrl(stripQuotes( s_fieldFieldRx.cap( 2 ) )) );
512
 
                QString comparator = s_fieldFieldRx.cap( 4 );
 
559
                ct.setProperty( QUrl(stripQuotes( fieldFieldRx.cap( 2 ) )) );
 
560
                QString comparator = fieldFieldRx.cap( 4 );
513
561
                ct.setComparator( fieldTypeRelationFromString( comparator ) );
514
 
                ct.setSubTerm( ComparisonTerm( QUrl(stripQuotes( s_fieldFieldRx.cap( 5 ) )),
515
 
                                               LiteralTerm( createLiteral( s_fieldFieldRx.cap( 8 ), flags&QueryTermGlobbing ) ),
516
 
                                               fieldTypeRelationFromString( s_fieldFieldRx.cap( 7 ) ) ) );
517
 
                pos += s_fieldFieldRx.matchedLength();
 
562
                ct.setSubTerm( ComparisonTerm( QUrl(stripQuotes( fieldFieldRx.cap( 5 ) )),
 
563
                                               LiteralTerm( createLiteral( fieldFieldRx.cap( 8 ), flags&QueryTermGlobbing ) ),
 
564
                                               fieldTypeRelationFromString( fieldFieldRx.cap( 7 ) ) ) );
 
565
                pos += fieldFieldRx.matchedLength();
518
566
 
519
 
                if ( !positiveTerm(s_fieldFieldRx.cap( 1 ) ) ) {
 
567
                if ( !positiveTerm( fieldFieldRx.cap( 1 ) ) ) {
520
568
                    term = NegationTerm::negateTerm( ct );
521
569
                }
522
570
                else {
524
572
                }
525
573
            }
526
574
 
527
 
            else if ( s_fieldRx.indexIn( query, pos ) == pos ) {
528
 
                kDebug() << "matched field term at" << pos << s_fieldRx.cap( 0 ) << s_fieldRx.cap( 2 ) << s_fieldRx.cap( 4 ) << s_fieldRx.cap( 5 );
529
 
                if( stripQuotes ( s_fieldRx.cap( 2 ) ).compare( QString( "inFolder" ), Qt::CaseInsensitive ) == 0 ) {
530
 
                    KUrl url( s_fieldRx.cap( 5 ) );
 
575
            else if ( fieldRx.indexIn( query, pos ) == pos ) {
 
576
                kDebug() << "matched field term at" << pos << fieldRx.cap( 0 ) << fieldRx.cap( 2 ) << fieldRx.cap( 4 ) << fieldRx.cap( 5 );
 
577
                if( stripQuotes ( fieldRx.cap( 2 ) ).compare( QString( "inFolder" ), Qt::CaseInsensitive ) == 0 ) {
 
578
                    KUrl url( fieldRx.cap( 5 ) );
531
579
                    kDebug() << "found include path" << url;
532
580
                    FileQuery fileQuery(final);
533
 
                    if ( positiveTerm( s_fieldRx.cap( 1 ) ) )
 
581
                    if ( positiveTerm( fieldRx.cap( 1 ) ) )
534
582
                        fileQuery.addIncludeFolder(url);
535
583
                    else
536
584
                        fileQuery.addExcludeFolder(url);
537
585
                    final = fileQuery;
538
 
                    pos += s_fieldRx.matchedLength();
 
586
                    pos += fieldRx.matchedLength();
539
587
                }
540
588
                else {
541
589
                    ComparisonTerm ct;
542
 
                    ct.setProperty( QUrl( stripQuotes( s_fieldRx.cap( 2 ) ) ) );
543
 
                    ct.setSubTerm( LiteralTerm( createLiteral( s_fieldRx.cap( 5 ), flags&QueryTermGlobbing ) ) );
544
 
                    QString comparator = s_fieldRx.cap( 4 );
 
590
                    ct.setProperty( QUrl( stripQuotes( fieldRx.cap( 2 ) ) ) );
 
591
                    ct.setSubTerm( LiteralTerm( createLiteral( fieldRx.cap( 5 ), flags&QueryTermGlobbing ) ) );
 
592
                    QString comparator = fieldRx.cap( 4 );
545
593
                    ct.setComparator( fieldTypeRelationFromString( comparator ) );
546
 
                    pos += s_fieldRx.matchedLength();
547
 
                    if ( !positiveTerm(s_fieldRx.cap( 1 ) ) ) {
 
594
                    pos += fieldRx.matchedLength();
 
595
                    if ( !positiveTerm(fieldRx.cap( 1 ) ) ) {
548
596
                        NegationTerm nt;
549
597
                        nt.setSubTerm( ct );
550
598
                        term = nt;
555
603
                }
556
604
            }
557
605
 
558
 
            else if ( s_plainTermRx.indexIn( query, pos ) == pos ) {
559
 
                QString value = s_plainTermRx.cap( 2 );
 
606
            else if ( plainTermRx.indexIn( query, pos ) == pos ) {
 
607
                QString value = plainTermRx.cap( 2 );
560
608
                if ( d->orKeywords.contains( value.toLower() ) ) {
561
609
                    inOrBlock = true;
562
610
                }
571
619
                    else {
572
620
                        term = LiteralTerm( createLiteral( value, flags&QueryTermGlobbing ) );
573
621
                    }
574
 
                    if ( !positiveTerm(s_plainTermRx.cap( 1 ) ) ) {
 
622
                    if ( !positiveTerm(plainTermRx.cap( 1 ) ) ) {
575
623
                        term = NegationTerm::negateTerm( term );
576
624
                    }
577
625
                }
578
 
                pos += s_plainTermRx.matchedLength();
 
626
                pos += plainTermRx.matchedLength();
579
627
            }
580
628
 
581
629
            else {
612
660
        final.setTerm( t );
613
661
    }
614
662
 
615
 
    final.setTerm( resolveFields( final.term(), this ) );
 
663
    final.setTerm( mergeLiteralTerms( resolveFields( final.term(), this ) ) );
616
664
    return final;
617
665
}
618
666