~ubuntu-branches/ubuntu/raring/clucene-core/raring-proposed

« back to all changes in this revision

Viewing changes to src/core/CLucene/search/PrefixQuery.cpp

  • Committer: Package Import Robot
  • Author(s): Fathi Boudra
  • Date: 2012-08-11 09:33:38 UTC
  • mfrom: (1.1.5)
  • Revision ID: package-import@ubuntu.com-20120811093338-fgrx41ftqew3qt6a
Tags: 2.3.3.4-1
* New upstream release (Closes: #661703).
* Convert package to multiarch.
* Drop obsolete patches:
  - 01_add_missing_include_bug505667.diff
  - 02_posixness_fix_bug530308.diff
* Add patches:
  - Fixing_ZLIB_configuration_in_shared_CMakeLists.patch
  - Fix-pkgconfig-file-by-adding-clucene-shared-library.patch
  - Install-contribs-lib.patch
  - multiarch.patch
* Update debian/compat: bump to 8.
* Update debian/control:
  - update build dependencies (add cmake, libboost-dev and libz-dev).
  - bump Standards-Version to 3.9.3.
  - rename packages due to ABI bump: libclucene0ldbl -> libclucene-core1.
  - add libclucene-contribs1 package.
* Update debian/rules:
  - rewrite to use CMake.
  - add multiarch support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*------------------------------------------------------------------------------
 
2
* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team
 
3
 
4
* Distributable under the terms of either the Apache License (Version 2.0) or 
 
5
* the GNU Lesser General Public License, as specified in the COPYING file.
 
6
------------------------------------------------------------------------------*/
 
7
#include "CLucene/_ApiHeader.h"
 
8
#include "CLucene/index/Term.h"
 
9
#include "CLucene/index/Terms.h"
 
10
#include "CLucene/index/IndexReader.h"
 
11
#include "Similarity.h"
 
12
#include "PrefixQuery.h"
 
13
#include "BooleanClause.h"
 
14
#include "BooleanQuery.h"
 
15
#include "TermQuery.h"
 
16
#include "CLucene/util/BitSet.h"
 
17
#include "CLucene/util/StringBuffer.h"
 
18
 
 
19
CL_NS_USE(util)
 
20
CL_NS_USE(index)
 
21
CL_NS_DEF(search)
 
22
 
 
23
  PrefixQuery::PrefixQuery(Term* Prefix){
 
24
  //Func - Constructor.
 
25
  //       Constructs a query for terms starting with prefix
 
26
  //Pre  - Prefix != NULL 
 
27
  //Post - The instance has been created
 
28
 
 
29
      //Get a pointer to Prefix
 
30
      prefix = _CL_POINTER(Prefix);
 
31
  }
 
32
 
 
33
  PrefixQuery::PrefixQuery(const PrefixQuery& clone):Query(clone){
 
34
        prefix = _CL_POINTER(clone.prefix);
 
35
  }
 
36
  Query* PrefixQuery::clone() const{
 
37
          return _CLNEW PrefixQuery(*this);
 
38
  }
 
39
 
 
40
  Term* PrefixQuery::getPrefix(bool pointer){
 
41
        if ( pointer )
 
42
                return _CL_POINTER(prefix);
 
43
        else
 
44
                return prefix;
 
45
  }
 
46
 
 
47
  PrefixQuery::~PrefixQuery(){
 
48
  //Func - Destructor
 
49
  //Pre  - true
 
50
  //Post - The instance has been destroyed.
 
51
    
 
52
      //Delete prefix by finalizing it
 
53
      _CLDECDELETE(prefix);
 
54
  }
 
55
 
 
56
 
 
57
        /** Returns a hash code value for this object.*/
 
58
        size_t PrefixQuery::hashCode() const {
 
59
                return Similarity::floatToByte(getBoost()) ^ prefix->hashCode();
 
60
        }
 
61
 
 
62
  const char* PrefixQuery::getObjectName()const{
 
63
  //Func - Returns the name "PrefixQuery" 
 
64
  //Pre  - true
 
65
  //Post - The string "PrefixQuery" has been returned
 
66
 
 
67
      return getClassName();
 
68
  }
 
69
  const char* PrefixQuery::getClassName(){
 
70
  //Func - Returns the name "PrefixQuery" 
 
71
  //Pre  - true
 
72
  //Post - The string "PrefixQuery" has been returned
 
73
 
 
74
      return "PrefixQuery";
 
75
  }
 
76
 
 
77
  bool PrefixQuery::equals(Query * other) const{
 
78
          if (!(other->instanceOf(PrefixQuery::getClassName())))
 
79
            return false;
 
80
 
 
81
        PrefixQuery* rq = (PrefixQuery*)other;
 
82
                bool ret = (this->getBoost() == rq->getBoost())
 
83
                        && (this->prefix->equals(rq->prefix));
 
84
 
 
85
                return ret;
 
86
  }
 
87
 
 
88
   Query* PrefixQuery::rewrite(IndexReader* reader){
 
89
    BooleanQuery* query = _CLNEW BooleanQuery( true );
 
90
    TermEnum* enumerator = reader->terms(prefix);
 
91
    Term* lastTerm = NULL;
 
92
    try {
 
93
      const TCHAR* prefixText = prefix->text();
 
94
      const TCHAR* prefixField = prefix->field();
 
95
      const TCHAR* tmp;
 
96
      size_t i;
 
97
      size_t prefixLen = prefix->textLength();
 
98
      do {
 
99
        lastTerm = enumerator->term();
 
100
        if (lastTerm != NULL &&
 
101
          lastTerm->field() == prefixField ) // interned comparison
 
102
        {
 
103
 
 
104
          //now see if term->text() starts with prefixText
 
105
          size_t termLen = lastTerm->textLength();
 
106
          if ( prefixLen>termLen )
 
107
            break; //the prefix is longer than the term, can't be matched
 
108
 
 
109
          tmp = lastTerm->text();
 
110
 
 
111
          //check for prefix match in reverse, since most change will be at the end
 
112
          for ( i=prefixLen-1;i!=-1;--i ){
 
113
              if ( tmp[i] != prefixText[i] ){
 
114
                  tmp=NULL;//signals inequality
 
115
                  break;
 
116
              }
 
117
          }
 
118
          if ( tmp == NULL )
 
119
              break;
 
120
 
 
121
          TermQuery* tq = _CLNEW TermQuery(lastTerm);     // found a match
 
122
          tq->setBoost(getBoost());                // set the boost
 
123
          query->add(tq,true,false, false);               // add to query
 
124
        } else
 
125
          break;
 
126
                _CLDECDELETE(lastTerm);
 
127
      } while (enumerator->next());
 
128
    }_CLFINALLY(
 
129
      enumerator->close();
 
130
          _CLDELETE(enumerator);
 
131
          _CLDECDELETE(lastTerm);
 
132
        );
 
133
        _CLDECDELETE(lastTerm);
 
134
 
 
135
 
 
136
        //if we only added one clause and the clause is not prohibited then
 
137
        //we can just return the query
 
138
        if (query->getClauseCount() == 1) {                    // optimize 1-clause queries
 
139
                BooleanClause* c=0;
 
140
                query->getClauses(&c);
 
141
 
 
142
                if (!c->prohibited) {                     // just return clause
 
143
                        c->deleteQuery=false;
 
144
                        Query* ret = c->getQuery();
 
145
 
 
146
                        _CLDELETE(query);
 
147
                        return ret;
 
148
        }
 
149
        }
 
150
 
 
151
    return query;
 
152
  }
 
153
 
 
154
  Query* PrefixQuery::combine(CL_NS(util)::ArrayBase<Query*>* queries) {
 
155
          return Query::mergeBooleanQueries(queries);
 
156
  }
 
157
 
 
158
  TCHAR* PrefixQuery::toString(const TCHAR* field) const{
 
159
  //Func - Creates a user-readable version of this query and returns it as as string
 
160
  //Pre  - field != NULL
 
161
  //Post - a user-readable version of this query has been returned as as string
 
162
 
 
163
    //Instantiate a stringbuffer buffer to store the readable version temporarily
 
164
    CL_NS(util)::StringBuffer buffer;
 
165
    //check if field equal to the field of prefix
 
166
    if( field==NULL ||
 
167
        _tcscmp(prefix->field(),field) != 0 ) {
 
168
        //Append the field of prefix to the buffer
 
169
        buffer.append(prefix->field());
 
170
        //Append a colon
 
171
        buffer.append(_T(":") );
 
172
    }
 
173
    //Append the text of the prefix
 
174
    buffer.append(prefix->text());
 
175
        //Append a wildchar character
 
176
    buffer.append(_T("*"));
 
177
        //if the boost factor is not eaqual to 1
 
178
    if (getBoost() != 1.0f) {
 
179
                //Append ^
 
180
        buffer.append(_T("^"));
 
181
                //Append the boost factor
 
182
        buffer.appendFloat( getBoost(),1);
 
183
    }
 
184
        //Convert StringBuffer buffer to TCHAR block and return it
 
185
    return buffer.toString();
 
186
  }
 
187
 
 
188
 
 
189
 
 
190
 
 
191
 
 
192
//todo: this needs to be exposed, but java is still a bit confused about how...
 
193
class PrefixFilter::PrefixGenerator{
 
194
  const Term* prefix;
 
195
public:
 
196
  PrefixGenerator(const Term* prefix){
 
197
    this->prefix = prefix;
 
198
  }
 
199
  virtual ~PrefixGenerator(){
 
200
  }
 
201
 
 
202
  virtual void handleDoc(int doc) = 0;
 
203
 
 
204
  void generate(IndexReader* reader) {
 
205
    TermEnum* enumerator = reader->terms(prefix);
 
206
    TermDocs* termDocs = reader->termDocs();
 
207
    const TCHAR* prefixText = prefix->text();
 
208
    const TCHAR* prefixField = prefix->field();
 
209
    const TCHAR* tmp;
 
210
    size_t i;
 
211
    size_t prefixLen = prefix->textLength();
 
212
    Term* term = NULL;
 
213
 
 
214
    try{
 
215
      do{
 
216
          term = enumerator->term(false);
 
217
          if (term != NULL &&
 
218
              term->field() == prefixField // interned comparison
 
219
          ){
 
220
              //now see if term->text() starts with prefixText
 
221
              size_t termLen = term->textLength();
 
222
              if ( prefixLen>termLen )
 
223
                  break; //the prefix is longer than the term, can't be matched
 
224
 
 
225
              tmp = term->text();
 
226
 
 
227
              //check for prefix match in reverse, since most change will be at the end
 
228
              for ( i=prefixLen-1;i!=-1;--i ){
 
229
                  if ( tmp[i] != prefixText[i] ){
 
230
                      tmp=NULL;//signals inequality
 
231
                      break;
 
232
                  }
 
233
              }
 
234
              if ( tmp == NULL )
 
235
                  break;
 
236
 
 
237
            termDocs->seek(enumerator);
 
238
            while (termDocs->next()) {
 
239
              handleDoc(termDocs->doc());
 
240
            }
 
241
          }
 
242
      }while(enumerator->next());
 
243
    } _CLFINALLY(
 
244
        termDocs->close();
 
245
        _CLDELETE(termDocs);
 
246
        enumerator->close();
 
247
      _CLDELETE(enumerator);
 
248
    )
 
249
  }
 
250
};
 
251
 
 
252
class DefaultPrefixGenerator: public PrefixFilter::PrefixGenerator{
 
253
public:
 
254
  BitSet* bts;
 
255
  DefaultPrefixGenerator(BitSet* bts, const Term* prefix):
 
256
    PrefixGenerator(prefix)
 
257
  {
 
258
    this->bts = bts;
 
259
  }
 
260
  virtual ~DefaultPrefixGenerator(){
 
261
  }
 
262
  void handleDoc(int doc) {
 
263
    bts->set(doc);
 
264
  }
 
265
};
 
266
 
 
267
PrefixFilter::PrefixFilter( Term* prefix )
 
268
{
 
269
        this->prefix = _CL_POINTER(prefix);
 
270
}
 
271
 
 
272
PrefixFilter::~PrefixFilter()
 
273
{
 
274
        _CLDECDELETE(prefix);
 
275
}
 
276
 
 
277
PrefixFilter::PrefixFilter( const PrefixFilter& copy ) : 
 
278
        Filter(),
 
279
        prefix( _CL_POINTER(copy.prefix) )
 
280
{
 
281
}
 
282
 
 
283
Filter* PrefixFilter::clone() const {
 
284
        return _CLNEW PrefixFilter(*this );
 
285
}
 
286
 
 
287
TCHAR* PrefixFilter::toString()
 
288
{
 
289
        //Instantiate a stringbuffer buffer to store the readable version temporarily
 
290
    CL_NS(util)::StringBuffer buffer;
 
291
    buffer.append(_T("PrefixFilter("));
 
292
    buffer.append(prefix->field());
 
293
    buffer.append(_T(")"));
 
294
 
 
295
        //Convert StringBuffer buffer to TCHAR block and return it
 
296
    return buffer.toString();
 
297
}
 
298
 
 
299
/** Returns a BitSet with true for documents which should be permitted in
 
300
search results, and false for those that should not. */
 
301
BitSet* PrefixFilter::bits( IndexReader* reader )
 
302
{
 
303
        BitSet* bts = _CLNEW BitSet( reader->maxDoc() );
 
304
  DefaultPrefixGenerator gen(bts, prefix);
 
305
  gen.generate(reader);
 
306
        return bts;
 
307
}
 
308
 
 
309
CL_NS(index)::Term* PrefixFilter::getPrefix() const { return prefix; }
 
310
 
 
311
CL_NS_END