predictivesearch/PcsServerClientAPI/src/CPsRequestHandler.cpp
changeset 0 e686773b3f54
child 7 b3431bff8c19
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/predictivesearch/PcsServerClientAPI/src/CPsRequestHandler.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,1287 @@
+/*
+* Copyright (c) 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:  This is the client side interface for the predictive search
+*                server.
+*
+*/
+
+// SYSTEM INCLUDES
+#include <MPsResultsObserver.h>
+#include <CPsRequestHandler.h>
+#include <RPsSession.h>
+
+// USER INCLUDE
+#include "CPsPropertyHandler.h"
+#include "CPcsDebug.h"
+#include "CPsPattern.h"
+
+// ========================= MEMBER FUNCTIONS ==================================
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::NewL()
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+EXPORT_C CPSRequestHandler* CPSRequestHandler::NewL()
+    {
+    PRINT ( _L("Enter CPSRequestHandler::NewL") );
+
+    CPSRequestHandler* self = NewLC();
+    CleanupStack::Pop(self);
+
+    PRINT ( _L("End CPSRequestHandler::NewL") );
+
+    return (self);
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::NewLC()
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+EXPORT_C CPSRequestHandler* CPSRequestHandler::NewLC()
+    {
+    PRINT ( _L("Enter CPSRequestHandler::NewLC") );
+
+    CPSRequestHandler* self = new (ELeave) CPSRequestHandler();
+    CleanupStack::PushL(self);
+    self->ConstructL();
+
+    PRINT ( _L("End CPSRequestHandler::NewLC") );
+
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::ConstructL()
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+void CPSRequestHandler::ConstructL()
+    {
+    PRINT ( _L("Enter CPSRequestHandler::ConstructL") );
+
+    User::LeaveIfError(iSession.Connect());
+
+    // Initiate the property handler
+    iPropertyHandler = CPsPropertyHandler::NewL(this);
+
+    // Initialize the contact id converter
+    iConverter = NULL;
+
+    PRINT ( _L("End CPSRequestHandler::ConstructL") );
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::CCSAsyncRequestHandler()
+// C++ default constructor can NOT contain any code, that might leave.
+// -----------------------------------------------------------------------------
+CPSRequestHandler::CPSRequestHandler() :
+    CActive(EPriorityStandard)
+    {
+    PRINT ( _L("Enter CPSRequestHandler::CPSRequestHandler") );
+
+    CActiveScheduler::Add(this);
+
+    PRINT ( _L("End CPSRequestHandler::CPSRequestHandler") );
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::~CPSRequestHandler()
+// Destructor.
+// -----------------------------------------------------------------------------
+CPSRequestHandler::~CPSRequestHandler()
+    {
+    PRINT ( _L("Enter CPSRequestHandler::~CPSRequestHandler") );
+
+    Cancel(); // Causes call to DoCancel()
+
+    // Close the session
+    iSession.Close();
+
+    // Cleanup
+    if (iSearchQueryBuffer)
+        {
+        delete iSearchQueryBuffer;
+        }
+
+    if (iPendingSearchQueryBuffer)
+        {
+        delete iPendingSearchQueryBuffer;
+        }
+
+    if (iSearchDataBuffer)
+        {
+        delete iSearchDataBuffer;
+        }
+
+    if (iSearchResultsBuffer)
+        {
+        delete iSearchResultsBuffer;
+        iSearchResultsBuffer = NULL;
+        }
+
+    if (iPropertyHandler)
+        {
+        delete iPropertyHandler;
+        iPropertyHandler = NULL;
+        }
+
+    if (iConverter)
+        {
+        delete iConverter;
+        iConverter = NULL;
+        }
+
+    iObservers.Reset();
+    iObservers.Close();
+
+    PRINT ( _L("End CPSRequestHandler::~CPSRequestHandler") );
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::AddObserverL()
+// 
+// -----------------------------------------------------------------------------
+EXPORT_C void CPSRequestHandler::AddObserverL(MPsResultsObserver* aObserver)
+    {
+    iObservers.InsertInAddressOrderL(aObserver);
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::RemoveObserver()
+// 
+// -----------------------------------------------------------------------------
+EXPORT_C TInt CPSRequestHandler::RemoveObserver(MPsResultsObserver* aObserver)
+    {
+    TInt index = iObservers.FindInAddressOrder(aObserver);
+    if (index != KErrNotFound)
+        {
+        iObservers.Remove(index);
+        return KErrNone;
+        }
+    else
+        {
+        return KErrNotFound;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::SetSearchSettingsL()
+// Send the search settings to the predictive search engine
+// -----------------------------------------------------------------------------
+EXPORT_C void CPSRequestHandler::SetSearchSettingsL(const CPsSettings& aSettings)
+    {
+    PRINT ( _L("Enter CPSRequestHandler::SetSearchSettingsL") );
+
+    // Tmp buffer        
+    CBufFlat *buf = CBufFlat::NewL(KBufferMaxLen);
+    CleanupStack::PushL(buf);
+
+    // Stream over the temp buffer
+    RBufWriteStream stream(*buf);
+    stream.PushL();
+
+    // Write the search query to the stream
+    aSettings.ExternalizeL(stream);
+    stream.CommitL();
+
+    // Create a HBufC8 for IPC
+    HBufC8* settingsBuffer = HBufC8::NewLC(buf->Size());
+    TPtr8 ptr(settingsBuffer->Des());
+    buf->Read(0, ptr, buf->Size());
+
+    // Send the settings to the server
+    iSession.SetSearchSettingsL(settingsBuffer->Des());
+
+    CleanupStack::PopAndDestroy(3, buf); // buf, stream, settingsBuffer	                 
+
+    PRINT ( _L("End CPSRequestHandler::SetSearchSettingsL") );
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::SearchL()
+// Sends a request to the predictive search engine to perform a search.
+// -----------------------------------------------------------------------------
+EXPORT_C void CPSRequestHandler::SearchL(const CPsQuery& aSearchQuery)
+    {
+    // __LATENCY_MARK ( _L("CPSRequestHandler::SearchL  <--- INITIATE SEARCH") );
+    PRINT ( _L("Enter CPSRequestHandler::SearchL") );
+
+    // ----------------------- Search Query ----------------------
+    iSearchRequestCancelled = EFalse;
+    
+    // Tmp buffer        
+    CBufFlat *buf = CBufFlat::NewL(KBufferMaxLen);
+    CleanupStack::PushL(buf);
+
+    // Stream over the temp buffer
+    RBufWriteStream stream(*buf);
+    stream.PushL();
+
+    // Write the search query to the stream
+    aSearchQuery.ExternalizeL(stream);
+    stream.CommitL();
+
+    // If there is no submitted request, then submits the new coming search request     
+    if (!IsActive())
+        {
+        // Create a HBufC8 for IPC
+        if (iSearchQueryBuffer)
+            {
+            delete iSearchQueryBuffer;
+            iSearchQueryBuffer = NULL;
+            }
+        iSearchQueryBuffer = HBufC8::NewLC(buf->Size());
+        CleanupStack::Pop(); // iSearchQueryBuffer
+        TPtr8 ptr(iSearchQueryBuffer->Des());
+        buf->Read(0, ptr, buf->Size());
+
+        // Clear pending search query buffer
+        if (iPendingSearchQueryBuffer)
+            {
+            delete iPendingSearchQueryBuffer;
+            iPendingSearchQueryBuffer = NULL;
+            }
+
+        // ------------------------- Results Buffer ---------------------
+
+        // Create a buffer to store the search results.    
+        if (iSearchResultsBuffer)
+            {
+            delete iSearchResultsBuffer;
+            iSearchResultsBuffer = NULL;
+            }
+        iSearchResultsBuffer = HBufC8::NewL(KSearchResultsBufferLen);
+
+        // --------------------------------------------------------------      
+
+        // Initiate the search
+        iSession.SearchL(iSearchQueryBuffer->Des(), iSearchResultsBuffer->Des(), iStatus);
+        SetActive();
+        }
+    else // else holds it in iPendingSearchQueryBuffer( which will be submitted in HandleSearchResults() )
+        {
+        CancelSearch();
+        iPendingSearchQueryBuffer = HBufC8::NewLC(buf->Size());
+        CleanupStack::Pop();
+        TPtr8 ptr(iPendingSearchQueryBuffer->Des());
+        buf->Read(0, ptr, buf->Size());
+        }
+
+    CleanupStack::PopAndDestroy(2, buf); // buf, stream   
+
+    PRINT ( _L("End CPSRequestHandler::SearchL") );
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::LookupL()
+// Sends a request to the predictive search engine to perform a search.
+// -----------------------------------------------------------------------------
+EXPORT_C void CPSRequestHandler::LookupL(const CPsQuery& aSearchQuery, 
+                                         const TDesC& aSearchData,
+                                         CDesCArray& aMatchSet, 
+                                         RArray<TPsMatchLocation>& aMatchLocation)
+    {
+    PRINT ( _L("Enter CPSRequestHandler::LookupL") );
+
+    // ----------------------- Search Query ----------------------
+
+    // Tmp buffer        
+    CBufFlat *buf = CBufFlat::NewL(KBufferMaxLen);
+    CleanupStack::PushL(buf);
+
+    // Stream over the temp buffer
+    RBufWriteStream stream(*buf);
+    stream.PushL();
+
+    // Write the search query to the stream
+    aSearchQuery.ExternalizeL(stream);
+    stream.CommitL();
+
+    // Create a HBufC8 for IPC
+    HBufC8* searchQueryBuffer = HBufC8::NewL(buf->Size());
+    TPtr8 ptr(searchQueryBuffer->Des());
+    buf->Read(0, ptr, buf->Size());
+    
+    CleanupStack::PopAndDestroy(2, buf); // buf, stream
+    CleanupStack::PushL(searchQueryBuffer);
+
+    // ----------------------- Search Data ----------------------
+
+    // Tmp buffer        
+    CBufFlat* dataBuf = CBufFlat::NewL(KBufferMaxLen);
+    CleanupStack::PushL(dataBuf);
+
+    // Stream over the temp buffer
+    RBufWriteStream dataStream(*dataBuf);
+    dataStream.PushL();
+
+    // Write the search data to the stream
+    dataStream.WriteUint16L(aSearchData.Size());
+    dataStream << aSearchData;
+
+    // Create a HBufC8 for IPC
+    HBufC8* searchDataBuffer = HBufC8::NewL(dataBuf->Size());
+    TPtr8 dataPtr(searchDataBuffer->Des());
+    dataBuf->Read(0, dataPtr, dataBuf->Size());
+
+    CleanupStack::PopAndDestroy(2, dataBuf); // dataBuf, dataStream
+    CleanupStack::PushL(searchDataBuffer);
+    
+    // ------------------------- Results Buffer ---------------------
+
+    // Create a buffer to store the search results.    
+    HBufC8* searchResultsBuffer = HBufC8::NewLC(KBufferMaxLen);
+
+    // --------------------------------------------------------------      
+
+    // Initiate the search
+    iSession.SearchL(searchQueryBuffer->Des(), searchDataBuffer->Des(),
+                     searchResultsBuffer->Des());
+
+    // Parse the results
+    RDesReadStream resultStream(searchResultsBuffer->Des());
+    resultStream.PushL();
+
+    // Number of results
+    TInt seqCount = resultStream.ReadUint16L();
+
+    PRINT1 ( _L("CPSRequestHandler::LookupL: Number of search seqs received = %d"), seqCount );
+
+    // Internalize each char seq
+    for (int i = 0; i < seqCount; i++)
+        {
+        // Size of sequence
+        TInt szSeq = resultStream.ReadUint16L();
+
+        // Character sequence
+        HBufC* seq = HBufC::NewLC(resultStream, szSeq);
+
+        aMatchSet.AppendL(seq->Des());
+
+        CleanupStack::PopAndDestroy();
+        }
+
+    // --------- match sequence location ------------------    
+    // number of results
+    TInt count = resultStream.ReadUint16L();
+
+    // read each data struct
+    for (TInt k = 0; k < count; k++)
+        {
+        TPsMatchLocation matchLoc;
+
+        matchLoc.index = resultStream.ReadUint16L();
+        matchLoc.length = resultStream.ReadUint16L();
+        matchLoc.direction  = (TBidiText::TDirectionality) (resultStream.ReadUint16L());
+
+        aMatchLocation.Append(matchLoc);
+        }
+
+    //cleanup
+    CleanupStack::PopAndDestroy(4, searchQueryBuffer); 
+    // resultStream, searchResultsBuffer, searchDataBuffer, searchQueryBuffer
+	
+    PRINT1        ( _L("CPSRequestHandler::LookupL: Search Data: %S"), &aSearchData );
+    PRINTMATCHSET ( _L("CPSRequestHandler::LookupL: "), aMatchSet );
+    PRINTMATCHLOC ( _L("CPSRequestHandler::LookupL: "), aMatchLocation );
+    PRINT ( _L("End CPSRequestHandler::LookupL") );
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::LookupMatchL()
+// Sends a request to the predictive search engine to perform a search.
+// -----------------------------------------------------------------------------
+EXPORT_C void CPSRequestHandler::LookupMatchL(const CPsQuery& aSearchQuery, 
+                                         const TDesC& aSearchData,
+                                         TDes& aMatch )
+    {
+    PRINT ( _L("Enter CPSRequestHandler::LookupMatchL") );
+
+    // ----------------------- Search Query ----------------------
+
+    // Tmp buffer        
+    CBufFlat *buf = CBufFlat::NewL(KBufferMaxLen);
+    CleanupStack::PushL(buf);
+
+    // Stream over the temp buffer
+    RBufWriteStream stream(*buf);
+    stream.PushL();
+
+    // Write the search query to the stream
+    aSearchQuery.ExternalizeL(stream);
+    stream.CommitL();
+
+    // Create a HBufC8 for IPC
+    HBufC8* searchQueryBuffer = HBufC8::NewL(buf->Size());
+    TPtr8 ptr(searchQueryBuffer->Des());
+    buf->Read(0, ptr, buf->Size());
+    
+    CleanupStack::PopAndDestroy(2, buf); // buf, stream
+    CleanupStack::PushL(searchQueryBuffer);
+
+    // ----------------------- Search Data ----------------------
+
+    // Tmp buffer        
+    CBufFlat* dataBuf = CBufFlat::NewL(KBufferMaxLen);
+    CleanupStack::PushL(dataBuf);
+
+    // Stream over the temp buffer
+    RBufWriteStream dataStream(*dataBuf);
+    dataStream.PushL();
+
+    // Write the search data to the stream
+    dataStream.WriteUint16L(aSearchData.Size());
+    dataStream << aSearchData;
+
+    // Create a HBufC8 for IPC
+    HBufC8* searchDataBuffer = HBufC8::NewL(dataBuf->Size());
+    TPtr8 dataPtr(searchDataBuffer->Des());
+    dataBuf->Read(0, dataPtr, dataBuf->Size());
+
+    CleanupStack::PopAndDestroy(2, dataBuf); // dataBuf, dataStream
+    CleanupStack::PushL(searchDataBuffer);      
+
+    // Initiate the search
+    iSession.SearchMatchStringL( 
+            searchQueryBuffer->Des(), searchDataBuffer->Des(), aMatch );
+
+    //cleanup
+    CleanupStack::PopAndDestroy(searchDataBuffer);
+    CleanupStack::PopAndDestroy(searchQueryBuffer); 
+    
+    PRINT1 ( _L("CPSRequestHandler::LookupMatchL: Search Data: %S"), &aSearchData );
+    PRINT1 ( _L("CPSRequestHandler::LookupMatchL: Result Match: %S"), &aMatch );
+    PRINT  ( _L("End CPSRequestHandler::LookupMatchL") );
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::SearchL()
+// Sends a request to the predictive search engine to perform a search.
+// -----------------------------------------------------------------------------
+EXPORT_C void CPSRequestHandler::SearchL(const CPsQuery& aSearchQuery,
+                                         RPointerArray<CPsClientData>& aMarkedContacts,
+                                         CVPbkContactManager* aContactManager)
+    {
+    PRINT ( _L("Enter CPSRequestHandler::SearchL") );
+
+    // Fire the normal search with the input search query
+    SearchL(aSearchQuery);
+
+    // Clear the bookmarked contacts if any
+    iMarkedContacts.Reset();
+
+    // Copy the contact manager
+    iBookMarkContactManager = aContactManager;
+
+    // Copy the bookmarked contacts
+    for (TInt i = 0; i < aMarkedContacts.Count(); i++)
+        {
+        iMarkedContacts.Append(aMarkedContacts[i]);
+        }
+
+    PRINT ( _L("End CPSRequestHandler::SearchL") );
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::CancelSearch()
+// Cancels ongoing search.
+// -----------------------------------------------------------------------------
+EXPORT_C void CPSRequestHandler::CancelSearch()
+    {
+    if( IsActive() )
+        {
+        iSearchRequestCancelled = ETrue;
+        }
+    
+    if( iPendingSearchQueryBuffer )
+        {
+        delete iPendingSearchQueryBuffer;
+        iPendingSearchQueryBuffer = NULL;
+        }
+    
+    iSession.CancelSearch();
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::HandleSearchResultsL()
+// Search is complete. Parse and send the results to the client.
+// -----------------------------------------------------------------------------
+void CPSRequestHandler::HandleSearchResultsL()
+    {
+    PRINT ( _L("Enter CPSRequestHandler::HandleSearchResultsL") );
+
+    // No pending search query, process the search result
+    RPointerArray<CPsClientData> searchResults;
+    RPointerArray<CPsPattern> searchSeqs;
+
+    if( !iSearchResultsBuffer )
+        {
+        return;
+        }
+    RDesReadStream stream(iSearchResultsBuffer->Des());
+    stream.PushL();
+
+    // Number of results
+    TInt count = stream.ReadInt32L();
+
+    PRINT1 ( _L("CPSRequestHandler::HandleSearchResultsL: Number of search results received = %d"), count );
+
+    // Internalize each data element
+    for (int i = 0; i < count; i++)
+        {
+        CPsClientData* data = CPsClientData::NewL();
+        CleanupStack::PushL(data);
+
+        data->InternalizeL(stream);
+
+        CleanupStack::Pop(data);
+        searchResults.Append(data);
+        }
+
+    // Check if book marked contacts are there
+    TInt nBookmark = 0;
+    if (iMarkedContacts.Count() != 0)
+        {
+        nBookmark = AddMarkedContactsL(searchResults);
+        }
+    
+#ifdef _DEBUG
+    for ( TInt i = 0; i < searchResults.Count(); i++ )
+        {
+        for ( TInt j = 0; j < searchResults[i]->DataElementCount(); j++ )
+            {
+            if ( searchResults[i]->Data(j) )
+                {
+                PRINT3 ( _L("CPSRequestHandler::HandleSearchResultsL: Results[%d,%d] = %S"),
+                         i, j, &searchResults[i]->Data(j)->Des() );
+                }       
+            }
+        }    
+#endif // _DEBUG
+
+    // Read number of character sequences
+    TInt seqCount = stream.ReadInt32L();
+
+    PRINT1 ( _L("CPSRequestHandler::HandleSearchResultsL: Number of match sequences received = %d"), seqCount );
+
+    // Internalize each char seq
+    for (int i = 0; i < seqCount; i++)
+        {
+        CPsPattern* pattern = CPsPattern::NewL();
+        CleanupStack::PushL(pattern);
+
+        pattern->InternalizeL(stream);
+
+        CleanupStack::Pop();
+        if (pattern->FirstIndex() >= 0) // -1 means that is a Alphabetical sort
+            {
+            pattern->SetFirstIndex(pattern->FirstIndex() + nBookmark);
+            }
+        searchSeqs.Append(pattern);
+        }
+
+    CleanupStack::PopAndDestroy(); // stream
+
+    // Pass the results to the observer
+    for (int i = 0; i < iObservers.Count(); i++)
+        {
+        iObservers[i]->HandlePsResultsUpdate(searchResults, searchSeqs);
+        }
+
+    // Clear all the internal buffers
+    if (iSearchQueryBuffer)
+        {
+        delete iSearchQueryBuffer;
+        iSearchQueryBuffer = NULL;
+        }
+
+    if (searchResults.Count())
+        {
+        searchResults.ResetAndDestroy();
+        }
+
+    if (searchSeqs.Count())
+        {
+        searchSeqs.ResetAndDestroy();
+        }
+
+    if (iSearchResultsBuffer)
+        {
+        delete iSearchResultsBuffer;
+        iSearchResultsBuffer = NULL;
+        }
+
+    PRINT ( _L("End CPSRequestHandler::HandleSearchResultsL") );
+
+    // __LATENCY_MARKEND ( _L("CPSRequestHandler::HandleSearchResultsL  <--- SEARCH COMPLETE") );
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::RunSearchFromBufferL()
+// Runs search if search query buffer ( iPendingSearchQueryBuffer ) is not empty
+// -----------------------------------------------------------------------------
+void CPSRequestHandler::RunSearchFromBufferL()
+    {
+    PRINT ( _L("Enter CPSRequestHandler::RunSearchFromBufferL") );
+
+    if( iPendingSearchQueryBuffer )
+        {
+        if (iSearchQueryBuffer)
+            {
+            delete iSearchQueryBuffer;
+            iSearchQueryBuffer = NULL;
+            }
+        iSearchQueryBuffer = HBufC8::NewLC(iPendingSearchQueryBuffer->Size());
+        CleanupStack::Pop();
+        iSearchQueryBuffer->Des().Copy(iPendingSearchQueryBuffer->Des());
+
+        delete iPendingSearchQueryBuffer;
+        iPendingSearchQueryBuffer = NULL;
+
+        // ------------------------- Results Buffer ---------------------
+
+        // Create a buffer to store the search results.    
+        if (iSearchResultsBuffer)
+            {
+            delete iSearchResultsBuffer;
+            iSearchResultsBuffer = NULL;
+            }
+        iSearchResultsBuffer = HBufC8::NewL(KSearchResultsBufferLen);
+
+        // --------------------------------------------------------------      
+
+        // Initiate the search
+        iSession.SearchL(iSearchQueryBuffer->Des(), iSearchResultsBuffer->Des(), iStatus);
+
+        SetActive();
+        }
+   
+    
+    PRINT ( _L("End CPSRequestHandler::RunSearchFromBufferL") );
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::AddBookMarkedContacts()
+// Adds the necessary bookmark contacts to the search result set
+// -----------------------------------------------------------------------------
+TInt CPSRequestHandler::AddMarkedContactsL(RPointerArray<CPsClientData>& searchResults)
+    {
+    __LATENCY_MARK ( _L(" CPSRequestHandler::AddMarkedContactsL") );
+    PRINT ( _L("Enter CPSRequestHandler::AddMarkedContactsL") );
+
+    RPointerArray<CPsClientData> filteredBookMarkList; // Local array to store the filtered bookmark contacts
+    TInt nBookmark = 0;
+
+    for (TInt i = 0; i < iMarkedContacts.Count(); i++)
+        {
+        MVPbkContactLink* bookMarkLink = NULL;
+
+        // See if this contact is already in the result set
+        TInt id = iMarkedContacts[i]->Id();
+
+        TInt j = 0;
+        for (; j < searchResults.Count(); j++)
+            {
+            if (id > 0)
+                {
+                if (id == searchResults[j]->Id())
+                    {
+                    searchResults[j]->SetMark(); // Set the bookmark
+                    break; // Found, go to the next bookmark contact
+                    }
+                else
+                    {
+                    continue;
+                    }
+                }
+            else
+                {
+                if (searchResults[j]->Id() > 0)
+                    {
+                    continue;
+                    }
+                else
+                    {
+                    if (!bookMarkLink)
+                        {
+                        bookMarkLink = ConvertToVpbkLinkLC(*(iMarkedContacts[i]),
+                                                           *iBookMarkContactManager);
+                        CleanupStack::Pop(); //  bookMarkLink  
+                        }
+
+                    MVPbkContactLink* searchContactLink = ConvertToVpbkLinkLC(*(searchResults[j]),
+                                                                              *iBookMarkContactManager);
+                    CleanupStack::Pop(); // searchContactLink
+
+                    if (bookMarkLink->IsSame(*searchContactLink))
+                        {
+                        searchResults[j]->SetMark(); // Set the bookmark
+                        break; // Found, go to the next bookmark contact
+                        }
+                    else
+                        continue;
+                    }
+                }
+            }
+        if (j == searchResults.Count()) // Not found in the result set, Add it
+            {
+            filteredBookMarkList.Append(iMarkedContacts[i]);
+            }
+        }
+
+    // Create the new CPsClientData objects for each filtered results 
+    // and prepend them to the actual result set
+    // in reverse order so that they will be in sorted order among themselves
+
+    nBookmark = filteredBookMarkList.Count();
+    for (TInt i = filteredBookMarkList.Count() - 1; i >= 0; i--)
+        {
+        CPsClientData* temp = CPsClientData::NewL();
+        temp->SetId(filteredBookMarkList[i]->Id());
+        temp->SetUriL(filteredBookMarkList[i]->Uri()->Des());
+
+        // Add the data fields
+        for (TInt j = 0; j < filteredBookMarkList[i]->DataElementCount(); j++)
+            {
+            temp->SetDataL(j, filteredBookMarkList[i]->Data(j)->Des());
+            }
+
+        temp->SetDataExtensionL(filteredBookMarkList[i]->DataExtension());
+        temp->SetMark(); // Set the bookmark
+
+        searchResults.Insert(temp, 0);
+        }
+
+    // Free the bookmark arrays
+    iMarkedContacts.Reset();
+    filteredBookMarkList.Reset();
+
+    PRINT ( _L("END CPSRequestHandler::AddMarkedContactsL") );
+    __LATENCY_MARKEND ( _L(" CPSRequestHandler::AddMarkedContactsL") );
+    return nBookmark;
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::HandleBufferOverFlowL()
+// Handle the buffer overflow error
+// -----------------------------------------------------------------------------
+void CPSRequestHandler::HandleBufferOverFlowL()
+    {
+    PRINT ( _L("Enter CPSRequestHandler::HandleBufferOverFlowL") );
+
+    // New buffer size is now stored in results buffer
+    RDesReadStream stream(iSearchResultsBuffer->Des());
+    stream.PushL();
+
+    // Read the buffer size and create a new buffer
+    TInt bufferSize = stream.ReadInt32L();
+
+    CleanupStack::PopAndDestroy(); // stream
+
+    // Delete and recreate the results buffer
+    if (iSearchResultsBuffer)
+        {
+        delete iSearchResultsBuffer;
+        iSearchResultsBuffer = NULL;
+        }
+
+    // Buffer created for the new size
+    iSearchResultsBuffer = HBufC8::NewL(bufferSize);
+
+    // Recover the search results 
+    iSession.SendNewBufferL(iSearchResultsBuffer->Des(), iStatus);
+
+    SetActive();
+
+    PRINT ( _L("End CPSRequestHandler::HandleBufferOverFlowL") );
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::RunL()
+// Invoked to handle responses from the server.
+// -----------------------------------------------------------------------------
+void CPSRequestHandler::RunL()
+    {
+    switch (iStatus.Int())
+        {
+        case ESearchComplete:
+            // The server has completed the request, signalled the client
+            // thread and the clients active scheduler runs the active object.
+            // Now send the search results over the observer interface.
+            // If request was canceled we will do search from buffer.
+            if( iSearchRequestCancelled )
+                {
+                RunSearchFromBufferL();
+                }
+            else
+                {
+                HandleSearchResultsL();
+                }
+            break;
+        
+        case KErrOverflow:
+            // Internal buffer used for IPC is in-adequate as the match results
+            // are more. Send a new buffer to recover the results.
+            // If request was canceled we will do search from buffer.
+            if( iSearchRequestCancelled )
+                {
+                RunSearchFromBufferL();
+                }
+            else
+                {
+                HandleBufferOverFlowL();
+                }
+            break;
+        
+        case ECancelComplete:
+        case KErrCancel:
+            // The search request was canceled
+            if( iPendingSearchQueryBuffer )
+                {
+                RunSearchFromBufferL();
+                }
+            break;
+
+        default:
+            // Errors
+            HandleErrorL(iStatus.Int());
+        }
+    iSearchRequestCancelled = EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::HandleErrorL()
+// Send the error code to the client.
+// -----------------------------------------------------------------------------
+void CPSRequestHandler::HandleErrorL(TInt aErrorCode)
+    {
+    for (int i = 0; i < iObservers.Count(); i++)
+        {
+        iObservers[i]->HandlePsError(aErrorCode);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::DoCancel()
+// Cancels any outstanding operation.
+// -----------------------------------------------------------------------------
+void CPSRequestHandler::DoCancel()
+    {
+    iSession.CancelSearch();
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::Version()
+// Recovers the predictive search server version.
+// -----------------------------------------------------------------------------
+EXPORT_C TVersion CPSRequestHandler::Version() const
+    {
+    return (iSession.Version());
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::ShutdownServerL()
+// Shuts down the predictive search engine.
+// -----------------------------------------------------------------------------
+EXPORT_C void CPSRequestHandler::ShutdownServerL()
+    {
+    return (iSession.ShutdownServerL());
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::IsLanguageSupportedL()
+// Checks if the language variant is supported by 
+// the predictive search engine.
+// -----------------------------------------------------------------------------
+EXPORT_C TBool CPSRequestHandler::IsLanguageSupportedL(const TLanguage aLanguage)
+    {
+    PRINT ( _L("Enter CPSRequestHandler::IsLanguageSupportedL") );
+
+    // ----------------------- language id----------------------
+
+    // Tmp buffer        
+    CBufFlat* dataBuf = CBufFlat::NewL(KBufferMaxLen);
+    CleanupStack::PushL(dataBuf);
+
+    // Stream over the temp buffer
+    RBufWriteStream dataStream(*dataBuf);
+    dataStream.PushL();
+
+    // Write the language id to the stream
+    dataStream.WriteUint32L(aLanguage);
+
+    // Create a HBufC8 for IPC
+    if (iSearchDataBuffer)
+        {
+        delete iSearchDataBuffer;
+        iSearchDataBuffer = NULL;
+        }
+
+    iSearchDataBuffer = HBufC8::NewLC(dataBuf->Size());
+    CleanupStack::Pop(); // iSearchDataBuffer
+    TPtr8 dataPtr(iSearchDataBuffer->Des());
+    dataBuf->Read(0, dataPtr, dataBuf->Size());
+
+    CleanupStack::PopAndDestroy(2, dataBuf); // dataBuf, dataStream
+
+    // ------------------------- Results Buffer ---------------------
+
+    // Create a buffer to store the search results.    
+    if (iSearchResultsBuffer)
+        {
+        delete iSearchResultsBuffer;
+        iSearchResultsBuffer = NULL;
+        }
+    iSearchResultsBuffer = HBufC8::NewL(KBufferMaxLen);
+
+    // -------------------------------------------------------------- 
+    // Send the request
+    iSession.IsLanguageSupportedL(iSearchDataBuffer->Des(), iSearchResultsBuffer->Des());
+
+    // parse the result
+    RDesReadStream resultStream(iSearchResultsBuffer->Des());
+    resultStream.PushL();
+
+    // result ETrue or EFalse
+    TBool flag = resultStream.ReadUint8L();
+
+    CleanupStack::PopAndDestroy(); // resultStream
+
+    PRINT ( _L("End CPSRequestHandler::IsLanguageSupportedL") );
+    return flag;
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::GetCachingStatusL()
+// Gets the status of the caching synchronously
+// -----------------------------------------------------------------------------
+EXPORT_C TInt CPSRequestHandler::GetCachingStatusL(TCachingStatus& aStatus)
+    {
+    PRINT ( _L("Enter CPSRequestHandler::GetCachingStatusL") );
+
+    // Get the status from property handler
+    // No need to send the request to engine
+    TInt cacheError = iPropertyHandler->GetCachingStatusL(aStatus);
+
+    PRINT ( _L("End CPSRequestHandler::GetCachingStatusL") );
+    return cacheError;
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::ConvertToVpbkLinkLC()
+// Get the contact link associated with the search result
+// -----------------------------------------------------------------------------
+EXPORT_C MVPbkContactLink* CPSRequestHandler::ConvertToVpbkLinkLC(const CPsClientData& aPsData, 
+                                                                  CVPbkContactManager& aContactManager)
+    {
+    PRINT ( _L("Enter CPSRequestHandler::ConvertToVpbkLinkLC") );
+
+    MVPbkContactLink* contactLink = NULL;
+
+    // Get the originating uri for this result    
+    HBufC* URI = aPsData.Uri();
+
+    // Leave if not in contacts domain
+    if (URI->CompareC(KVPbkDefaultCntDbURI) != 0 && URI->CompareC(KVPbkSimGlobalAdnURI) != 0 \
+            && URI->CompareC(KVPbkSimGlobalFdnURI) != 0 && URI->CompareC(KVPbkSimGlobalSdnURI) != 0
+            && URI->CompareC(KVPbkDefaultGrpDbURI) != 0)
+        {
+        User::Leave(KErrNotSupported);
+        }
+
+    // Create converter instance if not already available	
+    if (iConverter == NULL)
+        {
+        // Get the store corresponding to the URI
+        MVPbkContactStoreList& storeList = aContactManager.ContactStoresL();
+        TVPbkContactStoreUriPtr uriPtr(KVPbkDefaultCntDbURI);
+        MVPbkContactStore* store = storeList.Find(uriPtr);
+
+        // Create converter 			
+        if (store)
+            {
+            iConverter = CVPbkContactIdConverter::NewL(*store);
+            }
+        }
+
+    if (aPsData.Id() < 0) // ID is negative for contacts in SIM domain
+        {
+        // Contact link is already packed for SIM contacts in CPsClientData
+        HBufC8* linkBuf = (HBufC8*) aPsData.DataExtension();
+
+        // ---------------- Convert HBufC8* to contact link ---------------------------	   	   				
+
+        if (linkBuf->Length())
+            {
+            // Get the store corresponding to the URI
+            MVPbkContactStoreList& storeList = aContactManager.ContactStoresL();
+
+            // Link array
+            CVPbkContactLinkArray* array = CVPbkContactLinkArray::NewLC(*(linkBuf), storeList);
+
+            TInt count = array->Count();
+
+            if (count == 1) // should contain only single contact link
+                {
+                const MVPbkContactLink& link = array->At(0);
+                contactLink = link.CloneLC();
+                CleanupStack::Pop(); // contactLink
+                }
+
+            CleanupStack::PopAndDestroy(); // array	
+            }
+
+        // ---------------- End convert HBufC8* to contact link -----------------------
+        }
+    else
+        {
+        // cntdb domain
+        if (iConverter)
+            {
+            contactLink = iConverter->IdentifierToLinkLC(aPsData.Id());
+            CleanupStack::Pop();
+            }
+        }
+
+    // Add to cleanup stack
+    CleanupDeletePushL(contactLink);
+
+    PRINT ( _L("End CPSRequestHandler::ConvertToVpbkLinkLC") );
+
+    return contactLink;
+
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::GetAllContentsL()
+// Sends a request to the predictive search server to get all cached contents.
+// -----------------------------------------------------------------------------
+EXPORT_C void CPSRequestHandler::GetAllContentsL()
+    {
+    PRINT ( _L("Enter CPSRequestHandler::GetAllContentsL") );
+
+    // Create a empty CPsQuery
+    CPsQuery* query = CPsQuery::NewL();
+
+    // Perform a search
+    SearchL(*query);
+
+    // Cleanup
+    delete query;
+
+    PRINT ( _L("Enter CPSRequestHandler::GetAllContentsL") );
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::GetDataOrderL()
+// 
+// -----------------------------------------------------------------------------
+EXPORT_C void CPSRequestHandler::GetDataOrderL(const TDesC& aURI,
+        RArray<TInt>& aDataOrder)
+    {
+    PRINT ( _L("Enter CPSRequestHandler::GetDataOrderL") );
+
+    // ----------------------- URI ----------------------
+
+    // Tmp buffer        
+    CBufFlat* dataBuf = CBufFlat::NewL(KBufferMaxLen);
+    CleanupStack::PushL(dataBuf);
+
+    // Stream over the temp buffer
+    RBufWriteStream dataStream(*dataBuf);
+    dataStream.PushL();
+
+    // Write the URI details in the stream
+    TInt length = aURI.Length();
+    dataStream.WriteUint16L(length);
+    dataStream << aURI;
+
+    // Create a HBufC8 for IPC
+    if (iSearchDataBuffer)
+        {
+        delete iSearchDataBuffer;
+        iSearchDataBuffer = NULL;
+        }
+
+    iSearchDataBuffer = HBufC8::NewL(dataBuf->Size());
+    TPtr8 dataPtr(iSearchDataBuffer->Des());
+    dataBuf->Read(0, dataPtr, dataBuf->Size());
+
+    // ------------------------- Results Buffer ---------------------
+
+    // Create a buffer to store the search results.    
+    if (iSearchResultsBuffer)
+        {
+        delete iSearchResultsBuffer;
+        iSearchResultsBuffer = NULL;
+        }
+    iSearchResultsBuffer = HBufC8::NewL(KBufferMaxLen);
+
+    // --------------------------------------------------------------      
+
+    // Send the request
+    iSession.GetDataOrderL(iSearchDataBuffer->Des(), iSearchResultsBuffer->Des());
+
+    // Parse the results
+    RDesReadStream resultStream(iSearchResultsBuffer->Des());
+    resultStream.PushL();
+
+    // Number of fields
+    TInt fieldCount = resultStream.ReadUint16L();
+
+    // Fields
+    for (int i = 0; i < fieldCount; i++)
+        {
+        TInt fieldId = resultStream.ReadUint16L();
+        aDataOrder.Append(fieldId);
+        }
+
+    // Cleanup
+    delete iSearchResultsBuffer;
+    delete iSearchDataBuffer;
+    CleanupStack::PopAndDestroy(3, dataBuf); // resultStream, dataStream, dataBuf
+    iSearchResultsBuffer = NULL;
+    iSearchDataBuffer = NULL;
+
+    PRINT ( _L("End CPSRequestHandler::GetDataOrderL") );
+
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::GetSortOrderL()
+// 
+// -----------------------------------------------------------------------------
+EXPORT_C void CPSRequestHandler::GetSortOrderL(const TDesC& aURI, RArray<TInt>& aDataOrder)
+    {
+    PRINT ( _L("Enter CPSRequestHandler::GetSortOrderL") );
+
+    // ----------------------- URI ----------------------
+
+    // Tmp buffer        
+    CBufFlat* dataBuf = CBufFlat::NewL(KBufferMaxLen);
+    CleanupStack::PushL(dataBuf);
+
+    // Stream over the temp buffer
+    RBufWriteStream dataStream(*dataBuf);
+    dataStream.PushL();
+
+    // Write the URI details in the stream
+    TInt length = aURI.Length();
+    dataStream.WriteUint16L(length);
+    dataStream << aURI;
+
+    // Create a HBufC8 for IPC
+    if (iSearchDataBuffer)
+        {
+        delete iSearchDataBuffer;
+        iSearchDataBuffer = NULL;
+        }
+
+    iSearchDataBuffer = HBufC8::NewL(dataBuf->Size());
+    TPtr8 dataPtr(iSearchDataBuffer->Des());
+    dataBuf->Read(0, dataPtr, dataBuf->Size());
+
+    // ------------------------- Results Buffer ---------------------
+
+    // Create a buffer to store the search results.    
+    if (iSearchResultsBuffer)
+        {
+        delete iSearchResultsBuffer;
+        iSearchResultsBuffer = NULL;
+        }
+    iSearchResultsBuffer = HBufC8::NewL(KBufferMaxLen);
+
+    // --------------------------------------------------------------      
+
+    // Send the request
+    iSession.GetSortOrderL(iSearchDataBuffer->Des(), iSearchResultsBuffer->Des());
+
+    // Parse the results
+    RDesReadStream resultStream(iSearchResultsBuffer->Des());
+    resultStream.PushL();
+
+    // Number of fields
+    TInt fieldCount = resultStream.ReadUint16L();
+
+    // Fields
+    for (int i = 0; i < fieldCount; i++)
+        {
+        TInt fieldId = resultStream.ReadUint16L();
+        aDataOrder.Append(fieldId);
+        }
+
+    // Cleanup
+    delete iSearchResultsBuffer;
+    delete iSearchDataBuffer;
+    CleanupStack::PopAndDestroy(3, dataBuf); // resultStream, dataStream, dataBuf
+    iSearchResultsBuffer = NULL;
+    iSearchDataBuffer = NULL;
+
+    PRINT ( _L("End CPSRequestHandler::GetSortOrderL") );
+
+    }
+
+// -----------------------------------------------------------------------------
+// CPSRequestHandler::ChangeSortOrderL()
+// 
+// -----------------------------------------------------------------------------
+EXPORT_C void CPSRequestHandler::ChangeSortOrderL(const TDesC& aURI, RArray<TInt>& aSortOrder)
+    {
+    PRINT ( _L("Enter CPSRequestHandler::ChangeSortOrderL") );
+
+    // ----------------------- URI and Sort Order --------------------
+
+    // Tmp buffer        
+    CBufFlat* dataBuf = CBufFlat::NewL(KBufferMaxLen);
+    CleanupStack::PushL(dataBuf);
+
+    // Stream over the temp buffer
+    RBufWriteStream dataStream(*dataBuf);
+    dataStream.PushL();
+
+    // Write the URI details in the stream
+    TInt length = aURI.Length();
+    dataStream.WriteUint16L(length);
+    dataStream << aURI;
+
+    // Write the sort order
+    dataStream.WriteUint16L(aSortOrder.Count());
+    for (int i = 0; i < aSortOrder.Count(); i++)
+        {
+        dataStream.WriteUint16L(aSortOrder[i]);
+        }
+
+    // Create a HBufC8 for IPC
+    if (iSearchDataBuffer)
+        {
+        delete iSearchDataBuffer;
+        iSearchDataBuffer = NULL;
+        }
+
+    iSearchDataBuffer = HBufC8::NewL(dataBuf->Size());
+    TPtr8 dataPtr(iSearchDataBuffer->Des());
+    dataBuf->Read(0, dataPtr, dataBuf->Size());
+
+    // Send the request
+    iSession.ChangeSortOrderL(iSearchDataBuffer->Des());
+
+    // Cleanup
+    delete iSearchDataBuffer;
+    CleanupStack::PopAndDestroy(2, dataBuf); // dataStream, dataBuf
+    iSearchDataBuffer = NULL;
+
+    PRINT ( _L("End CPSRequestHandler::ChangeSortOrderL") );
+
+    }
+
+// End of File