predictivesearch/PcsAlgorithm/Algorithm2/src/CPcsCache.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 13 Oct 2010 14:15:33 +0300
branchRCL_3
changeset 85 38bb213f60ba
parent 68 9da50d567e3c
permissions -rw-r--r--
Revision: 201039 Kit: 201041

/*
* 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 <MVPbkContactLink.h>

#include "FindUtilChineseECE.h"
#include "CPsData.h"
#include "CPcsCache.h"
#include "CPcsDebug.h"
#include "CWords.h"
#include "CPcsAlgorithm2Utils.h"
#include "CPcsAlgorithm2.h"

// ============================== MEMBER FUNCTIONS ============================

// ----------------------------------------------------------------------------
// CPcsCache::NewL
// Two Phase Construction
// ----------------------------------------------------------------------------
CPcsCache* CPcsCache::NewL(CPcsAlgorithm2* aAlgorithm, TDesC& aURI, 
                           CPcsKeyMap& aKeyMap, TUint8 aUriId)
    {
    PRINT ( _L("Enter CPcsCache::NewL") );

    CPcsCache* instance = new (ELeave) CPcsCache();

    CleanupStack::PushL(instance);

    instance->ConstructL(aAlgorithm, 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(CPcsAlgorithm2* aAlgorithm, TDesC& aURI, 
                           CPcsKeyMap& aKeyMap, TUint8 aUriId)
    {
    PRINT ( _L("Enter CPcsCache::ConstructL") );
    iAlgorithm = aAlgorithm;

    iURI = aURI.AllocL();
    iUriId = aUriId;
    //Update the caching status for this cache
    iCacheStatus = ECachingNotStarted;

    keyMap = &aKeyMap;

    // Populate keyArr
    for (TInt i = 0; i < aKeyMap.PoolCount(); i++)
        {
        RPointerArray<CPcsPoolElement> *keyMap = new (ELeave) RPointerArray<CPcsPoolElement> (1);
        keyArr.InsertL(keyMap, i);
        }

    PRINT ( _L("End CPcsCache::ConstructL") );
    }

// ----------------------------------------------------------------------------
// CPcsCache::~CPcsCache
// Destructor
// ----------------------------------------------------------------------------
CPcsCache::~CPcsCache()
    {
    PRINT ( _L("Enter CPcsCache::~CPcsCache") );

    if (iURI)
        {
        delete iURI;
        }

    // Loop thru cache info and free and the data elements
    THashMapIter<TInt, TInt> iter(cacheInfo);

    do
        {
        TInt* id = const_cast<TInt*> (iter.NextKey());

        if (id == NULL)
            break;

        TInt* poolMap = iter.CurrentValue();

        if (poolMap == NULL)
            {
            continue;
            }

        CPsData *data = NULL;
        for (int keyIndex = 0; keyIndex <= keyArr.Count(); keyIndex++)
            {
            TBool present = GetPoolMap(*poolMap, keyIndex);

            if (!present)
                {
                continue;
                }

            RPointerArray<CPcsPoolElement> tmpKeyMap = *(keyArr[keyIndex]);
            for (int arrayIndex = 0; arrayIndex < tmpKeyMap.Count(); arrayIndex++)
                {
                CPcsPoolElement *element = tmpKeyMap[arrayIndex];
                TInt localId = element->GetPsData()->Id();
                if (*id == localId)
                    {
                    data = element->GetPsData();
                    delete element;
                    keyArr[keyIndex]->Remove(arrayIndex);
                    }
                }
            };

        // Remove this element from master pool
        for (int arrayIndex = 0; arrayIndex < masterPool.Count(); arrayIndex++)
            {
            CPsData *dataElement = masterPool[arrayIndex];
            TInt localId = dataElement->Id();
            if (*id == localId)
                {
                masterPool.Remove(arrayIndex);
                }
            }

        if (data)
            {
            delete data;
            }

        }
    while (1);

    for (TInt i = 0; i < keyArr.Count(); i++)
        {
        keyArr[i]->ResetAndDestroy();
        delete keyArr[i];
        keyArr[i] = NULL;
        }

    masterPool.ResetAndDestroy();

    cacheInfo.Close();

    keyArr.Reset();
    iDataFields.Reset();
    iSortOrder.Reset();
    iIndexOrder.Reset();

    PRINT ( _L("End CPcsCache::~CPcsCache") );
    }

// ----------------------------------------------------------------------------
// CPcsCache::GetContactsForKeyL
// Get list of pool elements specific to a pool
// ----------------------------------------------------------------------------     
void CPcsCache::GetContactsForKeyL(TInt aKeyId, RPointerArray<CPcsPoolElement>& aData)
    {
    PRINT ( _L("Enter CPcsCache::GetContactsForKeyL") );
    CleanupClosePushL( aData );
    RPointerArray<CPcsPoolElement> arr = *keyArr[aKeyId];
    for (int i = 0; i < arr.Count(); i++)
        {
        CPcsPoolElement* value = arr[i];
        aData.AppendL(value);
        }

    CleanupStack::Pop();
    PRINT ( _L("End CPcsCache::GetContactsForKeyL") );
    }

// ----------------------------------------------------------------------------
// CPcsCache::GetAllContentsL
// Get all data elements in this cache
// ----------------------------------------------------------------------------     
void CPcsCache::GetAllContentsL(RPointerArray<CPsData>& aData)
    {
    PRINT ( _L("Enter CPcsCache::GetAllContentsL") );
    CleanupClosePushL( aData );
    for (int i = 0; i < masterPool.Count(); i++)
        {
        CPsData* value = masterPool[i];
        aData.AppendL(value);
        }
    CleanupStack::Pop();
    PRINT ( _L("End CPcsCache::GetAllContentsL") );
    }

// ----------------------------------------------------------------------------
// CPcsCache::AddToPool
// Adds a contact to cache
// ----------------------------------------------------------------------------
void CPcsCache::AddToPoolL(TInt& 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<TInt, TInt> elementHash;
    TLinearOrder<CPcsPoolElement> rule(CPcsPoolElement::CompareByData);

    // Parse thru each data element    
    for (int dataIndex = 0; dataIndex < aData.DataElementCount(); dataIndex++)
        {
        // Stores first key for each word
        RArray<TChar> firstKey;

        // Recover the first character
        if (aData.Data(dataIndex) && aData.Data(dataIndex)->Length() != 0)
            {
            // Split the data into words	
            CWords* words = CWords::NewLC(*aData.Data(dataIndex));

            // Store the first numeric key for each word
            for (int i = 0; i < words->MdcaCount(); i++)
                {
                TChar firstChar;
                for (int j = 0; j < words->MdcaPoint(i).Length(); j++)
                    {
                    firstChar = (words->MdcaPoint(i))[j];
                    TBuf<20> word;
                    word.Append(firstChar);
                    if (iAlgorithm->FindUtilECE()->IsChineseWord(word))
                        {
                        RPointerArray<HBufC> spellList;
                        if (iAlgorithm->FindUtilECE()->T9ChineseTranslationL(firstChar, spellList))
                            {
                            for (int j = 0; j < spellList.Count(); j++)
                                {
                                firstKey.Append(keyMap->KeyForCharacter(*(spellList[j]->Ptr())));
                                }
                            }
                        else
                            {
                            firstKey.Append( keyMap->KeyForCharacter(firstChar));
                            }
                        spellList.ResetAndDestroy();
                        }
                    else
                        {
                        firstKey.Append(keyMap->KeyForCharacter(firstChar));
                        }
                    }
                }

            CleanupStack::PopAndDestroy(words);
            }

        for (TInt wordIndex = 0; wordIndex < firstKey.Count(); wordIndex++)
            {
            TInt arrayIndex = keyMap->PoolIdForCharacter(firstKey[wordIndex]);

            CPcsPoolElement* element = NULL;

            // Check if an element already exists in the pool for this data
            TInt* loc = NULL;
            loc = elementHash.Find(arrayIndex);
            if (loc != NULL)
                {
                // Exists. Then recover ...
                RPointerArray<CPcsPoolElement> tmpKeyMap = *(keyArr[arrayIndex]);
                element = tmpKeyMap[*loc];
                }

            if (element == NULL) // Pool element doesn't exist. Create new ...
                {
                element = CPcsPoolElement::NewL(aData);
                element->ClearDataMatchAttribute();
                element->SetDataMatch(dataIndex);

                // Insert to pool
                keyArr[arrayIndex]->InsertInOrderAllowRepeatsL(element, rule);
                TInt index = keyArr[arrayIndex]->FindInOrderL(element, rule);

                // Set the bit for this pool					
                SetPoolMap(aPoolMap, arrayIndex);

                // Store the array index in the temp hash
                elementHash.InsertL(arrayIndex, index);
                }
            else // Pool element exists. Just alter the data match attribute
                {
                element->SetDataMatch(dataIndex);

                // Set the bit for this pool					
                SetPoolMap(aPoolMap, arrayIndex);
                }

            } // for 2 loop

        firstKey.Reset();

        } // for 1 loop

    elementHash.Close();
    }

// ---------------------------------------------------------------------
// CPcsCache::AddToCacheL
// 
// ---------------------------------------------------------------------
void CPcsCache::AddToCacheL(CPsData& aData)
    {
    // Protect against duplicate items getting added
    if (cacheInfo.Find(aData.Id()) != NULL)
        {
        return;
        }

    // Include this element in the pool     
    TInt poolMap = 0;
    AddToPoolL(poolMap, aData);
    cacheInfo.InsertL(aData.Id(), poolMap);

    // Include this element in master pool        
    TLinearOrder<CPsData> rule(CPcsAlgorithm2Utils::CompareDataBySortOrder);
    masterPool.InsertInOrderAllowRepeatsL(&aData, rule);
    }

// ---------------------------------------------------------------------
// CPcsCache::RemoveContactL
// 
// ---------------------------------------------------------------------
void CPcsCache::RemoveFromCacheL(TInt aItemId)
    {
    CPsData *data = NULL;

    TInt* poolMap = cacheInfo.Find(aItemId);

    if (poolMap == NULL)
        {
        return;
        }

    // Remove this element from pools
    for (int keyIndex = 0; keyIndex <= keyArr.Count(); keyIndex++)
        {
        TBool present = GetPoolMap(*poolMap, keyIndex);

        if (!present)
            {
            continue;
            }

        RPointerArray<CPcsPoolElement> tmpKeyMap = *(keyArr[keyIndex]);
        for (int arrayIndex = 0; arrayIndex < tmpKeyMap.Count(); arrayIndex++)
            {
            CPcsPoolElement *element = tmpKeyMap[arrayIndex];
            TInt id = element->GetPsData()->Id();
            if (id == aItemId)
                {
                data = element->GetPsData();
                delete element;
                keyArr[keyIndex]->Remove(arrayIndex);
                }
            }
        }

    // Remove this element from master pool
    for (int arrayIndex = 0; arrayIndex < masterPool.Count(); arrayIndex++)
        {
        CPsData *dataElement = masterPool[arrayIndex];
        TInt id = dataElement->Id();
        if (id == aItemId)
            {
            masterPool.Remove(arrayIndex);
            }
        }

    // Delete data 
    if (data)
        {
        delete data;
        data = NULL;
        }

    // Clear up cache information
    cacheInfo.Remove(aItemId);
    }

// ---------------------------------------------------------------------
// CPcsCache::RemoveAllFromCacheL
// 
// ---------------------------------------------------------------------
void CPcsCache::RemoveAllFromCacheL()
    {
    PRINT ( _L("Enter CPcsCache::RemoveAllFromCacheL") );

    for (TInt i = 0; i < keyArr.Count(); i++)
        {
        keyArr[i]->ResetAndDestroy();

        }

    masterPool.ResetAndDestroy();
    cacheInfo.Close();

    PRINT ( _L("End CPcsCache::RemoveAllFromCacheL") );
    }

// ---------------------------------------------------------------------
// CPcsCache::SetPoolMap
// 
// ---------------------------------------------------------------------
void CPcsCache::SetPoolMap(TInt& aPoolMap, TInt arrayIndex)
    {
    TReal val;
    Math::Pow(val, 2, arrayIndex);

    aPoolMap |= (TInt) val;
    }

// ---------------------------------------------------------------------
// CPcsCache::GetPoolMap
// 
// ---------------------------------------------------------------------
TBool CPcsCache::GetPoolMap(TInt& aPoolMap, TInt arrayIndex)
    {
    TReal val;
    Math::Pow(val, 2, arrayIndex);

    return (aPoolMap & (TInt) val);
    }

// ---------------------------------------------------------------------
// CPcsCache::GetURI
// 
// ---------------------------------------------------------------------
TDesC& CPcsCache::GetURI()
    {
    return (*iURI);
    }

// ---------------------------------------------------------------------
// CPcsCache::SetDataFields
// 
// ---------------------------------------------------------------------
void CPcsCache::SetDataFields(RArray<TInt>& aDataFields)
    {
    for (TInt i(0); i < aDataFields.Count(); i++)
        {
        iDataFields.Append(aDataFields[i]);
        }
    }

// ---------------------------------------------------------------------
// CPcsCache::GetDataFields
// 
// ---------------------------------------------------------------------
void CPcsCache::GetDataFields(RArray<TInt>& 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::GetUri
// 
// ---------------------------------------------------------------------
HBufC* CPcsCache::GetUri()
    {
    return iURI;
    }

// ---------------------------------------------------------------------
// CPcsCache::SetSortOrder
// 
// ---------------------------------------------------------------------
void CPcsCache::SetSortOrder(RArray<TInt>& 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<TInt>& aSortOrder)
    {
    aSortOrder.Reset();

    for (TInt i(0); i < iSortOrder.Count(); i++)
        {
        aSortOrder.Append(iSortOrder[i]);
        }
    }

// ---------------------------------------------------------------------
// CPcsCache::GetIndexOrder
// 
// ---------------------------------------------------------------------
void CPcsCache::GetIndexOrder(RArray<TInt>& aIndexOrder)
    {
    aIndexOrder.Reset();

    for (TInt i(0); i < iIndexOrder.Count(); i++)
        {
        aIndexOrder.Append(iIndexOrder[i]);
        }
    }

// ---------------------------------------------------------------------
// CPcsCache::ComputeIndexOrder
// 
// ---------------------------------------------------------------------
void CPcsCache::ComputeIndexOrder()
    {
    iIndexOrder.Reset();

    for (int i = 0; i < iSortOrder.Count(); i++)
        {
        for (int j = 0; j < iDataFields.Count(); j++)
            {
            if (iSortOrder[i] == iDataFields[j])
                {
                iIndexOrder.Append(j);
                break;
                }
            }
        }
    }

// ---------------------------------------------------------------------
// CPcsCache::ResortdataInPools
// 
// ---------------------------------------------------------------------
void CPcsCache::ResortdataInPoolsL()
    {
    // copy masterPool data into masterPoolBackup
    for (TInt i = 0; i < masterPool.Count(); i++ )
        {
        masterPoolBackup.Append( masterPool[i] );
        }
    //Now reset the key array
    for (TInt i = 0; i < keyArr.Count(); i++ )
        {
        keyArr[i]->ResetAndDestroy();
        }
    masterPool.Reset();
    cacheInfo.Close();
    //now add data again from the masterPoolBackup
    for (TInt i = 0; i < masterPoolBackup.Count(); i++ )
        {
        CPsData* temp = static_cast<CPsData*>(masterPoolBackup[i]);
        AddToCacheL( *temp );
        }
    masterPoolBackup.Reset();
    } 
// End of file