diff -r 1a2a00e78665 -r f62f87b200ec xcfw/src/xcfwengine.cpp --- 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 -#include -#include -#include -#include -#include -#include - -// CONSTANTS -// default XML declaration -_LIT( KXMLDeclaration, ""); -// default Doctype declaration -_LIT( KDocTypeDecl, ""); -_LIT( KDocTypeDeclNoDTD, ""); -_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 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