searchfw/coresearchfw/utilities/src/searchtextsearcher.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 10:12:19 +0200
changeset 0 f979ecb2b13e
permissions -rw-r--r--
Revision: 201003 Kit: 201005

/*
* Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:   Class handling the search of several keywords in a block of 
*                text.
*
*/



#include <utf.h>

#include <searchtextsearcherobserver.h>
#include <searchsinglecondition.h>
#include <searchcondition.h>
#include <searchfield.h>
#include <searchtextsearcher.h>
#include "searchkeywordstatus.h"
#include "searchalgorithm.h"

#include <featmgr.h>

_LIT(KColon,":");
const  TInt KNumberDataLength( 50 );
const  TInt KTimeDataLength( 50 );
const  TInt KArrayGranularity( 2 );
const  TInt KSingleKeywordInArray( 1 ); 


// -----------------------------------------------------------------------------
// CSearchTextSearcher::NewL()
// Symbian C++ 2  phase construction
// -----------------------------------------------------------------------------
//
EXPORT_C CSearchTextSearcher*  CSearchTextSearcher::NewL( 
		MSearchTextSearcherObserver& aObserver )
    {
    CSearchTextSearcher* self = CSearchTextSearcher::NewLC( aObserver );
    CleanupStack::Pop( self );
    return self;
    }

// -----------------------------------------------------------------------------
// CSearchTextSearcher::NewLC()
// Symbian C++ 2  phase construction
// -----------------------------------------------------------------------------
//
EXPORT_C CSearchTextSearcher*  CSearchTextSearcher::NewLC( 
		MSearchTextSearcherObserver&  aObserver )
    {
    CSearchTextSearcher* self = new( ELeave ) CSearchTextSearcher( aObserver );
    CleanupStack::PushL( self );
    ( *self ).ConstructL();
    return self;
    }    
    
// -----------------------------------------------------------------------------
// CSearchTextSearcher::~CSearchTextSearcher()
// C++ destructor
// -----------------------------------------------------------------------------
//
CSearchTextSearcher::~CSearchTextSearcher()
    {
    iKeywordSearchStatusArray.Close();
    
    if ( iSearchKeywords8 )
        {
        iSearchKeywords8->Reset();
        delete iSearchKeywords8;
        iSearchKeywords8 = NULL;
        }
    
    if ( iHaveParameters != TRUE )
        {
        iSearchKeywords16->Reset();
        delete iSearchKeywords16;
        iSearchKeywords16 = NULL;
        }
  
    if ( iSearchAlgorithm )
        {
        delete iSearchAlgorithm;     
        iSearchAlgorithm = NULL;
        }
        iClause.Reset();
        iClause.Close();
        FeatureManager::UnInitializeLib();
    }
    
// -----------------------------------------------------------------------------
// CSearchTextSearcher::Cleanup()
// Cleanup Method
// -----------------------------------------------------------------------------
//
EXPORT_C void CSearchTextSearcher::Cleanup()
    {
    iKeywordSearchStatusArray.Reset();
    for ( TInt i = 0; i < iKeywordSearchStatusArray.Count() ; i++ )
        {
        iKeywordSearchStatusArray[i].iFound = EFalse;
        iKeywordSearchStatusArray[i].iFoundAtNthPosition = KErrNotFound;
        }
    }
// -----------------------------------------------------------------------------
// CSearchTextSearcher::SetParametersL()
// Sets the search parameters for the search.
// -----------------------------------------------------------------------------
//
EXPORT_C void CSearchTextSearcher::SetParametersL( const MDesCArray& aKeywords,
              CSearchTextSearcher::TSearchCriteriaOperator 
              aOperator, TBool aCaseSensitive )
    {
    iSearchKeywords = static_cast<const CDesC16Array*>( &aKeywords );
    iOperator = aOperator;
    iCaseSensitive = aCaseSensitive;
      
    //convert from 16 - 8 bits for keyword
    iSearchKeywords8->Reset();
    iCount = iSearchKeywords->MdcaCount();
    
    DoUftTo8BitConversionL( *iSearchKeywords );    
    
    //initialize keyword status
    iKeywordSearchStatusArray.Reset();
    for ( TInt i = 0 ;i < iCount ; i++ )
        {
        TKeywordSearchStatus status;
        status.iFound  = EFalse;
        status.iFoundAtNthPosition = KErrNotFound;
        iKeywordSearchStatusArray.AppendL( status ); 
        }
    //Set it here to indicate client has called this method   
    iHaveParameters = ETrue; 
    if ( iCount == KSingleKeywordInArray) 
        {
          iIsBooleanCondition = EFalse;
        }
    else
        {
          iIsBooleanCondition = ETrue;
          //SetCriteriaOperator(); not to be called here , dont have clause yet          
        }    
    
    }

// -----------------------------------------------------------------------------
// CSearchTextSearcher::SetParametersL()
// Sets the search parameters based on conditions for the search.
// -----------------------------------------------------------------------------
//
EXPORT_C void CSearchTextSearcher::SetParametersL( const CSearchCondition& 
                                                                aCondition )
    {
    if ( iHaveParameters )
        {
        return;
        }
    else
        {
        iSearchKeywords16 = new( ELeave ) CDesC16ArrayFlat( KArrayGranularity );     
        }
        
    switch( aCondition.Type() )
        {
        case CSearchCondition::EConditionTypeSimple:
            {
            iOperator = ESearchCriteriaAND; 
            iIsBooleanCondition = EFalse;
            SetSingleConditionDataL( 
            *(static_cast<const CSearchSingleCondition*>( &aCondition ) ) );
            }
            break;
        case CSearchCondition::EConditionTypeBoolean:
            {
            iOperator = ESearchCriteriaAND; 
            iIsBooleanCondition = ETrue;
            RPointerArray<CSearchCondition> conditions;
            (static_cast<const CSearchBooleanCondition*>( &aCondition ) )->
            GetConditions( conditions,iClause );
            
            for ( TInt i = 0; i < conditions.Count() ; i++ )
                {
                SetSingleConditionDataL( 
                *(static_cast<const CSearchSingleCondition*>( conditions[i] ) ) );
                }
            iCount = iSearchKeywords16->Count(); 
            conditions.Reset();
            conditions.Close();
            
            SetCriteriaOperator( );  
            }
            break;
            
        default:
            break;  
        }
      
    DoUftTo8BitConversionL( *iSearchKeywords16 );  
    }
    
// -----------------------------------------------------------------------------
// CSearchTextSearcher::SearchL()
// Starts the text search with the previous supplied parameters set 
// by SetParametersL. 16 bit version.
// -----------------------------------------------------------------------------
//
EXPORT_C void CSearchTextSearcher::SearchL( const TDesC16& aToBeSearchedDes )
    {
    iKeywordSearchStatusArray.Reset();
	for ( TInt i = 0 ;i < iCount ; i++ )
	    {
		TKeywordSearchStatus status;
		status.iFound  = EFalse;
		status.iFoundAtNthPosition = KErrNotFound;
		iKeywordSearchStatusArray.AppendL( status ); 
	    }
    
    if ( iHaveParameters )
        {
         DoStringCompareWithKeywordsL( aToBeSearchedDes,*iSearchKeywords,
              iKeywordSearchStatusArray,iOperator,iCaseSensitive ); 
        }
    else
        {
        DoStringCompareWithKeywordsL( aToBeSearchedDes,*iSearchKeywords16,
              iKeywordSearchStatusArray,iOperator,iCaseSensitive );
        }
    }


// -----------------------------------------------------------------------------
// CSearchTextSearcher::SearchL()
// Starts the text search with the previous supplied parameters set by
// SetParametersL.  8 bit version.
// -----------------------------------------------------------------------------
//
EXPORT_C void CSearchTextSearcher::SearchL ( const TDesC8& aToBeSearchedDes )
    {
    DoStringCompareWithKeywordsL( aToBeSearchedDes,*iSearchKeywords8,
            iKeywordSearchStatusArray,iOperator,iCaseSensitive );
    }  

// -----------------------------------------------------------------------------
// Set whether searching for the email
// -----------------------------------------------------------------------------
//      
EXPORT_C void CSearchTextSearcher::SearchEmailAddress ( TBool aSearchEmail ) 
    {
	iSearchAlgorithm->SearchEmailAddress ( aSearchEmail );
    }

// -----------------------------------------------------------------------------
// Return the search keyword
// -----------------------------------------------------------------------------
//
EXPORT_C CDesC16ArrayFlat* CSearchTextSearcher::SearchKeyword()
    {
    return iSearchKeywords16; 	
    }

// -----------------------------------------------------------------------------
// CSearchTextSearcher::CSearchTextSearcher()
// C++ default constructor
// -----------------------------------------------------------------------------
//
CSearchTextSearcher::CSearchTextSearcher(
       MSearchTextSearcherObserver& aObserver )
:   iObserver( aObserver ) 
    {
    
    }
   
// -----------------------------------------------------------------------------
// CSearchTextSearcher::ConstructL()
// Symbian 2nd phase construction
// -----------------------------------------------------------------------------
//
void CSearchTextSearcher::ConstructL()
    {
    iSearchKeywords8 = new(ELeave) CDesC8ArrayFlat( KArrayGranularity ); 
    iSearchAlgorithm = CSearchAlgorithm::NewL();
    iSearchAlgorithm->SearchEmailAddress( ETrue );
    iHaveParameters = EFalse;
    iSameCondition  = EFalse;
    iIsBooleanCondition = EFalse;
    FeatureManager::InitializeLibL();
    }
    
// -----------------------------------------------------------------------------
// CSearchTextSearcher::DoStringCompareWithKeywords()
// Compares the to be searched string with the list of keywords, 16 bit version. 
// -----------------------------------------------------------------------------
//
TBool CSearchTextSearcher::DoStringCompareWithKeywordsL (
			 const TDesC& aToBeSearchedDes,
             const CDesC16Array& aKeywords, 
             RArray<TKeywordSearchStatus>& aKeywordSearchStatusArray,
             CSearchTextSearcher::TSearchCriteriaOperator aOperator,
             TBool aCaseSensitive )
    {
    iSearchAlgorithm->SearchL( aToBeSearchedDes,aKeywords,
                              aKeywordSearchStatusArray,
                              aOperator,
                              aCaseSensitive );
    if ( aKeywordSearchStatusArray.Count() >= 0 )
        {
        if ( iIsBooleanCondition )
            {
            CheckForBooleanClausesL( aKeywordSearchStatusArray );   
            }
        else
            {
            if ( !aKeywordSearchStatusArray[0].iFound )
                {
                iObserver.HitL( KErrNotFound );
                }
            else
                {
                iObserver.HitL( aKeywordSearchStatusArray[0].iFoundAtNthPosition );
                }   
            }
        }
      
   return TRUE;                           
   }
      
     
// -----------------------------------------------------------------------------
// CSearchTextSearcher::DoStringCompareWithKeywords()
// Compares the to be searched string with the list of keywords, 8 bit version. 
// -----------------------------------------------------------------------------
//
TBool CSearchTextSearcher::DoStringCompareWithKeywordsL (
          const TDesC8& aToBeSearchedDes,
          const CDesC8Array& aKeywords, 
          RArray<TKeywordSearchStatus>& aKeywordSearchStatusArray,
          CSearchTextSearcher::TSearchCriteriaOperator  aOperator,
          TBool aCaseSensitive )
    {
    iSearchAlgorithm->SearchL( aToBeSearchedDes,aKeywords,
             aKeywordSearchStatusArray,aOperator, aCaseSensitive );
    if ( aKeywordSearchStatusArray.Count() >= 0 )
        {
        if ( iIsBooleanCondition )
            {
            CheckForBooleanClausesL( aKeywordSearchStatusArray );   
            }
        else
            {
            if ( !aKeywordSearchStatusArray[0].iFound )
                {
                iObserver.HitL( KErrNotFound );
                }
            else
                {
                iObserver.HitL( aKeywordSearchStatusArray[0].iFoundAtNthPosition );
                }   
            }
        }
    return TRUE; 
    }
     
 // -----------------------------------------------------------------------------
// CSearchTextSearcher::SetSingleConditionDataL()
// Sets the singlecondition data for the search.
// -----------------------------------------------------------------------------
//    
void  CSearchTextSearcher::SetSingleConditionDataL ( const 
          CSearchSingleCondition& aSingleCondition )
    {
    const CSearchField& field = aSingleCondition.Term();
    switch ( field.DataType() )
        { 
        case ESearchFieldDataTypeUnknown:
            break;
        case ESearchFieldDataTypeTInt:
            {
            TInt intData;
            field.GetData( intData );
            HBufC* pbuf = HBufC::NewLC( KNumberDataLength );
            pbuf->Des().AppendNum( intData );
            iSearchKeywords16->AppendL( pbuf->Des() );
            CleanupStack::PopAndDestroy( pbuf );
            }
            break;
        case ESearchFieldDataTypeTReal:
            {  
            TReal realData;
            TRealFormat  realFormat( KRealFormatGeneral,KDefaultRealWidth );
            field.GetData( realData );
            HBufC* pbuf = HBufC::NewLC( KNumberDataLength );
            pbuf->Des().AppendNum( realData,realFormat );
            iSearchKeywords16->AppendL( pbuf->Des() );
            CleanupStack::PopAndDestroy( pbuf );
            }
            break;
        case ESearchFieldDataTypeTTime:
            {
            TTime timeData;
            field.GetData( timeData );
            TDateTime dateTime = timeData.DateTime();
                   
            HBufC* pbuf = HBufC::NewLC( KTimeDataLength) ;
                   
            //Set Time and inset into array
            pbuf->Des().AppendNum( dateTime.Hour() );
            pbuf->Des().Append( KColon );
            pbuf->Des().AppendNum( dateTime.Minute() );
            pbuf->Des().Append( KColon );
            pbuf->Des().AppendNum( dateTime.Second() );
            iSearchKeywords16->AppendL( pbuf->Des() );
            CleanupStack::PopAndDestroy( pbuf );
            }
            break;
        case ESearchFieldDataTypeTDesC:
            {
            TPtrC8  ptr;
            field.GetData( ptr );
            HBufC*  dataDes = HBufC::NewLC( ptr.Length() );
            TPtr  pdata = dataDes->Des();
            CnvUtfConverter::ConvertToUnicodeFromUtf8( pdata , ptr  );
            
            if ( FeatureManager::FeatureSupported( KFeatureIdJapanese ) ||
                 FeatureManager::FeatureSupported( KFeatureIdChinese )  ||
                 FeatureManager::FeatureSupported( KFeatureIdThai ) )
                {
                HBufC* tempBuffer = HBufC::NewLC( ptr.Length() + 1);
                TPtr pDataTemp = tempBuffer->Des();
                _LIT(KStar, "*");
                pDataTemp.Zero();
                pDataTemp.Append(KStar);
                pDataTemp.Append(pdata);
                            
                iSearchKeywords16->AppendL( pDataTemp );
                CleanupStack::PopAndDestroy( tempBuffer );
                }
            else
                {
                iSearchKeywords16->AppendL( pdata );
                }
            
            CleanupStack::PopAndDestroy( dataDes );
            }
            break;
        case ESearchFieldDataTypeCustom:
            break;
        default:
            break;
        }
    }


// -----------------------------------------------------------------------------
// CSearchTextSearcher::DoUftTo8BitConvertionL()
// 16 - 8 bit conversion 
// -----------------------------------------------------------------------------
//
void CSearchTextSearcher::DoUftTo8BitConversionL ( const MDesCArray& aKeywords )
    {
    for ( TInt i = 0 ;i < aKeywords.MdcaCount() ; i++ )
        {
        HBufC8* pBuf = HBufC8::NewLC( aKeywords.MdcaPoint( i ).Length() );
        TPtr8 ptr8 = pBuf->Des();
        CnvUtfConverter::ConvertFromUnicodeToUtf8( ptr8 ,aKeywords.MdcaPoint( i ) );
        iSearchKeywords8->AppendL( ptr8 );
        CleanupStack::PopAndDestroy( pBuf );
        }
    }


// -----------------------------------------------------------------------------
// CSearchTextSearcher::SetCriteriaOperator()
// -----------------------------------------------------------------------------
//
void CSearchTextSearcher::SetCriteriaOperator()
    {
    
    RArray<CSearchBooleanCondition::TBooleanClause>& clause = iClause;
    
    TInt condition = iBooleanClause = clause[0]; // take first clause out 
    
    TInt nextclause= 0; 
    for ( TInt i = 0 ;i < clause.Count() ; i++ )
        {
        if ( i>0 )
            { 
            nextclause = clause[i];
            condition ^=nextclause; //check if all are 
            				//the same clause category ( ANDs or ORs )
            if ( condition )
                {
                iIntermediateClause = clause[i];
                break;
                }
            }
        }
     if ( !condition ) // iSameCondition is initially set to FALSE 
        {
        iSameCondition = TRUE;
        }
   
    }    
     
// -----------------------------------------------------------------------------
// CSearchTextSearcher::CheckForBooleanClausesL()
// Compares the to be searched string with the list of keywords, 8 bit version. 
// -----------------------------------------------------------------------------
//
void CSearchTextSearcher::CheckForBooleanClausesL( RArray<TKeywordSearchStatus>& 
                                                            aKeywordSearchStatusArray )
    {
    
    TBool ifNoneFound = ETrue;
    TInt  recordFirstPos   = 0;   
    
    for ( TInt i = 0 ; i < iCount && i < aKeywordSearchStatusArray.Count() ; i++ )
        {
        if (  iBooleanClause == CSearchBooleanCondition::EBooleanMust
        		 && iSameCondition )
            {
            if ( !aKeywordSearchStatusArray[i].iFound )
                {
                ifNoneFound = ETrue;
                break;
                }
            else
                {
                ifNoneFound = EFalse;
                if ( !recordFirstPos )
                    {
                    recordFirstPos = 
                       aKeywordSearchStatusArray[i].iFoundAtNthPosition;	
                    }
                //iObserver.HitL( 
                //	aKeywordSearchStatusArray[i].iFoundAtNthPosition );    
                }
            }
        else if ( iBooleanClause == CSearchBooleanCondition::EBooleanShould 
        			&&  iSameCondition )
            {
            if ( !aKeywordSearchStatusArray[i].iFound )
                {
                //Do nothing ,just pass on
                }
            else
                {
                ifNoneFound = EFalse;
                iObserver.HitL(
                	 aKeywordSearchStatusArray[i].iFoundAtNthPosition );
                }    
            }
        else //if( !iSameCondition ) 
            {
            if ( !aKeywordSearchStatusArray[i].iFound )
                {
                if ( iBooleanClause  == CSearchBooleanCondition::EBooleanMust )
                    {
                    ifNoneFound = ETrue;
                    //break;  
                    }
                else if( iBooleanClause  == 
                         CSearchBooleanCondition::EBooleanShould 
                         && iIntermediateClause == 
                         CSearchBooleanCondition::EBooleanMust )
                    {
                    ifNoneFound = ETrue;
                    //break;     
                   } 
                }
            else 
                {
                ifNoneFound = EFalse;
                iObserver.HitL( aKeywordSearchStatusArray[i].iFoundAtNthPosition );
                }
            }
        }
    
    if ( !ifNoneFound && iBooleanClause == 
           CSearchBooleanCondition::EBooleanMust ) 
        {
        iObserver.HitL( recordFirstPos ); 
        }
    }