phonebookengines/contactsmodel/src/CNTFIELD.CPP
changeset 0 e686773b3f54
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/contactsmodel/src/CNTFIELD.CPP	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,1967 @@
+// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <s32std.h>
+
+#include "CNTSTD.H"
+#include <cntdef.h>
+#include <cntfield.h>
+#include <cntfldst.h>
+
+#include <cntitem.h>
+#include <versit.h>
+#include "CNTPROF.H"
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include "cntfieldheader.h"
+#include "cnthint.h"
+#include "cntfield_internal.h"
+#endif
+
+//
+// class TContactFieldAtts
+//
+const TUint32 KAttribsMask		    = 0xf0000fff;
+const TUint32 KExtendedAttribsMask	= 0x000ff000;
+const TUint32 KStorageTypeMask	    = 0x00f00000;
+
+const TUint32 KTypeBitShift		    = 20;
+const TUint32 KExtendedAttsBitShift = 12;
+
+/** Set contact field attributes.
+
+@param aAttribs contact field arributes to be set.
+@internalTechnology
+*/
+void TContactFieldAtts::SetAttribs(TUint32 aAttribs)
+	{
+	iStorage |= aAttribs;
+	}
+	
+/** Set contact field extended arributes.
+
+@param aExtendedAttribs contact field extended arributes to be set.
+@internalTechnology
+*/
+void TContactFieldAtts::SetExtendedAttribs(TUint32 aExtendedAttribs)
+	{
+	iStorage |= aExtendedAttribs << KExtendedAttsBitShift;
+	}
+
+/** Set storage type.
+
+@param aType storage type to set.
+@internalTechnology
+*/
+void TContactFieldAtts::SetType(TStorageType aType)
+	{
+	iStorage |= aType << KTypeBitShift;
+	}
+
+/** Get contact field arributes.
+
+@return contact field arributes.
+@internalTechnology
+*/
+TUint32 TContactFieldAtts::Attribs() const
+	{
+	return (iStorage & KAttribsMask);
+	}
+	
+/** Get contact field extended arributes.
+
+@return contact field extended arributes.
+@internalTechnology
+*/
+TUint32 TContactFieldAtts::ExtendedAttribs() const
+	{
+	return (iStorage & KExtendedAttribsMask) >> KExtendedAttsBitShift;
+	}
+	
+/** Get contact field storage type.
+
+@return contact field storage type.
+@internalTechnology
+*/
+TStorageType TContactFieldAtts::Type() const
+	{
+	return (iStorage & KStorageTypeMask) >> KTypeBitShift;
+	}
+	
+/** Internalize implementation.
+
+@internalTechnology
+*/
+void TContactFieldAtts::InternalizeL(RReadStream& aStream)
+	{
+	iStorage=aStream.ReadUint32L();
+	}
+	
+/** Externalize implementation.
+
+@internalTechnology
+*/
+void TContactFieldAtts::ExternalizeL(RWriteStream& aStream) const
+	{
+	aStream.WriteUint32L(iStorage);
+	}
+
+
+//
+// class CContentType
+//
+   
+EXPORT_C CContentType::~CContentType()
+/** Frees all resources owned by the content type object, prior 
+to its destruction. */
+    {
+	delete iFieldTypes;
+	}
+      
+CContentType::CContentType()
+    {
+	}
+      
+CContentType::CContentType(TUid aMapping) : iMapping(aMapping)
+	{
+	}
+	
+/** Constructs a new content type based on a RReadStream.
+
+@param aStream RReadStream containing object to internalize.
+@return Pointer to the newly created CContentType. This is left on the cleanup stack. 
+@internalTechnology
+*/
+CContentType* CContentType::NewLC(RReadStream& aStream)
+	{ // static
+	CContentType* type = NewL();
+	CleanupStack::PushL(type);
+	type->InternalizeL(aStream);
+	
+	return type;
+	}		
+
+EXPORT_C CContentType* CContentType::NewL()
+/** Allocates and constructs a new default CContentType.
+
+The object has no field types and the mapping is set to KNullUid
+
+@return Pointer to the newly created content type object. */
+	{
+	CContentType* self=new(ELeave) CContentType(KNullUid);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop();	// self
+	return(self);
+	}
+
+EXPORT_C CContentType* CContentType::NewL(TFieldType aFieldType,TUid aMapping)
+/** Allocates and constructs a new CContentType with a single field 
+type and a mapping.
+
+@param aFieldType The field type to add to the content type.
+@param aMapping The mapping.
+@return Pointer to the newly created content type object. */
+	{
+	CContentType* self=new(ELeave) CContentType(aMapping);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	self->AddFieldTypeL(aFieldType);
+	CleanupStack::Pop();	// self
+	return(self);
+	}
+
+EXPORT_C CContentType* CContentType::NewL(const CContentType &aContentType)
+/** Allocates and constructs a new CContentType based on another one.
+
+@param aContentType The CContentType on which to base the new one.
+@return Pointer to the newly created content type object. */
+	{ // static
+	CContentType* self=new(ELeave) CContentType;
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	self->CloneL(aContentType);
+	CleanupStack::Pop();	// self
+	return self;
+	}
+ 
+void CContentType::ConstructL()
+	{
+	iFieldTypes=new(ELeave) CArrayFixFlat<TUid>(2);
+	}
+
+EXPORT_C void CContentType::AddFieldTypeL(TFieldType aFieldType)
+/** Appends a field type to the content type's list of field types.
+
+Note that certain combinations of field types are not valid and should not be
+used.
+
+@param aFieldType The field type to append to the list of field types. */
+	{
+	const TInt KMaxFieldTypes=15;
+	if (iFieldTypes->Count()==KMaxFieldTypes)
+		{
+		User::Leave(KErrOverflow);
+		}
+    		
+   	iFieldTypes->AppendL(aFieldType);
+	}
+
+EXPORT_C void CContentType::RemoveFieldType(TFieldType aFieldType)
+/** Removes a field type from the list of field types.
+
+@param aFieldType The field type to remove from the list of field types. */
+	{
+	for(TInt loop=0;loop<iFieldTypes->Count();loop++)
+		if ((*iFieldTypes)[loop]==aFieldType)
+			{
+			iFieldTypes->Delete(loop);
+			break;
+			}
+	}
+
+EXPORT_C void CContentType::SetMapping(TUid aMapping)
+/** Sets the vCard mapping.
+
+@param aMapping The new vCard mapping for the content type. */
+	{
+	iMapping=aMapping;
+	}
+
+void CContentType::CloneL(const CContentType &aContentType)
+	{
+    iMapping=aContentType.iMapping;
+	if (aContentType.iFieldTypes)
+		for(TInt loop=0;loop<aContentType.iFieldTypes->Count();loop++)
+			AddFieldTypeL((*aContentType.iFieldTypes)[loop]);
+	}
+
+EXPORT_C TInt CContentType::FieldTypeCount() const
+/** Gets the number of field types in the content type's list of field types.
+
+@return The number of field types in the content type. */
+	{
+	return(iFieldTypes->Count());
+	}
+
+EXPORT_C TFieldType CContentType::FieldType(TInt aIndex) const
+/** Gets the indexed field type.
+
+@param aIndex Index into the list of field types. The position is relative 
+to zero; i.e. zero implies the first element in the array. This value must 
+be non-negative and less than the number of objects currently within the array 
+otherwise the operator raises a panic.
+@return The indexed field type. */
+	{
+	__ASSERT_DEBUG(aIndex<iFieldTypes->Count(),Panic(ECntPanicFieldTypeIndex));
+	return((*iFieldTypes)[aIndex]);
+	}
+
+EXPORT_C TUid CContentType::Mapping() const
+/** Gets the vCard mapping.
+
+@return The vCard mapping. */
+	{
+	return(iMapping);
+	}
+
+EXPORT_C TBool CContentType::ContainsFieldType(TFieldType aFieldType) const
+/** Tests whether the content type object contains the specified field type UID 
+either as the mapping value or in its list of field types.
+
+@param aFieldType The field type of interest.
+@return ETrue if the CContentType contains the specified field type. EFalse 
+if not. */
+	{
+	if (iMapping==aFieldType)
+		return(ETrue);
+	for(TInt loop=0;loop<iFieldTypes->Count();loop++)
+		if ((*iFieldTypes)[loop]==aFieldType)
+			return(ETrue);
+	return(EFalse);
+	}
+
+void CContentType::InternalizeAdditionalUidsL(TInt aCount,RReadStream& aStream)
+	{
+	for (TInt ii=0;ii<aCount;ii++) 
+		iFieldTypes->AppendL(TUid::Uid(aStream.ReadInt32L()));
+	}
+
+EXPORT_C TBool CContentType::SupportsMultipleLines() const
+/** Tests whether the content type supports multiple lines of text. If the content 
+type object contains a field type which supports this, either in its list 
+of field types, or as its mapping, the function returns ETrue. Examples of 
+such field types are address fields (type KUidContactFieldAddress) and note 
+fields (type KUidContactFieldNote).
+
+@return ETrue if the CContentType supports multiple lines of text. EFalse 
+if not. */
+	{
+	return(ContainsFieldType(KUidContactFieldAddress) || ContainsFieldType(KUidContactFieldNote));
+	}
+
+EXPORT_C TBool CContentType::operator==(const CContentType &aType) const
+/** Compares two content type objects for equality. 
+Two content type objects are equal according to this method if all following 
+conditions are met:
+- vCard property mapping matches
+- same number of field types
+- main field type matches
+- additional field types and vCard property parameter mappings match
+ 
+@param aType The content type to compare with this CContentType.
++@return ETrue if aType is equal with current content type. */
+	{
+	// Compare vCard property mapping.
+	if (Mapping() != aType.Mapping())
+		{
+		return EFalse;
+		}
+	
+	// Compare field type counts.
+	const TInt typeCount = FieldTypeCount();
+	if (typeCount != aType.FieldTypeCount())
+		{
+		return EFalse;
+		}
+	if (typeCount <= 0)
+		{
+		// Nothing more to compare.
+		return ETrue;
+		}
+	
+	// Compare main field type.
+	if (FieldType(0) != aType.FieldType(0))
+		{
+		return EFalse;
+		}
+	
+	// Compare additional field types and vCard property parameter mappings.
+	for (TInt lhsIndex = 1; lhsIndex < typeCount; ++lhsIndex)
+		{
+		TInt rhsIndex = 1;
+		for (rhsIndex = 1; rhsIndex < typeCount; ++rhsIndex)
+			{
+			if (FieldType(lhsIndex) == aType.FieldType(rhsIndex))
+			    break;
+			}
+		if (rhsIndex == typeCount)
+			{
+			// No match found.
+			return EFalse;
+			}
+		}
+	
+	return ETrue;
+	}
+
+EXPORT_C TBool CContentType::IsEqual(const CContentType &aType) const
+/** Compares two content type objects for equality.
+Two content type objects are equal according to this method if all following 
+conditions are met:
+- vCard property mapping matches
+- same number of field types
+- main field type matches
+- additional field types and vCard property parameter mappings match
+ 
+@param aType The content type to compare with this CContentType.
+@return ETrue if aType is equal with current content type. */
+	{
+	// Compare vCard property mapping.
+	if (iMapping!=aType.iMapping)
+		{
+		return(EFalse);	
+		}
+	
+	// Compare field type counts.
+	const TInt typeCount = aType.FieldTypeCount();
+	if (FieldTypeCount()!= typeCount)
+		{
+		return(EFalse);	
+		}
+		
+    if (typeCount <= 0)
+        {
+        // Nothing more to compare.
+        return ETrue;
+        }
+			
+    // Compare main field type.
+    if (FieldType(0) != aType.FieldType(0))
+        {
+        return EFalse;
+        }
+
+    // Compare additional field types and vCard property parameter mappings.
+    for (TInt leftIndex = 1; leftIndex < typeCount; ++leftIndex)
+        {
+        TUint rightIndex = 1;
+        for (rightIndex = 1; rightIndex < typeCount; ++rightIndex)
+            {
+            if (FieldType(leftIndex) == aType.FieldType(rightIndex))
+                break;
+            }
+        if (rightIndex == typeCount)
+            {
+            // No match found.
+            return EFalse;
+            }
+        }
+
+    return ETrue;
+   	}
+  	
+void CContentType::Reset()
+	{
+	iMapping=TUid::Uid(0);
+	iFieldTypes->Reset();
+	}
+
+
+/*
+ * Determine if content types are suitable to match for synchronization purpose. 
+ * Some properties are subject to specific processing depending of the <code>CContentType</code> Mapping. 
+ * Notably: VOICE, PREF, VoiceDial and SpeedDial. 
+ * VOICE is a a default property parameter for all TEL properties.
+ *
+ * @param		"const CContentType& aType"
+ *				The content type to compare with this
+ *				<code>CContentType</code>. Beware, to do a proper comparison,
+ *				the <code>aType</code> parameter must not contains VoiceDial or SpeedDial properties.
+ *				Otherwise the fields will not match.				  
+ *
+ * @return 		"TBool"
+ *				<code>ETrue</code> if <code>aType</code> match this content type.
+ *				Field types do not need to be in the same order in the 
+ *				list of field types for a match to be made.
+ */
+EXPORT_C TBool CContentType::IsEqualForSyncUpdate(const CContentType& aType) const
+/** Tests whether the content types are suitable to match for synchronisation purpose. 
+
+@param aType The content type to compare with this CContentType.
+@return ETrue if aType is an identical content type
+ */
+	{
+	if (iMapping!=aType.iMapping)
+		return(EFalse);	
+
+	switch (iMapping.iUid)
+		{
+	case KIntContactFieldVCardMapTEL:
+		{
+		TInt countModifier=0;
+		TInt loop=0;
+
+		if (aType.ContainsFieldType(KUidContactFieldVCardMapVOICE))
+			{
+			++countModifier;
+			}
+
+		if (aType.ContainsFieldType(KUidContactFieldVCardMapPREF))
+			{
+			++countModifier;
+			}
+		
+		if (ContainsFieldType(KUidContactFieldVCardMapVOICE))
+			{
+			--countModifier;
+			}
+
+		if (ContainsFieldType(KUidContactFieldVCardMapPREF))
+			{
+			--countModifier;
+			}
+
+		if (ContainsFieldType(KUidContactsVoiceDialField))
+			{
+			--countModifier;
+			}
+
+		//look for speed dial property only in db field
+		for(loop=0;loop<iFieldTypes->Count();loop++)
+			{
+			TInt uid = (*iFieldTypes)[loop].iUid;
+			if (uid >= KUidSpeedDialOneValue && uid <= KUidSpeedDialNineValue)
+				{
+				--countModifier;
+				break; //only one speed dial property allowed for a field
+				}
+			}
+	
+		//now check for field count	
+		if ((FieldTypeCount()+countModifier)!=aType.FieldTypeCount())
+			{
+			return(EFalse);
+			}
+				
+		//Check that all type from the imported field match a type in this field but VOICE and PREF
+		for(loop=0;loop<aType.FieldTypeCount();loop++)
+			{
+			if (!ContainsFieldType(aType.FieldType(loop)))
+				{
+				if (aType.FieldType(loop).iUid==KIntContactFieldVCardMapVOICE || aType.FieldType(loop).iUid==KIntContactFieldVCardMapPREF)
+					{
+					continue;
+					}
+				return(EFalse);
+				}
+			}
+		return(ETrue);
+		}
+
+	case KIntContactFieldVCardMapEMAILINTERNET:
+		{
+		TInt countModifier=0;		
+
+		if (aType.ContainsFieldType(KUidContactFieldVCardMapPREF))
+			{
+			++countModifier;
+			}
+		
+		if (ContainsFieldType(KUidContactFieldVCardMapPREF))
+			{
+			--countModifier;
+			}
+	
+		//now check for field count	
+		if ((FieldTypeCount()+countModifier)!=aType.FieldTypeCount())
+			{
+			return(EFalse);
+			}
+				
+		//Check that all type from the imported field match a type in this field but PREF
+		for(TInt loop=0;loop<aType.FieldTypeCount();loop++)
+			{
+			if (!ContainsFieldType(aType.FieldType(loop)))
+				{
+				if (aType.FieldType(loop).iUid==KIntContactFieldVCardMapPREF)
+					{
+					continue;
+					}
+				return(EFalse);
+				}
+			}
+		return(ETrue);
+		}
+	
+	case KIntContactFieldVCardMapAGENT:
+		{
+		return(ETrue);
+		}	
+
+	default:
+		return *this==aType;
+		}
+	}
+	
+void CContentType::InternalizeL(RReadStream& aStream)
+/** Internalises a CContentType object from a read stream. 
+@param aStream Stream from which the object should be internalised. */
+	{
+    // TUid iMapping;
+	iMapping.iUid = aStream.ReadInt32L();
+	
+	// CArrayFix<TUid>* iFieldTypes;
+	const TInt count=aStream.ReadInt32L();
+
+	// Allocated in constructor
+	TUid tempID;
+	for(TInt index=0; index<count; ++index)
+		{
+		
+		aStream>>tempID;		
+		iFieldTypes->AppendL(tempID);
+		}
+	}
+
+void CContentType::ExternalizeL(RWriteStream& aStream) const 
+/** Externalises a CContentType object to a write stream.
+@param aStream Stream to which the object should be externalised. */
+	{
+	aStream.WriteInt32L(iMapping.iUid);
+	
+	const TInt count = iFieldTypes->Count();
+	aStream.WriteInt32L(count);	
+	for(TInt index=0; index<count; ++index)
+		{
+		aStream<<iFieldTypes->At(index);
+		}
+	}		
+
+
+//
+// class CContactItemField
+//
+
+EXPORT_C CContactItemField* CContactItemField::NewLC()
+/** Allocates and constructs a new default contact item field. 
+
+The field's storage type, content type and label are unspecified. 
+The ESynchronize attribute is set.
+
+@return Pointer to the newly created contact item field. */
+	{
+    CContactItemField* self=new(ELeave) CContactItemField;
+    CleanupStack::PushL(self);
+	self->iContentType=CContentType::NewL();
+    return self;
+	}
+
+EXPORT_C CContactItemField* CContactItemField::NewL(TStorageType aType)
+/** Allocates and constructs a contact item field with a storage type. 
+
+The field's label and content type are unspecified.
+
+@param aType The field's storage type.
+@return Pointer to the newly created contact item field. */
+	{
+    CContactItemField* self=CContactItemField::NewLC(aType);
+    CleanupStack::Pop(); // self
+    return self;
+	}
+
+EXPORT_C CContactItemField* CContactItemField::NewLC(TStorageType aType)
+/** Allocates and constructs a contact item field with a storage type. 
+
+The field's label and content type are unspecified.
+
+@param aType The field's storage type.
+@return Pointer to the newly created contact item field. This is left on 
+the cleanup stack. */
+	{
+    CContactItemField* self=new(ELeave) CContactItemField(aType);
+    CleanupStack::PushL(self);
+    self->ConstructStorageL();
+	self->iContentType=CContentType::NewL();
+    return self;
+	}
+
+EXPORT_C CContactItemField* CContactItemField::NewL(TStorageType aType, TFieldType aFieldType)
+/** Allocates and constructs a contact item field with a storage type 
+and a field type.
+
+The field's content type is initialised with the field type, 
+and its vCard mapping is set by default to KNullUid. The field's label is 
+unspecified.
+
+@param aType The field's storage type.
+@param aFieldType The field type as defined in cntdef.h.
+@return Pointer to the newly created contact item field. */
+    { // static
+    CContactItemField* self=CContactItemField::NewLC(aType,aFieldType);
+    CleanupStack::Pop(); // self
+    return self;
+    }
+
+EXPORT_C CContactItemField* CContactItemField::NewLC(TStorageType aType, TFieldType aFieldType)
+/** Allocates and constructs a contact item field with a storage type 
+and a field type.
+
+The field's content type is initialised with the field type, 
+and its vCard mapping is set by default to KNullUid. The field's label is 
+unspecified.
+
+@param aType The field's storage type.
+@param aFieldType The field type as defined in cntdef.h.
+@return Pointer to the newly created contact item field. This is left on 
+the cleanup stack. */
+    { // static
+    CContactItemField* self=new(ELeave) CContactItemField(aType);
+    CleanupStack::PushL(self);
+    self->ConstructStorageL();
+	self->iContentType=CContentType::NewL(aFieldType);
+    return self;
+    }
+
+EXPORT_C CContactItemField* CContactItemField::NewL(const CContactItemField &aField)
+/** Allocates and constructs a contact item field based on another one.
+
+All details (content type, storage type, attributes and label) are copied 
+from the specified field.
+
+@param aField The contact field to copy.
+@return Pointer to the newly created contact item field. */
+	{ // static
+	CContactItemField* self=CContactItemField::NewLC(aField);
+	CleanupStack::Pop(); // self
+	return self;
+	}
+
+EXPORT_C CContactItemField* CContactItemField::NewLC(const CContactItemField &aField)
+/** Allocates and constructs a contact item field based on another one.
+
+All details (content type, storage type, attributes and label) are copied 
+from the specified field.
+
+@param aField The contact field to copy.
+@return Pointer to the newly created contact item field. This is left on 
+the cleanup stack. */
+	{ // static
+	CContactItemField* self=new(ELeave) CContactItemField(aField.StorageType());
+	CleanupStack::PushL(self);
+	self->ConstructStorageL();
+	self->CloneL(aField);
+	return self;
+	}
+ 
+EXPORT_C CContactItemField* CContactItemField::NewL(TStorageType aType, const CContentType &aContentType)
+/** Allocates and constructs a contact item field with a content type 
+and a storage type. 
+
+The field's label is unspecified.
+
+@param aType The field's storage type.
+@param aContentType The field's content type. 
+@return Pointer to the newly created contact item field. */
+	{ // static
+	CContactItemField* self=CContactItemField::NewLC(aType,aContentType);
+	CleanupStack::Pop(); // self
+	return self;
+	}
+
+EXPORT_C CContactItemField* CContactItemField::NewLC(TStorageType aType, const CContentType &aContentType)
+/** Allocates and constructs a contact item field with a content type 
+and a storage type. 
+
+The field's label is unspecified.
+
+@param aType The field's storage type.
+@param aContentType The field's content type. 
+@return Pointer to the newly created contact item field. This is left on 
+the cleanup stack. */
+	{ // static
+	CContactItemField* self=new(ELeave) CContactItemField(aType);
+	CleanupStack::PushL(self);
+	self->ConstructStorageL();
+	self->iContentType=CContentType::NewL(aContentType);
+	return self;
+	}
+ 
+CContactItemField::CContactItemField(TStorageType aType)
+	: iStorageType(aType), iAttributes(ESynchronize|EOverRidesLabel|ELabelUnspecified),iTemplateFieldId(KNullFieldId)
+    {}
+
+CContactItemField::CContactItemField()
+	: iAttributes(ESynchronize),iTemplateFieldId(KNullFieldId)
+    {}
+
+void CContactItemField::ConstructStorageL()
+    {
+	__ASSERT_DEBUG(iStorage==NULL,Panic(ECntPanicStorageAlreadyAllocated));
+    switch (iStorageType)
+        {
+    case KStorageTypeText:
+        iStorage=new(ELeave) CContactTextField;
+        break;
+    case KStorageTypeStore:
+        iStorage=new(ELeave) CContactStoreField;
+        break;
+    case KStorageTypeDateTime:
+        iStorage=new(ELeave) CContactDateField;
+        break;
+    case KStorageTypeContactItemId:
+        iStorage=new(ELeave) CContactAgentField;
+        break;
+    default:
+    	User::Leave(KErrNotSupported);
+    	break;
+        }
+    }
+
+void CContactItemField::CloneL(const CContactItemField &aField)
+	{
+	iContentType=CContentType::NewL(aField.ContentType());
+	if (aField.iLabel)
+		iLabel=aField.iLabel->AllocL();
+	iAttributes=aField.iAttributes;
+	// copy extended attributes as well
+	iExtendedAttributes=aField.iExtendedAttributes; 
+	iTemplateFieldId=aField.iTemplateFieldId;
+	CopyStorageL(aField);
+	}
+
+void CContactItemField::CopyStorageL(const CContactItemField &aField)
+	{
+	switch(aField.StorageType())
+		{
+		case KStorageTypeText:
+			TextStorage()->SetTextL(aField.TextStorage()->Text());
+			break;
+		case KStorageTypeDateTime:
+			DateTimeStorage()->SetTime(aField.DateTimeStorage()->Time());
+			break;
+		case KStorageTypeContactItemId:
+			AgentStorage()->SetAgentId(aField.AgentStorage()->Value());
+			break;
+		case KStorageTypeStore:
+			if (aField.StoreStorage()->Thing())
+				{
+				StoreStorage()->SetThingL(*aField.StoreStorage()->Thing());
+				}
+			break;
+		}
+	}
+
+EXPORT_C CContactItemField::~CContactItemField()
+/** Frees all resources owned by the field (the label, the stored 
+data and the content type), prior to its destruction. */
+    {
+    delete iLabel;
+    delete iStorage;
+	delete iContentType;
+    }
+
+/**
+@internalTechnology
+  */
+EXPORT_C void CContactItemField::Reset()
+	{
+    delete iLabel;
+	iLabel=NULL;
+    delete iStorage;
+	iStorage=NULL;
+	iContentType->Reset();
+	iStorageType=0;
+	iId=KNullFieldId	;
+	iAttributes=ESynchronize;
+	iExtendedAttributes=0;
+	iTemplateFieldId=KNullFieldId;
+	}
+
+void CContactItemField::MapHintsToFieldTypesL(THint aHint)
+	{
+	if (aHint.IsPhone())
+		AddFieldTypeL(KUidContactFieldPhoneNumber);
+	if (aHint.IsMsg())
+		AddFieldTypeL(KUidContactFieldMsg);
+	if (aHint.IsCompanyName())
+		AddFieldTypeL(KUidContactFieldCompanyName);
+	if (aHint.IsFamilyName())
+		AddFieldTypeL(KUidContactFieldFamilyName);
+	if (aHint.IsGivenName())
+		AddFieldTypeL(KUidContactFieldGivenName);
+	if (aHint.IsCompanyNamePronunciation())
+		AddFieldTypeL(KUidContactFieldCompanyNamePronunciation);
+	if (aHint.IsFamilyNamePronunciation())
+		AddFieldTypeL(KUidContactFieldFamilyNamePronunciation);
+	if (aHint.IsGivenNamePronunciation())
+		AddFieldTypeL(KUidContactFieldGivenNamePronunciation);
+	if (aHint.IsAddress())
+		AddFieldTypeL(KUidContactFieldAddress);
+	if (aHint.IsAdditionalName())
+		AddFieldTypeL(KUidContactFieldAdditionalName);
+	if (aHint.IsSuffixName())
+		AddFieldTypeL(KUidContactFieldSuffixName);
+	if (aHint.IsPrefixName())
+		AddFieldTypeL(KUidContactFieldPrefixName);
+	if (aHint.IsEmail())
+		AddFieldTypeL(KUidContactFieldEMail);
+	if (aHint.IsStorageInline())
+		AddFieldTypeL(KUidContactStorageInline);
+	}
+
+TBool CContactItemField::AddFieldToHint(TFieldType aFieldType, CContactItemField::THint &aHint) const 
+  	{
+	TBool matchedHint = ETrue;
+	switch(aFieldType.iUid)
+		{
+		case KUidContactFieldAddressValue:
+			aHint.SetIsAddress();
+			break;
+		case KUidContactFieldCompanyNameValue:
+			aHint.SetIsCompanyName();
+			break;
+		case KUidContactFieldPhoneNumberValue:
+			aHint.SetIsPhone();
+			break;
+		case KUidContactFieldGivenNameValue:
+			aHint.SetIsGivenName();
+			break;
+		case KUidContactFieldFamilyNameValue:
+			aHint.SetIsFamilyName();
+			break;
+		case KUidContactFieldCompanyNamePronunciationValue:
+			aHint.SetIsCompanyNamePronunciation();
+			break;
+		case KUidContactFieldGivenNamePronunciationValue:
+			aHint.SetIsGivenNamePronunciation();
+			break;
+		case KUidContactFieldFamilyNamePronunciationValue:
+			aHint.SetIsFamilyNamePronunciation();
+			break;
+		case KUidContactFieldAdditionalNameValue:
+			aHint.SetIsAdditionalName();
+			break;
+		case KUidContactFieldSuffixNameValue:
+			aHint.SetIsSuffixName();
+			break;
+		case KUidContactFieldPrefixNameValue:
+			aHint.SetIsPrefixName();
+			break;
+		case KUidContactFieldEMailValue:
+			aHint.SetIsEmail();
+			break;
+		case KUidContactFieldMsgValue:
+			aHint.SetIsMsg();
+			break;
+		case KUidContactFieldStorageInlineValue:
+			aHint.SetStorageIsInline();
+			break;
+		default:
+			matchedHint=EFalse;
+			break;
+		}
+	return(matchedHint);
+	}
+
+
+/**
+Encode contact field data into stream store.
+
+@param aTextStream the text blob stream to export text data.
+@param aBlobStore the binary blob stream to export binary data.
+@param aTextFieldIndex the index of text field stored in the storage
+
+@return field header which is to be stored into header blob. 
+@internalTechnology 
+*/
+TFieldHeader CContactItemField::StoreL(RWriteStream& aTextStream, CStreamStore& aBlobStore, TInt aTextFieldIndex)
+	{
+	TStreamId streamId = KNullStreamIdValue;
+	if (iStorageType == KStorageTypeText)
+		{
+		STATIC_CAST(CContactTextField*,iStorage)->ExternalizeL(aTextStream, ETrue, aTextFieldIndex);
+		}
+	else
+	    {
+		streamId = iStorage->StoreL(aBlobStore);
+	    }
+	
+	TContactFieldAtts atts;
+	/* sets all attributes of the field:- hidden private etc.. + type (text etc..)
+	   into TContactFieldAtts which is then stored ahead of the field data */
+	atts.SetAttribs(iAttributes);
+	atts.SetExtendedAttribs(iExtendedAttributes);
+	atts.SetType(iStorageType);
+    return TFieldHeader(atts, iId, streamId);
+	}
+
+
+/**
+Decode given blob header stream into contact field relevent data.
+
+@param aStream reference to the blob header stream to be decoded.
+@param aSystemTemplateFields cached template fields.
+
+@return the stream id of content data stored in data store 
+@internalTechnology 
+*/
+EXPORT_C TStreamId CContactItemField::RestoreFieldTypesL(RReadStream &aStream, const CContactItemFieldSet *aSystemTemplateFields)
+  	{
+	THint hint;
+	TStreamId nestedId(KNullStreamIdValue);
+	TContactFieldAtts fieldAtts;
+
+	aStream >> fieldAtts;
+	
+	iAttributes = fieldAtts.Attribs();
+	iExtendedAttributes = fieldAtts.ExtendedAttribs();
+	iStorageType = fieldAtts.Type();
+	
+    if(fieldAtts.Type() != KStorageTypeText)
+        {
+   	    //Only import stream id when the storage type is not text
+        aStream >> nestedId;
+        }
+        
+    iId = aStream.ReadUint32L();
+    iTemplateFieldId = aStream.ReadUint32L();
+    
+	const CContactItemField* templateField = NULL;
+	
+	if (UsesTemplateTypes() || !OverRidesLabel())
+		{
+		if (aSystemTemplateFields == NULL)
+		    {
+			User::Leave(KErrCorrupt);
+		    }
+		templateField = aSystemTemplateFields->FindById(iTemplateFieldId);
+		}
+		
+	if (templateField)
+		{
+		iAttributes |= (templateField->iAttributes&ETemplateMask);
+		}
+		
+	if (UsesTemplateTypes() && templateField)
+		{
+		CContentType* newContent=CContentType::NewL(templateField->ContentType());
+		delete iContentType;
+		iContentType = NULL;
+		iContentType=newContent;
+		}
+	else
+		{
+  		hint = aStream.ReadInt32L();
+  		
+ 		if(hint.HasVCardMappingUid())
+ 		    {
+        	iContentType->SetMapping(TUid::Uid(aStream.ReadInt32L()));
+ 		    }
+ 		    
+		MapHintsToFieldTypesL(hint);
+ 		iContentType->InternalizeAdditionalUidsL(hint.AdditionalUidsNum(),aStream);
+		}
+		
+	ConstructStorageL();
+	
+	if (OverRidesLabel())
+		{
+		const TInt length = aStream.ReadInt32L();
+		if (length)
+		    {
+			iLabel = HBufC::NewL(aStream,length);
+		    }
+		}
+	else if(templateField)
+	    {
+		iLabel = templateField->Label().AllocL();
+	    }
+		    
+	return nestedId;
+    }
+	
+
+void CContactItemField::RestoreDataL(CStreamStore& aStore,TStreamId aId)
+    {
+    RStoreReadStream stream;
+    stream.OpenLC(aStore,aId);
+	iStorage->RestoreL(aStore,stream);
+	CleanupStack::PopAndDestroy(); // stream
+	}
+
+/**
+@internalTechnology 
+*/
+EXPORT_C void CContactItemField::RestoreTextL(HBufC *aTextStream,TInt aTextFieldIndex)
+    {
+	__ASSERT_ALWAYS(iStorageType==KStorageTypeText,Panic(ECntPanicInvalidStorageType));
+    STATIC_CAST(CContactTextField*,iStorage)->InternalizeL(aTextStream,aTextFieldIndex);
+	}
+
+/**
+@internalTechnology 
+*/
+EXPORT_C TBool CContactItemField::RestoreIfMatchL(RReadStream& aStream,const CContactItemFieldDef *aFieldDef, const CContactItemFieldSet *aSystemTemplateFields,HBufC *aTextStream,TInt aTextIndex)
+	{
+	TStreamId nestedId;
+	nestedId=RestoreFieldTypesL(aStream,aSystemTemplateFields);
+	TBool match=EFalse;
+	if (aFieldDef==NULL)
+		match=ETrue;
+	else
+		{
+		for(TInt loop=0;loop<aFieldDef->Count();loop++)
+			{
+			TUid fieldType=(*aFieldDef)[loop];
+			if (fieldType==KUidContactFieldMatchAll || iContentType->ContainsFieldType(fieldType))
+				{
+				match=ETrue;
+				break;
+				}
+			}
+		}
+	if (match && iStorageType==KStorageTypeText)
+		RestoreTextL(aTextStream,aTextIndex);
+	return match;
+	}
+	        
+TBool CContactItemField::RestoreIfMatchL(RReadStream& aRootStream,TFieldType aFieldType, const CContactItemFieldSet *aSystemTemplateFields,HBufC *aTextStream,TInt aTextIndex)
+	{
+	CContactItemFieldDef* fieldDef=new(ELeave) CContactItemFieldDef();
+	CleanupStack::PushL(fieldDef);
+	fieldDef->AppendL(aFieldType);
+	TBool ret=RestoreIfMatchL(aRootStream,fieldDef, aSystemTemplateFields,aTextStream,aTextIndex);
+	CleanupStack::PopAndDestroy();	// fieldDef
+	return(ret);
+	}
+
+EXPORT_C TStorageType CContactItemField::StorageType() const
+/** Gets the field's storage type.
+
+@return The field's storage type. */
+    {
+    return iStorageType;
+    }
+
+EXPORT_C const CContentType &CContactItemField::ContentType() const
+/** Gets the field's content type.
+
+@return Reference to the field's content type. */
+    {
+    return *iContentType;
+    }
+
+const CContentType &CContactItemField::TemplateContentType(const CContactItemFieldSet &aSystemTemplateFields) const
+	{
+	if (UsesTemplateTypes() || OverRidesLabel())
+		return(*iContentType);
+	const CContactItemField *templateField=aSystemTemplateFields.FindById(iTemplateFieldId);
+	if (!templateField)
+		return(*iContentType);
+	return(templateField->ContentType());
+	}
+
+EXPORT_C TPtrC CContactItemField::Label() const
+/** Gets the field's label.
+
+@return The field label. If no label has been set, its length is zero. */
+    {
+    TPtrC label;
+    if (iLabel)
+        label.Set(*iLabel);
+    return label;
+    }
+
+EXPORT_C void CContactItemField::ResetStore()
+/** Resets the field storage. The field's store is deleted, then re-allocated. */
+    {
+    delete iStorage;
+	iStorage=NULL;
+	ConstructStorageL();
+	}
+
+EXPORT_C CContactFieldStorage *CContactItemField::Storage() const
+/** Gets a pointer to the field's base storage.
+
+Rather than using this function and then casting to a specific storage class, 
+one of the following functions should normally be used: TextStorage(), 
+StoreStorage(), AgentStorage(), or DateTimeStorage().
+
+@return The field's base storage type. */
+    {
+    return iStorage;
+    }
+
+EXPORT_C CContactTextField *CContactItemField::TextStorage() const
+/** Gets a pointer to the field's storage as a CContactTextField. 
+
+If the field's storage type is not KStorageTypeText, this function raises a panic.
+
+@return The field's storage as a CContactTextField*. */
+    {
+	__ASSERT_ALWAYS(iStorageType==KStorageTypeText,Panic(ECntPanicInvalidStorageType));
+    return (CContactTextField *)iStorage;
+	}
+
+EXPORT_C CContactStoreField *CContactItemField::StoreStorage() const
+/** Gets a pointer to the field's storage as a CContactStoreField. 
+
+This indicates the field data is stored in a descriptor or descriptor array. 
+If the field storage type is not KStorageTypeStore, this function raises a panic.
+
+@return Field's storage as a CContactStoreField*. */
+    {
+	__ASSERT_ALWAYS(iStorageType==KStorageTypeStore,Panic(ECntPanicInvalidStorageType));
+    return (CContactStoreField *)iStorage;
+	}
+
+EXPORT_C CContactAgentField *CContactItemField::AgentStorage() const
+/** Gets a pointer to the field's storage as a CContactAgentField. 
+
+An agent is a property in a vCard which contains another person's contact details. 
+If the field storage type is not KStorageTypeContactItemId, this function raises 
+a panic.
+
+@return Field's storage as a CContactAgentField*. */
+    {
+	__ASSERT_ALWAYS(iStorageType==KStorageTypeContactItemId,Panic(ECntPanicInvalidStorageType));
+    return (CContactAgentField *)iStorage;
+	}
+
+EXPORT_C CContactDateField *CContactItemField::DateTimeStorage() const
+/** Returns a pointer to the field's storage as a CContactDateField. 
+
+If the field storage type is not KStorageTypeDateTime, this function raises a panic.
+
+@return Field's storage as a CContactDateField*. */
+    {
+	__ASSERT_ALWAYS(iStorageType==KStorageTypeDateTime,Panic(ECntPanicInvalidStorageType));
+    return (CContactDateField *)iStorage;
+	}
+
+EXPORT_C void CContactItemField::AddFieldTypeL(TFieldType aFieldType)
+/** Appends a field type to the field's content type.
+
+Note that certain combinations of field types are not valid and should not be
+used.
+
+@param aFieldType The field type to append to the field's content type. */
+    {
+    iContentType->AddFieldTypeL(aFieldType);
+	}
+
+EXPORT_C void CContactItemField::RemoveFieldType(TFieldType aFieldType)
+/** Removes a field type from the field's content type.
+
+@param aFieldType The field type to remove from the field's content type. */
+	{
+    iContentType->RemoveFieldType(aFieldType);
+	}
+
+EXPORT_C void CContactItemField::SetMapping(TUid aMapping)
+/** Sets the vCard mapping for the field's content type.
+
+@param aMapping The new mapping for the field's content type. */
+    {
+    iContentType->SetMapping(aMapping);
+    }
+
+EXPORT_C void CContactItemField::SetHidden(TBool aHidden)
+/** Sets the value of the hidden attribute. 
+
+If hidden fields are included in the view definition, the field is displayed 
+like other fields. If the view definition masks hidden fields, it is not displayed. 
+See the TMode enumeration defined in class CContactItemViewDef.
+
+@param aHidden ETrue for hidden, EFalse for displayed. */
+    {
+    if (aHidden)
+        iAttributes|=EHidden;
+    else
+        iAttributes&=~EHidden;
+    }
+
+EXPORT_C void CContactItemField::SetReadOnly(TBool aReadOnly)
+/** Sets the value of the field's read only attribute.
+
+@param aReadOnly ETrue to set the field's read only attribute, EFalse to unset 
+the attribute. */
+    {
+    if (aReadOnly)
+        iAttributes|=EReadOnly;
+    else
+        iAttributes&=~EReadOnly;
+    }
+
+EXPORT_C void CContactItemField::SetSynchronize(TBool aSynchronize)
+/** Sets the value of the field's synchronise attribute.
+
+@param aSynchronize ETrue to set synchronise attribute, EFalse to unset it. */
+    {
+    if (aSynchronize)
+        iAttributes|=ESynchronize;
+    else
+        iAttributes&=~ESynchronize;
+    }
+
+EXPORT_C void CContactItemField::SetDisabled(TBool aDisabled)
+/** Sets the value of the disabled attribute.
+
+@param aDisabled ETrue to set the disabled attribute, EFalse to unset the 
+attribute. */
+    {
+    if (aDisabled)
+        iAttributes|=EDisabled;
+    else
+        iAttributes&=~EDisabled;
+    }
+
+/** 
+@internalComponent
+*/
+void CContactItemField::UsesTemplateData(TInt aTemplateFieldId)
+	{
+	iTemplateFieldId=aTemplateFieldId;
+	}
+
+void CContactItemField::SetLabelUnspecified(TBool aUnspecified)
+	{
+	if (aUnspecified)
+		iAttributes|=ELabelUnspecified;
+	else
+		iAttributes&=~ELabelUnspecified;
+	}
+
+EXPORT_C void CContactItemField::SetUserAddedField(TBool aUserAddedField)
+/** Sets the user added field attribute.
+
+@param aUserAddedField ETrue to set the field's user added attribute, EFalse 
+to unset it. */
+	{
+	if (aUserAddedField)
+		iAttributes|=EUserAddedField;
+	else
+		iAttributes&=~EUserAddedField;
+	}
+
+EXPORT_C void CContactItemField::SetTemplateField(TBool aTemplateField)
+/** Sets whether the field is a template field.
+
+@param aTemplateField ETrue to set the field's Is template attribute. EFalse 
+to unset it. */
+	{
+	if (aTemplateField)
+		iAttributes|=ETemplate;
+	else
+		iAttributes&=~ETemplate;
+	}
+
+EXPORT_C void CContactItemField::SetPrivate(TBool aPrivateField)
+/** Sets the value of the field's private attribute. 
+
+This is used by the contact database when exporting a contact item as a vCard, 
+to identify fields which should not be exported.
+
+@param aTemplateField ETrue to set the field's private attribute, EFalse to 
+unset it. */
+	{
+	if (aPrivateField)
+		iExtendedAttributes|=EPrivate;
+	else
+		iExtendedAttributes&=~EPrivate;
+	}
+
+EXPORT_C void CContactItemField::SetSpeedDial(TBool aSpeedDialField)
+/** Sets the value of the field's speed dial attribute.
+
+@param aSpeedDialField ETrue if the field should be a speed dial field, EFalse 
+if not. */
+	{
+	if (aSpeedDialField)
+		iExtendedAttributes|=ESpeedDial;
+	else
+		iExtendedAttributes&=~ESpeedDial;
+	}
+
+/**
+@internalTechnology 
+*/
+EXPORT_C void CContactItemField::SetCustomFilterable(EContactFieldFlags aContactFilterType)
+	{
+	if (aContactFilterType == EContactFieldFlagFilterable) 
+		{
+ 		iExtendedAttributes |= EUserDefinedFilter;
+ 		}
+  	else if (aContactFilterType == EContactFieldFlagFilterable1) 
+ 		{
+ 		iExtendedAttributes |= EUserDefinedFilter1;
+ 		}
+ 	else if (aContactFilterType == EContactFieldFlagFilterable2) 
+ 		{
+ 		iExtendedAttributes |= EUserDefinedFilter2;
+ 		}
+ 	else if (aContactFilterType == EContactFieldFlagFilterable3) 
+ 		{
+ 		iExtendedAttributes |= EUserDefinedFilter3;
+ 		}
+ 	else if (aContactFilterType == EContactFieldFlagFilterable4) 
+ 		{
+ 		iExtendedAttributes |= EUserDefinedFilter4;
+ 		}
+	}
+
+/** 
+Determine if a custom filter exists. If it does, return the filter type.
+
+@param aContactFieldFlag The custom filter type if one exists.
+@return ETrue if custom filter exists.
+@internalTechnology 
+ */	
+EXPORT_C TBool CContactItemField::HasCustomFilter(EContactFieldFlags& aContactFieldFlag) const
+	{
+	if (iExtendedAttributes & EUserDefinedFilter) 
+ 		{
+ 		aContactFieldFlag = EContactFieldFlagFilterable;
+ 		return ETrue;
+ 		}
+	else if (iExtendedAttributes & EUserDefinedFilter1) 
+ 		{
+ 		aContactFieldFlag = EContactFieldFlagFilterable1;
+ 		return ETrue;
+ 		}
+ 	else if (iExtendedAttributes & EUserDefinedFilter2) 
+ 		{
+ 		aContactFieldFlag = EContactFieldFlagFilterable2;
+ 		return ETrue;
+ 		}
+ 	else if (iExtendedAttributes & EUserDefinedFilter3) 
+ 		{
+ 		aContactFieldFlag = EContactFieldFlagFilterable3;
+ 		return ETrue;
+ 		}
+ 	else if (iExtendedAttributes & EUserDefinedFilter4) 
+ 		{
+ 		aContactFieldFlag = EContactFieldFlagFilterable4;
+ 		return ETrue;
+ 		}
+ 		
+ 	return EFalse;
+  	}
+  	
+
+void CContactItemField::UsesTemplateLabel()
+	{
+	iAttributes&=~EOverRidesLabel;
+	SetLabelUnspecified(EFalse);
+	}
+
+void CContactItemField::SetOverRidesLabel(TBool aValue)
+	{
+	if (aValue)
+		{
+		iAttributes|=EOverRidesLabel;
+		}
+	else
+		{
+		iAttributes&=~EOverRidesLabel;
+		}
+	}
+
+void CContactItemField::SetUsesTemplateTypes(TBool aUsesTemplateTypes)
+	{
+	if (aUsesTemplateTypes)
+		iAttributes|=EUsesTemplateData;
+	else
+		iAttributes&=~EUsesTemplateData;
+	}
+
+EXPORT_C void CContactItemField::SetLabelL(const TDesC& aLabel)
+/** Sets the field label. 
+
+The label is allocated using TDesC::AllocL(), so the function can leave. 
+Any existing label is replaced.
+
+@param aLabel The new field label. */
+    {
+	SetLabel(aLabel.AllocL());
+    }
+
+EXPORT_C void CContactItemField::SetLabel(HBufC* aLabel)
+/** Sets the field label. 
+
+The field takes ownership of aLabel so the function cannot leave.
+
+@param aLabel The new field label. */
+	{
+	delete iLabel;
+	iLabel=aLabel;
+	SetLabelUnspecified(EFalse);
+	iAttributes|=EOverRidesLabel;
+	}
+
+EXPORT_C void CContactItemField::SetId(TInt aId)
+/** Sets the ID which uniquely identifies a field within a field set..
+
+Note that the field ID value is initialised when the field is added to the 
+field set (using CContactItemFieldSet::AddL()). It is equivalent to the field's 
+index within the field set array, and should not normally be changed.
+
+@param aId The new field ID. */
+	{
+	iId=aId;
+	}
+
+EXPORT_C TInt CContactItemField::Id() const
+/** Gets the field ID.
+
+@return The field ID. */
+	{
+	return(iId);
+	}
+
+EXPORT_C TUint CContactItemField::UserFlags() const
+/** Gets the value of the user flags, as set by SetUserFlags().
+
+@return The user flags value. */
+	{
+	return((iAttributes&EUserMask)>>EUserMaskShift);
+	}
+
+EXPORT_C void CContactItemField::SetUserFlags(TUint aFlags)
+/** Sets the value of the user flags.
+
+@param aFlags The user flags value. */
+	{
+	iAttributes&=~EUserMask;
+	iAttributes|=((aFlags<<EUserMaskShift)&EUserMask);
+	}
+
+TInt CContactItemField::TemplateFieldId() const
+	{
+	return iTemplateFieldId;
+	}
+
+void CContactItemField::SetDeleted(TBool aDeleted)
+	{
+	if (aDeleted)
+		iAttributes|=STATIC_CAST(TUint, EDeleted); 
+	else
+		iAttributes&=~EDeleted;
+	}
+
+void CContactItemField::UpdateFieldFlags(const CContactItemFieldSet& aTemplateFieldSet)
+	{
+	TInt templatePosition;
+	TBool exactMatch;
+
+	if (!Storage()->IsFull() && !IsTemplate())
+		{
+		SetDeleted(ETrue);
+		}
+	else
+		{
+		SetDeleted(EFalse);
+		templatePosition = aTemplateFieldSet.MatchTemplateField(ContentType(),UserFlags(),exactMatch);
+		if (templatePosition != KErrNotFound)
+			{
+			const CContactItemField& templateField = aTemplateFieldSet[templatePosition];
+			UsesTemplateData(templateField.Id());
+			SetUsesTemplateTypes(exactMatch);
+			if (LabelUnspecified() || templateField.Label().CompareF(Label())==0)
+				{
+				UsesTemplateLabel();
+				}
+			}
+		}
+	SetLabelUnspecified(EFalse);
+	}
+
+/** 
+@internalTechnology 
+ */
+EXPORT_C void CContactItemField::GetFieldText(TDes &aText) const 
+	{
+	if (StorageType()==KStorageTypeText)
+		{
+		TPtrC text=TextStorage()->Text();
+		TInt length=text.Length();
+		const TInt carriageReturn=13;
+		const TInt lineFeed=10;
+		for(TInt loop=0;loop<length;loop++)
+  			if ((TChar(text[loop])==carriageReturn) || (TChar(text[loop])==lineFeed))
+				{
+				length=loop;
+				break;
+				}
+		if (length>KTextFieldMinimalLength)
+			length=KTextFieldMinimalLength;
+		aText.Copy(text.Left(length));
+		}
+	}
+
+EXPORT_C TBool CContactItemField::IsValidLabel(const TDesC& aLabel,TInt& aInvalidPos)
+/** Tests whether a field label is valid.
+
+Note: the label is invalid if it contains any of the following characters: 
+
+[] (left or right square bracket) 
+
+= (equals sign)
+
+. (dot) 
+
+: (colon) 
+
+, (comma)
+
+@param aLabel The field label to test.
+@param aInvalidPos On return, contains the character position within the label 
+of the first invalid character. The first character position is zero.
+@return ETrue if valid, EFalse if invalid. */
+	{
+		return !(((aInvalidPos = aLabel.Locate(KVersitTokenLSquareBracketVal)) != KErrNotFound) ||
+		((aInvalidPos = aLabel.Locate(KVersitTokenRSquareBracketVal)) != KErrNotFound) ||
+		((aInvalidPos = aLabel.Locate(KVersitTokenEqualsVal)) != KErrNotFound) ||
+		((aInvalidPos = aLabel.Locate(KVersitTokenColonVal)) != KErrNotFound) ||
+		((aInvalidPos = aLabel.Locate(KVersitTokenPeriodVal)) != KErrNotFound) ||
+		((aInvalidPos = aLabel.Locate(KVersitTokenCommaVal)) != KErrNotFound));
+	}
+
+EXPORT_C TBool CContactItemField::IsTemplateLabelField() const
+/** Tests whether the field is a template label field (a field which holds 
+the label for a contact card template: see class CContactCardTemplate).
+
+@return ETrue if the field is a template label field, EFalse if not. */
+	{
+	return (iContentType->ContainsFieldType(KUidContactFieldTemplateLabel));
+	}
+
+
+/** 
+Part of the system template update implementation. 
+This could be used for a generic update method at a later stage.
+@internalTechnology
+*/
+void CContactItemField::PopulateStoreL(RStoreWriteStream& aRootStream, TInt aCount, CArrayFix<TFieldHeader>& aFieldHeaderArray) const
+	{
+	if (!IsDeleted())
+		{
+		//Store attributes
+        aRootStream << aFieldHeaderArray[aCount].FieldAtts();
+        
+		// since field is in fullFields it cannot be empty, so there is no need to check
+        if (StorageType() != KStorageTypeText)
+            {
+            aRootStream << aFieldHeaderArray[aCount].StreamId();
+            }
+		
+		//Store field id.
+		aRootStream.WriteUint32L(iId);
+		aRootStream.WriteUint32L(iTemplateFieldId);
+        
+		CContactItemField::THint hint(0);
+        if(!UsesTemplateTypes())
+            {
+			CArrayFixFlat<TUid>* additionalFields = new(ELeave) CArrayFixFlat<TUid>(5);
+			CleanupStack::PushL(additionalFields);
+			
+			for(TInt loop=0; loop < iContentType->FieldTypeCount(); loop++)
+				{
+				TFieldType fieldType = iContentType->FieldType(loop);
+				if (!AddFieldToHint(fieldType, hint))
+				    {
+					additionalFields->AppendL(fieldType);
+				    }
+				}
+				
+			const TInt KAdditionalUidsCount = additionalFields->Count();
+			hint.SetAdditionalUidsNum(KAdditionalUidsCount);
+			
+            if(iContentType->Mapping() != KNullUid)
+                {
+                //Store vCard mapping uid if there is a one.
+                hint.SetHasVCardMappingUid();
+                aRootStream.WriteInt32L(hint.iHintValue);
+    			aRootStream.WriteInt32L(iContentType->Mapping().iUid); // mapping
+                }
+            else
+                {
+                aRootStream.WriteInt32L(hint.iHintValue);            
+                }			
+			
+			for (TInt ii = 0; ii < KAdditionalUidsCount; ++ii) 
+				{
+				aRootStream.WriteInt32L((*additionalFields)[ii].iUid); // additional typing uids
+				}
+			CleanupStack::PopAndDestroy(); // additionalFields
+            }    
+		
+		if (OverRidesLabel())
+			{ // store label if not inherited from template
+			
+			TInt length;
+			
+			if(iLabel)
+				{
+				length = iLabel->Length();
+				}
+			else
+				{
+				length = 0;
+				}			
+			
+			aRootStream.WriteInt32L(length);	
+				
+			if (length > 0)
+			    {
+				aRootStream << *(iLabel);
+			    }
+			}
+		} //if (!IsDeleted())
+	}
+
+
+/** 
+Part of the system template update implementation. 
+This could be used for a generic update method at a later stage.
+@since 7.0
+@internalTechnology
+*/
+void CContactItemField::PrepareFieldAsTemplateL(CContactItemFieldSet& aSystemTemplateFieldSet)
+	{
+	TInt templatePosition = KErrNotFound;
+	TBool exactMatch = EFalse;
+	
+	if ( !iStorage->IsFull() && !IsTemplate() )
+		{
+		SetDeleted(ETrue);
+		} // if
+	else
+		{
+		SetDeleted(EFalse);
+		templatePosition = aSystemTemplateFieldSet.MatchTemplateField(ContentType(), UserFlags(), exactMatch);
+		if (templatePosition != KErrNotFound)
+			{
+			const CContactItemField& systemTemplateField = aSystemTemplateFieldSet[templatePosition];
+			UsesTemplateData( systemTemplateField.Id() );
+			SetUsesTemplateTypes( exactMatch );
+			if( LabelUnspecified() || systemTemplateField.Label().CompareF(Label()) == 0 )
+				{
+				UsesTemplateLabel();
+				} 
+			} //if
+		} //else
+
+	SetLabelUnspecified(EFalse);
+	}
+
+void CContactItemField::InternalizeL(RReadStream& aStream)
+/** Internalises a CContactItemField object from a read stream. 
+@param aStream Stream from which the object should be internalised. */
+	{
+
+	delete iContentType;
+	iContentType = NULL;
+	iContentType = CContentType::NewL();
+	iContentType->InternalizeL(aStream);
+	
+	iStorageType = aStream.ReadUint32L();
+	
+	if(iLabel)
+		{
+		delete iLabel;
+		iLabel = NULL;
+		}
+	const TInt length=aStream.ReadInt32L();
+	if (length)
+		{
+		iLabel=HBufC::NewL(aStream,length);	
+		}
+
+	iId = aStream.ReadInt32L();
+	
+	iAttributes = aStream.ReadUint32L();
+		
+	iExtendedAttributes = aStream.ReadUint32L();
+	
+	delete iStorage;
+	iStorage = NULL;
+	ConstructStorageL();
+	iStorage->InternalizeL(aStream);
+	
+	iTemplateFieldId = aStream.ReadInt32L();		
+
+	}
+
+void CContactItemField::ExternalizeL(RWriteStream& aStream) const 
+/** Externalises a CContactItemField object to a write stream.
+@param aStream Stream to which the object should be externalised. */
+	{
+	iContentType->ExternalizeL(aStream);
+	
+	aStream.WriteUint32L(iStorageType);
+	
+	if(iLabel)
+		{
+		
+		const TInt length=iLabel->Length();
+		aStream.WriteInt32L(length);	
+		if (iLabel && length)
+			{
+			aStream<<*(iLabel);
+			}
+		}
+		
+	else
+		{
+		aStream.WriteInt32L(0);
+		}
+	
+	aStream.WriteInt32L(iId);
+	
+	aStream.WriteUint32L(iAttributes);
+		
+	aStream.WriteUint32L(iExtendedAttributes);
+	
+	iStorage->ExternalizeL(aStream);
+	
+	aStream.WriteInt32L(iTemplateFieldId);
+	}
+
+
+
+//
+//	class THint
+//
+CContactItemField::THint::THint() : iHintValue(0)
+	{}
+
+CContactItemField::THint::THint(TInt aValue)
+	{
+	iHintValue = aValue;
+	}
+
+TBool CContactItemField::THint::operator==(const THint& aHint) const
+	{
+	return (iHintValue == aHint.iHintValue);
+	}
+
+TBool CContactItemField::THint::operator!=(const THint& aHint) const	
+	{
+	return (iHintValue != aHint.iHintValue);
+	}
+
+TInt  CContactItemField::THint::HintType() const
+	{
+	return (iHintValue & KHintTypeMask);
+	}
+
+TInt CContactItemField::THint::TemplateFieldId() const
+    {
+    return (iHintValue & KHintTemplateFieldMask);    
+    }
+    
+void  CContactItemField::THint::SetTemplateFieldId(TInt aTemplateFieldId)
+    {
+    iHintValue |= (aTemplateFieldId & KHintTemplateFieldMask);
+    }
+
+inline void CContactItemField::THint::SetHasVCardMappingUid()
+    {
+    iHintValue |= KHintVCardMappingMask;    
+    }
+    
+inline TBool CContactItemField::THint::HasVCardMappingUid() const
+    {
+    return (iHintValue & KHintVCardMappingMask);    
+    }
+
+inline TInt CContactItemField::THint::AdditionalUidsNum() const
+    {
+    return ((iHintValue & KHintAdditionalMask) >> KHintAdditionalMaskShift);
+    }
+    
+inline void CContactItemField::THint::SetAdditionalUidsNum(TInt aNumber)
+    {
+    iHintValue |= ((aNumber << KHintAdditionalMaskShift) & KHintAdditionalMask);       
+    }
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS	
+inline void CContactItemField::THint::SetIsPhone()
+	{iHintValue|=KIntContactHintIsPhone;}
+inline void CContactItemField::THint::SetIsMsg()
+	{iHintValue|=KIntContactHintIsMsg;}
+// turn off Pronunciation bit too?
+inline void CContactItemField::THint::SetIsCompanyName()
+	{iHintValue|=KIntContactHintIsCompanyName;}
+inline void CContactItemField::THint::SetIsFamilyName()
+	{iHintValue|=KIntContactHintIsFamilyName;}
+inline void CContactItemField::THint::SetIsGivenName()
+	{iHintValue|=KIntContactHintIsGivenName;}
+inline void CContactItemField::THint::SetIsCompanyNamePronunciation()
+	{iHintValue|=KIntContactHintIsCompanyName|KIntContactHintIsPronunciation;}
+inline void CContactItemField::THint::SetIsFamilyNamePronunciation()
+	{iHintValue|=KIntContactHintIsFamilyName|KIntContactHintIsPronunciation;}
+inline void CContactItemField::THint::SetIsGivenNamePronunciation()
+	{iHintValue|=KIntContactHintIsGivenName|KIntContactHintIsPronunciation;}
+inline void CContactItemField::THint::SetIsAddress()
+	{iHintValue|=KIntContactHintIsAddress;}
+inline void CContactItemField::THint::SetIsAdditionalName()
+	{iHintValue|=KIntContactHintIsAdditionalName;}
+inline void CContactItemField::THint::SetIsSuffixName()
+	{iHintValue|=KIntContactHintIsSuffixName;}
+inline void CContactItemField::THint::SetIsPrefixName()
+	{iHintValue|=KIntContactHintIsPrefixName;}
+inline void CContactItemField::THint::SetStorageIsInline()
+	{iHintValue|=KIntContactHintStorageInline;}
+inline void CContactItemField::THint::SetIsEmail()
+	{iHintValue|=KIntContactHintIsEmail;}
+inline TBool CContactItemField::THint::IsPhone() const
+	{return (iHintValue&KIntContactHintIsPhone);}
+inline TBool CContactItemField::THint::IsMsg() const
+	{return (iHintValue&KIntContactHintIsMsg);}
+inline TBool CContactItemField::THint::IsCompanyName() const
+	{return ((iHintValue&KIntContactHintIsCompanyNamePronunciation) == KIntContactHintIsCompanyName);}
+inline TBool CContactItemField::THint::IsFamilyName() const
+	{return ((iHintValue&KIntContactHintIsFamilyNamePronunciation)==KIntContactHintIsFamilyName);}
+inline TBool CContactItemField::THint::IsGivenName() const
+	{return ((iHintValue&KIntContactHintIsGivenNamePronunciation)==KIntContactHintIsGivenName);}
+inline TBool CContactItemField::THint::IsCompanyNamePronunciation() const
+	{return ((iHintValue&KIntContactHintIsCompanyNamePronunciation) == KIntContactHintIsCompanyNamePronunciation);}
+inline TBool CContactItemField::THint::IsFamilyNamePronunciation() const
+	{return ((iHintValue&KIntContactHintIsFamilyNamePronunciation)==KIntContactHintIsFamilyNamePronunciation);}
+inline TBool CContactItemField::THint::IsGivenNamePronunciation() const
+	{return ((iHintValue&KIntContactHintIsGivenNamePronunciation)==KIntContactHintIsGivenNamePronunciation);}
+inline TBool CContactItemField::THint::IsAddress() const
+	{return (iHintValue&KIntContactHintIsAddress);}
+inline TBool CContactItemField::THint::IsAdditionalName() const
+	{return (iHintValue&KIntContactHintIsAdditionalName);}
+inline TBool CContactItemField::THint::IsSuffixName() const
+	{return (iHintValue&KIntContactHintIsSuffixName);}
+inline TBool CContactItemField::THint::IsPrefixName() const
+	{return (iHintValue&KIntContactHintIsPrefixName);}
+inline TBool CContactItemField::THint::IsStorageInline() const
+	{return (iHintValue&KIntContactHintStorageInline);}
+inline TBool CContactItemField::THint::IsEmail() const
+	{return (iHintValue&KIntContactHintIsEmail);}
+	
+#ifndef __SYMBIAN_CNTMODEL_USE_SQLITE__	
+inline void CContactItemField::THint::SetHasAdditionalUids()
+	{iHintValue|=KHintAdditionalMask;}
+#endif //__SYMBIAN_CNTMODEL_USE_SQLITE__ 
+inline TBool CContactItemField::THint::Contains(const THint& aHint) const
+	{return (iHintValue&aHint.iHintValue);}
+#endif	
+//
+//	class TFieldHeader
+//
+
+/*
+ * Default constructor
+ */
+TFieldHeader::TFieldHeader()
+: iFieldUid(0),
+  iStreamId(KNullStreamIdValue)
+    {
+    }
+
+/*
+ * Overloaded constructor
+ */
+TFieldHeader::TFieldHeader(TContactFieldAtts aAtts, TUint32 aFieldUid, TStreamId aId)
+: iAtts(aAtts),
+  iFieldUid(aFieldUid),
+  iStreamId(aId)
+    {
+    }
+    
+inline TInt TFieldHeader::FieldId() const
+	{
+	return iFieldUid;
+	}
+
+inline void TFieldHeader::SetFieldId(TInt aId) 
+	{
+    iFieldUid = aId;
+	}
+
+inline TContactFieldAtts TFieldHeader::FieldAtts() const
+    {
+    return iAtts;
+    }
+    
+inline void TFieldHeader::SetFieldAtts(TContactFieldAtts aAtts)
+    {
+    iAtts = aAtts; 
+    }
+
+inline TStreamId TFieldHeader::StreamId() const
+    {
+    return iStreamId;    
+    }
+    
+inline void TFieldHeader::SetStreamId(TStreamId aId)
+    {
+    iStreamId = aId;
+    }