|
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 |