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