diff -r 000000000000 -r 8e480a14352b messagingfw/msgcommonutils/src/contactmatcher.cpp --- /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 +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + + +// ================= 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