phonebookui/Phonebook2/UIServices/src/CPbk2AiwAssignProvider.cpp
changeset 0 e686773b3f54
child 68 9da50d567e3c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook2/UIServices/src/CPbk2AiwAssignProvider.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,1309 @@
+/*
+* Copyright (c) 2005-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:  Phonebook 2 Assign UI service AIW provider.
+*
+*/
+
+
+#include "CPbk2AiwAssignProvider.h"
+
+// Phonebook 2
+#include "CPbk2ServerAppConnection.h"
+#include "Pbk2UIServices.hrh"
+#include <Pbk2IPCPackage.h>
+#include <Pbk2UiServicesRes.rsg>
+#include <Pbk2UIControls.rsg>
+#include <Pbk2DataCaging.hrh>
+#include <Pbk2MimeTypeHandler.h>
+#include <Pbk2InternalUID.h>
+
+// Virtual Phonebook
+#include <VPbkPublicUid.h>
+
+// System includes
+#include <AiwMenu.h>
+#include <AiwContactAssignDataTypes.h>
+#include <s32mem.h>
+#include <eikspane.h>
+#include <akntitle.h>
+#include <avkon.hrh>
+#include <featmgr.h>
+#include <aknViewAppUi.h>
+
+using namespace AiwContactAssign;
+
+/// Unnamed namespace for local definitions
+namespace {
+
+_LIT(KPbk2UiServicesDllResFileName, "Pbk2UiServicesRes.rsc");
+_LIT(KPbk2UiControlsDllResFileName, "Pbk2UiControls.rsc");
+
+#ifdef _DEBUG
+
+enum TPanicCode
+    {
+    ENullPointer,
+    EInvalidArgument,
+    EDataTypeNotSupported
+    };
+
+void Panic(TPanicCode aReason)
+    {
+    _LIT( KPanicText, "CPbk2AiwAssignProvider" );
+    User::Panic( KPanicText, aReason );
+    }
+
+#endif // _DEBUG
+
+
+/**
+ * Verifies whether the given command id is handled here.
+ * This should be done by AIW.
+ *
+ * @param aCmdId    The command id to check.
+ * @return  ETrue if command is handled by this provider
+ */
+inline TBool IsCorrectAiwCmd( const TInt aCmdId )
+    {
+    TBool ret = EFalse;
+    switch ( aCmdId )
+        {
+        case KAiwCmdAssign:                     // FALLTHROUGH
+        case EPbk2AiwCmdAssign:                 // FALLTHROUGH
+        case EPbk2AiwCmdDataSaveCreateNew:      // FALLTHROUGH
+        case EPbk2AiwCmdDataSaveAddToExisting:
+            {
+            ret = ETrue;
+            break;
+            }
+
+        default:        
+            {
+            // Do nothing
+            break;
+            }
+        }
+    return ret;
+    }
+
+/**
+ * Finds a AIW semantic id from the AIW in param list.
+ *
+ * @param aInParamList    AIW in param list.
+ * @param aSemanticId     The semantic id to look for.
+ * @return  ETrue if found, EFalse otherwise.
+ */
+inline TBool FindSemanticId
+        ( const CAiwGenericParamList& aInParamList,
+          const TGenericParamId aSemanticId )
+    {
+    TBool ret = EFalse;
+
+    TInt index = 0;
+    if ( aInParamList.FindFirst( index, aSemanticId ) )
+        {
+        ret = ETrue;
+        }
+
+    return ret;
+    }
+
+/**
+ * Validates that param's data is valid
+ *
+ * @param aInParamList  The data passed by the consumer.
+ * @param aSemanticId   The param which data to be validate.
+ * @return ETrue if data is valid, EFalse otherwise
+ */
+inline TBool ValidateData
+        ( const CAiwGenericParamList& aInParamList, 
+          TGenericParamId aSemanticId )
+    {
+    TBool result = ETrue;
+    
+    // EGenericParamMIMEType param data validation
+    if ( EGenericParamMIMEType == aSemanticId )
+        {
+        TInt index = 0;
+
+        const TAiwGenericParam* mimeTypeParam =
+            aInParamList.FindFirst( index, EGenericParamMIMEType,
+                EVariantTypeDesC );
+
+        TInt error = KErrNone;
+        TInt mimeType = Pbk2MimeTypeHandler::EMimeTypeNotSupported;
+        if ( mimeTypeParam )
+            {            
+            TRAP( error,
+                {                
+                if ( mimeTypeParam->Value().AsData().Ptr() )
+                    {
+                    // 8-bit
+                    mimeType = Pbk2MimeTypeHandler::MapMimeTypeL
+                        ( mimeTypeParam->Value().AsData() );
+                    }
+                else if ( mimeTypeParam->Value().AsDes().Ptr() )
+                    {
+                    // 16-bit
+                    mimeType = Pbk2MimeTypeHandler::MapMimeTypeL
+                        ( mimeTypeParam->Value().AsDes() );
+                    }
+                } ); // TRAP
+            }
+        
+        // No MIME type found if leaves with KErrNotFound.
+        // Not supported type if mimeType is not found.
+        if ( error == KErrNotFound  || 
+             Pbk2MimeTypeHandler::EMimeTypeNotSupported == mimeType )
+            {
+            result = EFalse;
+            }            
+        }
+        
+    return result;
+    }
+
+/**
+ * Validates that consumer passed all required data.
+ * Checks also if required param EGenericParamMIMEType data is valid.
+ * If invalid data is given leave KErrArgument will occur.
+ *
+ * @param aInParamList  The data passed by the consumer.
+ * @return  EGenericParamUnspecified if no valid data is found,
+ *          AIW semantic id of found data otherwise.
+ */
+inline TGenericParamId ValidateParams
+        ( const CAiwGenericParamList& aInParamList )
+    {
+    TGenericParamId ret = EGenericParamUnspecified;
+
+    if ( FindSemanticId( aInParamList, EGenericParamPhoneNumber ) )
+        {
+        ret = EGenericParamPhoneNumber;
+        }
+    else if ( FindSemanticId( aInParamList, EGenericParamEmailAddress ) )
+        {
+        ret = EGenericParamEmailAddress;
+        }
+    else if ( FindSemanticId( aInParamList, EGenericParamSIPAddress ) )
+        {
+        ret = EGenericParamSIPAddress;
+        }
+    else if ( FindSemanticId( aInParamList, EGenericParamURL ) )
+        {
+        ret = EGenericParamURL;
+        }
+    else if ( FindSemanticId( aInParamList, EGenericParamWVID ) )
+        {
+        ret = EGenericParamWVID;
+        }
+    else if ( FindSemanticId( aInParamList, EGenericParamSpeedDialIndex ) )
+        {
+        ret = EGenericParamSpeedDialIndex;
+        }
+    else if ( FindSemanticId( aInParamList, EGenericParamXSpId ) )
+        {
+        ret = EGenericParamXSpId;
+        }
+    else if ( FindSemanticId( aInParamList, EGenericParamContactItem ) )
+        {
+        ret = EGenericParamContactItem;
+        }
+    if ( ret == EGenericParamUnspecified )
+        {
+        // The in param list must have a MIME type with the data and file name
+        if ( FindSemanticId( aInParamList, EGenericParamMIMEType ) && 
+             ValidateData( aInParamList, EGenericParamMIMEType ) )
+            {            
+            if ( FindSemanticId( aInParamList, EGenericParamFile ) )
+                {
+                // In this case, return EGenericParamFile
+                ret = EGenericParamFile;
+                }
+            }
+        }
+
+    return ret;
+    }
+    
+/**
+ * Selects correct address select selector matching the passed parameters.
+ *
+ * @param aInParamList  Parameter list.
+ * @return  Selector resource id.
+ */
+TInt SelectSelectorResourceIdFromParams
+        ( const CAiwGenericParamList& aInParamList )
+    {
+    TInt resourceId = KErrNotFound;
+
+    if ( FindSemanticId( aInParamList, EGenericParamPhoneNumber ) )
+        {
+        if( FeatureManager::FeatureSupported( KFeatureIdCommonVoip ) )
+            {
+            resourceId = R_PBK2_AIW_PHONENUMBER_SELECTOR_VOIP;
+            }
+        else
+            {
+            resourceId = R_PBK2_AIW_PHONENUMBER_SELECTOR;
+            }
+        }
+    else if ( FindSemanticId( aInParamList, EGenericParamEmailAddress ) )
+        {
+        if( FeatureManager::FeatureSupported( KFeatureIdCommonVoip ) )
+            {
+            resourceId = R_PBK2_AIW_EMAIL_SELECTOR_VOIP;
+            }
+        else
+            {
+            resourceId = R_PBK2_AIW_EMAIL_SELECTOR;
+            }
+        }
+    else if ( FindSemanticId( aInParamList, EGenericParamSIPAddress ) )
+        {
+        if( FeatureManager::FeatureSupported( KFeatureIdCommonVoip ) )
+            {
+            resourceId = R_PBK2_AIW_SIP_SELECTOR_VOIP;
+            }
+        else
+            {
+            resourceId = R_PBK2_AIW_SIP_SELECTOR;
+            }
+        }
+    else if ( FindSemanticId( aInParamList, EGenericParamURL ) )
+        {
+        resourceId = R_PBK2_AIW_URL_SELECTOR;
+        }
+    else if ( FindSemanticId( aInParamList, EGenericParamWVID ) )
+        {
+        // Not supported yet
+        }
+    else if ( FindSemanticId( aInParamList, EGenericParamDateTime ) )
+        {
+        // Not supported yet
+        }
+    else if ( FindSemanticId( aInParamList, EGenericParamXSpId ) )
+        {
+        resourceId = R_PBK2_AIW_IMPP_SELECTOR;
+        }
+    else
+        {
+        TInt index = 0;
+
+        // Lets then try MIME type param
+        const TAiwGenericParam* mimeTypeParam =
+            aInParamList.FindFirst( index, EGenericParamMIMEType,
+                EVariantTypeDesC );
+
+        if ( mimeTypeParam )
+            {
+            // If MIME type is specified, then the selector resource
+            // depends on the type of MIME
+            TInt mimeType( 0 );
+            if ( mimeTypeParam->Value().AsData().Ptr() )
+                {
+                // 8-bit
+                mimeType = Pbk2MimeTypeHandler::MapMimeTypeL
+                    ( mimeTypeParam->Value().AsData() );
+                }
+            else if ( mimeTypeParam->Value().AsDes().Ptr() )
+                {
+                // 16-bit
+                mimeType = Pbk2MimeTypeHandler::MapMimeTypeL
+                    ( mimeTypeParam->Value().AsDes() );
+                }
+
+            switch ( mimeType )
+                {
+                case Pbk2MimeTypeHandler::EMimeTypeImage:
+                    {
+                    resourceId = R_PBK2_AIW_THUMBNAIL_SELECTOR;
+                    break;
+                    }
+                case Pbk2MimeTypeHandler::EMimeTypeAudio:   // FALLTHROUGH
+                case Pbk2MimeTypeHandler::EMimeTypeVideo:
+                    {
+                    resourceId = R_PBK2_AIW_RINGTONE_SELECTOR;
+                    break;
+                    }
+                default:
+                    {
+                    // Do nothing
+                    break;
+                    }
+                }
+            }
+        }
+
+    return resourceId;
+    }
+
+/**
+ * Selects correct contact view filter selector matching
+ * the passed parameters.
+ *
+ * @param aInParamList  Parameter list.
+ * @return  Selector resource id.
+ */
+TInt SelectFilterResourceIdFromParams
+        ( const CAiwGenericParamList& aInParamList )
+    {
+    TInt resourceId = KErrNotFound;
+
+    if ( FindSemanticId( aInParamList, EGenericParamSpeedDialIndex ) )
+        {
+        resourceId = R_PHONEBOOK2_PHONENUMBER_SELECTOR;
+        }
+
+    return resourceId;
+    }
+
+} /// namespace
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::CPbk2AiwAssignProvider
+// --------------------------------------------------------------------------
+//
+CPbk2AiwAssignProvider::CPbk2AiwAssignProvider()
+        : iUiServicesResourceFile( *CCoeEnv::Static() )
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::~CPbk2AiwAssignProvider
+// --------------------------------------------------------------------------
+//
+CPbk2AiwAssignProvider::~CPbk2AiwAssignProvider()
+    {
+    delete iConnection;
+    delete iEventParamList;
+    delete iDataPackage;
+    delete iConfigurationPackage;
+    delete iInstructionsPackage;
+    iUiServicesResourceFile.Close();
+    FeatureManager::UnInitializeLib();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::NewL
+// --------------------------------------------------------------------------
+//
+CPbk2AiwAssignProvider* CPbk2AiwAssignProvider::NewL()
+    {
+    CPbk2AiwAssignProvider* self = new ( ELeave)  CPbk2AiwAssignProvider;
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::ConstructL
+// --------------------------------------------------------------------------
+//
+void CPbk2AiwAssignProvider::ConstructL()
+    {
+    iUiServicesResourceFile.OpenL(KPbk2RomFileDrive,
+        KDC_RESOURCE_FILES_DIR, KPbk2UiServicesDllResFileName);
+    FeatureManager::InitializeLibL();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::InitializeMenuPaneL
+// --------------------------------------------------------------------------
+//
+void CPbk2AiwAssignProvider::InitializeMenuPaneL
+        ( CAiwMenuPane& aMenuPane, TInt aIndex,
+          TInt /*aCascadeId*/, const CAiwGenericParamList& aInParamList)
+    {
+    TAiwGenericParam param = ValidateParams(aInParamList);
+    if (param != EGenericParamUnspecified)
+        {
+        // Initialize with the default menu
+        TInt menuResourceId = R_PBK2_AIW_ASSIGN;
+
+        CreateInstructionPackageL( aInParamList );
+
+        if (iInstructionsPackage)
+            {
+            TInt version = TAiwContactAssignDataBase::
+                AssignDataTypeFromBuffer( *iInstructionsPackage );
+            if (version == EAiwMultipleContactAssignV1)
+                {
+                // Multi assign has always just one menu option,
+                // and it has already been set
+                }
+            else if (version == EAiwSingleContactAssignV1)
+                {
+                // Single assign defaults to R_PBK2_AIW_ADD_TO_CONTACTS,
+                // but if there is a raised EUseSimpleMenu flag
+                // then we show the R_PBK2_AIW_ASSIGN menu
+                TAiwSingleContactAssignDataV1Pckg data;
+                data.Copy( *iInstructionsPackage );
+                TUint assignFlags = data().Flags();
+                if ( !( assignFlags & EUseSimpleMenu ) )
+                    {
+                    if (param == EGenericParamXSpId)
+                        {
+                        menuResourceId = R_PBK2_AIW_ADD_TO_CONTACTS_XSP;
+                        }
+                    else
+                        {
+                        menuResourceId = R_PBK2_AIW_ADD_TO_CONTACTS;
+                        }
+                    }
+                }
+            else
+                {
+                User::Leave( KErrArgument );
+                }
+            }
+
+        // Show the menu
+        TResourceReader reader;
+        CCoeEnv::Static()->CreateResourceReaderLC
+            (reader, menuResourceId);
+        aMenuPane.AddMenuItemsL(reader, KAiwCmdAssign, aIndex);
+        CleanupStack::PopAndDestroy(); // reader
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::HandleMenuCmdL
+// --------------------------------------------------------------------------
+//
+void CPbk2AiwAssignProvider::HandleMenuCmdL
+        ( TInt aMenuCmdId, const CAiwGenericParamList& aInParamList,
+          CAiwGenericParamList& aOutParamList,
+          TUint aCmdOptions, const MAiwNotifyCallback* aCallback )
+    {
+    // Route to HandleServiceCmdL
+    HandleServiceCmdL( aMenuCmdId, aInParamList,
+        aOutParamList, aCmdOptions, aCallback );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::InitialiseL
+// --------------------------------------------------------------------------
+//
+void CPbk2AiwAssignProvider::InitialiseL
+        ( MAiwNotifyCallback& /*aFrameworkCallback*/,
+          const RCriteriaArray& /*aInterest*/ )
+    {
+    // Nothing needs to be done
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::HandleServiceCmdL
+// --------------------------------------------------------------------------
+//
+void CPbk2AiwAssignProvider::HandleServiceCmdL
+        ( const TInt& aCmdId, const CAiwGenericParamList& aInParamList,
+        CAiwGenericParamList& /*aOutParamList*/,
+        TUint aCmdOptions, const MAiwNotifyCallback* aCallback )
+    {
+    if ( IsCorrectAiwCmd( aCmdId ) )
+        {
+        if ( !iConnection )
+            {
+            iConnection = CPbk2ServerAppConnection::NewL( *this );
+            }
+        else if( iConnection->IsActive() )
+            {
+	            	if ( aCmdOptions & KAiwOptCancel )
+								{
+								// Client wants to cancel existing service
+								iConnection->CancelAssign();
+								}
+            
+            // Request is already active for the same client, do nothing
+            // as Phonebook supports only one request per client at a time.
+            return;
+            }
+            
+        if ( !iEventParamList )
+            {
+            iEventParamList = CAiwGenericParamList::NewL();
+            }
+
+        TGenericParamId semanticId = ValidateParams( aInParamList );
+        iCallback = aCallback;
+
+        // Create IPC packages
+        CreateInstructionPackageL( aInParamList );
+        ValidateInstructionPackageL();
+        ValidateMenuServiceL( aCmdId );
+        CreateConfigurationPackageL( aInParamList );
+
+        if ( semanticId == EGenericParamSpeedDialIndex )
+            {
+            LaunchAttributeAssignL( aInParamList, semanticId );
+            }
+        else
+            {
+            LaunchDataAssignL( aInParamList, semanticId );
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::OperationCompleteL
+// --------------------------------------------------------------------------
+//
+void CPbk2AiwAssignProvider::OperationCompleteL
+        ( const TDesC8& aContactLinks, TInt aExtraResultData,
+          const TDesC& /*aField*/ )
+    {
+    iEventParamList->Reset();
+    iEventParamList->AppendL(
+        TAiwGenericParam( EGenericParamContactLinkArray,
+            TAiwVariant( aContactLinks ) ) );
+
+    // aExtraResultData contains index of focused field from editor
+    // this is used in cca details view.
+    // todo: would it be better to add a new aiw semantic id instead of EGenericParamContactItem?
+    iEventParamList->AppendL(
+        TAiwGenericParam( EGenericParamContactItem,
+            TAiwVariant( aExtraResultData )));
+
+    if (iCallback)
+        {
+        // Must cast this because of AIW design error
+        const_cast<MAiwNotifyCallback*>(iCallback)->HandleNotifyL
+            ( KAiwCmdAssign, KAiwEventCompleted, *iEventParamList,
+              *iInParamList );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::OperationCanceledL
+// --------------------------------------------------------------------------
+//
+void CPbk2AiwAssignProvider::OperationCanceledL()
+    {
+    iEventParamList->Reset();
+    if (iCallback)
+        {
+        // Must cast this because of AIW design error
+        const_cast<MAiwNotifyCallback*>(iCallback)->HandleNotifyL
+            ( KAiwCmdAssign, KAiwEventCanceled, *iEventParamList,
+              *iInParamList );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::OperationErrorL
+// --------------------------------------------------------------------------
+//
+void CPbk2AiwAssignProvider::OperationErrorL( TInt aError )
+    {
+    iEventParamList->Reset();
+    iEventParamList->AppendL(
+            TAiwGenericParam( EGenericParamError,
+                TAiwVariant( aError ) ) );
+
+     if ( iCallback )
+        {
+        // Must cast this because of AIW design error
+        const_cast<MAiwNotifyCallback*>( iCallback )->HandleNotifyL
+            ( KAiwCmdAssign, KAiwEventError, *iEventParamList,
+              *iInParamList );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::OkToExitL
+// --------------------------------------------------------------------------
+//
+TBool CPbk2AiwAssignProvider::OkToExitL
+        ( TInt /*aCommandId*/, TPbk2ExitCommandParams aExitParameter )
+    {
+    TBool okToExit = ETrue;
+
+    if ( iCallback )
+        {
+        iEventParamList->Reset();
+        iEventParamList->AppendL(
+            TAiwGenericParam( EGenericParamApplication,
+                TAiwVariant( aExitParameter ) ) );
+
+        // Must cast this because of AIW design error
+        okToExit = const_cast<MAiwNotifyCallback*>( iCallback )
+            ->HandleNotifyL( KAiwCmdAssign, KAiwEventQueryExit,
+                *iEventParamList, *iInParamList );
+        }
+
+    return okToExit;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::AcceptSelectionL
+// --------------------------------------------------------------------------
+//
+TBool CPbk2AiwAssignProvider::AcceptSelectionL
+        ( TInt /*aNumberOfSelectedContacts*/, HBufC8& /*aContactLink*/ )
+    {
+    // Assign service does not contain support
+    // for verification of the selection
+    return ETrue;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::PackParameterToBufferL
+// --------------------------------------------------------------------------
+//
+HBufC8* CPbk2AiwAssignProvider::PackParameterToBufferL
+        ( TGenericParamId aParamId,
+          const CAiwGenericParamList& aInParamList) const
+    {
+    HBufC8* result = NULL;
+
+    TInt paramIndex = 0;
+    const TAiwGenericParam* paramData =
+        aInParamList.FindFirst( paramIndex, aParamId );
+
+    if ( paramData && paramData->Value().AsData().Ptr() )
+        {
+        result = paramData->Value().AsData().AllocL();
+        }
+    else if ( paramData && paramData->Value().AsDes().Ptr() )
+        {
+        // Data was given as 16-bit, transform it into 8-bit
+        const TInt size( paramData->Value().AsDes().Size() );
+        result = HBufC8::NewL( size );
+        result->Des().Copy( paramData->Value().AsDes() );
+        }
+
+    return result;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::PackParameterToBuffer16L
+// --------------------------------------------------------------------------
+//
+HBufC16* CPbk2AiwAssignProvider::PackParameterToBuffer16L
+        ( TGenericParamId aParamId,
+        const CAiwGenericParamList& aInParamList ) const
+    {
+    HBufC16* result = NULL;
+
+    TInt paramIndex = 0;
+    const TAiwGenericParam* paramData =
+        aInParamList.FindFirst(paramIndex, aParamId);
+
+    if ( paramData && paramData->Value().AsData().Ptr() )
+        {
+        // Data was given as 8-bit, transform it into 16-bit
+        const TInt size( paramData->Value().AsData().Size() );
+        result = HBufC::NewL( size );
+        result->Des().Copy( paramData->Value().AsData() );
+        }
+    else if ( paramData && paramData->Value().AsDes().Ptr() )
+        {
+        result = paramData->Value().AsDes().AllocL();
+        }
+
+    return result;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::PackSelectorToBufferL
+// --------------------------------------------------------------------------
+//
+HBufC8* CPbk2AiwAssignProvider::PackSelectorToBufferL
+        ( const CAiwGenericParamList& aInParamList ) const
+    {
+    HBufC8* result = NULL;
+
+    TInt resourceId = SelectSelectorResourceIdFromParams( aInParamList );
+    if ( resourceId != KErrNotFound )
+        {
+        // Construct a resource buffer pointed to
+        // VPBK_FIELD_TYPE_SELECTOR resource, which will
+        // contain the suitable fields for the passed data
+        RFs fs;
+        User::LeaveIfError( fs.Connect() );
+        CleanupClosePushL( fs );
+
+        RPbk2LocalizedResourceFile resFile =
+            RPbk2LocalizedResourceFile( &fs );
+        resFile.OpenLC( KPbk2RomFileDrive,
+            KDC_RESOURCE_FILES_DIR, KPbk2UiServicesDllResFileName );
+        result = resFile.AllocReadLC( resourceId );
+        CleanupStack::Pop(); // result
+        CleanupStack::PopAndDestroy(2); // resFile, fs
+        }
+
+    return result;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::PackFilterToBufferL
+// --------------------------------------------------------------------------
+//
+HBufC8* CPbk2AiwAssignProvider::PackFilterToBufferL
+        ( const CAiwGenericParamList& aInParamList ) const
+    {
+    HBufC8* result = NULL;
+
+    TInt resourceId = SelectFilterResourceIdFromParams( aInParamList );
+    if ( resourceId != KErrNotFound )
+        {
+        // Construct a resource buffer pointed to
+        // VPBK_FIELD_TYPE_SELECTOR resource, which will
+        // contain the suitable fields for the passed data
+        RFs fs;
+        User::LeaveIfError( fs.Connect() );
+        CleanupClosePushL( fs );
+
+        RPbk2LocalizedResourceFile resFile =
+            RPbk2LocalizedResourceFile( &fs );
+        resFile.OpenLC( KPbk2RomFileDrive,
+            KDC_RESOURCE_FILES_DIR, KPbk2UiControlsDllResFileName );
+        result = resFile.AllocReadLC( resourceId );
+        CleanupStack::Pop(); // result
+        CleanupStack::PopAndDestroy(2); // resFile, fs
+        }
+
+    return result;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::CreateDataPackageL
+// --------------------------------------------------------------------------
+//
+void CPbk2AiwAssignProvider::CreateDataPackageL
+        ( const CAiwGenericParamList& aInParamList,
+          const TGenericParamId aSemanticId )
+    {
+    // MIME type
+    HBufC8* mimeTypeBuffer = PackParameterToBufferL
+        ( EGenericParamMIMEType, aInParamList );
+    CleanupStack::PushL( mimeTypeBuffer );
+
+    // The data to assign, if any
+    HBufC16* dataBuffer = NULL;
+    HBufC16* indexBuffer = NULL;
+    if ( aSemanticId == EGenericParamXSpId)
+        {
+        dataBuffer = PackImppParametersToBufferL(aInParamList);
+        }
+    else if ( aSemanticId == EGenericParamContactItem )
+        {
+        // TODO: get index from aInParamList AsTInt32()
+        indexBuffer = PackParameterToBuffer16L( aSemanticId, aInParamList );
+        }
+    else if ( aSemanticId != EGenericParamUnspecified )
+        {
+        dataBuffer = PackParameterToBuffer16L( aSemanticId, aInParamList );
+        }
+    CleanupStack::PushL( dataBuffer );
+    CleanupStack::PushL( indexBuffer );
+
+    TInt length = Pbk2IPCPackage::CountPackageSize( mimeTypeBuffer );
+    length += Pbk2IPCPackage::CountPackageSize( dataBuffer );
+    length += Pbk2IPCPackage::CountPackageSize( indexBuffer );
+
+    delete iDataPackage;
+    iDataPackage = NULL;
+    iDataPackage = HBufC8::NewL( length );
+    TPtr8 bufferPtr( iDataPackage->Des() );
+
+    RDesWriteStream writeStream( bufferPtr  );
+    writeStream.PushL();
+    Pbk2IPCPackage::ExternalizeL( mimeTypeBuffer, writeStream );
+    Pbk2IPCPackage::ExternalizeL( dataBuffer, writeStream );
+    Pbk2IPCPackage::ExternalizeL( indexBuffer, writeStream );
+    writeStream.CommitL();
+
+    CleanupStack::PopAndDestroy( &writeStream );
+    CleanupStack::PopAndDestroy( 3 ); // dataBuffer, mimeTypeBuffer, indexbuffer
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::CreateAttributePackageL
+// --------------------------------------------------------------------------
+//
+TPbk2AttributeAssignData CPbk2AiwAssignProvider::CreateAttributePackageL
+        ( const CAiwGenericParamList& aInParamList,
+          const TGenericParamId aSemanticId )
+    {
+    TPbk2AttributeAssignData ret;
+    ret.iAttributeUid = TUid::Uid( KEPOCNullUID );
+    ret.iAttributeValue = KErrNotFound;
+
+    switch ( aSemanticId )
+        {
+        case EGenericParamSpeedDialIndex:
+            {
+            TInt speedDialIndex = KErrNotFound;
+            TInt paramIndex = 0;
+
+            const TAiwGenericParam* paramData =
+                aInParamList.FindFirst( paramIndex, aSemanticId );
+
+            if ( paramData )
+                {
+                speedDialIndex = paramData->Value().AsTInt32();
+                }
+
+            ret.iAttributeUid =
+                TUid::Uid( KVPbkSpeedDialAttributeImplementationUID );
+            ret.iAttributeValue = speedDialIndex;
+            break;
+            }
+
+        default:
+            {
+            __ASSERT_DEBUG( EFalse, Panic( EInvalidArgument ) );
+            break;
+            }
+        };
+
+    return ret;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::CreateConfigurationPackageL
+// --------------------------------------------------------------------------
+//
+void CPbk2AiwAssignProvider::CreateConfigurationPackageL
+        ( const CAiwGenericParamList& aInParamList )
+    {
+    // Store URIs
+    HBufC8* storeUriBuffer = PackParameterToBufferL
+        ( EGenericParamContactStoreUriArray, aInParamList );
+    CleanupStack::PushL( storeUriBuffer );
+
+    // Contact links
+    HBufC8* linkBuffer = PackParameterToBufferL
+        ( EGenericParamContactLinkArray, aInParamList );
+    CleanupStack::PushL( linkBuffer );
+
+    // Field type selector
+    HBufC8* selectorBuffer = PackSelectorToBufferL( aInParamList );
+    CleanupStack::PushL( selectorBuffer );
+
+    // Contact view filter
+    HBufC8* viewFilterBuffer = PackFilterToBufferL( aInParamList );
+    CleanupStack::PushL( viewFilterBuffer );
+
+    // Title pane
+    HBufC* titlePaneText = ClientTitlePaneL();
+    CleanupStack::PushL( titlePaneText );
+
+    HBufC* orientationType = ClientOrientation();
+    CleanupStack::PushL( orientationType );
+    TInt length = Pbk2IPCPackage::CountPackageSize( storeUriBuffer );
+    length += Pbk2IPCPackage::CountPackageSize( linkBuffer );
+    length += Pbk2IPCPackage::CountPackageSize( selectorBuffer );
+    length += Pbk2IPCPackage::CountPackageSize( viewFilterBuffer );
+    length += Pbk2IPCPackage::CountPackageSize( titlePaneText );
+    length += Pbk2IPCPackage::CountPackageSize( orientationType );
+
+    delete iConfigurationPackage;
+    iConfigurationPackage = NULL;
+    iConfigurationPackage = HBufC8::NewL( length );
+    TPtr8 bufferPtr( iConfigurationPackage->Des() );
+
+    RDesWriteStream writeStream( bufferPtr  );
+    writeStream.PushL();
+    Pbk2IPCPackage::ExternalizeL( storeUriBuffer, writeStream );
+    Pbk2IPCPackage::ExternalizeL( linkBuffer, writeStream );
+    Pbk2IPCPackage::ExternalizeL( selectorBuffer, writeStream );
+    Pbk2IPCPackage::ExternalizeL( viewFilterBuffer, writeStream );
+    Pbk2IPCPackage::ExternalizeL( titlePaneText, writeStream );
+    Pbk2IPCPackage::ExternalizeL( orientationType, writeStream );
+    writeStream.CommitL();
+
+    CleanupStack::PopAndDestroy( &writeStream );
+    CleanupStack::PopAndDestroy( 6 ); // orientationType, titlePaneText,
+                                      // viewFilterBuffer, selectorBuffer, 
+                                      // linkBuffer, storeUriBuffer 
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::CreateInstructionPackageL
+// --------------------------------------------------------------------------
+//
+void CPbk2AiwAssignProvider::CreateInstructionPackageL
+        ( const CAiwGenericParamList& aInParamList )
+    {
+    delete iInstructionsPackage;
+    iInstructionsPackage = NULL;
+    iInstructionsPackage = PackParameterToBufferL
+        ( EGenericParamContactAssignData, aInParamList );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::ValidateInstructionPackageL
+// --------------------------------------------------------------------------
+//
+void CPbk2AiwAssignProvider::ValidateInstructionPackageL()
+    {
+    if ( iInstructionsPackage )
+        {
+        // Version check
+        TInt version = TAiwContactAssignDataBase::
+            AssignDataTypeFromBuffer( *iInstructionsPackage );
+        if ( version == EAiwContactAssignDataTypeNotDefined )
+            {
+            User::Leave( KErrArgument );
+            }
+
+        switch( version )
+            {
+            case EAiwSingleContactAssignV1:
+                {
+                // Nothing to validate since for example editor can be
+                // on/off and similarly with new contact creation both
+                // choises on/off are supported
+                break;
+                }
+
+            case EAiwMultipleContactAssignV1:
+                {
+                TAiwMultipleContactAssignDataV1Pckg dataPckg;
+
+                // Reconstruct the instructions
+                dataPckg.Copy( iInstructionsPackage->Ptr(),
+                        sizeof( TAiwMultipleContactAssignDataV1 ) );
+
+                // Multi assign does not support new contact
+                // creation nor does it support contact editor,
+                // so disable those
+                TUint flags = dataPckg().Flags();
+                flags &= ~ECreateNewContact;
+                flags |= EDoNotOpenEditor;
+                dataPckg().SetFlags( flags );
+
+                delete iInstructionsPackage;
+                iInstructionsPackage = NULL;
+                iInstructionsPackage = dataPckg.AllocL();
+                break;
+                }
+
+            case EAiwContactAttributeAssignV1:
+                {
+                TAiwContactAttributeAssignDataV1Pckg dataPckg;
+
+                // Reconstruct the instructions
+                dataPckg.Copy( iInstructionsPackage->Ptr(),
+                    sizeof( TAiwContactAttributeAssignDataV1 ) );
+
+                // Attribute assign does not support new contact
+                // creation nor does it support contact editor,
+                // so disable those
+                TUint flags = dataPckg().Flags();
+                flags &= ~ECreateNewContact;
+                flags |= EDoNotOpenEditor;
+                dataPckg().SetFlags( flags );
+
+                delete iInstructionsPackage;
+                iInstructionsPackage = NULL;
+                iInstructionsPackage = dataPckg.AllocL();
+                break;
+                }
+
+            default:
+                {
+                __ASSERT_DEBUG( EFalse, Panic( EDataTypeNotSupported ) );
+                break;
+                }
+            }
+
+        }
+
+    // If client does not give instructions then default
+    // to multiple contact assign
+    if ( !iInstructionsPackage )
+        {
+        TAiwMultipleContactAssignDataV1Pckg dataPckg;
+        iInstructionsPackage = dataPckg.AllocL();
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::ValidateMenuServiceL
+// --------------------------------------------------------------------------
+//
+void CPbk2AiwAssignProvider::ValidateMenuServiceL( const TInt& aCmdId )
+    {
+    // Version check
+    TInt version = TAiwContactAssignDataBase::
+        AssignDataTypeFromBuffer( *iInstructionsPackage );
+    if ( version == EAiwContactAssignDataTypeNotDefined )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    switch ( aCmdId )
+        {
+        case EPbk2AiwCmdAssign:
+            {
+            // Nothing to validate
+            break;
+            }
+
+        case EPbk2AiwCmdDataSaveCreateNew:
+            {
+            // Create new supports only single contact assign
+            if ( version != EAiwSingleContactAssignV1 )
+                {
+                User::Leave( KErrArgument );
+                }
+
+            TAiwSingleContactAssignDataV1Pckg dataPckg;
+            // Reconstruct the instructions
+            dataPckg.Copy( iInstructionsPackage->Ptr(),
+                sizeof( TAiwSingleContactAssignDataV1 ) );
+            TUint flags = dataPckg().Flags();
+            // Make sure the Create New Contact flag is up
+            flags |= ECreateNewContact;
+            dataPckg().SetFlags( flags );
+
+            delete iInstructionsPackage;
+            iInstructionsPackage = NULL;
+            iInstructionsPackage = dataPckg.AllocL();
+            break;
+            }
+
+        case EPbk2AiwCmdDataSaveAddToExisting:
+            {
+            // Update existing can be done to multiple contacts
+            // or to a single contact. We must take care that
+            // create new contact flag is down.
+            switch ( version )
+                {
+                case EAiwMultipleContactAssignV1:
+                    {
+                    TAiwMultipleContactAssignDataV1Pckg dataPckg;
+                    // Reconstruct the instructions
+                    dataPckg.Copy( iInstructionsPackage->Ptr(),
+                        sizeof( TAiwMultipleContactAssignDataV1 ) );
+                    TUint flags = dataPckg().Flags();
+                    // Make sure the Create New Contact flag is down
+                    flags &= ~ECreateNewContact;
+                    dataPckg().SetFlags( flags );
+
+                    delete iInstructionsPackage;
+                    iInstructionsPackage = NULL;
+                    iInstructionsPackage = dataPckg.AllocL();
+                    break;
+                    }
+                case EAiwSingleContactAssignV1:
+                    {
+                    TAiwSingleContactAssignDataV1Pckg dataPckg;
+                    // Reconstruct the instructions
+                    dataPckg.Copy( iInstructionsPackage->Ptr(),
+                        sizeof( TAiwSingleContactAssignDataV1 ) );
+                    TUint flags = dataPckg().Flags();
+                    // Make sure the Create New Contact flag is down
+                    flags &= ~ECreateNewContact;
+                    dataPckg().SetFlags(flags);
+
+                    delete iInstructionsPackage;
+                    iInstructionsPackage = NULL;
+                    iInstructionsPackage = dataPckg.AllocL();
+                    break;
+                    }
+                default:
+                    {
+                    __ASSERT_DEBUG( EFalse, Panic( EDataTypeNotSupported ) );
+                    break;
+                    }    
+                };
+
+            break;
+            }
+
+        default:
+            {
+            // Service was used from client applications own menu
+            // or as a base service. Nothing to do.
+            break;
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::ClientTitlePaneL
+// --------------------------------------------------------------------------
+//
+HBufC* CPbk2AiwAssignProvider::ClientTitlePaneL()
+    {
+    HBufC* result = NULL;
+
+    CEikStatusPane* statusPane =
+        CEikonEnv::Static()->AppUiFactory()->StatusPane();
+
+    if ( statusPane &&
+         statusPane->PaneCapabilities(
+            TUid::Uid( EEikStatusPaneUidTitle ) ).IsPresent() )
+        {
+        CAknTitlePane* titlePane = static_cast<CAknTitlePane*>( statusPane->
+            ControlL( TUid::Uid( EEikStatusPaneUidTitle ) ) );
+
+        if ( titlePane->Text() )
+            {
+            result = titlePane->Text()->AllocL();
+            }
+        }
+
+    return result;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::ClientOrientation
+// --------------------------------------------------------------------------
+//
+HBufC* CPbk2AiwAssignProvider::ClientOrientation() const
+    {
+    HBufC* result = NULL;
+    
+    CAknViewAppUi* appUi = static_cast<CAknViewAppUi*> ( CEikonEnv::Static()->EikAppUi() );
+    
+    if( appUi )
+        {
+        TInt orientationType = appUi->Orientation();
+        result = HBufC::New( sizeof(orientationType) );
+        TPtr resultPtr = result->Des();
+        resultPtr.Num( orientationType );
+        }
+    return result;
+    }
+    
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::LaunchAttributeAssignL
+// --------------------------------------------------------------------------
+//
+inline void CPbk2AiwAssignProvider::LaunchAttributeAssignL
+        ( const CAiwGenericParamList& aInParamList,
+          const TGenericParamId aSemanticId )
+    {
+    iAttributeData =
+        CreateAttributePackageL( aInParamList, aSemanticId );
+
+    // Check does the client want to assign attribute,
+    // or does it want to unassign instead
+    TAiwContactAttributeAssignDataV1Pckg data;
+    data.Copy( *iInstructionsPackage );
+    TBool unassign = data().RemoveAttribute();
+
+    if ( !unassign )
+        {
+        // Launch assign
+        iConnection->LaunchAttributeAssignL
+            ( iConfigurationPackage, iAttributeData, iInstructionsPackage );
+        }
+    else
+        {
+        // Unassign service requires that contact links are also being sent
+        // to the server
+        if ( !FindSemanticId
+                ( aInParamList, EGenericParamContactLinkArray ) )
+            {
+            User::Leave( KErrArgument );
+            }
+
+        // Launch unassign
+        iConnection->LaunchAttributeUnassignL
+            ( iConfigurationPackage, iAttributeData, iInstructionsPackage );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::LaunchDataAssignL
+// --------------------------------------------------------------------------
+//
+inline void CPbk2AiwAssignProvider::LaunchDataAssignL
+        ( const CAiwGenericParamList& aInParamList,
+          const TGenericParamId aSemanticId )
+    {
+    CreateDataPackageL( aInParamList, aSemanticId );
+
+    // Launch
+    iConnection->LaunchAssignL
+        ( iConfigurationPackage, iDataPackage, iInstructionsPackage );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2AiwAssignProvider::PackImppParametersToBuffer
+// --------------------------------------------------------------------------
+//
+HBufC* CPbk2AiwAssignProvider::PackImppParametersToBufferL(
+        const CAiwGenericParamList& aInParamList)
+    {
+    _LIT(KSeparator, "\n");
+    const TInt KParamsCount = 4;
+    TGenericParamId paramId[KParamsCount] = {EGenericParamXSpId,
+            EGenericParamFirstName, EGenericParamLastName,
+            EGenericParamNickname};
+    TPtrC params[KParamsCount] = {TPtrC(), TPtrC(), TPtrC(), TPtrC()};
+    HBufC* paramsBuf[KParamsCount] = {NULL, NULL, NULL, NULL};
+
+    TInt i = 0;
+    TInt separators = 0;
+    TInt length = 0;
+    // read all parameters
+    for (; i < KParamsCount; i++)
+        {
+        TInt paramIndex = 0;
+        const TAiwGenericParam* paramData =
+            aInParamList.FindFirst(paramIndex, paramId[i]);
+        if (paramData && paramData->Value().AsData().Ptr())
+            {
+            // Data was given as 8-bit, transform it into 16-bit
+            TPtrC8 ptr = paramData->Value().AsData();
+            paramsBuf[i] = HBufC::NewLC(ptr.Size());
+            paramsBuf[i]->Des().Copy(ptr);
+            params[i].Set(*paramsBuf[i]);
+            separators = i;
+            }
+        else if ( paramData && paramData->Value().AsDes().Ptr() )
+            {
+            params[i].Set(paramData->Value().AsDes());
+            separators = i;
+            }
+        length += params[i].Length();
+        }
+    
+    HBufC* result = HBufC::NewL(length+separators);
+    TPtr ptr = result->Des();
+    // now separators will be used to count fields
+    // but fields is one more than separators
+    separators++;
+    // create parameter string for server
+    for (i = 0; i < separators; i++)
+        {
+        if (i)
+            {
+            ptr.Append(KSeparator);
+            }
+        ptr.Append(params[i]);
+        }
+    
+    // clean cleanup stack
+    for (i = KParamsCount-1; i >= 0; i--)
+        {
+        if (paramsBuf[i])
+            {
+            CleanupStack::PopAndDestroy(paramsBuf[i]);
+            }
+        }
+    
+    return result;
+    }
+
+// End of File