predictivesearch/PcsAlgorithm/Algorithm1/src/CPcsAlgorithm1Helper.cpp
changeset 0 e686773b3f54
child 3 04ab22b956c2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/predictivesearch/PcsAlgorithm/Algorithm1/src/CPcsAlgorithm1Helper.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,452 @@
+/*
+* 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:  Predictive Contact Search Algorithm 1 helper class
+*
+*/
+
+
+// INCLUDES
+
+#include "CPcsAlgorithm1.h"
+#include "CPcsAlgorithm1Helper.h"
+#include "CPcsAlgorithm1Utils.h"
+#include "CPcsDebug.h"
+#include "CPcsCache.h"
+#include "CPcsKeyMap.h"
+#include "CPsData.h"
+#include "CWords.h"
+#include "CPsQuery.h"
+#include "CPsQueryItem.h"
+#include "CPsDataPluginInterface.h"
+#include "CPcsPoolElement.h"
+
+// Compare functions
+TBool Compare1 ( const TDesC& aFirst, const TDesC& aSecond )
+{
+    return aFirst == aSecond;
+}
+
+TBool Compare2 ( const TDesC& aFirst, const TDesC& aSecond )
+{
+    return CPcsAlgorithm1Utils::MyCompareC(aFirst, aSecond);
+}
+
+// ============================== MEMBER FUNCTIONS ============================
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm1Helper::NewL
+// Two Phase Construction
+// ----------------------------------------------------------------------------
+CPcsAlgorithm1Helper* CPcsAlgorithm1Helper::NewL(CPcsAlgorithm1* aAlgorithm)
+{
+    PRINT ( _L("Enter CPcsAlgorithm1Helper::NewL") );
+
+    CPcsAlgorithm1Helper* self = new ( ELeave ) CPcsAlgorithm1Helper();
+    CleanupStack::PushL( self );
+    self->ConstructL(aAlgorithm);
+    CleanupStack::Pop( self );
+
+    PRINT ( _L("End CPcsAlgorithm1Helper::NewL") );
+
+    return self;
+}
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm1Helper::CPcsAlgorithm1Helper
+// Two Phase Construction
+// ----------------------------------------------------------------------------
+CPcsAlgorithm1Helper::CPcsAlgorithm1Helper()
+{
+    PRINT ( _L("Enter CPcsAlgorithm1Helper::CPcsAlgorithm1") );
+    PRINT ( _L("End CPcsAlgorithm1Helper::CPcsAlgorithm1") );
+}
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm1Helper::ConstructL
+// Two Phase Construction
+// ----------------------------------------------------------------------------
+void CPcsAlgorithm1Helper::ConstructL(CPcsAlgorithm1* aAlgorithm)
+{
+    PRINT ( _L("Enter CPcsAlgorithm1Helper::ConstructL") );
+
+    iAlgorithm = aAlgorithm;
+    iKeyMap = iAlgorithm->GetKeyMap();
+
+    PRINT ( _L("End CPcsAlgorithm1Helper::ConstructL") );
+}
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm1Helper::CPcsAlgorithm1Helper
+// Destructor
+// ----------------------------------------------------------------------------
+CPcsAlgorithm1Helper::~CPcsAlgorithm1Helper()
+{
+    PRINT ( _L("Enter CPcsAlgorithm1Helper::~CPcsAlgorithm1Helper") );
+    iSearchResultsArr.ResetAndDestroy();
+    PRINT ( _L("End CPcsAlgorithm1Helper::~CPcsAlgorithm1Helper") );
+}
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm1Helper::SearchSingleL
+// Search function for query in ITU-T mode, QWERTY mode, or Mixed (ITU-T and QWERTY) mode.
+// ----------------------------------------------------------------------------
+void  CPcsAlgorithm1Helper::SearchSingleL(const CPsSettings& aSettings,
+                                       CPsQuery& aPsQuery,
+                                       TBool isSearchInGroup,
+                                       RArray<TInt>& aContactsInGroup,
+                                       RPointerArray<CPsData>& searchResults,
+                                       RPointerArray<CPsPattern>& searchSeqs )
+{
+    PRINT ( _L("Enter CPcsAlgorithm1Helper::SearchSingleL") );
+
+    __LATENCY_MARK ( _L("CPcsAlgorithm1Helper::SearchSingleL") );
+
+    // Create filtering helper for the required sort type
+    TSortType sortType = aSettings.GetSortType();
+    CPcsAlgorithm1FilterHelper* filterHelper = CPcsAlgorithm1FilterHelper::NewL(sortType);
+
+    // Search based on first character
+    TInt numValue = iKeyMap->PoolIdForCharacter(aPsQuery.GetItemAtL(0).Character());
+
+    // Reset the result set array for new search
+    iSearchResultsArr.ResetAndDestroy();
+
+    // Get the data stores
+    RPointerArray<TDesC> aDataStores;
+    aSettings.SearchUrisL(aDataStores);
+
+    // Get the required display fields from the client
+    RArray<TInt> requiredDataFields;
+    aSettings.DisplayFieldsL(requiredDataFields);
+
+    // Perform search for each required data store
+    RPointerArray<CPcsPoolElement> elements;
+
+    for ( int dsIndex = 0;
+          dsIndex < aDataStores.Count();
+          dsIndex++ )
+    {
+        RPointerArray<CPsData> *temp = new (ELeave) RPointerArray<CPsData> ();
+        iSearchResultsArr.Append(temp);
+
+        // Get the contents for this data store
+        TInt arrayIndex = iAlgorithm->GetCacheIndex(*(aDataStores[dsIndex]));
+        if ( arrayIndex < 0 ) continue;
+        CPcsCache* cache = iAlgorithm->GetCache(arrayIndex);
+        cache->GetContactsForKeyL(numValue,elements);
+
+        // Get the supported data fields for this data store
+        RArray<TInt> supportedDataFields;
+        cache->GetDataFields(supportedDataFields);
+
+        // Get the filtered data fields for this data store
+        TUint8 filteredDataMatch = FilterDataFieldsL(requiredDataFields,
+                                                     supportedDataFields);
+
+        // Perform filtering
+        FilterResultsSingleL(filterHelper,
+                             elements,
+                             aPsQuery,
+                             filteredDataMatch,
+                             isSearchInGroup,
+                             aContactsInGroup);
+
+        // If alphabetical sorting, get the results for this datastore
+        if ( sortType == EAlphabetical )
+        {
+            filterHelper->GetResults(*(iSearchResultsArr[dsIndex]));
+        }
+
+        elements.Reset();
+        supportedDataFields.Reset();
+    }
+
+    aDataStores.ResetAndDestroy();
+    requiredDataFields.Reset();
+
+    // If alphabetical sorting, merge the result sets of all datastores
+    if ( sortType == EAlphabetical )
+    {
+        // Merge the result sets of individual datastores alphabetically
+        CPcsAlgorithm1Utils::FormCompleteSearchResultsL(iSearchResultsArr,
+                                                        searchResults);
+    }
+    else
+    {
+        // Results are already sorted pattern based
+        filterHelper->GetResults(searchResults);
+    }
+
+    // Get the sorted match sequence list
+    filterHelper->GetPatternsL(searchSeqs);
+
+    PRINT1 ( _L("CPcsAlgorithm1Helper::SearchSingleL: Number of search results = %d"), searchResults.Count() );
+
+    // Cleanup
+    for ( TInt i = 0; i < iSearchResultsArr.Count(); i++ )
+    {
+        iSearchResultsArr[i]->Reset();
+        delete iSearchResultsArr[i];
+        iSearchResultsArr[i] = NULL;
+    }
+    iSearchResultsArr.Reset();
+
+    delete filterHelper;
+
+    __LATENCY_MARKEND ( _L("CPcsAlgorithm1Helper::SearchSingleL") );
+
+    PRINT ( _L("End CPcsAlgorithm1Helper::SearchSingleL") );
+}
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm1Helper::FilterResultsSingleL
+// Subset search function
+// ----------------------------------------------------------------------------
+void  CPcsAlgorithm1Helper::FilterResultsSingleL(CPcsAlgorithm1FilterHelper* aAlgorithmFilterHelper,
+                                                 RPointerArray<CPcsPoolElement>& searchSet,
+                                                 CPsQuery& aPsQuery,
+                                                 TUint8 aFilteredDataMatch,
+                                                 TBool isSearchInGroup,
+                                                 RArray<TInt>& aContactsInGroup)
+{
+    PRINT ( _L("Enter CPcsAlgorithm1Helper::FilterResultsSingleL") );
+
+    __LATENCY_MARK ( _L("CPcsAlgorithm1Helper::FilterResultsSingleL") );
+
+    // Convert the search query to char-and-key string
+    TBuf<KPsQueryMaxLen> queryAsDes;
+    iKeyMap->GetMixedKeyStringForQueryL( aPsQuery, queryAsDes );
+
+    PRINTQUERY ( _L("CPcsAlgorithm1Helper::FilterResultsSingleL: "), aPsQuery );
+
+    PRINT1 ( _L("CPcsAlgorithm1Helper::FilterResultsSingleL: char-and-key string for the query is \"%S\""),
+             &queryAsDes );      
+
+    // Parse thru each search set elements and filter the results
+    for ( TInt index = 0; index < searchSet.Count(); index++ )
+    {
+        CPcsPoolElement* poolElement = static_cast<CPcsPoolElement*>(searchSet[index]);
+        CPsData* psData = poolElement->GetPsData();
+        psData->ClearDataMatches();
+        RPointerArray<TDesC> tempMatchSeq;
+        TBool isAdded = EFalse;
+
+        // Parse thru each data and filter the results
+        for ( TInt dataIndex = 0; dataIndex < psData->DataElementCount(); dataIndex++ )
+        {
+            // Filter off data fields not required in search
+            TReal bitIndex;
+            Math::Pow(bitIndex, 2, dataIndex);
+
+            TUint8 filter = (TUint8)bitIndex & aFilteredDataMatch;
+            if ( filter == 0x0 )
+            {
+                // Move to next data
+                continue;
+            }
+
+            if ( poolElement->IsDataMatch(dataIndex) )
+            {
+                TLex lex(psData->Data(dataIndex)->Des());
+
+                // First word
+                TPtrC token = lex.NextToken();
+
+                // Search thru multiple words
+                while ( token.Length() != 0 )
+                {
+                    // Convert the data to char-and-key string
+                    TBuf<KPsQueryMaxLen> dataWithKeys;
+                    iKeyMap->GetMixedKeyStringForDataL( aPsQuery, token, dataWithKeys );
+
+                    // MyCompareC is case insensitive.
+                    // We have some cases that key "Z" (uppercase) is mapping chars "Zz...."
+                    // and key "z" (lowercase) is mapping chars ".," or "Ää".
+                    // The comparison of "Z" and "z" should fail for the keys, that's why we use MyCompareK.
+                    if ( ( CPcsAlgorithm1Utils::MyCompareK(dataWithKeys, queryAsDes, aPsQuery) ) &&
+                         ( CPcsAlgorithm1Utils::MyCompareC(dataWithKeys.Left(queryAsDes.Length()), queryAsDes) == 0 ) )
+                    {
+                        psData->SetDataMatch(dataIndex);
+                        isAdded = ETrue;
+
+                        // Extract matched character sequence
+                        TInt len = queryAsDes.Length();
+                        HBufC* seq = HBufC::NewLC(len);
+                        *seq = token.Mid(0, len);
+                        seq->Des().UpperCase();
+
+                        TIdentityRelation<TDesC> rule(Compare1);
+                        if ( tempMatchSeq.Find(seq, rule) == KErrNotFound )
+                        {
+                            tempMatchSeq.Append(seq);
+                            CleanupStack::Pop();
+                        }
+                        else
+                        {
+                            CleanupStack::PopAndDestroy();
+                        }
+                    }
+                    // Next word
+                    token.Set(lex.NextToken());
+                }
+            }
+        }
+
+        // Add the result
+        if ( isAdded )
+        {
+            if ( isSearchInGroup )
+            {
+                if ( aContactsInGroup.Find(psData->Id()) != KErrNotFound )
+                {
+                    aAlgorithmFilterHelper->AddL(psData,tempMatchSeq);
+                }
+            }
+            else
+            {
+                aAlgorithmFilterHelper->AddL(psData,tempMatchSeq);
+            }
+        }
+
+        // Cleanup the match sequence array as
+        // they are stored in pattern details structure
+        tempMatchSeq.ResetAndDestroy();
+    }
+
+    __LATENCY_MARKEND ( _L("CPcsAlgorithm1Helper::FilterResultsSingleL") );
+
+    PRINT ( _L("End CPcsAlgorithm1Helper::FilterResultsSingleL") );
+}
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm1Helper::SearchMatchSeqL
+// Funciton to search matching sequences in the input text
+// ----------------------------------------------------------------------------
+void  CPcsAlgorithm1Helper::SearchMatchSeqL(CPsQuery& aPsQuery,
+                                            TDesC& aData,
+                                            RPointerArray<TDesC>& aMatchSet,
+                                            RArray<TPsMatchLocation>& aMatchLocation )
+{
+    PRINT ( _L("Enter CPcsAlgorithm1Helper::SearchMatchSeqL") );
+
+    HBufC* queryAsDes = HBufC::NewLC(aPsQuery.Count());
+    TPtr queryAsDesPtr(queryAsDes->Des());
+    iKeyMap->GetMixedKeyStringForQueryL( aPsQuery, queryAsDesPtr );
+
+    // Convert the data into words
+    TLex lex(aData);
+
+    // First word
+    TPtrC token = lex.NextToken();
+
+    TInt beg = lex.Offset() - token.Length();  // start index of match sequence
+
+    // Search thru multiple words
+    while ( token.Length() != 0 )
+    {
+         HBufC* data = HBufC::NewLC(token.Length());
+         TPtr dataPtr(data->Des());
+         iKeyMap->GetMixedKeyStringForDataL( aPsQuery, token, dataPtr );
+
+         // MyCompareC is case insensitive.
+         // We have some cases that key "Z" (uppercase) is mapping chars "Zz...."
+         // and key "z" (lowercase) is mapping chars ".," or "Ää".
+         // The comparison of "Z" and "z" should fail for the keys, that's why we use MyCompareK.
+         if ( ( CPcsAlgorithm1Utils::MyCompareK(dataPtr, *queryAsDes, aPsQuery) ) &&
+              ( CPcsAlgorithm1Utils::MyCompareC(dataPtr.Left(queryAsDes->Length()), *queryAsDes) == 0 ) )
+         {
+            TInt len = queryAsDes->Length();
+
+            TPsMatchLocation tempLocation;
+
+            // check for directionality of the text
+            TBool found(EFalse);
+            TBidiText::TDirectionality dir = TBidiText::TextDirectionality(token, &found);
+
+            tempLocation.index = beg;
+            tempLocation.length = len;
+            tempLocation.direction = dir;
+
+            // Add the match location to the data structure array
+            aMatchLocation.Append(tempLocation);
+
+            // Add the sequence to the match sequence
+            HBufC* seq = HBufC::NewLC(len);
+            *seq = token.Mid(0, len);
+            seq->Des().UpperCase();
+
+            TIdentityRelation<TDesC> rule(Compare1);
+            if ( aMatchSet.Find(seq, rule) == KErrNotFound )
+            {
+                aMatchSet.Append(seq);
+                CleanupStack::Pop();
+            }
+            else
+            {
+                CleanupStack::PopAndDestroy();
+            }
+         }
+
+         // Next word
+         token.Set(lex.NextToken());
+         beg = lex.Offset() - token.Length();  // start index of next word
+         CleanupStack::PopAndDestroy(); //data
+     }
+
+    CleanupStack::PopAndDestroy( queryAsDes );
+
+    PRINT ( _L("End CPcsAlgorithm1Helper::SearchMatchSeqL") );
+}
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm1Helper::SortSearchSeqsL()
+//
+// ----------------------------------------------------------------------------
+void  CPcsAlgorithm1Helper::SortSearchSeqsL(RPointerArray<TDesC>& aSearchSeqs)
+{
+    // Sort the search seqs
+    TLinearOrder<TDesC> rule( Compare2 );
+    aSearchSeqs.Sort(rule);
+}
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm1Helper::FilterDataFieldsL()
+// Constructs a bit pattern using the required/supported data fields
+// For example, 6, 4 and 27 are supported fields <-- 00000111
+//              6 and 4 are required fields      <-- 00000011
+// Bit pattern returned is 00000011.
+// ----------------------------------------------------------------------------
+TUint8 CPcsAlgorithm1Helper::FilterDataFieldsL(RArray<TInt>& aRequiredDataFields,
+                                               RArray<TInt>& aSupportedDataFields)
+{
+    TUint8 filteredMatch = 0x0;
+
+    for ( int i = 0; i < aSupportedDataFields.Count(); i++ )
+    {
+        for ( int j = 0; j < aRequiredDataFields.Count(); j++ )
+        {
+            if ( aSupportedDataFields[i] == aRequiredDataFields[j] )
+            {
+                TReal val;
+                Math::Pow(val, 2, i);
+
+                filteredMatch |= (TUint8)val;
+            }
+        }
+    }
+
+    return filteredMatch;
+}
+
+// End of file