--- /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