--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/homescreensrv_plat/context_utility_api/tsrc/src/hgctxcontactmatcher.cpp Thu Dec 17 08:54:17 2009 +0200
@@ -0,0 +1,2539 @@
+/*
+* Copyright (c) 2008 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: Contact matching class
+*
+*/
+
+
+// System includes
+#include <e32base.h>
+#include <bamdesca.h>
+#include <cntitem.h>
+#include <eikenv.h>
+#include <bautils.h>
+#include <fbs.h>
+#include <imageconversion.h>
+#include <data_caging_path_literals.hrh>
+
+#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 <MVPbkContactFieldUriData.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 <TVPbkWordParserCallbackParam.h>
+#include <CVPbkContactViewDefinition.h>
+#include <MVPbkContactViewBase.h>
+#include <coemain.h>
+#include <CPbk2SortOrderManager.h>
+#include <Pbk2ContactNameFormatterFactory.h>
+
+#include "hgctxcontactmatcher.h"
+
+
+#include "hgctxutilslogging.h"
+
+
+// ================= 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
+ };
+
+// number of digits that must match from the right side of a phone number
+const TInt KNumberMatchLenFromRight = 7;
+
+// granularity for CDesCArray
+const TInt KArrayGranularity = 4;
+
+// YYYYMMDD:HHMMSS.MMMMMM
+_LIT(KNullTime, "11110000:010101.00000");
+
+// ================= STATIC FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// FindWordSplitterL
+// ---------------------------------------------------------
+//
+static TInt FindWordSplitterL( TAny* aParams )
+ {
+ TVPbkWordParserCallbackParam* parser =
+ static_cast<TVPbkWordParserCallbackParam*>( aParams );
+
+ const TText* ptr = parser->iStringToParse->Ptr();
+ const TText* end = ptr + parser->iStringToParse->Length();
+
+ const TText* startOfWord=NULL;
+ for ( ; ; )
+ {
+ if ( ptr==end || TChar(*ptr).IsSpace() || *ptr == ',' || *ptr == ';' )
+ {
+ if ( startOfWord )
+ {
+ TPtrC addWord( startOfWord,ptr - startOfWord );
+ parser->iWordArray->AppendL( addWord );
+ startOfWord = NULL;
+ }
+ if ( ptr == end )
+ {
+ break;
+ }
+ }
+ else if ( !startOfWord )
+ {
+ startOfWord = ptr;
+ }
+ ptr++;
+ }
+ return( KErrNone );
+ }
+
+static HBufC* CombineStringsLC( CDesCArray& aArray )
+ {
+ TInt len = 0;
+ for ( TInt i = 0, ie = aArray.Count(); i != ie; ++i )
+ {
+ len += aArray[i].Length() + 1;
+ }
+ HBufC* result = HBufC::NewLC( len );
+ TPtr p( result->Des() );
+ for ( TInt i = 0, ie = aArray.Count(); i != ie; ++i )
+ {
+ if ( i )
+ {
+ p.Append( ' ' );
+ }
+ p.Append( aArray[i] );
+ }
+ return result;
+ }
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ----------------------------------------------------------------------------
+// Two-phase constructor for CHgCtxContactMatcher class.
+// ----------------------------------------------------------------------------
+EXPORT_C CHgCtxContactMatcher* CHgCtxContactMatcher::NewL(
+ RFs* aFsSession )
+ {
+ CHgCtxContactMatcher* self = CHgCtxContactMatcher::NewLC( aFsSession );
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+// ----------------------------------------------------------------------------
+// Two-phase constructor for CHgCtxContactMatcher class.
+// ----------------------------------------------------------------------------
+EXPORT_C CHgCtxContactMatcher* CHgCtxContactMatcher::NewLC(
+ RFs* aFsSession )
+ {
+ CHgCtxContactMatcher* self = new ( ELeave ) CHgCtxContactMatcher( aFsSession );
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+// ----------------------------------------------------------------------------
+// C++ destructor.
+// ----------------------------------------------------------------------------
+EXPORT_C CHgCtxContactMatcher::~CHgCtxContactMatcher()
+ {
+ delete iNameFieldTypes;
+ delete iNumberFieldTypes;
+ delete iEmailFieldTypes;
+ delete iXspIdFieldTypes;
+ delete iAddressFieldTypes;
+ delete iWebAddressFieldTypes;
+ delete iHomeAddressFieldTypes;
+ delete iWorkAddressFieldTypes;
+
+ FreeOldOperation();
+ CleanupNumberMatch();
+ delete iStoreUris;
+ delete iContactManager;
+ delete iSortOrderManager;
+ delete iNameFormatter;
+
+ if ( iClientStatus )
+ {
+ User::RequestComplete( iClientStatus, KErrCancel );
+ }
+ if ( iASchedulerWait.IsStarted() )
+ {
+ iASchedulerWait.AsyncStop();
+ }
+
+ iContactObservers.Close();
+
+ if ( iFsSessionOwned && iFsSession )
+ {
+ iFsSession->Close();
+ delete iFsSession;
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// C++ Constructor.
+// ----------------------------------------------------------------------------
+CHgCtxContactMatcher::CHgCtxContactMatcher( RFs* aFsSession) : iFsSession( aFsSession )
+ {
+ }
+
+// ----------------------------------------------------------------------------
+// Second phase constructor
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::ConstructL()
+ {
+ if ( !iFsSession )
+ {
+ // The contact manager would be okay with NULL but some of our own functions
+ // need an RFs.
+ iFsSessionOwned = ETrue;
+ iFsSession = new ( ELeave ) RFs;
+ User::LeaveIfError( iFsSession->Connect() );
+ }
+
+ iContactManager = CVPbkContactManager::NewL(
+ *CVPbkContactStoreUriArray::NewLC(), iFsSession );
+ CleanupStack::PopAndDestroy(); // CVPbkContactStoreUriArray
+
+ // No stores open yet
+ iStoreUris = CVPbkContactStoreUriArray::NewL();
+ }
+
+//******************* API-methods *********************************************
+
+// ----------------------------------------------------------------------------
+// Synchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::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 CHgCtxContactMatcher::OpenStoreL(
+ const CVPbkContactStoreUriArray& aUriArray, TRequestStatus& aStatus )
+ {
+ InitOperationL( EOpenStore );
+ OpenStoreCommonL( aUriArray );
+ InitOperation( &aStatus );
+
+ if ( iApiMethodStatus != EFinished )
+ {
+ iApiMethodStatus = EExecuting;
+ }
+ }
+
+
+// ----------------------------------------------------------------------------
+// Common code to sync/async versions.
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::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 CHgCtxContactMatcher::OpenAllStoresL()
+ {
+ OpenStoreL(AllStoreUris);
+ }
+
+// ----------------------------------------------------------------------------
+// Asynchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::OpenAllStoresL( TRequestStatus& aStatus )
+ {
+ OpenStoreL(AllStoreUris, aStatus);
+ }
+
+// ----------------------------------------------------------------------------
+// Synchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::OpenDefaultMatchStoresL()
+ {
+ OpenStoreL(NumberMatchStoreUris);
+ }
+
+// ----------------------------------------------------------------------------
+// Asynchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::OpenDefaultMatchStoresL( TRequestStatus& aStatus )
+ {
+ OpenStoreL(NumberMatchStoreUris, aStatus);
+ }
+
+// ----------------------------------------------------------------------------
+// Open OwnNumber stores.
+// Synchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::OpenOwnNumberStoresL()
+ {
+ OpenStoreL(OwnNumberStoreUris);
+ }
+
+// ----------------------------------------------------------------------------
+// Open OwnNumber stores.
+// Asynchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::OpenOwnNumberStoresL( TRequestStatus& aStatus )
+ {
+ OpenStoreL(OwnNumberStoreUris, aStatus);
+ }
+
+// ----------------------------------------------------------------------------
+// Close all open stores.
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::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 CHgCtxContactMatcher::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 CHgCtxContactMatcher::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 CHgCtxContactMatcher::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 CHgCtxContactMatcher::FindFromStoreSucceededL( MVPbkContactStore& /*aStore*/,
+ MVPbkContactLinkArray* aResultsFromStore )
+ {
+ __ASSERT_DEBUG( aResultsFromStore, HgContactMatcherPanics::Panic(
+ HgContactMatcherPanics::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 CHgCtxContactMatcher::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 CHgCtxContactMatcher::FindFromStoreFailed( MVPbkContactStore& /*aStore*/, TInt /*aError*/ )
+ {
+ //no operation, search to continue from the other stores
+ }
+
+
+// ----------------------------------------------------------------------------
+// Find complete
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::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& CHgCtxContactMatcher::FieldTypes() const
+ {
+ return iContactManager->FieldTypes();
+ }
+
+// ----------------------------------------------------------------------------
+// Synchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::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 CHgCtxContactMatcher::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 CHgCtxContactMatcher::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 CHgCtxContactMatcher::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 CHgCtxContactMatcher::CancelOperation()
+ {
+ if (iApiMethodStatus != EExecuting)
+ {
+ return;
+ }
+
+ __ASSERT_DEBUG(!iSync, HgContactMatcherPanics::Panic(
+ HgContactMatcherPanics::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 CHgCtxContactMatcher::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 CHgCtxContactMatcher::GetFieldDataDateTimeL(
+ const MVPbkStoreContact& aContact,
+ const MVPbkFieldType& aFType ) const
+ {
+ 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 CHgCtxContactMatcher::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* CHgCtxContactMatcher::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* CHgCtxContactMatcher::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 CHgCtxContactMatcher::OpenStoreL(const TDesC& (* const aFuncPtrs[])())
+ {
+ CVPbkContactStoreUriArray* uriArray = GetStoreArrayLC(aFuncPtrs);
+
+ CHgCtxContactMatcher::OpenStoreL(*uriArray);
+ CleanupStack::PopAndDestroy(uriArray);
+ }
+
+// ----------------------------------------------------------------------------
+// Open stores. Asynchronous version
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::OpenStoreL(const TDesC& (* const aFuncPtrs[])(),
+ TRequestStatus& aStatus)
+ {
+ CVPbkContactStoreUriArray* uriArray = GetStoreArrayLC(aFuncPtrs);
+
+ CHgCtxContactMatcher::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 CHgCtxContactMatcher::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 CHgCtxContactMatcher::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 CHgCtxContactMatcher::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 CHgCtxContactMatcher::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;
+ }
+ case TVPbkContactStoreEvent::EContactAdded:
+ case TVPbkContactStoreEvent::EContactDeleted:
+ case TVPbkContactStoreEvent::EContactChanged:
+ {
+ for ( TInt i = 0, ie = iContactObservers.Count(); i != ie; ++i )
+ {
+ iContactObservers[i]->HandleContactEventL();
+ }
+ 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 CHgCtxContactMatcher::FindCompleteL( MVPbkContactLinkArray* aResults )
+ {
+ __ASSERT_DEBUG( aResults, HgContactMatcherPanics::Panic(
+ HgContactMatcherPanics::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 CHgCtxContactMatcher::FindFailed( TInt aError )
+ {
+ OperationFailed( aError );
+ iResultContactLinkArray = NULL;
+ }
+
+// ----------------------------------------------------------------------------
+// Free old VPbk-operation.
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::FreeOldOperation()
+ {
+ delete iOperation;
+ iOperation = NULL;
+ }
+
+// ----------------------------------------------------------------------------
+// Called when operation is completed.
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::VPbkSingleContactOperationComplete(
+ MVPbkContactOperationBase& /*aOperation*/, MVPbkStoreContact* aContact)
+ {
+ *iResultStoreContact = aContact;
+ iResultStoreContact = NULL;
+ OperationComplete();
+ }
+
+// ----------------------------------------------------------------------------
+// Called if the operation fails.
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::VPbkSingleContactOperationFailed(
+ MVPbkContactOperationBase& /*aOperation*/, TInt aError)
+ {
+ OperationFailed( aError );
+ }
+
+// ----------------------------------------------------------------------------
+// Set member variables for sync operation
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::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 CHgCtxContactMatcher::InitOperationL( TMethodId aMethod, TRequestStatus* aStatus )
+ {
+ InitOperationL( aMethod );
+
+ iSync = EFalse;
+ iClientStatus = aStatus;
+ *iClientStatus = KRequestPending;
+ }
+
+// ----------------------------------------------------------------------------
+// Set member variables for async operation
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::InitOperation( TRequestStatus* aStatus )
+ {
+ iSync = EFalse;
+ iClientStatus = aStatus;
+ *iClientStatus = KRequestPending;
+ }
+
+// ----------------------------------------------------------------------------
+// Sync/async operation finished succesfully, return results to method caller.
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::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 CHgCtxContactMatcher::OperationFailed( TInt aError )
+ {
+ iError = aError;
+ OperationComplete( aError );
+ }
+
+// ----------------------------------------------------------------------------
+// Free resources allocated for number matching
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::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.
+}
+
+// ---------------------------------------------------------------------------
+// CHgCtxContactMatcher::GetContactStoresL
+// ---------------------------------------------------------------------------
+EXPORT_C MVPbkContactStoreList& CHgCtxContactMatcher::GetContactStoresL()
+ {
+ return iContactManager->ContactStoresL();
+ }
+
+
+// -----------------------------------------------------------------------------
+// TInt CHgCtxContactMatcher::GetName
+//
+// Returns the formatted name fo the contact
+// -----------------------------------------------------------------------------
+EXPORT_C HBufC* CHgCtxContactMatcher::GetNameL( MVPbkStoreContactFieldCollection&
+ aFieldCollection )
+ {
+ MPbk2ContactNameFormatter& nameFormatter = ContactNameFormatterL();
+
+ HBufC* formattedName = nameFormatter.GetContactTitleOrNullL( aFieldCollection,
+ MPbk2ContactNameFormatter::EUseSeparator );
+ return formattedName;
+ }
+
+// -----------------------------------------------------------------------------
+// CVPbkContactManager& CHgCtxContactMatcher::GetContactManager( )
+// -----------------------------------------------------------------------------
+EXPORT_C CVPbkContactManager& CHgCtxContactMatcher::GetContactManager()
+ {
+ return *iContactManager;
+ }
+
+
+// ----------------------------------------------------------------------------
+// Synchronous version
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::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 CHgCtxContactMatcher::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 CHgCtxContactMatcher::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 CHgCtxContactMatcher::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 );
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::ContactNameFormatterL
+// ----------------------------------------------------------------------------
+EXPORT_C MPbk2ContactNameFormatter& CHgCtxContactMatcher::ContactNameFormatterL()
+ {
+ //first initialise, if not already initialised
+ if ( !iSortOrderManager )
+ {
+ iSortOrderManager = CPbk2SortOrderManager::NewL( FieldTypes() );
+ }
+
+ if ( !iNameFormatter )
+ {
+ iNameFormatter = Pbk2ContactNameFormatterFactory::CreateL( FieldTypes(),
+ *iSortOrderManager );
+ }
+ return *iNameFormatter;
+ }
+
+
+// ---------------------------------------------------------------------------
+// HgContactMatcherPanics::Panic
+//
+// Panic function
+// ---------------------------------------------------------------------------
+void HgContactMatcherPanics::Panic( TPanic aPanic )
+ {
+ _LIT(KPanicCategory, "ContactMatcher");
+ User::Panic( KPanicCategory, aPanic );
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::SplitAndMatchL
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::SplitAndMatchL( const TDesC& aData,
+ const MVPbkFieldTypeList& aFieldTypes,
+ CVPbkContactLinkArray& aLinkArray)
+ {
+ CDesCArray* wordArray = SplitFindStringL( aData );
+ CleanupStack::PushL( wordArray );
+ TCallBack findParser( FindWordSplitterL );
+ MatchDataL( *wordArray, aFieldTypes, aLinkArray, findParser );
+ CleanupStack::PopAndDestroy( wordArray );
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::RegisterContactObserverL
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::RegisterContactObserverL(
+ MHgCtxContactObserver& aObserver )
+ {
+ if ( iContactObservers.Find( &aObserver ) == KErrNotFound )
+ {
+ iContactObservers.AppendL( &aObserver );
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::UnregisterContactObserver
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::UnregisterContactObserver(
+ MHgCtxContactObserver& aObserver )
+ {
+ TInt pos = iContactObservers.Find( &aObserver );
+ if ( pos >= 0 )
+ {
+ iContactObservers.Remove( pos );
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::LookupL
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::LookupL( const TDesC& aData,
+ CVPbkContactLinkArray& aLinkArray )
+ {
+ HGLOG_CONTEXT( LookupL, HGLOG_LOCAL );
+ HGLOG1_IN( "'%S'", &aData );
+
+ // Take part_A from "part_A <part_B>"
+ // or part_A from "part_A".
+ TPtrC input( aData );
+ TInt ltPos = input.Locate( '<' );
+ TInt gtPos = input.Locate( '>' );
+ if ( ltPos != KErrNotFound && gtPos> ltPos )
+ {
+ input.Set( aData.Mid( 0, ltPos ) );
+ }
+ HBufC* trimmedInput = input.AllocLC();
+ trimmedInput->Des().Trim();
+
+ TInt oldCount = aLinkArray.Count();
+ if ( IsPhoneNumberL( *trimmedInput ) )
+ {
+ TryNumberLookupL( *trimmedInput, aLinkArray );
+ }
+ else
+ {
+ TryTextLookupL( *trimmedInput, aLinkArray );
+ }
+
+ CleanupStack::PopAndDestroy( trimmedInput );
+
+ if ( aLinkArray.Count() == oldCount && ltPos != KErrNotFound && gtPos > ltPos )
+ {
+ // lookup for part_A was not successful so try part_B
+ trimmedInput = aData.Mid( ltPos + 1, gtPos - ltPos - 1 ).AllocLC();
+ trimmedInput->Des().Trim();
+ if ( IsPhoneNumberL( *trimmedInput ) )
+ {
+ TryNumberLookupL( *trimmedInput, aLinkArray );
+ }
+ else
+ {
+ TryTextLookupL( *trimmedInput, aLinkArray );
+ }
+ CleanupStack::PopAndDestroy( trimmedInput );
+ }
+
+ HGLOG1_OUT( "got %d results", aLinkArray.Count() - oldCount );
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::PreCreateNameFieldTypesL
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::PreCreateNameFieldTypesL()
+ {
+ HGLOG_CONTEXT( PreCreateNameFieldTypesL, HGLOG_LOCAL );
+ HGLOG_IN();
+
+ iNameFieldTypes = CVPbkFieldTypeRefsList::NewL();
+ const MVPbkFieldTypeList& types( FieldTypes() );
+ TVPbkFieldVersitProperty prop;
+ const MVPbkFieldType* t;
+
+ prop.SetName( EVPbkVersitNameFN );
+ prop.SetSubField( EVPbkVersitSubFieldNone );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iNameFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try FN" );
+ }
+
+ prop.SetName( EVPbkVersitNameN );
+ prop.SetSubField( EVPbkVersitSubFieldGivenName );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iNameFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try given name" );
+ }
+
+ prop.SetName( EVPbkVersitNameN );
+ prop.SetSubField( EVPbkVersitSubFieldFamilyName );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iNameFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try family name" );
+ }
+
+ prop.SetName( EVPbkVersitNameORG );
+ prop.SetSubField( EVPbkVersitSubFieldOrgName );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iNameFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try org name" );
+ }
+
+ HGLOG_OUT();
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::PreCreateEmailFieldTypesL
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::PreCreateEmailFieldTypesL()
+ {
+ HGLOG_CONTEXT( PreCreateEmailFieldTypesL, HGLOG_LOCAL );
+ HGLOG_IN();
+
+ iEmailFieldTypes = CVPbkFieldTypeRefsList::NewL();
+ const MVPbkFieldTypeList& types( FieldTypes() );
+ TVPbkFieldVersitProperty prop;
+ const MVPbkFieldType* t;
+
+ prop.SetName( EVPbkVersitNameEMAIL );
+ prop.SetSubField( EVPbkVersitSubFieldNone );
+ prop.Parameters().Reset();
+ prop.Parameters().Add( EVPbkVersitParamINTERNET );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iEmailFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try general email" );
+ }
+
+ prop.SetName( EVPbkVersitNameEMAIL );
+ prop.SetSubField( EVPbkVersitSubFieldNone );
+ prop.Parameters().Reset();
+ prop.Parameters().Add( EVPbkVersitParamINTERNET );
+ prop.Parameters().Add( EVPbkVersitParamWORK );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iEmailFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try work email" );
+ }
+
+ prop.SetName( EVPbkVersitNameEMAIL );
+ prop.SetSubField( EVPbkVersitSubFieldNone );
+ prop.Parameters().Reset();
+ prop.Parameters().Add( EVPbkVersitParamINTERNET );
+ prop.Parameters().Add( EVPbkVersitParamHOME );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iEmailFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try home email" );
+ }
+
+ HGLOG_OUT();
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::PreCreateXspIdFieldTypesL
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::PreCreateXspIdFieldTypesL()
+ {
+ HGLOG_CONTEXT( PreCreateXspIdFieldTypesL, HGLOG_LOCAL );
+ HGLOG_IN();
+
+ iXspIdFieldTypes = CVPbkFieldTypeRefsList::NewL();
+ const MVPbkFieldTypeList& types( FieldTypes() );
+ TVPbkFieldVersitProperty prop;
+ const MVPbkFieldType* t;
+
+ prop.SetName( EVPbkVersitNameIMPP );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iXspIdFieldTypes->AppendL( *t );
+ }
+
+ HGLOG1_OUT( "found %d xsp id field types",
+ iXspIdFieldTypes->FieldTypeCount() );
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::PreCreateNumberFieldTypesL
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::PreCreateNumberFieldTypesL()
+ {
+ HGLOG_CONTEXT( PreCreateNumberFieldTypesL, HGLOG_LOCAL );
+ HGLOG_IN();
+
+ iNumberFieldTypes = CVPbkFieldTypeRefsList::NewL();
+ const MVPbkFieldTypeList& types( FieldTypes() );
+ TVPbkFieldVersitProperty prop;
+ const MVPbkFieldType* t;
+
+ prop.SetName( EVPbkVersitNameTEL );
+ prop.SetSubField( EVPbkVersitSubFieldNone );
+ prop.Parameters().Reset();
+ prop.Parameters().Add( EVPbkVersitParamCELL );
+ prop.Parameters().Add( EVPbkVersitParamHOME );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iNumberFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try home mobile" );
+ }
+
+ prop.SetName( EVPbkVersitNameTEL );
+ prop.SetSubField( EVPbkVersitSubFieldNone );
+ prop.Parameters().Reset();
+ prop.Parameters().Add( EVPbkVersitParamCELL );
+ prop.Parameters().Add( EVPbkVersitParamWORK );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iNumberFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try work mobile" );
+ }
+
+ prop.SetName( EVPbkVersitNameTEL );
+ prop.SetSubField( EVPbkVersitSubFieldNone );
+ prop.Parameters().Reset();
+ prop.Parameters().Add( EVPbkVersitParamCELL );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iNumberFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try general mobile" );
+ }
+
+ prop.SetName( EVPbkVersitNameTEL );
+ prop.SetSubField( EVPbkVersitSubFieldNone );
+ prop.Parameters().Reset();
+ prop.Parameters().Add( EVPbkVersitParamHOME );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iNumberFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try home landline" );
+ }
+
+ prop.SetName( EVPbkVersitNameTEL );
+ prop.SetSubField( EVPbkVersitSubFieldNone );
+ prop.Parameters().Reset();
+ prop.Parameters().Add( EVPbkVersitParamWORK );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iNumberFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try work landline" );
+ }
+
+ prop.SetName( EVPbkVersitNameTEL );
+ prop.SetSubField( EVPbkVersitSubFieldNone );
+ prop.Parameters().Reset();
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iNumberFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try general landline" );
+ }
+
+ HGLOG_OUT();
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::PreCreateAddressFieldTypesL
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::PreCreateAddressFieldTypesL()
+ {
+ HGLOG_CONTEXT( PreCreateAddressFieldTypesL, HGLOG_LOCAL );
+ HGLOG_IN();
+
+ iAddressFieldTypes = CVPbkFieldTypeRefsList::NewL();
+ const MVPbkFieldTypeList& types( FieldTypes() );
+ TVPbkFieldVersitProperty prop;
+ const MVPbkFieldType* t;
+
+ prop.SetName( EVPbkVersitNameADR );
+ prop.SetSubField( EVPbkVersitSubFieldCountry );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iAddressFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try general country" );
+ }
+
+ prop.SetName( EVPbkVersitNameADR );
+ prop.SetSubField( EVPbkVersitSubFieldRegion );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iAddressFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try general region" );
+ }
+
+ prop.SetName( EVPbkVersitNameADR );
+ prop.SetSubField( EVPbkVersitSubFieldLocality );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iAddressFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try general locality" );
+ }
+
+ prop.SetName( EVPbkVersitNameADR );
+ prop.SetSubField( EVPbkVersitSubFieldStreet );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iAddressFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try general street" );
+ }
+
+ HGLOG_OUT();
+ }
+
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::PreCreateWebAddressFieldTypesL
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::PreCreateWebAddressFieldTypesL()
+ {
+ HGLOG_CONTEXT( PreCreateWebAddressFieldTypesL, HGLOG_LOCAL );
+ HGLOG_IN();
+
+ iWebAddressFieldTypes = CVPbkFieldTypeRefsList::NewL();
+ const MVPbkFieldTypeList& types( FieldTypes() );
+ TVPbkFieldVersitProperty prop;
+ const MVPbkFieldType* t;
+
+ prop.Parameters().Add( EVPbkVersitParamPREF );
+ prop.SetName( EVPbkVersitNameURL );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iWebAddressFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try prefered url" );
+ }
+
+ HGLOG_OUT();
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::PreCreateWebAddressFieldTypesL
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::PreCreateWebAddressHomeFieldTypesL()
+ {
+ HGLOG_CONTEXT( PreCreateWebAddressHomeFieldTypesL, HGLOG_LOCAL );
+ HGLOG_IN();
+
+ iWebAddressHomeFieldTypes = CVPbkFieldTypeRefsList::NewL();
+ const MVPbkFieldTypeList& types( FieldTypes() );
+ TVPbkFieldVersitProperty prop;
+ const MVPbkFieldType* t;
+
+ prop.Parameters().Add( EVPbkVersitParamHOME );
+ prop.SetName( EVPbkVersitNameURL );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iWebAddressHomeFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try home url" );
+ }
+
+ HGLOG_OUT();
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::PreCreateWebAddressFieldTypesL
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::PreCreateWebAddressWorkFieldTypesL()
+ {
+ HGLOG_CONTEXT( PreCreateWebAddressWorkFieldTypesL, HGLOG_LOCAL );
+ HGLOG_IN();
+
+ iWebAddressWorkFieldTypes = CVPbkFieldTypeRefsList::NewL();
+ const MVPbkFieldTypeList& types( FieldTypes() );
+ TVPbkFieldVersitProperty prop;
+ const MVPbkFieldType* t;
+
+ prop.Parameters().Add( EVPbkVersitParamWORK );
+ prop.SetName( EVPbkVersitNameURL );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iWebAddressWorkFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try work url" );
+ }
+
+ HGLOG_OUT();
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::PreCreateHomeAddressFieldTypesL
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::PreCreateHomeAddressFieldTypesL()
+ {
+ HGLOG_CONTEXT( PreCreateHomeAddressFieldTypesL, HGLOG_LOCAL );
+ HGLOG_IN();
+
+ iHomeAddressFieldTypes = CVPbkFieldTypeRefsList::NewL();
+ const MVPbkFieldTypeList& types( FieldTypes() );
+ TVPbkFieldVersitProperty prop;
+ const MVPbkFieldType* t;
+ prop.Parameters().Add( EVPbkVersitParamHOME );
+
+ prop.SetName( EVPbkVersitNameADR );
+ prop.SetSubField( EVPbkVersitSubFieldCountry );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iHomeAddressFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try home country" );
+ }
+
+ prop.SetName( EVPbkVersitNameADR );
+ prop.SetSubField( EVPbkVersitSubFieldRegion );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iHomeAddressFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try home region" );
+ }
+
+ prop.SetName( EVPbkVersitNameADR );
+ prop.SetSubField( EVPbkVersitSubFieldLocality );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iHomeAddressFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try home locality" );
+ }
+
+ prop.SetName( EVPbkVersitNameADR );
+ prop.SetSubField( EVPbkVersitSubFieldStreet );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iHomeAddressFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try home street" );
+ }
+
+ HGLOG_OUT();
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::PreCreateWorkAddressFieldTypesL
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::PreCreateWorkAddressFieldTypesL()
+ {
+ HGLOG_CONTEXT( PreCreateWorkAddressFieldTypesL, HGLOG_LOCAL );
+ HGLOG_IN();
+
+ iWorkAddressFieldTypes = CVPbkFieldTypeRefsList::NewL();
+ const MVPbkFieldTypeList& types( FieldTypes() );
+ TVPbkFieldVersitProperty prop;
+ const MVPbkFieldType* t;
+ prop.Parameters().Add( EVPbkVersitParamWORK );
+
+ prop.SetName( EVPbkVersitNameADR );
+ prop.SetSubField( EVPbkVersitSubFieldCountry );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iWorkAddressFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try work country" );
+ }
+
+ prop.SetName( EVPbkVersitNameADR );
+ prop.SetSubField( EVPbkVersitSubFieldRegion );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iWorkAddressFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try work region" );
+ }
+
+ prop.SetName( EVPbkVersitNameADR );
+ prop.SetSubField( EVPbkVersitSubFieldLocality );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iWorkAddressFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try work locality" );
+ }
+
+ prop.SetName( EVPbkVersitNameADR );
+ prop.SetSubField( EVPbkVersitSubFieldStreet );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ iWorkAddressFieldTypes->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "will try work street" );
+ }
+
+ HGLOG_OUT();
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::TryTextLookupL
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::TryTextLookupL( const TDesC& aName,
+ CVPbkContactLinkArray& aLinkArray )
+ {
+ HGLOG_CONTEXT( TryTextLookupL, HGLOG_LOCAL );
+ HGLOG_IN();
+
+ CVPbkFieldTypeRefsList* fieldTypes = CVPbkFieldTypeRefsList::NewL();
+ CleanupStack::PushL( fieldTypes );
+
+ // try name and email and ovi id fields
+ if ( !iNameFieldTypes )
+ {
+ PreCreateNameFieldTypesL();
+ }
+ for ( TInt i = 0, ie = iNameFieldTypes->FieldTypeCount(); i != ie; ++i )
+ {
+ fieldTypes->AppendL( iNameFieldTypes->FieldTypeAt( i ) );
+ }
+ if ( !iEmailFieldTypes )
+ {
+ PreCreateEmailFieldTypesL();
+ }
+ for ( TInt i = 0, ie = iEmailFieldTypes->FieldTypeCount(); i != ie; ++i )
+ {
+ fieldTypes->AppendL( iEmailFieldTypes->FieldTypeAt( i ) );
+ }
+ if ( !iXspIdFieldTypes )
+ {
+ PreCreateXspIdFieldTypesL();
+ }
+ for ( TInt i = 0, ie = iXspIdFieldTypes->FieldTypeCount(); i != ie; ++i )
+ {
+ fieldTypes->AppendL( iXspIdFieldTypes->FieldTypeAt( i ) );
+ }
+
+ SplitAndMatchL( aName, *fieldTypes, aLinkArray );
+
+ CleanupStack::PopAndDestroy( fieldTypes );
+ HGLOG_OUT();
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::TryNumberLookupL
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::TryNumberLookupL( const TDesC& aNumber,
+ CVPbkContactLinkArray& aLinkArray )
+ {
+ HGLOG_CONTEXT( TryNumberLookupL, HGLOG_LOCAL );
+ HGLOG_IN();
+
+ MatchPhoneNumberL( aNumber,
+ KNumberMatchLenFromRight,
+ CVPbkPhoneNumberMatchStrategy::EVPbkMatchFlagsNone,
+ aLinkArray );
+
+ HGLOG_OUT();
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::GetTextFieldsL
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::GetTextFieldsL(
+ const CVPbkFieldTypeRefsList& aList,
+ const MVPbkStoreContactFieldCollection& aFieldCollection,
+ CDesCArray& aArray )
+ {
+ HGLOG_CONTEXT( GetTextFieldsL, HGLOG_LOCAL );
+ HGLOG_IN();
+
+ for ( TInt i = 0, ie = aFieldCollection.FieldCount(); i != ie; ++i )
+ {
+ const MVPbkStoreContactField& field( aFieldCollection.FieldAt( i ) );
+ const MVPbkFieldType* type = field.BestMatchingFieldType();
+ if ( type && aList.ContainsSame( *type ) )
+ {
+ const MVPbkContactFieldData& fdata( field.FieldData() );
+ if ( fdata.DataType() == EVPbkFieldStorageTypeText )
+ {
+ const MVPbkContactFieldTextData& fdata2 =
+ MVPbkContactFieldTextData::Cast( fdata );
+ const TDesC& text( fdata2.Text() );
+ aArray.AppendL( text );
+ HGLOG1( HGLOG_INFO, "found: '%S'", &text );
+ }
+ }
+ }
+
+ HGLOG_OUT();
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::GetNumbersL
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::GetNumbersL(
+ MVPbkStoreContactFieldCollection& aFieldCollection,
+ CDesCArray& aArray )
+ {
+ HGLOG_CONTEXT( GetNumbersL, HGLOG_LOCAL );
+ HGLOG_IN();
+
+ if ( !iNumberFieldTypes )
+ {
+ PreCreateNumberFieldTypesL();
+ }
+ GetTextFieldsL( *iNumberFieldTypes, aFieldCollection, aArray );
+
+ HGLOG_OUT();
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::GetEmailAddressesL
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::GetEmailAddressesL(
+ MVPbkStoreContactFieldCollection& aFieldCollection,
+ CDesCArray& aArray )
+ {
+ HGLOG_CONTEXT( GetEmailAddressesL, HGLOG_LOCAL );
+ HGLOG_IN();
+
+ if ( !iEmailFieldTypes )
+ {
+ PreCreateEmailFieldTypesL();
+ }
+ GetTextFieldsL( *iEmailFieldTypes, aFieldCollection, aArray );
+
+ HGLOG_OUT();
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::GetAddressesL
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::GetAddressesL(
+ MVPbkStoreContactFieldCollection& aFieldCollection,
+ CDesCArray& aArray )
+ {
+ HGLOG_CONTEXT( GetAddressesL, HGLOG_LOCAL );
+ HGLOG_IN();
+
+ CDesC16ArrayFlat* arr = new ( ELeave ) CDesC16ArrayFlat( KArrayGranularity );
+ CleanupStack::PushL( arr );
+
+ if ( !iAddressFieldTypes )
+ {
+ PreCreateAddressFieldTypesL();
+ }
+ GetTextFieldsL( *iAddressFieldTypes, aFieldCollection, *arr );
+ if ( arr->Count() )
+ {
+ HBufC* combined = CombineStringsLC( *arr );
+ aArray.AppendL( *combined );
+ HGLOG1( HGLOG_INFO, "added '%S'", combined );
+ CleanupStack::PopAndDestroy( combined );
+ }
+
+ arr->Reset();
+ if ( !iHomeAddressFieldTypes )
+ {
+ PreCreateHomeAddressFieldTypesL();
+ }
+ GetTextFieldsL( *iHomeAddressFieldTypes, aFieldCollection, *arr );
+ if ( arr->Count() )
+ {
+ HBufC* combined = CombineStringsLC( *arr );
+ aArray.AppendL( *combined );
+ HGLOG1( HGLOG_INFO, "added '%S'", combined );
+ CleanupStack::PopAndDestroy( combined );
+ }
+
+ arr->Reset();
+ if ( !iWorkAddressFieldTypes )
+ {
+ PreCreateWorkAddressFieldTypesL();
+ }
+ GetTextFieldsL( *iWorkAddressFieldTypes, aFieldCollection, *arr );
+ if ( arr->Count() )
+ {
+ HBufC* combined = CombineStringsLC( *arr );
+ aArray.AppendL( *combined );
+ HGLOG1( HGLOG_INFO, "added '%S'", combined );
+ CleanupStack::PopAndDestroy( combined );
+ }
+
+ CleanupStack::PopAndDestroy( arr );
+ HGLOG_OUT();
+ }
+
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::GetWebAddressesL
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::GetWebAddressesL(
+ MVPbkStoreContactFieldCollection& aFieldCollection,
+ CDesCArray& aArray,
+ TWebAddressesType aType )
+ {
+ HGLOG_CONTEXT( GetWebAddressesL, HGLOG_LOCAL );
+ HGLOG_IN();
+ CVPbkFieldTypeRefsList* addressFieldTypes( NULL );
+
+ switch ( aType )
+ {
+ case EWebAddresses:
+ {
+ if ( !iWebAddressFieldTypes )
+ {
+ PreCreateWebAddressFieldTypesL();
+ }
+ addressFieldTypes = iWebAddressFieldTypes;
+ }
+ break;
+
+ case EWebAddressesHome:
+ {
+ if ( !iWebAddressHomeFieldTypes )
+ {
+ PreCreateWebAddressHomeFieldTypesL();
+ }
+ addressFieldTypes = iWebAddressHomeFieldTypes;
+ }
+ break;
+
+ case EWebAddressesWork:
+ {
+ if ( !iWebAddressWorkFieldTypes )
+ {
+ PreCreateWebAddressWorkFieldTypesL();
+ }
+ addressFieldTypes = iWebAddressWorkFieldTypes;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if( addressFieldTypes )
+ {
+ GetTextFieldsL( *addressFieldTypes, aFieldCollection, aArray );
+ }
+
+ HGLOG_OUT();
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::GetThumbnailL
+// ----------------------------------------------------------------------------
+EXPORT_C CFbsBitmap* CHgCtxContactMatcher::GetThumbnailL(
+ MVPbkStoreContactFieldCollection& aFieldCollection )
+ {
+ HGLOG_CONTEXT( GetThumbnailL, HGLOG_LOCAL );
+ HGLOG_IN();
+
+ CFbsBitmap* result = 0;
+ TVPbkFieldVersitProperty prop;
+ prop.SetName( EVPbkVersitNamePHOTO );
+ const MVPbkFieldType* t = FieldTypes().FindMatch( prop, 0 );
+ if ( t )
+ {
+ HGLOG0( HGLOG_INFO, "photo field type found" );
+ for ( TInt i = 0, ie = aFieldCollection.FieldCount(); i != ie; ++i )
+ {
+ const MVPbkStoreContactField& field( aFieldCollection.FieldAt( i ) );
+ const MVPbkFieldType* type = field.BestMatchingFieldType();
+ if ( type && type->IsSame( *t ) )
+ {
+ const MVPbkContactFieldData& fdata( field.FieldData() );
+ if ( fdata.DataType() == EVPbkFieldStorageTypeBinary )
+ {
+ HGLOG0( HGLOG_INFO, "found thumbnail" );
+ const MVPbkContactFieldBinaryData& fdata2 =
+ MVPbkContactFieldBinaryData::Cast( fdata );
+ TPtrC8 data( fdata2.BinaryData() );
+ CImageDecoder* decoder = 0;
+ // DataNewL does not seem to work properly with
+ // EOptionAlwaysThread, it will hang in WaitForRequest
+ // for ever, at least in the panel app.
+ // So write the image to a temporary file (duhhh...)
+ // and use FileNewL.
+ RFile f;
+ TFileName tempFileName;
+ iFsSession->CreatePrivatePath( EDriveC );
+ iFsSession->PrivatePath( tempFileName );
+ _LIT( KDriveC, "C:" );
+ _LIT( KTempName, "hgctxthumb" );
+ tempFileName.Insert( 0, KDriveC );
+ tempFileName.Append( KTempName );
+ HGLOG1( HGLOG_INFO, "tempfn='%S'", &tempFileName );
+ User::LeaveIfError( f.Replace( *iFsSession, tempFileName,
+ EFileWrite ) );
+ f.Write( data, data.Length() );
+ f.Close();
+ TRAPD( err, decoder = CImageDecoder::FileNewL( *iFsSession,
+ tempFileName,
+ CImageDecoder::EOptionAlwaysThread ) );
+ HGLOG1( HGLOG_INFO, "decoder NewL result: %d", err );
+ if ( err == KErrNone )
+ {
+ CleanupStack::PushL( decoder );
+ result = new ( ELeave ) CFbsBitmap;
+ CleanupStack::PushL( result );
+ TSize sz( decoder->FrameInfo().iOverallSizeInPixels );
+ TDisplayMode mode( decoder->FrameInfo().iFrameDisplayMode );
+ HGLOG3( HGLOG_INFO, "size=%dx%d, mode=%d", sz.iWidth,
+ sz.iHeight, mode );
+ User::LeaveIfError( result->Create( sz, mode ) );
+
+ TRequestStatus status;
+ HGLOG0( HGLOG_INFO, "starting to convert" );
+ decoder->Convert( &status, *result );
+ User::WaitForRequest( status );
+ HGLOG1( HGLOG_INFO, "decoder Convert result: %d",
+ status.Int() );
+ CleanupStack::Pop( result );
+ CleanupStack::PopAndDestroy( decoder );
+
+ if ( status.Int() != KErrNone )
+ {
+ delete result;
+ result = 0;
+ }
+ else
+ {
+ // stop and return the bitmap
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ HGLOG_OUT();
+ return result;
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::IsPhoneNumberL
+// ----------------------------------------------------------------------------
+EXPORT_C TBool CHgCtxContactMatcher::IsPhoneNumberL( const TDesC& aData )
+ {
+ TBool result = EFalse;
+ CFindItemEngine::SFoundItem item;
+ CFindItemEngine* search = CFindItemEngine::NewL( aData,
+ CFindItemEngine::EFindItemSearchPhoneNumberBin );
+ if ( search->ItemCount() )
+ {
+ search->Item( item );
+ result = item.iStartPos == 0;
+ }
+ delete search;
+ return result;
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::IsEmailAddressL
+// ----------------------------------------------------------------------------
+EXPORT_C TBool CHgCtxContactMatcher::IsEmailAddressL( const TDesC& aData )
+ {
+ TBool result = EFalse;
+ CFindItemEngine::SFoundItem item;
+ CFindItemEngine* search = CFindItemEngine::NewL( aData,
+ CFindItemEngine::EFindItemSearchMailAddressBin );
+ if ( search->ItemCount() )
+ {
+ search->Item( item );
+ result = item.iStartPos == 0;
+ }
+ delete search;
+ return result;
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::GetNamesForFindL
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::GetNamesForFindL(
+ MVPbkStoreContactFieldCollection& aFieldCollection,
+ CDesCArray& aArray )
+ {
+ CVPbkFieldTypeRefsList* nameTypes = CVPbkFieldTypeRefsList::NewL();
+ CleanupStack::PushL( nameTypes );
+ const MVPbkFieldTypeList& types( FieldTypes() );
+ TVPbkFieldVersitProperty prop;
+ const MVPbkFieldType* t;
+
+ prop.SetName( EVPbkVersitNameN );
+ prop.SetSubField( EVPbkVersitSubFieldGivenName );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ nameTypes->AppendL( *t );
+ }
+
+ prop.SetName( EVPbkVersitNameN );
+ prop.SetSubField( EVPbkVersitSubFieldFamilyName );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ nameTypes->AppendL( *t );
+ }
+
+ for ( TInt i = 0, ie = aFieldCollection.FieldCount(); i != ie; ++i )
+ {
+ const MVPbkStoreContactField& field( aFieldCollection.FieldAt( i ) );
+ t = field.MatchFieldType( 0 );
+ if ( t && nameTypes->ContainsSame( *t ) )
+ {
+ const MVPbkContactFieldData& fdata( field.FieldData() );
+ if ( fdata.DataType() == EVPbkFieldStorageTypeText )
+ {
+ const MVPbkContactFieldTextData& fdata2 =
+ MVPbkContactFieldTextData::Cast( fdata );
+ aArray.AppendL( fdata2.Text() );
+ }
+ }
+ }
+
+ CleanupStack::PopAndDestroy( nameTypes );
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::GetNamesForFindL
+// ----------------------------------------------------------------------------
+EXPORT_C HBufC* CHgCtxContactMatcher::GetNamesForFindL(
+ MVPbkStoreContactFieldCollection& aFieldCollection )
+ {
+ CDesC16ArrayFlat* arr = new ( ELeave ) CDesC16ArrayFlat( KArrayGranularity );
+ CleanupStack::PushL( arr );
+ GetNamesForFindL( aFieldCollection, *arr );
+ HBufC* result = CombineStringsLC( *arr );
+ CleanupStack::Pop( result );
+ CleanupStack::PopAndDestroy( arr );
+ return result;
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::SplitFindStringL
+// ----------------------------------------------------------------------------
+EXPORT_C CDesCArray* CHgCtxContactMatcher::SplitFindStringL(const TDesC& aFindString)
+ {
+ CDesCArray* wordArray = new ( ELeave ) CDesCArrayFlat( KArrayGranularity );
+ CleanupStack::PushL( wordArray );
+
+ TVPbkWordParserCallbackParam parser( &aFindString, wordArray );
+ FindWordSplitterL( &parser );
+
+ CleanupStack::Pop(); // wordArray
+ return parser.iWordArray;
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::SplitMsgContactL
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::SplitMsgContactL( const TDesC& aString,
+ CDesCArray& aArray )
+ {
+ TInt pos = aString.Locate( '<' );
+ if ( pos >= 0 )
+ {
+ // skip spaces before '<'
+ TInt endPos = pos - 1;
+ while ( endPos > 0 && TChar( aString[endPos] ).IsSpace() )
+ {
+ --endPos;
+ }
+ // take the text before '<'
+ aArray.AppendL( aString.Left( endPos + 1 ) );
+ // take the text between '<' and '>'
+ TInt closePos = aString.Locate( '>' );
+ if ( closePos > pos )
+ {
+ aArray.AppendL( aString.Mid( pos + 1, closePos - pos - 1 ) );
+ }
+ }
+ else
+ {
+ aArray.AppendL( aString );
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::GetCustomFieldL
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::GetCustomFieldL(
+ MVPbkStoreContactFieldCollection& aFieldCollection,
+ CDesCArray& aArray,
+ TVPbkFieldTypeName aVersitName,
+ TVPbkFieldTypeParameter aVersitParam )
+ {
+ HGLOG_CONTEXT( GetCustomFieldL, HGLOG_LOCAL );
+ HGLOG_IN();
+
+ CVPbkFieldTypeRefsList* typeList = GetCustomFieldTypeLC(
+ aVersitName, aVersitParam );
+
+ GetTextFieldsL( *typeList, aFieldCollection, aArray );
+
+ CleanupStack::PopAndDestroy( typeList );
+ HGLOG_OUT();
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::GetCustomFieldTypeLC
+// ----------------------------------------------------------------------------
+EXPORT_C CVPbkFieldTypeRefsList* CHgCtxContactMatcher::GetCustomFieldTypeLC(
+ TVPbkFieldTypeName aVersitName,
+ TVPbkFieldTypeParameter aVersitParam )
+ {
+ HGLOG_CONTEXT( GetCustomFieldTypeLC, HGLOG_LOCAL );
+ HGLOG_IN();
+
+ CVPbkFieldTypeRefsList* typeList = CVPbkFieldTypeRefsList::NewL();
+ CleanupStack::PushL( typeList );
+ const MVPbkFieldTypeList& types( FieldTypes() );
+ TVPbkFieldVersitProperty prop;
+ const MVPbkFieldType* t;
+
+ prop.SetName( aVersitName );
+ prop.Parameters().Add( aVersitParam );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ typeList->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "field found" );
+ }
+
+ HGLOG_OUT();
+ return typeList;
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::GetImppFieldL
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::GetImppFieldL(
+ MVPbkStoreContactFieldCollection& aFieldCollection,
+ CDesCArray* aSchemeOnlyArray,
+ CDesCArray* aUriOnlyArray,
+ CDesCArray* aFullArray )
+ {
+ HGLOG_CONTEXT( GetImppFieldL, HGLOG_LOCAL );
+ HGLOG_IN();
+
+ // this function will not build on TUBE
+ CVPbkFieldTypeRefsList* typeList = CVPbkFieldTypeRefsList::NewL();
+ CleanupStack::PushL( typeList );
+ const MVPbkFieldTypeList& types( FieldTypes() );
+ TVPbkFieldVersitProperty prop;
+ const MVPbkFieldType* t;
+ prop.SetName( EVPbkVersitNameIMPP );
+ t = types.FindMatch( prop, 0 );
+ if ( t )
+ {
+ typeList->AppendL( *t );
+ HGLOG0( HGLOG_INFO, "type found" );
+ }
+ for ( TInt i = 0, ie = aFieldCollection.FieldCount(); i != ie; ++i )
+ {
+ const MVPbkStoreContactField& field( aFieldCollection.FieldAt( i ) );
+ const MVPbkFieldType* type = field.BestMatchingFieldType();
+ if ( type && typeList->ContainsSame( *type ) )
+ {
+ const MVPbkContactFieldData& fdata( field.FieldData() );
+ HGLOG1( HGLOG_INFO, "field found %d", fdata.DataType() );
+ if ( fdata.DataType() == EVPbkFieldStorageTypeUri )
+ {
+ const MVPbkContactFieldUriData& fdata2 =
+ MVPbkContactFieldUriData::Cast( fdata );
+ const TDesC& schemeOnly( fdata2.Scheme() );
+ const TDesC& uriOnly( fdata2.Text() );
+ const TDesC& fullText( fdata2.Uri() );
+ HGLOG3( HGLOG_INFO, "'%S' + '%S' = '%S'",
+ &schemeOnly, &uriOnly, &fullText );
+ if ( aSchemeOnlyArray )
+ {
+ aSchemeOnlyArray->AppendL( schemeOnly );
+ }
+ if ( aUriOnlyArray )
+ {
+ aUriOnlyArray->AppendL( uriOnly );
+ }
+ if ( aFullArray )
+ {
+ aFullArray->AppendL( fullText );
+ }
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy( typeList );
+
+ HGLOG_OUT();
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::FindContactWithBirthdayL
+// ----------------------------------------------------------------------------
+EXPORT_C void CHgCtxContactMatcher::FindContactWithBirthdayL(
+ const TTime& aDate,
+ CVPbkContactLinkArray& aLinkArray )
+ {
+ HGLOG_CONTEXT( FindContactWithBirthdayL, HGLOG_LOCAL );
+ HGLOG1_IN( "%Ld", aDate.Int64() );
+
+ // extract month and day
+ TDateTime dt = aDate.DateTime();
+ TInt month = dt.Month();
+ TInt day = dt.Day();
+ HGLOG2( HGLOG_INFO, "wanted month = %d day = %d", month, day );
+
+ CVPbkFieldTypeRefsList* emptyList = CVPbkFieldTypeRefsList::NewL();
+ CleanupStack::PushL( emptyList );
+
+ // create view with all contacts
+ CVPbkContactViewDefinition* def = CVPbkContactViewDefinition::NewLC();
+ def->SetType( EVPbkContactsView );
+ def->SetUriL( VPbkContactStoreUris::DefaultCntDbUri() );
+ MVPbkContactViewBase* view = iContactManager->CreateContactViewLC(
+ *this, *def, *emptyList );
+
+ HGLOG0( HGLOG_INFO, "starting wait" );
+ iASchedulerWait.Start();
+ HGLOG0( HGLOG_INFO, "after wait" );
+
+ // view is ready
+ TInt ctCount = view->ContactCountL();
+ HGLOG1( HGLOG_INFO, "contact count: %d", ctCount );
+
+ // find the birthday field type
+ const MVPbkFieldTypeList& types( FieldTypes() );
+ TVPbkFieldVersitProperty prop;
+ const MVPbkFieldType* bdayFt;
+ prop.SetName( EVPbkVersitNameBDAY );
+ prop.SetSubField( EVPbkVersitSubFieldNone );
+ bdayFt = types.FindMatch( prop, 0 );
+
+ if ( bdayFt && ctCount )
+ {
+ HGLOG0( HGLOG_INFO, "found bday field type" );
+ TTime nullTime( KNullTime );
+ // go through all contacts and check birthday field values
+ for ( TInt i = 0; i < ctCount; ++i )
+ {
+ MVPbkContactLink* link( view->CreateLinkLC( i ) );
+ MVPbkStoreContact* contact = 0;
+ GetStoreContactL( *link, &contact );
+ if ( contact )
+ {
+ HGLOG1( HGLOG_INFO, "got contact, idx %d", i );
+ contact->PushL();
+ TTime bday;
+ bday = GetFieldDataDateTimeL( *contact, *bdayFt );
+ if ( bday != nullTime )
+ {
+ HGLOG1( HGLOG_INFO, "found bday %Ld", bday.Int64() );
+ dt = bday.DateTime();
+ TInt thisMonth = dt.Month();
+ TInt thisDay = dt.Day();
+ HGLOG2( HGLOG_INFO, "for this contact month = %d day = %d",
+ thisMonth, thisDay );
+ if ( thisMonth == month && thisDay == day )
+ {
+ HGLOG0( HGLOG_INFO, "match" );
+ aLinkArray.AppendL( link );
+ link = 0;
+ }
+ }
+ CleanupStack::PopAndDestroy(); // contact
+ }
+ CleanupStack::Pop(); // if matched then no ownership and link is NULL by now
+ delete link;
+ }
+ }
+
+ CleanupStack::PopAndDestroy(); // view
+ CleanupStack::PopAndDestroy( def );
+ CleanupStack::PopAndDestroy( emptyList );
+
+ HGLOG_OUT();
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::ContactViewReady
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::ContactViewReady(
+ MVPbkContactViewBase& aView )
+ {
+ HGLOG_CONTEXT( ContactViewReady, HGLOG_LOCAL );
+ HGLOG_IN();
+
+ if ( iASchedulerWait.IsStarted() )
+ {
+ iASchedulerWait.AsyncStop();
+ }
+
+ aView.RemoveObserver( *this );
+
+ HGLOG_OUT();
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::ContactViewUnavailable
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::ContactViewUnavailable(
+ MVPbkContactViewBase& /*aView*/ )
+ {
+ // means that view is unavailable for now
+ // but ContactViewReady will be called at some point
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::ContactAddedToView
+// ----------------------------------------------------------------------------
+void CHgCtxContactMatcher::ContactAddedToView(
+ MVPbkContactViewBase& /*aView*/,
+ TInt /*aIndex*/,
+ const MVPbkContactLink& /*aContactLink*/ )
+ {
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::ContactRemovedFromView
+// ----------------------------------------------------------------------------
+ void CHgCtxContactMatcher::ContactRemovedFromView(
+ MVPbkContactViewBase& /*aView*/,
+ TInt /*aIndex*/,
+ const MVPbkContactLink& /*aContactLink*/ )
+ {
+ }
+
+// ----------------------------------------------------------------------------
+// CHgCtxContactMatcher::ContactViewError
+// ----------------------------------------------------------------------------
+ void CHgCtxContactMatcher::ContactViewError(
+ MVPbkContactViewBase& aView,
+ TInt aError,
+ TBool /*aErrorNotified*/ )
+ {
+ HGLOG_CONTEXT( ContactViewError, HGLOG_LOCAL );
+ HGLOG1_IN( "aError = %d", aError );
+
+ if ( iASchedulerWait.IsStarted() )
+ {
+ iASchedulerWait.AsyncStop();
+ }
+
+ aView.RemoveObserver( *this );
+
+ HGLOG_OUT();
+ }
+
+
+// End of File