/*------------------------------------------------------------------------------
* 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 "RangeFilter.h"
CL_NS_DEF(search)
CL_NS_USE(index)
CL_NS_USE(util)
CL_NS_USE(document)
RangeFilter::RangeFilter( const TCHAR* fieldName, const TCHAR* lowerTerm, const TCHAR* upperTerm, bool includeLower, bool includeUpper )
{
this->field = STRDUP_TtoT(fieldName);
if ( lowerTerm != NULL )
this->lowerValue = STRDUP_TtoT(lowerTerm);
else
this->lowerValue = NULL;
if ( upperValue != NULL )
this->upperValue = STRDUP_TtoT(upperTerm);
else
this->upperValue = NULL;
this->includeLower = includeLower;
this->includeUpper = includeUpper;
}
/**
* Constructs a filter for field fieldName
matching
* less than or equal to upperTerm
.
*/
RangeFilter* RangeFilter::Less( TCHAR* fieldName, TCHAR* upperTerm ) {
return new RangeFilter( fieldName, NULL, upperTerm, false, true );
}
/**
* Constructs a filter for field fieldName
matching
* more than or equal to lowerTerm
.
*/
RangeFilter* RangeFilter::More( TCHAR* fieldName, TCHAR* lowerTerm ) {
return new RangeFilter( fieldName, lowerTerm, NULL, true, false );
}
RangeFilter::~RangeFilter()
{
_CLDELETE_CARRAY( lowerValue );
_CLDELETE_CARRAY( field );
_CLDELETE_CARRAY( upperValue );
}
RangeFilter::RangeFilter( const RangeFilter& copy ) :
field( STRDUP_TtoT(copy.field) ),
lowerValue( STRDUP_TtoT(copy.lowerValue) ),
upperValue( STRDUP_TtoT(copy.upperValue) ),
includeLower( copy.includeLower ),
includeUpper( copy.includeUpper )
{
}
Filter* RangeFilter::clone() const {
return _CLNEW RangeFilter(*this );
}
TCHAR* RangeFilter::toString()
{
size_t len = (field ? _tcslen(field) : 0) + (lowerValue ? _tcslen(lowerValue) : 0) + (upperValue ? _tcslen(upperValue) : 0) + 8;
TCHAR* ret = _CL_NEWARRAY( TCHAR, len );
ret[0] = 0;
_sntprintf( ret, len, _T("%s: [%s-%s]"), field, (lowerValue?lowerValue:_T("")), (upperValue?upperValue:_T("")) );
return ret;
}
/** Returns a BitSet with true for documents which should be permitted in
search results, and false for those that should not. */
BitSet* RangeFilter::bits( IndexReader* reader )
{
BitSet* bts = _CLNEW BitSet( reader->maxDoc() );
Term* term = NULL;
Term* t = _CLNEW Term( field, (lowerValue ? lowerValue : _T("")), false );
TermEnum* enumerator = reader->terms( t ); // get enumeration of all terms after lowerValue
_CLDECDELETE( t );
if( enumerator->term(false) == NULL ) {
_CLDELETE( enumerator );
return bts;
}
bool checkLower = false;
if( !includeLower ) // make adjustments to set to exclusive
checkLower = true;
TermDocs* termDocs = reader->termDocs();
try
{
do
{
term = enumerator->term();
if( term == NULL || _tcscmp(term->field(), field) )
break;
if( !checkLower || lowerValue == NULL || _tcscmp(term->text(), lowerValue) > 0 )
{
checkLower = false;
if( upperValue != NULL )
{
int compare = _tcscmp( upperValue, term->text() );
/* if beyond the upper term, or is exclusive and
* this is equal to the upper term, break out */
if( (compare < 0) || (!includeUpper && compare == 0) )
break;
}
termDocs->seek( enumerator->term(false) );
while( termDocs->next() ) {
bts->set( termDocs->doc() );
}
}
_CLDECDELETE( term );
}
while( enumerator->next() );
}
_CLFINALLY
(
_CLDECDELETE( term );
termDocs->close();
_CLVDELETE( termDocs );
enumerator->close();
_CLDELETE( enumerator );
);
return bts;
}
CL_NS_END