mtpfws/mtpfw/datatypes/src/cmtptypeserviceobjpropextnform.cpp
author hgs
Tue, 28 Sep 2010 20:14:08 +0800
changeset 52 866b4af7ffbe
parent 0 d0791faffa3f
permissions -rw-r--r--
201039_01

// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// 

/**
@file
@internalComponent
*/

#include <mtp/cmtptypeserviceobjpropextnform.h>
#include <mtp/mtpdatatypeconstants.h>
#include <mtp/mtpprotocolconstants.h>
#include <mtp/cmtptypestring.h>

#include "mtpdatatypespanic.h"

// Dataset constants
const TUint CMTPTypeServiceObjPropExtnForm::KFlat1ChunkSize(20);
const TUint CMTPTypeServiceObjPropExtnForm::KFlat2ChunkSize(1);
const TUint CMTPTypeServiceObjPropExtnForm::KNumChunksWithoutForm(EIdFlat2Chunk + 1);
const TUint CMTPTypeServiceObjPropExtnForm::KNumChunksWithForm(EIdFormChunk + 1);

//Dataset element metadata    
const CMTPTypeCompoundBase::TElementInfo CMTPTypeServiceObjPropExtnForm::iElementMetaData[CMTPTypeServiceObjPropExtnForm::ENumElements] = 
    {
        {EIdFlat1Chunk,       EMTPTypeFlat,       {EMTPTypeUINT128,    0,                 KMTPTypeUINT128Size}},   // EPKNamespace
        {EIdFlat1Chunk,       EMTPTypeFlat,       {EMTPTypeUINT32,    16,                 KMTPTypeUINT32Size}},    // EPKeyID
        {EIdNameChunk,        EMTPTypeString,     {EMTPTypeString, KMTPNotApplicable,     KMTPNotApplicable}},     // EPropertyName
        {EIdFlat2Chunk,       EMTPTypeFlat,       {EMTPTypeUINT8,     0,                  KMTPTypeUINT8Size}},     // EFormFlag
        {EIdFormChunk,        EMTPTypeReference,  {EMTPTypeUndefined, KMTPNotApplicable,  KMTPNotApplicable}},     // EForm
    };


/**
MTP Service Object Property Extension FORM dataset factory method. This method is used to 
create an empty MTP Service Object Property Extension FORM  of the specified Datatype. 
@param aDataType The data type identifier datacode of the object property.
@return A pointer to the form type. Ownership IS 
transfered.
@leave One of the system wide error codes, if unsuccessful.
*/ 
EXPORT_C  CMTPTypeServiceObjPropExtnForm* CMTPTypeServiceObjPropExtnForm::NewL( const TUint aDataType )
    {
    CMTPTypeServiceObjPropExtnForm* self = CMTPTypeServiceObjPropExtnForm::NewLC( aDataType );
    CleanupStack::Pop(self); 
    return self;
    }
/**
MTP DevicePropDesc  Service Object Property Extension FORM  factory method. This method is used to 
create an empty MTP Service Object Property Extension FORM  of the specified Datatype. 
@param aDataType The data type identifier datacode of the the object property.
@return A pointer to the form type. Ownership IS 
transfered.
@leave One of the system wide error codes, if unsuccessful.
*/
EXPORT_C  CMTPTypeServiceObjPropExtnForm* CMTPTypeServiceObjPropExtnForm::NewLC( const TUint aDataType )
    {
    CMTPTypeServiceObjPropExtnForm* self = new(ELeave) CMTPTypeServiceObjPropExtnForm( aDataType );
    CleanupStack::PushL(self);
    TMTPTypeGuid KUndefinedNamespace(0,0);
    TUint KPKeyID(0);
    TBuf<1> KName;
    self->ConstructL( KUndefinedNamespace, KPKeyID, KName, CMTPTypeObjectPropDesc::ENone, NULL );
    
    return self;
    }

   
EXPORT_C  CMTPTypeServiceObjPropExtnForm* CMTPTypeServiceObjPropExtnForm::NewL( const TUint aDataType, const TMTPTypeGuid  aPKNamespace, const TUint aPKID, const TDesC& aName, const TUint8 aFormFlag, const MMTPType* aForm)
    {
    CMTPTypeServiceObjPropExtnForm* self = CMTPTypeServiceObjPropExtnForm::NewLC( aDataType, aPKNamespace, aPKID, aName, aFormFlag, aForm );
    CleanupStack::Pop(self); 
    return self;
    }
   
  
EXPORT_C  CMTPTypeServiceObjPropExtnForm* CMTPTypeServiceObjPropExtnForm::NewLC( const TUint aDataType, const TMTPTypeGuid  aPKNamespace, const TUint aPKID, const TDesC& aName, const TUint8 aFormFlag, const MMTPType* aForm)
    {
    CMTPTypeServiceObjPropExtnForm* self = new(ELeave) CMTPTypeServiceObjPropExtnForm(aDataType);
    CleanupStack::PushL(self);
    self->ConstructL( aPKNamespace, aPKID, aName, aFormFlag, aForm );
    return self;
    }


/**
Destructor.
*/
EXPORT_C CMTPTypeServiceObjPropExtnForm::~CMTPTypeServiceObjPropExtnForm()
    {
    iChunkFlat1.Close();
    delete iChunkName;
    iChunkFlat2.Close();
    iChunkForm.Close();
    }

CMTPTypeServiceObjPropExtnForm::CMTPTypeServiceObjPropExtnForm(const TUint aDataType) : 
    CMTPTypeCompoundBase((KJustInTimeConstruction), KNumChunksWithoutForm),
    iElementInfo(iElementMetaData, ENumElements),
    iChunkFlat1(KFlat1ChunkSize, *this),
    iChunkFlat2(KFlat2ChunkSize, *this),
    iDataType(aDataType),
    iInitialised(EFalse)
    {

    }

EXPORT_C TUint CMTPTypeServiceObjPropExtnForm::Type() const
    {
    return EMTPTypeServiceObjPropExtnFormDataset;
    } 



EXPORT_C TInt CMTPTypeServiceObjPropExtnForm::FirstWriteChunk(TPtr8& aChunk)
    {
    /* 
    Reset the type in preparation for the data stream, by deleting all
    except the first chunk.
    */
    for (TUint i(ChunkCount() - 1); i > EIdFlat1Chunk ; i--)
      {
      ChunkRemove(i);
      }
      
    // Setup the write chunk pointer.
    TInt err(UpdateWriteSequenceErr(CMTPTypeCompoundBase::FirstWriteChunk(aChunk)));
    switch (err)
      {
    case KMTPChunkSequenceCompletion:
      err = KErrNone;
      // Don't break, fall through to set the write sequence state.
      
    case KErrNone:
      // Set the write sequence state.
      iWriteSequenceState = EFlat1Chunk; 
      
      /* 
      Set the write sequence completion state. Initially assume that the 
      extension form has a FORM field. If no FORM field is subsequently
      detected in the write data stream then the completion state is 
      adjusted accordingly.
      */
      iWriteSequenceCompletionState = EFormChunk;
      break;
      
    default:
      break;
      }
      
    return  err;
    }

EXPORT_C TInt CMTPTypeServiceObjPropExtnForm::NextWriteChunk(TPtr8& aChunk)
    {
    TInt err(KMTPChunkSequenceCompletion);
     
     if (iWriteSequenceState != EIdle)
         {
         err = UpdateWriteSequenceErr(CMTPTypeCompoundBase::NextWriteChunk(aChunk));
         if ((iWriteSequenceErr == KMTPChunkSequenceCompletion) && (iWriteSequenceState != EIdle))
             {
             err = KErrNone;
             }   
         }    
     return err;
    }

EXPORT_C TBool CMTPTypeServiceObjPropExtnForm::CommitRequired() const
    {
    return ETrue;
    }

EXPORT_C MMTPType* CMTPTypeServiceObjPropExtnForm::CommitChunkL(TPtr8& aChunk)
    {
    if (iWriteSequenceErr == KMTPChunkSequenceCompletion)
        {
        switch (iWriteSequenceState)
            {
        case EFlat1Chunk:     
            delete iChunkName;
            iChunkName = NULL;
            iChunkName = CMTPTypeString::NewL();
            ChunkAppendL(*iChunkName);
            break;
            
        case ENameChunk:
            ChunkAppendL(iChunkFlat2);
            break;
            
        case EFlat2Chunk: 
            {
            iChunkForm.Close();
            TUint8 flag(Uint8L(EFormFlag));
            iChunkForm.SetMeta(flag, iDataType);
            if (HasFormField(flag))
                {
                iChunkForm.OpenL(iElementInfo[EForm].iType);
                ChunkAppendL(iChunkForm);
                SetExpectedChunkCount(KNumChunksWithForm);
                }
            else
                {
                // Adjust the write sequence completion state.            
                iWriteSequenceCompletionState = EFlat2Chunk;
                }   
            }
            break;
            
        case EFormChunk:
        case EIdle:
        default:
            break;
            }
        
    if ( (iWriteSequenceState != EIdle ) && (iWriteSequenceState < iWriteSequenceCompletionState) )
        {
        iWriteSequenceState++;
        }
    else
        {
        iWriteSequenceState = EIdle;
        }
    }
        
    if (CMTPTypeCompoundBase::CommitRequired())
        {
        CMTPTypeCompoundBase::CommitChunkL(aChunk);
        }
    return NULL;
    }

TBool CMTPTypeServiceObjPropExtnForm::HasFormField(TUint8 aFormFlag) const
    {
    return ((aFormFlag != CMTPTypeObjectPropDesc::EDateTimeForm) && (aFormFlag != CMTPTypeObjectPropDesc::ENone) && (aFormFlag != CMTPTypeObjectPropDesc::EObjectIDForm) );
    }

TInt CMTPTypeServiceObjPropExtnForm::UpdateWriteSequenceErr(TInt aErr)
    {
    iWriteSequenceErr = aErr;
    return iWriteSequenceErr;        
    }

TBool CMTPTypeServiceObjPropExtnForm::ReadableElementL(TInt aElementId) const
    {
    __ASSERT_ALWAYS((aElementId < ENumElements), Panic(EMTPTypeBoundsError));
    
    TBool ret(ETrue);
    if (aElementId == EForm)
        {
        ret = HasFormField(Uint8L(EFormFlag));
        }
    return ret;
    }
    
TBool CMTPTypeServiceObjPropExtnForm::WriteableElementL(TInt aElementId) const
    {  
    __ASSERT_ALWAYS((aElementId < ENumElements), Panic(EMTPTypeBoundsError));
    
    if (!iInitialised)
        {
        return ETrue;    
        }
    
    if (aElementId == EForm)
        return EFalse;
    
    return ETrue;
    }

const CMTPTypeCompoundBase::TElementInfo& CMTPTypeServiceObjPropExtnForm::ElementInfo(TInt aElementId) const
    {
    __ASSERT_ALWAYS((aElementId < ENumElements), Panic(EMTPTypeBoundsError));
    
    return iElementInfo[aElementId];  
    }   

void CMTPTypeServiceObjPropExtnForm::ConstructL( const TMTPTypeGuid  aPKNamespace, const TUint aPKID, const TDesC& aName, const TUint8 aFormFlag, const MMTPType* aForm )
    {  
    for (TUint i(0); (i < ENumElements); i++)
       {
       const TElementInfo& element(iElementInfo[i]);
       if (ChunkCount() <= element.iChunkId)
           {
           MMTPType* chunk(NULL);
           switch (element.iChunkId)
               {
           case EIdFlat1Chunk:
               iChunkFlat1.OpenL();
               chunk = &iChunkFlat1;
               break;
               
           case EIdNameChunk:
               iChunkName = CMTPTypeString::NewL();
               chunk = iChunkName;
               break;
               
           case EIdFlat2Chunk:
               iChunkFlat2.OpenL();
               chunk = &iChunkFlat2;
               break;
               
           case EIdFormChunk:
               iChunkForm.SetMeta(aFormFlag, iDataType);
               if (HasFormField(aFormFlag))
                   {
                   iChunkForm.OpenL(element.iType);
                   chunk = &iChunkForm;
                   SetExpectedChunkCount(KNumChunksWithForm);
                   }
               break;
               
           default:
               Panic(EMTPTypeBoundsError);
               break;
               }
                   
           if (chunk)
               {
               ChunkAppendL(*chunk);   
               }
           }
       }      
    // Set the construction values.
    SetL( EPKeyNamespace, aPKNamespace );
    SetUint32L( EPKeyID, aPKID );
    SetStringL( EPropertyName, aName );
    SetUint8L(EFormFlag, aFormFlag);
    
    if (aForm)
        {
        if (!HasFormField(aFormFlag))
            { 
            User::Leave(KMTPDataTypeInvalid);
            } 
        else
            {
            SetL(EForm, *aForm); 
            }
        }
    
    iInitialised = ETrue;
    }