phonebookengines/contactsmodel/src/CNTITEM.CPP
changeset 0 e686773b3f54
child 3 04ab22b956c2
child 24 0ba2181d7c28
equal deleted inserted replaced
-1:000000000000 0:e686773b3f54
       
     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 #include <s32std.h>
       
    17 #include <f32file.h>
       
    18 
       
    19 #include <cntdef.h>
       
    20 #include <cntitem.h>
       
    21 #include <cntfield.h>
       
    22 #include <cntfldst.h>
       
    23 #include <cntdb.h>
       
    24 
       
    25 #include "CNTSTD.H"
       
    26 #include "CNTPROF.H"
       
    27 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    28 #include "cntfieldheader.h"
       
    29 #endif
       
    30 
       
    31 
       
    32 EXPORT_C CContactItemFieldSet* CContactItemFieldSet::NewL()
       
    33 /** Allocates and constructs a new field set.
       
    34 
       
    35 @return Pointer to the newly created field set. */
       
    36 	{ // static 
       
    37 	CContactItemFieldSet* self=CContactItemFieldSet::NewLC();
       
    38 	CleanupStack::Pop(); // self
       
    39 	return self;
       
    40 	}
       
    41 
       
    42 EXPORT_C CContactItemFieldSet* CContactItemFieldSet::NewLC()
       
    43 /** Allocates and constructs a new field set.
       
    44 
       
    45 @return Pointer to the newly created field set. This is left on the cleanup 
       
    46 stack. */
       
    47 	{ // static
       
    48 	CContactItemFieldSet* self=new(ELeave) CContactItemFieldSet;
       
    49 	CleanupStack::PushL(self);
       
    50 	self->ConstructL();
       
    51 	return self;
       
    52 	}
       
    53 
       
    54 EXPORT_C CContactItemFieldSet::~CContactItemFieldSet()
       
    55 /** The destructor frees all resources owned by the field set, prior to its destruction. */
       
    56 	{
       
    57 	if (iFields)
       
    58 		{
       
    59 		iFields->ResetAndDestroy();
       
    60 		delete iFields;
       
    61 		}
       
    62 	}
       
    63 
       
    64 CContactItemFieldSet::CContactItemFieldSet()
       
    65 	{}
       
    66 
       
    67 void CContactItemFieldSet::ConstructL()
       
    68 	{
       
    69 	iFields=new(ELeave) CArrayPtrFlat<CContactItemField>(4);
       
    70 	}
       
    71 
       
    72 const CContactItemField* CContactItemFieldSet::FindById(TInt aId) const
       
    73 	{
       
    74 	const CContactItemField* field=NULL;
       
    75 	for (TInt ii=0;ii<iFields->Count();ii++)
       
    76 		{
       
    77 		field=iFields->At(ii);
       
    78 		if (field->Id()==aId)
       
    79 			return(field);
       
    80 		}
       
    81 	return(NULL);
       
    82 	}
       
    83 
       
    84 EXPORT_C TInt CContactItemFieldSet::FindNext(TFieldType aFieldType,TInt aStartPos) const
       
    85 /** Finds the next field in the field set with the specified field type.
       
    86 
       
    87 @param aFieldType The field type of interest.
       
    88 @param aStartPos The index within the field set array at which to start the 
       
    89 search. By default set to KContactFieldSetSearchAll, to find the first field. 
       
    90 Must be a valid array index, or the function raises a panic.
       
    91 @return If found, the index of the field within the field set, or KErrNotFound 
       
    92 if not found. */
       
    93 	{
       
    94 	return(FindNext(aFieldType,KUidContactFieldMatchAll,aStartPos));
       
    95 	}
       
    96 
       
    97 EXPORT_C TInt CContactItemFieldSet::FindNext(TFieldType aFieldType,TUid aMapping,TInt aStartPos) const
       
    98 /** Finds the next field in the field set containing both the content type mapping 
       
    99 and the field type specified.
       
   100 
       
   101 @param aFieldType The field type of interest.
       
   102 @param aMapping The content type mapping of interest.
       
   103 @param aStartPos The index within the array at which to start the search. By 
       
   104 default set to KContactFieldSetSearchAll, to find the first field. Must be 
       
   105 a valid array index, or the function raises a panic.
       
   106 @return If found, the index of the field within the field set, or KErrNotFound 
       
   107 if not found. */
       
   108 	{
       
   109 	const TInt count=iFields->Count();
       
   110 	TInt pos=(aStartPos==KContactFieldSetSearchAll? 0 : aStartPos);
       
   111 	TInt ii=KErrNotFound;
       
   112 	for (ii=pos;ii<count;ii++)
       
   113 		{
       
   114 		const CContentType& contentType=(*iFields)[ii]->ContentType();
       
   115 		if (contentType.Mapping()==KUidContactFieldMatchAll || aMapping==KUidContactFieldMatchAll || contentType.Mapping()==aMapping)
       
   116 			if (aFieldType==KUidContactFieldMatchAll || contentType.ContainsFieldType(aFieldType))
       
   117 				return ii;
       
   118 		}
       
   119 	return KErrNotFound;
       
   120 	}
       
   121 
       
   122 void CContactItemFieldSet::SetFieldId(CContactItemField& aField)
       
   123 	{
       
   124 	TInt id=iFields->Count();
       
   125 	TInt count=iFields->Count();
       
   126 	FOREVER
       
   127 		{
       
   128 		TInt loop=0;
       
   129 		for(;loop<count;loop++)
       
   130 			if ((*iFields)[loop]->Id()==id)
       
   131 				break;
       
   132 		if (loop==count)
       
   133 			{
       
   134 			aField.SetId(id);
       
   135 			break;
       
   136 			}
       
   137 		id++;
       
   138 		}
       
   139 	}
       
   140 
       
   141 EXPORT_C CContactItemFieldSet& CContactItemFieldSet::AddL(CContactItemField& aField)
       
   142 /** Appends a field to the field set. The field set takes ownership of the field.
       
   143 
       
   144 @param aField Reference to the field to add to the field set. The field's 
       
   145 ID is updated.
       
   146 @return Reference to the current field set. */
       
   147 	{
       
   148 	__ASSERT_DEBUG(&aField!=NULL,Panic(ECntPanicNullPointer));
       
   149 	SetFieldId(aField);
       
   150 	iFields->AppendL(&aField);
       
   151 	return (*this);
       
   152 	}
       
   153 
       
   154 EXPORT_C void CContactItemFieldSet::Remove(TInt aIndex)
       
   155 /** Removes a field from the field set.
       
   156 
       
   157 @param aIndex The index of the field to delete. Must be a valid index within 
       
   158 the field set or the function raises a panic. */
       
   159 	{
       
   160 	delete (*iFields)[aIndex];
       
   161 	iFields->Delete(aIndex);
       
   162 	}
       
   163 
       
   164 EXPORT_C void CContactItemFieldSet::Move(TInt aFrom, TInt aTo)
       
   165 /** Changes a field's position within the field set.
       
   166 
       
   167 Both indexes specified must be valid (i.e. between zero and Count()-1 inclusive), 
       
   168 or the function raises a panic.
       
   169 
       
   170 @param aFrom The index of the field to move.
       
   171 @param aTo The index of the new position within the field set. */
       
   172 	{
       
   173 	CContactItemField *moveField=(*iFields)[aFrom];
       
   174 	if (aFrom<aTo)
       
   175 		{
       
   176 		for(TInt loop=aFrom;loop<aTo;loop++)
       
   177 			(*iFields)[loop]=(*iFields)[loop+1];
       
   178 		}
       
   179 	else
       
   180 		{
       
   181 		for(TInt loop=aFrom;loop>aTo;loop--)
       
   182 			(*iFields)[loop]=(*iFields)[loop-1];
       
   183 		}
       
   184 	(*iFields)[aTo]=moveField;
       
   185 	}
       
   186 
       
   187 EXPORT_C void CContactItemFieldSet::InsertL(TInt aIndex,CContactItemField& aField)
       
   188 /** Inserts a field into the field set.
       
   189 
       
   190 @param aIndex The position in the field set at which to insert the field. 
       
   191 If equal to or greater than the number of elements in the field set, the field 
       
   192 is appended to the field set.
       
   193 @param aField Reference to the field to add to the field set. The field's ID 
       
   194 is updated. */
       
   195 	{
       
   196 	__ASSERT_DEBUG(&aField!=NULL,Panic(ECntPanicNullPointer));
       
   197 	SetFieldId(aField);
       
   198 	TInt count=iFields->Count();
       
   199 	if (count>aIndex)
       
   200 		iFields->InsertL(aIndex,&aField);
       
   201 	else
       
   202 		iFields->AppendL(&aField);
       
   203 	}
       
   204 
       
   205 /**
       
   206 
       
   207 Find and return the index of the best matched template field. The method uses a matching algorithm which compares the content type of the template fields with that of the incoming contact item.
       
   208 
       
   209 Matching Algorithm Steps:
       
   210 ========================
       
   211 
       
   212 The algorithm is based on a scoring mechanism counting 'hits' and 'misses' in order to find the best possible field match within the fieldset of the template.
       
   213 
       
   214 1. Loop through all the contact item fields of the template.
       
   215 
       
   216 For each template field:
       
   217 
       
   218 2. Perform a strict, or exact, match between the vCard mappings of the template field and the field to be matched.
       
   219 3. If the vCard mappings match exactly, compare User Flags values and amend the overall score accordingly.
       
   220 4. Loop through all the field types (TFieldType array) stored as part of the content type of the field to be matched.
       
   221 
       
   222 For each field type of the field to be matched:
       
   223 
       
   224 5. Loop through the field types of the iterated template field to find a field type match. Amend the 'hits' and 'misses' count accordingly.
       
   225 6. Calculate the overall score weighing the 'hits' and 'misses' count.
       
   226 7. Amend the overall score count in order to account for special cases (e.g. user defined fields)
       
   227 8. Compare the overall score with the best score. If score > current best score, replace the 'bestScore' count and 'bestMatch' index.
       
   228 
       
   229 9. Return the 'bestMatch' field index of the template field.
       
   230 
       
   231 @param aContentType		The content type of the field to find a match for.
       
   232 @param aUserFlags		The user flags of the field to find a match for.
       
   233 @param aExactMatch		Boolean to indicate an exact field match within the template.
       
   234 
       
   235 @return The index of the best matched template field, if found, else KErrNotFound.
       
   236 
       
   237 */
       
   238 
       
   239 TInt CContactItemFieldSet::MatchTemplateField(const CContentType& aContentType,TUint aUserFlags,TBool &aExactMatch) const
       
   240 	{
       
   241 	const TInt count=Count();
       
   242 	TInt bestScore=5;	// Has to be better than one or fail the match
       
   243 	TInt bestMatch=KErrNotFound;
       
   244 	TInt contentTypeCount=aContentType.FieldTypeCount();
       
   245 
       
   246 	// Loop through all the template fields to find the best field match
       
   247 	for (TInt ii=0;ii<count;ii++)
       
   248 		{
       
   249 		const CContactItemField& field=*(*iFields)[ii];
       
   250 		const CContentType &fieldContentType=field.ContentType();
       
   251 
       
   252 		// Strict matching executed on the vCard mappings in order to avoid matching non-related fields e.g. Fax and Address fields.
       
   253 		// NOTE: The vCard mappings are intended to match the vCard PROPERTY (e.g. TEL in TEL;HOME;FAX:01234), wherein the field is to be exported into a vCard.
       
   254 		if (fieldContentType.Mapping()==aContentType.Mapping())
       
   255 			{
       
   256 			TInt score=fieldContentType.Mapping()==KUidContactFieldVCardMapUnusedN?0:100;
       
   257 			TInt hits=0;
       
   258 			TInt misses=0;
       
   259 
       
   260 			// The criteria for an exact match of the User Flags has been changed
       
   261 			// from a mandatory requirement to a preference within the scoring system
       
   262 			if (aUserFlags==0 || field.UserFlags()==aUserFlags)
       
   263 				{
       
   264 				++score;
       
   265 				}
       
   266 
       
   267 			// NOTE: A common Field Types array stores BOTH the Field Type in addition to the Extra Mappings
       
   268 			//
       
   269 			// A. Field Type     = Contact item field's type defined internally
       
   270 			// B. Extra Mappings = Refer to the vCard PARAMETERS (e.g. FAX and HOME in TEL;HOME;FAX:01234)
       
   271 			//
       
   272 			// The Field Type and Extra Mappings are defined as part of the FIELD structure within the template (cntmodel.rss)
       
   273 			//
       
   274 			// C. Field Types array = A (Field Type, first element) + B (Extra Mappings, all elements after the first element)
       
   275 			
       
   276 			// Loop through the incoming contact item field's Field Types (C)
       
   277 			for(TInt contactFieldTypeLoop=0; contactFieldTypeLoop < contentTypeCount; ++contactFieldTypeLoop)
       
   278 				{
       
   279 				// Match EACH of the incoming contact item field's Field Types (C) within the template field's Field Types (C)
       
   280 				if(ContainsFieldTypeMapping(fieldContentType,aContentType.FieldType(contactFieldTypeLoop)))
       
   281 					{
       
   282 					++hits;
       
   283 					}
       
   284 				else
       
   285 					{
       
   286 					++misses;
       
   287 					}				
       
   288 				}
       
   289 
       
   290 			// Check if the incoming contact item has a vCard property mapping
       
   291 			// that is also present in the current template field's Field Types.
       
   292 			// This covers the (unusual) case where a template field is defined
       
   293 			// to have a vCard property mapping which is also the same as one of
       
   294 			// field types (which contains property parameter mappings).
       
   295 			for(TInt fieldTypeIdx=0; fieldTypeIdx < fieldContentType.FieldTypeCount(); ++fieldTypeIdx)
       
   296 				{
       
   297 				if(fieldContentType.FieldType(fieldTypeIdx) == aContentType.Mapping())
       
   298 					{
       
   299 					++hits;
       
   300 					}
       
   301 				}
       
   302 			
       
   303 			misses+=fieldContentType.FieldTypeCount()-hits;
       
   304 			score+=10*hits-5*misses;
       
   305 			
       
   306 			if (!field.UserAddedField())
       
   307 				{
       
   308 				score+=3;	// Non-user added field takes priority over user added fields
       
   309 				}
       
   310 			
       
   311 			if (fieldContentType.ContainsFieldType(KUidContactFieldVCardMapWORK))
       
   312 				{
       
   313 				score+=1;	// Work fields take priority over home fields
       
   314 				}
       
   315 				
       
   316 			if (score>bestScore)
       
   317 				{
       
   318 				aExactMatch=(misses==0);
       
   319 				bestScore=score;
       
   320 				bestMatch=ii;
       
   321 				}
       
   322 			}
       
   323 		}
       
   324 	return bestMatch;
       
   325 	}
       
   326 
       
   327 // Attempt to find a contact item field type within the Field Types array (Field Types array = Field Type (internal) + Extra Mappings) of the base contact item.
       
   328 // NOTE: This function does not include the base contact item field's vCard mapping whilst looking for the Field Type
       
   329 TBool CContactItemFieldSet::ContainsFieldTypeMapping(const CContentType& aBaseFieldContentType, const TFieldType& aContactFieldType) const
       
   330 	{
       
   331 	// Loop through all the template Field Types to attempt to match the individual Field Type of the incoming contact item's field
       
   332 	for(TInt templateFieldTypeLoop=0; templateFieldTypeLoop < aBaseFieldContentType.FieldTypeCount(); ++templateFieldTypeLoop)
       
   333 		{
       
   334 		if(aBaseFieldContentType.FieldType(templateFieldTypeLoop) == aContactFieldType)
       
   335 			{
       
   336 			return ETrue;
       
   337 			}
       
   338 		}
       
   339 	return EFalse;
       
   340 	}
       
   341 
       
   342 /**
       
   343 @internalTechnology 
       
   344 */
       
   345 EXPORT_C TStreamId CContactItemFieldSet::StoreL(CStreamStore& aStore,const CContactItem* aTemplate,RWriteStream& aTextStream,CStreamStore& aBlobStore,CContactTables* aTables)
       
   346 	{
       
   347 	const TInt count=Count();
       
   348 	for (TInt ii=0;ii<count;ii++)
       
   349 		{
       
   350 		CContactItemField* field=(*iFields)[ii];
       
   351 		if (aTemplate)
       
   352 			{
       
   353 			const CContactItemFieldSet& templateFields = aTemplate->CardFields();
       
   354 			field->UpdateFieldFlags(templateFields);
       
   355 			}
       
   356 		else
       
   357 			{
       
   358 			field->SetLabelUnspecified(EFalse);
       
   359 			}
       
   360 		}
       
   361 	return StoreL(aStore,aTextStream,aBlobStore,aTables);
       
   362 	}
       
   363 
       
   364 EXPORT_C TStreamId CContactItemFieldSet::StoreL(CStreamStore& aStore,RWriteStream& aTextStream,CStreamStore& aBlobStore)
       
   365 /** Stores the field set to a stream store.
       
   366 @internalTechnology
       
   367 @param aStore Stream store to which the field set is written.
       
   368 @param aTextStream Stream to which data stored in text fields (with a storage 
       
   369 type of KStorageTypeText) is written.
       
   370 @param aBlobStore Stream store to which data stored in non-text fields is written.
       
   371 @return The ID of the stream store. */
       
   372 	{
       
   373 	//Overloaded to maintain SC.
       
   374 	return (StoreL(aStore,aTextStream,aBlobStore,NULL));
       
   375 	}
       
   376 	
       
   377 /* 
       
   378 Store all contact fields in this field set into given header and data stores.
       
   379 
       
   380 In SQLite data schema, contact field data is saved in the stream store (aStore) as:
       
   381 
       
   382 contact-item-field-set = number-of-fields *field		
       
   383     ; <field> repeated <number-of-fields> times
       
   384  
       
   385 field = contact-field-atts [ stream-id ] field-id template-id [ hint-value *mapping *additional-field ] [ label-length [ label ] ]
       
   386 	; 1st optional part is there if the contact field is NOT stored as text.
       
   387 	; if the field uses the template's content type, the 2nd optional part is left out
       
   388 	; <additional-field> is repeated a number of times as specified by <number-of-additional-fields> inside hint-value
       
   389 	; mapping is there if vcard-mapping-id-mask in hint-valute is set
       
   390 	; 3rd optional part is there if there is a label which overrides the template label. <label> is left out if <label-length> is zero
       
   391 
       
   392 contact-field-atts = attrib-store
       
   393 
       
   394 attrib-store =	attribs field-type extended-attribs				
       
   395 	; 32 bits -- order is endian-dependent
       
   396 
       
   397 attribs	= 14BIT						
       
   398 	; 14 bitfields: Hidden, ReadOnly, Synchronize, Disabled, 
       
   399 	;	4 user-defined fields, OverRidesLabel, UsesTemplateData, 
       
   400 	;	UserAddedField, Template, LabelUnspecified and Deleted (in that order), 
       
   401 	
       
   402 field-type = 4BIT						; 0..16
       
   403 extended-attribs = 8BIT
       
   404     ; 8 bitfields: Private, SpeedDial, EUserDefinedFilter and 
       
   405     ; EUserDefinedFilter1-4(in that order)		
       
   406 
       
   407 hint-value = vcard-mapping-id-mask *number-of-additional-fields *hint-value
       
   408     ; 32 bits -- order is endian-dependent
       
   409     ; hint-value and number-of-additional-fields is there if UsesTemplateData is NOT set in attribs
       
   410 vcard-mapping-id-mask= 1BIT   
       
   411 number-of-additional-fields = 7BIT
       
   412 hint-value = 24BIT
       
   413 
       
   414 mapping = Int32
       
   415 field-id =UInt32
       
   416 template-id =UInt32
       
   417 stream-id =UInt32
       
   418 label-length = Int32
       
   419 label = Descriptor
       
   420 
       
   421 @param aStore the stream store for data header
       
   422 @param aTextStream the stream to store text data
       
   423 @param aBlobStore  the stream store for blob data
       
   424 
       
   425 @return stream id the data header stored in aStore.
       
   426 */
       
   427 
       
   428 TStreamId CContactItemFieldSet::StoreL(CStreamStore& aStore, RWriteStream& aTextStream, CStreamStore& aBlobStore, CContactTables* /*aTables*/)
       
   429 	{
       
   430 	CArrayFix<TInt>* fullFields = new(ELeave) CArrayFixFlat<TInt>(4);
       
   431 	CleanupStack::PushL(fullFields);  // push here to make cleanup easier
       
   432 	
       
   433 	CArrayFix<TFieldHeader>* fieldHeader = new(ELeave) CArrayFixFlat<TFieldHeader>(5);
       
   434 	CleanupStack::PushL(fieldHeader);
       
   435 	
       
   436 	TInt textFieldIndex = 0;
       
   437 
       
   438 	const TInt KCount = Count();
       
   439 	for(TInt ii = 0; ii < KCount; ++ii)
       
   440 	    {  
       
   441 	    // find all non-empty fields
       
   442 		CContactItemField* field = (*iFields)[ii];
       
   443 
       
   444 		if (!field->IsDeleted()) 
       
   445 			{
       
   446 			// only save non-empty content in the blob
       
   447 			fullFields->AppendL(ii); // save for later
       
   448 			
       
   449 			//Add the text storage field data from the field to the blob
       
   450 			fieldHeader->AppendL(field->StoreL(aTextStream, aBlobStore, textFieldIndex));
       
   451 			if (field->StorageType() == KStorageTypeText)
       
   452 			    {
       
   453 				++textFieldIndex;
       
   454 			    }
       
   455 			}
       
   456 		}
       
   457 
       
   458 	// adjust the hint values for non-empty fields only
       
   459 	RStoreWriteStream rootStream;
       
   460 	TStreamId streamId = rootStream.CreateLC(aStore);
       
   461 	
       
   462 	const TInt KHintCount = fieldHeader->Count();
       
   463 	rootStream << TCardinality(KHintCount);
       
   464 	
       
   465 	for (TInt ii = 0; ii < KHintCount; ++ii)
       
   466 		{
       
   467 		CContactItemField* field=(*iFields)[(*fullFields)[ii]];
       
   468 		field->PopulateStoreL(rootStream, ii, *fieldHeader);
       
   469 		}	
       
   470 		
       
   471 	rootStream.CommitL();
       
   472 	aStore.CommitL();
       
   473 		
       
   474 	CleanupStack::PopAndDestroy(3, fullFields); // rootStream, fieldHeader, fullFields
       
   475 	return streamId;
       
   476 	}
       
   477 	
       
   478 HBufC* CContactItemFieldSet::LoadTextStreamLC(RReadStream& aStream)
       
   479 	{
       
   480 	TInt maxlen=0;
       
   481 	if (aStream.Source())
       
   482 		maxlen=aStream.Source()->SizeL(); 
       
   483 	maxlen=maxlen/2;
       
   484 	HBufC* textStream=HBufC::NewLC(maxlen);
       
   485 	if (maxlen)
       
   486 		{
       
   487 		TPtr des=textStream->Des();
       
   488 		aStream.ReadL(des,maxlen);
       
   489 		}
       
   490 	return(textStream);
       
   491 	}
       
   492 
       
   493 void CContactItemFieldSet::RestoreAndAddTemplateL(CStreamStore& aStore, TStreamId aId,CStreamStore* aBlobStore,const CContactItemViewDef& aViewDef,
       
   494 									const CContactItem* aTemplate,RReadStream& aReadStream,CContactTables* aContactsTable,RArray<TInt>* aEmailIdArray)
       
   495 	{
       
   496 	if (aViewDef.Use()==CContactItemViewDef::EIncludeFields && aViewDef.Count()==0)
       
   497 		return; // zzz temp kludge, fix this properly
       
   498 	if (aTemplate)
       
   499 		{
       
   500 		CContactItemFieldSet *original=CContactItemFieldSet::NewLC();
       
   501 		original->RestoreL(aStore,aId,aBlobStore,aViewDef,aTemplate,aReadStream,aContactsTable,aEmailIdArray);
       
   502 		TInt count=original->Count();
       
   503 		for(TInt loop=0;loop<count;loop++)
       
   504 			{
       
   505 			CContactItemField* additionalField=CContactItemField::NewLC((*original)[loop]);
       
   506 			AddL(*additionalField);
       
   507 			CleanupStack::Pop(); // additionalField
       
   508 			}
       
   509 		CleanupStack::PopAndDestroy(); // original
       
   510 		}
       
   511 	else
       
   512 		RestoreL(aStore,aId,aBlobStore,aViewDef,NULL,aReadStream,aContactsTable,aEmailIdArray);
       
   513 	}
       
   514 
       
   515 /** 
       
   516 Restores the field set using a view definition.
       
   517 @internalTechnology
       
   518 @param aStore Store from which to restore the field set.
       
   519 @param anId The root stream ID of aStore.
       
   520 @param aBlobStore If specified, the stream store from which data stored in 
       
   521 non-text fields is read.
       
   522 @param aViewDef The view definition to use.
       
   523 @param aReadStream Read stream from which data stored in text fields (with 
       
   524 a storage type of KStorageTypeText) is read. 
       
   525 */
       
   526 EXPORT_C void CContactItemFieldSet::RestoreL(CStreamStore& aStore, TStreamId anId,CStreamStore* aBlobStore,const CContactItemViewDef& aViewDef,RReadStream& aReadStream)
       
   527     {
       
   528 	//THIS FUNCTION IS TO BE REMOVED....
       
   529 	RestoreL(aStore,anId,aBlobStore,aViewDef,NULL,aReadStream,NULL,NULL);
       
   530 	}
       
   531 
       
   532 
       
   533 void CContactItemFieldSet::RestoreL(CStreamStore& aStore, TStreamId anId, CStreamStore* aBlobStore,const CContactItemViewDef& aViewDef,const CContactItem* aTemplate,RReadStream& aReadStream,CContactTables* /*aContactsTable*/, RArray<TInt>* /*aEmailIdArray*/)
       
   534 	// Overloaded looks in the Contacts Table for cetain fields.
       
   535 	{
       
   536 	const TBool includeFields=aViewDef.Use()==CContactItemViewDef::EIncludeFields;
       
   537 	if (includeFields && aViewDef.Count()==0)
       
   538 		return;
       
   539 	RStoreReadStream stream;
       
   540 	stream.OpenLC(aStore,anId);
       
   541 	TCardinality fieldCount;
       
   542 	stream>>fieldCount;
       
   543 	TStreamId nestedId;
       
   544 	TInt textFieldIndex=0;
       
   545 	HBufC *textStream=CContactItemFieldSet::LoadTextStreamLC(aReadStream);
       
   546 
       
   547 	for (TInt ii=0; ii<fieldCount; ++ii)
       
   548 		{
       
   549 		CContactItemField* field=CContactItemField::NewLC();
       
   550 		nestedId=field->RestoreFieldTypesL(stream,aTemplate?&(aTemplate->CardFields()):NULL);
       
   551 		const CContentType &type=field->ContentType();
       
   552 		TBool fieldDefined=aViewDef.MatchesAll() || (aViewDef.Find(type)!=KErrNotFound);
       
   553 		if (!((fieldDefined&&includeFields) || (!fieldDefined&&!includeFields)) || 
       
   554 			(field->IsHidden() && aViewDef.Mode()==CContactItemViewDef::EMaskHiddenFields)
       
   555 			)
       
   556 			{
       
   557 			if (field->StorageType()==KStorageTypeText)  
       
   558 				textFieldIndex++;
       
   559 			CleanupStack::PopAndDestroy(); // field
       
   560 			}
       
   561 		else
       
   562 			{
       
   563 			if (field->StorageType()==KStorageTypeText)  // restore from text stream
       
   564 				{
       
   565 				// restore text from contacts table.
       
   566 				TPtrC textPtr;
       
   567 				if(textPtr.Length())
       
   568 					{
       
   569 					field->TextStorage()->SetTextL(textPtr);
       
   570 					}
       
   571 				else
       
   572 					{
       
   573 					field->RestoreTextL(textStream,textFieldIndex);
       
   574 					}
       
   575 				iFields->AppendL(field);
       
   576 				CleanupStack::Pop(); // field
       
   577 				textFieldIndex++;
       
   578 				}
       
   579 			else if (aBlobStore)
       
   580 				{
       
   581 				field->RestoreDataL(*aBlobStore, nestedId);
       
   582 				iFields->AppendL(field);
       
   583 				CleanupStack::Pop(); // field
       
   584 				}
       
   585 			else
       
   586 				{
       
   587 				CleanupStack::PopAndDestroy(); // field
       
   588 				}
       
   589 			}
       
   590 		}
       
   591 	CleanupStack::PopAndDestroy(2); // textStream,stream
       
   592     }
       
   593 
       
   594 /**
       
   595 The overload that doesn't use dangerous CContactItemFieldSet::LoadTextStreamLC(aReadStream) method.
       
   596 LoadTextStreamLC relies on the stream to know its size, but now all types of streams support this functionality.
       
   597 In order to avoid calling LoadTextStreamLC, aTextBuf is already loaded in HBufC in the caller function.
       
   598 The caller function had access to the table and can use ColLength() API to get the lebgth of the field.
       
   599 @internalTechnology
       
   600 */
       
   601 EXPORT_C void CContactItemFieldSet::RestoreL(CStreamStore& aStore, TStreamId anId, CStreamStore* aBlobStore,const CContactItemViewDef& aViewDef,const CContactItem* aTemplate,HBufC* aTextBuf)
       
   602 	{
       
   603 	const TBool includeFields=aViewDef.Use()==CContactItemViewDef::EIncludeFields;
       
   604 	if (includeFields && aViewDef.Count()==0)
       
   605 		return;
       
   606 	RStoreReadStream stream;
       
   607 	stream.OpenLC(aStore,anId);
       
   608 	TCardinality fieldCount;
       
   609 	stream>>fieldCount;
       
   610 	TStreamId nestedId;
       
   611 	TInt textFieldIndex=0;
       
   612 
       
   613 	for (TInt ii=0;ii<fieldCount;ii++)
       
   614 		{
       
   615 		CContactItemField* field=CContactItemField::NewLC();
       
   616 		nestedId=field->RestoreFieldTypesL(stream,aTemplate?&(aTemplate->CardFields()):NULL);
       
   617 		const CContentType &type=field->ContentType();
       
   618 		TBool fieldDefined=aViewDef.MatchesAll() || (aViewDef.Find(type)!=KErrNotFound);
       
   619 		if (!((fieldDefined&&includeFields) || (!fieldDefined&&!includeFields)) || 
       
   620 			(field->IsHidden() && aViewDef.Mode()==CContactItemViewDef::EMaskHiddenFields)
       
   621 			)
       
   622 			{
       
   623 			if (field->StorageType()==KStorageTypeText)  
       
   624 				textFieldIndex++;
       
   625 			CleanupStack::PopAndDestroy(field);
       
   626 			}
       
   627 		else
       
   628 			{
       
   629 			if (field->StorageType()==KStorageTypeText)  // restore from text stream
       
   630 				{
       
   631 				// restore text from contacts table.
       
   632 				TPtrC textPtr;
       
   633 				if(textPtr.Length())
       
   634 					{
       
   635 					field->TextStorage()->SetTextL(textPtr);
       
   636 					}
       
   637 				else
       
   638 					{
       
   639 					field->RestoreTextL(aTextBuf,textFieldIndex);
       
   640 					}
       
   641 
       
   642                 if (aTemplate)
       
   643                     {
       
   644                     AddL(*field);
       
   645                     }
       
   646                 else
       
   647                     {
       
   648                     iFields->AppendL(field);
       
   649                     }
       
   650 
       
   651 				CleanupStack::Pop(field);
       
   652 				textFieldIndex++;
       
   653 				}
       
   654 			else if (aBlobStore)
       
   655 				{
       
   656 				field->RestoreDataL(*aBlobStore, nestedId);
       
   657 
       
   658                 if (aTemplate)
       
   659                     {
       
   660                     AddL(*field);
       
   661                     }
       
   662                 else
       
   663                     {
       
   664                     iFields->AppendL(field);
       
   665                     }
       
   666 
       
   667 				CleanupStack::Pop(field);
       
   668 				}
       
   669 			else
       
   670 				{
       
   671 				CleanupStack::PopAndDestroy(field);
       
   672 				}
       
   673 			}
       
   674 		}
       
   675 	CleanupStack::PopAndDestroy(&stream); 
       
   676     }
       
   677 
       
   678 
       
   679 
       
   680 EXPORT_C void CContactItemFieldSet::UpdateFieldL(const CContactItemField &aField, TInt aMatchCount)
       
   681 /** Updates a field in the field set. The field whose content type matches aField's 
       
   682 content type is replaced by aField. The second parameter is used to identify 
       
   683 which matching field is updated. Specify 1 to update the first matching field, 
       
   684 2 for the second and so on. If there is no field in the field set which matches 
       
   685 aField's content type, then aField is appended to the field set.
       
   686 
       
   687 @param aField The new field information.
       
   688 @param aMatchCount Identifies which matching field in the field set should 
       
   689 be updated. */
       
   690 	{
       
   691 	const CContentType &newContentType=aField.ContentType();
       
   692 	TInt fieldPos=0;
       
   693 	for(;fieldPos<iFields->Count();fieldPos++)
       
   694 		{
       
   695 		if (newContentType==(*iFields)[fieldPos]->ContentType())
       
   696 			{
       
   697 			--aMatchCount;
       
   698 			if (aMatchCount==0)
       
   699 				{
       
   700 				Remove(fieldPos); 
       
   701 				break;
       
   702 				}
       
   703 			}
       
   704 		}
       
   705 	if (aField.Storage()->IsFull())
       
   706 		{
       
   707 		CContactItemField* field=CContactItemField::NewLC(aField);
       
   708 		InsertL(fieldPos,*field);
       
   709 		CleanupStack::Pop();	// field
       
   710 		}
       
   711 	}
       
   712 
       
   713 
       
   714 EXPORT_C void CContactItemFieldSet::UpdateFieldSyncL(const CContactItemField& aField, TInt aMatchCount)
       
   715 /**
       
   716  *  Updates a field in the field set. 
       
   717  *  Searches the set for a matching field. Deletes the matching set's field if any.
       
   718  *  Adds the aField to the set anyway.
       
   719  *  Uses the IsEqualForSyncUpdate() function to compare two CContentType objects,
       
   720  *  rather than the default equals operator.
       
   721  *  Takes care to hold the PREF, VoiceDial, and SpeedDial properties in the updated field.  
       
   722  *
       
   723  *  @param aField Specifies both the type of the field to update and the updated field's value.
       
   724  *  @param aMatchCount Gives the offset of the matching field to update in the order of the set
       
   725  *          (i.e. 1, means update the first matching field in the set;
       
   726  *                2, means update the second matching field in the set).
       
   727  */
       
   728 	{
       
   729 	TBool mustAddFieldTypePREF=EFalse;
       
   730 	TBool mustAddFieldTypeVoiceDial=EFalse;
       
   731 	TUid voiceDialUid=KNullUid;
       
   732 		
       
   733 	const CContentType& newContentType=aField.ContentType();
       
   734 	TInt fieldPos=0;
       
   735 	for(;fieldPos<iFields->Count();fieldPos++)
       
   736 		{
       
   737 		if ((*iFields)[fieldPos]->ContentType().IsEqualForSyncUpdate(newContentType))
       
   738 			{
       
   739 			--aMatchCount;
       
   740 			if (aMatchCount==0)
       
   741 				{
       
   742 				const CContentType& contentType=(*iFields)[fieldPos]->ContentType(); 
       
   743 
       
   744 				if (contentType.Mapping().iUid==KIntContactFieldVCardMapTEL)
       
   745 					{
       
   746 					for(TInt loop=0;loop<contentType.FieldTypeCount();loop++)
       
   747 						{
       
   748 						if (contentType.FieldType(loop).iUid>=KUidSpeedDialOneValue && contentType.FieldType(loop).iUid<=KUidSpeedDialNineValue)
       
   749 							{
       
   750 							voiceDialUid.iUid=contentType.FieldType(loop).iUid;
       
   751 							break; //only one speed dial property allowed for a field
       
   752 							}
       
   753 						}
       
   754 					
       
   755 					if (contentType.ContainsFieldType(KUidContactsVoiceDialField))
       
   756 						{
       
   757 						mustAddFieldTypeVoiceDial=ETrue;
       
   758 						}
       
   759 					}
       
   760 
       
   761 				if (contentType.ContainsFieldType(KUidContactFieldVCardMapPREF) && !newContentType.ContainsFieldType(KUidContactFieldVCardMapPREF))
       
   762 					{
       
   763 					mustAddFieldTypePREF=ETrue;
       
   764 					}	
       
   765 				break;
       
   766 				}
       
   767 			}
       
   768 		}
       
   769 	if (aField.Storage()->IsFull())
       
   770 		{
       
   771 		if( fieldPos<iFields->Count() )
       
   772 			{
       
   773 			Remove(fieldPos);//if updating with full field, then remove old field first
       
   774 			}
       
   775 		CContactItemField* field=CContactItemField::NewLC(aField);
       
   776 		if (mustAddFieldTypePREF)
       
   777 			{
       
   778 			field->AddFieldTypeL(KUidContactFieldVCardMapPREF);
       
   779 			}
       
   780 
       
   781 		if (mustAddFieldTypeVoiceDial)
       
   782 			{
       
   783 			field->AddFieldTypeL(KUidContactsVoiceDialField);
       
   784 			}
       
   785 
       
   786 		if (voiceDialUid!=KNullUid)
       
   787 			{
       
   788 			field->AddFieldTypeL(voiceDialUid);
       
   789 			}
       
   790 
       
   791 		InsertL(fieldPos,*field);
       
   792 		CleanupStack::Pop(field);	
       
   793 		}
       
   794 	else if( fieldPos < iFields->Count() )
       
   795 		{
       
   796 		(*iFields)[fieldPos]->ResetStore();//if updating with empty field, just reset the field
       
   797 		}
       
   798 	}
       
   799 
       
   800 
       
   801 
       
   802 TInt CContactItemFieldSet::FieldText(TFieldType aFieldType, TDes  &aText, TInt aStartPosition) const
       
   803 	{
       
   804 	TInt fieldPos=FindNext(aFieldType, aStartPosition);
       
   805 	if (fieldPos!=KErrNotFound)
       
   806 		(*iFields)[fieldPos]->GetFieldText(aText);
       
   807 	return fieldPos;
       
   808 	}
       
   809 
       
   810 /** Get the first non-empty text field*/
       
   811 void CContactItemFieldSet::NonZeroFieldText(TFieldType aFieldType, TDes &aText) const
       
   812 	{
       
   813 	TInt fieldPos=-1;
       
   814 	do
       
   815 		{
       
   816 		fieldPos=FindNext(aFieldType,fieldPos+1);
       
   817 		if (fieldPos==KErrNotFound)
       
   818 			break;
       
   819 		(*iFields)[fieldPos]->GetFieldText(aText);
       
   820 		} while(aText.Length()==0);
       
   821 	}
       
   822 
       
   823 
       
   824 /** 
       
   825 Part of the system template update implementation. 
       
   826 This could be used for a generic update method at a later stage.
       
   827 @since 7.0
       
   828 @internalTechnology
       
   829 */
       
   830 CArrayFix<TFieldHeader>* CContactItemFieldSet::ConstructFieldHeaderArrayLC(RWriteStream& aTextStream, CStreamStore& aBlobStore)
       
   831 	{
       
   832 	CArrayFix<TFieldHeader>* retval = new(ELeave) CArrayFixFlat<TFieldHeader>(5);
       
   833 	CleanupStack::PushL(retval);
       
   834 	CContactItemField* field = NULL;
       
   835 	TPtrC textPointer;
       
   836 	HBufC* buffer = NULL;
       
   837 	TInt counter = 0;
       
   838 	TInt maxFields = 0;
       
   839 	TInt textFieldIndex = 0;
       
   840 
       
   841 	maxFields = Count();
       
   842 	for (counter=0;counter < maxFields; counter++)
       
   843 		{
       
   844 		field = (*iFields)[counter];
       
   845 		if (!field->IsDeleted() )
       
   846 			{
       
   847 			if (field->StorageType()==KStorageTypeText)
       
   848 				{
       
   849 				textPointer.Set(field->TextStorage()->Text());
       
   850 				buffer = textPointer.AllocLC();
       
   851 				} // if
       
   852 
       
   853 			retval->AppendL(field->StoreL(aTextStream,aBlobStore,textFieldIndex));
       
   854 
       
   855 			if (buffer && buffer->Length() > 0 )
       
   856 				{
       
   857 				field->TextStorage()->SetTextL(*buffer);
       
   858 				}
       
   859 
       
   860 			if (buffer)
       
   861 				{
       
   862 				CleanupStack::PopAndDestroy(buffer);
       
   863 				buffer = NULL;
       
   864 				}
       
   865 
       
   866 			if (field->StorageType()==KStorageTypeText)
       
   867 				{
       
   868 				textFieldIndex++;
       
   869 				}
       
   870 			}//if
       
   871 		} // for
       
   872 
       
   873 	return retval;
       
   874 	}
       
   875 
       
   876 
       
   877 
       
   878 /*
       
   879  * Iterate through the fields.
       
   880  * If the current field matches the field we are inserting from the template 
       
   881  * return the position of the match. 
       
   882  * 
       
   883  * @param aSystemTemplateFields System template fieldset
       
   884  * @param aStartIndex Field to start from
       
   885  * @param aField Template field
       
   886  * @return KErrNotFound, if no field matching the template field in the fieldset, 
       
   887  * else returns position of match in fieldset
       
   888  */
       
   889 
       
   890 TInt CContactItemFieldSet::FieldTypeCount(const CContactItemFieldSet& aSystemTemplateFields, TInt aStartIndex, const CContactItemField& aField) const
       
   891 	{
       
   892 	const TInt fieldSetCount = Count();
       
   893 	for (TInt ii=aStartIndex;ii<fieldSetCount;ii++)
       
   894 		{
       
   895 		const CContactItemField& field=*((*iFields)[ii]);
       
   896 		TInt tfId = field.TemplateFieldId();
       
   897 		if(tfId==KNullFieldId)
       
   898 			{
       
   899 			if (field.ContentType()==aField.ContentType())
       
   900 				return(ii);
       
   901 			}
       
   902 		else
       
   903 			{
       
   904 			const CContactItemField* sysField=aSystemTemplateFields.FindById(tfId);
       
   905 			if (sysField->ContentType()==aField.ContentType())
       
   906    				return(ii);
       
   907 			}
       
   908 		}		
       
   909 	return KErrNotFound;
       
   910 	}
       
   911 	
       
   912 void CContactItemFieldSet::InternalizeL(RReadStream& aStream)
       
   913 /** Internalises a CContactItemFieldSet object from a read stream. 
       
   914 @param aStream Stream from which the object should be internalised. */
       
   915 	{
       
   916 	TInt fieldCount = aStream.ReadInt32L(); // Number of fields.	
       
   917 	
       
   918 	for(TInt index=0; index<fieldCount; ++index)
       
   919 		{
       
   920 		CContactItemField* currentField = CContactItemField::NewLC();	
       
   921 		currentField->InternalizeL(aStream);	
       
   922 		iFields->AppendL(currentField);
       
   923 		CleanupStack::Pop(currentField);	
       
   924 		}
       
   925 
       
   926 	}
       
   927 
       
   928 void CContactItemFieldSet::ExternalizeL(RWriteStream& aStream) const 
       
   929 /** Externalises a CContactItemFieldSet object to a write stream.
       
   930 @param aStream Stream to which the object should be externalised. */
       
   931 	{
       
   932 	TInt fieldCount = Count(); // Number of fields.
       
   933 	aStream.WriteInt32L(fieldCount);	
       
   934 	for(TInt index=0; index<fieldCount; ++index)
       
   935 		{
       
   936 			(*iFields)[index]->ExternalizeL(aStream);
       
   937 			
       
   938 		}
       
   939 	}		
       
   940 
       
   941 
       
   942 /*
       
   943  * Constructor. 
       
   944  * This is marked as private because CContactItem is an abstract base class.
       
   945  */
       
   946 CContactItem::CContactItem()
       
   947 	{
       
   948 	}
       
   949 
       
   950 /** Constructs a new contact item based on a RReadStream.
       
   951 @param aStream RReadStream containing object to internalize.
       
   952 @return Pointer to the newly created CContactItem. This is left on the cleanup stack. 
       
   953 @internalTechnology 
       
   954 */	
       
   955 CContactItem* CContactItem::NewLC(RReadStream& aStream)
       
   956 	{ // static
       
   957 	TUid ContactItemType;
       
   958 	ContactItemType.iUid = aStream.ReadInt32L();
       
   959 
       
   960 	CContactItem* item = NewLC(ContactItemType);
       
   961 	item->InternalizeL(aStream);
       
   962 	
       
   963 	return item;
       
   964 	}	
       
   965 	
       
   966 /** Constructs a new contact item.
       
   967 
       
   968 @return Pointer to the newly created CContactItem. This is left on the cleanup stack. 
       
   969 @internalTechnology 
       
   970 */
       
   971 EXPORT_C CContactItem* CContactItem::NewLC(TUid aType)
       
   972 	{ // static
       
   973 	CContactItem* item=NULL;
       
   974 		
       
   975 	switch(aType.iUid)
       
   976 		{
       
   977 		case KUidContactCardValue:
       
   978 			item = CContactCard::NewLC();
       
   979 			break;
       
   980 			
       
   981 		case KUidContactGroupValue:
       
   982 			item = CContactGroup::NewLC();
       
   983 			break;
       
   984 						
       
   985 		case KUidContactOwnCardValue:
       
   986 			item = CContactOwnCard::NewLC();
       
   987 			break;
       
   988 			
       
   989 		case KUidContactICCEntryValue:
       
   990 			item=CContactICCEntry::NewL();
       
   991 			CleanupStack::PushL(item);
       
   992 			break;
       
   993 
       
   994 		case KUidContactTemplateValue:
       
   995 			item = CContactTemplate::NewLC();
       
   996 			break;												
       
   997 			
       
   998 		case KUidContactCardTemplateValue:
       
   999 			item = CContactCardTemplate::NewLC();
       
  1000 			break;	
       
  1001 			
       
  1002 		default:
       
  1003 			User::Leave(KErrNotSupported);
       
  1004 			break;																
       
  1005 		
       
  1006 		}		
       
  1007 		
       
  1008 	return item;
       
  1009 	}			
       
  1010 
       
  1011 /*
       
  1012  * Second-phase construction.
       
  1013  * Set template ID on which this contact item is based as KNullContactId.
       
  1014  */
       
  1015 void CContactItem::ConstructL()
       
  1016 	{
       
  1017 	iFieldSet=CContactItemFieldSet::NewL();
       
  1018 	SetTemplateRefId(KNullContactId);
       
  1019 	}
       
  1020 
       
  1021 /*
       
  1022  * Second-phase construction overload.
       
  1023  */
       
  1024 void CContactItem::ConstructL(const CContactItem* aTemplate)
       
  1025 	{
       
  1026 	ConstructL();
       
  1027 
       
  1028 	const TUid type = Type();
       
  1029 	if (type==KUidContactCardTemplate || type==KUidContactOwnCard || type==KUidContactGroup)
       
  1030 		{
       
  1031 		SetTemplateRefId(KNullContactId);
       
  1032 		}
       
  1033 	else if (aTemplate->TemplateRefId()==KNullContactId) // can only be template
       
  1034 		{//record the contacts template
       
  1035 		SetTemplateRefId(aTemplate->Id());
       
  1036 		}
       
  1037 
       
  1038 	const CContactItemFieldSet& fieldSet=aTemplate->CardFields();
       
  1039 	const TInt fieldCount = fieldSet.Count();
       
  1040 	for(TInt loop=0;loop<fieldCount;loop++)
       
  1041 		{
       
  1042 		const CContactItemField& templateField=fieldSet[loop];
       
  1043 		if (!templateField.IsTemplateLabelField())
       
  1044 			{
       
  1045 			CContactItemField* field=CContactItemField::NewLC(templateField);
       
  1046 			AddFieldL(*field);
       
  1047 			CleanupStack::Pop(field);	
       
  1048 			field->CopyStorageL(templateField);
       
  1049 			}
       
  1050 		}
       
  1051 	}
       
  1052 
       
  1053 EXPORT_C CContactItem::~CContactItem()
       
  1054 /** The destructor frees all resources owned by the contact item, prior to its 
       
  1055 destruction. */
       
  1056 	{
       
  1057 	delete iFieldSet;
       
  1058 	delete iGuid;
       
  1059 	}
       
  1060 
       
  1061 EXPORT_C TContactItemId CContactItem::Id() const
       
  1062 /** Gets the contact item's ID.
       
  1063 
       
  1064 @return The contact item's ID. */
       
  1065 	{
       
  1066 	return iId;
       
  1067 	}
       
  1068 	
       
  1069 /**
       
  1070 Sets the contact item's ID.
       
  1071 
       
  1072 @internalTechnology
       
  1073 @released
       
  1074 */	
       
  1075 EXPORT_C void CContactItem::SetId(TContactItemId aId)
       
  1076 	{
       
  1077 	iId = aId;
       
  1078 	}
       
  1079 	
       
  1080 /**
       
  1081 Returns the contact item's attributes.
       
  1082 
       
  1083 @return contact item's attributes
       
  1084 
       
  1085 @internalTechnology
       
  1086 @released
       
  1087 */		
       
  1088 EXPORT_C TUint32 CContactItem::Attributes() const
       
  1089 	{
       
  1090 	return iAttributes;	
       
  1091 	}
       
  1092 
       
  1093 /**
       
  1094 Sest the contact item's attributes.
       
  1095 
       
  1096 @internalTechnology
       
  1097 @released
       
  1098 */			
       
  1099 EXPORT_C void CContactItem::SetAttributes(TUint32 aAttributes)
       
  1100 	{
       
  1101 	iAttributes = aAttributes;	
       
  1102 	}
       
  1103 	
       
  1104 /**
       
  1105 Sest the contact item's access count.
       
  1106 
       
  1107 @internalTechnology
       
  1108 @released
       
  1109 */				
       
  1110 EXPORT_C void CContactItem::SetAccessCount(TUint32 aAccessCount)
       
  1111 	{
       
  1112 	iAccessCount = aAccessCount;	
       
  1113 	}
       
  1114 	
       
  1115 /**
       
  1116 Sest the contact item's creation time.
       
  1117 
       
  1118 @internalTechnology
       
  1119 @released
       
  1120 */				
       
  1121 EXPORT_C void CContactItem::SetCreationDate(const TTime& aTime)
       
  1122 	{
       
  1123 	iCreationDate = aTime.Int64();	
       
  1124 	}
       
  1125 	
       
  1126 EXPORT_C TContactItemId CContactItem::TemplateRefId() const
       
  1127 /** Gets the ID of the template which was used to create this contact item.
       
  1128 
       
  1129 @return The ID of the template on which this item is based. KNullContactId 
       
  1130 if the item is not based on a template. */
       
  1131 	{
       
  1132 	return iTemplateRefId;
       
  1133 	}
       
  1134 
       
  1135 EXPORT_C TTime CContactItem::LastModified() const
       
  1136 /** Gets the contact item's last modified date/time.
       
  1137 
       
  1138 @return The contact item's last modified date/time. */
       
  1139 	{
       
  1140 	return iLastModified;
       
  1141 	}
       
  1142 
       
  1143 EXPORT_C void CContactItem::SetLastModified(const TTime& aLastModified)
       
  1144 /** Sets the last modified date/time value stored in the local copy of the contact 
       
  1145 item. This value is returned by LastModified() for this copy of the item.
       
  1146 
       
  1147 This function has no effect on the item's last modified date/time which is 
       
  1148 stored in the database; this is always the date/time the contact was last 
       
  1149 committed.
       
  1150 
       
  1151 This function is provided for use when synchronising 
       
  1152 contact items.
       
  1153 
       
  1154 @param aLastModified The contact item's last modified date/time. */
       
  1155 	{
       
  1156 	iLastModified=aLastModified.Int64();
       
  1157 	}
       
  1158 
       
  1159 EXPORT_C void CContactItem::SetHidden(TBool aHidden)
       
  1160 /** Sets the contact item's hidden attribute. Hidden means that the item is not 
       
  1161 displayed if the view definition excludes hidden fields.
       
  1162 
       
  1163 @param aHidden ETrue to set the hidden attribute for the item, EFalse to unset 
       
  1164 it. */
       
  1165     	{
       
  1166     	if (aHidden)
       
  1167     		iAttributes|=EHidden;
       
  1168     	else
       
  1169     		iAttributes&=~EHidden;
       
  1170     	} 
       
  1171 EXPORT_C void CContactItem::SetSystem(TBool aSystem)
       
  1172 /** Sets the contact item's system attribute. Note that the system attribute is 
       
  1173 not currently used in the contacts model.
       
  1174 
       
  1175 @param aSystem ETrue to set the system attribute, EFalse to unset it. */
       
  1176     	{
       
  1177     	if (aSystem)
       
  1178     		iAttributes|=ESystem;
       
  1179     	else
       
  1180     		iAttributes&=~ESystem;
       
  1181     	}
       
  1182 
       
  1183 EXPORT_C void CContactItem::SetDeleted(TBool aDeleted)
       
  1184 /** Sets the value of the contact item's Is deleted attribute.
       
  1185 
       
  1186 If the attribute is set, this means that an attempt has been made to delete 
       
  1187 the contact item, but because the item's access count is greater than zero, 
       
  1188 its data persists and the item is just marked as deleted.
       
  1189 
       
  1190 @param aDeleted ETrue to set the Is deleted attribute. EFalse to unset it. */
       
  1191     	{
       
  1192     	if (aDeleted)
       
  1193     		iAttributes|=EDeleted;
       
  1194     	else
       
  1195     		iAttributes&=~EDeleted;
       
  1196     	}
       
  1197 
       
  1198 EXPORT_C TBool CContactItem::IsHidden() 
       
  1199 /** Gets the value of the contact item's hidden attribute. Hidden means that the 
       
  1200 item is not displayed if the view definition excludes hidden fields.
       
  1201 
       
  1202 @return ETrue if hidden, EFalse if not. */
       
  1203 	{ return iAttributes&EHidden; }
       
  1204 
       
  1205 EXPORT_C TBool CContactItem::IsSystem() 
       
  1206 /** Gets the value of the contact item's system attribute. Note that the system 
       
  1207 attribute is not currently used in the contacts model.
       
  1208 
       
  1209 @return ETrue if system, EFalse if not. */
       
  1210 	{ return iAttributes&ESystem; }
       
  1211 
       
  1212 EXPORT_C TBool CContactItem::IsDeleted()  const
       
  1213 /** Gets the value of the Is deleted attribute as set by SetDeleted().
       
  1214 
       
  1215 @return ETrue if deleted, EFalse if not. */
       
  1216 	{ return iAttributes&EDeleted; }
       
  1217 
       
  1218 EXPORT_C void CContactItem::SetTemplateRefId(TContactItemId aUid)
       
  1219 /** Sets the ID of the template on which this contact item is based.
       
  1220 
       
  1221 @param aUid The ID of the template on which this item is based. */
       
  1222 	{
       
  1223 	iTemplateRefId=aUid;
       
  1224 	}
       
  1225 
       
  1226 EXPORT_C void CContactItem::AddFieldL(CContactItemField& aField)
       
  1227 /** Appends a field to the contact item's field set. The contact item takes ownership 
       
  1228 of the field.
       
  1229 
       
  1230 @param aField The field to append to the contact item's field set. */
       
  1231 	{
       
  1232 	__ASSERT_DEBUG(&aField!=NULL,Panic(ECntPanicNullPointer));
       
  1233 	if (this->Type()==KUidContactCardTemplate)
       
  1234 		aField.SetTemplateField(ETrue);
       
  1235 	else 
       
  1236 		aField.SetTemplateField(EFalse);
       
  1237 	iFieldSet->AddL(aField);
       
  1238 	}
       
  1239 
       
  1240 EXPORT_C void CContactItem::RemoveField(TInt aFieldPos)
       
  1241 /** Removes a field from the contact item's field set. A panic occurs if the specified 
       
  1242 field does not exist in the field set.
       
  1243 
       
  1244 @param aFieldPos Index within the field set of the field to remove. */
       
  1245 	{
       
  1246 	if (!(*iFieldSet)[aFieldPos].IsTemplateLabelField())
       
  1247 		iFieldSet->Remove(aFieldPos);
       
  1248 	}
       
  1249 
       
  1250 EXPORT_C void CContactItem::InsertFieldL(CContactItemField& aField,TInt aFieldPos)
       
  1251 /** Inserts a field into the contact item's field set. The contact item takes ownership 
       
  1252 of the field.
       
  1253 
       
  1254 @param aField The field to insert into the contact item's field set.
       
  1255 @param aFieldPos The position in the field set at which to insert the field. 
       
  1256 If this value is greater than the total number of fields, it is appended. 
       
  1257 The position is relative to zero, i.e. zero implies that the element is inserted 
       
  1258 at the beginning of the array. */
       
  1259 	{
       
  1260 	if (this->Type()==KUidContactCardTemplate)
       
  1261 		aField.SetTemplateField(ETrue);
       
  1262 	iFieldSet->InsertL(aFieldPos,aField);
       
  1263 	}
       
  1264 
       
  1265 EXPORT_C void CContactItem::UpdateFieldSet(CContactItemFieldSet* aNewFieldSet)
       
  1266 /** Replaces the contact item's field set.
       
  1267 
       
  1268 @param aNewFieldSet The new field set with which to replace the existing one. */
       
  1269 	{
       
  1270 	delete iFieldSet;
       
  1271 	iFieldSet = NULL;
       
  1272 	iFieldSet=aNewFieldSet;
       
  1273 	}
       
  1274 
       
  1275 TContactItemId  CContactItem::Agent()
       
  1276 	{
       
  1277 	TContactItemId fieldindex=iFieldSet->FindNext(KUidContactFieldMatchAll,KUidContactFieldVCardMapAGENT);
       
  1278 	if (fieldindex!=KErrNotFound)
       
  1279 		return(TContactItemId(
       
  1280 		(*iFieldSet)[fieldindex].AgentStorage()->Value()));
       
  1281 	else
       
  1282 		return KNullContactId;
       
  1283 	}
       
  1284 
       
  1285 EXPORT_C CContactItemFieldSet& CContactItem::CardFields() const
       
  1286 /** Gets a reference to the contact item's field set.
       
  1287 
       
  1288 @return A reference to the contact item's field set. */
       
  1289 	{
       
  1290 	return *iFieldSet;
       
  1291 	}
       
  1292 
       
  1293 
       
  1294 EXPORT_C void CContactItem::SetUidStringL(TDesC& aString) 
       
  1295 /** Sets the item's UID string. This replaces any existing string. Contact items have 
       
  1296 a globally unique identifier, stored as a descriptor which is provided for 
       
  1297 vCard support. It is a combination of the database's unique identifier (see 
       
  1298 CContactDatabase::MachineId()), the contact item ID and the date/time of the 
       
  1299 contact item's creation.
       
  1300 
       
  1301 @param aString The contact item's UID string. */
       
  1302 	{
       
  1303 	HBufC* guid=aString.AllocL();
       
  1304 	if (iGuid)
       
  1305 		delete iGuid;
       
  1306 	iGuid=guid;
       
  1307 	}
       
  1308 
       
  1309 EXPORT_C TPtrC CContactItem::UidStringL(TInt64 aMachineUniqueId) const
       
  1310 /** Returns a descriptor which contains the item's UID string. Contact items have 
       
  1311 a globally unique identifier, stored as a descriptor. This is provided for 
       
  1312 vCard support. It is a combination of the database's unique identifier, the 
       
  1313 contact item ID and the date/time of the contact item's creation.
       
  1314 
       
  1315 @param aMachineUniqueId The database's unique identifier. This can be retrieved 
       
  1316 using CContactDatabase::MachineId().
       
  1317 @return The item's UID string. */
       
  1318 	{
       
  1319     TPtrC guid;
       
  1320 	if (iGuid)
       
  1321 		{
       
  1322 		if (GuidIsCompressed())
       
  1323 			CONST_CAST(CContactItem &,*this).MakeUidStringL(aMachineUniqueId);  
       
  1324 		guid.Set(*iGuid);
       
  1325 		}
       
  1326     return guid;
       
  1327 	}
       
  1328 
       
  1329 void CContactItem::MakeUidStringL(TInt64 aMachineUniqueId) 
       
  1330 	{
       
  1331 	HBufC* guid = NULL;
       
  1332 	if (iGuid->Length())
       
  1333 		guid=ContactGuid::CreateGuidLC(iGuid->Des(),iId,aMachineUniqueId); // pass creation time
       
  1334 	else
       
  1335 		guid=ContactGuid::CreateGuidLC(iId, aMachineUniqueId);
       
  1336 	delete iGuid;
       
  1337 	iGuid=guid;
       
  1338 	iAttributes&=~(ECompressedGuid);
       
  1339 	CleanupStack::Pop(); // iGuid
       
  1340 	}
       
  1341 
       
  1342 /**
       
  1343 @internalTechnology 
       
  1344 */
       
  1345 EXPORT_C void CContactItem::SetHasCompressedGuid(TBool aCompressed)
       
  1346 	{
       
  1347 	if (aCompressed)
       
  1348 		iAttributes|=ECompressedGuid;
       
  1349 	else
       
  1350 		iAttributes&=~(ECompressedGuid);
       
  1351 	}
       
  1352 
       
  1353 
       
  1354 TBool CContactItem::GuidIsCompressed() const
       
  1355 	{return iAttributes&ECompressedGuid;}
       
  1356 
       
  1357 
       
  1358 
       
  1359 /** 
       
  1360 Part of the system template update implementation. 
       
  1361 This could be used for a generic update method at a later stage.
       
  1362 @since 7.0
       
  1363 @internalTechnology
       
  1364 */
       
  1365 TInt CContactItem::NumberOfFieldsToStore() const
       
  1366 	{
       
  1367 	TInt retval = 0, counter = 0;
       
  1368 	const TInt max = iFieldSet->Count();
       
  1369 	for (counter = 0; counter < max; counter++)
       
  1370 		{
       
  1371 		if ( !   (*iFieldSet)[counter].IsDeleted() ) retval++;
       
  1372 		}
       
  1373 	return retval;
       
  1374 	}
       
  1375 
       
  1376 /** 
       
  1377 Part of the system template update implementation. 
       
  1378 This could be used for a generic update method at a later stage.
       
  1379 @since 7.0
       
  1380 @internalTechnology
       
  1381 */
       
  1382 TStreamId CContactItem::PopulateStoreL(CStreamStore& aStore, CArrayFix<TFieldHeader>& aFieldHeaderArray) const
       
  1383 	{
       
  1384 	RStoreWriteStream rootStream;
       
  1385 	TInt counter = 0;
       
  1386 	TStreamId streamId = rootStream.CreateLC(aStore);
       
  1387 	const TInt hintCount = aFieldHeaderArray.Count();
       
  1388 
       
  1389 	rootStream <<TCardinality(NumberOfFieldsToStore());
       
  1390 
       
  1391 	for (counter = 0;counter < hintCount; counter++)
       
  1392 		{
       
  1393 		(*iFieldSet)[counter].PopulateStoreL(rootStream, counter, aFieldHeaderArray);
       
  1394 		}
       
  1395 	rootStream.CommitL();
       
  1396 	aStore.CommitL();
       
  1397 	CleanupStack::PopAndDestroy(&rootStream); 
       
  1398 	return streamId;
       
  1399 	}
       
  1400 
       
  1401 
       
  1402 void CContactItem::AddLabelFieldL()
       
  1403 	{
       
  1404 	TInt pos = iFieldSet->Find(KUidContactFieldTemplateLabel);
       
  1405 	if (pos==KErrNotFound)	// !HasItemLabelField()
       
  1406 		{
       
  1407 		CContactItemField* labelField = CContactItemField::NewLC(KStorageTypeText);
       
  1408 		labelField->AddFieldTypeL(KUidContactFieldTemplateLabel);
       
  1409 		if (Type()==KUidContactGroup)
       
  1410 			{
       
  1411 			_LIT(KGroupLabel,"Group Label");
       
  1412 			labelField->SetLabelL(KGroupLabel);
       
  1413 			}
       
  1414 		else if (Type()==KUidContactCardTemplate)
       
  1415 			{
       
  1416 			_LIT(KTemplateLabel,"Template Label");
       
  1417 			labelField->SetLabelL(KTemplateLabel);
       
  1418 			}
       
  1419 	// field needs to be first in the list
       
  1420 	// bug in stream retrieval of fields
       
  1421 		InsertFieldL(*labelField,0);
       
  1422 		CleanupStack::Pop(); // labelField
       
  1423 		}
       
  1424 	else	if (pos!=0)
       
  1425 		{
       
  1426 		iFieldSet->Move(pos,0);
       
  1427 		}
       
  1428 	}
       
  1429 
       
  1430 
       
  1431 /**
       
  1432  Restore fields from the template to the contact item.
       
  1433 @param aTemplateFields Fields to add
       
  1434 @param aViewDef View definition to use
       
  1435 @internalTechnology 
       
  1436  */
       
  1437 EXPORT_C void CContactItem::RestoreTemplateFieldsL(const CContactItemFieldSet& aSystemTemplateFields, const CContactItemFieldSet& aTemplateFields, const CContactItemViewDef& aViewDef)
       
  1438 	{
       
  1439 	TInt insertPos=0;
       
  1440 	const TInt templateFieldCount=aTemplateFields.Count();
       
  1441 	for (TInt ii=0;ii<templateFieldCount;ii++)
       
  1442 		{
       
  1443 		const CContactItemField& templateField=aTemplateFields[ii];
       
  1444 		TInt fieldPos=iFieldSet->FieldTypeCount(aSystemTemplateFields, insertPos, templateField);
       
  1445 		if (fieldPos<0 && ((aViewDef.Mode()==CContactItemViewDef::EMaskHiddenFields && !templateField.IsHidden())
       
  1446 						|| (aViewDef.Mode()==CContactItemViewDef::EIncludeHiddenFields))
       
  1447 						&& (!templateField.ContentType().ContainsFieldType(KUidContactFieldTemplateLabel)))
       
  1448 			{
       
  1449 			CContactItemField* field = CContactItemField::NewLC(templateField);
       
  1450 			field->SetTemplateField(EFalse); //make sure it isn't set as a template field
       
  1451 			field->SetOverRidesLabel(EFalse);
       
  1452 			iFieldSet->InsertL(insertPos++,*field);
       
  1453 			CleanupStack::Pop(field); 
       
  1454 			}
       
  1455 		else 
       
  1456 			{
       
  1457 			while(fieldPos>=0)
       
  1458 				{
       
  1459 				iFieldSet->Move(fieldPos,insertPos++); //move the field to the correct position
       
  1460 				fieldPos=iFieldSet->FieldTypeCount(aSystemTemplateFields, insertPos, templateField);
       
  1461 				}
       
  1462 			}
       
  1463 		}
       
  1464 	}
       
  1465 
       
  1466 
       
  1467 
       
  1468 void CContactItem::ClearFieldContent()
       
  1469 	{	
       
  1470 	for (TInt i=0;i<iFieldSet->Count();i++)
       
  1471 		{
       
  1472 		CContactItemField& field=(*iFieldSet)[i];
       
  1473 		if (!field.IsTemplateLabelField())
       
  1474 			field.ResetStore();
       
  1475 		}
       
  1476 	}	
       
  1477 	
       
  1478 void CContactItem::InternalizeL(RReadStream& aStream)
       
  1479 /** Internalises a CContactItem object from a read stream. 
       
  1480 @param aStream Stream from which the object should be internalised. */
       
  1481 	{
       
  1482 	
       
  1483 	delete iFieldSet;
       
  1484 	iFieldSet = NULL;
       
  1485 	iFieldSet=CContactItemFieldSet::NewL();
       
  1486 	iFieldSet->InternalizeL(aStream);
       
  1487 	
       
  1488 	iAttributes = aStream.ReadUint32L();
       
  1489 	
       
  1490 	iId = aStream.ReadInt32L();
       
  1491 	
       
  1492 	iTemplateRefId = aStream.ReadInt32L();
       
  1493 	
       
  1494 	TInt64 tempInt64;
       
  1495 	aStream >> tempInt64;
       
  1496 	iLastModified = TTime(tempInt64);	
       
  1497 	
       
  1498 	aStream >> tempInt64;
       
  1499 	iCreationDate = TTime(tempInt64);	
       
  1500 		
       
  1501 	iAccessCount = aStream.ReadUint32L();
       
  1502 	
       
  1503 	if (iGuid)
       
  1504 		{
       
  1505 		delete iGuid;		
       
  1506 		iGuid = NULL;
       
  1507 		}
       
  1508 
       
  1509 	const TInt length=aStream.ReadInt32L();
       
  1510 	if (length)
       
  1511 		{
       
  1512 		iGuid=HBufC::NewL(aStream,length);	
       
  1513 		}	
       
  1514 				
       
  1515 	}
       
  1516 
       
  1517 void CContactItem::ExternalizeL(RWriteStream& aStream) const 
       
  1518 /** Externalises a CContactItem object to a write stream.
       
  1519 @param aStream Stream to which the object should be externalised. */
       
  1520 	{
       
  1521 	aStream.WriteInt32L(Type().iUid);
       
  1522 		
       
  1523 	iFieldSet->ExternalizeL(aStream);
       
  1524 	
       
  1525 	aStream.WriteUint32L(iAttributes);
       
  1526 	
       
  1527 	aStream.WriteInt32L(iId);
       
  1528 	
       
  1529 	aStream.WriteInt32L(iTemplateRefId);
       
  1530 	
       
  1531 	aStream << iLastModified.Int64();
       
  1532 	
       
  1533 	aStream << iCreationDate.Int64();
       
  1534 		
       
  1535 	aStream.WriteUint32L(iAccessCount);
       
  1536 	
       
  1537 	if(iGuid)
       
  1538 		{
       
  1539 		
       
  1540 		const TInt length=iGuid->Length();
       
  1541 		aStream.WriteInt32L(length);	
       
  1542 		if (length)
       
  1543 			{		
       
  1544 			aStream << *(iGuid);
       
  1545 			}
       
  1546 		}
       
  1547 	else
       
  1548 		{
       
  1549 		aStream.WriteInt32L(0);
       
  1550 		}
       
  1551 		
       
  1552 	}		
       
  1553 
       
  1554 
       
  1555 //
       
  1556 // class CContactCardTemplate
       
  1557 //
       
  1558 
       
  1559 EXPORT_C CContactCardTemplate* CContactCardTemplate::NewL()
       
  1560 	{ // static
       
  1561 	/** Allocates and constructs a new Contact Card Template .
       
  1562 	@return Pointer to the newly created Contact Card Template.     */
       
  1563 	CContactCardTemplate* card=CContactCardTemplate::NewLC();
       
  1564 	CleanupStack::Pop(); // card
       
  1565 	return card;
       
  1566 	}
       
  1567 
       
  1568 EXPORT_C CContactCardTemplate* CContactCardTemplate::NewLC()
       
  1569 	{ // static
       
  1570 	/** Allocates and constructs a new Contact Card Template .
       
  1571 	@return  Pointer to the newly created Contact Card Template. This is left on the cleanup stack. */
       
  1572 	CContactCardTemplate* card=new(ELeave) CContactCardTemplate;
       
  1573 	CleanupStack::PushL(card);
       
  1574 	card->ConstructL();
       
  1575 	return card;
       
  1576 	}
       
  1577 
       
  1578 EXPORT_C CContactCardTemplate* CContactCardTemplate::NewL(const CContactItem *aTemplate)
       
  1579 	{
       
  1580     /** Allocates and constructs a new Contact Card Template .
       
  1581 	@param aTemplate Pointer to the template whose field set and field data are copied into the new contact card template
       
  1582 	@return Pointer to the newly created Contact Card Template.      */   
       
  1583 	
       
  1584 	CContactCardTemplate* card=CContactCardTemplate::NewLC(aTemplate);
       
  1585 	CleanupStack::Pop(); // card
       
  1586 	return card;
       
  1587 	}
       
  1588 
       
  1589 EXPORT_C CContactCardTemplate* CContactCardTemplate::NewLC(const CContactItem *aTemplate)
       
  1590 	{ // static
       
  1591     /** Allocates and constructs a new Contact Card Template .
       
  1592 	@param aTemplate Pointer to the template whose field set and field data are copied into the new contact card template 
       
  1593 	@return  Pointer to the newly created Contact Card Template. This is left on the cleanup stack. */
       
  1594 	
       
  1595 	CContactCardTemplate* card=new(ELeave) CContactCardTemplate;
       
  1596 	CleanupStack::PushL(card);
       
  1597 	card->ConstructL(aTemplate);
       
  1598 	return card;
       
  1599 	}
       
  1600 
       
  1601 EXPORT_C void CContactCardTemplate::SetTemplateLabelL(const TDesC& aLabel)
       
  1602 /** Changes the label for a contact card template. The label is initialised when 
       
  1603 the template is created. The template label is stored in a text field in the 
       
  1604 template. This field has a unique content type mapping of KUidContactFieldTemplateLabel. 
       
  1605 By default, this field is the first field in the field set; it must not be 
       
  1606 moved from this position.
       
  1607 
       
  1608 @param aLabel The new template label.
       
  1609 @leave KErrNotFound Indicates there is no template label field in the template. */
       
  1610 	{
       
  1611 	CContactItemFieldSet& labelFields = this->CardFields();
       
  1612 	// find label field
       
  1613 	TInt pos = labelFields.Find(KUidContactFieldTemplateLabel);
       
  1614 	if (pos==KErrNotFound)
       
  1615 		User::Leave(pos);
       
  1616 	labelFields[pos].TextStorage()->SetTextL(aLabel);
       
  1617 	}		
       
  1618 
       
  1619 EXPORT_C TPtrC CContactCardTemplate::GetTemplateLabelL()
       
  1620 /** Gets the label for a contact card template.
       
  1621 
       
  1622 @leave KErrNotFound Indicates there is no template label field in the template. 
       
  1623 
       
  1624 @return The template label. */
       
  1625 	{
       
  1626 	CContactItemFieldSet& labelFields = this->CardFields();
       
  1627 	// find 
       
  1628 	TInt pos = labelFields.Find(KUidContactFieldTemplateLabel);
       
  1629 	if (pos==KErrNotFound)
       
  1630 		User::Leave(pos);
       
  1631 	return(labelFields[pos].TextStorage()->Text());
       
  1632 	}
       
  1633 
       
  1634 EXPORT_C TBool CContactCardTemplate::HasItemLabelField()
       
  1635 	{
       
  1636 /** Tests whether a Template label field is present.
       
  1637 @return ETrue if Template Label Field is present, EFalse otherwise.  */
       
  1638 	CContactItemFieldSet& labelFields = this->CardFields();
       
  1639 	TInt pos = labelFields.Find(KUidContactFieldTemplateLabel);
       
  1640 	if (pos==KErrNotFound)
       
  1641 		return EFalse;
       
  1642 	return ETrue;
       
  1643 	}
       
  1644 
       
  1645 EXPORT_C TUid CContactCardTemplate::Type() const
       
  1646 	{
       
  1647 	return KUidContactCardTemplate;
       
  1648 	}
       
  1649 
       
  1650 CContactCardTemplate::CContactCardTemplate()
       
  1651 	{
       
  1652 	}
       
  1653 
       
  1654 //
       
  1655 // CContactItemPlusGroup
       
  1656 //
       
  1657 
       
  1658 /**
       
  1659 @internalComponent
       
  1660 */
       
  1661 CContactItemPlusGroup::CContactItemPlusGroup()
       
  1662 	{}
       
  1663 
       
  1664 EXPORT_C CContactItemPlusGroup::~CContactItemPlusGroup()
       
  1665 /** 
       
  1666 Frees the array of group IDs to which the derived class object 
       
  1667 belongs.
       
  1668 Frees the array of contact item IDs which identify the groups to 
       
  1669 which the derived class object belongs, prior to its destruction. */
       
  1670 
       
  1671 	{
       
  1672 	delete iGroups;
       
  1673 	}
       
  1674 
       
  1675 EXPORT_C const CContactIdArray* CContactItemPlusGroup::GroupsJoined() const
       
  1676 /** Returns a pointer to a list of contact item IDs which identify the groups to 
       
  1677 which the derived class object belongs.
       
  1678 
       
  1679 @return A pointer to the array of groups IDs to which the derived class object 
       
  1680 belongs. NULL if the object is not a member of any groups. */
       
  1681 	{
       
  1682 	return(iGroups);
       
  1683 	}
       
  1684 
       
  1685 EXPORT_C CContactIdArray* CContactItemPlusGroup::GroupsJoinedLC() const
       
  1686 /** Returns a pointer to a list of contact item IDs which identify the groups to 
       
  1687 which the derived class object belongs.
       
  1688 
       
  1689 @return A pointer to a copy of the array of groups IDs to which the derived 
       
  1690 class object belongs. This array is empty if the object is not a member of 
       
  1691 any groups. The caller takes ownership of this object, so is responsible for 
       
  1692 its deletion. */
       
  1693 	{
       
  1694 	CContactIdArray* copy=NULL;
       
  1695 	if (iGroups)
       
  1696 		copy=CContactIdArray::NewLC(iGroups);
       
  1697 	else
       
  1698 		copy=CContactIdArray::NewLC();
       
  1699 	return copy;
       
  1700 	}
       
  1701 	
       
  1702 void CContactItemPlusGroup::InternalizeL(RReadStream& aStream)
       
  1703 /** Internalises a CContactItemPlusGroup object from a read stream. 
       
  1704 @param aStream Stream from which the object should be internalised. */
       
  1705 	{
       
  1706 	// Call Parent InternalizeL to internalize all members.
       
  1707 	CContactItem::InternalizeL(aStream);
       
  1708 	
       
  1709 	if (iGroups)
       
  1710 		{
       
  1711 		delete iGroups;		
       
  1712 		iGroups = NULL;
       
  1713 		}
       
  1714 	
       
  1715 	// TBool CheckIfExists = aStream.ReadInt32L();
       
  1716 	if (aStream.ReadInt32L())
       
  1717 		{
       
  1718 		iGroups = CContactIdArray::NewL();		
       
  1719 		iGroups->InternalizeL(aStream);
       
  1720 		}	
       
  1721 		
       
  1722 	}
       
  1723 
       
  1724 void CContactItemPlusGroup::ExternalizeL(RWriteStream& aStream) const 
       
  1725 /** Externalises a CContactItemPlusGroup object to a write stream.
       
  1726 @param aStream Stream to which the object should be externalised. */
       
  1727 	{	
       
  1728 	// Call Parent ExternalizeL to externalize all members.
       
  1729 	CContactItem::ExternalizeL(aStream);
       
  1730 	if(iGroups)
       
  1731 		{
       
  1732 		aStream.WriteInt32L(1);
       
  1733 		iGroups->ExternalizeL(aStream);
       
  1734 		}
       
  1735 	else
       
  1736 		{
       
  1737 		aStream.WriteInt32L(0); // Empty group
       
  1738 		}		
       
  1739 
       
  1740 	}		
       
  1741 
       
  1742 /**
       
  1743 Resets groups.
       
  1744 
       
  1745 @internalTechnology
       
  1746 @released
       
  1747 */	
       
  1748 EXPORT_C void CContactItemPlusGroup::ResetGroups()
       
  1749 	{
       
  1750 	delete iGroups;
       
  1751 	iGroups = NULL;	
       
  1752 	}
       
  1753 	
       
  1754 /**
       
  1755 Sets groups.
       
  1756 
       
  1757 @internalTechnology
       
  1758 @released
       
  1759 */		
       
  1760 EXPORT_C void CContactItemPlusGroup::SetGroups(CContactIdArray* aGroups)
       
  1761 	{
       
  1762 	iGroups = aGroups;		
       
  1763 	}
       
  1764 
       
  1765 //
       
  1766 // class CContactCard
       
  1767 //
       
  1768 
       
  1769 EXPORT_C CContactCard::~CContactCard()
       
  1770 /** Frees all resources owned by the contact card, prior to its 
       
  1771 destruction. */
       
  1772 	{
       
  1773 	}
       
  1774 
       
  1775 EXPORT_C CContactCard* CContactCard::NewL()
       
  1776 /** Allocates and constructs a new contact card.
       
  1777 
       
  1778 @return Pointer to the newly created contact card. */
       
  1779 	{ // static
       
  1780 	CContactCard* card=CContactCard::NewLC();
       
  1781 	CleanupStack::Pop(); // card
       
  1782 	return card;
       
  1783 	}
       
  1784 
       
  1785 EXPORT_C CContactCard* CContactCard::NewLC()
       
  1786 /** Allocates and constructs a new contact card.
       
  1787 
       
  1788 @return Pointer to the newly created contact card. This is left on the 
       
  1789 cleanup stack.*/
       
  1790 	{ // static
       
  1791 	CContactCard* card=new(ELeave) CContactCard;
       
  1792 	CleanupStack::PushL(card);
       
  1793 	card->ConstructL();
       
  1794 	return card;
       
  1795 	}
       
  1796 
       
  1797 EXPORT_C CContactCard* CContactCard::NewL(const CContactItem *aTemplate)
       
  1798 /** Allocates and constructs a new contact card whose field set is seeded from 
       
  1799 a template.
       
  1800 
       
  1801 @param aTemplate Pointer to the template whose field set and field data are 
       
  1802 copied into the new contact card.
       
  1803 @return Pointer to the newly created contact card. */
       
  1804 	{
       
  1805 	CContactCard* card=CContactCard::NewLC(aTemplate);
       
  1806 	CleanupStack::Pop(); // card
       
  1807 	return card;
       
  1808 	}
       
  1809 
       
  1810 EXPORT_C CContactCard* CContactCard::NewLC(const CContactItem *aTemplate)
       
  1811 /** Allocates and constructs a new contact card whose field set is seeded from 
       
  1812 a template.
       
  1813 
       
  1814 @param aTemplate Pointer to the template whose field set and field data are 
       
  1815 copied into the new contact card.
       
  1816 @return Pointer to the newly created contact card. This is left on the cleanup stack. */
       
  1817 	{ // static
       
  1818 	CContactCard* card=new(ELeave) CContactCard;
       
  1819 	CleanupStack::PushL(card);
       
  1820 	card->ConstructL(aTemplate);
       
  1821 	return card;
       
  1822 	}
       
  1823 
       
  1824 EXPORT_C TUid CContactCard::Type() const
       
  1825 /** Implements CContactItem::Type().
       
  1826 
       
  1827 @return KUidContactCard. */
       
  1828 	{
       
  1829 	return KUidContactCard;
       
  1830 	}
       
  1831 
       
  1832 EXPORT_C CContactIdArray* CContactCard::GroupsJoinedLC() const
       
  1833 /** Returns a pointer to a list of contact item IDs which identify the groups to 
       
  1834 which this contact card belongs.
       
  1835 
       
  1836 @return A pointer to a copy of the array of groups IDs to which this contact 
       
  1837 card belongs. This array is empty if the card is not a member of any groups. 
       
  1838 The caller takes ownership of this object, so is responsible for its deletion. */
       
  1839 	{
       
  1840 	return(CContactItemPlusGroup::GroupsJoinedLC());
       
  1841 	}
       
  1842 
       
  1843 CContactCard::CContactCard()
       
  1844 	{
       
  1845 	}
       
  1846 
       
  1847 //
       
  1848 // class CContactOwnCard
       
  1849 //
       
  1850 
       
  1851 EXPORT_C CContactOwnCard::~CContactOwnCard()
       
  1852 /** Frees all resources owned by the own card, prior to its destruction. */
       
  1853 	{
       
  1854 	}
       
  1855 
       
  1856 EXPORT_C CContactOwnCard* CContactOwnCard::NewL()
       
  1857 /** Allocates and constructs a new own card. 
       
  1858 
       
  1859 Note: own cards should normally be constructed using the factory functions provided 
       
  1860 in class CContactDatabase, for example CreateOwnCardL().
       
  1861 
       
  1862 @return Pointer to the newly created own card. */
       
  1863 	{ // static
       
  1864 	CContactOwnCard* card=CContactOwnCard::NewLC();
       
  1865 	CleanupStack::Pop(); // card
       
  1866 	return card;
       
  1867 	}
       
  1868 
       
  1869 EXPORT_C CContactOwnCard* CContactOwnCard::NewLC()
       
  1870 /** Allocates and constructs a new own card. 
       
  1871 
       
  1872 Note: own cards should normally be constructed using the factory functions provided 
       
  1873 in class CContactDatabase, for example CreateOwnCardL().
       
  1874 
       
  1875 @return Pointer to the newly created own card. This is left on the cleanup stack. */
       
  1876 	{ // static
       
  1877 	CContactOwnCard* card=new(ELeave) CContactOwnCard;
       
  1878 	CleanupStack::PushL(card);
       
  1879 	card->ConstructL();
       
  1880 	return card;
       
  1881 	}
       
  1882 
       
  1883 EXPORT_C CContactOwnCard* CContactOwnCard::NewL(const CContactItem *aTemplate)
       
  1884 /** Allocates and constructs a new own card whose field set is seeded from a template. 
       
  1885 
       
  1886 Note: own cards should normally be constructed using the factory functions provided 
       
  1887 in class CContactDatabase, for example CreateOwnCardL().
       
  1888 
       
  1889 @param aTemplate Pointer to the template whose field set and field data are 
       
  1890 copied into the new own card.
       
  1891 @return Pointer to the newly created own card. */
       
  1892 	{
       
  1893 	CContactOwnCard* card=CContactOwnCard::NewLC(aTemplate);
       
  1894 	CleanupStack::Pop(); // card
       
  1895 	return card;
       
  1896 	}
       
  1897 
       
  1898 EXPORT_C CContactOwnCard* CContactOwnCard::NewLC(const CContactItem *aTemplate)
       
  1899 /** Allocates and constructs a new own card whose field set is seeded from a template. 
       
  1900 
       
  1901 Note: own cards should normally be constructed using the factory functions provided 
       
  1902 in class CContactDatabase, for example CreateOwnCardL().
       
  1903 
       
  1904 @param aTemplate Pointer to the template whose field set and field data are 
       
  1905 copied into the new own card.
       
  1906 @return Pointer to the newly created own card. This is left on the cleanup stack. */
       
  1907 	{ // static
       
  1908 	CContactOwnCard* card=new(ELeave) CContactOwnCard;
       
  1909 	CleanupStack::PushL(card);
       
  1910 	card->ConstructL(aTemplate);
       
  1911 	return card;
       
  1912 	}
       
  1913 
       
  1914 EXPORT_C TUid CContactOwnCard::Type() const
       
  1915 /** Implements CContactItem::Type(). 
       
  1916 
       
  1917 @return KUidContactOwnCard. */
       
  1918 	{
       
  1919 	return KUidContactOwnCard;
       
  1920 	}
       
  1921 
       
  1922 EXPORT_C CContactIdArray* CContactOwnCard::GroupsJoinedLC() const
       
  1923 /** Returns a pointer to a list of contact item IDs which identify the groups to 
       
  1924 which the current own card belongs.
       
  1925 
       
  1926 @return A pointer to a copy of the array of groups IDs to which this own card 
       
  1927 belongs. This array is empty if the own card is not a member of any groups. 
       
  1928 The caller takes ownership of this object, so is responsible for its deletion. */
       
  1929 	{
       
  1930 	return(CContactItemPlusGroup::GroupsJoinedLC());
       
  1931 	}
       
  1932 
       
  1933 /*
       
  1934  * Own card.
       
  1935  *
       
  1936  * An own card is a contact card which contains information about the
       
  1937  * device's owner. This can be sent to another compatible electronic
       
  1938  * device as a vCard. The contact database recognises a single own card
       
  1939  * referred to as the current own card; its ID is returned by
       
  1940  * <code>CContactDatabase::OwnCardId()</code>. Like a contact card, an
       
  1941  * own card can be a member of one or more contact card groups. The own
       
  1942  * card type is identified by a UID of <code>KUidContactOwnCard</code>,
       
  1943  * as returned by <code>Type()</code>.Own cards can be constructed using
       
  1944  * either <code>CContactDatabase::CreateOwnCardLC()</code> or
       
  1945  * <code>CreateOwnCardL()</code>. These functions create an own card,
       
  1946  * based on the system template, add it to the database, set it as the
       
  1947  * database's current own card and return a pointer to it. To change the
       
  1948  * database's current own card, use
       
  1949  * <code>CContactDatabase::SetOwnCardL()</code>.
       
  1950  *
       
  1951  * @since 5.2
       
  1952  */
       
  1953 CContactOwnCard::CContactOwnCard()
       
  1954 	{
       
  1955 	}
       
  1956 
       
  1957 //
       
  1958 // class CContactGroup
       
  1959 //
       
  1960 EXPORT_C CContactGroup* CContactGroup::NewL()
       
  1961 /** Allocates and constructs a new default contact card group. The group has no label and 
       
  1962 its list of members is NULL.
       
  1963 
       
  1964 Contact groups should be constructed using the factory functions provided 
       
  1965 in class CContactDatabase, for example CreateContactGroupL().
       
  1966 
       
  1967 @return Pointer to the new contact card group. */
       
  1968 	{ // static
       
  1969 	CContactGroup* group=CContactGroup::NewLC();
       
  1970 	CleanupStack::Pop();
       
  1971 	return group;
       
  1972 	}
       
  1973 
       
  1974 EXPORT_C CContactGroup* CContactGroup::NewLC()
       
  1975 /** Allocates and constructs a new default contact card group.
       
  1976 
       
  1977 The group has no label and its list of members is NULL.
       
  1978 
       
  1979 Contact groups should be constructed using the factory functions provided 
       
  1980 in class CContactDatabase, for example CreateContactGroupLC().
       
  1981 
       
  1982 @return Pointer to the new contact card group. This is left on the cleanup stack.*/
       
  1983 	{
       
  1984 	CContactGroup* group=new(ELeave) CContactGroup;
       
  1985 	CleanupStack::PushL(group);
       
  1986 	group->ConstructL();
       
  1987 	return group;
       
  1988 	}
       
  1989 
       
  1990 CContactGroup::CContactGroup()
       
  1991 	{
       
  1992 	}
       
  1993 
       
  1994 EXPORT_C CContactGroup::~CContactGroup()
       
  1995 /** The destructor frees all resources owned by the contact group, prior to its 
       
  1996 destruction. */
       
  1997 	{
       
  1998 	delete iItems;
       
  1999 	}
       
  2000 
       
  2001 EXPORT_C TUid CContactGroup::Type() const
       
  2002 /** Implements CContactItem::Type(). 
       
  2003 
       
  2004 @return KUidContactGroup. */
       
  2005 	{
       
  2006 	return KUidContactGroup;
       
  2007 	}
       
  2008 
       
  2009 EXPORT_C CContactIdArray* CContactGroup::ItemsContainedLC() const
       
  2010 /** Returns a pointer to a copy of the group's list of members.
       
  2011 
       
  2012 @return Pointer to a copy of the group's list of members. This is left on 
       
  2013 the cleanup stack. */
       
  2014 	{
       
  2015 	if (iItems)
       
  2016 		{
       
  2017 		CContactIdArray* copy = CContactIdArray::NewLC(iItems);
       
  2018 		return copy;
       
  2019 		}
       
  2020 	else
       
  2021 		{
       
  2022 		// iItems is NULL
       
  2023 		CleanupStack::PushL(iItems);
       
  2024 		return NULL;
       
  2025 		}
       
  2026 	}
       
  2027 
       
  2028 EXPORT_C const CContactIdArray* CContactGroup::ItemsContained() const
       
  2029 /** Returns a constant pointer to the group's list of members.
       
  2030 
       
  2031 @return Pointer to the group's list of members. */
       
  2032 	{
       
  2033 	return iItems;
       
  2034 	}
       
  2035 
       
  2036 EXPORT_C TBool CContactGroup::IsSystem() const
       
  2037 /** Tests the value of the group's system attribute. 
       
  2038 
       
  2039 The system attribute is not currently used in the Contacts Model API.
       
  2040 
       
  2041 @return ETrue if system, EFalse if not. */
       
  2042 	{
       
  2043 	return iAttributes&ESystem;
       
  2044 	}
       
  2045 
       
  2046 EXPORT_C void CContactGroup::SetSystem(TBool aSystem)
       
  2047 /** Sets the value of the group's system attribute. 
       
  2048 
       
  2049 The system attribute is not currently used in the Contacts Model API.
       
  2050 
       
  2051 @param aSystem ETrue to set the system attribute, EFalse to unset it. */
       
  2052 	{
       
  2053 	if (aSystem)
       
  2054 		iAttributes|=ESystem;
       
  2055 	else
       
  2056 		iAttributes&=~ESystem;
       
  2057 	}
       
  2058 
       
  2059 EXPORT_C TBool CContactGroup::ContainsItem(TContactItemId aContactId)
       
  2060 /** Tests whether a contact item is a member of the group.
       
  2061 
       
  2062 @param aContactId The ID of the contact item to test.
       
  2063 @return ETrue if the item is a member of the group, EFalse if not. */
       
  2064 	{
       
  2065 	if (iItems && iItems->Count())
       
  2066 		{
       
  2067 		TInt index=iItems->Find(aContactId);
       
  2068 		if (index==KErrNotFound)
       
  2069 			return EFalse;
       
  2070 		}
       
  2071 	else
       
  2072 		return EFalse;
       
  2073 	return ETrue;
       
  2074 	}
       
  2075 
       
  2076 EXPORT_C void CContactGroup::SetGroupLabelL(const TDesC& aLabel)
       
  2077 /** Sets the group label, replacing any existing one.
       
  2078 
       
  2079 @param aLabel The new group label.
       
  2080 @leave KErrNotFound The group has no label field (of type KUidContactFieldTemplateLabel). */
       
  2081 	{
       
  2082 	CContactItemFieldSet& labelFields = this->CardFields();
       
  2083 	// find label field
       
  2084 	TInt pos = labelFields.Find(KUidContactFieldTemplateLabel);
       
  2085 	if (pos==KErrNotFound)
       
  2086 		User::Leave(pos);
       
  2087 	labelFields[pos].TextStorage()->SetTextL(aLabel);
       
  2088 	}		
       
  2089 
       
  2090 EXPORT_C TPtrC CContactGroup::GetGroupLabelL()
       
  2091 /** Gets the group label.
       
  2092 
       
  2093 @leave KErrNotFound The group has no label field (of type KUidContactFieldTemplateLabel).
       
  2094 
       
  2095 @return The new group label. */
       
  2096 	{
       
  2097 	CContactItemFieldSet& labelFields = this->CardFields();
       
  2098 	// find 
       
  2099 	TInt pos = labelFields.Find(KUidContactFieldTemplateLabel);
       
  2100 	if (pos==KErrNotFound)
       
  2101 		User::Leave(pos);
       
  2102 	return(labelFields[pos].TextStorage()->Text());
       
  2103 	}
       
  2104 
       
  2105 EXPORT_C TBool CContactGroup::HasItemLabelField()
       
  2106 /** Tests whether the group has a label field (of type KUidContactFieldTemplateLabel).
       
  2107 
       
  2108 @return ETrue if the group has a label field. EFalse if not. */
       
  2109 	{
       
  2110 	CContactItemFieldSet& labelFields = this->CardFields();
       
  2111 	TInt pos = labelFields.Find(KUidContactFieldTemplateLabel);
       
  2112 	if (pos==KErrNotFound)
       
  2113 		return EFalse;
       
  2114 	return ETrue;
       
  2115 	}
       
  2116 
       
  2117 EXPORT_C CContactIdArray* CContactGroup::GroupsJoinedLC()const
       
  2118 /** Returns a pointer to a list of contact groups to which the current group belongs 
       
  2119 (a contact group can belong to other groups).
       
  2120 
       
  2121 @return A pointer to a copy of the array of groups IDs to which this group 
       
  2122 belongs. This array is empty if the group is not a member of any other groups. 
       
  2123 The caller takes ownership of this object, so is responsible for its deletion. */
       
  2124 	{
       
  2125 	return(CContactItemPlusGroup::GroupsJoinedLC());
       
  2126 	}
       
  2127 
       
  2128 
       
  2129 /**
       
  2130 Adds a contact with the given Id to the group. This method doesn't make any changes to the database.
       
  2131 The change should be persisted by means of CContactDatabase::CommitContactL() API.
       
  2132 
       
  2133 @param aContactId The Id of the contact being added to the group.
       
  2134 @leave KErrAlreadyExists The contact is already a member of this group.
       
  2135 
       
  2136 @internalTechnology
       
  2137 */
       
  2138 EXPORT_C void CContactGroup::AddContactL(TContactItemId aContactId)
       
  2139 	{
       
  2140 	if (!iItems)
       
  2141 		{
       
  2142 		iItems = CContactIdArray::NewL(); //No need to push on the stack because it is a member
       
  2143 		}
       
  2144 	if (iItems->Find(aContactId) == KErrNotFound)
       
  2145 		{
       
  2146 		iItems->AddL(aContactId);
       
  2147 		}
       
  2148 	else
       
  2149 		{
       
  2150 		User::Leave(KErrAlreadyExists);
       
  2151 		}
       
  2152 	}
       
  2153 
       
  2154 /**
       
  2155 Removes a contact with the given Id from the group. This method doesn't make any changes to the database.
       
  2156 The change should be persisted by means of CContactDatabase::CommitContactL() API.
       
  2157 
       
  2158 @param aContactId The Id of the contact being removed from the group.
       
  2159 @leave KErrNotFound The contact is not a member of this group.
       
  2160 
       
  2161 @internalTechnology
       
  2162 */
       
  2163 EXPORT_C void CContactGroup::RemoveContactL(TContactItemId aContactId)
       
  2164 	{
       
  2165 	TInt arrIndex(0);
       
  2166 	if (!iItems || KErrNotFound == (arrIndex = iItems->Find(aContactId)))
       
  2167 		{ //If array is empty of the contact ID is not found
       
  2168 		User::Leave(KErrNotFound);
       
  2169 		}
       
  2170 	iItems->Remove(arrIndex);
       
  2171 	}
       
  2172 
       
  2173 void CContactGroup::InternalizeL(RReadStream& aStream)
       
  2174 /** Internalises a CContactGroup object from a read stream. 
       
  2175 @param aStream Stream from which the object should be internalised. */
       
  2176 	{
       
  2177 	// Call Parent InternalizeL to internalize all members.
       
  2178 	CContactItemPlusGroup::InternalizeL(aStream);
       
  2179 		
       
  2180 	if (iItems)
       
  2181 		{
       
  2182 		delete iItems;
       
  2183 		iItems = NULL;		
       
  2184 		}
       
  2185 
       
  2186 	const TBool iItemsExists=aStream.ReadInt32L();
       
  2187 	if (iItemsExists)
       
  2188 		{
       
  2189 		iItems = CContactIdArray::NewL();
       
  2190 		iItems->InternalizeL(aStream);		
       
  2191 		}	
       
  2192 						
       
  2193 	}
       
  2194 
       
  2195 void CContactGroup::ExternalizeL(RWriteStream& aStream) const 
       
  2196 /** Externalises a CContactGroup object to a write stream.
       
  2197 @param aStream Stream to which the object should be externalised. */
       
  2198 	{
       
  2199 	// Call Parent ExternalizeL to externalize all members.
       
  2200 	CContactItemPlusGroup::ExternalizeL(aStream);
       
  2201 
       
  2202 	if(iItems)
       
  2203 		{
       
  2204 		aStream.WriteInt32L(1);
       
  2205 		iItems->ExternalizeL(aStream);
       
  2206 		}
       
  2207 		
       
  2208 	else
       
  2209 		{
       
  2210 		aStream.WriteInt32L(0);
       
  2211 		}	
       
  2212 	}	
       
  2213 	
       
  2214 /**
       
  2215 Resets items.
       
  2216 
       
  2217 @internalTechnology
       
  2218 @released
       
  2219 */	
       
  2220 EXPORT_C void CContactGroup::ResetItems()
       
  2221 	{
       
  2222 	delete iItems;
       
  2223 	iItems = NULL;	
       
  2224 	}
       
  2225 	
       
  2226 /**
       
  2227 Sets groups.
       
  2228 
       
  2229 @internalTechnology
       
  2230 @released
       
  2231 */		
       
  2232 EXPORT_C void CContactGroup::SetItems(CContactIdArray* aItems)
       
  2233 	{
       
  2234 	iItems = aItems;		
       
  2235 	}
       
  2236 	
       
  2237 //
       
  2238 // class CContactTemplate
       
  2239 //
       
  2240 
       
  2241 EXPORT_C CContactTemplate* CContactTemplate::NewL()
       
  2242 /** Allocates and constructs a new default system template.
       
  2243 
       
  2244 @return Pointer to the newly created system template. */
       
  2245 	{ // static
       
  2246 	CContactTemplate* item=CContactTemplate::NewLC();
       
  2247 	CleanupStack::Pop(); // item
       
  2248 	return item;
       
  2249 	}
       
  2250 
       
  2251 EXPORT_C CContactTemplate* CContactTemplate::NewLC()
       
  2252 /** Allocates and constructs a new default system template.
       
  2253 
       
  2254 @return Pointer to the newly created system template. This is left on the cleanup stack.*/
       
  2255 	{ // static
       
  2256 	CContactTemplate* item=new(ELeave) CContactTemplate;
       
  2257 	CleanupStack::PushL(item);
       
  2258 	item->ConstructL();
       
  2259 	return item;
       
  2260 	}
       
  2261 
       
  2262 EXPORT_C CContactTemplate* CContactTemplate::NewL(const CContactItem *aTemplate)
       
  2263 /** Allocates and constructs a new system template seeded from another one.
       
  2264 
       
  2265 @param aTemplate The contact template to copy.
       
  2266 @return Pointer to the newly created system template. */
       
  2267 	{
       
  2268 	CContactTemplate* item=CContactTemplate::NewLC(aTemplate);
       
  2269 	CleanupStack::Pop(); // item
       
  2270 	return item;
       
  2271 	}
       
  2272 
       
  2273 EXPORT_C CContactTemplate* CContactTemplate::NewLC(const CContactItem *aTemplate)
       
  2274 /** Allocates and constructs a new system template seeded from another one.
       
  2275 
       
  2276 @param aTemplate The contact template to copy.
       
  2277 @return Pointer to the newly created system template. This is left on the cleanup stack.*/
       
  2278 	{
       
  2279 	CContactTemplate* item=new(ELeave) CContactTemplate;
       
  2280 	CleanupStack::PushL(item);
       
  2281 	item->ConstructL(aTemplate);
       
  2282 	return item;
       
  2283 	}
       
  2284 
       
  2285 EXPORT_C TUid CContactTemplate::Type() const
       
  2286 /** Implements CContactItem::Type(). 
       
  2287 
       
  2288 @return KUidContactTemplate. */
       
  2289 	{
       
  2290 	return KUidContactTemplate;
       
  2291 	}
       
  2292 
       
  2293 CContactTemplate::CContactTemplate()
       
  2294 	{
       
  2295 	}
       
  2296 
       
  2297 
       
  2298 EXPORT_C CContactICCEntry::~CContactICCEntry()
       
  2299 /** Empty destructor. */
       
  2300 	{
       
  2301 	}
       
  2302 
       
  2303 
       
  2304 /** Allocates and constructs a new ICC entry.
       
  2305 
       
  2306 @param The contact template to use.
       
  2307 @return Pointer to newly created CContactICCEntry.  
       
  2308 @publishedAll
       
  2309 @released
       
  2310 */
       
  2311 EXPORT_C CContactICCEntry* CContactICCEntry::NewL(const CContactItem& aTemplate)
       
  2312 	{
       
  2313 	CContactICCEntry* entry = new (ELeave) CContactICCEntry();
       
  2314 	CleanupStack::PushL(entry);
       
  2315 	entry->ConstructL(&aTemplate);
       
  2316 	CleanupStack::Pop(entry);
       
  2317 	return entry;
       
  2318 	}
       
  2319 
       
  2320 /*
       
  2321  * Allocates and constructs a new ICC entry.
       
  2322  * Not exported - only used by CNTMODEL code.
       
  2323  * 
       
  2324  * @return Pointer to newly created CContactEntry
       
  2325  * @since 7.0
       
  2326  */
       
  2327 CContactICCEntry* CContactICCEntry::NewL()
       
  2328 	{
       
  2329 	CContactICCEntry* entry = new (ELeave) CContactICCEntry();
       
  2330 	CleanupStack::PushL(entry);
       
  2331 	entry->ConstructL();
       
  2332 	CleanupStack::Pop(entry);
       
  2333 	return entry;
       
  2334 	}
       
  2335 
       
  2336 TUid CContactICCEntry::Type() const
       
  2337 /** Implements CContactItem::Type().
       
  2338 
       
  2339 @return KUidContactICCEntry. */
       
  2340 	{
       
  2341 	return KUidContactICCEntry;
       
  2342 	}
       
  2343 
       
  2344 CContactICCEntry::CContactICCEntry()
       
  2345 	{
       
  2346 	}
       
  2347 
       
  2348 
       
  2349 EXPORT_C TContactItemId ContactGuid::IsLocalContactUidString(const TDesC& aString, TInt64 aMachineUniqueId)
       
  2350 /** Tests whether a contact item was created in the database with the unique ID 
       
  2351 specified. If so, the item's contact item ID is returned. If not, returns 
       
  2352 KErrNotFound.
       
  2353 
       
  2354 @param aString The contact item's UID string. Use CContactItem::UidStringL() 
       
  2355 to get a pointer to the item's UID string.
       
  2356 @param aMachineUniqueId The database's unique ID. This can be found by calling 
       
  2357 CContactDatabase::MachineId().
       
  2358 @return KErrNotFound if the database ID specified is not found in the UID string. 
       
  2359 Otherwise, the contact item's contact item ID. */
       
  2360 	{ // static
       
  2361 	TLex lex(aString);
       
  2362 	TInt ii=0;
       
  2363 	TChar c;
       
  2364 	TInt64 pos=KErrNotFound;
       
  2365 	// check machine id
       
  2366 	c=lex.Peek();
       
  2367 	if (c==KUidStringSeparator)
       
  2368 		;
       
  2369 	else
       
  2370 		{
       
  2371 		lex.Val(pos,EHex);
       
  2372 		if ((TInt64)pos!=aMachineUniqueId)
       
  2373 			return (KErrNotFound);
       
  2374 		}
       
  2375 	for(;;)
       
  2376 		{
       
  2377 		c=lex.Get();
       
  2378 		if (c)
       
  2379 			{
       
  2380 			if (c==KUidStringSeparator)
       
  2381 				{
       
  2382 				ii++;
       
  2383 				}
       
  2384 			else
       
  2385 				{
       
  2386 				if (ii==2) // extract the field id
       
  2387 					{
       
  2388 					lex.UnGet();
       
  2389 					lex.Val(pos);
       
  2390 					break;
       
  2391 					}
       
  2392 				}
       
  2393 			}
       
  2394 		else //EOS
       
  2395 			break;
       
  2396 		}
       
  2397 	return I64INT(pos);
       
  2398 	}
       
  2399 
       
  2400 /** 
       
  2401 @internalTechnology 
       
  2402  */
       
  2403 EXPORT_C TBool ContactGuid::GetCreationDate(TDes& aString, TInt64 aMachineUniqueId)
       
  2404 	{ // static
       
  2405 	if (ContactGuid::IsLocalContactUidString(aString,aMachineUniqueId)>=0)
       
  2406 		{
       
  2407 		const TInt startPos=aString.Locate(TChar(KUidStringSeparator));
       
  2408 		if (startPos!=KErrNotFound)
       
  2409 			{
       
  2410 			TInt endPos=aString.Length();
       
  2411 			while (--endPos>startPos)
       
  2412 				{
       
  2413 				if (aString[endPos]==KUidStringSeparator)
       
  2414 					{
       
  2415 					aString=aString.Left(endPos);
       
  2416 					aString=aString.Right(aString.Length()-startPos-1);
       
  2417 					return ETrue;
       
  2418 					}
       
  2419 				}
       
  2420 			}
       
  2421 		}
       
  2422 	return EFalse;
       
  2423 	}
       
  2424 
       
  2425 HBufC* ContactGuid::CreateGuidLC(const TDesC& aCreationDate,TContactItemId aId, TInt64 aMachineUniqueId)
       
  2426 	{ // static
       
  2427 	HBufC* guid=HBufC::NewLC(KUidStringLength);
       
  2428 	TPtr ptr=guid->Des();
       
  2429 	ptr.AppendFormat(_L("%08x"),I64HIGH(aMachineUniqueId));
       
  2430 	ptr.AppendFormat(_L("%08x"),I64LOW(aMachineUniqueId));
       
  2431 	ptr.Append(KUidStringSeparator);
       
  2432 	ptr.Append(aCreationDate);
       
  2433 	ptr.Append(KUidStringSeparator);
       
  2434 	TBuf<20> localId;
       
  2435 	localId.Num((TInt)aId);
       
  2436 	ptr.Append(localId);
       
  2437 	return guid;
       
  2438 	}
       
  2439 
       
  2440 HBufC* ContactGuid::CreateGuidLC(const TTime& aCreationDate,TContactItemId aId, TInt64 aMachineUniqueId)
       
  2441 	{ // static
       
  2442 	TBuf<32> time;
       
  2443 	TInt64 num=aCreationDate.Int64();
       
  2444 	time.AppendFormat(_L("%08x"),(TInt32)I64HIGH(num));
       
  2445 	time.AppendFormat(_L("%08x"),(TInt32)I64LOW(num));
       
  2446 	return ContactGuid::CreateGuidLC(time,aId,aMachineUniqueId);
       
  2447 	}
       
  2448 
       
  2449 HBufC* ContactGuid::CreateGuidLC(TContactItemId aId, TInt64 aMachineUniqueId)
       
  2450 	{ // static
       
  2451 	TTime time;
       
  2452 	time.UniversalTime();
       
  2453 	return ContactGuid::CreateGuidLC(time,aId,aMachineUniqueId);
       
  2454 	}