xcfw/src/xcfwengine.cpp
changeset 0 79c6a41cd166
child 3 ff572005ac23
equal deleted inserted replaced
-1:000000000000 0:79c6a41cd166
       
     1 /*
       
     2 * Copyright (c) 2002-2005 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Implementation of XCFW Engine
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include    "xcfwengine.h"
       
    22 #include    "gecoobjectfactorybase.h"
       
    23 #include    "gecodefaultobject.h"
       
    24 #include    "xcfwtree.h"
       
    25 #include    "xcfwlocalizer.h"
       
    26 #include    "xcfwpanic.h"
       
    27 #include    "xcfwentityconverter.h"
       
    28 
       
    29 #include    <gmxmlnode.h>
       
    30 #include    <gmxmlelement.h>
       
    31 #include    <gmxmlcomposer.h>
       
    32 #include    <gmxmldocument.h>
       
    33 #include    <gmxmlcharacterdata.h>
       
    34 #include    <gmxmltext.h>
       
    35 #include    <gmxmlcdatasection.h>
       
    36 
       
    37 // CONSTANTS
       
    38 // default XML declaration
       
    39 _LIT( KXMLDeclaration, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
       
    40 // default Doctype declaration
       
    41 _LIT( KDocTypeDecl, "<!DOCTYPE xcfwml SYSTEM \"%S\">");
       
    42 _LIT( KDocTypeDeclNoDTD, "<!DOCTYPE xcfwml>");
       
    43 _LIT( KMmsDTD, "mms_smil.dtd"); //this is autogenerated by GMXML if no DTD decl.
       
    44 _LIT( KXCFWAnd, "&" );
       
    45 _LIT( KXCFWSemiC, ";" );
       
    46 _LIT( KDTDExt, ".dtd" );
       
    47 _LIT( KLocFormat, "%0*d\\");
       
    48 const TInt KDTDExtLen = 4; // ".dtd"
       
    49 const TInt KLocFormatLen = 7; // "%0*d\\" 
       
    50 
       
    51 //Entity reference extra character count
       
    52 const TInt KExtraChars = 2;
       
    53 const TInt KMaxDTDLength = 160;
       
    54 
       
    55 
       
    56 // ============================ MEMBER FUNCTIONS ===============================
       
    57 
       
    58 // -----------------------------------------------------------------------------
       
    59 // CXCFWEngine::CXCFWEngine
       
    60 // C++ default constructor can NOT contain any code, that
       
    61 // might leave.
       
    62 // -----------------------------------------------------------------------------
       
    63 //
       
    64 CXCFWEngine::CXCFWEngine(
       
    65     MXCFWEngineObserver* aObserver ):
       
    66     CActive( CActive::EPriorityStandard )
       
    67     {
       
    68     iObserver = aObserver;
       
    69     CActiveScheduler::Add( this );
       
    70     }
       
    71 
       
    72 // -----------------------------------------------------------------------------
       
    73 // CXCFWEngine::ConstructL
       
    74 // Symbian 2nd phase constructor can leave.
       
    75 // -----------------------------------------------------------------------------
       
    76 //
       
    77 void CXCFWEngine::ConstructL()
       
    78     {
       
    79     //Create default object factory
       
    80     iDefaultFactory = CGECODefaultObjectFactory::NewL();
       
    81     iState = EStateIdle;
       
    82     }
       
    83 
       
    84 // -----------------------------------------------------------------------------
       
    85 // CXCFWEngine::NewL
       
    86 // Two-phased constructor.
       
    87 // -----------------------------------------------------------------------------
       
    88 //
       
    89 EXPORT_C CXCFWEngine* CXCFWEngine::NewL(
       
    90     MXCFWEngineObserver* aObserver )
       
    91     {
       
    92     
       
    93     __ASSERT_LEAVE( aObserver!=NULL, KErrArgument );
       
    94     
       
    95     CXCFWEngine* self = new( ELeave ) CXCFWEngine( aObserver ) ;
       
    96     
       
    97     CleanupStack::PushL( self );
       
    98     self->ConstructL();
       
    99     CleanupStack::Pop( self );
       
   100 
       
   101     return self;
       
   102     }
       
   103 
       
   104     
       
   105 // Destructor
       
   106 EXPORT_C CXCFWEngine::~CXCFWEngine()
       
   107     {
       
   108     if ( IsActive() )
       
   109         {
       
   110         Cancel();
       
   111         }
       
   112 
       
   113     // Reset object factory array (factories are not owned)
       
   114     iFactoryList.Reset();
       
   115     iFactoryList.Close();    
       
   116 
       
   117     // delete default object factory
       
   118     delete iDefaultFactory;
       
   119 
       
   120     // delete xml parser
       
   121     delete iParser;
       
   122 
       
   123     // delete XML composer
       
   124     delete iComposer;
       
   125 
       
   126     // delete XML document object
       
   127     delete iXMLDoc;
       
   128 
       
   129     // delete XML file name buffer
       
   130     delete iFile;
       
   131 
       
   132     // delete DTD file name buffer
       
   133     delete iDTD;
       
   134 
       
   135     // delete localizer instance
       
   136     delete iLocalizer;
       
   137 
       
   138     // delete node text buffer
       
   139     delete iNodeText;
       
   140 
       
   141     // Set non-owned pointers to NULL
       
   142     iCurrentXMLNode = NULL;
       
   143     if ( iTree )
       
   144         {
       
   145         iTree->SetLocked( EFalse );
       
   146         iTree = NULL;
       
   147         }
       
   148     iCurrentTreeNode = NULL;
       
   149     iObserver = NULL;
       
   150 
       
   151     //Close file system handle (just in case)
       
   152     iFileSystem.Close();
       
   153     
       
   154    }
       
   155 
       
   156 // -----------------------------------------------------------------------------
       
   157 // CXCFWEngine::RunL
       
   158 // Engine conducts itself according to internal state.
       
   159 // -----------------------------------------------------------------------------
       
   160 //
       
   161 void CXCFWEngine::RunL()
       
   162     {
       
   163 
       
   164     TRequestStatus *s = &iStatus;
       
   165     
       
   166     switch ( iState )
       
   167         {
       
   168 
       
   169         case EStateInitializingLoad:
       
   170             {
       
   171             //Instantiate parser and request parsing. If ParseFile returns
       
   172             //an error code, it is most probably a file that is not found
       
   173             //or it can't be currently accessed => leave.            
       
   174             //we'll get notification from parser through ParseFileCompleteL
       
   175             //when ready.
       
   176             iState = EStateLoadingFile;
       
   177             delete iParser;
       
   178 	    iParser = NULL;
       
   179             iParser = CMDXMLParser::NewL( this );    
       
   180             User::LeaveIfError ( 
       
   181                 iParser->ParseFile( iFileSystem, iFile->Des() ) );
       
   182             break;                
       
   183             }    
       
   184 
       
   185         case EStateInitializingSave:
       
   186             {
       
   187             if ( iLocalizer && iLocalizer->LastError() != KErrNone )
       
   188                 {
       
   189                 iObserver->HandleEngineErrorL ( KErrGeneral );
       
   190                 Cancel();
       
   191                 FreeResources();
       
   192                 }
       
   193             else
       
   194                 {
       
   195                 iState = EStateConstructingDOM;
       
   196                 SetActive();
       
   197                 User::RequestComplete( s, KErrNone );                    
       
   198                 }
       
   199             break;
       
   200             }
       
   201     
       
   202 
       
   203         case EStateParsing: //Constructing XCFWTree from DOM
       
   204             {
       
   205             if ( iCurrentXMLNode )
       
   206                 {
       
   207                 iTree->SetLocked( EFalse );
       
   208                 DOM2TreeNextCycleL();
       
   209                 iTree->SetLocked( ETrue );
       
   210                 iState = EStateParsing;   
       
   211                 SetActive();
       
   212                 User::RequestComplete( s, KErrNone );
       
   213                 }
       
   214             else
       
   215                 {
       
   216                 iState = EStateIdle;
       
   217                 //free parsing resources
       
   218                 iObserver->HandleEngineEventL( 
       
   219                     MXCFWEngineObserver::EEvtParsingComplete );
       
   220                 FreeResources();
       
   221                 }
       
   222 
       
   223             #ifdef __XCFW_MODULE_TEST
       
   224             iObserver->HandleEngineEventL( MXCFWEngineObserver::EEvtNull );                
       
   225             #endif
       
   226 
       
   227             break;
       
   228             }
       
   229 
       
   230         case EStateConstructingDOM: //Constructing DOM from XCFW Tree
       
   231             {
       
   232             if ( iCurrentTreeNode )
       
   233                 {
       
   234                 iTree->SetLocked( EFalse );
       
   235                 Tree2DOMNextCycleL();
       
   236                 iTree->SetLocked( ETrue );
       
   237                 iState = EStateConstructingDOM;
       
   238                 SetActive();
       
   239                 User::RequestComplete( s, KErrNone );
       
   240                 }
       
   241             else
       
   242                 {
       
   243                 iTree->SetLocked( EFalse );
       
   244                 iState = EStateSavingFile;                    
       
   245                 //delete possible previous instance of composer
       
   246                 //and create new.
       
   247                 delete iComposer;
       
   248                 iConverter = NULL; //Deleted by composer
       
   249                 iConverter = new ( ELeave ) CXCFWEntityConverter;
       
   250                 iComposer = CMDXMLComposer::NewL( this );
       
   251                 iComposer->SetEntityConverter( iConverter );
       
   252                 
       
   253 		// Ask composer to compose the file.
       
   254                 // we'll get notification about the op through 
       
   255                 // ComposeFileCompleteL
       
   256                 User::LeaveIfError( 
       
   257                     iComposer->ComposeFile( 
       
   258                     iFileSystem, iFile->Des(), iXMLDoc, EUtf8 ) );
       
   259                 }
       
   260 
       
   261             #ifdef __XCFW_MODULE_TEST
       
   262             iObserver->HandleEngineEventL( MXCFWEngineObserver::EEvtNull );                
       
   263             #endif
       
   264             
       
   265             break;                
       
   266             }
       
   267 
       
   268 
       
   269         case EStateIdle: //idle state, not doing anything
       
   270             {
       
   271             break;
       
   272             } 
       
   273 
       
   274         default:
       
   275             {
       
   276             break;
       
   277             }
       
   278         }
       
   279     
       
   280     
       
   281     }
       
   282 
       
   283 
       
   284 // -----------------------------------------------------------------------------
       
   285 // CXCFWEngine::RunError
       
   286 // Notify observer about the error and free resources
       
   287 // -----------------------------------------------------------------------------
       
   288 //
       
   289 TInt CXCFWEngine::RunError(
       
   290     TInt aError )
       
   291     {
       
   292     TInt ret = KErrNone;
       
   293     iStateByLastError = iState;
       
   294 
       
   295     FreeResources();            
       
   296     
       
   297     TRAP( ret, iObserver->HandleEngineErrorL( aError ) );    
       
   298     return ret;
       
   299     }
       
   300 
       
   301 // -----------------------------------------------------------------------------
       
   302 // CXCFWEngine::DoCancel
       
   303 // Notify observer about operation cancellation and free resources.
       
   304 // -----------------------------------------------------------------------------
       
   305 //
       
   306 void CXCFWEngine::DoCancel()
       
   307     {
       
   308     TInt state = iState;
       
   309     FreeResources();
       
   310     switch ( state )
       
   311         {
       
   312         case EStateInitializingLoad: //fallthrough
       
   313         case EStateParsing:
       
   314             {
       
   315             TInt err = 0;
       
   316             TRAP(err, iObserver->HandleEngineEventL( 
       
   317                 MXCFWEngineObserver::EEvtParsingCanceled ) );
       
   318             break;   
       
   319             }
       
   320         case EStateInitializingSave: //fallthrough
       
   321         case EStateConstructingDOM:
       
   322             {
       
   323             TInt err = 0;
       
   324             TRAP(err, iObserver->HandleEngineEventL( 
       
   325                 MXCFWEngineObserver::EEvtSavingCanceled ) );
       
   326             break;   
       
   327             }
       
   328         default:
       
   329             break;
       
   330         }
       
   331     }
       
   332 
       
   333 // -----------------------------------------------------------------------------
       
   334 // CXCFWEngine::CancelOperation
       
   335 // -----------------------------------------------------------------------------
       
   336 //
       
   337 EXPORT_C void CXCFWEngine::CancelOperation()
       
   338     {
       
   339     
       
   340     Cancel();
       
   341     //in case engine was not active, need to free the resources here.
       
   342     FreeResources();
       
   343                 
       
   344     }
       
   345 
       
   346 // -----------------------------------------------------------------------------
       
   347 // CXCFWEngine::LoadL
       
   348 // Wrapper to support loading of XML without giving a DTD file name (i.e. when
       
   349 // loading content that has no localized strings)
       
   350 // -----------------------------------------------------------------------------
       
   351 //
       
   352 EXPORT_C void CXCFWEngine::LoadL(
       
   353     MXCFWTree& aTree, 
       
   354     const TDesC& aFile )
       
   355     {
       
   356     LoadL( aTree, aFile, KNullDesC );
       
   357     }
       
   358 
       
   359 
       
   360 // -----------------------------------------------------------------------------
       
   361 // CXCFWEngine::LoadL
       
   362 // XML loading operation is started. Internal members are initialized and
       
   363 // object is set active. 
       
   364 // -----------------------------------------------------------------------------
       
   365 //
       
   366 EXPORT_C void CXCFWEngine::LoadL(
       
   367     MXCFWTree& aTree, 
       
   368     const TDesC& aFile, 
       
   369     const TDesC& aDTDFile )
       
   370     {
       
   371 
       
   372     // If we're active at the moment or iState is something else than Idle,
       
   373     // leave with KErrInUse.
       
   374     if ( IsActive() || iState != EStateIdle )
       
   375         {
       
   376         User::Leave( KErrInUse );        
       
   377         }
       
   378 
       
   379     User::LeaveIfError( iFileSystem.Connect() );
       
   380     
       
   381     //delete previous instances of parser and DTD name buffers
       
   382     delete iParser;     
       
   383     iParser = NULL;               
       
   384     delete iDTD;
       
   385     iDTD = NULL;
       
   386     iDTD = aDTDFile.AllocL();
       
   387     delete iFile;
       
   388     iFile = NULL;
       
   389     iFile = aFile.AllocL();
       
   390 
       
   391     //Set tree to use (not owned)
       
   392     iTree = &aTree;
       
   393     if ( iTree->Root () )
       
   394         {
       
   395         //if the tree has already a root, we'll load items under that root
       
   396         iCurrentTreeNode = iTree->Root();            
       
   397         }
       
   398     else
       
   399         {
       
   400         iCurrentTreeNode = NULL;            
       
   401         }
       
   402 
       
   403     iStateByLastError = EStateIdle;
       
   404 
       
   405     //Reset possible DTD name 
       
   406     iTree->SetDTDNameL( aDTDFile );
       
   407     iTree->SetLocked( ETrue );
       
   408 
       
   409     delete iParser;
       
   410     iParser = NULL;
       
   411     iParser = CMDXMLParser::NewL( this );    
       
   412     User::LeaveIfError ( 
       
   413         iParser->ParseFile( iFileSystem, iFile->Des() ) );
       
   414     iState = EStateLoadingFile;
       
   415 
       
   416     }
       
   417 
       
   418 // -----------------------------------------------------------------------------
       
   419 // CXCFWEngine::SaveL
       
   420 // Wrapper to support saving of XML without giving a DTD file name (i.e. when
       
   421 // saving content that has no localized strings)
       
   422 // -----------------------------------------------------------------------------
       
   423 //
       
   424 EXPORT_C void CXCFWEngine::SaveL(
       
   425     MXCFWTree& aTree, 
       
   426     const TDesC& aFile )
       
   427     {
       
   428     SaveL( aTree, aFile, aTree.DTDName() );
       
   429     }
       
   430 
       
   431 
       
   432 // -----------------------------------------------------------------------------
       
   433 // CXCFWEngine::SaveL
       
   434 // Save operation is initialized and started
       
   435 // -----------------------------------------------------------------------------
       
   436 //
       
   437 EXPORT_C void CXCFWEngine::SaveL(
       
   438     MXCFWTree& aTree,
       
   439     const TDesC& aFile,
       
   440     const TDesC& aDTDFile )
       
   441     {
       
   442 
       
   443     if ( IsActive() || iState != EStateIdle )
       
   444         {
       
   445         User::Leave( KErrInUse );        
       
   446         }
       
   447 
       
   448     User::LeaveIfError( iFileSystem.Connect() );
       
   449 
       
   450     //create folder if not exist
       
   451     TChar bs = '\\';
       
   452     if ( aFile.Locate( bs ) != KErrNotFound )
       
   453         {
       
   454         TPtrC dir = aFile.Left( aFile.LocateReverse( bs ) + 1 );
       
   455         TInt ret = iFileSystem.MkDirAll( dir );
       
   456         if ( KErrAlreadyExists != ret && KErrNone != ret ) 
       
   457             {
       
   458             User::Leave( ret );                
       
   459             }
       
   460         }
       
   461 
       
   462     //Set tree pointer ( not owned )
       
   463     iTree = &aTree;
       
   464     if ( iTree->Root () )
       
   465         {
       
   466         //init current tree node to root if there's one
       
   467         iCurrentTreeNode = iTree->Root();            
       
   468         }
       
   469     else
       
   470         {
       
   471         // this tree can't be saved, has no data
       
   472         User::Leave( KErrArgument );
       
   473         }
       
   474 
       
   475     //delete previous instances of parser and filename buffers
       
   476     delete iComposer;     
       
   477     iComposer = NULL;               
       
   478 
       
   479     delete iFile;
       
   480     iFile = NULL;
       
   481     iFile = aFile.AllocL();
       
   482 
       
   483     delete iDTD;
       
   484     iDTD = NULL;
       
   485     iDTD = aDTDFile.AllocL();
       
   486 
       
   487     iStateByLastError = EStateIdle;
       
   488 
       
   489     // delete possible previous instance of XML Doc object
       
   490     // create new doc and initialize with XML decl + Doctype
       
   491     delete iXMLDoc;
       
   492     iXMLDoc = NULL;
       
   493     iXMLDoc = CMDXMLDocument::NewL();
       
   494     iXMLDoc->SetVersionTagL( KXMLDeclaration );
       
   495 
       
   496     // set doc type tag according to given DTD file name
       
   497     if ( aDTDFile.Compare ( KNullDesC) != 0 )
       
   498         {
       
   499         TBuf<KMaxDTDLength> buf;
       
   500         TInt bsloc = aDTDFile.LocateReverse( bs );
       
   501         
       
   502         // take just the file name, no preceding path chars
       
   503         // (the assumption is that loc files are stored
       
   504         // at relative path \locNN\dtdname.dtd related to
       
   505         // XML file location)
       
   506         if ( bsloc != KErrNotFound)
       
   507             {
       
   508             TPtrC dtdname = aDTDFile.Mid( bsloc + 1 );
       
   509             buf.Format( KDocTypeDecl, &dtdname);
       
   510             }
       
   511         else
       
   512             {
       
   513             buf.Format( KDocTypeDecl, &aDTDFile );
       
   514             }
       
   515         
       
   516         iXMLDoc->SetDocTypeTagL( buf );
       
   517         }
       
   518     else
       
   519         {
       
   520         iXMLDoc->SetDocTypeTagL( KDocTypeDeclNoDTD );
       
   521         }
       
   522     // notify observer that we're about to start saving
       
   523     iObserver->HandleEngineEventL( 
       
   524         MXCFWEngineObserver::EEvtSavingStarted );
       
   525 
       
   526     iState = EStateInitializingSave;
       
   527     PrepareEntityConverterAndSetActiveL();
       
   528 
       
   529     // lock tree to prevent changes during save
       
   530     iTree->SetLocked( ETrue );   
       
   531     }
       
   532 
       
   533 // -----------------------------------------------------------------------------
       
   534 // CXCFWEngine::HasTextData
       
   535 // returns ETrue if the current xml node has text data under it.
       
   536 // -----------------------------------------------------------------------------
       
   537 //
       
   538 EXPORT_C TBool CXCFWEngine::HasTextData()
       
   539     {
       
   540     TBool ret = EFalse;
       
   541     if ( iCurrentXMLNode && iCurrentXMLNode->FirstChild() )
       
   542         {
       
   543         CMDXMLNode::TDOMNodeType t = iCurrentXMLNode->FirstChild()->NodeType();
       
   544         
       
   545         if ( t == CMDXMLNode::ETextNode || t == CMDXMLNode::ECDATASectionNode )
       
   546             {
       
   547             ret = ETrue;                
       
   548             }
       
   549         }
       
   550     return ret;
       
   551     }
       
   552 
       
   553 // -----------------------------------------------------------------------------
       
   554 // CXCFWEngine::TextDetailsL
       
   555 // returns text details for the current XML node (if it has text)
       
   556 // Node may contain CDATA sections, but mixed content is not supported.
       
   557 // -----------------------------------------------------------------------------
       
   558 //
       
   559 EXPORT_C void CXCFWEngine::TextDetailsL(
       
   560     TPtrC& aText,
       
   561     TBool& aIsLocalized )
       
   562     {
       
   563     _LIT(KEntityRef, "*&*;*");
       
   564     
       
   565     
       
   566     TInt err = KErrNotFound;
       
   567     CMDXMLNode* ptr = iCurrentXMLNode->FirstChild();
       
   568 
       
   569     if ( ptr )
       
   570         {
       
   571         
       
   572         //delete previous text pointer now
       
   573         delete iNodeText;
       
   574         iNodeText = NULL;
       
   575         
       
   576         //loop through all text / cdata elements
       
   577         while ( ptr && 
       
   578             ( ptr->NodeType() == CMDXMLNode::ETextNode || 
       
   579             ptr->NodeType() == CMDXMLNode::ECDATASectionNode ) )
       
   580             {
       
   581             err = KErrNone;
       
   582             TPtrC nextdata;
       
   583             switch ( ptr->NodeType() )
       
   584                 {
       
   585                 case CMDXMLNode::ETextNode:
       
   586                     {
       
   587                     nextdata.Set( ((CMDXMLCharacterData*)ptr)->Data() );                    
       
   588                     break;
       
   589                     }
       
   590                 case CMDXMLNode::ECDATASectionNode:
       
   591                     {
       
   592                     nextdata.Set( ((CMDXMLCDATASection*)ptr)->Data() );                    
       
   593                     break;
       
   594                     }
       
   595                 default:
       
   596                     {
       
   597                     err = KErrNotFound;
       
   598                     break;
       
   599                     }
       
   600                 }
       
   601                 
       
   602             if ( KErrNone == err )
       
   603                 {
       
   604                 //create nodetext buffer if we don't have it yet.
       
   605                 if ( !iNodeText )
       
   606                     {
       
   607                     iNodeText = HBufC::NewL( nextdata.Length() );
       
   608                     iNodeText->Des().Copy( nextdata );    
       
   609                     }
       
   610                 else
       
   611                     {
       
   612                     //increase nodetext buffer and append new data.
       
   613                     iNodeText = iNodeText->ReAllocL( 
       
   614                         iNodeText->Length() + nextdata.Length() );
       
   615                     iNodeText->Des().Append( nextdata );
       
   616                     }
       
   617                 }
       
   618             ptr = ptr->NextSibling();
       
   619             }
       
   620         
       
   621         //If we have some text, do localization
       
   622         if( iNodeText )
       
   623             {
       
   624             err = KErrNone;
       
   625             aText.Set( *iNodeText );
       
   626             aIsLocalized = EFalse;
       
   627             
       
   628             if ( aText.Match( KEntityRef ) != KErrNotFound && iLocalizer)
       
   629                 {
       
   630                 TPtrC ltext;
       
   631                 if ( KErrNone == iLocalizer->EntityRefToText( aText, ltext ) )
       
   632                     {
       
   633                     aText.Set( ltext );                        
       
   634                     aIsLocalized = ETrue;
       
   635                     }
       
   636                 }
       
   637             }
       
   638         }
       
   639     User::LeaveIfError( err );
       
   640     }
       
   641 
       
   642 
       
   643 // -----------------------------------------------------------------------------
       
   644 // CXCFWEngine::NumAttributes
       
   645 // return number of attributes for current XML node
       
   646 // -----------------------------------------------------------------------------
       
   647 //
       
   648 EXPORT_C TInt CXCFWEngine::NumAttributes()
       
   649     {
       
   650 
       
   651     TInt count = 0;
       
   652 
       
   653     //Return attribute count for normal element only.
       
   654     if ( iCurrentXMLNode )
       
   655         {
       
   656         if ( iCurrentXMLNode->NodeType() == CMDXMLNode::EElementNode )
       
   657             {
       
   658             count = ((CMDXMLElement*)iCurrentXMLNode)->NumAttributes();
       
   659             }
       
   660         }
       
   661 
       
   662     return count;    
       
   663     }
       
   664     
       
   665 // -----------------------------------------------------------------------------
       
   666 // CXCFWEngine::AttributeDetailsL
       
   667 // Function reads attributes from current xml node and returns them in TPtrC's
       
   668 // -----------------------------------------------------------------------------
       
   669 //
       
   670 EXPORT_C void CXCFWEngine::AttributeDetailsL(
       
   671     const TInt aIndex, 
       
   672     TPtrC& aAttributeName, 
       
   673     TPtrC& aAttributeValue, 
       
   674     TBool& aIsLocalized )
       
   675     {
       
   676     _LIT(KEntityRef, "*&*;*");
       
   677     
       
   678     
       
   679     //Return attribute details for normal element only.
       
   680     if ( iCurrentXMLNode )
       
   681         {
       
   682         if ( iCurrentXMLNode->NodeType() == CMDXMLNode::EElementNode )
       
   683             {
       
   684             aIsLocalized = EFalse;
       
   685             // Get attribute name + value
       
   686             User::LeaveIfError (
       
   687                 ((CMDXMLElement*)iCurrentXMLNode)->
       
   688                 AttributeDetails(aIndex, aAttributeName, aAttributeValue) );
       
   689             
       
   690             // query localizer component for localized text
       
   691             if ( aAttributeValue.Match( KEntityRef ) != KErrNotFound 
       
   692                  && iLocalizer )
       
   693                 {
       
   694                 TPtrC ltext;
       
   695                 if ( KErrNone == iLocalizer->EntityRefToText( 
       
   696                     aAttributeValue, ltext) )
       
   697                     {
       
   698                     aAttributeValue.Set( ltext );                        
       
   699                     aIsLocalized = ETrue;
       
   700                     }
       
   701                 }
       
   702             }
       
   703         }
       
   704     }
       
   705     
       
   706 
       
   707 // -----------------------------------------------------------------------------
       
   708 // CXCFWEngine::AttributeDetailsL
       
   709 // Function reads attributes from current xml node and returns them in TPtrC's
       
   710 // -----------------------------------------------------------------------------
       
   711 //
       
   712 EXPORT_C void CXCFWEngine::AttributeDetailsL(
       
   713     const TInt aIndex, 
       
   714     TPtrC& aAttributeName, 
       
   715     TPtrC& aAttributeValue)
       
   716     {
       
   717     
       
   718     //Return attribute details for normal element only.
       
   719     if ( iCurrentXMLNode )
       
   720         {
       
   721         if ( iCurrentXMLNode->NodeType() == CMDXMLNode::EElementNode )
       
   722             {
       
   723             // Get attribute name + value
       
   724             User::LeaveIfError (
       
   725                 ((CMDXMLElement*)iCurrentXMLNode)->
       
   726                 AttributeDetails(aIndex, aAttributeName, aAttributeValue) );
       
   727             }
       
   728         }
       
   729     }
       
   730     
       
   731 // -----------------------------------------------------------------------------
       
   732 // CXCFWEngine::UnRegisterObjectFactory
       
   733 // Removes given object factory pointer from factory array. Does not delete.
       
   734 // -----------------------------------------------------------------------------
       
   735 //
       
   736 EXPORT_C TInt CXCFWEngine::UnRegisterObjectFactory(
       
   737     CGECOObjectFactoryBase* aFactory )
       
   738     {
       
   739     
       
   740     TInt err = KErrNotFound;
       
   741     TInt maxindex = iFactoryList.Count() - 1;
       
   742 
       
   743     for ( TInt i = maxindex; i >= 0 ; i-- )
       
   744         {
       
   745         if ( iFactoryList[i] == aFactory )
       
   746             {
       
   747             iFactoryList.Remove(i);
       
   748             err = KErrNone;
       
   749             }
       
   750         }
       
   751 
       
   752     return err;
       
   753         
       
   754     }
       
   755 
       
   756 // -----------------------------------------------------------------------------
       
   757 // CXCFWEngine::RegisterObjectFactory
       
   758 // Adds given object factory pointer to factory array. Ownership NOT taken.
       
   759 // Adding same factory many times is not possible.
       
   760 // -----------------------------------------------------------------------------
       
   761 //
       
   762 EXPORT_C void CXCFWEngine::RegisterObjectFactoryL(
       
   763     CGECOObjectFactoryBase* aFactory )
       
   764     {
       
   765     
       
   766     __ASSERT_LEAVE ( aFactory != NULL, KErrArgument );
       
   767 
       
   768     TInt maxindex = iFactoryList.Count() - 1;
       
   769     
       
   770     for ( TInt i = maxindex; i>= 0 ; i-- )
       
   771         {
       
   772         if ( iFactoryList[i] == aFactory )
       
   773             {
       
   774             User::Leave( KErrAlreadyExists );                
       
   775             }
       
   776         }
       
   777         
       
   778     // add to factory array
       
   779     User::LeaveIfError( iFactoryList.Append( aFactory ) );
       
   780 
       
   781     }
       
   782     
       
   783 // -----------------------------------------------------------------------------
       
   784 // CXCFWEngine::ParseFileCompleteL()
       
   785 // Detaches parsed XML document from parser. If DTD file was provided in LoadL
       
   786 // call, we will next load the DTD for getting entity references ready. If no
       
   787 // DTD file was given, we go straight to parsing.
       
   788 // -----------------------------------------------------------------------------
       
   789 //
       
   790 void CXCFWEngine::ParseFileCompleteL()
       
   791     {
       
   792 
       
   793     //see if we have urecoverable errors from GMXML => if error severity is
       
   794     //fatal, let's not go any further in processing.
       
   795     if ( iParser->ErrorSeverity() == EXMLFatal )
       
   796         {
       
   797         iStateByLastError = iState;
       
   798         iState = EStateIdle;
       
   799         iObserver->HandleEngineErrorL( iParser->Error() );
       
   800         FreeResources();  
       
   801         }
       
   802     else
       
   803         {
       
   804         //delete previous instance of document
       
   805         if ( iXMLDoc )
       
   806             {
       
   807             delete iXMLDoc;
       
   808             iXMLDoc = NULL;            
       
   809             }
       
   810             
       
   811         iXMLDoc = iParser->DetachXMLDoc();
       
   812         iCurrentXMLNode = iXMLDoc->DocumentElement()->FirstChild();
       
   813 
       
   814         //set up DTD if not already done
       
   815         PrepareDTDPathL();
       
   816 
       
   817         TRAPD( err, iObserver->HandleEngineEventL( 
       
   818                 MXCFWEngineObserver::EEvtParsingStarted ) );
       
   819         if ( KErrNone != err )
       
   820             {
       
   821             iObserver->HandleEngineErrorL( err );
       
   822             Cancel();
       
   823             FreeResources();                
       
   824             }
       
   825 
       
   826         //Set active        
       
   827         iState = EStateParsing;
       
   828         PrepareEntityConverterAndSetActiveL();
       
   829         }
       
   830     }
       
   831     
       
   832 // -----------------------------------------------------------------------------
       
   833 // CXCFWEngine::AddCurrentXMLNodeToTreeL
       
   834 // New content object is generated, initialized and added to tree. Object
       
   835 // initialization is done with a registered object factory if there's such.
       
   836 // Otherwise default object factory is used.
       
   837 // -----------------------------------------------------------------------------
       
   838 //
       
   839 void CXCFWEngine::AddCurrentXMLNodeToTreeL()
       
   840     {
       
   841     
       
   842     __ASSERT_LEAVE( iTree && iCurrentXMLNode, KErrGeneral );
       
   843 
       
   844     CGECOObjectBase* obj = NULL;
       
   845     CGECOObjectFactoryBase* factory = NULL;
       
   846     TInt count = iFactoryList.Count();
       
   847 
       
   848     //XCFW will only handle element nodes.
       
   849     if ( iCurrentXMLNode->NodeType() == CMDXMLNode::EElementNode )
       
   850         {
       
   851         if ( count > 0 )
       
   852             {
       
   853             //loop through factories starting from the most recently added
       
   854             //until a factory returns an object for the given tag or we run
       
   855             //out of factories.
       
   856             for ( TInt i = count-1 ; i>= 0 && !obj ; i--)
       
   857                 {
       
   858                 //Query factory for object
       
   859                 factory = iFactoryList[i];
       
   860                 obj = factory->
       
   861                     GetContentObjectAndSetContextL( 
       
   862                         iCurrentXMLNode->NodeName() );
       
   863                 }
       
   864             }
       
   865         
       
   866         // if none of the user factories recognized this tag, 
       
   867         // use default factory.
       
   868         if ( !obj ) 
       
   869             {
       
   870             factory = iDefaultFactory;
       
   871             obj = factory->GetContentObjectAndSetContextL( 
       
   872                 iCurrentXMLNode->NodeName() );	
       
   873             }
       
   874         }
       
   875 
       
   876     //if we have an object, let's add it to tree. 
       
   877     //otherwise the whole branch starting from this node will
       
   878     //be discarded from XCFWTree.
       
   879     if ( obj )
       
   880         {
       
   881         CleanupStack::PushL( obj );
       
   882         
       
   883         factory->InitializeObjectL( *this );
       
   884         
       
   885         if ( !iCurrentTreeNode )
       
   886             {
       
   887             //Adding root.
       
   888             iCurrentTreeNode = iTree->AddNodeL( obj );
       
   889             }
       
   890         else
       
   891             {
       
   892             //add under certain parent.
       
   893             iCurrentTreeNode = iTree->AddNodeL( obj, iCurrentTreeNode );            
       
   894             }
       
   895             
       
   896         CleanupStack::Pop( obj );
       
   897         }
       
   898     else
       
   899         {
       
   900         //Notify observer about unknown data if current node is an element node        
       
   901         if ( iCurrentXMLNode->NodeType() == CMDXMLNode::EElementNode )
       
   902             {
       
   903             iObserver->HandleEngineErrorL( KErrUnknown );            
       
   904             }
       
   905 
       
   906         // discard this branch in tree: loop out to next sibling of 
       
   907         // this node or its parent
       
   908         while ( iCurrentXMLNode && !iCurrentXMLNode->NextSibling() )
       
   909             {
       
   910             iCurrentXMLNode = iCurrentXMLNode->ParentNode();
       
   911             if ( iCurrentXMLNode && iCurrentTreeNode->Parent() )
       
   912                 {
       
   913                 iCurrentTreeNode = iCurrentTreeNode->Parent();
       
   914                 }
       
   915             }
       
   916             
       
   917         // set next node pointer to process
       
   918         if( iCurrentXMLNode && iCurrentXMLNode->NextSibling() )
       
   919 			{
       
   920 			iCurrentXMLNode = iCurrentXMLNode->NextSibling();
       
   921 			}
       
   922         }
       
   923             
       
   924     }
       
   925 
       
   926 // -----------------------------------------------------------------------------
       
   927 // CXCFWEngine::DOM2TreeNextCycleL
       
   928 // XML DOM is traversed node by node, and elements are added to content tree. 
       
   929 // Each call leaves will set iCurrentXMLNode to point to the next DOM node to 
       
   930 // be processed until there's no more nodes.
       
   931 // -----------------------------------------------------------------------------
       
   932 //
       
   933 void CXCFWEngine::DOM2TreeNextCycleL()
       
   934     {
       
   935 
       
   936     CMDXMLNode* reference = NULL;
       
   937 
       
   938     if ( iCurrentXMLNode )
       
   939         {
       
   940 
       
   941         reference = iCurrentXMLNode;
       
   942         
       
   943         //add this XML node data to content tree
       
   944         AddCurrentXMLNodeToTreeL();    
       
   945         // if node was discareded for some reason, let's keep calling
       
   946         // until a node is accepted.
       
   947         while ( iCurrentXMLNode && iCurrentXMLNode != reference )
       
   948             {
       
   949             reference = iCurrentXMLNode;
       
   950             AddCurrentXMLNodeToTreeL();                
       
   951             }
       
   952         
       
   953         if ( !iCurrentXMLNode )
       
   954             {
       
   955             return;                
       
   956             }
       
   957         
       
   958         //if this node has children, go to first child now
       
   959         if ( iCurrentXMLNode->FirstChild() )
       
   960             {
       
   961             iCurrentXMLNode = iCurrentXMLNode->FirstChild();                        
       
   962             }
       
   963         else //no children
       
   964             {
       
   965             
       
   966             //update XCFWTree parent node pointer as this xml node had no child
       
   967             if ( iCurrentTreeNode && iCurrentTreeNode->Parent() )
       
   968                 {
       
   969                 iCurrentTreeNode = iCurrentTreeNode->Parent();    
       
   970                 }
       
   971 
       
   972             //if there's siblings at the same level, go to next sibling
       
   973             if ( iCurrentXMLNode->NextSibling() )
       
   974                 {
       
   975                 iCurrentXMLNode = iCurrentXMLNode->NextSibling();    
       
   976                 }
       
   977             else //no siblings left
       
   978                 {
       
   979                 // get back in the tree to a level that has still siblings left
       
   980                 while ( iCurrentXMLNode && !iCurrentXMLNode->NextSibling() )
       
   981                     {
       
   982                     iCurrentXMLNode = iCurrentXMLNode->ParentNode();
       
   983                     // update XCFWTree parent pointer if necessary
       
   984                     if ( iCurrentXMLNode && 
       
   985                         iCurrentTreeNode && iCurrentTreeNode->Parent() )
       
   986                         {
       
   987                         iCurrentTreeNode = iCurrentTreeNode->Parent();
       
   988                         }
       
   989                     }
       
   990                 // now we're either at a level that has siblings, or then
       
   991                 // we're out of nodes. If there's a sibling, we'll process
       
   992                 // that next
       
   993                 if( iCurrentXMLNode && iCurrentXMLNode->NextSibling() )
       
   994 					{
       
   995 					iCurrentXMLNode = iCurrentXMLNode->NextSibling();
       
   996 					}
       
   997                 }
       
   998             }
       
   999         }
       
  1000     }
       
  1001 
       
  1002 // -----------------------------------------------------------------------------
       
  1003 // CXCFWEngine::CurrentState()
       
  1004 // Returns engine's internal state. Client may want to know this at error
       
  1005 // situations to determine if a retry would be necessary. 
       
  1006 // -----------------------------------------------------------------------------
       
  1007 //
       
  1008 EXPORT_C CXCFWEngine::TXCFWEngineState CXCFWEngine::CurrentState()
       
  1009     {
       
  1010     //If the last state change was by an error, return the state that
       
  1011     //engine was in when error occurred (error routine will set the state to
       
  1012     //EStateIdle). Otherwise return the current state.
       
  1013     if ( iStateByLastError != EStateIdle )
       
  1014         {
       
  1015         return iStateByLastError;            
       
  1016         }
       
  1017     else
       
  1018         {
       
  1019         return iState;
       
  1020         }
       
  1021     }
       
  1022 
       
  1023 
       
  1024 // -----------------------------------------------------------------------------
       
  1025 // CXCFWEngine::ComposeFileCompleteL()
       
  1026 // Called by GMXML composer when DOM has been saved to file.
       
  1027 // Possible fatal errors are sent forward to XCFW client. Otherwise the client
       
  1028 // is just informed with saving completed event.
       
  1029 // -----------------------------------------------------------------------------
       
  1030 //
       
  1031 void CXCFWEngine::ComposeFileCompleteL()
       
  1032     {
       
  1033 
       
  1034     //see if we have urecoverable errors from GMXML => if error severity is
       
  1035     //fatal, let's not go any further in processing.
       
  1036     if ( iComposer->ErrorSeverity() == EXMLFatal )
       
  1037         {
       
  1038         TInt err = iComposer->Error();
       
  1039         iStateByLastError = iState;
       
  1040         iState = EStateIdle;
       
  1041         FreeResources();  
       
  1042         iObserver->HandleEngineErrorL( err );
       
  1043         }
       
  1044     else
       
  1045         {
       
  1046         FreeResources();
       
  1047         iObserver->HandleEngineEventL( 
       
  1048             MXCFWEngineObserver::EEvtSavingComplete );
       
  1049         }
       
  1050     }
       
  1051 
       
  1052 
       
  1053 // -----------------------------------------------------------------------------
       
  1054 // CXCFWEngine::Tree2DOMNextCycleLL
       
  1055 // XCFWTree is traversed node by node, and elements are added to XML DOM. 
       
  1056 // Each call leaves will set iCurrentTreeNode to point to the next node to 
       
  1057 // be processed until there's no more nodes left in XCFW Tree.
       
  1058 // -----------------------------------------------------------------------------
       
  1059 //
       
  1060 void CXCFWEngine::Tree2DOMNextCycleL()
       
  1061     {
       
  1062 
       
  1063     MXCFWNode* reference = NULL;
       
  1064 
       
  1065     if ( iCurrentTreeNode )
       
  1066         {
       
  1067 
       
  1068         reference = iCurrentTreeNode;
       
  1069         
       
  1070         //add this tree node data to DOM
       
  1071         AddCurrentTreeNodeToDOML();    
       
  1072         // if node was discareded for some reason, let's keep calling
       
  1073         // until a node is accepted.
       
  1074         while ( iCurrentTreeNode && iCurrentTreeNode != reference )
       
  1075             {
       
  1076             reference = iCurrentTreeNode;
       
  1077             AddCurrentTreeNodeToDOML();                
       
  1078             }
       
  1079         
       
  1080         if ( !iCurrentTreeNode )
       
  1081             {
       
  1082             return;                
       
  1083             }
       
  1084         
       
  1085         //if this node has children, go to first child now
       
  1086         if ( iCurrentTreeNode->FirstChild() )
       
  1087             {
       
  1088             iCurrentTreeNode = iCurrentTreeNode->FirstChild();                        
       
  1089             }
       
  1090         else //no children
       
  1091             {
       
  1092             
       
  1093             //update DOM parent node pointer as this Tree node had no child
       
  1094             if ( iCurrentXMLNode && iCurrentXMLNode->ParentNode() )
       
  1095                 {
       
  1096                 iCurrentXMLNode = iCurrentXMLNode->ParentNode();    
       
  1097                 }
       
  1098 
       
  1099             //if there's siblings at the same level, go to next sibling
       
  1100             if ( iCurrentTreeNode->NextSibling() )
       
  1101                 {
       
  1102                 iCurrentTreeNode = iCurrentTreeNode->NextSibling();    
       
  1103                 }
       
  1104             else //no siblings left
       
  1105                 {
       
  1106                 // get back in the tree to a level that has still siblings left
       
  1107                 while ( iCurrentTreeNode && !iCurrentTreeNode->NextSibling() )
       
  1108                     {
       
  1109                     iCurrentTreeNode = iCurrentTreeNode->Parent();
       
  1110                     // update DOM parent pointer if necessary
       
  1111                     if ( iCurrentTreeNode && 
       
  1112                         iCurrentXMLNode && iCurrentXMLNode->ParentNode() )
       
  1113                         {
       
  1114                         iCurrentXMLNode = iCurrentXMLNode->ParentNode();
       
  1115                         }
       
  1116                     }
       
  1117                 // now we're either at a level that has siblings, or then
       
  1118                 // we're out of nodes. If there's a sibling, we'll process
       
  1119                 // that next
       
  1120                 if( iCurrentTreeNode && iCurrentTreeNode->NextSibling() )
       
  1121 					{
       
  1122 					iCurrentTreeNode = iCurrentTreeNode->NextSibling();
       
  1123 					}
       
  1124                 }
       
  1125             }
       
  1126         }  
       
  1127     }
       
  1128 
       
  1129 // -----------------------------------------------------------------------------
       
  1130 // CXCFWEngine::AddCurrentTreeNodeToDOML
       
  1131 // New XML DOM element node is generated out of the XCFW Tree node data.
       
  1132 // DOM node data is queried from XCFW Tree node using the corresponding
       
  1133 // object factory. If registered object factory recognizes this node's typeid,
       
  1134 // default factory implementation is used.
       
  1135 // New XML Element node is added to XML DOM.
       
  1136 // -----------------------------------------------------------------------------
       
  1137 //
       
  1138 void CXCFWEngine::AddCurrentTreeNodeToDOML()
       
  1139     {
       
  1140 
       
  1141     __ASSERT_LEAVE( iTree && iCurrentTreeNode, KErrGeneral );
       
  1142 
       
  1143     CGECOObjectBase* obj = iCurrentTreeNode->Data();
       
  1144     CGECOObjectFactoryBase* factory = NULL;
       
  1145     TInt count = iFactoryList.Count();
       
  1146     TInt err = KErrNotSupported;
       
  1147     //Find factory for the current tree node
       
  1148     if ( count > 0 )
       
  1149         {
       
  1150         //loop through factories starting from the most recently added
       
  1151         //until a factory returns KErrNone for SetContext or we run out 
       
  1152         //of factories
       
  1153         for ( TInt i = count-1 ; i>= 0 && KErrNone != err ; i--)
       
  1154             {
       
  1155             //Query factory for object
       
  1156             factory = iFactoryList[i];
       
  1157             err = factory->SetContext( obj );
       
  1158             }
       
  1159         }
       
  1160 
       
  1161     // if none of the user factories recognized this object, 
       
  1162     // use default factory.
       
  1163     if ( KErrNone != err ) 
       
  1164         {
       
  1165         factory = iDefaultFactory;
       
  1166         err = factory->SetContext( obj );	
       
  1167         }
       
  1168 
       
  1169 
       
  1170     //if we have an object, let's add it to tree. 
       
  1171     //otherwise the whole branch starting from this node will
       
  1172     //be discarded from XCFWTree.
       
  1173     if ( err == KErrNone )
       
  1174         {
       
  1175         CMDXMLElement* node = CMDXMLElement::NewLC( 
       
  1176             ETrue, iXMLDoc, obj->TypeIdentifier() );
       
  1177         
       
  1178         TInt counter = factory->NumAttributes() - 1;
       
  1179         while ( counter >= 0 )
       
  1180             {
       
  1181             TPtrC attrname;
       
  1182             TPtrC attrvalue;
       
  1183             HBufC* ebuf = NULL;
       
  1184             factory->AttributeDetailsL( counter, attrname, attrvalue );
       
  1185             
       
  1186             node->SetAttributeL( attrname, attrvalue, ETrue );
       
  1187 
       
  1188             if ( ebuf )
       
  1189                 {
       
  1190                 CleanupStack::PopAndDestroy( ebuf );
       
  1191                 }
       
  1192 
       
  1193             counter--;                
       
  1194             }
       
  1195 
       
  1196         //if object has text data, let's put it to a child node...
       
  1197         if ( factory->HasTextData() )
       
  1198             {
       
  1199             CMDXMLText* textnode = CMDXMLText::NewLC( iXMLDoc );
       
  1200             TPtrC text;
       
  1201             TBool locstatus;
       
  1202             factory->TextDetailsL( text, locstatus );
       
  1203             HBufC* ebuf = NULL;
       
  1204             //Check localization
       
  1205             if ( locstatus && iLocalizer )
       
  1206                 {
       
  1207                 TPtrC eref;
       
  1208                 if ( KErrNone == iLocalizer->TextToEntityRef( text, eref ) )
       
  1209                     {
       
  1210                     ebuf = HBufC::NewLC( eref.Length() + KExtraChars );
       
  1211                     ebuf->Des().Copy( KXCFWAnd );
       
  1212                     ebuf->Des().Append( eref );
       
  1213                     ebuf->Des().Append( KXCFWSemiC );
       
  1214                     text.Set( ebuf->Des() );                  
       
  1215                     }
       
  1216                 }
       
  1217             textnode->SetDataL( text );
       
  1218             node->AppendChild( textnode );
       
  1219             //destroying entity ref buffer is safe now
       
  1220             if ( ebuf )
       
  1221                 {
       
  1222                 CleanupStack::PopAndDestroy( ebuf );                    
       
  1223                 }
       
  1224             CleanupStack::Pop( textnode );
       
  1225             }
       
  1226             
       
  1227         if ( !iCurrentXMLNode )
       
  1228             {
       
  1229             iXMLDoc->DocumentElement()->AppendChild(node);
       
  1230             }
       
  1231         else
       
  1232             {
       
  1233             iCurrentXMLNode->AppendChild( node );
       
  1234             }
       
  1235         iCurrentXMLNode = node;
       
  1236         CleanupStack::Pop( node );
       
  1237         }
       
  1238     else
       
  1239         {
       
  1240         //Notify observer about unknown data        
       
  1241         iObserver->HandleEngineErrorL( KErrUnknown );            
       
  1242     
       
  1243         // discard this branch in tree: loop out to next sibling of 
       
  1244         // this node or its parent
       
  1245         while ( iCurrentTreeNode && !iCurrentTreeNode->NextSibling() )
       
  1246             {
       
  1247             iCurrentTreeNode = iCurrentTreeNode->Parent();
       
  1248             if ( iCurrentTreeNode && iCurrentXMLNode->ParentNode() )
       
  1249                 {
       
  1250                 iCurrentXMLNode = iCurrentXMLNode->ParentNode();
       
  1251                 }
       
  1252             }
       
  1253             
       
  1254         // set next node pointer to process
       
  1255         if( iCurrentTreeNode && iCurrentTreeNode->NextSibling() )
       
  1256 			{
       
  1257 			iCurrentTreeNode = iCurrentTreeNode->NextSibling();
       
  1258 			}
       
  1259         }
       
  1260     }
       
  1261 
       
  1262 
       
  1263 // -----------------------------------------------------------------------------
       
  1264 // CXCFWEngine::FreeResources
       
  1265 // XML parser / composer resources are freed (DOM tree will be deleted from mem)
       
  1266 // File name buffers are freed.
       
  1267 // -----------------------------------------------------------------------------
       
  1268 //
       
  1269 void CXCFWEngine::FreeResources()
       
  1270     {
       
  1271     iState = EStateIdle;
       
  1272     iFileSystem.Close();
       
  1273     delete iParser;
       
  1274     iParser = NULL;
       
  1275     delete iComposer;
       
  1276     iComposer = NULL;
       
  1277     delete iFile;
       
  1278     iFile = NULL;
       
  1279     delete iDTD;
       
  1280     iDTD = NULL;
       
  1281     delete iXMLDoc;
       
  1282     iXMLDoc = NULL;
       
  1283     iCurrentXMLNode = NULL;
       
  1284     iCurrentTreeNode = NULL;
       
  1285     if ( iTree )
       
  1286         {
       
  1287         iTree->SetLocked( EFalse );
       
  1288         iTree = NULL;    
       
  1289         }
       
  1290     }
       
  1291 
       
  1292 
       
  1293 // -----------------------------------------------------------------------------
       
  1294 // CXCFWEngine::PrepareEntityConverterL
       
  1295 // Localizer is created and DTD load is requested. Localizer will complete
       
  1296 // pending request when done => Engine's RunL will be called.
       
  1297 // -----------------------------------------------------------------------------
       
  1298 //
       
  1299 void CXCFWEngine::PrepareEntityConverterAndSetActiveL()
       
  1300     {
       
  1301 
       
  1302     TRequestStatus *s = &iStatus;
       
  1303 
       
  1304     delete iLocalizer;
       
  1305     iLocalizer = NULL;
       
  1306     iLocalizer = CXCFWLocalizer::NewL();
       
  1307 
       
  1308 
       
  1309     //If we have a DTD
       
  1310     if ( iDTD->Des().Compare( KNullDesC ) != 0 )
       
  1311         {
       
  1312         // delete possible previous localizer instance and create new.
       
  1313         // For performance reasons, it could be wise to first
       
  1314         // check if we're loading the same DTD as last time. This
       
  1315         // could be done at localizer side.
       
  1316 
       
  1317         // Ask Localizer to load Entity references. Localizer will
       
  1318         // complete the request when ready.
       
  1319         SetActive();
       
  1320         TRAPD( err, iLocalizer->LoadDTDL( iDTD->Des(), iFileSystem, &iStatus) );
       
  1321         if ( KErrNone != err )
       
  1322             {
       
  1323             User::RequestComplete(s, KErrNone );
       
  1324             iObserver->HandleEngineErrorL( KErrDTDLoadFailed );
       
  1325             //Complete here, since localizer will not do it
       
  1326             delete iLocalizer;
       
  1327             iLocalizer = NULL;
       
  1328             }
       
  1329         }
       
  1330     else
       
  1331         {
       
  1332         SetActive();
       
  1333         User::RequestComplete( s, KErrNone );             
       
  1334         }
       
  1335     }
       
  1336 
       
  1337 // -----------------------------------------------------------------------------
       
  1338 // CXCFWEngine::PrepareDTDPathL()
       
  1339 // Function checks the XML DOM for doc type declaration and extracts the 
       
  1340 // possible dtd file name from it. DTD path is then created out of 
       
  1341 // XML file location + localization folder template + dtd name.
       
  1342 // CXCFWLocalizer will then complete the string with current language setting
       
  1343 // and search for the file using language downgrade path if necessary.
       
  1344 // -----------------------------------------------------------------------------
       
  1345 //
       
  1346 void CXCFWEngine::PrepareDTDPathL()
       
  1347     {
       
  1348     //set up DTD if not already done
       
  1349     if ( iDTD && iXMLDoc && iDTD->Des().Compare ( KNullDesC ) == 0 )
       
  1350         {
       
  1351         
       
  1352         //check if we have a dtd defined...
       
  1353         const TChar KQuote = '"';
       
  1354         const TChar KBckSlash = '\\';
       
  1355         TInt extStart = iXMLDoc->DocTypeTag().Find( KDTDExt );
       
  1356         if ( extStart != KErrNotFound )
       
  1357             {
       
  1358             if ( iXMLDoc->DocTypeTag().Find ( KMmsDTD ) != KErrNotFound )
       
  1359                 {
       
  1360                 iXMLDoc->SetDocTypeTagL( KDocTypeDeclNoDTD );                
       
  1361                 }
       
  1362             else
       
  1363                 {
       
  1364                 TInt delim = iXMLDoc->DocTypeTag().Left( extStart ).
       
  1365                     LocateReverse( KQuote ) + 1;
       
  1366                 TInt bsdelim = iXMLDoc->DocTypeTag().Left( extStart).
       
  1367                     LocateReverse ( KBckSlash ) + 1;
       
  1368                 delim = (bsdelim>delim)?bsdelim:delim;
       
  1369                 
       
  1370                 if ( delim != KErrNotFound )
       
  1371                     {
       
  1372                     TInt dtdnamelen = extStart - delim + KDTDExtLen;
       
  1373                     TInt pathlen = iFile->Des().LocateReverse ( KBckSlash );
       
  1374                     delete iDTD;
       
  1375                     iDTD = NULL;
       
  1376                     iDTD = HBufC::NewL( pathlen + dtdnamelen + KLocFormatLen );
       
  1377                     iDTD->Des().Copy( iFile->Des().Left( pathlen ) );
       
  1378                     iDTD->Des().Append( KBckSlash );
       
  1379                     iDTD->Des().Append( KLocFormat );
       
  1380                     iDTD->Des().Append ( iXMLDoc->DocTypeTag().
       
  1381                         Mid( delim, dtdnamelen ) );                
       
  1382                     }
       
  1383                 }                
       
  1384             }
       
  1385         }
       
  1386     //Store DTD name to tree, so it is available at save.
       
  1387     iTree->SetDTDNameL( iDTD->Des() );
       
  1388     }
       
  1389 
       
  1390 //  End of File