diff -r 5b6f26637ad3 -r f4a778e096c2 predictivesearch/PcsAlgorithm/Algorithm1/src/CPcsCache.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/predictivesearch/PcsAlgorithm/Algorithm1/src/CPcsCache.cpp Wed Sep 01 12:29:52 2010 +0100 @@ -0,0 +1,707 @@ +/* +* 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: Holds the contact information in memory. It maintains a +* master array of all contacts. It also has 10 pools corresponding +* to each key id in the keyboard. Based on numeric key char of +* first char of firstname/ lastname a contact is added to one of the +* pools. Implements MDataStoreObserver interface functions to +* add/ remove contacts. +* +*/ + + +// INCLUDE FILES +#include +#include +#include "CPcsDefs.h" +#include "CPsData.h" +#include "CPcsCache.h" +#include "CPcsDebug.h" +#include "CWords.h" +#include "CPcsAlgorithm1Utils.h" +#include "CPcsAdaptiveGridItem.h" + +// ============================== MEMBER FUNCTIONS ============================ + +// ---------------------------------------------------------------------------- +// CPcsCache::NewL +// Two Phase Construction +// ---------------------------------------------------------------------------- +CPcsCache* CPcsCache::NewL(const TDesC& aURI, CPcsKeyMap& aKeyMap, TUint8 aUriId) +{ + PRINT ( _L("Enter CPcsCache::NewL") ); + + CPcsCache* instance= new ( ELeave ) CPcsCache(); + + CleanupStack::PushL( instance ); + + instance->ConstructL(aURI, aKeyMap, aUriId); + + CleanupStack::Pop( instance ); + + PRINT ( _L("End CPcsCache::NewL") ); + + return instance; +} + +// ---------------------------------------------------------------------------- +// CPcsCache::CPcsCache +// Constructor +// ---------------------------------------------------------------------------- +CPcsCache::CPcsCache() +{ + PRINT ( _L("Enter CPcsCache::CPcsCache") ); + PRINT ( _L("End CPcsCache::CPcsCache") ); +} + +// ---------------------------------------------------------------------------- +// CPcsCache::ConstructL +// 2nd Phase Constructor +// ---------------------------------------------------------------------------- +void CPcsCache::ConstructL(const TDesC& aURI, CPcsKeyMap& aKeyMap, TUint8 aUriId) +{ + PRINT ( _L("Enter CPcsCache::ConstructL") ); + + PRINT2 ( _L("CPcsCache::ConstructL: aURI=%S, aUriId=%d"), &aURI, aUriId); + + iURI = aURI.AllocL(); + iUriId = aUriId; + //Update the caching status for this cache + iCacheStatus = ECachingNotStarted; + + iKeyMap = &aKeyMap; + + // Populate iKeyArr + for(TInt i= 0; i *keyMap = new (ELeave) RPointerArray(1); + iKeyArr.InsertL(keyMap,i); + } + + // Adaptive Grid map + if ( iURI->Compare( KVPbkDefaultCntDbURI ) == 0 + || iURI->Compare( KVPbkSimGlobalAdnURI ) == 0 + || iURI->Compare( KVPbkSimGlobalFdnURI ) == 0 + || iURI->Compare( KVPbkSimGlobalSdnURI ) == 0 + || iURI->Compare( KVPbkDefaultGrpDbURI ) == 0 ) + { + iAdaptiveGridMap = CPcsAdaptiveGrid::NewL(); + } + + PRINT ( _L("End CPcsCache::ConstructL") ); +} + +// ---------------------------------------------------------------------------- +// CPcsCache::~CPcsCache +// Destructor +// ---------------------------------------------------------------------------- +CPcsCache::~CPcsCache() +{ + PRINT ( _L("Enter CPcsCache::~CPcsCache") ); + + delete iURI; + + RemoveAllFromCache(); // cleans up iMasterPool and iCacheInfo + + iKeyArr.ResetAndDestroy(); + iDataFields.Reset(); + iSortOrder.Reset(); + iIndexOrder.Reset(); + iMasterPoolBackup.Close(); + + delete iAdaptiveGridMap; + + PRINT ( _L("End CPcsCache::~CPcsCache") ); +} + +// ---------------------------------------------------------------------------- +// CPcsCache::GetContactsForKeyL +// Get list of pool elements specific to a pool +// ---------------------------------------------------------------------------- +void CPcsCache::GetContactsForKeyL(TInt aKeyId, RPointerArray& aData) + { + PRINT ( _L("Enter CPcsCache::GetContactsForKeyL") ); + CleanupClosePushL( aData ); + if ( aKeyId >= 0 && aKeyId < iKeyArr.Count() ) + { + const RPointerArray& arr = *iKeyArr[aKeyId]; + for ( TInt i = 0; i < arr.Count(); i++ ) + { + aData.AppendL(arr[i]); + } + } + CleanupStack::Pop(); + PRINT ( _L("End CPcsCache::GetContactsForKeyL") ); + } + +// ---------------------------------------------------------------------------- +// CPcsCache::GetAllContentsL +// Get all data elements in this cache +// ---------------------------------------------------------------------------- +void CPcsCache::GetAllContentsL(RPointerArray& aData) +{ + PRINT ( _L("Enter CPcsCache::GetAllContentsL") ); + CleanupClosePushL( aData ); + for ( TInt i = 0; i < iMasterPool.Count(); i++ ) + { + aData.AppendL(iMasterPool[i]); + } + CleanupStack::Pop(); + PRINT ( _L("End CPcsCache::GetAllContentsL") ); +} + +// ---------------------------------------------------------------------------- +// CPcsCache::AddToPool +// Adds a contact to cache +// ---------------------------------------------------------------------------- +void CPcsCache::AddToPoolL(TUint64& aPoolMap, CPsData& aData) +{ + // Temp hash to remember the location of pool elements + // First TInt = Pool + // Second TInt = Location in the pool + // Required for memory optimization so that more than one pool + // element doesn't get added for the same data + RHashMap elementHash; + CleanupClosePushL( elementHash ); + TLinearOrder rule( CPcsPoolElement::CompareByData ); + + TBool unnamed = ETrue; + // Parse thru each data element + for ( TInt dataIndex = 0; dataIndex < aData.DataElementCount(); dataIndex++ ) + { + HBufC* dataStr = aData.Data(dataIndex); + + // Find store all the pool IDs where this contact should be + RArray poolIds; + CleanupClosePushL( poolIds ); + + // Recover the first character + if ( dataStr && dataStr->Length() != 0 ) + { + // Split the data into words + CWords* words = CWords::NewLC(*dataStr); + + // Store the first numeric key for each word + for ( TInt i = 0; i < words->MdcaCount(); i++ ) + { + TChar firstChar = (words->MdcaPoint(i))[0]; + + // Pool ID according to ITU-T mappings + if ( iKeyMap->IsItutPredictiveAvailable() ) + { + TInt itutPoolId = iKeyMap->PoolIdForCharacter(firstChar, EPredictiveItuT); + if ( itutPoolId != KErrNotFound ) + { + poolIds.Append(itutPoolId); + } + } + + // Pool ID according to QWERTY mappings + if ( iKeyMap->IsQwertyPredictiveAvailable() ) + { + TInt qwertyPoolId = iKeyMap->PoolIdForCharacter(firstChar, EPredictiveQwerty); + if ( qwertyPoolId != KErrNotFound ) + { + poolIds.Append(qwertyPoolId); + } + } + +#ifdef _DEBUG + PRINT2 ( _L("CPcsCache::AddToPoolL: iURI=\"%S\", iUriId=%d"), &*iURI, iUriId ); + TPtrC16 ptr = words->MdcaPoint(i); + PRINT5 ( _L("CPcsCache::AddToPoolL: Data[%d]=\"%S\", word=\"%S\", firstChar='%c', Match=%d" ), + dataIndex, &*dataStr, &(ptr), (TUint) firstChar, aData.IsDataMatch(dataIndex) ); +#endif // _DEBUG + + if ( iAdaptiveGridMap ) + { + // Set the 1st char of the word for the Adaptive Grid or + // increment the reference counter + TUint selector = GridItemSelector( dataIndex, unnamed ); + iAdaptiveGridMap->IncrementRefCounterL( firstChar, selector ); + } + } + + CleanupStack::PopAndDestroy(words); + } + + for ( TInt poolIdIndex = 0; poolIdIndex < poolIds.Count(); poolIdIndex++ ) + { + TUint poolId = poolIds[poolIdIndex]; + CPcsPoolElement* element = NULL; + + // Check if an element already exists in the pool for this data + TInt* loc = NULL; + loc = elementHash.Find(poolId); + if ( loc != NULL ) + { + // Exists. Then recover ... + const RPointerArray& tmpKeyMap = *(iKeyArr[poolId]); + element = tmpKeyMap[*loc]; + } + + if ( element == NULL ) // Pool element doesn't exist. Create new ... + { + element = CPcsPoolElement::NewL(aData); + CleanupStack::PushL( element ); + element->ClearDataMatchAttribute(); + element->SetDataMatch(dataIndex); + + // Insert to pool + iKeyArr[poolId]->InsertInOrderAllowRepeatsL(element, rule); + CleanupStack::Pop( element ); // ownership transferred + TInt index = iKeyArr[poolId]->FindInOrderL(element, rule); + + // Set the bit for this pool + SetPoolMap(aPoolMap, poolId); + + // Store the array index in the temp hash + elementHash.InsertL(poolId, index); + } + else // Pool element exists. Just alter the data match attribute + { + element->SetDataMatch(dataIndex); + + // Set the bit for this pool + SetPoolMap(aPoolMap, poolId); + } + + } // for 2 loop + + CleanupStack::PopAndDestroy( &poolIds ); + + } // for 1 loop + + CleanupStack::PopAndDestroy( &elementHash ); +} + +// --------------------------------------------------------------------- +// CPcsCache::AddToCacheL +// +// --------------------------------------------------------------------- +void CPcsCache::AddToCacheL( CPsData& aData ) +{ + // Protect against duplicate items getting added + if ( iCacheInfo.Find(aData.Id()) != NULL ) + { + return; + } + + // Include this element in the pool + TUint64 poolMap = 0; + AddToPoolL(poolMap, aData); + iCacheInfo.InsertL(aData.Id(), poolMap); + + // Include this element in master pool + TLinearOrder rule( CPcsAlgorithm1Utils::CompareDataBySortOrderL ); + + iMasterPool.InsertInOrderAllowRepeatsL(&aData, rule); +} + +// --------------------------------------------------------------------- +// CPcsCache::RemoveContactL +// +// --------------------------------------------------------------------- +void CPcsCache::RemoveFromCacheL( TInt aItemId ) +{ + CPsData* data = NULL; + + TUint64* poolMap = iCacheInfo.Find(aItemId); + + if ( poolMap == NULL ) + { + return; + } + + // Remove this element from pools + for ( TInt keyIndex = 0; keyIndex < iKeyArr.Count(); keyIndex++ ) + { + TBool present = GetPoolMap(*poolMap, keyIndex); + + if ( !present ) + { + continue; + } + + TInt arrayIndex = 0; + TInt arrayCount = iKeyArr[keyIndex]->Count(); + while ( arrayIndex < arrayCount ) + { + CPcsPoolElement* element = (*(iKeyArr[keyIndex]))[arrayIndex]; + if ( element->GetPsData()->Id() == aItemId ) + { + data = element->GetPsData(); + delete element; + iKeyArr[keyIndex]->Remove(arrayIndex); + arrayCount--; + } + else + { + arrayIndex++; + } + } + } + + // Remove this element from master pool + TInt arrayIndex = 0; + TInt arrayCount = iMasterPool.Count(); + while ( arrayIndex < arrayCount ) + { + if ( iMasterPool[arrayIndex]->Id() == aItemId ) + { + iMasterPool.Remove(arrayIndex); + arrayCount--; + } + else + { + arrayIndex++; + } + } + + if ( iAdaptiveGridMap && data ) + { + TBool unnamed = ETrue; + // Parse thru each data element + for ( TInt dataIndex = 0; dataIndex < data->DataElementCount(); dataIndex++ ) + { + HBufC* dataStr = data->Data(dataIndex); + + // Recover the first character + if ( dataStr && dataStr->Length() != 0 ) + { + // Split the data into words + CWords* words = CWords::NewLC(*dataStr); + + // Store the first numeric key for each word + for ( TInt i = 0; i < words->MdcaCount(); i++ ) + { + TChar firstChar = (words->MdcaPoint(i))[0]; + +#ifdef _DEBUG + PRINT2 ( _L("CPcsCache::RemoveFromCacheL: iURI=\"%S\", iUriId=%d"), &*iURI, iUriId ); + TPtrC16 ptr = words->MdcaPoint(i); + PRINT5 ( _L("CPcsCache::RemoveFromCacheL: Data[%d]=\"%S\", word=\"%S\", firstChar='%c', Match=%d" ), + dataIndex, &*dataStr, &(ptr), (TUint) firstChar, data->IsDataMatch(dataIndex) ); +#endif // _DEBUG + // Decrement the reference counter of the 1st char of the word for the Adaptive Grid or + // delete the Adaptive Grid item if there are no references to it anymore + TUint selector = GridItemSelector( dataIndex, unnamed ); + iAdaptiveGridMap->DecrementRefCounter( firstChar, selector ); + } + CleanupStack::PopAndDestroy( words ); + } + } + } + + // Delete data + delete data; + data = NULL; + + // Clear up cache information + iCacheInfo.Remove(aItemId); +} + +// --------------------------------------------------------------------- +// CPcsCache::RemoveAllFromCache +// +// --------------------------------------------------------------------- +void CPcsCache::RemoveAllFromCache() +{ + PRINT ( _L("Enter CPcsCache::RemoveAllFromCache") ); + + for ( TInt i = 0; i < iKeyArr.Count(); i++ ) + { + iKeyArr[i]->ResetAndDestroy(); + } + + iMasterPool.ResetAndDestroy(); + iCacheInfo.Close(); + + if ( iAdaptiveGridMap ) + { + iAdaptiveGridMap->Reset(); + } + + PRINT ( _L("End CPcsCache::RemoveAllFromCache") ); +} + +// --------------------------------------------------------------------- +// CPcsCache::GetAdaptiveGridL +// +// --------------------------------------------------------------------- +void CPcsCache::GetAdaptiveGridL( const TBool aCompanyName, TDes& aAdaptiveGrid ) +{ + PRINT ( _L("Enter CPcsCache::GetAdaptiveGridL") ); + + if ( iAdaptiveGridMap ) + { + iAdaptiveGridMap->GetAdaptiveGrid( aCompanyName, aAdaptiveGrid ); + } + + PRINT ( _L("End CPcsCache::GetAdaptiveGridL") ); +} + +// --------------------------------------------------------------------- +// CPcsCache::SetPoolMap +// +// --------------------------------------------------------------------- +void CPcsCache::SetPoolMap(TUint64& aPoolMap, TInt aArrayIndex) +{ + __ASSERT_DEBUG( aArrayIndex < 64, User::Panic(_L("CPcsCache"), KErrOverflow ) ); + + /* Some platforms do not support 64 bits shift operations. + * Split to two 32 bits operations. + */ + + TUint32 poolMapH = I64HIGH(aPoolMap); + TUint32 poolMapL = I64LOW(aPoolMap); + + TUint32 valH = 0; + TUint32 valL = 0; + if (aArrayIndex < 32) + { + valL = 1 << aArrayIndex; + } + else + { + valH = 1 << (aArrayIndex-32); + } + + poolMapH |= valH; + poolMapL |= valL; + + aPoolMap = MAKE_TUINT64(poolMapH, poolMapL); +} + +// --------------------------------------------------------------------- +// CPcsCache::GetPoolMap +// +// --------------------------------------------------------------------- +TBool CPcsCache::GetPoolMap(TUint64& aPoolMap, TInt aArrayIndex) +{ + __ASSERT_DEBUG( aArrayIndex < 64, User::Panic(_L("CPcsCache"), KErrOverflow ) ); + + /* Some platforms do not support 64 bits shift operations. + * Split to two 32 bits operations. + */ + + TUint32 poolMapH = I64HIGH(aPoolMap); + TUint32 poolMapL = I64LOW(aPoolMap); + + TUint32 valH = 0; + TUint32 valL = 0; + if (aArrayIndex < 32) + { + valL = 1 << aArrayIndex; + } + else + { + valH = 1 << (aArrayIndex-32); + } + + TBool ret = (poolMapH & valH) || (poolMapL & valL); + + return (ret); +} + +// --------------------------------------------------------------------- +// CPcsCache::GetURI +// +// --------------------------------------------------------------------- +TDesC& CPcsCache::GetURI() +{ + return (*iURI); +} + +// --------------------------------------------------------------------- +// CPcsCache::SetDataFields +// +// --------------------------------------------------------------------- +void CPcsCache::SetDataFields(RArray& aDataFields) +{ + for (TInt i(0); i < aDataFields.Count(); i++) + { + iDataFields.Append(aDataFields[i]); + } +} + +// --------------------------------------------------------------------- +// CPcsCache::GetDataFields +// +// --------------------------------------------------------------------- +void CPcsCache::GetDataFields(RArray& aDataFields) +{ + for (TInt i(0); i < iDataFields.Count(); i++) + { + aDataFields.Append(iDataFields[i]); + } +} + +// --------------------------------------------------------------------- +// CPcsCache::UpdateCacheStatus +// +// --------------------------------------------------------------------- +void CPcsCache::UpdateCacheStatus(TInt aStatus) +{ + iCacheStatus = aStatus; +} + +// --------------------------------------------------------------------- +// CPcsCache::GetCacheStatus +// +// --------------------------------------------------------------------- +TInt CPcsCache::GetCacheStatus() +{ + return iCacheStatus; +} + +// --------------------------------------------------------------------- +// CPcsCache::GetUriId +// +// --------------------------------------------------------------------- +TUint8 CPcsCache::GetUriId() +{ + return iUriId; +} + +// --------------------------------------------------------------------- +// CPcsCache::SetSortOrder +// +// --------------------------------------------------------------------- +void CPcsCache::SetSortOrder(RArray& aSortOrder) +{ + PRINT ( _L("Enter CPcsCache::SetSortOrder") ); + + iSortOrder.Reset(); + + for (TInt i(0); i < aSortOrder.Count(); i++) + { + iSortOrder.Append(aSortOrder[i]); + } + + ComputeIndexOrder(); + + PRINT ( _L("End CPcsCache::SetSortOrder") ); +} + +// --------------------------------------------------------------------- +// CPcsCache::GetSortOrder +// +// --------------------------------------------------------------------- +void CPcsCache::GetSortOrder(RArray& aSortOrder) +{ + aSortOrder.Reset(); + + for (TInt i(0); i < iSortOrder.Count(); i++) + { + aSortOrder.Append(iSortOrder[i]); + } +} + +// --------------------------------------------------------------------- +// CPcsCache::GetIndexOrder +// +// --------------------------------------------------------------------- +void CPcsCache::GetIndexOrder(RArray& aIndexOrder) +{ + aIndexOrder.Reset(); + + for (TInt i(0); i < iIndexOrder.Count(); i++) + { + aIndexOrder.Append(iIndexOrder[i]); + } +} + +// --------------------------------------------------------------------- +// CPcsCache::ComputeIndexOrder +// +// --------------------------------------------------------------------- +void CPcsCache::ComputeIndexOrder() +{ + iIndexOrder.Reset(); + + for ( TInt i = 0; i < iSortOrder.Count(); i++ ) + { + for ( TInt j = 0; j < iDataFields.Count(); j++ ) + { + if ( iSortOrder[i] == iDataFields[j] ) + { + iIndexOrder.Append(j); + break; + } + } + } +} + +// --------------------------------------------------------------------- +// CPcsCache::ResortdataInPools +// +// --------------------------------------------------------------------- +void CPcsCache::ResortdataInPoolsL() + { + // Copy iMasterPool data into iMasterPoolBackup + for (TInt i = 0; i < iMasterPool.Count(); i++ ) + { + iMasterPoolBackup.Append( iMasterPool[i] ); + } + + // Now reset the key array + for (TInt i = 0; i < iKeyArr.Count(); i++ ) + { + iKeyArr[i]->ResetAndDestroy(); + } + iMasterPool.Reset(); + iCacheInfo.Close(); + if ( iAdaptiveGridMap ) + { + iAdaptiveGridMap->Reset(); + } + + // Now add data again from the iMasterPoolBackup + for (TInt i = 0; i < iMasterPoolBackup.Count(); i++ ) + { + CPsData* temp = iMasterPoolBackup[i]; + AddToCacheL( *temp ); + } + iMasterPoolBackup.Reset(); + } + +// --------------------------------------------------------------------- +// CPcsCache::GridItemSelectorL +// +// --------------------------------------------------------------------- +TUint CPcsCache::GridItemSelector( TInt aIndex, TBool& aUnnamed ) + { + __ASSERT_ALWAYS( iDataFields.Count() > aIndex, User::Panic(_L("CPcsCache"), KErrArgument ) ); + + if ( iDataFields[aIndex] == R_VPBK_FIELD_TYPE_LASTNAME || iDataFields[aIndex] == R_VPBK_FIELD_TYPE_FIRSTNAME ) + { + aUnnamed = EFalse; + return CPcsAdaptiveGridItem::EFirstNameLastName; + } + else if ( iDataFields[aIndex] == R_VPBK_FIELD_TYPE_COMPANYNAME && !aUnnamed ) + { + return CPcsAdaptiveGridItem::ECompanyName; + } + else if ( iDataFields[aIndex] == R_VPBK_FIELD_TYPE_COMPANYNAME ) + { + return CPcsAdaptiveGridItem::EUnnamedCompanyName; + } + else + { + return CPcsAdaptiveGridItem::ENumberCounters; + } + } + +// End of file