javaextensions/pim/versit/src.s60/cpimcardpropertyconverter.cpp
branchRCL_3
changeset 19 04becd199f91
equal deleted inserted replaced
16:f5050f1da672 19:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Converts properties PIM <-> vCard
       
    15  *
       
    16 */
       
    17 
       
    18 
       
    19 // CLASS HEADER
       
    20 #include "cpimcardpropertyconverter.h"
       
    21 
       
    22 // INTERNAL INCLUDES
       
    23 #include "pimcommon.h"
       
    24 #include "pimpanics.h"
       
    25 #include "pimversit.h"
       
    26 #include "cpimitem.h"
       
    27 #include "cpimvcardparser.h"
       
    28 #include "cpimcontactitem.h"
       
    29 #include "cpimparserproperty.h"
       
    30 #include "cpimcontactvalidator.h"
       
    31 #include "cpimvcardparserparamarray.h"
       
    32 #include "logger.h"
       
    33 
       
    34 // EXTERNAL INCLUDES
       
    35 #include <vcard.h>
       
    36 #include <cntdef.h> // parameter literals
       
    37 #include <tz.h>
       
    38 #include <tzconverter.h>
       
    39 
       
    40 // ============================ MEMBER FUNCTIONS ===============================
       
    41 
       
    42 // -----------------------------------------------------------------------------
       
    43 // CPIMCardPropertyConverter::NewL
       
    44 // Two-phased constructor.
       
    45 // -----------------------------------------------------------------------------
       
    46 //
       
    47 CPIMCardPropertyConverter* CPIMCardPropertyConverter::NewL(
       
    48     const CPIMContactValidator& aValidator)
       
    49 {
       
    50     JELOG2(EPim);
       
    51     CPIMCardPropertyConverter* self =
       
    52         new(ELeave) CPIMCardPropertyConverter(aValidator);
       
    53 
       
    54     return self;
       
    55 }
       
    56 
       
    57 // Destructor
       
    58 CPIMCardPropertyConverter::~CPIMCardPropertyConverter()
       
    59 {
       
    60     JELOG2(EPim);
       
    61 }
       
    62 
       
    63 // -----------------------------------------------------------------------------
       
    64 // CPIMCardPropertyConverter::ConvertFieldL
       
    65 // Inserts a Field from a PIM Contact Item to CParserVCard as a property.
       
    66 // -----------------------------------------------------------------------------
       
    67 //
       
    68 void CPIMCardPropertyConverter::ConvertFieldL(const CPIMItem& aItem, // item to read the field from
       
    69         CParserVCard& aParser, // parser to insert the property to.
       
    70         TPIMContactField aField) // field to convert
       
    71 {
       
    72     JELOG2(EPim);
       
    73     TInt valueCount = aItem.CountValuesL(aField);
       
    74     for (TInt i = 0; i < valueCount; i++)
       
    75     {
       
    76         switch (aField)
       
    77         {
       
    78         case EPIMContactAddr:
       
    79         {
       
    80             ConvertAddressFieldL(aItem, aParser, aField, i);
       
    81             break;
       
    82         }
       
    83         case EPIMContactBirthday:
       
    84         case EPIMContactRevision:
       
    85         case EPIMContactExtAnniversary:
       
    86         {
       
    87             ConvertDateFieldL(aItem, aParser, aField, i);
       
    88             break;
       
    89         }
       
    90         case EPIMContactEmail:
       
    91         case EPIMContactNote:
       
    92         case EPIMContactTel:
       
    93         case EPIMContactTitle:
       
    94         case EPIMContactUrl:
       
    95         case EPIMContactNickname:
       
    96         case EPIMContactExtSip:
       
    97         case EPIMContactExtDtmf:
       
    98         case EPIMContactExtWvUserId:
       
    99         case EPIMContactExtSpouse:
       
   100         case EPIMContactExtChildren:
       
   101         case EPIMContactExtAssistantName:
       
   102         case EPIMContactExtVoip:
       
   103         case EPIMContactExtPTT:
       
   104         case EPIMContactExtSWIS:
       
   105             // UID is required by VFX. Do not fix even though this is wrong
       
   106         case EPIMContactUid:
       
   107         {
       
   108             ConvertStringFieldL(aItem, aParser, aField, i);
       
   109             break;
       
   110         }
       
   111         case EPIMContactName:
       
   112         {
       
   113             ConvertNameFieldL(aItem, aParser, aField, i);
       
   114             break;
       
   115         }
       
   116         case EPIMContactOrg:
       
   117         case EPIMContactExtDepartment:
       
   118         {
       
   119             ConvertOrganisationalFieldsL(aItem, aParser, aField, i);
       
   120             break;
       
   121         }
       
   122         case EPIMContactPhoto:
       
   123         {
       
   124             ConvertPhotoFieldL(aItem, aParser, aField, i);
       
   125             break;
       
   126         }
       
   127         case EPIMContactClass:
       
   128         {
       
   129             ConvertClassFieldL(aItem, aParser, aField, i);
       
   130             break;
       
   131         }
       
   132         // PIM API vCard parser does not support converting formatted names
       
   133         // since the conversion is not unambiguous and an optional feature
       
   134         // for vCard parsers based on IMC vCard specification. Also, PIM
       
   135         // API internal specification version 4.3 does not allow
       
   136         // Contact.FORMATTED_NAME to be a supported fields in S60 implementations
       
   137         case EPIMContactFormattedName:
       
   138         case EPIMContactFormattedAddr:
       
   139         case EPIMContactPhotoUrl:
       
   140         case EPIMContactPublicKey:
       
   141         case EPIMContactPublicKeyString:
       
   142         default:
       
   143         {
       
   144             __ASSERT_DEBUG(EFalse, User::Panic(KPIMPanicCategory,
       
   145                                                EPIMPanicUnsupportedField));
       
   146             return;
       
   147         }
       
   148         }
       
   149     }
       
   150 }
       
   151 
       
   152 // -----------------------------------------------------------------------------
       
   153 // CPIMCardPropertyConverter::ConvertPropertyL
       
   154 // Inserts a proprety from a vCard to a PIM Contact Item as a field
       
   155 // -----------------------------------------------------------------------------
       
   156 //
       
   157 CParserVCard* CPIMCardPropertyConverter::ConvertPropertyL(
       
   158     const CParserProperty& aProperty, // property to convert
       
   159     CPIMContactItem& aItem) // item to insert the field to
       
   160 {
       
   161     JELOG2(EPim);
       
   162     TUid valueTypeUid = aProperty.Uid();
       
   163     TInt valueType = valueTypeUid.iUid;
       
   164     CParserVCard* retVal = NULL;
       
   165 
       
   166     // The following, rather ugly, cast makes it possible for us to access
       
   167     // the protected iArrayOfParams field.
       
   168     const CPIMParserProperty& property =
       
   169         static_cast<const CPIMParserProperty&>(aProperty);
       
   170 
       
   171     // CLASS field is converted before others
       
   172     if (aProperty.Name().CompareF(KVersitTokenClass) == 0)
       
   173     {
       
   174         ConvertClassPropertyL(property, aItem);
       
   175     }
       
   176     // If SOUND field holds parameter X-IRMC-N, it countains name reading fields
       
   177     else if ((aProperty.Name().CompareF(KVersitTokenSOUND) == 0)
       
   178              && (aProperty.Param(KVersitParam8NamePrn)))
       
   179     {
       
   180         ConvertNameReadingFieldL(property, aItem);
       
   181     }
       
   182     else
       
   183     {
       
   184         switch (valueType)
       
   185         {
       
   186         case KVersitPropertyBinaryUid:
       
   187         {
       
   188             ConvertPhotoPropertyL(property, aItem);
       
   189             break;
       
   190         }
       
   191         case KVersitPropertyCDesCArrayUid:
       
   192         {
       
   193             // name and address arrays
       
   194             ConvertCDesCArrayPropertyL(property, aItem);
       
   195             break;
       
   196         }
       
   197         case KVersitPropertyDateUid:
       
   198         case KVersitPropertyDateTimeUid:
       
   199         {
       
   200             // REV, BDAY, X-ANNIVERSARY
       
   201             ConvertDatePropertyL(property, aItem);
       
   202             break;
       
   203         }
       
   204         case KVersitPropertyHBufCUid:
       
   205         {
       
   206             ConvertStringPropertyL(property, aItem);
       
   207             break;
       
   208         }
       
   209         case KVCardPropertyAgentUid:
       
   210         {
       
   211             retVal = ConvertAgentPropertyL(property);
       
   212         }
       
   213         default:
       
   214         {
       
   215             // don't support, don't care
       
   216         }
       
   217         }
       
   218     }
       
   219     return retVal;
       
   220 }
       
   221 
       
   222 // -----------------------------------------------------------------------------
       
   223 // CPIMCardPropertyConverter::CPIMCardPropertyConverter
       
   224 // C++ default constructor can NOT contain any code, that
       
   225 // might leave.
       
   226 // -----------------------------------------------------------------------------
       
   227 //
       
   228 CPIMCardPropertyConverter::CPIMCardPropertyConverter(
       
   229     const CPIMContactValidator& aValidator) :
       
   230         iContactValidator(aValidator)
       
   231 {
       
   232     JELOG2(EPim);
       
   233 }
       
   234 
       
   235 // -----------------------------------------------------------------------------
       
   236 // CPIMCardPropertyConverter::ConvertAgentPropertyL
       
   237 // Converts an agent property.
       
   238 // -----------------------------------------------------------------------------
       
   239 //
       
   240 inline CParserVCard* CPIMCardPropertyConverter::ConvertAgentPropertyL(
       
   241     const CPIMParserProperty& aProperty) // property to convert
       
   242 {
       
   243     JELOG2(EPim);
       
   244     CParserPropertyValueAgent* propertyValue =
       
   245         static_cast<CParserPropertyValueAgent*>(aProperty.Value());
       
   246     CParserVCard* value = propertyValue->Value();
       
   247     return value;
       
   248 }
       
   249 
       
   250 // -----------------------------------------------------------------------------
       
   251 // CPIMCardPropertyConverter::AddParamHomeAndWorkL
       
   252 // Adds parameters "HOME" and "WORK" if necessary to given property parameter
       
   253 // array.
       
   254 // -----------------------------------------------------------------------------
       
   255 //
       
   256 void CPIMCardPropertyConverter::AddParamHomeAndWorkL(TPIMAttribute aAttributes, // checked if it contains AttrHome or AttrWork
       
   257         CPIMVCardParserParamArray& aParamArray) // array to add the parameters to
       
   258 {
       
   259     JELOG2(EPim);
       
   260     if ((aAttributes & EPIMContactAttrHome) != 0)
       
   261     {
       
   262         AddParserParameterL(aParamArray, KVersitParam8Home());
       
   263     }
       
   264     if ((aAttributes & EPIMContactAttrWork) != 0)
       
   265     {
       
   266         AddParserParameterL(aParamArray, KVersitParam8Work());
       
   267     }
       
   268 }
       
   269 
       
   270 // -----------------------------------------------------------------------------
       
   271 // CPIMCardPropertyConverter::ConvertAddressFieldL
       
   272 // Converts an address field from a PIM Contact Item to CParserVCard.
       
   273 // The field is stored in the parser as a property.
       
   274 // The address values are stored in CParserPropertyValue
       
   275 // CParserProperty is created, given the value.
       
   276 // Parameters are added, and finally the property is added to parser.
       
   277 // -----------------------------------------------------------------------------
       
   278 //
       
   279 void CPIMCardPropertyConverter::ConvertAddressFieldL(const CPIMItem& aItem, // item to convert from
       
   280         CParserVCard& aParser, // parsers to write to
       
   281         TPIMContactField aField, // field to convert
       
   282         TInt aIndex) // index to the field
       
   283 {
       
   284     JELOG2(EPim);
       
   285     // Add attributes if there are any
       
   286     TPIMAttribute attributes = aItem.getAttributes(aField, aIndex);
       
   287     CPIMVCardParserParamArray* paramArray =
       
   288         new(ELeave) CPIMVCardParserParamArray(3);
       
   289     CleanupStack::PushL(paramArray);
       
   290     AddParamHomeAndWorkL(attributes, *paramArray);
       
   291 
       
   292     const CDesCArray& itemAddrArray = aItem.GetStringArrayL(aField, aIndex);
       
   293     // Copy the array
       
   294     TInt elementCount = itemAddrArray.Count();
       
   295     CDesCArrayFlat* addrArray = new(ELeave) CDesCArrayFlat(elementCount);
       
   296     CleanupStack::PushL(addrArray);
       
   297     for (TInt i = 0; i < elementCount; i++)
       
   298     {
       
   299         if (itemAddrArray[i].Compare(KPIMNullArrayElement) == 0)
       
   300         {
       
   301             addrArray->AppendL(KNullDesC);
       
   302         }
       
   303         else
       
   304         {
       
   305             addrArray->AppendL(itemAddrArray[i]);
       
   306         }
       
   307     }
       
   308 
       
   309     CParserPropertyValue* propertyValue =
       
   310         new(ELeave) CParserPropertyValueCDesCArray(addrArray);
       
   311     // addrArray is now owned by propertyValue
       
   312     CleanupStack::Pop(addrArray);
       
   313     AddPropertyToParserL(propertyValue, KVersitTokenADR(), paramArray, aParser);
       
   314     // The paramArray and propertyValue are popped by the previous function call
       
   315 }
       
   316 
       
   317 // -----------------------------------------------------------------------------
       
   318 // CPIMCardPropertyConverter::ConvertNameFieldL
       
   319 // Converts a Name field from a PIM Contact Item to CParserVCard.
       
   320 // The field is stored in the parser as a property.
       
   321 // The name values are stored in CParserPropertyValue
       
   322 // CParserProperty is created, given the value.
       
   323 // Parameters are added, and finally the property is added to parser.
       
   324 // -----------------------------------------------------------------------------
       
   325 //
       
   326 void CPIMCardPropertyConverter::ConvertNameFieldL(const CPIMItem& aItem, // item to convert from
       
   327         CParserVCard& aParser, // parsers to write to
       
   328         TPIMContactField aField, // field to convert
       
   329         TInt aIndex) // index to the field
       
   330 {
       
   331     JELOG2(EPim);
       
   332     TBool readingFieldsPresent = EFalse;
       
   333     const CDesCArray& itemNameArray = aItem.GetStringArrayL(aField, aIndex);
       
   334     TInt elementCount = itemNameArray.Count();
       
   335     CDesCArray* readingArray = new(ELeave) CDesCArrayFlat(2);
       
   336     CleanupStack::PushL(readingArray);
       
   337     CDesCArray* nameArray = new(ELeave) CDesCArrayFlat(elementCount);
       
   338     CleanupStack::PushL(nameArray);
       
   339 
       
   340     // Names should be ordered as follows:
       
   341     // Family name, Given name, Middle name, Prefix, Suffix
       
   342     // so check TPIMContactNameElement that it is in the right order
       
   343     for (TInt i = 0; i < elementCount; i++)
       
   344     {
       
   345         // Skip extended name reading fields on here
       
   346         if (i == EPIMContactExtFamilyNameReading || i
       
   347                 == EPIMContactExtGivenNameReading)
       
   348         {
       
   349             if (itemNameArray[i].Compare(KPIMNullArrayElement) != 0)
       
   350             {
       
   351                 readingFieldsPresent = ETrue;
       
   352                 readingArray->AppendL(itemNameArray[TPIMContactNameElement(i)]);
       
   353             }
       
   354             else
       
   355             {
       
   356                 readingArray->AppendL(KNullDesC);
       
   357             }
       
   358         }
       
   359         // Replace null array elements with KNullDesC
       
   360         else if (itemNameArray[i].Compare(KPIMNullArrayElement) == 0)
       
   361         {
       
   362             nameArray->AppendL(KNullDesC);
       
   363         }
       
   364         else
       
   365         {
       
   366             nameArray->AppendL(itemNameArray[TPIMContactNameElement(i)]);
       
   367         }
       
   368     }
       
   369     CParserPropertyValue* propertyValue =
       
   370         new(ELeave) CParserPropertyValueCDesCArray(nameArray);
       
   371     // nameArray is now owned by propertyValue
       
   372     CleanupStack::Pop(nameArray);
       
   373     AddPropertyToParserL(propertyValue, KVersitTokenN(), NULL, aParser);
       
   374     // The paramArray and propertyValue are popped by the previous function call
       
   375 
       
   376     // Add name reading fields if they are present
       
   377     if (readingFieldsPresent)
       
   378     {
       
   379         // Create parameter array
       
   380         CPIMVCardParserParamArray* paramArray =
       
   381             new(ELeave) CPIMVCardParserParamArray(1);
       
   382         CleanupStack::PushL(paramArray);
       
   383         // Create pronunciation parameter and add it to the parameter array
       
   384         AddParserParameterL(*paramArray, KVersitParam8NamePrn());
       
   385         // Create a new proprety value from the reading names array
       
   386         CParserPropertyValue* readingPropValue =
       
   387             new(ELeave) CParserPropertyValueCDesCArray(readingArray);
       
   388         // nameArray is now owned by propertyValue
       
   389         CleanupStack::Pop(paramArray);
       
   390         CleanupStack::Pop(readingArray);
       
   391         CleanupStack::PushL(paramArray);
       
   392         AddPropertyToParserL(readingPropValue, KVersitTokenSOUND(), paramArray,
       
   393                              aParser);
       
   394         // The paramArray and propertyValue are popped
       
   395         // by the previous function call
       
   396     }
       
   397     else
       
   398     {
       
   399         // Clean the reading array
       
   400         CleanupStack::PopAndDestroy(readingArray);
       
   401     }
       
   402 }
       
   403 
       
   404 // -----------------------------------------------------------------------------
       
   405 // CPIMCardPropertyConverter::ConvertCDesCArrayPropertyL
       
   406 // Converts name and address arrays from a vCard to a PIM Contact Item
       
   407 // -----------------------------------------------------------------------------
       
   408 //
       
   409 void CPIMCardPropertyConverter::ConvertCDesCArrayPropertyL(
       
   410     const CPIMParserProperty& aProperty, // property to convert
       
   411     CPIMContactItem& aItem) // item to insert the field to
       
   412 {
       
   413     JELOG2(EPim);
       
   414     TPIMField field = aProperty.MatchContactField();
       
   415 
       
   416     if ((field != EPIMContactAddr) && (field != EPIMContactName) && (field
       
   417             != EPIMContactOrg) && (field != EPIMContactExtChildren))
       
   418     {
       
   419         // unsupported properties are silently discarded
       
   420         return;
       
   421     }
       
   422 
       
   423     CParserPropertyValueCDesCArray* propertyValue =
       
   424         static_cast<CParserPropertyValueCDesCArray*>(aProperty.Value());
       
   425     const CDesCArray* value = propertyValue->Value();
       
   426 
       
   427     // In ORG field, the Organizational name is the first item and the second
       
   428     // item is extended department name
       
   429     if (field == EPIMContactOrg)
       
   430     {
       
   431         TInt valueCount = value->Count();
       
   432         if (valueCount >= 1)
       
   433         {
       
   434             HBufC* orgValue = value->MdcaPoint(0).AllocLC();
       
   435             aItem.AddStringL(field, KPIMAttrNone, orgValue);
       
   436             CleanupStack::Pop(orgValue);
       
   437             // Get department from the array
       
   438             if (valueCount > 1)
       
   439             {
       
   440                 HBufC* department = value->MdcaPoint(1).AllocLC();
       
   441                 aItem.AddStringL(EPIMContactExtDepartment, KPIMAttrNone,
       
   442                                  department);
       
   443                 CleanupStack::Pop(department);
       
   444             }
       
   445         }
       
   446         return;
       
   447     }
       
   448     // Children is imported as a CDesCArray so we have to convert it here
       
   449     if (field == EPIMContactExtChildren && value->Count() >= 1)
       
   450     {
       
   451         // We are only interested about the first value
       
   452         HBufC* children = value->MdcaPoint(0).AllocLC();
       
   453         aItem.AddStringL(field, KPIMAttrNone, children);
       
   454         CleanupStack::Pop(children);
       
   455         return;
       
   456     }
       
   457 
       
   458     // Copy the array
       
   459     TInt elementCount = value->Count();
       
   460     CDesCArrayFlat* itemArray = new(ELeave) CDesCArrayFlat(elementCount);
       
   461     CleanupStack::PushL(itemArray);
       
   462     TInt i;
       
   463     for (i = 0; i < elementCount; i++)
       
   464     {
       
   465         itemArray->AppendL((*value)[i]);
       
   466     }
       
   467 
       
   468     // If we need more elements, add nulls
       
   469     TInt itemElementCount = iContactValidator.NumElementsL(field);
       
   470     TPtrC nullArrayElement(KPIMNullArrayElement);
       
   471     for (; i < itemElementCount; i++)
       
   472     {
       
   473         itemArray->AppendL(nullArrayElement);
       
   474     }
       
   475 
       
   476     TPIMAttribute attributes = KPIMAttrNone;
       
   477     // Usually people only have one name. However, both PIM api and
       
   478     // vCards allow two names: Formatted name is not supported anymore since
       
   479     // converting it is not unambiguous and it must not be supported by the
       
   480     // PIM API internal specification version 4.3. IMC's vCard specification
       
   481     // states that Formatted name is an optional field for vCard parsers.
       
   482     if (field == EPIMContactName && aItem.CountValuesL(EPIMContactName) > 0)
       
   483     {
       
   484         // we already have a name, so we just change the current one
       
   485         // NOTE: There can be name reading fields before the name array
       
   486         // elements are added so we have take care of it
       
   487         const CDesCArray& nameArray = aItem.GetStringArrayL(EPIMContactName, 0);
       
   488         TPtrC name(nameArray.MdcaPoint(EPIMContactExtFamilyNameReading));
       
   489         if (name != KPIMNullArrayElement)
       
   490         {
       
   491             // Delete empty item and add existing item
       
   492             itemArray->Delete(EPIMContactExtFamilyNameReading);
       
   493             itemArray->InsertL(EPIMContactExtFamilyNameReading, name);
       
   494         }
       
   495         name.Set(nameArray.MdcaPoint(EPIMContactExtGivenNameReading));
       
   496         if (name != KPIMNullArrayElement)
       
   497         {
       
   498             // Delete empty item and add existing item
       
   499             itemArray->Delete(EPIMContactExtGivenNameReading);
       
   500             itemArray->InsertL(EPIMContactExtGivenNameReading, name);
       
   501         }
       
   502 
       
   503         aItem.SetStringArrayL(EPIMContactName, 0, attributes, itemArray);
       
   504         CleanupStack::Pop(); // itemArray now owned by aItem
       
   505         return;
       
   506     }
       
   507     else
       
   508     {
       
   509         // address can have attributes
       
   510         attributes = aProperty.MatchHomeAndWorkAttributes();
       
   511     }
       
   512     aItem.AddStringArrayL(field, attributes, itemArray);
       
   513     CleanupStack::Pop(); // itemArray now owned by aItem
       
   514 }
       
   515 
       
   516 // -----------------------------------------------------------------------------
       
   517 // CPIMCardPropertyConverter::ConvertDateFieldL
       
   518 // Converts a date field from a PIM Contact Item to a CParserVCard.
       
   519 // -----------------------------------------------------------------------------
       
   520 //
       
   521 void CPIMCardPropertyConverter::ConvertDateFieldL(const CPIMItem& aItem, // item to convert from
       
   522         CParserVCard& aParser, // parser to insert the property to.
       
   523         TPIMContactField aField, // field to convert
       
   524         TInt aIndex) // index to the field
       
   525 {
       
   526     JELOG2(EPim);
       
   527     TVersitDateTime* versitDateTime = NULL;
       
   528     CParserPropertyValue* propertyValue = NULL;
       
   529     TPtrC8 propertyName(KNullDesC8);
       
   530 
       
   531     // Handle fields separately
       
   532     switch (aField)
       
   533     {
       
   534     case EPIMContactExtAnniversary:
       
   535     case EPIMContactBirthday:
       
   536     {
       
   537         const TPIMDate date = aItem.GetDateL(aField, aIndex);
       
   538         // Convert times to local time since UTC time designator is not
       
   539         // supported in anniversary and birthday fields
       
   540         RTz tzServer;
       
   541         User::LeaveIfError(tzServer.Connect());
       
   542         CleanupClosePushL(tzServer);
       
   543 
       
   544         // Create timezone converter
       
   545         CTzConverter* converter = CTzConverter::NewL(tzServer);
       
   546         CleanupStack::PushL(converter);
       
   547 
       
   548         TTime localTime(date);
       
   549         User::LeaveIfError(converter->ConvertToLocalTime(localTime));
       
   550         CleanupStack::PopAndDestroy(2); // converter, tzServer
       
   551 
       
   552         versitDateTime
       
   553         = new(ELeave) TVersitDateTime(date.DateTime(), TVersitDateTime::EIsMachineLocal);
       
   554 
       
   555         // Set specific property name
       
   556         if (aField == EPIMContactBirthday)
       
   557         {
       
   558             propertyName.Set(KVersitTokenBDAY);
       
   559         }
       
   560         else if (aField == EPIMContactExtAnniversary)
       
   561         {
       
   562             propertyName.Set(KVersitTokenAnniversary);
       
   563         }
       
   564         CleanupDeletePushL(versitDateTime);
       
   565         // Create new date property value
       
   566         propertyValue = new(ELeave) CParserPropertyValueDate(versitDateTime);
       
   567         break;
       
   568     }
       
   569     case EPIMContactRevision:
       
   570     {
       
   571         TPIMDate date = aItem.LastModified();
       
   572         versitDateTime
       
   573         = new(ELeave) TVersitDateTime(date.DateTime(), TVersitDateTime::EIsUTC);
       
   574         propertyName.Set(KVersitTokenREV);
       
   575         CleanupDeletePushL(versitDateTime);
       
   576         // Create new date and time property value
       
   577         propertyValue
       
   578         = new(ELeave) CParserPropertyValueDateTime(versitDateTime);
       
   579         break;
       
   580     }
       
   581     default:
       
   582     {
       
   583         User::Panic(KPIMPanicCategory, EPIMPanicUnsupportedDateField);
       
   584         break;
       
   585     }
       
   586     }
       
   587     // versitDateTime is now owned by propertyValue
       
   588     CleanupStack::Pop(versitDateTime);
       
   589     AddPropertyToParserL(propertyValue, propertyName, NULL, aParser);
       
   590     // The paramArray and propertyValue are popped by the previous function call
       
   591 }
       
   592 
       
   593 // -----------------------------------------------------------------------------
       
   594 // CPIMCardPropertyConverter::ConvertDatePropertyL
       
   595 // Converts a birthday from a vCard to a PIM Contact Item
       
   596 // -----------------------------------------------------------------------------
       
   597 //
       
   598 void CPIMCardPropertyConverter::ConvertDatePropertyL(
       
   599     const CPIMParserProperty& aProperty, // property to convert
       
   600     CPIMContactItem& aItem) // item to insert the field to
       
   601 {
       
   602     JELOG2(EPim);
       
   603     TPIMField field = aProperty.MatchContactField();
       
   604     switch (field)
       
   605     {
       
   606     case EPIMContactExtAnniversary:
       
   607     case EPIMContactBirthday:
       
   608     case EPIMContactRevision:
       
   609     {
       
   610         // All date property values are equal (in some way)
       
   611         CParserPropertyValueDateTime* value =
       
   612             static_cast<CParserPropertyValueDateTime*>(aProperty.Value());
       
   613         // Get versit date time object. Both date time properties
       
   614         // return TVersitDateTime so we don't care about the actual object
       
   615         const TVersitDateTime* vDateTime = value->Value();
       
   616         // Add new date to PIM item
       
   617         TPIMDate date(vDateTime->iDateTime);
       
   618         aItem.AddDateL(field, KPIMAttrNone, date);
       
   619         break;
       
   620     }
       
   621     default:
       
   622     {
       
   623         // Discard other fields
       
   624     }
       
   625     }
       
   626 }
       
   627 
       
   628 // -----------------------------------------------------------------------------
       
   629 // CPIMCardPropertyConverter::ConvertStringFieldL
       
   630 // Converts a string field from a PIM Item to vCard
       
   631 // -----------------------------------------------------------------------------
       
   632 //
       
   633 void CPIMCardPropertyConverter::ConvertStringFieldL(const CPIMItem& aItem, // item to convert from
       
   634         CParserVCard& aParser, // parser to write to
       
   635         TPIMContactField aField, // field to convert
       
   636         TInt aIndex) // index to the value in the field
       
   637 {
       
   638     JELOG2(EPim);
       
   639     // We'll gather all property parameters (attributes) to an array
       
   640     // which we give to the property in construction. It seems to be
       
   641     // the only way to give a property multiple parameters of same type.
       
   642     TPIMAttribute attributes = aItem.getAttributes(aField, aIndex);
       
   643     // Assistant tel field is mapped for its own field in s60, so
       
   644     // it must not be associated with the standard TEL field in vCards
       
   645     if (aField == EPIMContactTel && (attributes & EPIMContactAttrAsst) != 0)
       
   646     {
       
   647         const TDesC& asstTel = aItem.GetStringL(aField, aIndex);
       
   648         CParserPropertyValue* propertyValue = CParserPropertyValueHBufC::NewL(
       
   649                                                   asstTel);
       
   650         AddPropertyToParserL(propertyValue, KPIMVersitTokenASSTTEL(), NULL,
       
   651                              aParser);
       
   652         // Needed cleanup stack cleanup is done within the function
       
   653         return;
       
   654     }
       
   655     CPIMVCardParserParamArray* paramArray =
       
   656         new(ELeave) CPIMVCardParserParamArray(3);
       
   657     CleanupStack::PushL(paramArray);
       
   658 
       
   659     TPtrC8 propertyName; // mapped from field identifier
       
   660 
       
   661     switch (aField)
       
   662     {
       
   663     case EPIMContactEmail:
       
   664     {
       
   665         propertyName.Set(KVersitTokenEMAIL);
       
   666         AddParamHomeAndWorkL(attributes, *paramArray);
       
   667         // Contacts Model and PIM support PREF attribute, how ever
       
   668         // vCard specification does not. Thus we don't add it.
       
   669         break;
       
   670     }
       
   671     case EPIMContactNote:
       
   672     {
       
   673         propertyName.Set(KVersitTokenNOTE);
       
   674         break;
       
   675     }
       
   676     case EPIMContactTel:
       
   677     {
       
   678         propertyName.Set(KVersitTokenTEL);
       
   679         if ((attributes & EPIMContactAttrFax) != 0)
       
   680         {
       
   681             AddParserParameterL(*paramArray, KVersitParam8Fax());
       
   682         }
       
   683         if ((attributes & EPIMContactAttrMobile) != 0)
       
   684         {
       
   685             AddParserParameterL(*paramArray, KVersitParam8Cell());
       
   686         }
       
   687         if ((attributes & EPIMContactAttrPager) != 0)
       
   688         {
       
   689             AddParserParameterL(*paramArray, KVersitParam8Pager());
       
   690         }
       
   691         if ((attributes & (EPIMContactAttrPager | EPIMContactAttrFax
       
   692                            | EPIMContactAttrSms | EPIMContactAttrAuto
       
   693                            | EPIMContactAttrExtVideoCall)) == 0)
       
   694         {
       
   695             AddParserParameterL(*paramArray, KVersitParam8Voice());
       
   696         }
       
   697         if ((attributes & (EPIMContactAttrPreferred)) != 0)
       
   698         {
       
   699             AddParserParameterL(*paramArray, KVersitParam8Pref());
       
   700         }
       
   701         if ((attributes & EPIMContactAttrAuto) != 0)
       
   702         {
       
   703             AddParserParameterL(*paramArray, KVersitParam8Car());
       
   704         }
       
   705         if ((attributes & EPIMContactAttrExtVideoCall) != 0)
       
   706         {
       
   707             AddParserParameterL(*paramArray, KVersitParam8Video());
       
   708         }
       
   709         // Contacts Model and PIM support SMS attribute, how ever
       
   710         // vCard specification does not. Thus we ignore it.
       
   711         // ATTR_OTHER is also ingored because Contacts Model doesn't
       
   712         // provide anything where we could map ATTR_OTHER
       
   713 
       
   714         // Add HOME or WORK after all other attributes
       
   715         AddParamHomeAndWorkL(attributes, *paramArray);
       
   716         break;
       
   717     }
       
   718     case EPIMContactTitle:
       
   719     {
       
   720         propertyName.Set(KVersitTokenTITLE);
       
   721         break;
       
   722     }
       
   723     case EPIMContactUrl:
       
   724     {
       
   725         propertyName.Set(KVersitTokenURL);
       
   726         AddParamHomeAndWorkL(attributes, *paramArray);
       
   727         break;
       
   728     }
       
   729     case EPIMContactNickname:
       
   730     {
       
   731         propertyName.Set(KPIMVersitTokenNICKNAME);
       
   732         break;
       
   733     }
       
   734     case EPIMContactExtDtmf:
       
   735     {
       
   736         propertyName.Set(KPIMVersitTokenDTMF);
       
   737         break;
       
   738     }
       
   739     case EPIMContactExtWvUserId:
       
   740     {
       
   741         propertyName.Set(KPIMVersitTokenWVID);
       
   742         break;
       
   743     }
       
   744     case EPIMContactExtSpouse:
       
   745     {
       
   746         propertyName.Set(KVersitTokenSpouse);
       
   747         break;
       
   748     }
       
   749     case EPIMContactExtChildren:
       
   750     {
       
   751         propertyName.Set(KVersitTokenChildren);
       
   752         break;
       
   753     }
       
   754     case EPIMContactExtAssistantName:
       
   755     {
       
   756         propertyName.Set(KVersitTokenAssistant);
       
   757         break;
       
   758     }
       
   759     case EPIMContactExtVoip:
       
   760     case EPIMContactExtSip:
       
   761     case EPIMContactExtPTT:
       
   762     case EPIMContactExtSWIS:
       
   763     {
       
   764         TPtrC8 paramName;
       
   765         propertyName.Set(KPIMVersitTokenSIP);
       
   766         // VOIP is mapped to a subfield of X-SIP
       
   767         if (aField == EPIMContactExtVoip)
       
   768         {
       
   769             paramName.Set(KPIMVersitTokenVoip);
       
   770         }
       
   771         // PTT is mapped to a subfield of X-SIP
       
   772         else if (aField == EPIMContactExtPTT)
       
   773         {
       
   774             paramName.Set(KPIMVersitTokenPoc);
       
   775         }
       
   776         // SWIS is mapped to a subfield of X-SIP
       
   777         else if (aField == EPIMContactExtSWIS)
       
   778         {
       
   779             paramName.Set(KPIMVersitTokenSwis);
       
   780         }
       
   781         if (aField != EPIMContactExtSip)
       
   782         {
       
   783             AddParserParameterL(*paramArray, paramName);
       
   784         }
       
   785 
       
   786         AddParamHomeAndWorkL(attributes, *paramArray);
       
   787         // Contacts Model and PIM support PREF attribute, how ever
       
   788         // vCard specification does not. Thus we don't add it.
       
   789         break;
       
   790     }
       
   791     case EPIMContactUid:
       
   792     {
       
   793         propertyName.Set(KVersitTokenUID);
       
   794         break;
       
   795     }
       
   796     default:
       
   797     {
       
   798         User::Panic(KPIMPanicCategory, EPIMPanicUnsupportedStringField);
       
   799     }
       
   800     }
       
   801 
       
   802     const TDesC& pimStringValue = aItem.GetStringL(aField, aIndex);
       
   803 
       
   804     CParserPropertyValue* propertyValue = CParserPropertyValueHBufC::NewL(
       
   805                                               pimStringValue);
       
   806     AddPropertyToParserL(propertyValue, propertyName, paramArray, aParser);
       
   807     // The paramArray and propertyValue are popped by the previous function call
       
   808 }
       
   809 
       
   810 // -----------------------------------------------------------------------------
       
   811 // CPIMCardPropertyConverter::AddParserParameterL
       
   812 // Adds new parser parameter to the parameter array
       
   813 // -----------------------------------------------------------------------------
       
   814 //
       
   815 void CPIMCardPropertyConverter::AddParserParameterL(
       
   816     CPIMVCardParserParamArray& aArrayOfParams, const TPtrC8 aParamName)
       
   817 {
       
   818     JELOG2(EPim);
       
   819     // Create a new parameter from the name
       
   820     CParserParam* newParam = CParserParam::NewL(aParamName, KNullDesC8);
       
   821     CleanupStack::PushL(newParam);
       
   822     // Add parameter to the param array
       
   823     aArrayOfParams.AppendL(newParam);
       
   824     // newParam is now owned by the parameter array
       
   825     CleanupStack::Pop(newParam);
       
   826 }
       
   827 
       
   828 // -----------------------------------------------------------------------------
       
   829 // CPIMCardPropertyConverter::ConvertStringPropertyL
       
   830 // Converts a string property from a vCard to a PIM Contact Item
       
   831 // -----------------------------------------------------------------------------
       
   832 //
       
   833 void CPIMCardPropertyConverter::ConvertStringPropertyL(
       
   834     const CPIMParserProperty& aProperty, // property to convert
       
   835     CPIMContactItem& aItem) // item to insert the field to
       
   836 {
       
   837     JELOG2(EPim);
       
   838     TPIMField field = aProperty.MatchContactField();
       
   839     TPIMAttribute attributes = KPIMAttrNone;
       
   840 
       
   841     if (field == KErrNotFound)
       
   842     {
       
   843         return;
       
   844     }
       
   845 
       
   846     CParserPropertyValueHBufC* propertyValue =
       
   847         static_cast<CParserPropertyValueHBufC*>(aProperty.Value());
       
   848     HBufC* value = propertyValue->TakeValueOwnership();
       
   849     CleanupStack::PushL(value);
       
   850 
       
   851     switch (field)
       
   852     {
       
   853     case EPIMContactUrl:
       
   854     case EPIMContactEmail:
       
   855         // vCard EMAIL does not support PREF
       
   856     {
       
   857         attributes = aProperty.MatchHomeAndWorkAttributes();
       
   858         break;
       
   859     }
       
   860     case EPIMContactTel:
       
   861     {
       
   862         // Assistant phone is not an attribute in TEL field
       
   863         // it must be handled separately
       
   864         if (aProperty.Name().CompareF(KPIMVersitTokenASSTTEL) == 0)
       
   865         {
       
   866             attributes = EPIMContactAttrAsst;
       
   867         }
       
   868         else
       
   869         {
       
   870             attributes = aProperty.MatchAllAttributes();
       
   871         }
       
   872         break;
       
   873     }
       
   874     case EPIMContactExtVoip:
       
   875     {
       
   876         // VOIP field can have parameters HOME or WORK
       
   877         attributes = aProperty.MatchHomeAndWorkAttributes();
       
   878         break;
       
   879     }
       
   880     default:
       
   881     {
       
   882         // no attributes
       
   883     }
       
   884     }
       
   885     aItem.AddStringL(field, attributes, value);
       
   886     CleanupStack::Pop(value);
       
   887 }
       
   888 
       
   889 // -----------------------------------------------------------------------------
       
   890 // CPIMCardPropertyConverter::ConvertPhotoFieldL
       
   891 // Converts a photo field from a PIM Contact Item to a vCard
       
   892 // -----------------------------------------------------------------------------
       
   893 //
       
   894 void CPIMCardPropertyConverter::ConvertPhotoFieldL(const CPIMItem& aItem, // item to convert from
       
   895         CParserVCard& aParser, // parser to write to
       
   896         TPIMContactField aField, // field to convert
       
   897         TInt aIndex) // index to the field
       
   898 {
       
   899     JELOG2(EPim);
       
   900     const CPIMByteArray& byteArray = aItem.GetBinaryRawL(aField, aIndex);
       
   901 
       
   902     const TUint8& byteRef = byteArray.At(0);
       
   903     const TUint8* bytePtr = &byteRef;
       
   904     TPtrC8 data(bytePtr, byteArray.Count());
       
   905 
       
   906     CParserPropertyValue* propertyValue =
       
   907         CParserPropertyValueBinary::NewL(data);
       
   908     AddPropertyToParserL(propertyValue, KVersitTokenPHOTO(), NULL, aParser);
       
   909     // The paramArray and propertyValue are popped by the previous function call
       
   910 }
       
   911 
       
   912 // -----------------------------------------------------------------------------
       
   913 // CPIMCardPropertyConverter::ConvertPhotoPropertyL
       
   914 // Converts a photo field from a vCard to a PIM Contact Item
       
   915 // -----------------------------------------------------------------------------
       
   916 //
       
   917 void CPIMCardPropertyConverter::ConvertPhotoPropertyL(
       
   918     const CPIMParserProperty& aProperty, // property to convert
       
   919     CPIMContactItem& aItem) // item to insert the field to
       
   920 {
       
   921     JELOG2(EPim);
       
   922     if (aProperty.Name().CompareF(KVersitTokenPHOTO) != 0)
       
   923     {
       
   924         // Unsupported binary property, silently discarded
       
   925         return;
       
   926     }
       
   927 
       
   928     CParserPropertyValueBinary* propertyValue =
       
   929         static_cast<CParserPropertyValueBinary*>(aProperty.Value());
       
   930     const CBufSeg* value = propertyValue->Value();
       
   931 
       
   932     TInt binarySize = value->Size();
       
   933     CPIMByteArray* byteArray = new(ELeave) CPIMByteArray(binarySize);
       
   934     CleanupStack::PushL(byteArray);
       
   935     byteArray->ResizeL(binarySize);
       
   936     TUint8& byteRef = byteArray->At(0);
       
   937     TUint8* bytePtr = &byteRef;
       
   938 
       
   939     value->Read(0, static_cast<TAny*>(bytePtr), binarySize);
       
   940 
       
   941     aItem.AddBinaryRawL(EPIMContactPhoto, KPIMAttrNone, byteArray);
       
   942     CleanupStack::Pop(byteArray); // byteArray now owned by aItem
       
   943 }
       
   944 
       
   945 // -----------------------------------------------------------------------------
       
   946 // CPIMCardPropertyConverter::ConvertClassFieldL
       
   947 // Converts a CLASS field from a PIM Contact Item to a vCard
       
   948 // -----------------------------------------------------------------------------
       
   949 //
       
   950 void CPIMCardPropertyConverter::ConvertClassFieldL(const CPIMItem& aItem,
       
   951         CParserVCard& aParser, TPIMContactField aField, TInt aIndex)
       
   952 {
       
   953     JELOG2(EPim);
       
   954     TInt classIntValue = aItem.getInt(aField, aIndex);
       
   955     TPtrC classStringValue(KPIMClassStringConfidential());
       
   956     switch (classIntValue)
       
   957     {
       
   958     case EPIMContactClassConfidential:
       
   959     {
       
   960         classStringValue.Set(KPIMClassStringConfidential());
       
   961         break;
       
   962     }
       
   963     case EPIMContactClassPrivate:
       
   964     {
       
   965         classStringValue.Set(KPIMClassStringPrivate());
       
   966         break;
       
   967     }
       
   968     case EPIMContactClassPublic:
       
   969     {
       
   970         classStringValue.Set(KPIMClassStringPublic());
       
   971         break;
       
   972     }
       
   973     default:
       
   974     {
       
   975         __ASSERT_DEBUG(EFalse, User::Invariant());
       
   976         break;
       
   977     }
       
   978     }
       
   979     CParserPropertyValue* propertyValue = CParserPropertyValueHBufC::NewL(
       
   980                                               classStringValue);
       
   981     AddPropertyToParserL(propertyValue, KVersitTokenClass(), NULL, aParser);
       
   982     // The paramArray and propertyValue are popped by the previous function call
       
   983 }
       
   984 
       
   985 // -----------------------------------------------------------------------------
       
   986 // CPIMCardPropertyConverter::ConvertClassPropertyL
       
   987 // Converts CLASS property to a PIM Event item.
       
   988 // -----------------------------------------------------------------------------
       
   989 //
       
   990 void CPIMCardPropertyConverter::ConvertClassPropertyL(
       
   991     const CPIMParserProperty& aProperty, CPIMContactItem& aItem)
       
   992 {
       
   993     JELOG2(EPim);
       
   994     CParserPropertyValueHBufC* propertyValue =
       
   995         static_cast<CParserPropertyValueHBufC*>(aProperty.Value());
       
   996 
       
   997     const TPtrC classStringPtr = propertyValue->Value();
       
   998     TInt classInt = KErrCorrupt;
       
   999 
       
  1000     if (classStringPtr.CompareF(KPIMClassStringPublic) == 0)
       
  1001     {
       
  1002         classInt = EPIMContactClassPublic;
       
  1003     }
       
  1004     else if (classStringPtr.CompareF(KPIMClassStringPrivate) == 0)
       
  1005     {
       
  1006         classInt = EPIMContactClassPrivate;
       
  1007     }
       
  1008     else if (classStringPtr.CompareF(KPIMClassStringConfidential) == 0)
       
  1009     {
       
  1010         classInt = EPIMContactClassConfidential;
       
  1011     }
       
  1012     // else the class value in the originating vCalendar is flawed - ignore
       
  1013 
       
  1014     if (classInt != KErrCorrupt)
       
  1015     {
       
  1016         aItem.addInt(EPIMContactClass, KPIMAttrNone, classInt);
       
  1017     }
       
  1018 }
       
  1019 
       
  1020 // -----------------------------------------------------------------------------
       
  1021 // CPIMCardPropertyConverter::ConvertOrganisationalFieldsL
       
  1022 // Converts organisational fields from PIM item to CParserVCard
       
  1023 // -----------------------------------------------------------------------------
       
  1024 //
       
  1025 void CPIMCardPropertyConverter::ConvertOrganisationalFieldsL(
       
  1026     const CPIMItem& aItem, CParserVCard& aParser, TPIMContactField /*aField*/,
       
  1027     TInt /*aIndex*/)
       
  1028 {
       
  1029     JELOG2(EPim);
       
  1030     // Check that the field is not converted twice (e.g one of the
       
  1031     // organisational fields have been already converted and caused
       
  1032     // other field to be converted also
       
  1033     CArrayPtr<CParserProperty>* props = aParser.ArrayOfProperties(EFalse);
       
  1034     if (props)
       
  1035     {
       
  1036         TInt propCount = props->Count();
       
  1037         for (TInt i = 0; i < propCount; i++)
       
  1038         {
       
  1039             const CParserProperty* property = props->At(i);
       
  1040             if (property->Name().CompareF(KVersitTokenORG) == 0)
       
  1041             {
       
  1042                 return;
       
  1043             }
       
  1044         }
       
  1045     }
       
  1046 
       
  1047     // Create array from organisation and department fields
       
  1048     CDesCArray* orgArray = new(ELeave) CDesCArrayFlat(2);
       
  1049     CleanupStack::PushL(orgArray);
       
  1050     if (aItem.CountValuesL(EPIMContactOrg) > 0)
       
  1051     {
       
  1052         const TDesC& org = aItem.GetStringL(EPIMContactOrg, 0);
       
  1053         orgArray->AppendL(org);
       
  1054     }
       
  1055     else
       
  1056     {
       
  1057         orgArray->AppendL(KNullDesC);
       
  1058     }
       
  1059     // Department field is after organisational unit
       
  1060     if (aItem.CountValuesL(EPIMContactExtDepartment) > 0)
       
  1061     {
       
  1062         const TDesC& dep = aItem.GetStringL(EPIMContactExtDepartment, 0);
       
  1063         orgArray->AppendL(dep);
       
  1064     }
       
  1065     else
       
  1066     {
       
  1067         orgArray->AppendL(KNullDesC);
       
  1068     }
       
  1069 
       
  1070     CParserPropertyValue* propertyValue =
       
  1071         new(ELeave) CParserPropertyValueCDesCArray(orgArray);
       
  1072     CleanupStack::Pop(orgArray); // orgArray now owned by propertyValue
       
  1073     AddPropertyToParserL(propertyValue, KVersitTokenORG(), NULL, aParser);
       
  1074     // The paramArray and propertyValue are popped by the previous function call
       
  1075 }
       
  1076 
       
  1077 // -----------------------------------------------------------------------------
       
  1078 // CPIMCardPropertyConverter::ConvertNameReadingFieldL
       
  1079 // Converts name reading fields from vCard to PIM item
       
  1080 // -----------------------------------------------------------------------------
       
  1081 //
       
  1082 void CPIMCardPropertyConverter::ConvertNameReadingFieldL(
       
  1083     const CPIMParserProperty& aProperty, CPIMContactItem& aItem)
       
  1084 {
       
  1085     JELOG2(EPim);
       
  1086     TInt nameCount = iContactValidator.NumElementsL(EPIMContactName);
       
  1087 
       
  1088     // Name reading fields come in a HBufC property value although they
       
  1089     // are in an array property value and SHOULD come in as an array.
       
  1090     // So, we have to generate an array property from the HBufC proprety
       
  1091     CParserPropertyValueHBufC* propertyValue =
       
  1092         static_cast<CParserPropertyValueHBufC*>(aProperty.Value());
       
  1093     HBufC* value = propertyValue->TakeValueOwnership();
       
  1094     CleanupStack::PushL(value);
       
  1095     // PIM parser to access protected methods
       
  1096     CPIMVCardParser* parser = CPIMVCardParser::NewLC();
       
  1097     CDesCArray* readingValues = parser->MakePropertyValueCDesCArrayL(
       
  1098                                     value->Des());
       
  1099     CleanupStack::PopAndDestroy(2, value); // parser
       
  1100     CleanupStack::PushL(readingValues);
       
  1101 
       
  1102     // Array for the new name elements
       
  1103     CDesCArray* newNameArray = new(ELeave) CDesCArrayFlat(nameCount);
       
  1104     CleanupStack::PushL(newNameArray);
       
  1105     // Old elements exist
       
  1106     if (aItem.CountValuesL(EPIMContactName) > 0)
       
  1107     {
       
  1108         const CDesCArray& nameArray = aItem.GetStringArrayL(EPIMContactName, 0);
       
  1109         for (TInt i = 0; i < nameCount; i++)
       
  1110         {
       
  1111             TPtrC element(nameArray.MdcaPoint(i));
       
  1112             newNameArray->AppendL(element);
       
  1113         }
       
  1114         // Add array elements. If the array count is larger than zero
       
  1115         // it indicates that at least the Last name reading field is present
       
  1116         if (readingValues->Count() > 0)
       
  1117         {
       
  1118             // Remove old value and add new
       
  1119             newNameArray->Delete(EPIMContactExtFamilyNameReading);
       
  1120             newNameArray->InsertL(EPIMContactExtFamilyNameReading,
       
  1121                                   readingValues->MdcaPoint(0));
       
  1122         }
       
  1123         // If the array count is larger than one it indicates that
       
  1124         // the First name reading is also present
       
  1125         if (readingValues->Count() > 1)
       
  1126         {
       
  1127             newNameArray->Delete(EPIMContactExtGivenNameReading);
       
  1128             newNameArray->InsertL(EPIMContactExtGivenNameReading,
       
  1129                                   readingValues->MdcaPoint(1));
       
  1130         }
       
  1131 
       
  1132         // Set new string array for the contact name field
       
  1133         aItem.SetStringArrayL(EPIMContactName, 0, KPIMAttrNone, newNameArray);
       
  1134     }
       
  1135     // No old name array
       
  1136     else
       
  1137     {
       
  1138         // Create a new array and append name reading values to it
       
  1139         for (TInt i = 0; i < nameCount; i++)
       
  1140         {
       
  1141             newNameArray->AppendL(KPIMNullArrayElement);
       
  1142         }
       
  1143         // Add array elements. If the array count is larger than zero
       
  1144         // it indicates that at least the Last name reading field is present
       
  1145         if (readingValues->Count() > 0)
       
  1146         {
       
  1147             // Remove old value and add new
       
  1148             newNameArray->Delete(EPIMContactExtFamilyNameReading);
       
  1149             newNameArray->InsertL(EPIMContactExtFamilyNameReading,
       
  1150                                   readingValues->MdcaPoint(0));
       
  1151         }
       
  1152         // If the array count is larger than one it indicates that
       
  1153         // the First name reading is also present
       
  1154         if (readingValues->Count() > 1)
       
  1155         {
       
  1156             newNameArray->Delete(EPIMContactExtGivenNameReading);
       
  1157             newNameArray->InsertL(EPIMContactExtGivenNameReading,
       
  1158                                   readingValues->MdcaPoint(1));
       
  1159         }
       
  1160         // Add new string array for the cotnact name field
       
  1161         aItem.AddStringArrayL(EPIMContactName, KPIMAttrNone, newNameArray);
       
  1162     }
       
  1163 
       
  1164     CleanupStack::Pop(newNameArray);
       
  1165     CleanupStack::PopAndDestroy(readingValues);
       
  1166 }
       
  1167 
       
  1168 // -----------------------------------------------------------------------------
       
  1169 // CPIMCardPropertyConverter::AddPropertyToParserL
       
  1170 // adds a new property value to the parser. NOTE that the property value
       
  1171 // -----------------------------------------------------------------------------
       
  1172 //
       
  1173 void CPIMCardPropertyConverter::AddPropertyToParserL(
       
  1174     CParserPropertyValue* aPropertyValue, const TDesC8& aPropertyName,
       
  1175     CPIMVCardParserParamArray* aArrayOfParams, CParserVCard& aParser)
       
  1176 {
       
  1177     JELOG2(EPim);
       
  1178     // Add property value to the cleanup stack. It should not be added
       
  1179     // before this call. This function is an exception and reduces much code
       
  1180     CleanupStack::PushL(aPropertyValue);
       
  1181     // Create a new parser property from the property value, its name and
       
  1182     // array of parameters. If there are no parameters, the aArrayOfParams
       
  1183     // should be NULL and the parser property will be generated without params
       
  1184     CParserProperty* property = CParserProperty::NewL(*aPropertyValue,
       
  1185                                 aPropertyName, aArrayOfParams);
       
  1186     // property takes ownership of the property value
       
  1187     CleanupStack::Pop(aPropertyValue);
       
  1188     // Pop aArrayOfParams if it is not NULL
       
  1189     if (aArrayOfParams)
       
  1190     {
       
  1191         CleanupStack::Pop(aArrayOfParams);
       
  1192     }
       
  1193     // NOTE: property MUST not be pushed to the cleanup stack since the
       
  1194     // AddPropertyL pushes it right away to the cleanup stack. So, we must not
       
  1195     // push it here to avoid duplicate stack pointers
       
  1196     aParser.AddPropertyL(property);
       
  1197     // Property is now owned by the parser but we do not have to pop it
       
  1198 }
       
  1199 
       
  1200 // End of file