Logo Search packages:      
Sourcecode: qt4-x11 version File versions

PrefixQuery.cpp

/*------------------------------------------------------------------------------
* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team
* 
* Distributable under the terms of either the Apache License (Version 2.0) or 
* the GNU Lesser General Public License, as specified in the COPYING file.
------------------------------------------------------------------------------*/
#include "CLucene/StdHeader.h"
#include "PrefixQuery.h"
#include "CLucene/util/BitSet.h"

CL_NS_USE(util)
CL_NS_USE(index)
CL_NS_DEF(search)

  PrefixQuery::PrefixQuery(Term* Prefix){
  //Func - Constructor.
  //       Constructs a query for terms starting with prefix
  //Pre  - Prefix != NULL 
  //Post - The instance has been created

      //Get a pointer to Prefix
      prefix = _CL_POINTER(Prefix);
  }

  PrefixQuery::PrefixQuery(const PrefixQuery& clone):Query(clone){
      prefix = _CL_POINTER(clone.prefix);
  }
  Query* PrefixQuery::clone() const{
        return _CLNEW PrefixQuery(*this);
  }

  Term* PrefixQuery::getPrefix(bool pointer){
      if ( pointer )
            return _CL_POINTER(prefix);
      else
            return prefix;
  }

  PrefixQuery::~PrefixQuery(){
  //Func - Destructor
  //Pre  - true
  //Post - The instance has been destroyed.
    
      //Delete prefix by finalizing it
      _CLDECDELETE(prefix);
  }


      /** Returns a hash code value for this object.*/
      size_t PrefixQuery::hashCode() const {
            return Similarity::floatToByte(getBoost()) ^ prefix->hashCode();
      }

  const TCHAR* PrefixQuery::getQueryName()const{
  //Func - Returns the name "PrefixQuery" 
  //Pre  - true
  //Post - The string "PrefixQuery" has been returned

      return getClassName();
  }
  const TCHAR* PrefixQuery::getClassName(){
  //Func - Returns the name "PrefixQuery" 
  //Pre  - true
  //Post - The string "PrefixQuery" has been returned

      return _T("PrefixQuery");
  }

  bool PrefixQuery::equals(Query * other) const{
        if (!(other->instanceOf(PrefixQuery::getClassName())))
            return false;

        PrefixQuery* rq = (PrefixQuery*)other;
            bool ret = (this->getBoost() == rq->getBoost())
                  && (this->prefix->equals(rq->prefix));

            return ret;
  }

   Query* PrefixQuery::rewrite(IndexReader* reader){
    BooleanQuery* query = _CLNEW BooleanQuery();
    TermEnum* enumerator = reader->terms(prefix);
      Term* lastTerm = NULL;
    try {
      const TCHAR* prefixText = prefix->text();
      const TCHAR* prefixField = prefix->field();
        int32_t prefixLen = prefix->textLength();
      do {
        lastTerm = enumerator->term();
            if (lastTerm != NULL && lastTerm->field() == prefixField ){
              
              //now see if term->text() starts with prefixText
              int32_t termLen = lastTerm->textLength();
              if ( prefixLen>termLen )
                    break; //the prefix is longer than the term, can't be matched

              //check for prefix match
              if ( _tcsncmp(lastTerm->text(),prefixText,prefixLen)!=0 )
                    break;

          TermQuery* tq = _CLNEW TermQuery(lastTerm);   // found a match
          tq->setBoost(getBoost());                // set the boost
          query->add(tq,true,false, false);             // add to query
        } else
          break;
            _CLDECDELETE(lastTerm);
      } while (enumerator->next());
    }_CLFINALLY(
      enumerator->close();
        _CLDELETE(enumerator);
        _CLDECDELETE(lastTerm);
      );
      _CLDECDELETE(lastTerm);


      //if we only added one clause and the clause is not prohibited then
      //we can just return the query
      if (query->getClauseCount() == 1) {                    // optimize 1-clause queries
            BooleanClause* c=0;
            query->getClauses(&c);

            if (!c->prohibited) {                 // just return clause
                  c->deleteQuery=false;
                  Query* ret = c->query;

                  _CLDELETE(query);
                  return ret;
        }
      }

    return query;
  }

  Query* PrefixQuery::combine(Query** queries) {
        return Query::mergeBooleanQueries(queries);
  }

  TCHAR* PrefixQuery::toString(const TCHAR* field) const{
  //Func - Creates a user-readable version of this query and returns it as as string
  //Pre  - field != NULL
  //Post - a user-readable version of this query has been returned as as string

    //Instantiate a stringbuffer buffer to store the readable version temporarily
    CL_NS(util)::StringBuffer buffer;
    //check if field equal to the field of prefix
    if( field==NULL || _tcscmp(prefix->field(),field) != 0 ) {
        //Append the field of prefix to the buffer
        buffer.append(prefix->field());
        //Append a colon
        buffer.append(_T(":") );
    }
    //Append the text of the prefix
    buffer.append(prefix->text());
      //Append a wildchar character
    buffer.append(_T("*"));
      //if the boost factor is not eaqual to 1
    if (getBoost() != 1.0f) {
            //Append ^
        buffer.append(_T("^"));
            //Append the boost factor
        buffer.appendFloat( getBoost(),1);
    }
      //Convert StringBuffer buffer to TCHAR block and return it
    return buffer.toString();
  }








PrefixFilter::PrefixFilter( Term* prefix )
{
      this->prefix = _CL_POINTER(prefix);
}

PrefixFilter::~PrefixFilter()
{
      _CLDECDELETE(prefix);
}

PrefixFilter::PrefixFilter( const PrefixFilter& copy ) : 
      prefix( _CL_POINTER(copy.prefix) )
{
}

Filter* PrefixFilter::clone() const {
      return _CLNEW PrefixFilter(*this );
}

TCHAR* PrefixFilter::toString()
{
      //Instantiate a stringbuffer buffer to store the readable version temporarily
    CL_NS(util)::StringBuffer buffer;
    //check if field equal to the field of prefix
    if( prefix->field() != NULL ) {
        //Append the field of prefix to the buffer
      buffer.append(prefix->field());
        //Append a colon
      buffer.append(_T(":") );
    }
    //Append the text of the prefix
    buffer.append(prefix->text());
    buffer.append(_T("*"));

      //Convert StringBuffer buffer to TCHAR block and return it
    return buffer.toString();
}

/** Returns a BitSet with true for documents which should be permitted in
search results, and false for those that should not. */
BitSet* PrefixFilter::bits( IndexReader* reader )
{
      BitSet* bts = _CLNEW BitSet( reader->maxDoc() );
      TermEnum* enumerator = reader->terms(prefix);
      TermDocs* docs = reader->termDocs();
    const TCHAR* prefixText = prefix->text();
    const TCHAR* prefixField = prefix->field();
    int32_t prefixLen = prefix->textLength();
      Term* lastTerm = NULL;
    
      try{
            do{
            lastTerm = enumerator->term(false);
            if (lastTerm != NULL && lastTerm->field() == prefixField ){
                //now see if term->text() starts with prefixText
                int32_t termLen = lastTerm->textLength();
                if ( prefixLen>termLen )
                    break; //the prefix is longer than the term, can't be matched

                //check for prefix match
                if ( _tcsncmp(lastTerm->text(),prefixText,prefixLen)!=0 )
                    break;

                  docs->seek(enumerator);
                  while (docs->next()) {
                    bts->set(docs->doc());
                  }
            }
            }while(enumerator->next());
      } _CLFINALLY(
      docs->close();
      _CLDELETE(docs);
      enumerator->close();
        _CLDELETE(enumerator);
    )

      return bts;
}

CL_NS_END

Generated by  Doxygen 1.6.0   Back to index