xdmprotocols/XcapProtocol/src/XcapDocument.cpp
changeset 0 c8caa15ef882
child 10 96b99892dd80
child 12 e6a66db4e9d0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xdmprotocols/XcapProtocol/src/XcapDocument.cpp	Tue Feb 02 01:05:17 2010 +0200
@@ -0,0 +1,1097 @@
+/*
+* Copyright (c) 2005 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: CXcapDocument
+*
+*/
+
+
+
+
+// INCLUDE FILES
+#include <f32file.h>
+#include <XdmErrors.h>
+#include "XdmOperationFactory.h"
+#include "XcapProtocol.h"
+#include "XcapDocument.h"
+#include "XcapAppUsage.h"
+#include "XdmXmlParser.h"
+#include "XdmNamespace.h"
+#include "CommonDefines.h"
+#include "XcapDocumentNode.h"
+#include "XcapHttpRequest.h"
+#include "XcapHttpOperation.h"
+#include "XcapHttpTransport.h"
+
+// ================= MEMBER FUNCTIONS =======================
+//
+
+
+// ----------------------------------------------------------
+// CXcapDocument::CXcapDocument
+// 
+// ----------------------------------------------------------
+//
+CXcapDocument::CXcapDocument( TXdmDocType aDocumentType,
+                              const CXdmEngine& aXdmEngine,
+                              const CXcapProtocol& aXcapProtocol ) :
+                              CXdmDocument( CONST_CAST( CXdmEngine&, aXdmEngine ) ),
+                              iDocumentType( aDocumentType ),
+                              iXcapProtocol( CONST_CAST( CXcapProtocol&, aXcapProtocol ) )
+                                                
+    { 
+    }
+
+// ----------------------------------------------------------
+// CXcapDocument::NewL
+// 
+// ----------------------------------------------------------
+//
+CXcapDocument* CXcapDocument::NewL( TXdmDocType aDocumentType,
+                                    const TDesC& aDocumentName,
+                                    const CXdmEngine& aXdmEngine,
+                                    const CXcapProtocol& aXcapProtocol )
+    {
+    CXcapDocument* self = new ( ELeave ) CXcapDocument( aDocumentType, aXdmEngine, aXcapProtocol );
+    CleanupStack::PushL( self );
+    self->BaseConstructL( KXcapOperationFactory, aDocumentName );
+    self->ConstructL();
+    CleanupStack::Pop();
+    return self;
+    }
+
+// ----------------------------------------------------------
+// CXcapDocument::NewL
+// 
+// ----------------------------------------------------------
+//
+CXcapDocument* CXcapDocument::NewL( TXdmDocType aDocumentType,
+                                    const TDesC8& aDocumentName,
+                                    const CXdmEngine& aXdmEngine,
+                                    const CXcapProtocol& aXcapProtocol )
+    {
+    CXcapDocument* self = new ( ELeave ) CXcapDocument( aDocumentType, aXdmEngine, aXcapProtocol );
+    CleanupStack::PushL( self );
+    self->ConstructL( aDocumentName );
+    CleanupStack::Pop();
+    return self;
+    }
+
+// ----------------------------------------------------------
+// CXcapDocument::ConstructL
+// 
+// ----------------------------------------------------------
+//
+void CXcapDocument::ConstructL( const TDesC8& aDocumentName )
+    {
+    BaseConstructL( KXcapOperationFactory, aDocumentName );
+    ConstructL();
+    }
+    
+// ----------------------------------------------------------
+// CXcapDocument::ConstructL
+// 
+// ----------------------------------------------------------
+//
+void CXcapDocument::ConstructL()
+    {
+    InstallAppUsageL();
+    iErrorRoot = CXcapDocumentNode::NewL( iXdmEngine, iXcapProtocol );
+    TPtrC8 root( iXcapProtocol.Transport().RootUri() );
+    #ifdef _DEBUG
+        HBufC8* buf = HBufC8::NewLC( iDocumentName->Des().Length() );
+        buf->Des().Copy( iDocumentName->Des() );
+        TPtr8 nameDesc( buf->Des() );
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::ConstructL()" ) );
+        iXcapProtocol.WriteToLog( _L8( "  Root URI:   %S" ), &root );
+        iXcapProtocol.WriteToLog( _L8( "  Document:   %S" ), &nameDesc );
+        CleanupStack::PopAndDestroy();  //buf
+    #endif
+    RXcapCache* cache = iXcapProtocol.Cache();
+    if( cache )
+        UpdateDocumentInfoL( cache );
+    else
+        {
+        #ifdef _DEBUG
+            iXcapProtocol.WriteToLog( _L8( "  Cache disabled, no info for the document" ) );
+        #endif
+        }
+    CActiveScheduler::Add( this );
+    }
+
+// ----------------------------------------------------
+// CXcapDocument::~CXcapDocument
+// 
+// ----------------------------------------------------
+//
+CXcapDocument::~CXcapDocument()
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::~CXcapDocument()" ) );
+    #endif
+    Cancel();
+    delete iTempCopy;
+    delete iEightBitName;
+    delete iDocumentRoot;
+    delete iErrorRoot;
+    delete iAppUsage;
+    iNamespaces.ResetAndDestroy();
+    iNamespaces.Close();
+    }
+
+// ----------------------------------------------------------
+// CXcapDocument::ResetContents
+// 
+// ----------------------------------------------------------
+//
+void CXcapDocument::ResetContents()
+    {
+    iOptions = 0;
+    delete iDocumentRoot;
+    iDocumentRoot = NULL;
+    delete iErrorRoot;
+    iErrorRoot = NULL;
+    delete iTempCopy;
+    iTempCopy = NULL;
+    iNamespaces.ResetAndDestroy();
+    }
+    
+// ----------------------------------------------------------
+// CXcapDocument::UpdateDocumentInfoL
+// 
+// ----------------------------------------------------------
+//
+void CXcapDocument::UpdateDocumentInfoL( RXcapCache* aCacheClient )
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::UpdateDocumentInfo()" ) );
+    #endif
+    iETagBuffer.Zero();
+    TCacheEntryInfo cacheEntryInfo;
+    TPtrC8 root( iXcapProtocol.Transport().RootUri() );
+    TInt error = aCacheClient->FetchDocumentInfo( 
+                 iETagBuffer, iDocumentName->Des(), root, cacheEntryInfo );    
+    if( error == KErrNone )
+        {
+        iLastAccess = cacheEntryInfo.iLastAccess;
+        iLastModification = cacheEntryInfo.iLastUpdate;
+        iDataLength = cacheEntryInfo.iDataLength;
+        #ifdef _DEBUG
+            const TInt KDateTimeMaxSize = 100;
+            TBuf8<KDateTimeMaxSize> printBuffer;
+            TBuf<KDateTimeMaxSize> dateTimeBuffer;
+            _LIT( KDateTimeFormat, "%D%M%Y%/0%1%/1%2%/2%3%/3 %:0%H%:1%T%:2%S");
+            iLastModification.FormatL( dateTimeBuffer, KDateTimeFormat );
+            printBuffer.Copy( dateTimeBuffer );
+            iXcapProtocol.WriteToLog( _L8( "  ETag:        %S" ), &iETagBuffer );
+            iXcapProtocol.WriteToLog( _L8( "  Size:        %d bytes" ), iDataLength );
+            iXcapProtocol.WriteToLog( _L8( "  Time stamp:  %S" ), &printBuffer );
+        #endif
+        }
+    else
+        {
+        #ifdef _DEBUG
+            iXcapProtocol.WriteToLog( _L8( "  Cache read complete - Error: %d" ), error );
+        #endif
+        }
+    }
+    
+// ----------------------------------------------------
+// CXcapDocument::InstallAppUsageL
+// 
+// ----------------------------------------------------
+//
+void CXcapDocument::InstallAppUsageL()
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::InstallAppUsageL()" ) );
+    #endif  
+    HBufC8* docName = NULL;
+    iAppUsage = CXcapAppUsage::NewL( iXdmEngine, iDocumentType );
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::InstallAppUsageL() type = %d" ), iDocumentType );
+    #endif  
+    TPtrC8 auid = iAppUsage->AUID();
+    if( IsGlobalTree( auid ) )
+        {
+        docName = HBufC8::NewLC( auid.Length() + KGlobalDirName().Length() + 
+                                 KXcapGlobalDocName().Length() );
+        docName->Des().Copy( auid );
+        docName->Des().Append( KGlobalDirName );
+        docName->Des().Append( KXcapGlobalDocName );
+        delete iDocumentName;
+        iDocumentName = NULL;
+        iDocumentName = HBufC::NewL( docName->Des().Length() );
+        iDocumentName->Des().Copy( docName->Des() );
+        CleanupStack::PopAndDestroy();  //docName
+        }
+    else
+        {
+        TPtrC8 user = iXcapProtocol.UserName();
+        docName = HBufC8::NewLC( auid.Length() + user.Length() + 
+                                 KUserDirName().Length() + 1 /*'/'*/ + 
+                                 iDocumentName->Des().Length() );
+        docName->Des().Copy( auid );
+        docName->Des().Append( KUserDirName );
+        docName->Des().Append( user );
+        docName->Des().Append( KSlash );
+        docName->Des().Append( iDocumentName->Des() );
+        delete iDocumentName;
+        iDocumentName = NULL;
+        iDocumentName = HBufC::NewL( docName->Des().Length() );
+        iDocumentName->Des().Copy( docName->Des() );
+        CleanupStack::PopAndDestroy();  //docName
+        }
+    
+    }
+
+// ----------------------------------------------------
+// CXcapDocument::IsGlobalTree
+// 
+// ----------------------------------------------------
+//
+TBool CXcapDocument::IsGlobalTree( const TDesC8& aAuid )
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::IsGlobalTree()" ) );
+    #endif
+    TBool found = EFalse;
+    //Update this array when necessary
+    const TPtrC8 KGlobalTreeAuids[] = { TPtrC8( KXdmCapabilityUsageAUID ) };
+    const TInt count = sizeof( KGlobalTreeAuids ) / sizeof( KGlobalTreeAuids[0] );
+    for( TInt i = 0;!found && i < count;i++ )
+        found = aAuid.Compare( KGlobalTreeAuids[i] ) == 0;
+    return found;
+    }
+    
+// ----------------------------------------------------
+// CXcapDocument::CreateTempCopyL
+// 
+// ----------------------------------------------------
+//
+void CXcapDocument::CreateTempCopyL()
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::CreateTempCopyL()" ) );
+    #endif
+    CXdmDocument* copy = iXdmEngine.CreateDocumentModelL( Name(), iDocumentType );
+    iTempCopy = ( CXcapDocument* )copy;
+    }
+
+// ----------------------------------------------------
+// CXcapDocument::TempCopyL
+// 
+// ----------------------------------------------------
+//
+EXPORT_C CXcapDocument* CXcapDocument::TempCopyL()
+    {
+    return CXcapDocument::NewL( iDocumentType, Name(), iXdmEngine, iXcapProtocol );
+    }
+
+// ----------------------------------------------------
+// CXcapDocument::CreateRootL
+// 
+// ----------------------------------------------------
+//
+CXdmDocumentNode* CXcapDocument::CreateRootL()
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXdmDocument::CreateRootL()" ) );
+    #endif
+    delete iDocumentRoot;
+    iDocumentRoot = NULL;
+    iDocumentRoot = CXcapDocumentNode::NewL( iXdmEngine, iXcapProtocol );
+    return iDocumentRoot;
+    }
+
+// ----------------------------------------------------
+// CXcapDocument::AppendPathPartL
+// 
+// ----------------------------------------------------
+//
+void CXcapDocument::AppendPathPartL( const TDesC& aString )
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::PathPartL()" ) );
+    #endif
+    if( iDocumentRoot != NULL )
+        {
+        CXdmDocumentNode* node = NULL;
+        CXdmDocumentNode* parent = iDocumentRoot;
+        while( parent->NextNode() != NULL )
+            parent = parent->NextNode();
+        node = CXcapDocumentNode::NewL( iXdmEngine, aString, iXcapProtocol, parent );
+        parent->SetNextNode( node );
+        }
+    else iDocumentRoot = CXcapDocumentNode::NewL( iXdmEngine, aString, iXcapProtocol );
+    }
+
+// ----------------------------------------------------
+// CXcapDocument::CurrentExtent
+// 
+// ----------------------------------------------------
+//
+CXdmDocumentNode* CXcapDocument::CurrentExtent() const
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXdmDocument::CurrentExtent()" ) );
+    #endif
+    CXdmDocumentNode* ret = NULL;
+    if( iDocumentRoot != NULL )
+        {
+        CXdmDocumentNode* node = iDocumentRoot;
+        while( node->NextNode() != NULL )
+            node = node->NextNode();
+        ret = node;
+        }
+    else
+        {
+        #ifdef _DEBUG
+            iXcapProtocol.WriteToLog( _L8( " This document does not yet have a root, leave with KErrGeneral" ) );
+        #endif
+        User::Leave( KErrGeneral );
+        }
+    return ret;
+    }
+    
+// ----------------------------------------------------
+// CXcapDocument::DocumentRoot
+// 
+// ----------------------------------------------------
+//
+CXdmDocumentNode* CXcapDocument::DocumentRoot() const
+    {
+    return iDocumentRoot;
+    }     
+
+// ----------------------------------------------------
+// CXcapDocument::ErrorRoot
+// 
+// ----------------------------------------------------
+//
+CXdmDocumentNode* CXcapDocument::ErrorRoot()
+    {
+    if( !iErrorRoot )
+        {
+        iErrorRoot = CXcapDocumentNode::NewL( iXdmEngine, iXcapProtocol );
+        }
+    return iErrorRoot;
+    }
+
+// ----------------------------------------------------
+// CXcapDocument::ResetSubset
+// 
+// ----------------------------------------------------
+//
+EXPORT_C void CXcapDocument::ResetSubset()
+    {
+    CXdmDocument::ResetSubset();
+    delete iDocumentRoot;
+    iDocumentRoot = NULL;
+    iOptions = 0;
+    }
+           
+// ----------------------------------------------------
+// CXcapDocument::ETag
+// 
+// ----------------------------------------------------
+//
+EXPORT_C TDesC8& CXcapDocument::ETag()
+    {
+    return iETagBuffer;
+    }
+        
+// ----------------------------------------------------
+// CXcapDocument::SetETag
+// 
+// ----------------------------------------------------
+//     
+EXPORT_C void CXcapDocument::SetETag( const TDesC8& aETagDesc )
+    {
+    iETagBuffer.Zero();
+    iETagBuffer.Copy( aETagDesc );
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::SetETag()" ) );
+        iXcapProtocol.WriteToLog( _L8( "  New ETag: %S" ), &iETagBuffer );
+    #endif
+    }
+
+// ----------------------------------------------------
+// CXcapDocument::DataLength
+// 
+// ----------------------------------------------------
+//
+EXPORT_C TInt CXcapDocument::DataLength() const
+    {
+    return iDataLength;
+    }
+
+// ----------------------------------------------------
+// CXcapDocument::ApplicationUsage
+// 
+// ----------------------------------------------------
+//
+EXPORT_C CXcapAppUsage& CXcapDocument::ApplicationUsage() const
+    {
+    return *iAppUsage;
+    }
+
+// ----------------------------------------------------
+// CXcapDocument::Protocol
+// 
+// ----------------------------------------------------
+//
+EXPORT_C CXcapProtocol& CXcapDocument::Protocol() const
+    {
+    return iXcapProtocol;
+    }
+    
+// ----------------------------------------------------
+// CXcapDocument::RemoveData
+// 
+// ----------------------------------------------------
+//
+EXPORT_C void CXcapDocument::RemoveData( CXcapDocumentNode* aDocumentNode )
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::RemoveData()" ) );
+    #endif
+    CXcapDocumentNode* parent = ( CXcapDocumentNode* )aDocumentNode->Parent();
+    if( parent != NULL )
+        parent->RemoveNode( aDocumentNode );
+    }
+    
+// ----------------------------------------------------
+// CXcapDocument::StartUpdateL
+// 
+// ----------------------------------------------------
+//
+void CXcapDocument::StartUpdateL()
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::StartUpdateL()" ) );
+    #endif
+    TInt resolverError = 0;
+    if( iXcapProtocol.IsSimRequestPending( resolverError ) )
+        {
+        #ifdef _DEBUG
+            iXcapProtocol.WriteToLog( _L8( "  IMS Resolver pending => add to queue" ) );
+        #endif
+        iXcapProtocol.AppendNotifyeeL( this );
+        }
+    else
+        {
+        if( resolverError == KErrNone && !IsActive() && iChangeRequests.Count() > 0 )
+            {
+            iUpdateIndex = 0;
+            iDocumentState = EXdmDocUpdating;
+            iOperationCount = iChangeRequests.Count();
+            ActivateOperationL();
+            }
+        else
+            {
+            #ifdef _DEBUG
+                iXcapProtocol.WriteToLog( _L8(
+                 "  Already active, no operations or IMS resolver failed => complete with error" ) );
+            #endif
+            TInt error = resolverError == KErrNone ? KErrNotReady : resolverError; 
+            User::RequestComplete( iClientStatus, error );
+            }
+        }
+    }
+
+// ----------------------------------------------------
+// CXcapDocument::StartInternalL
+// 
+// ----------------------------------------------------
+//
+void CXcapDocument::StartInternalL( TRequestStatus& aStatus )
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::StartInternalL()" ) );
+    #endif
+    aStatus = KRequestPending;
+    iClientStatus = &aStatus;
+    StartUpdateL();
+    }
+
+// ----------------------------------------------------
+// CXcapDocument::NotifyResolverCompleteL
+// 
+// ----------------------------------------------------
+//
+void CXcapDocument::NotifyResolverCompleteL( TInt aError )
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::NotifyResolverCompleteL()" ) );
+    #endif
+    if( aError == KErrNone )
+        {
+        #ifdef _DEBUG
+            iXcapProtocol.WriteToLog( _L8( "  IMS Resolver ready" ) );
+        #endif
+        StartUpdateL();
+        }
+    else
+        {
+        #ifdef _DEBUG
+            iXcapProtocol.WriteToLog( _L8( "  IMS Resolver failed => complete with %d" ), aError );
+        #endif
+        DequeueAll();
+        User::RequestComplete( iClientStatus, aError );
+        }
+    }
+    
+// ----------------------------------------------------
+// CXcapDocument::ActivateOperationL
+// 
+// ----------------------------------------------------
+//
+void CXcapDocument::ActivateOperationL()
+    {
+    MXdmOperation* request = iChangeRequests[iUpdateIndex];
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::ActivateOperation() - Operation: %x" ), request );
+    #endif
+    if( iDocSubset )
+        {
+        #ifdef _DEBUG
+            iXcapProtocol.WriteToLog( _L8( " Document subset => set KXdmOption1 and KXdmOption2" ) );
+        #endif
+        SetOption( KXdmOption1 );
+        SetOption( KXdmOption2 );
+        }
+    if( iXcapProtocol.AuthType() == EXcapAuthEarlyIms )
+        {
+        #ifdef _DEBUG
+            iXcapProtocol.WriteToLog( _L8( " EarlyIMS is in use => set KXdmOption4" ) );
+        #endif
+        SetOption( KXdmOption4 );
+        }
+    request->ExecuteL( iStatus, iOptions );
+    SetActive();
+    }
+
+// ----------------------------------------------------
+// CXcapDocument::SetOption
+// 
+// ----------------------------------------------------
+//
+void CXcapDocument::SetOption( TInt aOption )
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::SetOption()" ) );
+    #endif
+    iOptions |= aOption;
+    }
+       
+// ----------------------------------------------------
+// CXcapDocument::CancelUpdate
+// 
+// ----------------------------------------------------
+//
+void CXcapDocument::CancelUpdate()
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::CancelUpdate()" ) );
+    #endif
+    TInt resolverError = 0;
+    if( iXcapProtocol.IsSimRequestPending( resolverError ) )
+        {
+        iXcapProtocol.CancelImsResolver();
+        }
+    else
+        {
+        switch( iDocumentState )
+            {
+            case EResolvingAsyncConflict:
+                iTempCopy->CancelUpdate();
+                break;
+            default:
+                {
+                TInt count = iChangeRequests.Count();
+                if( count > 0 )
+                    {
+                    MXdmOperation* request = iChangeRequests[iUpdateIndex];
+                    request->CancelOperation();
+                    #ifdef _DEBUG
+                        iXcapProtocol.WriteToLog( _L8( "  Operation %x cancelled" ), request );
+                    #endif
+                    }
+                }
+            }
+        }
+    User::RequestComplete( iClientStatus, KErrCancel );
+    }
+
+// ---------------------------------------------------------
+// CXcapDocument::RunL()
+// 
+// ---------------------------------------------------------
+//
+void CXcapDocument::RunL()
+    {
+    #ifdef _DEBUG
+        HBufC8* buf = HBufC8::NewLC( iDocumentName->Des().Length() );
+        buf->Des().Copy( iDocumentName->Des() );
+        TPtr8 nameDesc( buf->Des() );
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::RunL()" ) );
+        iXcapProtocol.WriteToLog( _L8( "  Name:         %S" ), &nameDesc );
+        iXcapProtocol.WriteToLog( _L8( "  Error:        %d" ), iStatus.Int() );
+        iXcapProtocol.WriteToLog( _L8( "  Update index: %d" ), iUpdateIndex );
+        CleanupStack::PopAndDestroy();  //buf
+    #endif
+    if( iStatus == KErrNone )
+        {
+        switch( iDocumentState )
+            {
+            case EXdmDocUpdating:
+                #ifdef _DEBUG
+                    iXcapProtocol.WriteToLog( _L8( "  Document state: EXdmDocUpdating" ) );
+                #endif
+                HandleRequestCompletionL();
+                break;
+            case EResolvingAsyncConflict:
+                #ifdef _DEBUG
+                    iXcapProtocol.WriteToLog( _L8( "  Document state: EResolvingAsyncConflict" ) );
+                #endif
+                ResolveAsyncConflictL();
+                break;
+            case ERetryingFailedOperation:
+                #ifdef _DEBUG
+                    iXcapProtocol.WriteToLog( _L8( "  Document state: ERetryingFailedOperation" ) );
+                #endif
+                ResolveAsyncConflictL();
+                break;
+            default:
+                break;
+            }
+        }
+    else HandleErrorL();
+    #ifdef _DEBUG
+        TInt biggestBlock( 0 );
+        TInt memory( User::Available( biggestBlock ) );
+        iXcapProtocol.WriteToLog( _L8( "** RunL() completes - Available memory: %d" ), memory );
+    #endif
+    }
+
+// ---------------------------------------------------------
+// CXcapDocument::HandleRequestCompletionL
+// 
+// ---------------------------------------------------------
+//
+void CXcapDocument::HandleRequestCompletionL()
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::HandleRequestCompletionL()" ) );
+    #endif
+    MXdmOperation* request = iChangeRequests[iUpdateIndex];
+    const TXdmCompletionData& data = request->CompletionData();
+    switch( data.iCompletion )
+        {
+        case KInsertConflict:
+            ResolveAsyncConflictL();
+            break;
+        default:
+            {
+            RXcapCache* cache = iXcapProtocol.Cache();
+            if( cache )
+                UpdateDocumentInfoL( cache );
+            DequeueOperation( request );
+            CheckOperationQueueL();
+            break;
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CXcapDocument::ResolveAsyncConflictL
+// 
+// ---------------------------------------------------------
+//
+void CXcapDocument::ResolveAsyncConflictL()
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::ResolveAsyncConflictL()" ) );
+    #endif
+    switch( iDocumentState )
+        {
+        //This means the cached version of this document
+        //is out-of-date and that it needs to be updated.
+        case EXdmDocUpdating:
+            {
+            CreateTempCopyL();
+            iTempCopy->SetETag( iETagBuffer );
+            iTempCopy->FetchDataL();
+            iTempCopy->SaveClientStatus( iStatus );
+            iTempCopy->StartUpdateL();
+            iDocumentState = EResolvingAsyncConflict;
+            SetActive();
+            }
+            break;
+        case EResolvingAsyncConflict:
+            #ifdef _DEBUG
+                iXcapProtocol.WriteToLog( _L8( "  Async conflict resolved, retry insert" ) );
+            #endif
+            //CheckOperationQueueL() will increment the index
+            iUpdateIndex--;
+            SetETag( iTempCopy->ETag() );
+            iDocumentState = ERetryingFailedOperation;
+            CheckOperationQueueL();
+            break;
+        case ERetryingFailedOperation:
+            #ifdef _DEBUG
+                iXcapProtocol.WriteToLog( _L8( "  Operation retry ready" ) );
+            #endif
+            //Nothing can be done now but instruct the
+            //client to re-fetch the whole document and
+            //retry the failed operation.
+            User::RequestComplete( iClientStatus, KErrPathNotFound );
+            break;
+        default:
+            break;
+        }
+    }
+    
+// ---------------------------------------------------------
+// CXcapDocument::HandleErrorL
+// 
+// ---------------------------------------------------------
+//
+void CXcapDocument::HandleErrorL()
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::HandleErrorL()" ) );
+    #endif
+    TInt clientCode = KErrGeneral;
+    MXdmOperation* request = request = iChangeRequests[iUpdateIndex];
+    //The TXdmCompletionData is guaranteed to point at something 
+    const TXdmCompletionData& data = request->CompletionData();
+    switch( data.iCompletion )
+        {
+        case KErrCancel:
+            #ifdef _DEBUG
+                iXcapProtocol.WriteToLog( _L8( " Update cancelled" ) );
+            #endif
+            clientCode = KErrCancel;
+            break;
+        case ERetryingFailedOperation:
+            #ifdef _DEBUG
+                iXcapProtocol.WriteToLog( _L8( "  Operation retry failed" ) );
+            #endif
+            //Nothing can be done now but instruct the
+            //client to re-fetch the whole document and
+            //retry the failed operation.
+            User::RequestComplete( iClientStatus, KXcapErrorUnrecoverableConflict );
+            break;
+        case KXcapErrorHttpConflict:
+            #ifdef _DEBUG
+                iXcapProtocol.WriteToLog( _L8( "  Conflict, parse error document if available" ) );
+            #endif
+            if( data.iResponseData != NULL )
+                {
+                TInt error = KErrNone;
+                TPtrC8 errorData( data.iResponseData->Des() );
+                TRAP( error, iXcapProtocol.Parser().ParseDocumentL( errorData, ErrorRoot() ) );
+                #ifdef _DEBUG
+                    iXcapProtocol.WriteToLog( _L8( "  Parsing completed: %d" ), error );
+                    ErrorRoot()->Print();
+                #endif
+                //Suppress build warning
+                error = KErrNone;
+                }
+		        User::RequestComplete( iClientStatus, KXcapErrorHttpConflict );
+            break;
+        case KXcapErrorNetworkNotAvailabe:
+            {
+            #ifdef _DEBUG
+                iXcapProtocol.WriteToLog( _L8( "  Network not available, check cache" ) );
+            #endif
+            if( iDataLength > 0 )
+                {
+                RXcapCache* cache = iXcapProtocol.Cache();
+                if( cache != NULL )
+                    {
+                    TPtrC name( Name() );
+                    TInt error = KErrNone;
+                    TPtrC8 root = iXcapProtocol.Transport().RootUri();
+                    HBufC8* data = HBufC8::NewLC( iDataLength );
+                    TPtr8 dataPtr( data->Des() );
+                    cache->FetchDocumentContent( dataPtr, name, root );
+                    TRAP( error, iXcapProtocol.Parser().ParseDocumentL( this, dataPtr ) );
+                    #ifdef _DEBUG
+                        iXcapProtocol.WriteToLog( _L8( "  Parsing completed: %d" ), error );
+                    #endif
+                    //Suppress build warning
+                    error = KErrNone;
+                    CleanupStack::PopAndDestroy();  //data
+                    }
+                }
+            else
+                {
+                #ifdef _DEBUG
+                    iXcapProtocol.WriteToLog( _L8( "  No data in cache, nothing to do" ) );
+                #endif
+                }
+            User::RequestComplete( iClientStatus, KXcapErrorNetworkNotAvailabe );
+            }
+            break;
+        default:
+            #ifdef _DEBUG
+                iXcapProtocol.WriteToLog( _L8( " Default case - Result: %d" ), data.iCompletion );
+            #endif
+            clientCode = iStatus.Int();
+            User::RequestComplete( iClientStatus, clientCode );
+        }
+    DequeueOperation( request );
+    }
+     
+// ---------------------------------------------------------
+// CXcapDocument::CheckOperationQueueL
+// 
+// ---------------------------------------------------------
+//
+void CXcapDocument::CheckOperationQueueL()
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::CheckOperationQueueL()" ) );
+    #endif
+    iUpdateIndex++;
+    if( iUpdateIndex < iOperationCount )
+        ActivateOperationL();
+    else
+        {
+        DequeueAll();
+        iUpdateIndex = 0;
+        iXcapProtocol.CheckActivity();
+        User::RequestComplete( iClientStatus, KErrNone );   
+        }
+    }
+
+// ---------------------------------------------------------
+// CXcapDocument::DequeueOperation
+// 
+// ---------------------------------------------------------
+//
+void CXcapDocument::DequeueOperation( MXdmOperation* aOperation )
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::DequeueOperation()" ) );
+    #endif
+    TInt index = iChangeRequests.Find( aOperation );
+    if( index >= 0 )
+    	{	
+		iChangeRequests.Remove( index );    
+        aOperation->Destroy();
+        aOperation = NULL;
+    	}  
+   	iOperationCount = iChangeRequests.Count();
+    }
+
+// ---------------------------------------------------------
+// CXcapDocument::DequeueAll
+// 
+// ---------------------------------------------------------
+//
+void CXcapDocument::DequeueAll()
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::DequeueAll()" ) );
+    #endif
+    TInt count = iChangeRequests.Count();
+    for( TInt i = 0;i < count;i++ )
+    	{
+    	MXdmOperation* request = iChangeRequests[i];
+    	iChangeRequests.Remove( i );
+    	request->Destroy();
+    	request = NULL;
+    	} 
+    }
+      
+// ---------------------------------------------------------
+// CXcapDocument::EightBitNameLC
+// 
+// ---------------------------------------------------------
+//
+HBufC8* CXcapDocument::EightBitNameLC()
+    {
+    /*#ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::EightBitNameLC()" ) );
+    #endif*/
+    __ASSERT_DEBUG( Name().Length() > 0, User::Panic( _L( "CXcapDocument" ), 1 ) );
+    HBufC8* buf = HBufC8::NewLC( Name().Length() );
+    buf->Des().Copy( Name() );
+    return buf;
+    }
+
+// ---------------------------------------------------------
+// CXcapDocument::DocumentType
+// 
+// ---------------------------------------------------------
+//
+TXdmDocType CXcapDocument::DocumentType() const
+    {
+    return iDocumentType;
+    }
+
+// ---------------------------------------------------------
+// CXcapDocument::AppendNamespaceL
+// 
+// ---------------------------------------------------------
+//
+void CXcapDocument::AppendNamespaceL( const TDesC8& aUri, const TDesC8& aPrefix )
+    {
+    CXdmNamespace* ns = CXdmNamespace::NewL( aUri, aPrefix );
+    CleanupStack::PushL( ns );
+    User::LeaveIfError( iNamespaces.Append( ns ) );
+    CleanupStack::Pop();  //ns
+    }
+
+// ---------------------------------------------------------
+// CXcapDocument::RemoveNamespace
+// 
+// ---------------------------------------------------------
+//
+void CXcapDocument::RemoveNamespace( const TDesC8& aUri )
+    {
+    TBool found = EFalse;
+    CXdmNamespace* ns = NULL;
+    TInt count = iNamespaces.Count();
+    for( TInt i = 0;!found && i < count;i++ )
+        {
+        ns = iNamespaces[i];
+        if( ns->Uri().Compare( aUri ) == 0 )
+            {
+            found = ETrue;
+            iNamespaces.Remove( i );
+            delete ns;
+            ns = NULL;
+            }
+        }
+    }
+                    
+// ---------------------------------------------------------
+// CXcapDocument::Uri
+// 
+// ---------------------------------------------------------
+//
+TPtrC8 CXcapDocument::Uri( const TDesC8& aPrefix ) const
+    {
+    TPtrC8 uri( _L8( "" ) );
+    TBool found = EFalse;
+    TInt count = iNamespaces.Count();
+    for( TInt i = 0;!found && i < count ;i++ )
+        {
+        if( iNamespaces[i]->Prefix().Compare( aPrefix ) == 0 )
+            {
+            uri.Set( iNamespaces[i]->Uri() );
+            found = ETrue;
+            }
+        }
+    return uri;
+    }
+
+// ---------------------------------------------------------
+// CXcapDocument::Count
+// 
+// ---------------------------------------------------------
+//
+TInt CXcapDocument::Count() const
+    {
+    return iNamespaces.Count();
+    }
+
+// ---------------------------------------------------------
+// CXcapDocument::Prefix
+// 
+// ---------------------------------------------------------
+//
+TPtrC8 CXcapDocument::Prefix( TInt aIndex ) const
+    {
+    TInt count = iNamespaces.Count();
+    if( count > 0 && ( aIndex >= 0 && aIndex < count ) )
+        return iNamespaces[aIndex]->Prefix();
+    else return TPtrC8();
+    }
+    
+// ---------------------------------------------------------
+// CXcapDocument::Uri
+// 
+// ---------------------------------------------------------
+//
+TPtrC8 CXcapDocument::Uri( TInt aIndex ) const
+    {
+    TInt count = iNamespaces.Count();
+    if( count > 0 && ( aIndex >= 0 && aIndex < count ) )
+        return iNamespaces[aIndex]->Uri();
+    else return TPtrC8();
+    }
+    
+// ---------------------------------------------------------
+// CXcapDocument::ResetNamespaces
+// 
+// ---------------------------------------------------------
+//
+void CXcapDocument::ResetNamespaces( ) 
+    {   
+    iNamespaces.ResetAndDestroy();
+    } 
+    
+// ---------------------------------------------------------
+// CXcapDocument::TimeStamp
+// 
+// ---------------------------------------------------------
+//
+TTime CXcapDocument::TimeStamp() const
+    {
+    return iLastModification;
+    }
+
+// ----------------------------------------------------
+// CXdmDocument::SaveClientStatus
+// 
+// ----------------------------------------------------
+//
+void CXcapDocument::SaveClientStatus( TRequestStatus& aClientStatus )
+    {
+    iClientStatus = &aClientStatus;        
+    }
+            
+// ---------------------------------------------------------
+// CXcapDocument::DoCancel
+// 
+// ---------------------------------------------------------
+//
+void CXcapDocument::DoCancel()
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDocument::DoCancel()" ) );
+    #endif
+    if( iClientStatus )
+        {
+        User::RequestComplete( iClientStatus, KErrCancel );
+        #ifdef _DEBUG
+            iXcapProtocol.WriteToLog( _L8( " Request completed" ) );
+        #endif
+        }
+    else
+        {
+        #ifdef _DEBUG
+            iXcapProtocol.WriteToLog( _L8( " iClientStatus == NULL => do nothing" ) );
+        #endif
+        }
+    }
+
+
+
+