phonebookengines/VirtualPhonebook/VPbkVCardEng/src/CVPbkVCardPropertyExporter.cpp
branchRCL_3
changeset 63 f4a778e096c2
child 64 c1e8ba0c2b16
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/VirtualPhonebook/VPbkVCardEng/src/CVPbkVCardPropertyExporter.cpp	Wed Sep 01 12:29:52 2010 +0100
@@ -0,0 +1,775 @@
+/*
+* Copyright (c) 2006-2007 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:  Exporting the contact field from contact to 
+*                CParserProperty field
+*
+*/
+
+
+#include "CVPbkVCardPropertyExporter.h"
+#include "CVPbkVCardParserParamArray.h"
+#include "CVPbkVCardFieldTypeProperty.h"
+#include "CVPbkVCardIdNameMapping.h"
+#include "VPbkVCardEngError.h"
+#include "CVPbkVCardData.h"
+#include <MVPbkContactStore.h>
+#include <MVPbkBaseContactField.h>
+#include <MVPbkStoreContact.h>
+#include <MVPbkStoreContactFieldCollection.h>
+#include <TVPbkFieldVersitProperty.h>
+#include <MVPbkContactFieldTextData.h>
+#include <MVPbkContactFieldUriData.h>
+#include <MVPbkContactFieldDateTimeData.h>
+#include <MVPbkContactFieldBinaryData.h>
+#include <VPbkError.h>
+#include <MVPbkSingleContactOperationObserver.h>
+#include <CVPbkContactManager.h>
+#include <MVPbkContactAttributeManager.h>
+#include <CVPbkDefaultAttribute.h>
+#include <CVPbkLocalVariationManager.h>
+
+// System includes
+#include <vcard.h>
+#include <bldvariant.hrh>
+
+// Debug includes
+#include <VPbkDebug.h>
+
+#include <centralrepository.h> 
+#include <MVPbkStoreContactProperties.h>
+
+// CONSTANTS
+const TInt KNsmlDsGeoField = 0x0000;  //  defined in DS cenrep
+const TUid KCRUidGeoFieldInternalKeys = { 0x20022EE1 };  // 0x20022EE1 defined in DS cenrep
+
+_LIT8(KGEO, "GEO");
+_LIT8(KREV, "REV");
+
+
+
+namespace
+    {
+    _LIT8(KPropEncoding, "ENCODING");
+    _LIT8(KPropBase64, "BASE64");
+    _LIT8(KPropType, "TYPE");
+    _LIT(KFormatJPEG, "JPEG");
+    _LIT8(KPropPREF, "PREF");
+    const TInt KOne = 1;
+    }
+
+CVPbkVCardPropertyExporter* CVPbkVCardPropertyExporter::NewLC(
+            CVPbkVCardData& aData,
+            const MVPbkStoreContact* aSourceItem,
+            RWriteStream& aDestStream,
+            MVPbkSingleContactOperationObserver& aObserver,
+            const TBool aBeamed)
+    {
+    CVPbkVCardPropertyExporter* self =
+        new (ELeave) CVPbkVCardPropertyExporter(
+            aData,
+            aSourceItem,
+            aDestStream,
+            aObserver,
+            aBeamed);
+    CleanupStack::PushL( self );
+    self->ConstructL(aData);
+    return self;
+    }
+
+CVPbkVCardPropertyExporter::CVPbkVCardPropertyExporter(
+            CVPbkVCardData& aData,
+            const MVPbkStoreContact* aSourceItem,
+            RWriteStream& aDestStream,
+            MVPbkSingleContactOperationObserver& aObserver,
+            const TBool aBeamed)
+    :   CVPbkVCardActiveIncremental( EPriorityStandard,
+                                     *this,
+                                     aData,
+                                     aObserver),
+        iContact ( aSourceItem ),
+        iDestinationStream( aDestStream ),
+        iCurrentPropertyIndex( 0 ),
+        iMaxPropertyCount( aData.Properties().Count() ),
+        iState( EExporting ),
+        iMaskedFieldsArray(aData.GetMaskedFields()),
+        iBeamed(aBeamed)
+    {
+    }
+
+CVPbkVCardPropertyExporter* CVPbkVCardPropertyExporter::NewLC(
+            CVPbkVCardData& aData,
+            RWriteStream& aDestStream,
+            MVPbkSingleContactOperationObserver& aObserver,
+            const TBool aBeamed)
+    {
+    CVPbkVCardPropertyExporter* self =
+        new (ELeave) CVPbkVCardPropertyExporter(
+            aData,
+            aDestStream,
+            aObserver,
+            aBeamed);
+    CleanupStack::PushL( self );
+    self->ConstructL(aData);
+    return self;
+    }
+
+CVPbkVCardPropertyExporter::CVPbkVCardPropertyExporter(
+            CVPbkVCardData& aData,
+            RWriteStream& aDestStream,
+            MVPbkSingleContactOperationObserver& aObserver,
+            const TBool aBeamed)
+    :   CVPbkVCardActiveIncremental( EPriorityStandard,
+                                     *this,
+                                     aData,
+                                     aObserver),
+        iDestinationStream( aDestStream ),
+        iCurrentPropertyIndex( 0 ),
+        iMaxPropertyCount( aData.Properties().Count() ),
+        iState( ECreatingRetriever ),
+        iMaskedFieldsArray(aData.GetMaskedFields()),
+        iBeamed(aBeamed)
+    {
+    }
+
+CVPbkVCardPropertyExporter::~CVPbkVCardPropertyExporter()
+    {
+    iValues.ResetAndDestroy();
+    delete iOwnedContact;
+    delete iOperation;
+    delete iParser;
+    delete iOwncardHandler;
+    delete iGroupcardHandler;
+    }
+
+void CVPbkVCardPropertyExporter::ExportFieldL( CVPbkVCardFieldTypeProperty& aVCardProperty )
+    {
+    iVCardProperty = &aVCardProperty;
+    
+   if ( iVCardProperty->Name().Compare(KGEO) == 0 )
+   {
+   	   	        // Read from cenrep	
+	      CRepository* repository = CRepository::NewLC( KCRUidGeoFieldInternalKeys );
+	      TBool geoFeatureValue(1); 
+	      // Get the geo feature value..
+	      TInt err = repository->Get( KNsmlDsGeoField, geoFeatureValue );
+	      User::LeaveIfError(err);
+	      CleanupStack::PopAndDestroy(repository);
+	      if (!geoFeatureValue)
+	        {
+	          return; //no Need to add GEO field during Sync/BT
+	        }
+   }  
+    
+    // If the current operation is a beamed export
+    if (iBeamed)
+    {
+        TInt count(iMaskedFieldsArray ? iMaskedFieldsArray->Count() : 0);
+        TInt val(-1);
+        for (TInt i(0); i < count; i++)
+        {
+            val = iVCardProperty->Name().Find( (*iMaskedFieldsArray)[i] );
+            if (0 == val)
+            {
+                // This is a masked field
+                return;
+            }
+        }
+    }
+    
+    GetValuesFromIndexedPropertiesL( iVCardProperty->Count() == KOne );
+    }
+
+void CVPbkVCardPropertyExporter::GetValuesFromIndexedPropertiesL(
+    TBool aSingleItem )
+    {
+    CVPbkVCardParserParamArray* params = NULL;
+    TInt findIndex( 0 );
+
+    if ( aSingleItem )
+        {
+        TBool doContinue( ETrue );
+        const TVPbkVCardIndexedProperty& indexedProperty =
+            iVCardProperty->IndexedPropertyAt( 0 );
+
+        while( doContinue )
+            {
+            InitDataL();
+            params =
+                new (ELeave) CVPbkVCardParserParamArray( KOne );
+            CleanupStack::PushL( params );
+
+            doContinue = GetSingleValueAndParamsL( indexedProperty,
+                                                   *params,
+                                                   findIndex );
+            ++findIndex;
+            CleanupStack::Pop( params );
+            // The params is pushed straight back to the CleanupStack in AddPropertyParserL
+            // unless AddPropertyToParserL returns EFalse
+            if( !AddPropertyToParserL( iValues, params ) )
+                {
+                delete params;
+                params = NULL;
+                }
+            }
+        }
+    else
+        {
+        TInt indexedPropertyCount( iVCardProperty->Count() );
+        InitDataL();
+        params =
+            new (ELeave) CVPbkVCardParserParamArray( indexedPropertyCount );
+        CleanupStack::PushL( params );
+
+        for ( TInt i = 0; i < indexedPropertyCount; ++i )
+            {
+            const TVPbkVCardIndexedProperty& indexedProperty =
+                iVCardProperty->IndexedPropertyAt( i );
+            findIndex = 0;
+            GetSingleValueAndParamsL( indexedProperty, *params, findIndex );
+            }
+
+        CleanupStack::Pop( params );
+        // The params are pushed straight back to the CleanupStack in 
+        // AddPropertyParserL unless AddPropertyToParserL returns EFalse
+        if( !AddPropertyToParserL( iValues, params ) )
+            {
+            delete params;
+            params = NULL;
+            }
+        }
+    }
+
+TBool CVPbkVCardPropertyExporter::GetSingleValueAndParamsL(
+    const TVPbkVCardIndexedProperty& aIndexedProperty,
+    CVPbkVCardParserParamArray& aParamArray,
+    TInt& aFindIndex )
+    {
+    MVPbkStoreContactField* field =
+        FindFieldFromContact( aIndexedProperty, aFindIndex );
+    if( !field )
+        {
+        return EFalse;
+        }
+    // Fetch field value and additional params
+    CParserPropertyValue* value = FetchDataFromFieldL( *field, aParamArray );
+    if( !value )
+        {
+        return ETrue;
+        }
+    CleanupStack::PushL( value );
+    TInt index ( aIndexedProperty.Index() );
+    iValues[ index ] = value;
+    CleanupStack::Pop( value );
+
+    return ETrue;
+    }
+
+void CVPbkVCardPropertyExporter::ConstructL(CVPbkVCardData& aData)
+    {
+    iParser = CParserVCard::NewL();
+    
+    iOwncardHandler = CVPbkOwnCardHandler::NewL(aData);
+    iGroupcardHandler = CVPbkGroupCardHandler::NewL(aData);
+    }
+
+MVPbkStoreContactField*
+CVPbkVCardPropertyExporter::FindFieldFromContact(
+    const TVPbkVCardIndexedProperty& aIndexedProperty, TInt& aIndex )
+    {
+    const MVPbkFieldType* exportPropertyType =
+        aIndexedProperty.FindMatch( iData.SupportedFieldTypes());
+    
+    TInt fieldCount = iContact->Fields().FieldCount();
+    for ( TInt n = aIndex; n < fieldCount; ++n )
+        {
+        // We have to find out additional properties of the contact field so
+        // we need non-const reference of the field class.
+        MVPbkStoreContactField& sourceField =
+            const_cast<MVPbkStoreContact*>( iContact )->Fields().FieldAt( n );
+
+        const TInt maxMatchPriority = 
+                    iData.SupportedFieldTypes().MaxMatchPriority();
+        for ( TInt matchPriority = 0;
+             matchPriority <= maxMatchPriority;
+             ++matchPriority )
+            {
+            const MVPbkFieldType* sourceFieldType =
+                sourceField.MatchFieldType( matchPriority );
+            if ( sourceFieldType &&
+                 exportPropertyType->IsSame( *sourceFieldType ) )
+                {
+                aIndex = n;
+                return &sourceField;
+                }
+            }
+        }
+    return NULL;
+    }
+
+CParserPropertyValue* CVPbkVCardPropertyExporter::FetchDataFromFieldL(
+    MVPbkStoreContactField& aField, CVPbkVCardParserParamArray& aParameters )
+    {
+    CParserPropertyValue* value = NULL;
+    TVPbkFieldStorageType storageType = aField.FieldData().DataType();
+    switch ( storageType )
+        {
+        case EVPbkFieldStorageTypeText:
+            {
+            value = GetExportTextValueL( aField );
+            break;
+            }
+            
+         case EVPbkFieldStorageTypeUri:
+            {
+            value = GetExportUriValueL( aField );
+            break;
+            }    
+
+        case EVPbkFieldStorageTypeBinary:
+            {
+            value = GetExportBinaryValueL(aField, aParameters);
+            break;
+            }
+
+        case EVPbkFieldStorageTypeDateTime:
+            {
+            value = GetExportDateValueL( aField );
+            break;
+            }
+
+        default:
+            {
+            value = NULL;
+            break;
+            }
+        }
+
+    if ( value )
+        {
+        CleanupStack::PushL( value );
+        GetAdditionalParamsL( aField, aParameters );
+        CleanupStack::Pop( value );
+        }
+
+    return value;
+    }
+
+
+TBool CVPbkVCardPropertyExporter::AddPropertyToParserL(
+    RPointerArray< CParserPropertyValue >& aValues,
+    CVPbkVCardParserParamArray* aParams )
+    {
+    if( !HasValues() )
+        {
+        return EFalse;
+        }
+
+    CleanupStack::PushL( aParams );
+    CParserPropertyValue* value = GetValueL( aValues );
+
+    __ASSERT_DEBUG( value,
+        VPbkVCardEngError::Panic( VPbkVCardEngError::ENullParserProperty ) );
+
+    CleanupStack::PushL(value);
+    CParserProperty* property =
+        CParserProperty::NewL( *value, iVCardProperty->Name(), aParams );
+    CleanupStack::Pop( value );
+    CleanupStack::Pop( aParams ); // The ownership has taken by CParserProperty
+    // NOTE: Versit pushes the CParserProperty* pointer stright away
+    // to the cleanup stack, so to avoid duplicate entries in
+    // the stack pointer must not be pushed there.
+    iParser->AddPropertyL( property );
+
+    return ETrue;
+    }
+
+TBool CVPbkVCardPropertyExporter::HasValues()
+    {
+    for ( TInt i = 0; i < iValues.Count(); ++i )
+        {
+        if ( iValues[ i ] )
+            {
+            return ETrue;
+            }
+        }
+    return EFalse;
+    }
+
+CParserPropertyValue* CVPbkVCardPropertyExporter::GetValueL(
+    RPointerArray< CParserPropertyValue >& aValues)
+    {
+    CParserPropertyValue* value = NULL;
+    if ( aValues.Count() == KOne )
+        {
+        value = aValues[ 0 ];
+        aValues.Remove( 0 );
+        }
+    else
+        {
+        CDesCArrayFlat* desarr = new(ELeave) CDesCArrayFlat( aValues.Count() );
+        CleanupStack::PushL( desarr );
+
+        while ( aValues.Count() > 0 )
+            {
+            CParserPropertyValueHBufC* tmpValue =
+                static_cast<CParserPropertyValueHBufC*>( aValues[ 0 ] );
+            CleanupStack::PushL( tmpValue );
+            aValues.Remove( 0 );
+
+            if ( !tmpValue || tmpValue->Value().Length() == 0 )
+                {
+                desarr->AppendL( KNullDesC );
+                }
+            else
+                {
+                desarr->AppendL( tmpValue->Value() );
+                }
+
+            CleanupStack::PopAndDestroy( tmpValue );
+            }
+
+        value = new (ELeave) CParserPropertyValueCDesCArray( desarr );
+        CleanupStack::Pop( desarr );
+        }
+
+    __ASSERT_DEBUG( aValues.Count() == 0,
+        VPbkVCardEngError::Panic(
+            VPbkVCardEngError::EInvalidLengthOfPropertyArray ) );
+
+    return value;
+    }
+
+CParserPropertyValue* CVPbkVCardPropertyExporter::GetExportTextValueL(
+    const MVPbkBaseContactField& aField )
+    {
+    TPtrC text( MVPbkContactFieldTextData::Cast( aField.FieldData() ).Text() );
+    if( !ContainsValidTextualDataL( text ) )
+        {
+        return NULL;
+        }
+
+    CParserPropertyValueHBufC* value = CParserPropertyValueHBufC::NewL( text );
+
+    return value;
+    }
+    
+ CParserPropertyValue* CVPbkVCardPropertyExporter::GetExportUriValueL(
+    const MVPbkBaseContactField& aField )
+    {
+    TPtrC text( MVPbkContactFieldUriData::Cast( aField.FieldData() ).Uri() );
+    if( !ContainsValidTextualDataL( text ) )
+        {
+        return NULL;
+        }
+
+    CParserPropertyValueHBufC* value = CParserPropertyValueHBufC::NewL( text );
+
+    return value;
+    }
+    
+
+CParserPropertyValue* CVPbkVCardPropertyExporter::GetExportDateValueL(
+    const MVPbkBaseContactField& aField)
+    {
+    TTime time =
+        MVPbkContactFieldDateTimeData::Cast( aField.FieldData() ).DateTime();
+    TVersitDateTime* vdt =
+        new (ELeave) TVersitDateTime( time.DateTime(),
+                                      TVersitDateTime::EIsMachineLocal );
+    CleanupStack::PushL( vdt );
+    CParserPropertyValueDate* value =
+        new (ELeave) CParserPropertyValueDate( vdt );
+    CleanupStack::Pop( vdt );
+    return value;
+    }
+
+CParserPropertyValue*
+CVPbkVCardPropertyExporter::GetExportBinaryValueL(
+    const MVPbkBaseContactField& aField,
+    CVPbkVCardParserParamArray& aParameters )
+    {
+    const TDesC8& data =
+        MVPbkContactFieldBinaryData::Cast( aField.FieldData() ).BinaryData();
+
+    CParserParam* param = CParserParam::NewL( KPropEncoding, KPropBase64 );
+    CleanupStack::PushL( param );
+    aParameters.AppendL( param );
+    CleanupStack::Pop( param );
+
+    // format is always jpeg when retrieved from db
+    param = CParserParam::NewL( KPropType, KFormatJPEG );
+    CleanupStack::PushL( param );
+    aParameters.AppendL( param );
+    CleanupStack::Pop( param );
+
+    CParserPropertyValueBinary* value = CParserPropertyValueBinary::NewL( data );
+    return value;
+    }
+
+TBool CVPbkVCardPropertyExporter::ContainsValidTextualDataL(
+    const TDesC& aDataText) const
+    {
+    if ( !aDataText.Length() )
+        {
+        return EFalse;
+        }
+
+    HBufC* tmpText = aDataText.AllocLC();
+    TPtr tmpPtr = tmpText->Des();
+    tmpPtr.Trim();
+
+    if ( tmpPtr.Length() == 0 )
+        {
+        CleanupStack::PopAndDestroy(); // tmpText
+        return EFalse;
+        }
+
+    CleanupStack::PopAndDestroy(); // tmpText
+    return ETrue;
+    }
+
+void CVPbkVCardPropertyExporter::GetAdditionalParamsL(
+    MVPbkStoreContactField& aField, CVPbkVCardParserParamArray& aParams )
+    {
+    if ( aParams.Count() > 0 ) // Fetch params only once.
+        {
+        return;
+        }
+
+    const MVPbkFieldType* fieldType = NULL;
+    const TInt maxMatchPriority = iData.SupportedFieldTypes().MaxMatchPriority();
+    for (TInt matchPriority = 0;
+         matchPriority <= maxMatchPriority && !fieldType;
+         ++matchPriority)
+        {
+        fieldType = aField.MatchFieldType( matchPriority );
+        }
+    if ( !fieldType )
+        {
+        return;
+        }
+
+    TBool match( EFalse );
+    TVPbkFieldTypeParameters params;
+    TArray<TVPbkFieldVersitProperty> array = fieldType->VersitProperties();
+    for ( TInt n = 0; n < array.Count() && !match; ++n )
+        {
+        TVPbkFieldVersitProperty vProperty = array[ n ];
+        for ( TInt priority = 0;
+            priority <= maxMatchPriority && !match;
+            ++priority )
+            {
+            match = fieldType->Matches( vProperty, priority );
+            if ( match )
+                {
+                params.AddAll( vProperty.Parameters() );
+                }
+            }
+        }
+    
+    TInt count = iData.ParamIdNameMappings().Count();
+    for ( TInt i = 0; i < count; ++i )
+        {
+        if ( params.Contains(
+                static_cast<TVPbkFieldTypeParameter>(
+                    iData.ParamIdNameMappings()[ i ]->Id() ) ) )
+            {
+            CParserParam* param =
+                CParserParam::NewL( iData.ParamIdNameMappings()[ i ]->Name(),
+                                    KNullDesC );
+            CleanupStack::PushL( param );
+            aParams.AppendL( param );
+            CleanupStack::Pop( param );
+            }
+        }
+
+    // Set PREF param if field has default attribute set
+    if ( iData.AttributeManagerL().HasFieldAttributeL(
+                                CVPbkDefaultAttribute::Uid(), aField) )
+        {
+        CParserParam* param = CParserParam::NewL( KPropPREF, KNullDesC );
+        CleanupStack::PushL( param );
+        aParams.AppendL( param );
+        CleanupStack::Pop( param );
+        }
+    }
+
+void CVPbkVCardPropertyExporter::InitDataL()
+    {
+    TInt indexedPropertyCount( iVCardProperty->Count() );
+
+    iValues.ResetAndDestroy();
+    // Initialize array with NULL values
+    while ( iValues.Count() < indexedPropertyCount )
+        {
+        iValues.AppendL( NULL );
+        }
+    }
+
+TInt CVPbkVCardPropertyExporter::Next(TInt& aRemainingSteps)
+    {
+    __ASSERT_DEBUG( iState == EExporting,
+        VPbkVCardEngError::Panic( VPbkVCardEngError::EInvalidStateOfExporter ) );
+    TInt err( KErrNone );
+    TRAP( err, DoNextL() );
+
+    ++iCurrentPropertyIndex;
+    aRemainingSteps = (iCurrentPropertyIndex < iMaxPropertyCount ) ?
+        ( iMaxPropertyCount - iCurrentPropertyIndex ) :
+        0;
+    
+ 	if(!iBeamed && err == KErrNone && !aRemainingSteps )
+	    {
+	    TRAP( err, HandleOwnCardL() );
+            if(err == KErrNone ) 
+                TRAP( err, HandleGroupCardL() );
+            
+            // Parse the REV (Revision) field if any
+            if(err == KErrNone ) 
+            	TRAP( err, AddRevL() ); 
+	    }
+    return err;
+    }
+
+// ----------------------------------------------------------------------------
+// CVPbkVCardPropertyExporter::HandleGroupCardL
+// ----------------------------------------------------------------------------
+void CVPbkVCardPropertyExporter::HandleGroupCardL()
+    {
+    CParserProperty* property = iGroupcardHandler->CreateXGroupPropertyL(iContact);
+    if (property)
+        {
+        CleanupStack::PushL( property );
+        iParser->AddPropertyL( property );  
+        CleanupStack::Pop( property );
+        }
+    }
+
+void CVPbkVCardPropertyExporter::HandleOwnCardL()
+	{
+	iOwncardHandler->DoInitL(iContact->ParentStore());
+    if(iOwncardHandler->IsOwnContactL(iContact))
+    	{
+    	CParserProperty* property =iOwncardHandler->CreateXSelfPropertyL();
+    	CleanupStack::PushL( property );
+	   	iParser->AddPropertyL( property );	
+	   	CleanupStack::Pop( property );
+    	}
+	}
+void CVPbkVCardPropertyExporter::DoNextL()
+    {
+    ExportFieldL( *iData.Properties()[ iCurrentPropertyIndex ] );
+    }
+
+void CVPbkVCardPropertyExporter::CloseL()
+    {
+    iParser->ExternalizeL( iDestinationStream );
+    iObserver.VPbkSingleContactOperationComplete( *this, NULL );
+    }
+
+void CVPbkVCardPropertyExporter::HandleLeave( TInt aError )
+    {
+    iObserver.VPbkSingleContactOperationFailed( *this, aError );
+    }
+
+void CVPbkVCardPropertyExporter::HandleCancel()
+    {
+    iObserver.VPbkSingleContactOperationFailed( *this, KErrCancel );
+    }
+
+void CVPbkVCardPropertyExporter::InitLinkL(
+    const MVPbkContactLink& aContactLink,
+    CVPbkContactManager& aContactManager )
+    {
+    iOperation =
+        aContactManager.RetrieveContactL( aContactLink, *this );
+    }
+
+void CVPbkVCardPropertyExporter::VPbkSingleContactOperationComplete(
+        MVPbkContactOperationBase& VPBK_DEBUG_ONLY( aOperation ),
+        MVPbkStoreContact* aContact)
+    {
+    __ASSERT_DEBUG( iOperation == &aOperation,
+        VPbkVCardEngError::Panic( VPbkVCardEngError::EStrayOperation ) );
+    iOwnedContact = aContact;
+    iContact = iOwnedContact;
+    iState = EExporting;
+    Complete( KErrNone );
+    }
+
+void CVPbkVCardPropertyExporter::VPbkSingleContactOperationFailed
+        ( MVPbkContactOperationBase& VPBK_DEBUG_ONLY( aOperation ), TInt aError )
+    {
+    __ASSERT_DEBUG( iOperation == &aOperation,
+        VPbkVCardEngError::Panic( VPbkVCardEngError::EStrayOperation ) );
+    Complete( aError );
+    }
+
+void CVPbkVCardPropertyExporter::StartL()
+    {
+    if ( iState == ECreatingRetriever )
+        {
+        StartWaiting();
+        }
+    else
+        {
+        Start();
+        }
+    }
+
+void CVPbkVCardPropertyExporter::AddRevL()
+    {
+    MVPbkStoreContact* tempContact = const_cast<MVPbkStoreContact*>(iContact);
+    if( tempContact )
+        {
+        MVPbkStoreContact2* tempContact2 = 	reinterpret_cast<MVPbkStoreContact2*>
+            (tempContact->StoreContactExtension (KMVPbkStoreContactExtension2Uid) );	    
+        if(tempContact2)
+            {
+            MVPbkStoreContactProperties* propreties = tempContact2->PropertiesL();
+            if( propreties )
+                {
+                CleanupDeletePushL(propreties);
+
+                // Convert the last_modified field defined in Contact Model database 
+                // to REV (Revision) field in vCard Specification 2.1
+                CParserPropertyValueDateTime* valueDateTime =
+                        CreateDateTimePropertyL(
+                            propreties->LastModifiedL(),
+                            TVersitDateTime::EIsUTC );
+                CleanupStack::PopAndDestroy(propreties);
+                
+                CleanupStack::PushL(valueDateTime);
+                CParserProperty* property =
+                        CParserGroupedProperty::NewL(*valueDateTime, KREV, NULL, NULL);
+                
+                CleanupStack::PushL( property );
+                iParser->AddPropertyL(property); //takes ownership
+                CleanupStack::Pop(2);//valueDateTime and property
+                }
+            }
+        }
+    }	
+	
+CParserPropertyValueDateTime* CVPbkVCardPropertyExporter::CreateDateTimePropertyL
+    (const TTime& aDateTime, TVersitDateTime::TRelativeTime aRelativeTime)
+    {
+    TVersitDateTime* dateTime= new(ELeave)TVersitDateTime(aDateTime.DateTime(), aRelativeTime);
+    CleanupStack::PushL(dateTime);
+    CParserPropertyValueDateTime* dateTimeValue=new(ELeave) CParserPropertyValueDateTime(dateTime);
+    CleanupStack::Pop(dateTime);	
+    return dateTimeValue;
+    }
+
+// End of file