diff -r 000000000000 -r e686773b3f54 phonebookengines/contactsmodel/src/CNTITEM.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookengines/contactsmodel/src/CNTITEM.CPP Tue Feb 02 10:12:17 2010 +0200 @@ -0,0 +1,2454 @@ +// 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 +#include + +#include +#include +#include +#include +#include + +#include "CNTSTD.H" +#include "CNTPROF.H" +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include "cntfieldheader.h" +#endif + + +EXPORT_C CContactItemFieldSet* CContactItemFieldSet::NewL() +/** Allocates and constructs a new field set. + +@return Pointer to the newly created field set. */ + { // static + CContactItemFieldSet* self=CContactItemFieldSet::NewLC(); + CleanupStack::Pop(); // self + return self; + } + +EXPORT_C CContactItemFieldSet* CContactItemFieldSet::NewLC() +/** Allocates and constructs a new field set. + +@return Pointer to the newly created field set. This is left on the cleanup +stack. */ + { // static + CContactItemFieldSet* self=new(ELeave) CContactItemFieldSet; + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +EXPORT_C CContactItemFieldSet::~CContactItemFieldSet() +/** The destructor frees all resources owned by the field set, prior to its destruction. */ + { + if (iFields) + { + iFields->ResetAndDestroy(); + delete iFields; + } + } + +CContactItemFieldSet::CContactItemFieldSet() + {} + +void CContactItemFieldSet::ConstructL() + { + iFields=new(ELeave) CArrayPtrFlat(4); + } + +const CContactItemField* CContactItemFieldSet::FindById(TInt aId) const + { + const CContactItemField* field=NULL; + for (TInt ii=0;iiCount();ii++) + { + field=iFields->At(ii); + if (field->Id()==aId) + return(field); + } + return(NULL); + } + +EXPORT_C TInt CContactItemFieldSet::FindNext(TFieldType aFieldType,TInt aStartPos) const +/** Finds the next field in the field set with the specified field type. + +@param aFieldType The field type of interest. +@param aStartPos The index within the field set array at which to start the +search. By default set to KContactFieldSetSearchAll, to find the first field. +Must be a valid array index, or the function raises a panic. +@return If found, the index of the field within the field set, or KErrNotFound +if not found. */ + { + return(FindNext(aFieldType,KUidContactFieldMatchAll,aStartPos)); + } + +EXPORT_C TInt CContactItemFieldSet::FindNext(TFieldType aFieldType,TUid aMapping,TInt aStartPos) const +/** Finds the next field in the field set containing both the content type mapping +and the field type specified. + +@param aFieldType The field type of interest. +@param aMapping The content type mapping of interest. +@param aStartPos The index within the array at which to start the search. By +default set to KContactFieldSetSearchAll, to find the first field. Must be +a valid array index, or the function raises a panic. +@return If found, the index of the field within the field set, or KErrNotFound +if not found. */ + { + const TInt count=iFields->Count(); + TInt pos=(aStartPos==KContactFieldSetSearchAll? 0 : aStartPos); + TInt ii=KErrNotFound; + for (ii=pos;iiContentType(); + if (contentType.Mapping()==KUidContactFieldMatchAll || aMapping==KUidContactFieldMatchAll || contentType.Mapping()==aMapping) + if (aFieldType==KUidContactFieldMatchAll || contentType.ContainsFieldType(aFieldType)) + return ii; + } + return KErrNotFound; + } + +void CContactItemFieldSet::SetFieldId(CContactItemField& aField) + { + TInt id=iFields->Count(); + TInt count=iFields->Count(); + FOREVER + { + TInt loop=0; + for(;loopId()==id) + break; + if (loop==count) + { + aField.SetId(id); + break; + } + id++; + } + } + +EXPORT_C CContactItemFieldSet& CContactItemFieldSet::AddL(CContactItemField& aField) +/** Appends a field to the field set. The field set takes ownership of the field. + +@param aField Reference to the field to add to the field set. The field's +ID is updated. +@return Reference to the current field set. */ + { + __ASSERT_DEBUG(&aField!=NULL,Panic(ECntPanicNullPointer)); + SetFieldId(aField); + iFields->AppendL(&aField); + return (*this); + } + +EXPORT_C void CContactItemFieldSet::Remove(TInt aIndex) +/** Removes a field from the field set. + +@param aIndex The index of the field to delete. Must be a valid index within +the field set or the function raises a panic. */ + { + delete (*iFields)[aIndex]; + iFields->Delete(aIndex); + } + +EXPORT_C void CContactItemFieldSet::Move(TInt aFrom, TInt aTo) +/** Changes a field's position within the field set. + +Both indexes specified must be valid (i.e. between zero and Count()-1 inclusive), +or the function raises a panic. + +@param aFrom The index of the field to move. +@param aTo The index of the new position within the field set. */ + { + CContactItemField *moveField=(*iFields)[aFrom]; + if (aFromaTo;loop--) + (*iFields)[loop]=(*iFields)[loop-1]; + } + (*iFields)[aTo]=moveField; + } + +EXPORT_C void CContactItemFieldSet::InsertL(TInt aIndex,CContactItemField& aField) +/** Inserts a field into the field set. + +@param aIndex The position in the field set at which to insert the field. +If equal to or greater than the number of elements in the field set, the field +is appended to the field set. +@param aField Reference to the field to add to the field set. The field's ID +is updated. */ + { + __ASSERT_DEBUG(&aField!=NULL,Panic(ECntPanicNullPointer)); + SetFieldId(aField); + TInt count=iFields->Count(); + if (count>aIndex) + iFields->InsertL(aIndex,&aField); + else + iFields->AppendL(&aField); + } + +/** + +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. + +Matching Algorithm Steps: +======================== + +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. + +1. Loop through all the contact item fields of the template. + +For each template field: + +2. Perform a strict, or exact, match between the vCard mappings of the template field and the field to be matched. +3. If the vCard mappings match exactly, compare User Flags values and amend the overall score accordingly. +4. Loop through all the field types (TFieldType array) stored as part of the content type of the field to be matched. + +For each field type of the field to be matched: + +5. Loop through the field types of the iterated template field to find a field type match. Amend the 'hits' and 'misses' count accordingly. +6. Calculate the overall score weighing the 'hits' and 'misses' count. +7. Amend the overall score count in order to account for special cases (e.g. user defined fields) +8. Compare the overall score with the best score. If score > current best score, replace the 'bestScore' count and 'bestMatch' index. + +9. Return the 'bestMatch' field index of the template field. + +@param aContentType The content type of the field to find a match for. +@param aUserFlags The user flags of the field to find a match for. +@param aExactMatch Boolean to indicate an exact field match within the template. + +@return The index of the best matched template field, if found, else KErrNotFound. + +*/ + +TInt CContactItemFieldSet::MatchTemplateField(const CContentType& aContentType,TUint aUserFlags,TBool &aExactMatch) const + { + const TInt count=Count(); + TInt bestScore=5; // Has to be better than one or fail the match + TInt bestMatch=KErrNotFound; + TInt contentTypeCount=aContentType.FieldTypeCount(); + + // Loop through all the template fields to find the best field match + for (TInt ii=0;iibestScore) + { + aExactMatch=(misses==0); + bestScore=score; + bestMatch=ii; + } + } + } + return bestMatch; + } + +// 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. +// NOTE: This function does not include the base contact item field's vCard mapping whilst looking for the Field Type +TBool CContactItemFieldSet::ContainsFieldTypeMapping(const CContentType& aBaseFieldContentType, const TFieldType& aContactFieldType) const + { + // Loop through all the template Field Types to attempt to match the individual Field Type of the incoming contact item's field + for(TInt templateFieldTypeLoop=0; templateFieldTypeLoop < aBaseFieldContentType.FieldTypeCount(); ++templateFieldTypeLoop) + { + if(aBaseFieldContentType.FieldType(templateFieldTypeLoop) == aContactFieldType) + { + return ETrue; + } + } + return EFalse; + } + +/** +@internalTechnology +*/ +EXPORT_C TStreamId CContactItemFieldSet::StoreL(CStreamStore& aStore,const CContactItem* aTemplate,RWriteStream& aTextStream,CStreamStore& aBlobStore,CContactTables* aTables) + { + const TInt count=Count(); + for (TInt ii=0;iiCardFields(); + field->UpdateFieldFlags(templateFields); + } + else + { + field->SetLabelUnspecified(EFalse); + } + } + return StoreL(aStore,aTextStream,aBlobStore,aTables); + } + +EXPORT_C TStreamId CContactItemFieldSet::StoreL(CStreamStore& aStore,RWriteStream& aTextStream,CStreamStore& aBlobStore) +/** Stores the field set to a stream store. +@internalTechnology +@param aStore Stream store to which the field set is written. +@param aTextStream Stream to which data stored in text fields (with a storage +type of KStorageTypeText) is written. +@param aBlobStore Stream store to which data stored in non-text fields is written. +@return The ID of the stream store. */ + { + //Overloaded to maintain SC. + return (StoreL(aStore,aTextStream,aBlobStore,NULL)); + } + +/* +Store all contact fields in this field set into given header and data stores. + +In SQLite data schema, contact field data is saved in the stream store (aStore) as: + +contact-item-field-set = number-of-fields *field + ; repeated times + +field = contact-field-atts [ stream-id ] field-id template-id [ hint-value *mapping *additional-field ] [ label-length [ label ] ] + ; 1st optional part is there if the contact field is NOT stored as text. + ; if the field uses the template's content type, the 2nd optional part is left out + ; is repeated a number of times as specified by inside hint-value + ; mapping is there if vcard-mapping-id-mask in hint-valute is set + ; 3rd optional part is there if there is a label which overrides the template label.