/*
* 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
while (iChangeRequests.Count() )
{
MXdmOperation* request = iChangeRequests[0];
iChangeRequests.Remove( 0 );
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
}
}