--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/msgcommonutils/src/contactmatcher.cpp Mon Jan 18 20:36:02 2010 +0200
@@ -0,0 +1,1239 @@
+/*
+* Copyright (c) 2005-2006 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: CContactMatcher class implementation
+*
+*/
+
+
+
+// System includes
+#include <e32base.h>
+#include <bamdesca.h>
+#include <cntitem.h>
+#include <eikenv.h>
+#include <bautils.h>
+#include <data_caging_path_literals.hrh>
+
+#include <contactmatcher.h>
+
+#include <CVPbkContactManager.h>
+#include <MVPbkContactStoreList.h>
+#include <MVPbkContactStore.h>
+#include <CVPbkContactStoreUriArray.h>
+#include <MVPbkContactLinkArray.h>
+#include <MVPbkContactLink.h>
+#include <MVPbkFieldType.h>
+#include <MVPbkStoreContact.h>
+#include <MVPbkStoreContactField.h>
+#include <MVPbkStoreContactFieldCollection.h>
+#include <MVPbkContactFieldData.h>
+#include <MVPbkContactFieldTextData.h>
+#include <MVPbkContactFieldDateTimeData.h>
+#include <MVPbkContactFieldBinaryData.h>
+#include <MVPbkContactOperationBase.h>
+#include <MVPbkContactStoreProperties.h>
+#include <TVPbkContactStoreUriPtr.h>
+#include <VPbkContactStoreUris.h>
+#include <MPbk2ContactNameFormatter.h>
+#include <CVPbkFieldTypeSelector.h>
+#include <TVPbkFieldVersitProperty.h>
+#include <CVPbkFieldTypeRefsList.h>
+
+#include <coemain.h>
+#include <CPbk2SortOrderManager.h>
+#include <Pbk2ContactNameFormatterFactory.h>
+
+#include <msgcommonutils.rsg>
+
+
+// ================= Static Constant Data ===================
+
+typedef const TDesC& (*UriFuncPtr)();
+
+// Number match store URIs in priority order.
+// When doing number matching, order of the stores in the uri array will
+// determine which stores are searched first (sequential match). We stop
+// the search when first match is found.
+static const UriFuncPtr NumberMatchStoreUris[] =
+ {
+ VPbkContactStoreUris::DefaultCntDbUri,
+ // If we don't manage to open some store, we remove it from our array
+ VPbkContactStoreUris::SimGlobalAdnUri,
+ VPbkContactStoreUris::SimGlobalSdnUri,
+ NULL, // end marker
+ };
+
+// All store URIs except own number store
+static const UriFuncPtr AllStoreUris[] =
+ {
+ VPbkContactStoreUris::DefaultCntDbUri,
+ // If we don't manage to open some store, we remove it from our array
+ VPbkContactStoreUris::SimGlobalAdnUri,
+ VPbkContactStoreUris::SimGlobalSdnUri,
+ VPbkContactStoreUris::SimGlobalFdnUri,
+ NULL, // end marker
+ };
+
+// Own number store URIs
+static const UriFuncPtr OwnNumberStoreUris[] =
+ {
+ VPbkContactStoreUris::SimGlobalOwnNumberUri,
+ NULL, // end marker
+ };
+
+_LIT(KMsgCommonUtilsResourceFileName, "msgcommonutils.rsc");
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ----------------------------------------------------------------------------
+// Two-phase constructor for CContactMatcher class.
+// ----------------------------------------------------------------------------
+EXPORT_C CContactMatcher* CContactMatcher::NewL(
+ RFs* aFsSession )
+ {
+ CContactMatcher* self = CContactMatcher::NewLC( aFsSession );
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+// ----------------------------------------------------------------------------
+// Two-phase constructor for CContactMatcher class.
+// ----------------------------------------------------------------------------
+EXPORT_C CContactMatcher* CContactMatcher::NewLC(
+ RFs* aFsSession )
+ {
+ CContactMatcher* self = new ( ELeave ) CContactMatcher( aFsSession );
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+// ----------------------------------------------------------------------------
+// C++ destructor.
+// ----------------------------------------------------------------------------
+EXPORT_C CContactMatcher::~CContactMatcher()
+ {
+ FreeOldOperation();
+ CleanupNumberMatch();
+ delete iStoreUris;
+ delete iContactManager;
+ delete iSortOrderManager;
+ delete iNameFormatter;
+ iResourceFile.Close();
+
+ if ( iClientStatus )
+ {
+ User::RequestComplete( iClientStatus, KErrCancel );
+ }
+ if ( iASchedulerWait.IsStarted() )
+ {
+ iASchedulerWait.AsyncStop();
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// C++ Constructor.
+// ----------------------------------------------------------------------------
+CContactMatcher::CContactMatcher( RFs* aFsSession) : iFsSession( aFsSession )
+ {
+ }
+
+// ----------------------------------------------------------------------------
+// Second phase constructor
+// ----------------------------------------------------------------------------
+void CContactMatcher::ConstructL()
+ {
+ iContactManager = CVPbkContactManager::NewL(
+ *CVPbkContactStoreUriArray::NewLC(), iFsSession );
+ CleanupStack::PopAndDestroy(); // CVPbkContactStoreUriArray
+
+ // No stores open yet
+ iStoreUris = CVPbkContactStoreUriArray::NewL();
+ }
+
+//******************* API-methods *********************************************
+
+// ----------------------------------------------------------------------------
+// Synchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CContactMatcher::OpenStoreL(
+ const CVPbkContactStoreUriArray& aUriArray )
+ {
+ InitOperationL( EOpenStore );
+ OpenStoreCommonL( aUriArray );
+ if ( iApiMethodStatus != EFinished )
+ {
+ iApiMethodStatus = EExecuting;
+ // Wait until stores are open
+ iASchedulerWait.Start();
+ }
+ User::LeaveIfError( iError );
+ }
+
+// ----------------------------------------------------------------------------
+// Asynchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CContactMatcher::OpenStoreL(
+ const CVPbkContactStoreUriArray& aUriArray, TRequestStatus& aStatus )
+ {
+ InitOperationL( EOpenStore );
+ OpenStoreCommonL( aUriArray );
+ InitOperation( &aStatus );
+
+ if ( iApiMethodStatus != EFinished )
+ {
+ iApiMethodStatus = EExecuting;
+ }
+ }
+
+
+// ----------------------------------------------------------------------------
+// Common code to sync/async versions.
+// ----------------------------------------------------------------------------
+void CContactMatcher::OpenStoreCommonL(
+ const CVPbkContactStoreUriArray& aUriArray )
+ {
+ if (iStoreUris->Count())
+ {
+ // Opening more stores when some stores are already open is not
+ // supported. Support would require managing iStoreUris properly
+ // so that it contains all open stores.
+ User::Leave(KErrGeneral);
+ }
+
+ const TInt count = aUriArray.Count();
+
+ for (TInt i = 0; i < count; ++i)
+ {
+ // Appended Uri:s to the array. If store fails to open it is removed
+ // from the array. This keeps Uri's in priority order in the array.
+ TVPbkContactStoreUriPtr uriPtr = aUriArray[i];
+ iStoreUris->AppendL( uriPtr );
+
+ iContactManager->LoadContactStoreL( uriPtr );
+ }
+ MVPbkContactStoreList& storeList = iContactManager->ContactStoresL();
+ storeList.OpenAllL( *this );
+ }
+
+// ----------------------------------------------------------------------------
+// Synchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CContactMatcher::OpenAllStoresL()
+ {
+ OpenStoreL(AllStoreUris);
+ }
+
+// ----------------------------------------------------------------------------
+// Asynchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CContactMatcher::OpenAllStoresL( TRequestStatus& aStatus )
+ {
+ OpenStoreL(AllStoreUris, aStatus);
+ }
+
+// ----------------------------------------------------------------------------
+// Synchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CContactMatcher::OpenDefaultMatchStoresL()
+ {
+ OpenStoreL(NumberMatchStoreUris);
+ }
+
+// ----------------------------------------------------------------------------
+// Asynchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CContactMatcher::OpenDefaultMatchStoresL( TRequestStatus& aStatus )
+ {
+ OpenStoreL(NumberMatchStoreUris, aStatus);
+ }
+
+// ----------------------------------------------------------------------------
+// Open OwnNumber stores.
+// Synchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CContactMatcher::OpenOwnNumberStoresL()
+ {
+ OpenStoreL(OwnNumberStoreUris);
+ }
+
+// ----------------------------------------------------------------------------
+// Open OwnNumber stores.
+// Asynchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CContactMatcher::OpenOwnNumberStoresL( TRequestStatus& aStatus )
+ {
+ OpenStoreL(OwnNumberStoreUris, aStatus);
+ }
+
+// ----------------------------------------------------------------------------
+// Close all open stores.
+// ----------------------------------------------------------------------------
+EXPORT_C void CContactMatcher::CloseStoresL()
+ {
+ // Closing stores does not work. MatchDataL() finds contacts from
+ // closed stores.
+
+ InitOperationL( ECloseStores );
+
+ iApiMethodStatus = EExecuting;
+ TRAPD( err, iContactManager->ContactStoresL().CloseAll( *this ) );
+ iApiMethodStatus = EFinished;
+ if ( err == KErrNone)
+ {
+ delete iStoreUris; iStoreUris = NULL;
+ iStoreUris = CVPbkContactStoreUriArray::NewL();
+ }
+ else
+ {
+ User::Leave(err);
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// Synchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CContactMatcher::MatchPhoneNumberL(
+ const TDesC& aData, TInt aDigits,
+ CVPbkPhoneNumberMatchStrategy::TVPbkPhoneNumberMatchFlags aFlags,
+ CVPbkContactLinkArray& aLinkArray )
+ {
+ InitOperationL( EMatchPhoneNumber );
+ iResultContactLinkArray = &aLinkArray;
+
+ // Start asynchronous matching and wait until results are ready
+ MatchPhoneNumberCommonL( aData, aDigits, aFlags );
+ if ( iApiMethodStatus != EFinished )
+ {
+ iApiMethodStatus = EExecuting;
+ iASchedulerWait.Start();
+ }
+ User::LeaveIfError( iError );
+ }
+
+
+// ----------------------------------------------------------------------------
+// Asynchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CContactMatcher::MatchPhoneNumberL(
+ const TDesC& aData, TInt aDigits,
+ CVPbkPhoneNumberMatchStrategy::TVPbkPhoneNumberMatchFlags aFlags,
+ CVPbkContactLinkArray& aLinkArray, TRequestStatus& aStatus )
+ {
+ InitOperationL( EMatchPhoneNumber );
+ iResultContactLinkArray = &aLinkArray;
+ // Start asynchronous matching
+ MatchPhoneNumberCommonL( aData, aDigits, aFlags );
+ InitOperation( &aStatus );
+ if ( iApiMethodStatus != EFinished )
+ {
+ iApiMethodStatus = EExecuting;
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// Common code for sync and async versions
+// ----------------------------------------------------------------------------
+void CContactMatcher::MatchPhoneNumberCommonL(
+ const TDesC& aData, TInt aDigits,
+ CVPbkPhoneNumberMatchStrategy::TVPbkPhoneNumberMatchFlags aFlags )
+ {
+ // Delete resources allocated for previous match
+ CleanupNumberMatch();
+
+ // iStoreUris is filled when stores are opened
+
+ iStratConfig = new (ELeave) CVPbkPhoneNumberMatchStrategy::TConfig(
+ aDigits,
+ *iStoreUris,
+ CVPbkPhoneNumberMatchStrategy::EVPbkSequentialMatch,
+ aFlags);
+ iMatchStrategy = CVPbkPhoneNumberMatchStrategy::NewL(
+ *iStratConfig,
+ *iContactManager,
+ *this);
+ // Start asynchronous matching
+ iMatchStrategy->MatchL( aData );
+ }
+
+
+// ----------------------------------------------------------------------------
+// Find from a store succeeded
+// ----------------------------------------------------------------------------
+void CContactMatcher::FindFromStoreSucceededL( MVPbkContactStore& /*aStore*/,
+ MVPbkContactLinkArray* aResultsFromStore )
+ {
+ __ASSERT_DEBUG( aResultsFromStore, ContactMatcherPanics::Panic(
+ ContactMatcherPanics::EPanNullPointer ));
+
+ // Take the ownership of the result immediately
+ CleanupDeletePushL( aResultsFromStore );
+
+ CopyFindResultsL( aResultsFromStore );
+
+ CleanupStack::PopAndDestroy(); // aResultsFromStore
+ }
+
+// ----------------------------------------------------------------------------
+// Copy the found results for a store into array
+// ----------------------------------------------------------------------------
+void CContactMatcher::CopyFindResultsL( MVPbkContactLinkArray*
+ aResults )
+ {
+ const TInt count = aResults->Count();
+ if ( iResultContactLinkArray )
+ {
+ // Copy links to the member array
+ for ( TInt i = 0; i < count; ++i )
+ {
+ iResultContactLinkArray->AppendL( aResults->At( i ).CloneLC() );
+ CleanupStack::Pop(); // cloned link
+ }
+ }
+ else
+ {
+ iResultContactLinkCnt += count;
+ }
+ }
+
+
+// ----------------------------------------------------------------------------
+// Find failed
+// ----------------------------------------------------------------------------
+void CContactMatcher::FindFromStoreFailed( MVPbkContactStore& /*aStore*/, TInt /*aError*/ )
+ {
+ //no operation, search to continue from the other stores
+ }
+
+
+// ----------------------------------------------------------------------------
+// Find complete
+// ----------------------------------------------------------------------------
+void CContactMatcher::FindFromStoresOperationComplete()
+ {
+ if (!iResultContactLinkArray)
+ {
+ // Links were not copied. Result is whether any links found or not.
+ OperationComplete( iResultContactLinkCnt ? KErrNone:KErrNotFound );
+ }
+ else
+ {
+ OperationComplete();
+ iResultContactLinkArray = NULL;
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// Return global list of field types.
+// ----------------------------------------------------------------------------
+EXPORT_C const MVPbkFieldTypeList& CContactMatcher::FieldTypes() const
+ {
+ return iContactManager->FieldTypes();
+ }
+
+// ----------------------------------------------------------------------------
+// Synchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CContactMatcher::GetStoreContactL(
+ const MVPbkContactLink& aLink, MVPbkStoreContact** aStoreContact )
+ {
+ InitOperationL( EGetStoreContact );
+ iResultStoreContact = aStoreContact;
+
+ // Start asynchronous operation and wait until results are ready
+ FreeOldOperation();
+ iOperation = iContactManager->RetrieveContactL( aLink, *this );
+ if ( iApiMethodStatus != EFinished )
+ {
+ iApiMethodStatus = EExecuting;
+ iASchedulerWait.Start();
+ }
+ User::LeaveIfError( iError );
+ }
+
+// ----------------------------------------------------------------------------
+// Asynchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CContactMatcher::GetStoreContactL(
+ const MVPbkContactLink& aLink, MVPbkStoreContact** aStoreContact,
+ TRequestStatus& aStatus )
+ {
+ InitOperationL( EGetStoreContact );
+ iResultStoreContact = aStoreContact;
+ // Start asynchronous operation
+ FreeOldOperation();
+ iOperation = iContactManager->RetrieveContactL( aLink, *this );
+ InitOperation( &aStatus );
+ if ( iApiMethodStatus != EFinished )
+ {
+ iApiMethodStatus = EExecuting;
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// Synchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CContactMatcher::IsOwnNumberL( const TDesC& aNumber, TBool& aResult )
+ {
+ InitOperationL( EMatchPhoneNumber );
+
+ // Not interested in links, only whether found or not
+ iResultContactLinkArray = NULL;
+ iResultContactLinkCnt = 0;
+
+ // Start asynchronous matching and wait until results are ready
+ MatchPhoneNumberCommonL( aNumber, aNumber.Length(),
+ CVPbkPhoneNumberMatchStrategy::EVPbkStopOnFirstMatchFlag );
+ if ( iApiMethodStatus != EFinished )
+ {
+ iApiMethodStatus = EExecuting;
+ iASchedulerWait.Start();
+ }
+ User::LeaveIfError( iError );
+
+ aResult = iResultContactLinkCnt > 0;
+ }
+
+// ----------------------------------------------------------------------------
+// Asynchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CContactMatcher::IsOwnNumberL( const TDesC& aNumber,
+ TRequestStatus& aStatus )
+ {
+ InitOperationL( EMatchPhoneNumber );
+
+ // Not interested in links, only whether found or not
+ iResultContactLinkArray = NULL;
+ iResultContactLinkCnt = 0;
+
+ // Start asynchronous matching
+ MatchPhoneNumberCommonL( aNumber, aNumber.Length(),
+ CVPbkPhoneNumberMatchStrategy::EVPbkStopOnFirstMatchFlag );
+ InitOperation( &aStatus );
+ if ( iApiMethodStatus != EFinished )
+ {
+ iApiMethodStatus = EExecuting;
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// Cancel asynchronous operation
+// ----------------------------------------------------------------------------
+EXPORT_C void CContactMatcher::CancelOperation()
+ {
+ if (iApiMethodStatus != EExecuting)
+ {
+ return;
+ }
+
+ __ASSERT_DEBUG(!iSync, ContactMatcherPanics::Panic(
+ ContactMatcherPanics::EPanInvalidOp));
+
+ switch(iApiMethod)
+ {
+ case EMatchData:
+ case EGetStoreContact:
+ FreeOldOperation(); // deleting the operation cancels it
+ break;
+ case EMatchPhoneNumber:
+ CleanupNumberMatch();
+ break;
+ default:
+ ;
+ }
+
+ User::RequestComplete( iClientStatus, KErrCancel );
+
+ iApiMethod = ENoMethod;
+ iApiMethodStatus = EFinished;
+ }
+
+// ----------------------------------------------------------------------------
+// GetFieldData, for EVPbkFieldStorageTypeText
+// ----------------------------------------------------------------------------
+EXPORT_C TPtrC CContactMatcher::GetFieldDataTextL(
+ const MVPbkStoreContact& aContact,
+ const MVPbkFieldType& aFType ) const
+ {
+ TPtrC ret(KNullDesC);
+ const MVPbkStoreContactField* field = FindField( aContact, aFType);
+ if (field)
+ {
+ const MVPbkContactFieldData& fdata = field->FieldData();
+ if (fdata.DataType() == EVPbkFieldStorageTypeText)
+ {
+ const MVPbkContactFieldTextData& fdata2 =
+ MVPbkContactFieldTextData::Cast(fdata);
+ ret.Set( fdata2.Text() );
+ }
+ else
+ {
+ User::Leave( KErrArgument );
+ }
+ }
+ return ret;
+ }
+
+// ----------------------------------------------------------------------------
+// GetFieldData, for EVPbkFieldStorageTypeDateTime
+// ----------------------------------------------------------------------------
+EXPORT_C TTime CContactMatcher::GetFieldDataDateTimeL(
+ const MVPbkStoreContact& aContact,
+ const MVPbkFieldType& aFType ) const
+ {
+ // YYYYMMDD:HHMMSS.MMMMMM
+ _LIT(KNullTime, "11110000:010101.00000");
+ TTime ret(KNullTime);
+ const MVPbkStoreContactField* field = FindField( aContact, aFType);
+ if (field)
+ {
+ const MVPbkContactFieldData& fdata = field->FieldData();
+ if (fdata.DataType() == EVPbkFieldStorageTypeDateTime)
+ {
+ const MVPbkContactFieldDateTimeData& fdata2 =
+ MVPbkContactFieldDateTimeData::Cast( fdata );
+ ret = fdata2.DateTime();
+ }
+ else
+ {
+ User::Leave( KErrArgument );
+ }
+ }
+ return ret;
+ }
+
+// ----------------------------------------------------------------------------
+// GetFieldData, for EVPbkFieldStorageTypeBinary
+// ----------------------------------------------------------------------------
+EXPORT_C TPtrC8 CContactMatcher::GetFieldDataBinaryL(
+ const MVPbkStoreContact& aContact,
+ const MVPbkFieldType& aFType ) const
+ {
+ TPtrC8 ret(KNullDesC8);
+ const MVPbkStoreContactField* field = FindField( aContact, aFType);
+ if (field)
+ {
+ const MVPbkContactFieldData& fdata = field->FieldData();
+ if (fdata.DataType() == EVPbkFieldStorageTypeBinary)
+ {
+ const MVPbkContactFieldBinaryData& fdata2 =
+ MVPbkContactFieldBinaryData::Cast( fdata );
+ ret.Set( fdata2.BinaryData() );
+ }
+ else
+ {
+ User::Leave( KErrArgument );
+ }
+ }
+ return ret;
+ }
+
+
+//******************************** Private Methods ***************************
+
+// ----------------------------------------------------------------------------
+// Finds a field of given type from contact.
+// Returns pointer to field or NULL if not found.
+// ----------------------------------------------------------------------------
+ const MVPbkStoreContactField* CContactMatcher::FindField(
+ const MVPbkStoreContact& aContact,
+ const MVPbkFieldType& aFType ) const
+ {
+ const MVPbkStoreContactFieldCollection& coll = aContact.Fields();
+ TInt n = coll.FieldCount();
+
+ const MVPbkStoreContactField* field = NULL;
+ TBool bFound = EFalse;
+ for(TInt i=0; i < n && !bFound; ++i)
+ {
+ field = &coll.FieldAt( i );
+ const MVPbkFieldType* ftype = field->MatchFieldType( 0 );
+ if ( ftype )
+ {
+ if ( ftype->IsSame( aFType ))
+ {
+ bFound = ETrue;
+ }
+ }
+ }
+ if ( !bFound )
+ {
+ field = NULL;
+ }
+ return field;
+ }
+
+// ----------------------------------------------------------------------------
+// Get URI array with stores
+// ----------------------------------------------------------------------------
+CVPbkContactStoreUriArray* CContactMatcher::GetStoreArrayLC(
+ const TDesC& (* const aFuncPtrs[])() )
+ {
+ CVPbkContactStoreUriArray* uriArray = CVPbkContactStoreUriArray::NewLC();
+
+ // Add stores
+ for(TInt i = 0; aFuncPtrs[i]; i++)
+ {
+ TVPbkContactStoreUriPtr uriPtr(aFuncPtrs[i]());
+ uriArray->AppendL(uriPtr);
+ }
+ return uriArray;
+ }
+
+// ----------------------------------------------------------------------------
+// Open stores. Synchronous version
+// ----------------------------------------------------------------------------
+void CContactMatcher::OpenStoreL(const TDesC& (* const aFuncPtrs[])())
+ {
+ CVPbkContactStoreUriArray* uriArray = GetStoreArrayLC(aFuncPtrs);
+
+ CContactMatcher::OpenStoreL(*uriArray);
+ CleanupStack::PopAndDestroy(uriArray);
+ }
+
+// ----------------------------------------------------------------------------
+// Open stores. Asynchronous version
+// ----------------------------------------------------------------------------
+void CContactMatcher::OpenStoreL(const TDesC& (* const aFuncPtrs[])(),
+ TRequestStatus& aStatus)
+ {
+ CVPbkContactStoreUriArray* uriArray = GetStoreArrayLC(aFuncPtrs);
+
+ CContactMatcher::OpenStoreL(*uriArray, aStatus);
+ CleanupStack::PopAndDestroy(uriArray);
+ }
+
+// ----------------------------------------------------------------------------
+// Called when the opening process is complete,
+// ie. all stores have been reported either failed or successfully opened.
+// ----------------------------------------------------------------------------
+//
+void CContactMatcher::OpenComplete()
+ {
+ TInt error = KErrNone;
+ if ( iStoreUris->Count() == 0 )
+ {
+ // unable to open any of the specified stores
+ error = KErrNotSupported;
+ }
+ OperationComplete( error );
+ }
+
+// ----------------------------------------------------------------------------
+// Called when a contact store is ready to use.
+// ----------------------------------------------------------------------------
+void CContactMatcher::StoreReady( MVPbkContactStore& /*aContactStore*/ )
+ {
+ }
+
+// ----------------------------------------------------------------------------
+// Called when a contact store becomes unavailable.
+// Client may inspect the reason of the unavailability and decide whether or not
+// it will keep the store opened (ie. listen to the store events).
+// @param aContactStore The store that became unavailable.
+// @param aReason The reason why the store is unavailable.
+// This is one of the system wide error codes.
+// ----------------------------------------------------------------------------
+void CContactMatcher::StoreUnavailable( MVPbkContactStore& aContactStore,
+ TInt /*aReason*/ )
+ {
+ // Remove contact store from uri list
+ iStoreUris->Remove( aContactStore.StoreProperties().Uri() );
+ }
+
+// ----------------------------------------------------------------------------
+// Called when changes occur in the contact store.
+// @see TVPbkContactStoreEvent
+//
+// @param aStoreEvent Event that has occured.
+// ----------------------------------------------------------------------------
+void CContactMatcher::HandleStoreEventL(
+ MVPbkContactStore& /*aContactStore*/,
+ TVPbkContactStoreEvent aStoreEvent)
+ {
+ // Contact and group events can be ignored, but we pass backup events for the observer.
+ switch ( aStoreEvent.iEventType )
+ {
+ case TVPbkContactStoreEvent::EStoreBackupBeginning:
+ case TVPbkContactStoreEvent::EStoreRestoreBeginning:
+ {
+ iBackup = ETrue;
+ break;
+ }
+ case TVPbkContactStoreEvent::EStoreBackupRestoreCompleted:
+ {
+ iBackup = EFalse;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+
+// ----------------------------------------------------------------------------
+// Called when find is complete. Callee takes ownership of the results.
+// In case of an error during find, the aResults may contain only
+// partial results of the find.
+//
+// @param aResults Array of contact links that matched the find.
+// ----------------------------------------------------------------------------
+void CContactMatcher::FindCompleteL( MVPbkContactLinkArray* aResults )
+ {
+ __ASSERT_DEBUG( aResults, ContactMatcherPanics::Panic(
+ ContactMatcherPanics::EPanNullPointer ));
+
+ // Take the ownership of the result immediately
+ CleanupDeletePushL( aResults );
+
+ CopyFindResultsL( aResults );
+
+ CleanupStack::PopAndDestroy(); // aResults
+
+ if (!iResultContactLinkArray)
+ {
+ // No need to copy links. Only interested whether found or not
+ OperationComplete( iResultContactLinkCnt ? KErrNone:KErrNotFound );
+ }
+ else
+ {
+ OperationComplete();
+ iResultContactLinkArray = NULL;
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// Called in case the find fails for some reason.
+//
+// @param aError One of the system wide error codes.
+// ----------------------------------------------------------------------------
+void CContactMatcher::FindFailed( TInt aError )
+ {
+ OperationFailed( aError );
+ iResultContactLinkArray = NULL;
+ }
+
+// ----------------------------------------------------------------------------
+// Free old VPbk-operation.
+// ----------------------------------------------------------------------------
+void CContactMatcher::FreeOldOperation()
+ {
+ delete iOperation;
+ iOperation = NULL;
+ }
+
+// ----------------------------------------------------------------------------
+// Called when operation is completed.
+// ----------------------------------------------------------------------------
+void CContactMatcher::VPbkSingleContactOperationComplete(
+ MVPbkContactOperationBase& /*aOperation*/, MVPbkStoreContact* aContact)
+ {
+ *iResultStoreContact = aContact;
+ iResultStoreContact = NULL;
+ OperationComplete();
+ }
+
+// ----------------------------------------------------------------------------
+// Called if the operation fails.
+// ----------------------------------------------------------------------------
+void CContactMatcher::VPbkSingleContactOperationFailed(
+ MVPbkContactOperationBase& /*aOperation*/, TInt aError)
+ {
+ OperationFailed( aError );
+ }
+
+// ----------------------------------------------------------------------------
+// Set member variables for sync operation
+// ----------------------------------------------------------------------------
+void CContactMatcher::InitOperationL( TMethodId aMethod )
+ {
+ if ( iBackup )
+ {
+ User::Leave( KErrAccessDenied );
+ }
+
+ // Check whether operation is in progress
+ if ( iApiMethodStatus == EExecuting )
+ {
+ User::Leave( KErrInUse );
+ }
+
+ iSync = ETrue;
+ iError = KErrNone;
+ iApiMethod = aMethod;
+ iApiMethodStatus = EIdle;
+ }
+
+// ----------------------------------------------------------------------------
+// Set member variables for async operation
+// ----------------------------------------------------------------------------
+void CContactMatcher::InitOperationL( TMethodId aMethod, TRequestStatus* aStatus )
+ {
+ InitOperationL( aMethod );
+
+ iSync = EFalse;
+ iClientStatus = aStatus;
+ *iClientStatus = KRequestPending;
+ }
+
+// ----------------------------------------------------------------------------
+// Set member variables for async operation
+// ----------------------------------------------------------------------------
+void CContactMatcher::InitOperation( TRequestStatus* aStatus )
+ {
+ iSync = EFalse;
+ iClientStatus = aStatus;
+ *iClientStatus = KRequestPending;
+ }
+
+// ----------------------------------------------------------------------------
+// Sync/async operation finished succesfully, return results to method caller.
+// ----------------------------------------------------------------------------
+void CContactMatcher::OperationComplete( TInt aErrorCode )
+ {
+ if (iSync)
+ {
+ if ( iASchedulerWait.IsStarted() )
+ {
+ iASchedulerWait.AsyncStop();
+ }
+ }
+ else
+ {
+ if ( iClientStatus )
+ {
+ User::RequestComplete( iClientStatus, aErrorCode );
+ iClientStatus = NULL;
+ }
+ }
+ iApiMethodStatus = EFinished;
+ }
+
+// ----------------------------------------------------------------------------
+// Sync/async operation failed, return results to method caller.
+// ----------------------------------------------------------------------------
+void CContactMatcher::OperationFailed( TInt aError )
+ {
+ iError = aError;
+ OperationComplete( aError );
+ }
+
+// ----------------------------------------------------------------------------
+// Free resources allocated for number matching
+// ----------------------------------------------------------------------------
+void CContactMatcher::CleanupNumberMatch()
+{
+ delete iMatchStrategy;
+ iMatchStrategy = NULL;
+
+ delete iStratConfig;
+ iStratConfig = NULL;
+
+ // store uris are not deleted here - opened array remains valid
+ // until new set of stores is opened.
+}
+
+// ---------------------------------------------------------------------------
+// CContactMatcher::GetContactStoresL
+// ---------------------------------------------------------------------------
+EXPORT_C MVPbkContactStoreList& CContactMatcher::GetContactStoresL()
+ {
+ return iContactManager->ContactStoresL();
+ }
+
+
+// -----------------------------------------------------------------------------
+// TInt CContactMatcher::GetName
+//
+// Returns the formatted name fo the contact
+// -----------------------------------------------------------------------------
+EXPORT_C HBufC* CContactMatcher::GetNameL( MVPbkStoreContactFieldCollection&
+ aFieldCollection )
+ {
+ MPbk2ContactNameFormatter& nameFormatter = ContactNameFormatterL();
+
+ HBufC* formattedName = nameFormatter.GetContactTitleOrNullL( aFieldCollection,
+ MPbk2ContactNameFormatter::EUseSeparator );
+ return formattedName;
+ }
+
+// -----------------------------------------------------------------------------
+// TInt CContactMatcher::ContactHasFieldOfTypeL( )
+// -----------------------------------------------------------------------------
+EXPORT_C TInt CContactMatcher::ContactHasFieldOfTypeL
+ ( TAiwAddressSelectType aAddressSelectType, const MVPbkStoreContact& aContact )
+ {
+ TInt resId = 0;
+
+ switch ( aAddressSelectType )
+ {
+ case EAiwPhoneNumberSelect:
+ resId = R_PHONE_NUMBER_SELECTOR;
+ break;
+ case EAiwEMailSelect:
+ resId = R_EMAIL_ADDRESS_SELECTOR;
+ break;
+ case EAiwMMSSelect:
+ resId = R_MMS_ADDRESS_SELECTOR;
+ break;
+ default:
+ resId = R_PHONE_NUMBER_SELECTOR;
+ break;
+ }
+
+ MVPbkContactFieldSelector* fieldTypeSelector =
+ CreateFieldTypeSelectorLC( resId );
+
+ // Check if the specified field type is included in the contact
+ const MVPbkStoreContactFieldCollection& fields = aContact.Fields();
+ TInt fieldCount = fields.FieldCount();
+
+ TInt ret = KErrNotFound;
+ for ( TInt i = 0; i < fieldCount && ret == KErrNotFound; ++i )
+ {
+ const MVPbkBaseContactField& field = fields.FieldAt( i );
+ if ( fieldTypeSelector->IsFieldIncluded( field ) )
+ {
+ ret = i;
+ }
+ }
+
+ CleanupStack::PopAndDestroy(); // fieldTypeSelector
+
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CVPbkContactManager& CContactMatcher::GetContactManager( )
+// -----------------------------------------------------------------------------
+EXPORT_C CVPbkContactManager& CContactMatcher::GetContactManager()
+ {
+ return *iContactManager;
+ }
+
+
+// ----------------------------------------------------------------------------
+// Synchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CContactMatcher::MatchDataL( const TDesC& aData,
+ const MVPbkFieldTypeList& aFieldTypes,
+ CVPbkContactLinkArray& aLinkArray)
+ {
+ InitOperationL( EMatchData );
+ iResultContactLinkArray = &aLinkArray;
+
+ // Start asynchronous matching and wait until results are ready
+ FreeOldOperation();
+ iOperation = iContactManager->FindL(aData, aFieldTypes, *this);
+ if ( iApiMethodStatus != EFinished )
+ {
+ iApiMethodStatus = EExecuting;
+ iASchedulerWait.Start();
+ }
+
+ User::LeaveIfError( iError );
+ RemoveSimilarEmailAddressesL( aData, aLinkArray, aFieldTypes );
+ }
+
+// ----------------------------------------------------------------------------
+// Remove contacts that do not have exactly the correct email address
+// e.g. if cbd@test.com address is requested, the for example a contact with address abcd@test.com will be removed
+// from the result.
+// This filtering is done only in the syncronous version of MatchDataL
+// ----------------------------------------------------------------------------
+void CContactMatcher::RemoveSimilarEmailAddressesL( const TDesC& aData, CVPbkContactLinkArray& aLinkArray, const MVPbkFieldTypeList& aFieldTypes )
+ {
+ TVPbkFieldVersitProperty prop;
+ prop.SetName( EVPbkVersitNameEMAIL );
+ // do extra checks for email addresses
+
+ const MVPbkFieldType* foundType = NULL;
+ // Continue only if at least one type is EVPbkVersitNameEMAIL
+ TInt i;
+ for ( i = 0 ; i < aFieldTypes.FieldTypeCount() ; i++ )
+ {
+ foundType = &(aFieldTypes.FieldTypeAt( i ));
+ if ( foundType->VersitProperties().Count() > 0
+ && foundType->VersitProperties()[0].Name() == prop.Name() )
+ {
+ break;
+ }
+ }
+ if ( i == aFieldTypes.FieldTypeCount() )
+ {
+ // no email types
+ return;
+ }
+
+ const MVPbkFieldTypeList& fieldTypeList = FieldTypes();
+
+ TInt index = 0;
+ TBool isExactMatch;
+ while( index < aLinkArray.Count() )
+ {
+ MVPbkStoreContact* storeContact;
+ GetStoreContactL( aLinkArray.At( index ), &storeContact );
+ storeContact->PushL();
+
+ isExactMatch = EFalse;
+ for ( TInt i = 0; i < fieldTypeList.FieldTypeCount(); i++ )
+ {
+ // find the email property
+ foundType = &(fieldTypeList.FieldTypeAt( i ));
+ if ( foundType->VersitProperties().Count() > 0
+ && foundType->VersitProperties()[0].Name() == prop.Name() )
+ {
+ TPtrC src = GetFieldDataTextL(*storeContact, *foundType );
+ if ( aData.CompareF( src ) == 0 )
+ {
+ isExactMatch = ETrue;
+ }
+ }
+ }
+ if ( isExactMatch )
+ {
+ // go for the next contact
+ index++;
+ }
+ else
+ {
+ // remove the contact, because the email address does not match the one queried.
+ // the next one will take plce of this contact in the list (=do not increase index)
+ aLinkArray.Delete( index );
+ }
+ CleanupStack::PopAndDestroy( storeContact );
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// Asynchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CContactMatcher::MatchDataL( const TDesC& aData,
+ const MVPbkFieldTypeList& aFieldTypes,
+ CVPbkContactLinkArray& aLinkArray,
+ TRequestStatus& aStatus)
+ {
+ InitOperationL( EMatchData );
+ iResultContactLinkArray = &aLinkArray;
+
+ // Start asynchronous matching
+ FreeOldOperation();
+ iOperation = iContactManager->FindL(aData, aFieldTypes, *this);
+ InitOperation( &aStatus );
+ if ( iApiMethodStatus != EFinished )
+ {
+ iApiMethodStatus = EExecuting;
+ }
+ }
+// ----------------------------------------------------------------------------
+// MatchData for searchstrings
+// ----------------------------------------------------------------------------
+EXPORT_C void CContactMatcher::MatchDataL( const MDesC16Array& aSearchStrings,
+ const MVPbkFieldTypeList& aFieldTypes,
+ CVPbkContactLinkArray& aLinkArray,
+ const TCallBack& aWordParserCallBack )
+ {
+ InitOperationL( EMatchData );
+ iResultContactLinkArray = &aLinkArray;
+
+ // Start asynchronous matching and wait here until results are ready
+ FreeOldOperation();
+ iOperation = iContactManager->FindL( aSearchStrings, aFieldTypes,
+ *this, aWordParserCallBack );
+
+ if ( iApiMethodStatus != EFinished )
+ {
+ iApiMethodStatus = EExecuting;
+ iASchedulerWait.Start();
+ }
+ User::LeaveIfError( iError );
+ }
+
+// ----------------------------------------------------------------------------
+// CContactMatcher::ContactNameFormatterL
+// ----------------------------------------------------------------------------
+EXPORT_C MPbk2ContactNameFormatter& CContactMatcher::ContactNameFormatterL()
+ {
+ //first initialise, if not already initialised
+ if ( !iSortOrderManager )
+ {
+ iSortOrderManager = CPbk2SortOrderManager::NewL( FieldTypes() );
+ }
+
+ if ( !iNameFormatter )
+ {
+ iNameFormatter = Pbk2ContactNameFormatterFactory::CreateL( FieldTypes(),
+ *iSortOrderManager );
+ }
+ return *iNameFormatter;
+ }
+
+
+// -----------------------------------------------------------------------------
+// MVPbkContactFieldSelector* CContactMatcher::CreateFieldTypeSelectorLC( )
+// -----------------------------------------------------------------------------
+MVPbkContactFieldSelector* CContactMatcher::CreateFieldTypeSelectorLC
+ ( TInt aResId )
+ {
+ if ( !iResourceFileInitialized )
+ {
+ TFileName tmpName;
+ // Append the Resource Files Directory
+ tmpName.Append( KDC_RESOURCE_FILES_DIR );
+ // Append the Ressource File Name
+ tmpName.Append( KMsgCommonUtilsResourceFileName );
+
+ // Obtain the drive where the DLL is installed
+ TFileName dllDrive;
+ Dll::FileName( dllDrive );
+
+ // Obtain the Complete path for the Resource File
+ TParse parse;
+ parse.Set( dllDrive, NULL, NULL );
+ parse.Set( parse.Drive(), &tmpName, NULL );
+ TFileName fileName;
+ fileName.Append( parse.FullName());
+
+ iResourceFile.OpenL( *iFsSession, fileName );
+ iResourceFile.ConfirmSignatureL( 0 );
+ iResourceFileInitialized = ETrue;
+ }
+
+ HBufC8* dataBuffer = iResourceFile.AllocReadLC( aResId );
+
+ TResourceReader reader;
+ reader.SetBuffer( dataBuffer );
+
+ CVPbkFieldTypeSelector* fieldTypeSelector =
+ CVPbkFieldTypeSelector::NewL( reader,
+ FieldTypes() );
+
+ CleanupStack::PopAndDestroy( dataBuffer );
+
+ CleanupStack::PushL( fieldTypeSelector );
+ return fieldTypeSelector;
+ }
+
+// ---------------------------------------------------------------------------
+// ContactMatcherPanics::Panic
+//
+// Panic function
+// ---------------------------------------------------------------------------
+void ContactMatcherPanics::Panic( TPanic aPanic )
+ {
+ _LIT(KPanicCategory, "ContactMatcher");
+ User::Panic( KPanicCategory, aPanic );
+ }
+
+// End of File