--- a/xcfw/src/xcfwengine.cpp Tue Feb 02 00:23:10 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1394 +0,0 @@
-/*
-* Copyright (c) 2002-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: Implementation of XCFW Engine
-*
-*/
-
-
-
-// INCLUDE FILES
-#include "xcfwengine.h"
-#include "gecoobjectfactorybase.h"
-#include "gecodefaultobject.h"
-#include "xcfwtree.h"
-#include "xcfwlocalizer.h"
-#include "xcfwpanic.h"
-#include "xcfwentityconverter.h"
-
-#include <gmxmlnode.h>
-#include <gmxmlelement.h>
-#include <gmxmlcomposer.h>
-#include <gmxmldocument.h>
-#include <gmxmlcharacterdata.h>
-#include <gmxmltext.h>
-#include <gmxmlcdatasection.h>
-
-// CONSTANTS
-// default XML declaration
-_LIT( KXMLDeclaration, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
-// default Doctype declaration
-_LIT( KDocTypeDecl, "<!DOCTYPE xcfwml SYSTEM \"%S\">");
-_LIT( KDocTypeDeclNoDTD, "<!DOCTYPE xcfwml>");
-_LIT( KMmsDTD, "mms_smil.dtd"); //this is autogenerated by GMXML if no DTD decl.
-_LIT( KXCFWAnd, "&" );
-_LIT( KXCFWSemiC, ";" );
-_LIT( KDTDExt, ".dtd" );
-_LIT( KLocFormat, "%0*d\\");
-const TInt KDTDExtLen = 4; // ".dtd"
-const TInt KLocFormatLen = 7; // "%0*d\\"
-
-//Entity reference extra character count
-const TInt KExtraChars = 2;
-const TInt KMaxDTDLength = 160;
-
-
-// ============================ MEMBER FUNCTIONS ===============================
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::CXCFWEngine
-// C++ default constructor can NOT contain any code, that
-// might leave.
-// -----------------------------------------------------------------------------
-//
-CXCFWEngine::CXCFWEngine(
- MXCFWEngineObserver* aObserver ):
- CActive( CActive::EPriorityStandard )
- {
- iObserver = aObserver;
- CActiveScheduler::Add( this );
- }
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::ConstructL
-// Symbian 2nd phase constructor can leave.
-// -----------------------------------------------------------------------------
-//
-void CXCFWEngine::ConstructL()
- {
- //Create default object factory
- iDefaultFactory = CGECODefaultObjectFactory::NewL();
- iState = EStateIdle;
- }
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::NewL
-// Two-phased constructor.
-// -----------------------------------------------------------------------------
-//
-EXPORT_C CXCFWEngine* CXCFWEngine::NewL(
- MXCFWEngineObserver* aObserver )
- {
-
- __ASSERT_LEAVE( aObserver!=NULL, KErrArgument );
-
- CXCFWEngine* self = new( ELeave ) CXCFWEngine( aObserver ) ;
-
- CleanupStack::PushL( self );
- self->ConstructL();
- CleanupStack::Pop( self );
-
- return self;
- }
-
-
-// Destructor
-EXPORT_C CXCFWEngine::~CXCFWEngine()
- {
- if ( IsActive() )
- {
- Cancel();
- }
-
- // Reset object factory array (factories are not owned)
- iFactoryList.Reset();
- iFactoryList.Close();
-
- // delete default object factory
- delete iDefaultFactory;
-
- // delete xml parser
- delete iParser;
-
- // delete XML composer
- delete iComposer;
-
- // delete XML document object
- delete iXMLDoc;
-
- // delete XML file name buffer
- delete iFile;
-
- // delete DTD file name buffer
- delete iDTD;
-
- // delete localizer instance
- delete iLocalizer;
-
- // delete node text buffer
- delete iNodeText;
-
- // Set non-owned pointers to NULL
- iCurrentXMLNode = NULL;
- if ( iTree )
- {
- iTree->SetLocked( EFalse );
- iTree = NULL;
- }
- iCurrentTreeNode = NULL;
- iObserver = NULL;
-
- //Close file system handle (just in case)
- iFileSystem.Close();
-
- }
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::RunL
-// Engine conducts itself according to internal state.
-// -----------------------------------------------------------------------------
-//
-void CXCFWEngine::RunL()
- {
-
- TRequestStatus *s = &iStatus;
-
- switch ( iState )
- {
-
- case EStateInitializingLoad:
- {
- //Instantiate parser and request parsing. If ParseFile returns
- //an error code, it is most probably a file that is not found
- //or it can't be currently accessed => leave.
- //we'll get notification from parser through ParseFileCompleteL
- //when ready.
- iState = EStateLoadingFile;
- delete iParser;
- iParser = NULL;
- iParser = CMDXMLParser::NewL( this );
- User::LeaveIfError (
- iParser->ParseFile( iFileSystem, iFile->Des() ) );
- break;
- }
-
- case EStateInitializingSave:
- {
- if ( iLocalizer && iLocalizer->LastError() != KErrNone )
- {
- iObserver->HandleEngineErrorL ( KErrGeneral );
- Cancel();
- FreeResources();
- }
- else
- {
- iState = EStateConstructingDOM;
- SetActive();
- User::RequestComplete( s, KErrNone );
- }
- break;
- }
-
-
- case EStateParsing: //Constructing XCFWTree from DOM
- {
- if ( iCurrentXMLNode )
- {
- iTree->SetLocked( EFalse );
- DOM2TreeNextCycleL();
- iTree->SetLocked( ETrue );
- iState = EStateParsing;
- SetActive();
- User::RequestComplete( s, KErrNone );
- }
- else
- {
- iState = EStateIdle;
- //free parsing resources
- iObserver->HandleEngineEventL(
- MXCFWEngineObserver::EEvtParsingComplete );
- FreeResources();
- }
-
- #ifdef __XCFW_MODULE_TEST
- iObserver->HandleEngineEventL( MXCFWEngineObserver::EEvtNull );
- #endif
-
- break;
- }
-
- case EStateConstructingDOM: //Constructing DOM from XCFW Tree
- {
- if ( iCurrentTreeNode )
- {
- iTree->SetLocked( EFalse );
- Tree2DOMNextCycleL();
- iTree->SetLocked( ETrue );
- iState = EStateConstructingDOM;
- SetActive();
- User::RequestComplete( s, KErrNone );
- }
- else
- {
- iTree->SetLocked( EFalse );
- iState = EStateSavingFile;
- //delete possible previous instance of composer
- //and create new.
- delete iComposer;
- iConverter = NULL; //Deleted by composer
- iConverter = new ( ELeave ) CXCFWEntityConverter;
- iComposer = CMDXMLComposer::NewL( this );
- iComposer->SetEntityConverter( iConverter );
-
- // Ask composer to compose the file.
- // we'll get notification about the op through
- // ComposeFileCompleteL
- User::LeaveIfError(
- iComposer->ComposeFile(
- iFileSystem, iFile->Des(), iXMLDoc, EUtf8 ) );
- }
-
- #ifdef __XCFW_MODULE_TEST
- iObserver->HandleEngineEventL( MXCFWEngineObserver::EEvtNull );
- #endif
-
- break;
- }
-
-
- case EStateIdle: //idle state, not doing anything
- {
- break;
- }
-
- default:
- {
- break;
- }
- }
-
-
- }
-
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::RunError
-// Notify observer about the error and free resources
-// -----------------------------------------------------------------------------
-//
-TInt CXCFWEngine::RunError(
- TInt aError )
- {
- TInt ret = KErrNone;
- iStateByLastError = iState;
-
- FreeResources();
-
- TRAP( ret, iObserver->HandleEngineErrorL( aError ) );
- return ret;
- }
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::DoCancel
-// Notify observer about operation cancellation and free resources.
-// -----------------------------------------------------------------------------
-//
-void CXCFWEngine::DoCancel()
- {
- TInt state = iState;
- FreeResources();
- switch ( state )
- {
- case EStateInitializingLoad: //fallthrough
- case EStateParsing:
- {
- TInt err = 0;
- TRAP(err, iObserver->HandleEngineEventL(
- MXCFWEngineObserver::EEvtParsingCanceled ) );
- break;
- }
- case EStateInitializingSave: //fallthrough
- case EStateConstructingDOM:
- {
- TInt err = 0;
- TRAP(err, iObserver->HandleEngineEventL(
- MXCFWEngineObserver::EEvtSavingCanceled ) );
- break;
- }
- default:
- break;
- }
- }
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::CancelOperation
-// -----------------------------------------------------------------------------
-//
-EXPORT_C void CXCFWEngine::CancelOperation()
- {
-
- Cancel();
- //in case engine was not active, need to free the resources here.
- FreeResources();
-
- }
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::LoadL
-// Wrapper to support loading of XML without giving a DTD file name (i.e. when
-// loading content that has no localized strings)
-// -----------------------------------------------------------------------------
-//
-EXPORT_C void CXCFWEngine::LoadL(
- MXCFWTree& aTree,
- const TDesC& aFile )
- {
- LoadL( aTree, aFile, KNullDesC );
- }
-
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::LoadL
-// XML loading operation is started. Internal members are initialized and
-// object is set active.
-// -----------------------------------------------------------------------------
-//
-EXPORT_C void CXCFWEngine::LoadL(
- MXCFWTree& aTree,
- const TDesC& aFile,
- const TDesC& aDTDFile )
- {
-
- // If we're active at the moment or iState is something else than Idle,
- // leave with KErrInUse.
- if ( IsActive() || iState != EStateIdle )
- {
- User::Leave( KErrInUse );
- }
-
- User::LeaveIfError( iFileSystem.Connect() );
-
- //delete previous instances of parser and DTD name buffers
- delete iParser;
- iParser = NULL;
- delete iDTD;
- iDTD = NULL;
- iDTD = aDTDFile.AllocL();
- delete iFile;
- iFile = NULL;
- iFile = aFile.AllocL();
-
- //Set tree to use (not owned)
- iTree = &aTree;
- if ( iTree->Root () )
- {
- //if the tree has already a root, we'll load items under that root
- iCurrentTreeNode = iTree->Root();
- }
- else
- {
- iCurrentTreeNode = NULL;
- }
-
- iStateByLastError = EStateIdle;
-
- //Reset possible DTD name
- iTree->SetDTDNameL( aDTDFile );
- iTree->SetLocked( ETrue );
-
- delete iParser;
- iParser = NULL;
- iParser = CMDXMLParser::NewL( this );
- User::LeaveIfError (
- iParser->ParseFile( iFileSystem, iFile->Des() ) );
- iState = EStateLoadingFile;
-
- }
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::SaveL
-// Wrapper to support saving of XML without giving a DTD file name (i.e. when
-// saving content that has no localized strings)
-// -----------------------------------------------------------------------------
-//
-EXPORT_C void CXCFWEngine::SaveL(
- MXCFWTree& aTree,
- const TDesC& aFile )
- {
- SaveL( aTree, aFile, aTree.DTDName() );
- }
-
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::SaveL
-// Save operation is initialized and started
-// -----------------------------------------------------------------------------
-//
-EXPORT_C void CXCFWEngine::SaveL(
- MXCFWTree& aTree,
- const TDesC& aFile,
- const TDesC& aDTDFile )
- {
-
- if ( IsActive() || iState != EStateIdle )
- {
- User::Leave( KErrInUse );
- }
-
- User::LeaveIfError( iFileSystem.Connect() );
-
- //create folder if not exist
- TChar bs = '\\';
- if ( aFile.Locate( bs ) != KErrNotFound )
- {
- TPtrC dir = aFile.Left( aFile.LocateReverse( bs ) + 1 );
- TInt ret = iFileSystem.MkDirAll( dir );
- if ( KErrAlreadyExists != ret && KErrNone != ret )
- {
- User::Leave( ret );
- }
- }
-
- //Set tree pointer ( not owned )
- iTree = &aTree;
- if ( iTree->Root () )
- {
- //init current tree node to root if there's one
- iCurrentTreeNode = iTree->Root();
- }
- else
- {
- // this tree can't be saved, has no data
- User::Leave( KErrArgument );
- }
-
- //delete previous instances of parser and filename buffers
- delete iComposer;
- iComposer = NULL;
-
- delete iFile;
- iFile = NULL;
- iFile = aFile.AllocL();
-
- delete iDTD;
- iDTD = NULL;
- iDTD = aDTDFile.AllocL();
-
- iStateByLastError = EStateIdle;
-
- // delete possible previous instance of XML Doc object
- // create new doc and initialize with XML decl + Doctype
- delete iXMLDoc;
- iXMLDoc = NULL;
- iXMLDoc = CMDXMLDocument::NewL();
- iXMLDoc->SetVersionTagL( KXMLDeclaration );
-
- // set doc type tag according to given DTD file name
- if ( aDTDFile.Compare ( KNullDesC) != 0 )
- {
- TBuf<KMaxDTDLength> buf;
- TInt bsloc = aDTDFile.LocateReverse( bs );
-
- // take just the file name, no preceding path chars
- // (the assumption is that loc files are stored
- // at relative path \locNN\dtdname.dtd related to
- // XML file location)
- if ( bsloc != KErrNotFound)
- {
- TPtrC dtdname = aDTDFile.Mid( bsloc + 1 );
- buf.Format( KDocTypeDecl, &dtdname);
- }
- else
- {
- buf.Format( KDocTypeDecl, &aDTDFile );
- }
-
- iXMLDoc->SetDocTypeTagL( buf );
- }
- else
- {
- iXMLDoc->SetDocTypeTagL( KDocTypeDeclNoDTD );
- }
- // notify observer that we're about to start saving
- iObserver->HandleEngineEventL(
- MXCFWEngineObserver::EEvtSavingStarted );
-
- iState = EStateInitializingSave;
- PrepareEntityConverterAndSetActiveL();
-
- // lock tree to prevent changes during save
- iTree->SetLocked( ETrue );
- }
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::HasTextData
-// returns ETrue if the current xml node has text data under it.
-// -----------------------------------------------------------------------------
-//
-EXPORT_C TBool CXCFWEngine::HasTextData()
- {
- TBool ret = EFalse;
- if ( iCurrentXMLNode && iCurrentXMLNode->FirstChild() )
- {
- CMDXMLNode::TDOMNodeType t = iCurrentXMLNode->FirstChild()->NodeType();
-
- if ( t == CMDXMLNode::ETextNode || t == CMDXMLNode::ECDATASectionNode )
- {
- ret = ETrue;
- }
- }
- return ret;
- }
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::TextDetailsL
-// returns text details for the current XML node (if it has text)
-// Node may contain CDATA sections, but mixed content is not supported.
-// -----------------------------------------------------------------------------
-//
-EXPORT_C void CXCFWEngine::TextDetailsL(
- TPtrC& aText,
- TBool& aIsLocalized )
- {
- _LIT(KEntityRef, "*&*;*");
-
-
- TInt err = KErrNotFound;
- CMDXMLNode* ptr = iCurrentXMLNode->FirstChild();
-
- if ( ptr )
- {
-
- //delete previous text pointer now
- delete iNodeText;
- iNodeText = NULL;
-
- //loop through all text / cdata elements
- while ( ptr &&
- ( ptr->NodeType() == CMDXMLNode::ETextNode ||
- ptr->NodeType() == CMDXMLNode::ECDATASectionNode ) )
- {
- err = KErrNone;
- TPtrC nextdata;
- switch ( ptr->NodeType() )
- {
- case CMDXMLNode::ETextNode:
- {
- nextdata.Set( ((CMDXMLCharacterData*)ptr)->Data() );
- break;
- }
- case CMDXMLNode::ECDATASectionNode:
- {
- nextdata.Set( ((CMDXMLCDATASection*)ptr)->Data() );
- break;
- }
- default:
- {
- err = KErrNotFound;
- break;
- }
- }
-
- if ( KErrNone == err )
- {
- //create nodetext buffer if we don't have it yet.
- if ( !iNodeText )
- {
- iNodeText = HBufC::NewL( nextdata.Length() );
- iNodeText->Des().Copy( nextdata );
- }
- else
- {
- //increase nodetext buffer and append new data.
- iNodeText = iNodeText->ReAllocL(
- iNodeText->Length() + nextdata.Length() );
- iNodeText->Des().Append( nextdata );
- }
- }
- ptr = ptr->NextSibling();
- }
-
- //If we have some text, do localization
- if( iNodeText )
- {
- err = KErrNone;
- aText.Set( *iNodeText );
- aIsLocalized = EFalse;
-
- if ( aText.Match( KEntityRef ) != KErrNotFound && iLocalizer)
- {
- TPtrC ltext;
- if ( KErrNone == iLocalizer->EntityRefToText( aText, ltext ) )
- {
- aText.Set( ltext );
- aIsLocalized = ETrue;
- }
- }
- }
- }
- User::LeaveIfError( err );
- }
-
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::NumAttributes
-// return number of attributes for current XML node
-// -----------------------------------------------------------------------------
-//
-EXPORT_C TInt CXCFWEngine::NumAttributes()
- {
-
- TInt count = 0;
-
- //Return attribute count for normal element only.
- if ( iCurrentXMLNode )
- {
- if ( iCurrentXMLNode->NodeType() == CMDXMLNode::EElementNode )
- {
- count = ((CMDXMLElement*)iCurrentXMLNode)->NumAttributes();
- }
- }
-
- return count;
- }
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::AttributeDetailsL
-// Function reads attributes from current xml node and returns them in TPtrC's
-// -----------------------------------------------------------------------------
-//
-EXPORT_C void CXCFWEngine::AttributeDetailsL(
- const TInt aIndex,
- TPtrC& aAttributeName,
- TPtrC& aAttributeValue,
- TBool& aIsLocalized )
- {
- _LIT(KEntityRef, "*&*;*");
-
-
- //Return attribute details for normal element only.
- if ( iCurrentXMLNode )
- {
- if ( iCurrentXMLNode->NodeType() == CMDXMLNode::EElementNode )
- {
- aIsLocalized = EFalse;
- // Get attribute name + value
- User::LeaveIfError (
- ((CMDXMLElement*)iCurrentXMLNode)->
- AttributeDetails(aIndex, aAttributeName, aAttributeValue) );
-
- // query localizer component for localized text
- if ( aAttributeValue.Match( KEntityRef ) != KErrNotFound
- && iLocalizer )
- {
- TPtrC ltext;
- if ( KErrNone == iLocalizer->EntityRefToText(
- aAttributeValue, ltext) )
- {
- aAttributeValue.Set( ltext );
- aIsLocalized = ETrue;
- }
- }
- }
- }
- }
-
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::AttributeDetailsL
-// Function reads attributes from current xml node and returns them in TPtrC's
-// -----------------------------------------------------------------------------
-//
-EXPORT_C void CXCFWEngine::AttributeDetailsL(
- const TInt aIndex,
- TPtrC& aAttributeName,
- TPtrC& aAttributeValue)
- {
-
- //Return attribute details for normal element only.
- if ( iCurrentXMLNode )
- {
- if ( iCurrentXMLNode->NodeType() == CMDXMLNode::EElementNode )
- {
- // Get attribute name + value
- User::LeaveIfError (
- ((CMDXMLElement*)iCurrentXMLNode)->
- AttributeDetails(aIndex, aAttributeName, aAttributeValue) );
- }
- }
- }
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::UnRegisterObjectFactory
-// Removes given object factory pointer from factory array. Does not delete.
-// -----------------------------------------------------------------------------
-//
-EXPORT_C TInt CXCFWEngine::UnRegisterObjectFactory(
- CGECOObjectFactoryBase* aFactory )
- {
-
- TInt err = KErrNotFound;
- TInt maxindex = iFactoryList.Count() - 1;
-
- for ( TInt i = maxindex; i >= 0 ; i-- )
- {
- if ( iFactoryList[i] == aFactory )
- {
- iFactoryList.Remove(i);
- err = KErrNone;
- }
- }
-
- return err;
-
- }
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::RegisterObjectFactory
-// Adds given object factory pointer to factory array. Ownership NOT taken.
-// Adding same factory many times is not possible.
-// -----------------------------------------------------------------------------
-//
-EXPORT_C void CXCFWEngine::RegisterObjectFactoryL(
- CGECOObjectFactoryBase* aFactory )
- {
-
- __ASSERT_LEAVE ( aFactory != NULL, KErrArgument );
-
- TInt maxindex = iFactoryList.Count() - 1;
-
- for ( TInt i = maxindex; i>= 0 ; i-- )
- {
- if ( iFactoryList[i] == aFactory )
- {
- User::Leave( KErrAlreadyExists );
- }
- }
-
- // add to factory array
- User::LeaveIfError( iFactoryList.Append( aFactory ) );
-
- }
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::ParseFileCompleteL()
-// Detaches parsed XML document from parser. If DTD file was provided in LoadL
-// call, we will next load the DTD for getting entity references ready. If no
-// DTD file was given, we go straight to parsing.
-// -----------------------------------------------------------------------------
-//
-void CXCFWEngine::ParseFileCompleteL()
- {
-
- //see if we have urecoverable errors from GMXML => if error severity is
- //fatal, let's not go any further in processing.
- if ( iParser->ErrorSeverity() == EXMLFatal )
- {
- iStateByLastError = iState;
- iState = EStateIdle;
- iObserver->HandleEngineErrorL( iParser->Error() );
- FreeResources();
- }
- else
- {
- //delete previous instance of document
- if ( iXMLDoc )
- {
- delete iXMLDoc;
- iXMLDoc = NULL;
- }
-
- iXMLDoc = iParser->DetachXMLDoc();
- iCurrentXMLNode = iXMLDoc->DocumentElement()->FirstChild();
-
- //set up DTD if not already done
- PrepareDTDPathL();
-
- TRAPD( err, iObserver->HandleEngineEventL(
- MXCFWEngineObserver::EEvtParsingStarted ) );
- if ( KErrNone != err )
- {
- iObserver->HandleEngineErrorL( err );
- Cancel();
- FreeResources();
- }
-
- //Set active
- iState = EStateParsing;
- PrepareEntityConverterAndSetActiveL();
- }
- }
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::AddCurrentXMLNodeToTreeL
-// New content object is generated, initialized and added to tree. Object
-// initialization is done with a registered object factory if there's such.
-// Otherwise default object factory is used.
-// -----------------------------------------------------------------------------
-//
-void CXCFWEngine::AddCurrentXMLNodeToTreeL()
- {
-
- __ASSERT_LEAVE( iTree && iCurrentXMLNode, KErrGeneral );
-
- CGECOObjectBase* obj = NULL;
- CGECOObjectFactoryBase* factory = NULL;
- TInt count = iFactoryList.Count();
-
- //XCFW will only handle element nodes.
- if ( iCurrentXMLNode->NodeType() == CMDXMLNode::EElementNode )
- {
- if ( count > 0 )
- {
- //loop through factories starting from the most recently added
- //until a factory returns an object for the given tag or we run
- //out of factories.
- for ( TInt i = count-1 ; i>= 0 && !obj ; i--)
- {
- //Query factory for object
- factory = iFactoryList[i];
- obj = factory->
- GetContentObjectAndSetContextL(
- iCurrentXMLNode->NodeName() );
- }
- }
-
- // if none of the user factories recognized this tag,
- // use default factory.
- if ( !obj )
- {
- factory = iDefaultFactory;
- obj = factory->GetContentObjectAndSetContextL(
- iCurrentXMLNode->NodeName() );
- }
- }
-
- //if we have an object, let's add it to tree.
- //otherwise the whole branch starting from this node will
- //be discarded from XCFWTree.
- if ( obj )
- {
- CleanupStack::PushL( obj );
-
- factory->InitializeObjectL( *this );
-
- if ( !iCurrentTreeNode )
- {
- //Adding root.
- iCurrentTreeNode = iTree->AddNodeL( obj );
- }
- else
- {
- //add under certain parent.
- iCurrentTreeNode = iTree->AddNodeL( obj, iCurrentTreeNode );
- }
-
- CleanupStack::Pop( obj );
- }
- else
- {
- //Notify observer about unknown data if current node is an element node
- if ( iCurrentXMLNode->NodeType() == CMDXMLNode::EElementNode )
- {
- iObserver->HandleEngineErrorL( KErrUnknown );
- }
-
- // discard this branch in tree: loop out to next sibling of
- // this node or its parent
- while ( iCurrentXMLNode && !iCurrentXMLNode->NextSibling() )
- {
- iCurrentXMLNode = iCurrentXMLNode->ParentNode();
- if ( iCurrentXMLNode && iCurrentTreeNode->Parent() )
- {
- iCurrentTreeNode = iCurrentTreeNode->Parent();
- }
- }
-
- // set next node pointer to process
- if( iCurrentXMLNode && iCurrentXMLNode->NextSibling() )
- {
- iCurrentXMLNode = iCurrentXMLNode->NextSibling();
- }
- }
-
- }
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::DOM2TreeNextCycleL
-// XML DOM is traversed node by node, and elements are added to content tree.
-// Each call leaves will set iCurrentXMLNode to point to the next DOM node to
-// be processed until there's no more nodes.
-// -----------------------------------------------------------------------------
-//
-void CXCFWEngine::DOM2TreeNextCycleL()
- {
-
- CMDXMLNode* reference = NULL;
-
- if ( iCurrentXMLNode )
- {
-
- reference = iCurrentXMLNode;
-
- //add this XML node data to content tree
- AddCurrentXMLNodeToTreeL();
- // if node was discareded for some reason, let's keep calling
- // until a node is accepted.
- while ( iCurrentXMLNode && iCurrentXMLNode != reference )
- {
- reference = iCurrentXMLNode;
- AddCurrentXMLNodeToTreeL();
- }
-
- if ( !iCurrentXMLNode )
- {
- return;
- }
-
- //if this node has children, go to first child now
- if ( iCurrentXMLNode->FirstChild() )
- {
- iCurrentXMLNode = iCurrentXMLNode->FirstChild();
- }
- else //no children
- {
-
- //update XCFWTree parent node pointer as this xml node had no child
- if ( iCurrentTreeNode && iCurrentTreeNode->Parent() )
- {
- iCurrentTreeNode = iCurrentTreeNode->Parent();
- }
-
- //if there's siblings at the same level, go to next sibling
- if ( iCurrentXMLNode->NextSibling() )
- {
- iCurrentXMLNode = iCurrentXMLNode->NextSibling();
- }
- else //no siblings left
- {
- // get back in the tree to a level that has still siblings left
- while ( iCurrentXMLNode && !iCurrentXMLNode->NextSibling() )
- {
- iCurrentXMLNode = iCurrentXMLNode->ParentNode();
- // update XCFWTree parent pointer if necessary
- if ( iCurrentXMLNode &&
- iCurrentTreeNode && iCurrentTreeNode->Parent() )
- {
- iCurrentTreeNode = iCurrentTreeNode->Parent();
- }
- }
- // now we're either at a level that has siblings, or then
- // we're out of nodes. If there's a sibling, we'll process
- // that next
- if( iCurrentXMLNode && iCurrentXMLNode->NextSibling() )
- {
- iCurrentXMLNode = iCurrentXMLNode->NextSibling();
- }
- }
- }
- }
- }
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::CurrentState()
-// Returns engine's internal state. Client may want to know this at error
-// situations to determine if a retry would be necessary.
-// -----------------------------------------------------------------------------
-//
-EXPORT_C CXCFWEngine::TXCFWEngineState CXCFWEngine::CurrentState()
- {
- //If the last state change was by an error, return the state that
- //engine was in when error occurred (error routine will set the state to
- //EStateIdle). Otherwise return the current state.
- if ( iStateByLastError != EStateIdle )
- {
- return iStateByLastError;
- }
- else
- {
- return iState;
- }
- }
-
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::ComposeFileCompleteL()
-// Called by GMXML composer when DOM has been saved to file.
-// Possible fatal errors are sent forward to XCFW client. Otherwise the client
-// is just informed with saving completed event.
-// -----------------------------------------------------------------------------
-//
-void CXCFWEngine::ComposeFileCompleteL()
- {
-
- //see if we have urecoverable errors from GMXML => if error severity is
- //fatal, let's not go any further in processing.
- if ( iComposer->ErrorSeverity() == EXMLFatal )
- {
- TInt err = iComposer->Error();
- iStateByLastError = iState;
- iState = EStateIdle;
- FreeResources();
- iObserver->HandleEngineErrorL( err );
- }
- else
- {
- FreeResources();
- iObserver->HandleEngineEventL(
- MXCFWEngineObserver::EEvtSavingComplete );
- }
- }
-
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::Tree2DOMNextCycleLL
-// XCFWTree is traversed node by node, and elements are added to XML DOM.
-// Each call leaves will set iCurrentTreeNode to point to the next node to
-// be processed until there's no more nodes left in XCFW Tree.
-// -----------------------------------------------------------------------------
-//
-void CXCFWEngine::Tree2DOMNextCycleL()
- {
-
- MXCFWNode* reference = NULL;
-
- if ( iCurrentTreeNode )
- {
-
- reference = iCurrentTreeNode;
-
- //add this tree node data to DOM
- AddCurrentTreeNodeToDOML();
- // if node was discareded for some reason, let's keep calling
- // until a node is accepted.
- while ( iCurrentTreeNode && iCurrentTreeNode != reference )
- {
- reference = iCurrentTreeNode;
- AddCurrentTreeNodeToDOML();
- }
-
- if ( !iCurrentTreeNode )
- {
- return;
- }
-
- //if this node has children, go to first child now
- if ( iCurrentTreeNode->FirstChild() )
- {
- iCurrentTreeNode = iCurrentTreeNode->FirstChild();
- }
- else //no children
- {
-
- //update DOM parent node pointer as this Tree node had no child
- if ( iCurrentXMLNode && iCurrentXMLNode->ParentNode() )
- {
- iCurrentXMLNode = iCurrentXMLNode->ParentNode();
- }
-
- //if there's siblings at the same level, go to next sibling
- if ( iCurrentTreeNode->NextSibling() )
- {
- iCurrentTreeNode = iCurrentTreeNode->NextSibling();
- }
- else //no siblings left
- {
- // get back in the tree to a level that has still siblings left
- while ( iCurrentTreeNode && !iCurrentTreeNode->NextSibling() )
- {
- iCurrentTreeNode = iCurrentTreeNode->Parent();
- // update DOM parent pointer if necessary
- if ( iCurrentTreeNode &&
- iCurrentXMLNode && iCurrentXMLNode->ParentNode() )
- {
- iCurrentXMLNode = iCurrentXMLNode->ParentNode();
- }
- }
- // now we're either at a level that has siblings, or then
- // we're out of nodes. If there's a sibling, we'll process
- // that next
- if( iCurrentTreeNode && iCurrentTreeNode->NextSibling() )
- {
- iCurrentTreeNode = iCurrentTreeNode->NextSibling();
- }
- }
- }
- }
- }
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::AddCurrentTreeNodeToDOML
-// New XML DOM element node is generated out of the XCFW Tree node data.
-// DOM node data is queried from XCFW Tree node using the corresponding
-// object factory. If registered object factory recognizes this node's typeid,
-// default factory implementation is used.
-// New XML Element node is added to XML DOM.
-// -----------------------------------------------------------------------------
-//
-void CXCFWEngine::AddCurrentTreeNodeToDOML()
- {
-
- __ASSERT_LEAVE( iTree && iCurrentTreeNode, KErrGeneral );
-
- CGECOObjectBase* obj = iCurrentTreeNode->Data();
- CGECOObjectFactoryBase* factory = NULL;
- TInt count = iFactoryList.Count();
- TInt err = KErrNotSupported;
- //Find factory for the current tree node
- if ( count > 0 )
- {
- //loop through factories starting from the most recently added
- //until a factory returns KErrNone for SetContext or we run out
- //of factories
- for ( TInt i = count-1 ; i>= 0 && KErrNone != err ; i--)
- {
- //Query factory for object
- factory = iFactoryList[i];
- err = factory->SetContext( obj );
- }
- }
-
- // if none of the user factories recognized this object,
- // use default factory.
- if ( KErrNone != err )
- {
- factory = iDefaultFactory;
- err = factory->SetContext( obj );
- }
-
-
- //if we have an object, let's add it to tree.
- //otherwise the whole branch starting from this node will
- //be discarded from XCFWTree.
- if ( err == KErrNone )
- {
- CMDXMLElement* node = CMDXMLElement::NewLC(
- ETrue, iXMLDoc, obj->TypeIdentifier() );
-
- TInt counter = factory->NumAttributes() - 1;
- while ( counter >= 0 )
- {
- TPtrC attrname;
- TPtrC attrvalue;
- HBufC* ebuf = NULL;
- factory->AttributeDetailsL( counter, attrname, attrvalue );
-
- node->SetAttributeL( attrname, attrvalue, ETrue );
-
- if ( ebuf )
- {
- CleanupStack::PopAndDestroy( ebuf );
- }
-
- counter--;
- }
-
- //if object has text data, let's put it to a child node...
- if ( factory->HasTextData() )
- {
- CMDXMLText* textnode = CMDXMLText::NewLC( iXMLDoc );
- TPtrC text;
- TBool locstatus;
- factory->TextDetailsL( text, locstatus );
- HBufC* ebuf = NULL;
- //Check localization
- if ( locstatus && iLocalizer )
- {
- TPtrC eref;
- if ( KErrNone == iLocalizer->TextToEntityRef( text, eref ) )
- {
- ebuf = HBufC::NewLC( eref.Length() + KExtraChars );
- ebuf->Des().Copy( KXCFWAnd );
- ebuf->Des().Append( eref );
- ebuf->Des().Append( KXCFWSemiC );
- text.Set( ebuf->Des() );
- }
- }
- textnode->SetDataL( text );
- node->AppendChild( textnode );
- //destroying entity ref buffer is safe now
- if ( ebuf )
- {
- CleanupStack::PopAndDestroy( ebuf );
- }
- CleanupStack::Pop( textnode );
- }
-
- if ( !iCurrentXMLNode )
- {
- iXMLDoc->DocumentElement()->AppendChild(node);
- }
- else
- {
- iCurrentXMLNode->AppendChild( node );
- }
- iCurrentXMLNode = node;
- CleanupStack::Pop( node );
- }
- else
- {
- //Notify observer about unknown data
- iObserver->HandleEngineErrorL( KErrUnknown );
-
- // discard this branch in tree: loop out to next sibling of
- // this node or its parent
- while ( iCurrentTreeNode && !iCurrentTreeNode->NextSibling() )
- {
- iCurrentTreeNode = iCurrentTreeNode->Parent();
- if ( iCurrentTreeNode && iCurrentXMLNode->ParentNode() )
- {
- iCurrentXMLNode = iCurrentXMLNode->ParentNode();
- }
- }
-
- // set next node pointer to process
- if( iCurrentTreeNode && iCurrentTreeNode->NextSibling() )
- {
- iCurrentTreeNode = iCurrentTreeNode->NextSibling();
- }
- }
- }
-
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::FreeResources
-// XML parser / composer resources are freed (DOM tree will be deleted from mem)
-// File name buffers are freed.
-// -----------------------------------------------------------------------------
-//
-void CXCFWEngine::FreeResources()
- {
- iState = EStateIdle;
- iFileSystem.Close();
- delete iParser;
- iParser = NULL;
- delete iComposer;
- iComposer = NULL;
- delete iFile;
- iFile = NULL;
- delete iDTD;
- iDTD = NULL;
- delete iXMLDoc;
- iXMLDoc = NULL;
- iCurrentXMLNode = NULL;
- iCurrentTreeNode = NULL;
- if ( iTree )
- {
- iTree->SetLocked( EFalse );
- iTree = NULL;
- }
- }
-
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::PrepareEntityConverterL
-// Localizer is created and DTD load is requested. Localizer will complete
-// pending request when done => Engine's RunL will be called.
-// -----------------------------------------------------------------------------
-//
-void CXCFWEngine::PrepareEntityConverterAndSetActiveL()
- {
-
- TRequestStatus *s = &iStatus;
-
- delete iLocalizer;
- iLocalizer = NULL;
- iLocalizer = CXCFWLocalizer::NewL();
-
-
- //If we have a DTD
- if ( iDTD->Des().Compare( KNullDesC ) != 0 )
- {
- // delete possible previous localizer instance and create new.
- // For performance reasons, it could be wise to first
- // check if we're loading the same DTD as last time. This
- // could be done at localizer side.
-
- // Ask Localizer to load Entity references. Localizer will
- // complete the request when ready.
- SetActive();
- TRAPD( err, iLocalizer->LoadDTDL( iDTD->Des(), iFileSystem, &iStatus) );
- if ( KErrNone != err )
- {
- User::RequestComplete(s, KErrNone );
- iObserver->HandleEngineErrorL( KErrDTDLoadFailed );
- //Complete here, since localizer will not do it
- delete iLocalizer;
- iLocalizer = NULL;
- }
- }
- else
- {
- SetActive();
- User::RequestComplete( s, KErrNone );
- }
- }
-
-// -----------------------------------------------------------------------------
-// CXCFWEngine::PrepareDTDPathL()
-// Function checks the XML DOM for doc type declaration and extracts the
-// possible dtd file name from it. DTD path is then created out of
-// XML file location + localization folder template + dtd name.
-// CXCFWLocalizer will then complete the string with current language setting
-// and search for the file using language downgrade path if necessary.
-// -----------------------------------------------------------------------------
-//
-void CXCFWEngine::PrepareDTDPathL()
- {
- //set up DTD if not already done
- if ( iDTD && iXMLDoc && iDTD->Des().Compare ( KNullDesC ) == 0 )
- {
-
- //check if we have a dtd defined...
- const TChar KQuote = '"';
- const TChar KBckSlash = '\\';
- TInt extStart = iXMLDoc->DocTypeTag().Find( KDTDExt );
- if ( extStart != KErrNotFound )
- {
- if ( iXMLDoc->DocTypeTag().Find ( KMmsDTD ) != KErrNotFound )
- {
- iXMLDoc->SetDocTypeTagL( KDocTypeDeclNoDTD );
- }
- else
- {
- TInt delim = iXMLDoc->DocTypeTag().Left( extStart ).
- LocateReverse( KQuote ) + 1;
- TInt bsdelim = iXMLDoc->DocTypeTag().Left( extStart).
- LocateReverse ( KBckSlash ) + 1;
- delim = (bsdelim>delim)?bsdelim:delim;
-
- if ( delim != KErrNotFound )
- {
- TInt dtdnamelen = extStart - delim + KDTDExtLen;
- TInt pathlen = iFile->Des().LocateReverse ( KBckSlash );
- delete iDTD;
- iDTD = NULL;
- iDTD = HBufC::NewL( pathlen + dtdnamelen + KLocFormatLen );
- iDTD->Des().Copy( iFile->Des().Left( pathlen ) );
- iDTD->Des().Append( KBckSlash );
- iDTD->Des().Append( KLocFormat );
- iDTD->Des().Append ( iXMLDoc->DocTypeTag().
- Mid( delim, dtdnamelen ) );
- }
- }
- }
- }
-
- if ( iDTD )
- {
- //Store DTD name to tree, so it is available at save.
- iTree->SetDTDNameL( iDTD->Des() );
- }
- }
-
-// End of File