phonebookengines_old/contactsmodel/cntmodel/src/ccontactprivate.cpp
changeset 40 b46a585f6909
equal deleted inserted replaced
37:fd64c38c277d 40:b46a585f6909
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 /**
       
    17  @file
       
    18  @internalComponent
       
    19  @released
       
    20 */
       
    21 
       
    22 
       
    23 #include <cntdb.h>
       
    24 #include "CNTSTD.H"
       
    25 #include "rcntmodel.h"
       
    26 #include "ccontactprivate.h"
       
    27 #include "cntviewprivate.h"
       
    28 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    29 #include "cntdb_internal.h"
       
    30 #include "cntsyncecom.h"
       
    31 #endif
       
    32 
       
    33 
       
    34 const TInt KMaxItemsInTemplateCache = 8; // Maximum number of cached templates.
       
    35 const TInt KInitialSortArraySize = 20; // Initial size of sort array.
       
    36 
       
    37 
       
    38 /**
       
    39 CTextFieldMinimal destructor.
       
    40 */
       
    41 CTextFieldMinimal::~CTextFieldMinimal()
       
    42 	{
       
    43 	delete iText;
       
    44 	}
       
    45 
       
    46 
       
    47 /**
       
    48 CTextFieldMinimal second phase constructor.
       
    49 */
       
    50 void CTextFieldMinimal::ConstructL(const TDesC &aText, TContactItemId aId)
       
    51 	{
       
    52 	iText=aText.AllocL();
       
    53 	iId=aId;
       
    54 	}
       
    55 
       
    56 
       
    57 /**
       
    58 CSortArray first phase constructor.
       
    59 */
       
    60 CSortArray::CSortArray()
       
    61 	:
       
    62 	iArray(KInitialSortArraySize)
       
    63 	{
       
    64 	}
       
    65 
       
    66 
       
    67 /**
       
    68 CSortArray destructor.
       
    69 */
       
    70 CSortArray::~CSortArray()
       
    71 	{
       
    72 	iArray.ResetAndDestroy();
       
    73 	iArray.Close();
       
    74 	}
       
    75 
       
    76 
       
    77 /**
       
    78 Create a CTextFieldMinimal object using the given text and Contact ID and append
       
    79 it to the sort array.
       
    80 
       
    81 @param aText Text for CTextFieldMinimal object.
       
    82 @param aId Contact ID for CTextFieldMinimal object.
       
    83 */
       
    84 void CSortArray::AppendL(const TDesC &aText, TContactItemId aId)
       
    85 	{
       
    86 	CTextFieldMinimal *tm=new(ELeave) CTextFieldMinimal;
       
    87 	CleanupStack::PushL(tm);
       
    88 	tm->ConstructL(aText, aId);
       
    89 	User::LeaveIfError(iArray.Append(tm));
       
    90 	CleanupStack::Pop(); // tm
       
    91 	}
       
    92 
       
    93 
       
    94 /**
       
    95 Sort the sort array using the given sort order.
       
    96 
       
    97 @param aOrder EAsc for ascending order, EDesc for descending order.
       
    98 */
       
    99 void CSortArray::SortL(CContactDatabase::TSortPref::TOrder aOrder)
       
   100 	{
       
   101 	// If nothing to sort then return immediately.
       
   102 	if (iArray.Count()==0)
       
   103 		{
       
   104 		return;
       
   105 		}
       
   106 		
       
   107 	// Sort the array in ascending sort order using the default algorithm to
       
   108 	// compare the elements in the sort array.
       
   109 	iArray.Sort(TLinearOrder<CTextFieldMinimal>(DefaultAlgorithmToCompareNames));
       
   110 	
       
   111 	// If descending sort order then reverse the elements in the sort array.
       
   112 	if (aOrder==CContactDatabase::TSortPref::EDesc)
       
   113 		{
       
   114 		TInt count=Count();
       
   115 		TInt end=count/2;
       
   116 		TInt index2=count-1;
       
   117 		for(TInt index=0;index<end;index++)
       
   118 			{
       
   119 			CTextFieldMinimal *tfm=(CTextFieldMinimal *)iArray[index];
       
   120 			iArray[index]=iArray[index2];
       
   121 			iArray[index2]=tfm;
       
   122 			index2--;
       
   123 			}
       
   124 		}
       
   125 	}
       
   126 
       
   127 
       
   128 /**
       
   129 Compare the text in the given CTextFieldMinimal objects.
       
   130 
       
   131 The custom TCollation method is required to ensure that the collated comparison
       
   132 will not ignore spaces and punctuation (which it does by default).
       
   133 
       
   134 Mem::CollationMethodByIndex() is an exec call and is hence relatively expensive.
       
   135 Although it is inefficient to create a collation method each time this method is
       
   136 called, there is no benefit in storing TCollationMethod as a member of
       
   137 CSortArray because this method must be static.
       
   138 
       
   139 @param aName1
       
   140 @param aName2
       
   141 
       
   142 @return A positive value if text in aName1 is greater than text in aName2, a
       
   143 negative value if text in aName1 is less than text in aName2 and zero if the
       
   144 text in both aName1 and aName2 is the same.
       
   145 */
       
   146 TInt CSortArray::DefaultAlgorithmToCompareNames(const CTextFieldMinimal& aName1, const CTextFieldMinimal& aName2)
       
   147 	{
       
   148 	TCollationMethod collateMethod;
       
   149 	collateMethod = *Mem::CollationMethodByIndex(0);
       
   150 	collateMethod.iFlags|=TCollationMethod::EIgnoreNone;
       
   151 	return aName1.iText->CompareC(*aName2.iText,3,&collateMethod);
       
   152 	}
       
   153 
       
   154 
       
   155 /**
       
   156 Get the Contact ID at the given index in the sort array.
       
   157 
       
   158 @return The Contact ID at the given index.
       
   159 */
       
   160 TContactItemId CSortArray::Id(TInt aIndex) const
       
   161 	{
       
   162 	return(((CTextFieldMinimal *)iArray[aIndex])->iId);
       
   163 	}
       
   164 
       
   165 
       
   166 /**
       
   167 Get the text at the given index in the sort array.
       
   168 
       
   169 @return The text at the given index.
       
   170 */
       
   171 HBufC* CSortArray::Text(TInt aIndex) const
       
   172 	{
       
   173 	return(((CTextFieldMinimal *)iArray[aIndex])->iText);
       
   174 	}
       
   175 
       
   176 
       
   177 /**
       
   178 Merge the given sort array with this sort array starting from the given position
       
   179 in this sort array.
       
   180 
       
   181 @param aDuplicates The sort array to be merged with this sort array.
       
   182 @param aStartPos The starting position for the merge in this sort array.
       
   183 */
       
   184 void CSortArray::Merge(CSortArray *aDuplicates,TInt aStartPos)
       
   185 	{
       
   186 	TInt numDuplicates=aDuplicates->Count();
       
   187 	for (TInt loop=0;loop<numDuplicates;loop++)
       
   188 		{
       
   189 		const TInt index=aStartPos+loop;
       
   190 		delete iArray[index];
       
   191 		iArray[index]=aDuplicates->iArray[0];
       
   192 		aDuplicates->iArray.Remove(0);
       
   193 		}
       
   194 	}
       
   195 
       
   196 
       
   197 /**
       
   198 CCntTemplateCache object factory.
       
   199 
       
   200 @return CCntTemplateCache object.
       
   201 */
       
   202 CCntTemplateCache* CCntTemplateCache::NewL(RCntModel& aCntSvr)
       
   203 	{
       
   204 	CCntTemplateCache* templateCache = new(ELeave) CCntTemplateCache(aCntSvr);
       
   205 	return templateCache;		
       
   206 	}
       
   207 	
       
   208 
       
   209 /**
       
   210 CCntTemplateCache first phase constructor.
       
   211 
       
   212 @param aCntSvr Client Contacts Model session object handle.
       
   213 */
       
   214 CCntTemplateCache::CCntTemplateCache(RCntModel& aCntSvr)
       
   215 	:
       
   216 	iCache(KMaxItemsInTemplateCache),
       
   217 	iCntSvr(aCntSvr),
       
   218 	iTemplateId(KGoldenTemplateId)
       
   219 	{
       
   220 	}
       
   221 
       
   222 
       
   223 /**
       
   224 CCntTemplateCache destructor.
       
   225 */
       
   226 CCntTemplateCache::~CCntTemplateCache()
       
   227 	{
       
   228 	iCache.ResetAndDestroy();
       
   229 	delete iViewDef;
       
   230 	delete iSystemTemplate;
       
   231 	}
       
   232 
       
   233 
       
   234 /**
       
   235 Delete an entry from the template cache.
       
   236 
       
   237 @param aIndex Index of entry in template cache to be deleted.
       
   238 */
       
   239 void CCntTemplateCache::DeleteEntry(TInt aIndex)
       
   240 	{
       
   241 	delete iCache [aIndex];
       
   242 	iCache.Remove(aIndex);
       
   243 	}
       
   244 
       
   245 
       
   246 /**
       
   247 Remove a template from the template cache.
       
   248 
       
   249 @param aId ID of the template which is to be removed from the template cache.
       
   250 */
       
   251 void CCntTemplateCache::RemoveTemplate(TContactItemId aId)
       
   252 	{
       
   253 	for(TInt ii=iCache.Count() - 1; ii >= 0; --ii)
       
   254 		{
       
   255 		if (iCache[ii]->Id() == aId)
       
   256 			{
       
   257 			DeleteEntry(ii);	
       
   258 			}
       
   259 		}
       
   260 	
       
   261 	// Are we removing the system template?
       
   262 	if (iSystemTemplate != NULL && iSystemTemplate->Id() == aId)	
       
   263 		{
       
   264 		delete iSystemTemplate;
       
   265 		iSystemTemplate = NULL;	
       
   266 		}
       
   267 	}
       
   268 
       
   269 
       
   270 /**
       
   271 Get the system template.  If the system template does not yet exist then
       
   272 create it (lazy initialisation).
       
   273 
       
   274 @return CContactItem object reference for the system template.
       
   275 */
       
   276 CContactItem& CCntTemplateCache::SystemTemplateL() 
       
   277 	{
       
   278 	if (!iSystemTemplate)
       
   279 		{
       
   280 		CContactItemViewDef* matchAll = CContactItemViewDef::NewLC(	CContactItemViewDef::EMaskFields,
       
   281 																CContactItemViewDef::EIncludeHiddenFields);
       
   282 		iSystemTemplate = static_cast<CContactItem*>(iCntSvr.ReadContactL(matchAll, KGoldenTemplateId));
       
   283 		CleanupStack::PopAndDestroy(matchAll);
       
   284 		}
       
   285 
       
   286 	return *iSystemTemplate;
       
   287 	}
       
   288 
       
   289 
       
   290 /**
       
   291 Dispose of the system template.  The next time the system template is accessed
       
   292 via the SystemTemplateL() method it will be fetched from the Server.
       
   293 */
       
   294 void CCntTemplateCache::ResetSystemTemplate()
       
   295 	{
       
   296 	delete iSystemTemplate;
       
   297 	iSystemTemplate = NULL;
       
   298 	}
       
   299 
       
   300 
       
   301 /**
       
   302 Get a template from the template cache with the given ID.
       
   303 
       
   304 @param Contact item ID of the template.
       
   305 
       
   306 @return CContactItem object reference for the template.
       
   307 */
       
   308 CContactItem& CCntTemplateCache::TemplateL(TContactItemId aId)
       
   309 	{
       
   310 	if (aId == KGoldenTemplateId)
       
   311 		return SystemTemplateL();
       
   312 	
       
   313 	CContactItem *retVal = NULL;
       
   314 	TInt maxCount 		 = iCache.Count();
       
   315 	TInt ii				 = maxCount;
       
   316 	
       
   317 	// Try to find the template in the cache.
       
   318 	while(ii) 
       
   319 		{
       
   320 		--ii;	
       
   321 		if (iCache[ii]->Id() == aId)
       
   322 			{
       
   323 			retVal = iCache[ii];
       
   324 			break; // Stop searching
       
   325 			}
       
   326 		}
       
   327 		
       
   328 	if (!retVal) // Template does not exist in cache.
       
   329 		{
       
   330 		// Read the template from the Server.
       
   331 		CContactItemViewDef* matchAll = CContactItemViewDef::NewLC(	CContactItemViewDef::EMaskFields,
       
   332 										CContactItemViewDef::EIncludeHiddenFields);
       
   333 		retVal = iCntSvr.ReadContactL(matchAll, aId);
       
   334 		CleanupStack::PopAndDestroy(matchAll);
       
   335 		if (maxCount == KMaxItemsInTemplateCache)
       
   336 			{
       
   337 			// Remove the first item from the cache (cache is maintained in
       
   338 			// using FIFO behaviour i.e. oldest template is removed when cache
       
   339 			// size is exceeded.
       
   340 			DeleteEntry(0);
       
   341 			}
       
   342 		iCache.Append(retVal);		
       
   343 		}
       
   344 		
       
   345 	return *retVal;
       
   346 	}
       
   347 
       
   348 
       
   349 /**
       
   350 Get the default view definition for the template cache.  If the default view 
       
   351 definition does not yet exist then create it (lazy initialisation).
       
   352 
       
   353 @return CContactItemViewDef object reference.
       
   354 
       
   355 @leave KErrNoMemory Out of memory.
       
   356 */
       
   357 CContactItemViewDef& CCntTemplateCache::DefaultViewDefL()
       
   358 	{
       
   359 	if (!iViewDef)
       
   360 		{
       
   361 		iViewDef = CContactItemViewDef::NewL(CContactItemViewDef::EIncludeFields, CContactItemViewDef::EIncludeHiddenFields);
       
   362 		iViewDef->AddL(KUidContactFieldMatchAll);
       
   363 		}
       
   364 	return *iViewDef;	
       
   365 	}
       
   366 
       
   367 	
       
   368 /**
       
   369 Merge the given Contact Item with the template used to create the Contact Item.
       
   370 If no view definition is supplied then use the default view definition.
       
   371 
       
   372 @param aContact Contact Item to be merged with template.
       
   373 @param aViewDef View definition to use.
       
   374 */
       
   375 void CCntTemplateCache::MergeWithTemplateL(CContactItem& aContact, const CContactItemViewDef* aViewDef)
       
   376 	{
       
   377 	if (aContact.TemplateRefId()!= KNullContactId && aContact.Type() != KUidContactCardTemplate)
       
   378 		{
       
   379 		CContactItemViewDef* viewDef = NULL;
       
   380 		if(aViewDef == NULL) // Only create a viewDef if none has been given.
       
   381 			{
       
   382 			viewDef = &(DefaultViewDefL());
       
   383 			}
       
   384 		else 
       
   385 			{
       
   386 			viewDef = const_cast<CContactItemViewDef*>(aViewDef);	
       
   387 			}
       
   388 	
       
   389 		// Restore template fields.
       
   390 		if (aContact.TemplateRefId() != KNullContactId && aContact.Type() != KUidContactCardTemplate)
       
   391 			{
       
   392 			// Get the template ID used to create the Contact Item.
       
   393 			CContactItem* contactTemplate=&(static_cast<CContactTemplate&>(TemplateL(aContact.TemplateRefId())));
       
   394 			aContact.RestoreTemplateFieldsL(SystemTemplateL().CardFields(), contactTemplate->CardFields(), const_cast<CContactItemViewDef&> (*viewDef));
       
   395 			}
       
   396 		}
       
   397 	else if (aContact.Type()==KUidContactCardTemplate)
       
   398 		{
       
   399 		aContact.AddLabelFieldL();
       
   400 		}
       
   401 	}
       
   402 
       
   403 
       
   404 /**
       
   405 CPrivConverter object factory.
       
   406 
       
   407 @param aImplementationUid UID of the converter plugin.
       
   408 
       
   409 @return CPrivConverter object.
       
   410 */
       
   411 CPrivConverter* CPrivConverter::NewL(TUid aImplementationUid)
       
   412 	{
       
   413 	CPrivConverter* self=new(ELeave) CPrivConverter;
       
   414 	CleanupStack::PushL(self);
       
   415 	CVersitTlsData::VersitTlsDataL();
       
   416 	self->LoadEComPluginL(aImplementationUid);
       
   417 	CleanupStack::Pop(self); 
       
   418 	return self;
       
   419 	}
       
   420 /**
       
   421 CPrivConverter object factory.
       
   422 Loads PBAP contact converter plug-in.
       
   423 @param aImplementationUid UID of the converter plugin.
       
   424 @param aContactFieldFilter Specifies contact fields to be exported.
       
   425 @param aCallback Callback to client for providing intra-contact properties.
       
   426 @param aVersion Denotes the vCard version for contact export.
       
   427 @return CPrivConverter object.
       
   428 */
       
   429 CPrivConverter* CPrivConverter::NewL(TUid aUid, TInt64 aContactFieldFilter, MConverterCallBack* aCallback, TVCardVersion aVersion, TBool aExportTel)
       
   430 	{
       
   431 	CPrivConverter* self = new(ELeave) CPrivConverter;
       
   432 	CleanupStack::PushL(self);
       
   433 	CVersitTlsData::VersitTlsDataL();
       
   434 	self->LoadEComPluginL(aUid, aContactFieldFilter, aCallback, aVersion, aExportTel);
       
   435 	CleanupStack::Pop(self); 
       
   436 	return self;
       
   437 	}
       
   438 
       
   439 TInt64 CPrivConverter::GetPBAPFilter() const
       
   440 	{
       
   441 	return iPBAPFilter;
       
   442 	}
       
   443 
       
   444 TBool CPrivConverter::GetExportTel() const
       
   445 	{
       
   446 	return iExportTel;
       
   447 	}
       
   448 
       
   449 TVCardVersion CPrivConverter::GetCurrentVersion() const
       
   450 	{
       
   451 	return iVersion;
       
   452 	}
       
   453 
       
   454 /**
       
   455 CPrivConverter destructor.
       
   456 */
       
   457 CPrivConverter::~CPrivConverter()
       
   458 	{
       
   459 	delete iConverter;
       
   460 	CVersitTlsData::CloseVersitTlsData();
       
   461 	}
       
   462 
       
   463 
       
   464 /**
       
   465 Load the ECOM plugin with the given UID.
       
   466 
       
   467 @param aUid UID of the plugin.
       
   468 @param aContactFieldFilter Specifies contact fields to be exported.
       
   469 @param aCallback Callback to client for providing intra-contact properties.
       
   470 @param aVersion Denotes the vCard version for contact export.
       
   471 */
       
   472 void CPrivConverter::LoadEComPluginL(TUid aUid, TInt64 aContactFieldFilter, MConverterCallBack* aCallback, TVCardVersion aVersion, TBool aExportTel)
       
   473 	{
       
   474 	if(IsImplementationAvailableL(aUid))
       
   475 		{
       
   476 		iVersion = aVersion;
       
   477 		iPBAPFilter = aContactFieldFilter;
       
   478 		iExportTel = aExportTel;
       
   479 		iConverter = CContactEcomConverter::NewL(aUid, aContactFieldFilter, aCallback, aVersion, aExportTel);
       
   480 		}
       
   481 	__ASSERT_DEBUG(ETrue, User::Invariant());
       
   482 	}
       
   483 
       
   484 /**
       
   485 Load the ECOM plugin with the given UID.
       
   486 
       
   487 @param aUid UID of the plugin.
       
   488 */
       
   489 void CPrivConverter::LoadEComPluginL(TUid aUid)
       
   490 	{
       
   491 	if(IsImplementationAvailableL(aUid))
       
   492 		{
       
   493 		iVersion = EVCard21;
       
   494 		iConverter = CContactEcomConverter::NewL(aUid);	
       
   495 		}
       
   496 	__ASSERT_DEBUG(ETrue, User::Invariant());
       
   497 	}
       
   498 
       
   499 /**
       
   500 Finds out if implementation for a given plug-in uid is present as part of vCard Interface.
       
   501 
       
   502 @param aUid UID of the plugin.
       
   503 @return TBool ETrue if implementation exists.
       
   504 
       
   505 @leave KErrNoMemory 
       
   506 @leave KErrNotConnected 
       
   507 @leave KErrArgument 
       
   508 
       
   509 */
       
   510 TBool CPrivConverter::IsImplementationAvailableL(TUid aUid)
       
   511 	{
       
   512 	RImplInfoPtrArray	implInfoArray;
       
   513 	CleanupResetAndDestroyPushL(implInfoArray);
       
   514 
       
   515 	REComSession::ListImplementationsL(KUidEcomCntVCardConverterInterface, implInfoArray);
       
   516 
       
   517 	// Check that aImplementationUid is an implementation of
       
   518 	// KUidEcomCnVCardConverterInterface by checking it is included in
       
   519 	// implInfoArray.
       
   520 	const TInt count = implInfoArray.Count();
       
   521 	__ASSERT_ALWAYS( count > 0, User::Leave(KErrNotFound));
       
   522 
       
   523 	TBool isAvailable = EFalse;
       
   524 
       
   525 	for(TInt i = 0 ; i < count ; ++i)
       
   526 		{
       
   527 		if(	aUid == implInfoArray[i]->ImplementationUid())
       
   528 			{
       
   529 			switch(aUid.iUid)
       
   530 				{
       
   531 				case KUidVCardConvDefaultImpl:
       
   532 					isAvailable = ETrue;
       
   533 				break;
       
   534 				case KUidPBAPVCardConvImpl:
       
   535 					isAvailable = ETrue;
       
   536 				break;
       
   537 				default:
       
   538 				break;
       
   539 				}
       
   540 			break;
       
   541 			}
       
   542 		}
       
   543 	CleanupStack::PopAndDestroy(&implInfoArray);
       
   544 	
       
   545 	return isAvailable;
       
   546 	}
       
   547 
       
   548 /**
       
   549 CContactPlugin constructor.
       
   550 */
       
   551 CContactPlugin::CContactPlugin()
       
   552 	{
       
   553 	}
       
   554 
       
   555 /**
       
   556 CContactPlugin destructor.
       
   557 */
       
   558 CContactPlugin::~CContactPlugin()
       
   559 	{
       
   560 	iDll.Close();
       
   561 	}
       
   562 
       
   563 
       
   564 /**
       
   565 Initialise this TSortPref object from the given stream.
       
   566 
       
   567 @param aStream Stream to read TSortPref object state from.
       
   568 */
       
   569 EXPORT_C void CContactDatabase::TSortPref::InternalizeL(RReadStream& aStream)
       
   570 	{
       
   571 	iFieldType.iUid=aStream.ReadInt32L();
       
   572 	iOrder=STATIC_CAST(CContactDatabase::TSortPref::TOrder,aStream.ReadInt32L());
       
   573 	}
       
   574 
       
   575 /**
       
   576 Store this TSortPref object in the given stream.
       
   577 
       
   578 @param aStream Stream to write TSortPref object state to.
       
   579 */
       
   580 EXPORT_C void CContactDatabase::TSortPref::ExternalizeL(RWriteStream& aStream) const
       
   581 	{
       
   582 	aStream.WriteInt32L(iFieldType.iUid);
       
   583 	aStream.WriteInt32L(iOrder);
       
   584 	}
       
   585 
       
   586 
       
   587 /**
       
   588 Determine if the asynchronous find is complete.
       
   589 	
       
   590 @return ETrue If asynchronous find is complete, EFalse otherwise.
       
   591 */
       
   592 EXPORT_C  TBool CIdleFinder::IsComplete() const
       
   593 /** Checks whether the contact database search is complete.
       
   594 @return ETrue if search is complete, otherwise EFalse.  */
       
   595 	{
       
   596 	return(iContactDatabase==NULL);
       
   597 	}
       
   598 
       
   599 
       
   600 /**
       
   601 Get and take ownership of the Contact IDs.
       
   602 
       
   603 @return Array of Contact IDs.
       
   604 */
       
   605 EXPORT_C  CContactIdArray* CIdleFinder::TakeContactIds()
       
   606 /** Gets an array of contact item IDs where the match is found.
       
   607 @return Array of contact item IDs.  */
       
   608 	{
       
   609 	iOwnsIds=EFalse;
       
   610 	return(iIdsFound);
       
   611 	}
       
   612 
       
   613 
       
   614 /**
       
   615 Get the last asynchronous find error.
       
   616 
       
   617 @return The last asynchronous find error.
       
   618 */
       
   619 EXPORT_C  TInt CIdleFinder::Error() const
       
   620 /** Signals an error while searching the database.
       
   621 @return The error code, if any error occurs during the search operation.  */
       
   622 	{
       
   623 	return iError;
       
   624 	}
       
   625 
       
   626 
       
   627 /**
       
   628 CIdleFinder constructor.
       
   629 */
       
   630 CIdleFinder::CIdleFinder(CContactDatabase &aContactDatabase, const CContactItemFieldDef *aFieldDef, const CContactTextDef* aTextDef, MIdleFindObserver *aObserver)
       
   631 	:
       
   632 	CIdle(CActive::EPriorityIdle),
       
   633 	iContactDatabase(&aContactDatabase),
       
   634 	iFieldDef(aFieldDef), 
       
   635 	iTextDef(aTextDef),
       
   636 	iObserver(aObserver)
       
   637 	{
       
   638 	}
       
   639 
       
   640 
       
   641 /**
       
   642 CIdleFinder destructor.
       
   643 */
       
   644 CIdleFinder::~CIdleFinder()
       
   645 	{
       
   646 	// Only delete the found Contact IDs if ownership has not been taken with
       
   647 	// a call to TakeContactIds().
       
   648 	if (iOwnsIds)
       
   649 		{
       
   650 		delete iIdsFound;
       
   651 		}
       
   652 	delete iFindWords;
       
   653 	}
       
   654 
       
   655 
       
   656 void CIdleFinder::DoCancel()
       
   657 	{
       
   658 	// Setting to NULL indicates complete.
       
   659 	iContactDatabase=NULL;
       
   660 	}
       
   661 
       
   662 
       
   663 /**
       
   664 CIdleFinder object factory.  This form of NewL() should be used when performing
       
   665 an asynchronous find using text and a field definition.
       
   666 
       
   667 @return CIdleFinder object.
       
   668 */
       
   669 CIdleFinder* CIdleFinder::NewL(CContactDatabase &aContactDatabase, const TDesC& aText, const CContactItemFieldDef *aFieldDef, MIdleFindObserver *aObserver)
       
   670 	{
       
   671 	CIdleFinder *finder=new(ELeave) CIdleFinder(aContactDatabase, aFieldDef,NULL,aObserver);
       
   672 	CleanupStack::PushL(finder);
       
   673 	finder->ConstructL(&aText,NULL,NULL);
       
   674 	CleanupStack::Pop(); // finder
       
   675 	return(finder);
       
   676 	}
       
   677 
       
   678 
       
   679 /**
       
   680 CIdleFinder object factory.  This form of NewL() should be used when performing
       
   681 an asynchronous find using "find words"/"find words parser" and a text
       
   682 definition.
       
   683 
       
   684 @return CIdleFinder object.
       
   685 */
       
   686 CIdleFinder* CIdleFinder::NewL(CContactDatabase &aContactDatabase, const MDesCArray* aFindWords,const CContactTextDef* aTextDef, MIdleFindObserver *aObserver, const TCallBack &aWordParserCallback)
       
   687 	{
       
   688 	CIdleFinder *finder=new(ELeave) CIdleFinder(aContactDatabase,NULL,aTextDef,aObserver);
       
   689 	CleanupStack::PushL(finder);
       
   690 	finder->ConstructL(NULL,aFindWords,&aWordParserCallback);
       
   691 	CleanupStack::Pop(); // finder
       
   692 	return(finder);
       
   693 	}
       
   694 
       
   695 
       
   696 /**
       
   697 Set the CIdle object going.
       
   698 */
       
   699 void CIdleFinder::Start()
       
   700 	{
       
   701 	CIdle::Start(TCallBack(CIdleFinder::CallbackL, this));
       
   702 	}
       
   703 
       
   704 
       
   705 TInt CIdleFinder::CallbackL(TAny *aSelf)
       
   706 	{
       
   707 	return ((CIdleFinder *)aSelf)->doFindL();
       
   708 	}
       
   709 
       
   710 
       
   711 TInt CIdleFinder::RunError(TInt aError)
       
   712 	{
       
   713 	iError = aError;
       
   714 	iContactDatabase = NULL;
       
   715 	if (iObserver)
       
   716 		{
       
   717 		iObserver->IdleFindCallback();
       
   718 		}
       
   719 	return KErrNone;
       
   720 	}
       
   721 
       
   722 
       
   723 /**
       
   724 CIdle callback method.  Makes an IPC call into the Server to perform a find
       
   725 iteration.
       
   726 
       
   727 On return from the find iteration from the Server if "find words" were
       
   728 specified when initialising the find then the client supplied "find words
       
   729 parser" is invoked to search the returned Contact IDs.  The search cannot be
       
   730 performed on the server because it is not possible to provide the client
       
   731 supplied callback to the server.
       
   732 
       
   733 @return ETrue if further find iterations are required otherwise EFalse.
       
   734 */
       
   735 TBool CIdleFinder::doFindL()
       
   736 	{
       
   737 	iError = KErrNone;
       
   738 	TBool moreToGo = EFalse;
       
   739 	iOwnsIds = ETrue;
       
   740 	
       
   741 	// Perform a find iteration in the Server.
       
   742 	TRAP(iError, moreToGo = iContactDatabase->iCntSvr->FindAsyncL(iIdsFound));
       
   743 
       
   744 	if (iError != KErrNone)
       
   745 		{
       
   746 		CContactIdArray* newIdArray = CContactIdArray::NewLC();
       
   747 		CleanupStack::Pop(newIdArray);
       
   748 		delete iIdsFound;
       
   749 		iIdsFound = newIdArray;		
       
   750 		}
       
   751 	
       
   752 	if(iFindWords != NULL)
       
   753 		{
       
   754 		// Construct a new Contacts ID array by calling CheckFindL().  This
       
   755 		// method then calls ScanForMatchL() which calls the client's function
       
   756 		// pointer (supplied when the find was initialised) for the "find
       
   757 		// words parser".
       
   758 		CContactIdArray* newIdArray = CContactIdArray::NewLC();
       
   759 		for(TInt i=0;i<iIdsFound->Count();++i)
       
   760 			{
       
   761 			if(CheckFindL((*iIdsFound)[i]))
       
   762 				{
       
   763 				newIdArray->AddL((*iIdsFound)[i]);
       
   764 				}
       
   765 			}
       
   766 		CleanupStack::Pop(newIdArray);
       
   767 
       
   768 		// Dispose of the existing found Contacts IDs and replace with the fully
       
   769 		// filtered Contacts IDs.
       
   770 		delete iIdsFound;
       
   771 		iIdsFound = newIdArray;
       
   772 		}
       
   773 	
       
   774 	if(!moreToGo)
       
   775 		{
       
   776 		// Set to NULL to indicate complete.
       
   777 		iContactDatabase=NULL;
       
   778 		}
       
   779 	
       
   780 	if (iObserver)
       
   781 		{
       
   782 		iObserver->IdleFindCallback();
       
   783 		}
       
   784 	
       
   785 	return moreToGo;
       
   786 	}
       
   787 
       
   788 
       
   789 NONSHARABLE_CLASS(TKeyCmpTextLength) : public TKeyArrayFix
       
   790 	{
       
   791 public:
       
   792 	TKeyCmpTextLength();
       
   793 protected:
       
   794 	// From TKey.
       
   795 	virtual TInt Compare(TInt aLeft,TInt aRight) const;
       
   796 	};
       
   797 
       
   798 
       
   799 TKeyCmpTextLength::TKeyCmpTextLength()
       
   800 	:
       
   801 	// Doesn't matter using ECmpNormal, it's ignored.
       
   802 	TKeyArrayFix(0,ECmpNormal,0)
       
   803 	{
       
   804 	}
       
   805 
       
   806 
       
   807 /**
       
   808 Compare the lengths of the words.
       
   809 */
       
   810 TInt TKeyCmpTextLength::Compare(TInt aLeft,TInt aRight) const
       
   811 	{
       
   812 	TDesC* left=(*((TDesC**)At(aLeft)));
       
   813 	TDesC* right=(*((TDesC**)At(aRight)));
       
   814 	return right->Length()-left->Length();
       
   815 	}
       
   816 
       
   817 
       
   818 /**
       
   819 Initialise and start the asynchronous find.
       
   820 */
       
   821 void CIdleFinder::ConstructL(const TDesC *aText, const MDesCArray* aFindWords, const TCallBack *aWordParserCallback)
       
   822 	{
       
   823 	if(aFindWords != NULL) // Find using a CContactTextDef.
       
   824 		{
       
   825 		// Construct "find words" from the client supplied aFindWords.
       
   826 		iFindWords = new (ELeave) CDesCArrayFlat(5);
       
   827 		for(TInt loop=0;loop<aFindWords->MdcaCount();loop++)
       
   828 			{
       
   829 			// Construct iFindWords which contains all the strings in the search
       
   830 			// surrounded by a *.
       
   831 			TPtrC findWord(aFindWords->MdcaPoint(loop));
       
   832 			TKeyCmpTextLength key;
       
   833 			HBufC* bufPtr=findWord.AllocLC();
       
   834 			iFindWords->CArrayFixBase::InsertIsqAllowDuplicatesL(&bufPtr,key);
       
   835 			CleanupStack::Pop(); // bufPtr
       
   836 			}
       
   837 
       
   838 		// This is the client supplied "find words parser" callback method.
       
   839 		iWordParserCallback = *aWordParserCallback;
       
   840 
       
   841 		// Initialise the asynchronous find in the Server.
       
   842 		iContactDatabase->iCntSvr->FindAsyncTextDefInitL(*iFindWords,const_cast<CContactTextDef*>(iTextDef));
       
   843 		}
       
   844 	else // Find using text and a CContactItemFieldDef.
       
   845 		{
       
   846 		// Initialise the asynchronous find in the Server.
       
   847 		iContactDatabase->iCntSvr->FindAsyncInitL(*aText,const_cast<CContactItemFieldDef*>(iFieldDef));		
       
   848 		}
       
   849 
       
   850 	// Start the asynchronous find.
       
   851 	CActiveScheduler::Add(this);
       
   852 	Start();
       
   853 	}
       
   854 
       
   855 
       
   856 class TFoundMatch
       
   857 	{
       
   858 public:
       
   859 	inline TFoundMatch(TFieldType aFieldType,TInt aPos) : iFieldType(aFieldType),iPos(aPos) {};
       
   860 	inline TBool operator==(const TFoundMatch &aMatch) const;
       
   861 
       
   862 private:
       
   863 	TFieldType iFieldType;
       
   864 	TInt iPos;
       
   865 	};
       
   866 
       
   867 
       
   868 inline TBool TFoundMatch::operator==(const TFoundMatch &aMatch) const
       
   869 	{
       
   870 	return(aMatch.iFieldType==iFieldType && aMatch.iPos==iPos);
       
   871 	}
       
   872 
       
   873 
       
   874 /**
       
   875 List of matches.
       
   876 */
       
   877 class CFoundMatches : public CArrayFixFlat<TFoundMatch>
       
   878 	{
       
   879 public:
       
   880 	inline CFoundMatches() : CArrayFixFlat<TFoundMatch>(8) {};
       
   881 	inline void SetCurrentMatchField(TFieldType aFieldType) {iFieldType=aFieldType;};
       
   882 	TBool AddMatchL(TInt aPos);
       
   883 
       
   884 private:
       
   885 	TFieldType iFieldType;
       
   886 	};
       
   887 
       
   888 
       
   889 TBool CFoundMatches::AddMatchL(TInt aPos)
       
   890 	{
       
   891 	TFoundMatch newMatch(iFieldType,aPos);
       
   892 	for(TInt loop=0;loop<Count();loop++)
       
   893 		{
       
   894 		if (At(loop)==newMatch)
       
   895 			{
       
   896 			return(EFalse);
       
   897 			}
       
   898 		}
       
   899 	AppendL(newMatch);
       
   900 	return(ETrue);
       
   901 	}
       
   902 
       
   903 
       
   904 TBool CIdleFinder::ScanForMatchL(const TDesC &aFieldText,const TDesC &aFindText, CFoundMatches *aFoundMatches) const
       
   905 	{
       
   906 	CDesCArray *wordArray=new(ELeave) CDesCArrayFlat(10);
       
   907 	CleanupStack::PushL(wordArray);
       
   908 
       
   909 	SFindInTextDefWordParser parser(&aFieldText,wordArray);
       
   910 	(*iWordParserCallback.iFunction)(&parser);
       
   911 
       
   912 	TBool matched=EFalse;
       
   913 
       
   914 	TInt findLen=aFindText.Length();
       
   915 
       
   916 	for(TInt loop=0;loop<wordArray->Count();loop++)
       
   917 		{
       
   918 		TPtrC fieldWord((*wordArray)[loop]);
       
   919 		if (findLen<=fieldWord.Length() && fieldWord.Left(findLen).CompareF(aFindText)==0)
       
   920 			{
       
   921 			if (aFoundMatches->AddMatchL(loop))
       
   922 				{
       
   923 				matched=ETrue;
       
   924 				break;
       
   925 				}
       
   926 			}
       
   927 		}
       
   928 
       
   929 	CleanupStack::PopAndDestroy(); // wordArray
       
   930 
       
   931 	return(matched);
       
   932 	}
       
   933 
       
   934 
       
   935 /**
       
   936 Use the client supplied "find words parser" to check for a match of the "find
       
   937 words" within the text fields in the given Contact Item.
       
   938 
       
   939 @param aContactID Contact Item to check for match.
       
   940 */
       
   941 TBool CIdleFinder::CheckFindL(TContactItemId aContactId) const
       
   942 	{
       
   943 	// If iTextDef is NULL can't check so return EFalse to indicate no match.
       
   944 	if (!iTextDef)
       
   945 		{
       
   946 		return(EFalse);
       
   947 		}
       
   948 
       
   949 	// Use ReadMininalContactLC() to read the Contact Item.  We don't need the
       
   950 	// template and groups data for the find check.
       
   951 	CContactItem* item = iContactDatabase->ReadMinimalContactLC(aContactId);
       
   952 	const CContactItemFieldSet& fieldSet = item->CardFields();
       
   953 
       
   954 	TBool found=ETrue;
       
   955 	CFoundMatches *foundWords=new(ELeave) CFoundMatches;
       
   956 	CleanupStack::PushL(foundWords);
       
   957 
       
   958 	// Iterate through iFindWords.
       
   959 	for(TInt searchWord=0;found && searchWord<iFindWords->Count();searchWord++)
       
   960 		{
       
   961 		const TPtrC findMe((*iFindWords)[searchWord]);
       
   962 		TBool foundInTextDef=EFalse;
       
   963 		
       
   964 		// Iterate through iTextDef field types then fallback field type.
       
   965 		for(TInt loop=0;!foundInTextDef && loop<=iTextDef->Count();loop++)
       
   966 			{
       
   967 			TFieldType fieldType;
       
   968 
       
   969 			if (loop==iTextDef->Count())
       
   970 				{
       
   971 				fieldType=iTextDef->FallbackField();
       
   972 				}
       
   973 			else
       
   974 				{
       
   975 				fieldType=(*iTextDef)[loop].iFieldType;
       
   976 				}
       
   977 
       
   978 			// If field type is KUidContactFieldNone, skip this field.
       
   979 			if (fieldType==KUidContactFieldNone)
       
   980 				{
       
   981 				continue;
       
   982 				}
       
   983 
       
   984 			TBuf<KTextFieldMinimalLength> textFieldMin;
       
   985 
       
   986 			// While that field type is found in the Contact Item field text...
       
   987 			TInt pos=0;
       
   988 	        while (pos!=KErrNotFound)
       
   989 				{
       
   990 				// Get the field text for this field type.
       
   991 				pos=fieldSet.FieldText(fieldType,textFieldMin,pos);				
       
   992 				
       
   993 				// Scan for match in this field text.
       
   994 				foundWords->SetCurrentMatchField(fieldType);
       
   995 				if (ScanForMatchL(textFieldMin,findMe,foundWords))
       
   996 					{
       
   997 					foundInTextDef=ETrue;
       
   998 					break;
       
   999 					}
       
  1000 				if (pos!=KErrNotFound)
       
  1001 					{
       
  1002 					pos++;
       
  1003 					}
       
  1004 				}
       
  1005 			}
       
  1006 
       
  1007 		// If there wasn't a match then set found to EFalse.
       
  1008 		if (!foundInTextDef)
       
  1009 			{
       
  1010 			found=EFalse;
       
  1011 			}
       
  1012 		}
       
  1013 
       
  1014 	CleanupStack::PopAndDestroy(2,item); // + foundWords
       
  1015 
       
  1016 	return(found);
       
  1017 	}
       
  1018 
       
  1019 
       
  1020 /**
       
  1021 Reserved (private) virtual function to allow further extension of the
       
  1022 MContactSynchroniser interface without requiring changes to all derived classes.
       
  1023 This can be used to return a pointer to an additional extension class.
       
  1024 */
       
  1025 EXPORT_C void MContactSynchroniser::MContactSynchroniser_Reserved_1()
       
  1026 	{
       
  1027 	}
       
  1028 
       
  1029 
       
  1030 EXPORT_C CContactSynchroniser::~CContactSynchroniser()
       
  1031 	{
       
  1032 	REComSession::DestroyedImplementation(iDtor_ID_Key);
       
  1033 	}
       
  1034 
       
  1035 
       
  1036 /**
       
  1037 Panic the current thread with CNTMODEL as the category
       
  1038 */
       
  1039 GLDEF_C void Panic(TCntModelPanic aPanic)
       
  1040 	{
       
  1041 	User::Panic(_L("CNTMODEL"),aPanic);
       
  1042 	}
       
  1043 
       
  1044 
       
  1045 #ifdef __VC32__
       
  1046 extern "C" void __E32Dll(void)
       
  1047 	{
       
  1048 	}
       
  1049 #endif 
       
  1050 
       
  1051 
       
  1052 /**
       
  1053  Standard Epoc32 DLL entry point.
       
  1054 */
       
  1055 #ifndef EKA2
       
  1056 GLDEF_C TInt E32Dll(TInt /*aReason*/)
       
  1057 	{
       
  1058 	return KErrNone;
       
  1059 	}
       
  1060 #endif