metadataengine/server/src/mdsfindsequence.cpp
changeset 0 c53acadfccc6
child 1 acef663c1218
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metadataengine/server/src/mdsfindsequence.cpp	Mon Jan 18 20:34:07 2010 +0200
@@ -0,0 +1,642 @@
+/*
+* Copyright (c) 2005-2009 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:  Manages object search from database*
+*/
+
+#include <badesca.h>
+
+#include "mdsfindsequence.h"
+
+#include "mdcitem.h"
+#include "mdcresult.h"
+#include "mdcserializationbuffer.h"
+#include "mdsschema.h"
+#include "mdslogger.h"
+#include "mdsfindengine.h"
+#include "mdssqlfindoperation.h"
+#include "mdssqliteconnection.h"
+#include "mdsfindsqlclause.h"
+#include "mdsdbconnectionpool.h"
+#include "mdsclausebuffer.h"
+
+
+/** logging instance */
+__USES_LOGGER
+
+
+// ------------------------------------------------
+// NewL
+// ------------------------------------------------
+//
+CMdSFindSequence* CMdSFindSequence::NewL( 
+	CMdSServer& aServer, CMdsSchema& aSchema, CMdSFindEngine& aObserver )
+    {
+    CMdSFindSequence* self = CMdSFindSequence::NewLC( aServer, aSchema, aObserver );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// ------------------------------------------------
+// NewLC
+// ------------------------------------------------
+//
+CMdSFindSequence* CMdSFindSequence::NewLC( 
+	CMdSServer& aServer, CMdsSchema& aSchema, CMdSFindEngine& aObserver )
+    {
+    CMdSFindSequence* self = new(ELeave) CMdSFindSequence( aServer, aSchema, aObserver );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+// ------------------------------------------------
+// Default constructor
+// ------------------------------------------------
+//
+CMdSFindSequence::CMdSFindSequence( 
+	CMdSServer& aServer, CMdsSchema& aSchema, CMdSFindEngine& aObserver )
+    : CActive( CActive::EPriorityStandard )
+    , iServer( aServer )
+    , iSchema( aSchema )
+    , iObserver( &aObserver )
+    , iUserLevel( EUserLevelNone )
+    {
+	iNotifyCount = KMaxTUint32;
+
+    iFindOperation = NULL;
+    }
+
+// ------------------------------------------------
+// ConstructL
+// ------------------------------------------------
+//
+void CMdSFindSequence::ConstructL()
+    {
+    CActiveScheduler::Add( this );
+    __INIT_LOGGER;
+    }
+
+// ------------------------------------------------
+// Destructor
+// ------------------------------------------------
+//
+CMdSFindSequence::~CMdSFindSequence()
+    {
+    CleanUp();
+    
+    Cancel();
+    }
+
+void CMdSFindSequence::SetFindParams( TUint32 aNotifyCount )
+	{
+	iNotifyCount = aNotifyCount;
+	}
+
+// ------------------------------------------------
+// FindL
+// ------------------------------------------------
+//
+TInt CMdSFindSequence::FindL(
+    CMdCSerializationBuffer& aSerializedCriteria,
+    TUserLevel aUserLevel )
+    {
+    __ASSERT_DEBUG( !iFindOperation, MMdCCommon::Panic( KErrCorrupt ) );
+
+	iUserLevel = aUserLevel;
+
+	iSerializedCriteria = &aSerializedCriteria;
+
+	if( iFindResults )
+		{
+		delete iFindResults;
+		iFindResults = NULL;
+		}
+ 
+    iFindOperation = CreateOperationL( aSerializedCriteria );
+
+    TInt result = KErrNone;
+    result = iFindOperation->ExecuteL();
+    
+    iFindResults = iFindOperation->Results();
+    
+    if( iFindResults )
+    	{
+    	PostProcessL( *iFindResults );
+    	}
+
+    return result;
+    }
+
+// ------------------------------------------------
+// ContinueL
+// ------------------------------------------------
+//
+TInt CMdSFindSequence::ContinueL()
+    {
+    __ASSERT_DEBUG( iFindOperation, MMdCCommon::Panic( KErrCorrupt ) );
+
+	if( iFindResults )
+		{
+		delete iFindResults;
+		iFindResults = NULL;
+		}
+    
+    TInt result = iFindOperation->ContinueL();
+
+    if ( result == KErrNone )
+        {
+        iFindResults = iFindOperation->Results();
+
+		if( iFindResults )
+			{
+			PostProcessL( *iFindResults );
+			}
+        }
+
+    return result;
+    }
+
+// ------------------------------------------------
+// FindAsync
+// ------------------------------------------------
+//
+void CMdSFindSequence::FindAsync(CMdCSerializationBuffer& aSerializedCriteria,
+		TUserLevel aUserLevel )
+    {
+    __ASSERT_DEBUG( !iFindOperation, MMdCCommon::Panic( KErrCorrupt ) );
+    
+    iUserLevel = aUserLevel;
+
+	if( iFindResults )
+		{
+		delete iFindResults;
+		iFindResults = NULL;
+		}
+
+    iSerializedCriteria = &aSerializedCriteria;
+
+    SetActive();
+    TRequestStatus* pStatus = &iStatus;
+    User::RequestComplete( pStatus, EAsyncFind );
+    }
+
+// ------------------------------------------------
+// ContinueAsync
+// ------------------------------------------------
+//
+void CMdSFindSequence::ContinueAsync()
+    {
+    __ASSERT_DEBUG( iFindOperation, MMdCCommon::Panic( KErrCorrupt ) );
+
+	if( iFindResults )
+		{
+		delete iFindResults;
+		iFindResults = NULL;
+		}
+
+    SetActive();
+    TRequestStatus* pStatus = &iStatus;
+    User::RequestComplete( pStatus, EContinueAsyncFind );
+    }
+
+// ------------------------------------------------
+// Results
+// ------------------------------------------------
+//
+CMdCSerializationBuffer& CMdSFindSequence::ResultsL() const
+    {
+    if( !iFindResults )
+    	{
+    	User::Leave( KErrCorrupt );
+    	}
+
+    return *iFindResults;
+    }
+
+// ------------------------------------------------
+// SetResultMode
+// ------------------------------------------------
+//
+void CMdSFindSequence::SetResultMode( TBool aResultModeItems )
+	{
+	iLastResultModeItems = aResultModeItems;
+	iObserver->SetResultMode( aResultModeItems );
+	}
+
+// ------------------------------------------------
+// RunL
+// ------------------------------------------------
+//
+void CMdSFindSequence::RunL()
+    {
+    TInt result = 0;
+
+    switch ( iStatus.Int() )
+        {
+        case EAsyncFind:
+            {
+            iFindOperation = CreateOperationL( *iSerializedCriteria );
+            result = iFindOperation->ExecuteL();
+            break;
+            }
+        case EContinueAsyncFind:
+            {
+            if( iFindOperation )
+            	{
+            	result = iFindOperation->ContinueL();
+            	}
+            else
+            	{
+            	result = KErrNotFound;
+            	}
+            break;
+            }
+        default:
+            {
+#ifdef _DEBUG
+            User::Panic( _L("MdSFSRun") , KErrCorrupt );
+#endif            
+            User::Leave( KErrCorrupt );
+            }
+        }
+    if( result == KErrNone || result == KFindSetReady )
+        {
+        iFindResults = iFindOperation->Results();
+
+        if( iFindResults )
+        	{        	
+        	PostProcessL( *iFindResults );
+        	}
+        }
+
+    if ( result == KFindSetReady )
+        {
+        CMdSFindEngine* obs = iObserver;
+        if ( obs )
+        	{
+        	obs->SetComplete( KErrNone );
+        	}
+        }
+    else if ( result == KErrCancel )
+        {
+        CleanUp();
+        // do NOT notify observer
+        }
+    else
+        {
+        CMdSFindEngine* obs = iObserver;
+        if ( obs )
+        	{
+        	obs->FindComplete( result );
+        	}
+        }
+    }
+
+// ------------------------------------------------
+// RunError
+// ------------------------------------------------
+//
+TInt CMdSFindSequence::RunError( TInt aError )
+    {
+    // Cleanup if RunL() leaves
+    CMdSFindEngine* obs = iObserver;
+    CleanUp();
+    obs->FindComplete( aError );
+    return KErrNone;
+    }
+
+// ------------------------------------------------
+// DoCancel
+// ------------------------------------------------
+//
+void CMdSFindSequence::DoCancel()
+    {
+    if ( !iFindOperation )
+        {
+        // already finished
+        CleanUp();
+        return;
+        }
+    TInt state = iFindOperation->State();
+    if ( state == CMdSSqlFindOperation::EStateIdle )
+        {
+        // loop is idle - safe to clean up.
+        CleanUp();
+        }
+    else if ( state == CMdSSqlFindOperation::EStateRunning )
+        {
+        // interrupt loop.
+        iFindOperation->Cancel();
+        }
+    else if ( state == CMdSSqlFindOperation::EStateDead )
+        {
+        // loop is already ending.
+        }
+    return;
+    }
+
+// ------------------------------------------------
+// CreateOperationL
+// ------------------------------------------------
+//
+CMdSSqlFindOperation* CMdSFindSequence::CreateOperationL(
+		CMdCSerializationBuffer& aSerializedCriteria )
+    {
+    CMdSSqlFindOperation* operation = CreateOperationLC( aSerializedCriteria );
+    CleanupStack::Pop( operation );
+    return operation;
+    }
+
+// ------------------------------------------------
+// CreateOperationLC
+// ------------------------------------------------
+//
+CMdSSqlFindOperation* CMdSFindSequence::CreateOperationLC(
+    CMdCSerializationBuffer& aSerializedCriteria )
+    {
+    CMdSSqlFindOperation* operation = CMdSSqlFindOperation::NewLC( *this, iNotifyCount );
+
+	CMdSFindSqlClause& findSqlClause = operation->FindCriteria();
+
+	if( aSerializedCriteria.Buffer().Ptr() && aSerializedCriteria.Buffer().Length() != 0 )
+		{		
+   		findSqlClause.CreateL( aSerializedCriteria, iUserLevel );
+
+		operation->SetLimit( findSqlClause.Limit() );
+
+   		__LOGQUERY_16( _L("Execute query:"), operation->FindCriteria().AsTextL(), operation->FindCriteria().Variables() );
+		}
+	else
+		{
+		User::Leave( KErrBadDescriptor );
+		}
+
+    return operation;
+    }
+
+struct TObjectHitCount
+	{
+	TInt iCount;
+	TUint32 iObjectOffset;
+	};
+
+static TInt SortValues(const TObjectHitCount& aFirst, const TObjectHitCount& aSecond)
+	{
+	TInt result = aSecond.iCount - aFirst.iCount;
+	if (result == 0)
+		{
+		result = aFirst.iObjectOffset - aSecond.iObjectOffset;
+		}
+	return result;
+	}
+
+void CMdSFindSequence::GetFreeTextForObjectL( CDesCArray& aResultWordBuffer,
+		TDefId aNamespaceDefId, TItemId aObjectId )
+	{
+	_LIT( KMdSFindSeqWords, "SELECT Word FROM TextSearch%u AS ts, TextSearchDictionary%u AS tsd ON tsd.WordId = ts.WordId WHERE ObjectId = ? ORDER BY Position ASC;" );
+
+	CMdsClauseBuffer* buffer = CMdsClauseBuffer::NewLC( KMdSFindSeqWords.iTypeLength + 20 ); // two int
+	buffer->BufferL().Format( KMdSFindSeqWords, aNamespaceDefId, aNamespaceDefId );
+	
+	CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL();
+	
+	RRowData data;
+    CleanupClosePushL( data );
+	data.AppendL( TColumn( aObjectId ) );
+	RMdsStatement query;
+    CleanupClosePushL( query );
+	connection.ExecuteQueryL( buffer->ConstBufferL(), query, data );
+	TPtrC16 word;
+	data.Column(0).Set( word );
+	while (connection.NextRowL(query, data))
+		{
+		data.Column(0).Get( word );
+		aResultWordBuffer.AppendL( word );
+		data.Free();
+		}
+
+	CleanupStack::PopAndDestroy( 3, buffer ); // query, data, buffer
+	}
+
+// ------------------------------------------------
+// PostProcessL
+// ------------------------------------------------
+//
+void CMdSFindSequence::PostProcessL( CMdCSerializationBuffer& aSerializedResultBuffer )
+    {
+#ifdef _DEBUG    
+	_LIT( KFindFunctionName, "CMdSFindSequence::PostProcessL" );
+#endif
+
+    // process only on items result
+    if (!iLastResultModeItems)
+    	{
+    	return;
+    	}
+    
+    if(iFindOperation && iFindOperation->FindCriteria().IncludesFreetexts() == EFalse )
+   		{
+    	return;
+    	}
+    
+    if (!iFindOperation)
+        {
+        return;
+        }
+    
+    RPointerArray<HBufC>& searchFreeText = iFindOperation->QueryFreeText();
+    // to through every object and check freetext
+    aSerializedResultBuffer.PositionL( KNoOffset );
+    const TMdCItems& items = TMdCItems::GetFromBufferL( aSerializedResultBuffer );
+    const TBool needToSort = searchFreeText.Count() != 0 
+    		&& items.iObjects.iPtr.iCount > 1;
+
+    RArray<TObjectHitCount> hitCountArray;
+    CleanupClosePushL( hitCountArray );
+
+    TObjectHitCount hitCount;
+    for( TUint32 i = 0; i < items.iObjects.iPtr.iCount; ++i )
+    	{
+    	aSerializedResultBuffer.PositionL( items.iObjects.iPtr.iOffset 
+    			+ i * sizeof(TMdCObject) );
+    	const TMdCObject& object = TMdCObject::GetFromBufferL( aSerializedResultBuffer );
+    	// check all objects
+
+		// jump to freetext
+		if ( object.iFreeTexts.iPtr.iCount == 0 )
+			{
+			continue;
+			}
+
+		CDesC16ArrayFlat* resultWordBuffer = new(ELeave) CDesC16ArrayFlat( object.iFreeTexts.iPtr.iCount );
+		CleanupStack::PushL( resultWordBuffer );
+		// get freetext for object
+		GetFreeTextForObjectL( *resultWordBuffer, items.iNamespaceDefId, object.iId );
+		__ASSERT_DEBUG( object.iFreeTexts.iPtr.iCount == resultWordBuffer->Count(), User::Panic( KFindFunctionName, KErrCorrupt) );
+
+	    if (needToSort)
+	    	{
+ 		   	hitCount.iObjectOffset = items.iObjects.iPtr.iOffset + i * sizeof(TMdCObject);
+			hitCount.iCount = GetFreeTextHitCountL( *resultWordBuffer, searchFreeText );
+    		hitCountArray.AppendL( hitCount );
+	    	}
+		
+		aSerializedResultBuffer.PositionL( object.iFreeTexts.iPtr.iOffset );
+		for ( TUint32 f = 0; f < object.iFreeTexts.iPtr.iCount; ++f )
+			{
+			// insert freeText here
+			TPtrC16 word = (*resultWordBuffer)[f];
+			aSerializedResultBuffer.InsertL( word );
+			}
+		CleanupStack::PopAndDestroy( resultWordBuffer );
+		}
+
+    if ( needToSort && hitCountArray.Count() > 1 )
+    	{
+		hitCountArray.Sort( TLinearOrder<TObjectHitCount>( SortValues ) );
+
+		RArray<TMdCObject> objectArray;
+		CleanupClosePushL( objectArray );
+		objectArray.Reserve( items.iObjects.iPtr.iCount );
+		// store objects in array in correct order
+		for( TInt i = 0; i < items.iObjects.iPtr.iCount; ++i )
+			{
+			aSerializedResultBuffer.PositionL( hitCountArray[i].iObjectOffset );
+			const TMdCObject& object = TMdCObject::GetFromBufferL( aSerializedResultBuffer );
+			objectArray.AppendL( object );
+			}
+		// set them back in serialized buffer
+		aSerializedResultBuffer.PositionL( items.iObjects.iPtr.iOffset );
+		for (TInt i = 0; i < items.iObjects.iPtr.iCount; ++i)
+			{
+			objectArray[i].SerializeL( aSerializedResultBuffer );
+			}
+		CleanupStack::PopAndDestroy( &objectArray );
+    	}
+
+	CleanupStack::PopAndDestroy( &hitCountArray );
+    }
+
+// ------------------------------------------------
+// CleanUp
+// ------------------------------------------------
+//
+void CMdSFindSequence::CleanUp()
+    {
+    // clean up rubbish
+	if( iFindOperation )
+		{
+	   	delete iFindOperation;
+		iFindOperation = NULL;
+		}
+
+    iObserver = NULL;
+
+	if( iFindResults )
+		{
+		delete iFindResults;
+		iFindResults = NULL;
+		}
+    }
+
+// ------------------------------------------------
+// IsCleaned
+// ------------------------------------------------
+//
+TBool CMdSFindSequence::IsComplete() const
+	{
+	// not failed or query still running
+	if( //iObserver || 
+		( iFindOperation && iFindOperation->State() != CMdSSqlFindOperation::EStateDead ) )
+		{
+		return EFalse;
+		}
+		
+	return ETrue;
+	}
+    
+// ------------------------------------------------
+// IsComplete
+// ------------------------------------------------
+//
+TBool CMdSFindSequence::IsQueryComplete() const
+	{
+	if ( iFindOperation )
+		{
+		return ( iFindOperation->State() == CMdSSqlFindOperation::EStateDead );
+		}
+	else
+		{
+		return ETrue;
+		}
+	}
+
+const CMdsSchema& CMdSFindSequence::Schema() const
+	{
+	return iSchema;
+	}
+
+CMdSServer& CMdSFindSequence::Server() const
+	{
+	return iServer;
+	}
+
+// ------------------------------------------------
+// GetFreeTextHitCountL
+// ------------------------------------------------
+//
+TUint32 CMdSFindSequence::GetFreeTextHitCountL(
+		const CDesCArray& aObjectFreeText, 
+		const RPointerArray<HBufC>& aSearchFreeText)
+	{
+	TUint32 hitCount = 0;
+
+	const TInt objectFreeTextCount = aObjectFreeText.Count();
+
+	for(TInt i = 0; i < objectFreeTextCount; ++i)
+		{
+		TInt length = aObjectFreeText[i].Length();
+		const TDesC& objectText = aObjectFreeText[i];
+		const TInt32 objectTextLength = objectText.Length();
+		const TInt searchFreeTextCount = aSearchFreeText.Count();
+
+    	for( TInt j = 0; j < searchFreeTextCount; ++j )
+	    	{
+			const TDesC& searchText = *aSearchFreeText[j];
+			const TInt32 searchTextLength = searchText.Length();
+
+			if (searchTextLength > objectTextLength)
+				{
+				continue;
+				}
+			TInt32 searchStart = 0;
+			while(objectTextLength - searchStart >= searchTextLength)
+				{
+				const TInt retValue = objectText.Mid(searchStart, 
+						objectTextLength - searchStart).FindF(searchText);
+
+				if(retValue != KErrNotFound)
+					{
+					searchStart += retValue+searchTextLength;
+					hitCount++;
+					}
+				else
+					{
+					break;
+					}
+				}
+	    	}
+    	}
+    return hitCount;
+	}