metadataengine/server/src/mdsfindsequence.cpp
changeset 0 c53acadfccc6
child 1 acef663c1218
equal deleted inserted replaced
-1:000000000000 0:c53acadfccc6
       
     1 /*
       
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Manages object search from database*
       
    15 */
       
    16 
       
    17 #include <badesca.h>
       
    18 
       
    19 #include "mdsfindsequence.h"
       
    20 
       
    21 #include "mdcitem.h"
       
    22 #include "mdcresult.h"
       
    23 #include "mdcserializationbuffer.h"
       
    24 #include "mdsschema.h"
       
    25 #include "mdslogger.h"
       
    26 #include "mdsfindengine.h"
       
    27 #include "mdssqlfindoperation.h"
       
    28 #include "mdssqliteconnection.h"
       
    29 #include "mdsfindsqlclause.h"
       
    30 #include "mdsdbconnectionpool.h"
       
    31 #include "mdsclausebuffer.h"
       
    32 
       
    33 
       
    34 /** logging instance */
       
    35 __USES_LOGGER
       
    36 
       
    37 
       
    38 // ------------------------------------------------
       
    39 // NewL
       
    40 // ------------------------------------------------
       
    41 //
       
    42 CMdSFindSequence* CMdSFindSequence::NewL( 
       
    43 	CMdSServer& aServer, CMdsSchema& aSchema, CMdSFindEngine& aObserver )
       
    44     {
       
    45     CMdSFindSequence* self = CMdSFindSequence::NewLC( aServer, aSchema, aObserver );
       
    46     CleanupStack::Pop( self );
       
    47     return self;
       
    48     }
       
    49 
       
    50 // ------------------------------------------------
       
    51 // NewLC
       
    52 // ------------------------------------------------
       
    53 //
       
    54 CMdSFindSequence* CMdSFindSequence::NewLC( 
       
    55 	CMdSServer& aServer, CMdsSchema& aSchema, CMdSFindEngine& aObserver )
       
    56     {
       
    57     CMdSFindSequence* self = new(ELeave) CMdSFindSequence( aServer, aSchema, aObserver );
       
    58     CleanupStack::PushL( self );
       
    59     self->ConstructL();
       
    60     return self;
       
    61     }
       
    62 
       
    63 // ------------------------------------------------
       
    64 // Default constructor
       
    65 // ------------------------------------------------
       
    66 //
       
    67 CMdSFindSequence::CMdSFindSequence( 
       
    68 	CMdSServer& aServer, CMdsSchema& aSchema, CMdSFindEngine& aObserver )
       
    69     : CActive( CActive::EPriorityStandard )
       
    70     , iServer( aServer )
       
    71     , iSchema( aSchema )
       
    72     , iObserver( &aObserver )
       
    73     , iUserLevel( EUserLevelNone )
       
    74     {
       
    75 	iNotifyCount = KMaxTUint32;
       
    76 
       
    77     iFindOperation = NULL;
       
    78     }
       
    79 
       
    80 // ------------------------------------------------
       
    81 // ConstructL
       
    82 // ------------------------------------------------
       
    83 //
       
    84 void CMdSFindSequence::ConstructL()
       
    85     {
       
    86     CActiveScheduler::Add( this );
       
    87     __INIT_LOGGER;
       
    88     }
       
    89 
       
    90 // ------------------------------------------------
       
    91 // Destructor
       
    92 // ------------------------------------------------
       
    93 //
       
    94 CMdSFindSequence::~CMdSFindSequence()
       
    95     {
       
    96     CleanUp();
       
    97     
       
    98     Cancel();
       
    99     }
       
   100 
       
   101 void CMdSFindSequence::SetFindParams( TUint32 aNotifyCount )
       
   102 	{
       
   103 	iNotifyCount = aNotifyCount;
       
   104 	}
       
   105 
       
   106 // ------------------------------------------------
       
   107 // FindL
       
   108 // ------------------------------------------------
       
   109 //
       
   110 TInt CMdSFindSequence::FindL(
       
   111     CMdCSerializationBuffer& aSerializedCriteria,
       
   112     TUserLevel aUserLevel )
       
   113     {
       
   114     __ASSERT_DEBUG( !iFindOperation, MMdCCommon::Panic( KErrCorrupt ) );
       
   115 
       
   116 	iUserLevel = aUserLevel;
       
   117 
       
   118 	iSerializedCriteria = &aSerializedCriteria;
       
   119 
       
   120 	if( iFindResults )
       
   121 		{
       
   122 		delete iFindResults;
       
   123 		iFindResults = NULL;
       
   124 		}
       
   125  
       
   126     iFindOperation = CreateOperationL( aSerializedCriteria );
       
   127 
       
   128     TInt result = KErrNone;
       
   129     result = iFindOperation->ExecuteL();
       
   130     
       
   131     iFindResults = iFindOperation->Results();
       
   132     
       
   133     if( iFindResults )
       
   134     	{
       
   135     	PostProcessL( *iFindResults );
       
   136     	}
       
   137 
       
   138     return result;
       
   139     }
       
   140 
       
   141 // ------------------------------------------------
       
   142 // ContinueL
       
   143 // ------------------------------------------------
       
   144 //
       
   145 TInt CMdSFindSequence::ContinueL()
       
   146     {
       
   147     __ASSERT_DEBUG( iFindOperation, MMdCCommon::Panic( KErrCorrupt ) );
       
   148 
       
   149 	if( iFindResults )
       
   150 		{
       
   151 		delete iFindResults;
       
   152 		iFindResults = NULL;
       
   153 		}
       
   154     
       
   155     TInt result = iFindOperation->ContinueL();
       
   156 
       
   157     if ( result == KErrNone )
       
   158         {
       
   159         iFindResults = iFindOperation->Results();
       
   160 
       
   161 		if( iFindResults )
       
   162 			{
       
   163 			PostProcessL( *iFindResults );
       
   164 			}
       
   165         }
       
   166 
       
   167     return result;
       
   168     }
       
   169 
       
   170 // ------------------------------------------------
       
   171 // FindAsync
       
   172 // ------------------------------------------------
       
   173 //
       
   174 void CMdSFindSequence::FindAsync(CMdCSerializationBuffer& aSerializedCriteria,
       
   175 		TUserLevel aUserLevel )
       
   176     {
       
   177     __ASSERT_DEBUG( !iFindOperation, MMdCCommon::Panic( KErrCorrupt ) );
       
   178     
       
   179     iUserLevel = aUserLevel;
       
   180 
       
   181 	if( iFindResults )
       
   182 		{
       
   183 		delete iFindResults;
       
   184 		iFindResults = NULL;
       
   185 		}
       
   186 
       
   187     iSerializedCriteria = &aSerializedCriteria;
       
   188 
       
   189     SetActive();
       
   190     TRequestStatus* pStatus = &iStatus;
       
   191     User::RequestComplete( pStatus, EAsyncFind );
       
   192     }
       
   193 
       
   194 // ------------------------------------------------
       
   195 // ContinueAsync
       
   196 // ------------------------------------------------
       
   197 //
       
   198 void CMdSFindSequence::ContinueAsync()
       
   199     {
       
   200     __ASSERT_DEBUG( iFindOperation, MMdCCommon::Panic( KErrCorrupt ) );
       
   201 
       
   202 	if( iFindResults )
       
   203 		{
       
   204 		delete iFindResults;
       
   205 		iFindResults = NULL;
       
   206 		}
       
   207 
       
   208     SetActive();
       
   209     TRequestStatus* pStatus = &iStatus;
       
   210     User::RequestComplete( pStatus, EContinueAsyncFind );
       
   211     }
       
   212 
       
   213 // ------------------------------------------------
       
   214 // Results
       
   215 // ------------------------------------------------
       
   216 //
       
   217 CMdCSerializationBuffer& CMdSFindSequence::ResultsL() const
       
   218     {
       
   219     if( !iFindResults )
       
   220     	{
       
   221     	User::Leave( KErrCorrupt );
       
   222     	}
       
   223 
       
   224     return *iFindResults;
       
   225     }
       
   226 
       
   227 // ------------------------------------------------
       
   228 // SetResultMode
       
   229 // ------------------------------------------------
       
   230 //
       
   231 void CMdSFindSequence::SetResultMode( TBool aResultModeItems )
       
   232 	{
       
   233 	iLastResultModeItems = aResultModeItems;
       
   234 	iObserver->SetResultMode( aResultModeItems );
       
   235 	}
       
   236 
       
   237 // ------------------------------------------------
       
   238 // RunL
       
   239 // ------------------------------------------------
       
   240 //
       
   241 void CMdSFindSequence::RunL()
       
   242     {
       
   243     TInt result = 0;
       
   244 
       
   245     switch ( iStatus.Int() )
       
   246         {
       
   247         case EAsyncFind:
       
   248             {
       
   249             iFindOperation = CreateOperationL( *iSerializedCriteria );
       
   250             result = iFindOperation->ExecuteL();
       
   251             break;
       
   252             }
       
   253         case EContinueAsyncFind:
       
   254             {
       
   255             if( iFindOperation )
       
   256             	{
       
   257             	result = iFindOperation->ContinueL();
       
   258             	}
       
   259             else
       
   260             	{
       
   261             	result = KErrNotFound;
       
   262             	}
       
   263             break;
       
   264             }
       
   265         default:
       
   266             {
       
   267 #ifdef _DEBUG
       
   268             User::Panic( _L("MdSFSRun") , KErrCorrupt );
       
   269 #endif            
       
   270             User::Leave( KErrCorrupt );
       
   271             }
       
   272         }
       
   273     if( result == KErrNone || result == KFindSetReady )
       
   274         {
       
   275         iFindResults = iFindOperation->Results();
       
   276 
       
   277         if( iFindResults )
       
   278         	{        	
       
   279         	PostProcessL( *iFindResults );
       
   280         	}
       
   281         }
       
   282 
       
   283     if ( result == KFindSetReady )
       
   284         {
       
   285         CMdSFindEngine* obs = iObserver;
       
   286         if ( obs )
       
   287         	{
       
   288         	obs->SetComplete( KErrNone );
       
   289         	}
       
   290         }
       
   291     else if ( result == KErrCancel )
       
   292         {
       
   293         CleanUp();
       
   294         // do NOT notify observer
       
   295         }
       
   296     else
       
   297         {
       
   298         CMdSFindEngine* obs = iObserver;
       
   299         if ( obs )
       
   300         	{
       
   301         	obs->FindComplete( result );
       
   302         	}
       
   303         }
       
   304     }
       
   305 
       
   306 // ------------------------------------------------
       
   307 // RunError
       
   308 // ------------------------------------------------
       
   309 //
       
   310 TInt CMdSFindSequence::RunError( TInt aError )
       
   311     {
       
   312     // Cleanup if RunL() leaves
       
   313     CMdSFindEngine* obs = iObserver;
       
   314     CleanUp();
       
   315     obs->FindComplete( aError );
       
   316     return KErrNone;
       
   317     }
       
   318 
       
   319 // ------------------------------------------------
       
   320 // DoCancel
       
   321 // ------------------------------------------------
       
   322 //
       
   323 void CMdSFindSequence::DoCancel()
       
   324     {
       
   325     if ( !iFindOperation )
       
   326         {
       
   327         // already finished
       
   328         CleanUp();
       
   329         return;
       
   330         }
       
   331     TInt state = iFindOperation->State();
       
   332     if ( state == CMdSSqlFindOperation::EStateIdle )
       
   333         {
       
   334         // loop is idle - safe to clean up.
       
   335         CleanUp();
       
   336         }
       
   337     else if ( state == CMdSSqlFindOperation::EStateRunning )
       
   338         {
       
   339         // interrupt loop.
       
   340         iFindOperation->Cancel();
       
   341         }
       
   342     else if ( state == CMdSSqlFindOperation::EStateDead )
       
   343         {
       
   344         // loop is already ending.
       
   345         }
       
   346     return;
       
   347     }
       
   348 
       
   349 // ------------------------------------------------
       
   350 // CreateOperationL
       
   351 // ------------------------------------------------
       
   352 //
       
   353 CMdSSqlFindOperation* CMdSFindSequence::CreateOperationL(
       
   354 		CMdCSerializationBuffer& aSerializedCriteria )
       
   355     {
       
   356     CMdSSqlFindOperation* operation = CreateOperationLC( aSerializedCriteria );
       
   357     CleanupStack::Pop( operation );
       
   358     return operation;
       
   359     }
       
   360 
       
   361 // ------------------------------------------------
       
   362 // CreateOperationLC
       
   363 // ------------------------------------------------
       
   364 //
       
   365 CMdSSqlFindOperation* CMdSFindSequence::CreateOperationLC(
       
   366     CMdCSerializationBuffer& aSerializedCriteria )
       
   367     {
       
   368     CMdSSqlFindOperation* operation = CMdSSqlFindOperation::NewLC( *this, iNotifyCount );
       
   369 
       
   370 	CMdSFindSqlClause& findSqlClause = operation->FindCriteria();
       
   371 
       
   372 	if( aSerializedCriteria.Buffer().Ptr() && aSerializedCriteria.Buffer().Length() != 0 )
       
   373 		{		
       
   374    		findSqlClause.CreateL( aSerializedCriteria, iUserLevel );
       
   375 
       
   376 		operation->SetLimit( findSqlClause.Limit() );
       
   377 
       
   378    		__LOGQUERY_16( _L("Execute query:"), operation->FindCriteria().AsTextL(), operation->FindCriteria().Variables() );
       
   379 		}
       
   380 	else
       
   381 		{
       
   382 		User::Leave( KErrBadDescriptor );
       
   383 		}
       
   384 
       
   385     return operation;
       
   386     }
       
   387 
       
   388 struct TObjectHitCount
       
   389 	{
       
   390 	TInt iCount;
       
   391 	TUint32 iObjectOffset;
       
   392 	};
       
   393 
       
   394 static TInt SortValues(const TObjectHitCount& aFirst, const TObjectHitCount& aSecond)
       
   395 	{
       
   396 	TInt result = aSecond.iCount - aFirst.iCount;
       
   397 	if (result == 0)
       
   398 		{
       
   399 		result = aFirst.iObjectOffset - aSecond.iObjectOffset;
       
   400 		}
       
   401 	return result;
       
   402 	}
       
   403 
       
   404 void CMdSFindSequence::GetFreeTextForObjectL( CDesCArray& aResultWordBuffer,
       
   405 		TDefId aNamespaceDefId, TItemId aObjectId )
       
   406 	{
       
   407 	_LIT( KMdSFindSeqWords, "SELECT Word FROM TextSearch%u AS ts, TextSearchDictionary%u AS tsd ON tsd.WordId = ts.WordId WHERE ObjectId = ? ORDER BY Position ASC;" );
       
   408 
       
   409 	CMdsClauseBuffer* buffer = CMdsClauseBuffer::NewLC( KMdSFindSeqWords.iTypeLength + 20 ); // two int
       
   410 	buffer->BufferL().Format( KMdSFindSeqWords, aNamespaceDefId, aNamespaceDefId );
       
   411 	
       
   412 	CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL();
       
   413 	
       
   414 	RRowData data;
       
   415     CleanupClosePushL( data );
       
   416 	data.AppendL( TColumn( aObjectId ) );
       
   417 	RMdsStatement query;
       
   418     CleanupClosePushL( query );
       
   419 	connection.ExecuteQueryL( buffer->ConstBufferL(), query, data );
       
   420 	TPtrC16 word;
       
   421 	data.Column(0).Set( word );
       
   422 	while (connection.NextRowL(query, data))
       
   423 		{
       
   424 		data.Column(0).Get( word );
       
   425 		aResultWordBuffer.AppendL( word );
       
   426 		data.Free();
       
   427 		}
       
   428 
       
   429 	CleanupStack::PopAndDestroy( 3, buffer ); // query, data, buffer
       
   430 	}
       
   431 
       
   432 // ------------------------------------------------
       
   433 // PostProcessL
       
   434 // ------------------------------------------------
       
   435 //
       
   436 void CMdSFindSequence::PostProcessL( CMdCSerializationBuffer& aSerializedResultBuffer )
       
   437     {
       
   438 #ifdef _DEBUG    
       
   439 	_LIT( KFindFunctionName, "CMdSFindSequence::PostProcessL" );
       
   440 #endif
       
   441 
       
   442     // process only on items result
       
   443     if (!iLastResultModeItems)
       
   444     	{
       
   445     	return;
       
   446     	}
       
   447     
       
   448     if(iFindOperation && iFindOperation->FindCriteria().IncludesFreetexts() == EFalse )
       
   449    		{
       
   450     	return;
       
   451     	}
       
   452     
       
   453     if (!iFindOperation)
       
   454         {
       
   455         return;
       
   456         }
       
   457     
       
   458     RPointerArray<HBufC>& searchFreeText = iFindOperation->QueryFreeText();
       
   459     // to through every object and check freetext
       
   460     aSerializedResultBuffer.PositionL( KNoOffset );
       
   461     const TMdCItems& items = TMdCItems::GetFromBufferL( aSerializedResultBuffer );
       
   462     const TBool needToSort = searchFreeText.Count() != 0 
       
   463     		&& items.iObjects.iPtr.iCount > 1;
       
   464 
       
   465     RArray<TObjectHitCount> hitCountArray;
       
   466     CleanupClosePushL( hitCountArray );
       
   467 
       
   468     TObjectHitCount hitCount;
       
   469     for( TUint32 i = 0; i < items.iObjects.iPtr.iCount; ++i )
       
   470     	{
       
   471     	aSerializedResultBuffer.PositionL( items.iObjects.iPtr.iOffset 
       
   472     			+ i * sizeof(TMdCObject) );
       
   473     	const TMdCObject& object = TMdCObject::GetFromBufferL( aSerializedResultBuffer );
       
   474     	// check all objects
       
   475 
       
   476 		// jump to freetext
       
   477 		if ( object.iFreeTexts.iPtr.iCount == 0 )
       
   478 			{
       
   479 			continue;
       
   480 			}
       
   481 
       
   482 		CDesC16ArrayFlat* resultWordBuffer = new(ELeave) CDesC16ArrayFlat( object.iFreeTexts.iPtr.iCount );
       
   483 		CleanupStack::PushL( resultWordBuffer );
       
   484 		// get freetext for object
       
   485 		GetFreeTextForObjectL( *resultWordBuffer, items.iNamespaceDefId, object.iId );
       
   486 		__ASSERT_DEBUG( object.iFreeTexts.iPtr.iCount == resultWordBuffer->Count(), User::Panic( KFindFunctionName, KErrCorrupt) );
       
   487 
       
   488 	    if (needToSort)
       
   489 	    	{
       
   490  		   	hitCount.iObjectOffset = items.iObjects.iPtr.iOffset + i * sizeof(TMdCObject);
       
   491 			hitCount.iCount = GetFreeTextHitCountL( *resultWordBuffer, searchFreeText );
       
   492     		hitCountArray.AppendL( hitCount );
       
   493 	    	}
       
   494 		
       
   495 		aSerializedResultBuffer.PositionL( object.iFreeTexts.iPtr.iOffset );
       
   496 		for ( TUint32 f = 0; f < object.iFreeTexts.iPtr.iCount; ++f )
       
   497 			{
       
   498 			// insert freeText here
       
   499 			TPtrC16 word = (*resultWordBuffer)[f];
       
   500 			aSerializedResultBuffer.InsertL( word );
       
   501 			}
       
   502 		CleanupStack::PopAndDestroy( resultWordBuffer );
       
   503 		}
       
   504 
       
   505     if ( needToSort && hitCountArray.Count() > 1 )
       
   506     	{
       
   507 		hitCountArray.Sort( TLinearOrder<TObjectHitCount>( SortValues ) );
       
   508 
       
   509 		RArray<TMdCObject> objectArray;
       
   510 		CleanupClosePushL( objectArray );
       
   511 		objectArray.Reserve( items.iObjects.iPtr.iCount );
       
   512 		// store objects in array in correct order
       
   513 		for( TInt i = 0; i < items.iObjects.iPtr.iCount; ++i )
       
   514 			{
       
   515 			aSerializedResultBuffer.PositionL( hitCountArray[i].iObjectOffset );
       
   516 			const TMdCObject& object = TMdCObject::GetFromBufferL( aSerializedResultBuffer );
       
   517 			objectArray.AppendL( object );
       
   518 			}
       
   519 		// set them back in serialized buffer
       
   520 		aSerializedResultBuffer.PositionL( items.iObjects.iPtr.iOffset );
       
   521 		for (TInt i = 0; i < items.iObjects.iPtr.iCount; ++i)
       
   522 			{
       
   523 			objectArray[i].SerializeL( aSerializedResultBuffer );
       
   524 			}
       
   525 		CleanupStack::PopAndDestroy( &objectArray );
       
   526     	}
       
   527 
       
   528 	CleanupStack::PopAndDestroy( &hitCountArray );
       
   529     }
       
   530 
       
   531 // ------------------------------------------------
       
   532 // CleanUp
       
   533 // ------------------------------------------------
       
   534 //
       
   535 void CMdSFindSequence::CleanUp()
       
   536     {
       
   537     // clean up rubbish
       
   538 	if( iFindOperation )
       
   539 		{
       
   540 	   	delete iFindOperation;
       
   541 		iFindOperation = NULL;
       
   542 		}
       
   543 
       
   544     iObserver = NULL;
       
   545 
       
   546 	if( iFindResults )
       
   547 		{
       
   548 		delete iFindResults;
       
   549 		iFindResults = NULL;
       
   550 		}
       
   551     }
       
   552 
       
   553 // ------------------------------------------------
       
   554 // IsCleaned
       
   555 // ------------------------------------------------
       
   556 //
       
   557 TBool CMdSFindSequence::IsComplete() const
       
   558 	{
       
   559 	// not failed or query still running
       
   560 	if( //iObserver || 
       
   561 		( iFindOperation && iFindOperation->State() != CMdSSqlFindOperation::EStateDead ) )
       
   562 		{
       
   563 		return EFalse;
       
   564 		}
       
   565 		
       
   566 	return ETrue;
       
   567 	}
       
   568     
       
   569 // ------------------------------------------------
       
   570 // IsComplete
       
   571 // ------------------------------------------------
       
   572 //
       
   573 TBool CMdSFindSequence::IsQueryComplete() const
       
   574 	{
       
   575 	if ( iFindOperation )
       
   576 		{
       
   577 		return ( iFindOperation->State() == CMdSSqlFindOperation::EStateDead );
       
   578 		}
       
   579 	else
       
   580 		{
       
   581 		return ETrue;
       
   582 		}
       
   583 	}
       
   584 
       
   585 const CMdsSchema& CMdSFindSequence::Schema() const
       
   586 	{
       
   587 	return iSchema;
       
   588 	}
       
   589 
       
   590 CMdSServer& CMdSFindSequence::Server() const
       
   591 	{
       
   592 	return iServer;
       
   593 	}
       
   594 
       
   595 // ------------------------------------------------
       
   596 // GetFreeTextHitCountL
       
   597 // ------------------------------------------------
       
   598 //
       
   599 TUint32 CMdSFindSequence::GetFreeTextHitCountL(
       
   600 		const CDesCArray& aObjectFreeText, 
       
   601 		const RPointerArray<HBufC>& aSearchFreeText)
       
   602 	{
       
   603 	TUint32 hitCount = 0;
       
   604 
       
   605 	const TInt objectFreeTextCount = aObjectFreeText.Count();
       
   606 
       
   607 	for(TInt i = 0; i < objectFreeTextCount; ++i)
       
   608 		{
       
   609 		TInt length = aObjectFreeText[i].Length();
       
   610 		const TDesC& objectText = aObjectFreeText[i];
       
   611 		const TInt32 objectTextLength = objectText.Length();
       
   612 		const TInt searchFreeTextCount = aSearchFreeText.Count();
       
   613 
       
   614     	for( TInt j = 0; j < searchFreeTextCount; ++j )
       
   615 	    	{
       
   616 			const TDesC& searchText = *aSearchFreeText[j];
       
   617 			const TInt32 searchTextLength = searchText.Length();
       
   618 
       
   619 			if (searchTextLength > objectTextLength)
       
   620 				{
       
   621 				continue;
       
   622 				}
       
   623 			TInt32 searchStart = 0;
       
   624 			while(objectTextLength - searchStart >= searchTextLength)
       
   625 				{
       
   626 				const TInt retValue = objectText.Mid(searchStart, 
       
   627 						objectTextLength - searchStart).FindF(searchText);
       
   628 
       
   629 				if(retValue != KErrNotFound)
       
   630 					{
       
   631 					searchStart += retValue+searchTextLength;
       
   632 					hitCount++;
       
   633 					}
       
   634 				else
       
   635 					{
       
   636 					break;
       
   637 					}
       
   638 				}
       
   639 	    	}
       
   640     	}
       
   641     return hitCount;
       
   642 	}