predictivesearch/PcsServerClientAPI/src/CPsRequestHandler.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 31 Mar 2010 21:13:53 +0300
branchRCL_3
changeset 21 b3431bff8c19
parent 0 e686773b3f54
child 35 4ae315f230bc
permissions -rw-r--r--
Revision: 201011 Kit: 201013

/*
* 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 (TInt 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 (TInt 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 (TInt i = 0; i < iObservers.Count(); i++)
        {
        iObservers[i]->HandlePsResultsUpdate(searchResults, searchSeqs);
        }

    // Clear all the internal buffers
    searchResults.ResetAndDestroy();
    searchSeqs.ResetAndDestroy();
    delete iSearchQueryBuffer;
    iSearchQueryBuffer = NULL;
    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