Salome HOME
Copyright update 2020
[modules/yacs.git] / src / engine / VisitorSaveSchema.cxx
1 // Copyright (C) 2006-2020  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "VisitorSaveSchema.hxx"
21
22 #include "ElementaryNode.hxx"
23 #include "InlineNode.hxx"
24 #include "ServiceNode.hxx"
25 #include "ServerNode.hxx"
26 #include "ServiceInlineNode.hxx"
27 #include "Bloc.hxx"
28 #include "Proc.hxx"
29 #include "ForEachLoop.hxx"
30 #include "OptimizerLoop.hxx"
31 #include "Loop.hxx"
32 #include "ForLoop.hxx"
33 #include "WhileLoop.hxx"
34 #include "Switch.hxx"
35 #include "InputPort.hxx"
36 #include "TypeCode.hxx"
37 #include "HomogeneousPoolContainer.hxx"
38 #include "ComponentInstance.hxx"
39 #include "InputDataStreamPort.hxx"
40 #include "OutputDataStreamPort.hxx"
41 #include "Container.hxx"
42 #include "DataNode.hxx"
43
44 #include <cassert>
45 #include <iostream>
46 #include <string>
47 #include <set>
48
49 using namespace YACS::ENGINE;
50 using namespace std;
51
52 //#define _DEVDEBUG_
53 #include "YacsTrace.hxx"
54
55 /*! \class YACS::ENGINE::VisitorSaveSchema
56  *  \brief Base class for all visitors that save a schema.
57  *
58  *  Can be specialized in runtime.
59  */
60
61 VisitorSaveSchema::VisitorSaveSchema(ComposedNode *root): _root(root), Visitor(root)
62 {
63 }
64
65 VisitorSaveSchema::~VisitorSaveSchema()
66 {
67   if (_out)
68     {
69       _out << "</proc>" << endl;
70       _out.close();
71     }
72 }
73
74 void VisitorSaveSchema::openFileSchema(std::string xmlSchema) throw(YACS::Exception)
75 {
76   _out.open(xmlSchema.c_str(), ios::out);
77   if (!_out)
78     {
79       string what = "Impossible to open file for writing: " + xmlSchema;
80       throw Exception(what);
81     }
82   _out << "<?xml version='1.0' encoding='iso-8859-1' ?>" << endl;
83 }
84
85 void VisitorSaveSchema::closeFileSchema()
86 {
87   if (!_out) throw Exception("No file open for save schema");
88   _out << "</proc>" << endl;
89   _out.close();
90 }
91
92 void VisitorSaveSchema::visitBloc(Bloc *node)
93 {
94   DEBTRACE("START visitBloc " << _root->getChildName(node));
95   beginCase(node);
96   int depth = depthNode(node);
97   _out << indent(depth) << "<bloc name=\"" << node->getName() << "\"";
98   if (node->getState() == YACS::DISABLED)
99     _out << " state=\"disabled\">" << endl;
100   else
101     _out << ">" << endl;
102   writeProperties(node);
103   node->ComposedNode::accept(this);
104   writeControls(node);
105   writeSimpleDataLinks(node);
106   writeSimpleStreamLinks(node);
107   _out << indent(depth) << "</bloc>" << endl;
108   endCase(node);
109   DEBTRACE("END visitBloc " << _root->getChildName(node));
110 }
111
112 void VisitorSaveSchema::visitElementaryNode(ElementaryNode *node)
113 {
114   DEBTRACE("START visitElementaryNode " << _root->getChildName(node));
115   beginCase(node);
116   writeProperties(node);
117   writeInputPorts(node);
118   writeInputDataStreamPorts(node);
119   writeOutputPorts(node);
120   writeOutputDataStreamPorts(node);
121   endCase(node);
122   DEBTRACE("END visitElementaryNode " << _root->getChildName(node));
123 }
124
125 void VisitorSaveSchema::visitForEachLoop(ForEachLoop *node)
126 {
127   DEBTRACE("START visitForEachLoop " << _root->getChildName(node));
128   beginCase(node);
129   int depth = depthNode(node);
130
131   _out << indent(depth) << "<foreach name=\"" << node->getName() << "\"";
132   AnyInputPort *nbranch = static_cast<AnyInputPort*>(node->edGetNbOfBranchesPort());
133   if (node->getState() == YACS::DISABLED)
134     _out << " state=\"disabled\"";
135   if (!nbranch->isEmpty())
136     _out << " nbranch=\"" << nbranch->getIntValue() << "\"";
137   _out << " loopWeight=\"" << node->getWeight()->getSimpleLoopWeight() << "\"";
138   if (node->edGetSamplePort())
139     _out << " type=\"" << node->edGetSamplePort()->edGetType()->name() << "\"";
140   _out << ">" << endl;
141   
142   writeProperties(node);
143   node->DynParaLoop::accept(this);
144   writeSimpleDataLinks(node);
145   writeSimpleStreamLinks(node);
146   _out << indent(depth) << "</foreach>" << endl;
147   endCase(node);
148   DEBTRACE("END visitForEachLoop " << _root->getChildName(node));
149 }
150
151 void VisitorSaveSchema::visitOptimizerLoop(OptimizerLoop *node)
152 {
153   DEBTRACE("START visitOptimizerLoop " << _root->getChildName(node));
154   beginCase(node);
155   int depth = depthNode(node);
156
157   _out << indent(depth) << "<optimizer name=\"" << node->getName() << "\"";
158   AnyInputPort *nbranch = static_cast<AnyInputPort*>(node->edGetNbOfBranchesPort());
159   if (node->getState() == YACS::DISABLED)
160     _out << " state=\"disabled\"";
161   if (!nbranch->isEmpty())
162     _out << " nbranch=\"" << nbranch->getIntValue() << "\"";
163   _out << " loopWeight=\"" << node->getWeight()->getSimpleLoopWeight() << "\"";
164   _out << " lib=\"" << node->getAlgLib() << "\"";
165   _out << " entry=\"" << node->getSymbol() << "\"";
166   _out << ">" << endl;
167
168   writeProperties(node);
169   node->DynParaLoop::accept(this);
170   writeSimpleDataLinks(node);
171   writeSimpleStreamLinks(node);
172   _out << indent(depth) << "</optimizer>" << endl;
173   endCase(node);
174   DEBTRACE("END visitOptimizerLoop " << _root->getChildName(node));
175 }
176
177 void VisitorSaveSchema::visitDynParaLoop(DynParaLoop *node)
178 {
179   DEBTRACE("START visitDynParaLoop " << _root->getChildName(node));
180   int depth = depthNode(node);
181   if (node->getInitNode() != NULL)
182     {
183       _out << indent(depth+1) << "<initnode>" << endl;
184       node->getInitNode()->accept(this);
185       _out << indent(depth+1) << "</initnode>" << endl;
186     }
187   if (node->getExecNode() != NULL)
188     {
189       node->getExecNode()->accept(this);
190     }
191   if (node->getFinalizeNode() != NULL)
192     {
193       _out << indent(depth+1) << "<finalizenode>" << endl;
194       node->getFinalizeNode()->accept(this);
195       _out << indent(depth+1) << "</finalizenode>" << endl;
196     }
197   DEBTRACE("END visitDynParaLoop " << _root->getChildName(node));
198 }
199
200 void VisitorSaveSchema::visitForLoop(ForLoop *node)
201 {
202   DEBTRACE("START visitForLoop " << _root->getChildName(node));
203   beginCase(node);
204   int depth = depthNode(node);
205   AnyInputPort *nsteps = static_cast<AnyInputPort*>(node->edGetNbOfTimesInputPort());
206   _out << indent(depth) << "<forloop name=\"" << node->getName() << "\"";
207   if (node->getState() == YACS::DISABLED)
208     _out << " state=\"disabled\"";
209   if (nsteps->isEmpty())
210     _out << ">" << endl;
211   else   
212     _out << " nsteps=\"" << nsteps->getIntValue() << "\">" << endl;
213   writeProperties(node);
214   node->ComposedNode::accept(this);
215   writeSimpleDataLinks(node);
216   writeSimpleStreamLinks(node);
217   _out << indent(depth) << "</forloop>" << endl;
218   endCase(node);
219   DEBTRACE("END visitForLoop " << _root->getChildName(node));
220 }
221
222 void VisitorSaveSchema::visitInlineNode(InlineNode *node)
223 {
224   DEBTRACE("START visitInlineNode " << _root->getChildName(node));
225   beginCase(node);
226   int depth = depthNode(node);
227   if(node->getExecutionMode()==InlineNode::LOCAL_STR)
228     _out << indent(depth) << "<inline name=\"" << node->getName() << "\"";
229   else
230     {
231       _out << indent(depth) << "<remote name=\"" << node->getName() << "\"";
232       _out << " elementaryWeight=\"" << node->getWeight()->getElementaryWeight() << "\"";
233     }
234   if (node->getState() == YACS::DISABLED)
235     _out << " state=\"disabled\">" << endl;
236   else
237     _out << ">" << endl;
238   _out << indent(depth+1) << "<script><code><![CDATA[";
239   _out << node->getScript();
240   _out << "]]></code></script>" << endl;
241
242   //add load container if node is remote
243   Container *cont = node->getContainer();
244   if (cont)
245     _out << indent(depth+1) << "<load container=\"" << cont->getName() << "\"/>" << endl;
246
247   writeProperties(node);
248   writeInputPorts(node);
249   writeInputDataStreamPorts(node);
250   writeOutputPorts(node);
251   writeOutputDataStreamPorts(node);
252
253   if(node->getExecutionMode()==InlineNode::LOCAL_STR)
254     _out << indent(depth) << "</inline>" << endl;
255   else
256     _out << indent(depth) << "</remote>" << endl;
257
258   endCase(node);
259   DEBTRACE("END visitInlineNode " << _root->getChildName(node));
260 }
261
262 void VisitorSaveSchema::visitInlineFuncNode(InlineFuncNode *node)
263 {
264   DEBTRACE("START visitInlineFuncNode " << _root->getChildName(node));
265   beginCase(node);
266   int depth = depthNode(node);
267   if(node->getExecutionMode()==InlineNode::LOCAL_STR)
268     _out << indent(depth) << "<inline name=\"" << node->getName() << "\"";
269   else
270     {
271       _out << indent(depth) << "<remote name=\"" << node->getName() << "\"";
272       _out << " elementaryWeight=\"" << node->getWeight()->getElementaryWeight() << "\"";
273     }
274   if (node->getState() == YACS::DISABLED)
275     _out << " state=\"disabled\">" << endl;
276   else
277     _out << ">" << endl;
278   _out << indent(depth+1) << "<function name=\"" << node->getFname() << "\">" << endl;
279   _out << indent(depth+2) << "<code><![CDATA[";
280   _out << node->getScript();
281   _out << "]]></code>" << endl;
282   _out << indent(depth+1) << "</function>" << endl;
283
284   //add load container if node is remote
285   Container *cont = node->getContainer();
286   if (cont)
287     _out << indent(depth+1) << "<load container=\"" << cont->getName() << "\"/>" << endl;
288
289   writeProperties(node);
290   writeInputPorts(node);
291   writeInputDataStreamPorts(node);
292   writeOutputPorts(node);
293   writeOutputDataStreamPorts(node);
294
295   if(node->getExecutionMode()==InlineNode::LOCAL_STR)
296     _out << indent(depth) << "</inline>" << endl;
297   else
298     _out << indent(depth) << "</remote>" << endl;
299
300   endCase(node);
301   DEBTRACE("END visitInlineFuncNode " << _root->getChildName(node));
302 }
303
304 void VisitorSaveSchema::visitLoop(Loop *node)
305 {
306   DEBTRACE("START visitLoop " << _root->getChildName(node));
307   beginCase(node);
308   int depth = depthNode(node);
309   writeProperties(node);
310   node->ComposedNode::accept(this);
311   writeControls(node);
312   writeSimpleDataLinks(node);
313   writeSimpleStreamLinks(node);
314   endCase(node);
315   DEBTRACE("END visitLoop " << _root->getChildName(node));
316 }
317
318 void VisitorSaveSchema::visitProc(Proc *node)
319 {
320   DEBTRACE("START visitProc " << node->getName());
321   _out << "<proc name=\""<< node->getName() << "\">" << endl;
322   beginCase(node);
323   writeProperties(node);
324   writeTypeCodes(node);
325   writeContainers(node);
326   writeComponentInstances(node);
327   node->ComposedNode::accept(this);
328   writeControls(node);
329   writeSimpleDataLinks(node);
330   writeSimpleStreamLinks(node);
331   writeParameters(node);
332   endCase(node);
333   DEBTRACE("END visitProc " << node->getName());
334 }
335
336 void VisitorSaveSchema::visitServiceNode(ServiceNode *node)
337 {
338   DEBTRACE("START visitServiceNode " << _root->getChildName(node));
339   beginCase(node);
340   int depth = depthNode(node);
341   _out << indent(depth) << "<service name=\"" << node->getName() << "\"";
342   if (node->getState() == YACS::DISABLED)
343     _out << " state=\"disabled\">" << endl;
344   else
345     _out << ">" << endl;
346   if (node->getKind() == "xmlsh")
347     {
348       _out << indent(depth+1) << "<kind>xmlsh</kind>" << endl;
349       _out << indent(depth+1) << "<ref>" << node->getRef() << "</ref>" << endl;
350     }
351   else
352     {
353       ComponentInstance *compo = node->getComponent();
354       if (compo && !compo->isAnonymous())
355         {
356           _out << indent(depth+1) << "<componentinstance>" << compo->getInstanceName() << "</componentinstance>" << endl;
357         }
358       else if (compo && (_componentInstanceMap.find(compo) == _componentInstanceMap.end()))
359         {
360           _out << indent(depth+1) << compo->getFileRepr() << endl;
361           _componentInstanceMap[compo] = _root->getChildName(node);
362           Container *cont = compo->getContainer();
363           if (cont)
364             {
365               map<string, Container*>::const_iterator it;
366               for (it = _containerMap.begin(); it != _containerMap.end(); ++it)
367                 {
368                   if (it->second == cont) break;
369                 }
370               if (it != _containerMap.end())
371                 _out << indent(depth+1) << "<load container=\"" << it->first << "\"/>" << endl;
372             }
373         }
374       else if(compo)
375         {
376           _out << indent(depth+1) << "<node>" << _componentInstanceMap[compo] << "</node>" << endl;
377         }
378       else
379         {
380           _out << indent(depth+1) << "<component>" << "UNKNOWN" << "</component>" << endl;
381         }
382     }
383   _out << indent(depth+1) << "<method>" << node->getMethod() << "</method>" << endl;
384
385   writeProperties(node);
386   writeInputPorts(node);
387   writeInputDataStreamPorts(node);
388   writeOutputPorts(node);
389   writeOutputDataStreamPorts(node);
390   _out << indent(depth) << "</service>" << endl;
391   endCase(node);
392   DEBTRACE("END visitServiceNode " << _root->getChildName(node));
393 }
394
395 void VisitorSaveSchema::visitServerNode(ServerNode *node)
396 {
397   DEBTRACE("START visitServerNode " << _root->getChildName(node));
398   beginCase(node);
399   int depth = depthNode(node);
400   _out << indent(depth) << "<server name=\"" << node->getName() << "\"";
401   if (node->getState() == YACS::DISABLED)
402     _out << " state=\"disabled\">" << endl;
403   else
404     _out << ">" << endl;
405   Container *cont = node->getContainer();
406   map<string, Container*>::const_iterator it;
407   for (it = _containerMap.begin(); it != _containerMap.end(); ++it)
408     {
409       if (it->second == cont) break;
410     }
411   if (it != _containerMap.end())
412     _out << indent(depth+1) << "<loadcontainer>" << it->first << "</loadcontainer>" << endl;
413   /*else
414     {
415       _out << indent(depth+1) << "<node>" << _contnentInstanceMap[cont] << "</node>" << endl;
416       }*/
417   _out << indent(depth+1) << "<method>" << node->getFname() << "</method>" << endl;
418   _out << indent(depth+2) << "<script><code><![CDATA[";
419   _out << node->getScript();
420   _out << "]]></code></script>" << endl;
421   //_out << indent(depth+1) << "</function>" << endl;
422   writeProperties(node);
423   writeInputPorts(node);
424   writeInputDataStreamPorts(node);
425   writeOutputPorts(node);
426   writeOutputDataStreamPorts(node);
427   _out << indent(depth) << "</server>" << endl;
428   endCase(node);
429   DEBTRACE("END visitServerNode " << _root->getChildName(node));
430 }
431
432 void VisitorSaveSchema::visitServiceInlineNode(ServiceInlineNode *node)
433 {
434   DEBTRACE("START visitServiceInlineNode " << _root->getChildName(node));
435   beginCase(node);
436   int depth = depthNode(node);
437   _out << indent(depth) << "<serviceInline name=\"" << node->getName() << "\"";
438   if (node->getState() == YACS::DISABLED)
439     _out << " state=\"disabled\">" << endl;
440   else
441     _out << ">" << endl;
442   
443   ComponentInstance *compo = node->getComponent();
444   if (compo)
445     _out << indent(depth+1) << compo->getFileRepr() << endl;
446
447   _out << indent(depth+1) << "<function name=\"" << node->getMethod() << "\">" << endl;
448   _out << indent(depth+2) << "<code><![CDATA[";
449   _out << node->getScript();
450   _out << "]]></code>" << endl;
451   _out << indent(depth+1) << "</function>" << endl;
452   writeProperties(node);
453   writeInputPorts(node);
454   writeOutputPorts(node);
455   _out << indent(depth) << "</serviceInline>" << endl;
456   endCase(node);
457   DEBTRACE("END visitServiceInlineNode " << _root->getChildName(node));
458 }
459
460 void VisitorSaveSchema::visitPresetNode(DataNode *node)
461 {
462   DEBTRACE("START visitPresetNode " << _root->getChildName(node));
463   DEBTRACE("END visitPresetNode " << _root->getChildName(node));
464 }
465
466 void VisitorSaveSchema::visitOutNode(DataNode *node)
467 {
468   DEBTRACE("START visitOutNode " << _root->getChildName(node));
469   DEBTRACE("END visitOutNode " << _root->getChildName(node));
470 }
471
472 void VisitorSaveSchema::visitStudyInNode(DataNode *node)
473 {
474   DEBTRACE("START visitStudyInNode " << _root->getChildName(node));
475   DEBTRACE("END visitStudyInNode " << _root->getChildName(node));
476 }
477
478 void VisitorSaveSchema::visitStudyOutNode(DataNode *node)
479 {
480   DEBTRACE("START visitStudyOutNode " << _root->getChildName(node));
481   DEBTRACE("END visitStudyOutNode " << _root->getChildName(node));
482 }
483
484
485 void VisitorSaveSchema::visitSwitch(Switch *node)
486 {
487   DEBTRACE("START visitSwitch " << _root->getChildName(node));
488   beginCase(node);
489   int depth = depthNode(node);
490   AnyInputPort *condition = static_cast<AnyInputPort*>(node->edGetConditionPort());
491   _out << indent(depth) << "<switch name=\"" << node->getName() << "\"";
492   if (node->getState() == YACS::DISABLED)
493     _out << " state=\"disabled\"";
494   if (condition->isEmpty())
495     _out << ">" << endl;
496   else   
497     _out << " select=\"" << condition->getIntValue() << "\">" << endl;
498   writeProperties(node);
499   node->ComposedNode::accept(this);
500   writeControls(node);
501   writeSimpleDataLinks(node);
502   writeSimpleStreamLinks(node);
503   _out << indent(depth) << "</switch>" << endl;
504   endCase(node);
505   DEBTRACE("END visitSwitch " << _root->getChildName(node));
506 }
507
508 void VisitorSaveSchema::visitWhileLoop(WhileLoop *node)
509 {
510   DEBTRACE("START visitWhileLoop " << _root->getChildName(node));
511   beginCase(node);
512   int depth = depthNode(node);
513   _out << indent(depth) << "<while name=\"" << node->getName() << "\"";
514   if (node->getState() == YACS::DISABLED)
515     _out << " state=\"disabled\">" << endl;
516   else
517     _out << ">" << endl;
518   writeProperties(node);
519   node->ComposedNode::accept(this);
520   writeSimpleDataLinks(node);
521   writeSimpleStreamLinks(node);
522   _out << indent(depth) << "</while>" << endl;
523   endCase(node);
524   DEBTRACE("END visitWhileLoop " << _root->getChildName(node));
525 }
526
527
528 void VisitorSaveSchema::writeProperties(Node *node)
529 {
530   int depth = depthNode(node)+1;
531   map<string,string> properties = getNodeProperties(node);
532   map<string,string>::const_iterator it;
533   for(it = properties.begin(); it != properties.end(); ++it)
534     {
535       _out << indent(depth) << "<property name=\"" << it->first
536            << "\" value=\"" << it->second << "\"/>" << endl;
537     }
538 }
539
540 void VisitorSaveSchema::dumpTypeCode(TypeCode* type, std::set<std::string>& typeNames,std::map<std::string, TypeCode*>& typeMap,int depth)
541 {
542   DynType kind = type->kind();
543   string typeName = type->name();
544   if (typeNames.find(typeName) != typeNames.end())
545     return;
546   switch(kind)
547     {
548     case YACS::ENGINE::Double:
549       {
550         typeNames.insert(typeName);
551         _out << indent(depth) << "<type name=\"" << typeName << "\" kind=\"double\"/>" << endl;
552         break;
553       }
554     case YACS::ENGINE::Int:
555       {
556         typeNames.insert(typeName);
557         _out << indent(depth) << "<type name=\"" << typeName << "\" kind=\"int\"/>" << endl;
558         break;
559       }
560     case YACS::ENGINE::String:
561       {
562         typeNames.insert(typeName);
563         _out << indent(depth) << "<type name=\"" << typeName << "\" kind=\"string\"/>" << endl;
564         break;
565       }
566     case YACS::ENGINE::Bool:
567       {
568         typeNames.insert(typeName);
569         _out << indent(depth) << "<type name=\"" << typeName << "\" kind=\"bool\"/>" << endl;
570         break;
571       }
572     case YACS::ENGINE::Objref:
573       {
574         TypeCodeObjref *objref = dynamic_cast<TypeCodeObjref*>(type);
575         std::list<TypeCodeObjref*> listOfBases = getListOfBases(objref);
576         //try to dump base classes
577         for(std::list<TypeCodeObjref*>::iterator il=listOfBases.begin(); il != listOfBases.end(); ++il)
578           {
579             if (typeNames.find((*il)->name()) == typeNames.end())
580               dumpTypeCode((*il),typeNames,typeMap,depth);
581           }
582         //effective dump
583         typeNames.insert(typeName);
584         _out << indent(depth) << "<objref name=\"" << typeName << "\" id=\""
585              << objref->id() << "\"";
586         if (listOfBases.empty())
587           _out << "/>" << endl;
588         else
589           {
590             _out << ">" << endl;
591             for(std::list<TypeCodeObjref*>::iterator il=listOfBases.begin(); il != listOfBases.end(); ++il)
592               {
593                 _out << indent(depth+1) << "<base>";
594                 _out << (*il)->name();
595                 _out << "</base>" << endl;
596               }
597             _out << indent(depth) << "</objref>" << endl;
598           }
599         break;
600       }
601     case YACS::ENGINE::Sequence:
602       {
603         TypeCode* content = (TypeCode*)type->contentType();
604         if (typeNames.find(content->name()) == typeNames.end())
605           {
606             //content type not dumped
607             dumpTypeCode(content,typeNames,typeMap,depth);
608           }
609         typeNames.insert(typeName);
610         _out << indent(depth) << "<sequence name=\"" << typeName << "\" content=\""
611              << content->name() <<  "\"/>" << endl;
612         break;
613       }
614     case YACS::ENGINE::Array:
615       {
616         TypeCode* content = (TypeCode*)type->contentType();
617         if (typeNames.find(content->name()) == typeNames.end())
618           {
619             //content type not dumped
620             dumpTypeCode(content,typeNames,typeMap,depth);
621           }
622         typeNames.insert(typeName);
623         _out << indent(depth) << "<array name=\"" << typeName << "\" content=\""
624              << content->name() <<  "\"/>" << endl;
625         break;
626       }
627     case YACS::ENGINE::Struct:
628       {
629         TypeCodeStruct* tcStruct = dynamic_cast<TypeCodeStruct*>(type);
630         YASSERT(tcStruct);
631         int mbCnt = tcStruct->memberCount();
632         for (int i=0; i<mbCnt; i++)
633           {
634             TypeCode* member = tcStruct->memberType(i);
635             if (typeNames.find(member->name()) == typeNames.end())
636               {
637                 //content type not dumped
638                 dumpTypeCode(member,typeNames,typeMap,depth);
639               }            
640           }
641         typeNames.insert(typeName);
642         _out << indent(depth) << "<struct name=\"" << typeName << "\">" << endl;
643         for (int i=0; i<mbCnt; i++)
644           {
645             TypeCode* member = tcStruct->memberType(i);
646             _out << indent(depth+1) << "<member name=\"" <<tcStruct->memberName(i) << "\" type=\"" << member->name() << "\"/>" << endl;
647           }
648         _out << indent(depth) << "</struct>" << endl;
649         break;
650       }
651     default:
652       {
653         string what = "wrong TypeCode: "; 
654         throw Exception(what);
655       }
656     }
657 }
658
659 void VisitorSaveSchema::writeTypeCodes(Proc *proc)
660 {
661   int depth = depthNode(proc)+1;
662   map<string, TypeCode*> typeMap = getTypeCodeMap(proc);
663   map<string, TypeCode*>::const_iterator it;
664   set<string> typeNames;
665
666   // --- force definition of simple types first
667
668   for (it = typeMap.begin(); it != typeMap.end(); it++)
669     {
670       dumpTypeCode(it->second,typeNames,typeMap,depth);
671     }
672 }
673
674 void VisitorSaveSchema::writeComponentInstances(Proc *proc)
675 {
676   int depth = depthNode(proc)+1;
677   std::map<std::string, ComponentInstance*>::const_iterator it;
678   for (it = proc->componentInstanceMap.begin(); it != proc->componentInstanceMap.end(); it++)
679     {
680       string name = it->first;
681       ComponentInstance* inst=it->second;
682       if(!inst->isAnonymous())
683         {
684           _out << indent(depth) << "<componentinstance name=\"" << inst->getInstanceName() << "\">" << endl;
685           _out << indent(depth+1) << "<component>" << inst->getCompoName() << "</component>" << endl;
686
687           Container *cont = inst->getContainer();
688           if (cont)
689             _out << indent(depth+1) << "<load container=\"" << cont->getName() << "\"/>" << endl;
690
691           std::map<std::string, std::string> properties = inst->getProperties();
692           std::map<std::string, std::string>::const_iterator itm;
693           for(itm = properties.begin(); itm != properties.end(); ++itm)
694             _out << indent(depth+1) << "<property name=\"" << (*itm).first
695                  << "\" value=\"" << (*itm).second << "\"/>" << endl;
696
697           _out << indent(depth) << "</componentinstance>" << endl;
698         }
699     }
700 }
701
702 void VisitorSaveSchema::writeContainers(Proc *proc)
703 {
704   int depth = depthNode(proc)+1;
705   _containerMap = getContainerMap(proc);
706   map<string, Container*>::const_iterator it; 
707   for (it = _containerMap.begin(); it != _containerMap.end(); it++)
708     {
709       string name = it->first;
710       _out << indent(depth) << "<container name=\"" << name << "\">" << endl;
711       _out << indent(depth+1) << "<property name=\"" << Container::KIND_ENTRY << "\" value=\"" << it->second->getKind() << "\"/>" << endl;
712       _out << indent(depth+1) << "<property name=\"" << Container::AOC_ENTRY << "\" value=\"" << (int)it->second->isAttachedOnCloning() << "\"/>" << endl;
713       map<string, string> properties = (it->second)->getProperties();
714       map<string, string>::iterator itm;
715       for(itm = properties.begin(); itm != properties.end(); ++itm)
716         {
717           if((*itm).first==Container::KIND_ENTRY)
718             continue;
719           if((*itm).first==Container::AOC_ENTRY)
720             continue;
721           if((*itm).first!=HomogeneousPoolContainer::INITIALIZE_SCRIPT_KEY)
722             {
723               _out << indent(depth+1) << "<property name=\"" << (*itm).first << "\" value=\"" << (*itm).second << "\"/>" << endl;
724             }
725           else
726             {
727               _out << indent(depth+1) << "<initializescriptkey><code><![CDATA[" << (*itm).second << "]]></code></initializescriptkey>" << endl;
728             }
729         }
730       _out << indent(depth) << "</container>"  << endl;
731     }
732 }
733
734
735 void VisitorSaveSchema::writeInputPorts(Node *node)
736 {
737   int depth = depthNode(node)+1;
738   list<InputPort*> listOfInputPorts = node->getSetOfInputPort();
739   for (list<InputPort*>::iterator it = listOfInputPorts.begin(); it != listOfInputPorts.end(); ++it)
740     {
741       _out << indent(depth) << "<inport name=\"" << (*it)->getName() << "\" type=\"" 
742            << (*it)->edGetType()->name() << "\"/>" << endl;
743     }
744 }
745
746 void VisitorSaveSchema::writeInputDataStreamPorts(Node *node)
747 {
748   int depth = depthNode(node)+1;
749   list<InputDataStreamPort*> listOfInputPorts = node->getSetOfInputDataStreamPort();
750   for (list<InputDataStreamPort*>::iterator it = listOfInputPorts.begin(); it != listOfInputPorts.end(); ++it)
751     {
752       std::map<std::string,std::string> aPropMap = (*it)->getProperties();
753       if ( aPropMap.empty() )
754         _out << indent(depth) << "<instream name=\"" << (*it)->getName() << "\" type=\"" 
755              << (*it)->edGetType()->name() << "\"/>" << endl;
756       else
757         {
758           _out << indent(depth) << "<instream name=\"" << (*it)->getName() << "\" type=\"" 
759                << (*it)->edGetType()->name() << "\">" << endl;
760           for (std::map<std::string,std::string>::iterator itP = aPropMap.begin(); itP != aPropMap.end(); itP++)
761             _out << indent(depth+1) << "<property name=\"" << (*itP).first << "\" value=\"" 
762                  << (*itP).second << "\"/>" << endl;
763           _out << indent(depth) << "</instream>" << endl;
764         }
765     }
766 }
767
768 void VisitorSaveSchema::writeOutputPorts(Node *node)
769 {
770   int depth = depthNode(node)+1;
771   list<OutputPort*> listOfOutputPorts = node->getSetOfOutputPort();
772   for (list<OutputPort*>::iterator it = listOfOutputPorts.begin(); it != listOfOutputPorts.end(); ++it)
773     {
774       _out << indent(depth) << "<outport name=\"" << (*it)->getName() << "\" type=\"" 
775            << (*it)->edGetType()->name() << "\"/>" << endl;
776     }
777 }
778
779 void VisitorSaveSchema::writeOutputDataStreamPorts(Node *node)
780 {
781   int depth = depthNode(node)+1;
782   list<OutputDataStreamPort*> listOfOutputPorts = node->getSetOfOutputDataStreamPort();
783   for (list<OutputDataStreamPort*>::iterator it = listOfOutputPorts.begin(); it != listOfOutputPorts.end(); ++it)
784     {
785       std::map<std::string,std::string> aPropMap = (*it)->getProperties();
786       if ( aPropMap.empty() )
787         _out << indent(depth) << "<outstream name=\"" << (*it)->getName() << "\" type=\"" 
788              << (*it)->edGetType()->name() << "\"/>" << endl;
789       else
790         {
791           _out << indent(depth) << "<outstream name=\"" << (*it)->getName() << "\" type=\"" 
792                << (*it)->edGetType()->name() << "\">" << endl;
793           for (std::map<std::string,std::string>::iterator itP = aPropMap.begin(); itP != aPropMap.end(); itP++)
794             _out << indent(depth+1) << "<property name=\"" << (*itP).first << "\" value=\"" 
795                  << (*itP).second << "\"/>" << endl;
796           _out << indent(depth) << "</outstream>" << endl;
797         }
798     }
799 }
800
801 void VisitorSaveSchema::writeControls(ComposedNode *node)
802 {
803   int depth = depthNode(node)+1;
804   list<Node*> setOfChildren =  node->edGetDirectDescendants();
805   for (list<Node*>::iterator ic = setOfChildren.begin(); ic != setOfChildren.end(); ++ic)
806     {
807       // --- Control links from direct descendant to nodes inside the bloc
808       list<InGate*> setOfInGates = (*ic)->getOutGate()->edSetInGate();
809       for (list<InGate*>::iterator ig = setOfInGates.begin(); ig != setOfInGates.end(); ++ig)
810         {
811           Node *to = (*ig)->getNode();
812           if (node->isInMyDescendance(to))
813             {
814               Node *from = (*ic);
815               _out << indent(depth) << "<control> <fromnode>" << node->getChildName(from) << "</fromnode> ";
816               _out << "<tonode>" << node->getChildName(to) << "</tonode> </control>" << endl;
817             }
818         }
819       // --- Control links from nodes inside the bloc to direct descendant
820       //     avoid links between direct descendants (already done above)
821       list<OutGate*> listOfOutGates = (*ic)->getInGate()->getBackLinks();
822       for (list<OutGate*>::iterator ig = listOfOutGates.begin(); ig != listOfOutGates.end(); ++ig)
823         {
824           Node *from = (*ig)->getNode();
825           if ((node->isInMyDescendance(from)) && (from->getFather()->getNumId() != node->getNumId()))
826             {
827               Node *to = *ic;
828               _out << indent(depth) << "<control> <fromnode>" << node->getChildName(from) << "</fromnode> ";
829               _out << "<tonode>" << node->getChildName(to) << "</tonode> </control>" << endl;
830             }
831         }
832     }
833 }
834
835 /*!
836  * Write simple data links from and to direct children of node (grand children already done).
837  * First, for all output ports of direct children, write links where the input port is inside
838  * the node scope. Keep in memory the links where the input port is outside the node scope.
839  * Second, retreive links where the output port is inside the scope, using the links kept in memory
840  * and not yet written.
841  */
842 void VisitorSaveSchema::writeSimpleDataLinks(ComposedNode *node)
843 {
844   int depth = depthNode(node)+1;
845   list<Node*> setOfChildren =  node->edGetDirectDescendants();
846
847   list<Node*> setOfChildrenPlusSplitters = setOfChildren;
848
849   for (list<Node*>::iterator ic = setOfChildren.begin(); ic != setOfChildren.end(); ++ic)
850     // add "splitter" node of ForEachLoop nodes to the set of children
851     if ( dynamic_cast<ForEachLoop*>( *ic ) )
852       {
853         Node *nodeToInsert=(*ic)->getChildByName(ForEachLoop::NAME_OF_SPLITTERNODE);
854         if(find(setOfChildrenPlusSplitters.begin(),setOfChildrenPlusSplitters.end(),nodeToInsert)==setOfChildrenPlusSplitters.end())
855           setOfChildrenPlusSplitters.push_back(nodeToInsert);
856       }
857   
858   // --- first pass,  write links where the input port is inside the node scope. Keep in memory others.
859   
860   for (list<Node*>::iterator ic = setOfChildrenPlusSplitters.begin(); ic != setOfChildrenPlusSplitters.end(); ++ic)
861     {
862       Node* from = *ic;
863       list<OutputPort*> listOP = from->getLocalOutputPorts();
864       for (list<OutputPort*>::iterator io = listOP.begin(); io != listOP.end(); ++io)
865         {
866           OutputPort* anOP = *io;
867           set<InPort*> setIP = anOP->edSetInPort();
868           for (set<InPort*>::iterator iip = setIP.begin(); iip != setIP.end(); ++iip)
869             {
870               InPort *anIP = *iip;
871               Node* to = anIP->getNode();
872               DEBTRACE("from " << from->getName() << " outputPort " << anOP->getName()
873                        << " to " << to->getName() << " inputPort " << anIP->getName() );
874               Node* child = node->isInMyDescendance(to);
875               if (child && (child->getNumId() != node->getNumId())
876                   && (from->getNumId() != to->getNumId()))
877                 {
878                   DEBTRACE( "BINGO!" );
879
880                   string fromName;
881                   if ( dynamic_cast<SplitterNode*>(from) && dynamic_cast<ForEachLoop*>(from->getFather()) )
882                     fromName = from->getFather()->getName();
883                   else
884                     fromName = node->getChildName(from);
885
886                   string childName;
887                   if ( dynamic_cast<SplitterNode*>(to) && dynamic_cast<ForEachLoop*>(to->getFather()) )
888                     childName = node->getChildName(to->getFather());
889                   else
890                     childName = node->getChildName(to);
891                   _out << indent(depth) << "<datalink control=\"false\">" << endl;
892                   _out << indent(depth+1) << "<fromnode>" << fromName << "</fromnode> ";
893                   _out << "<fromport>" << anOP->getName() << "</fromport>" << endl;
894                   _out << indent(depth+1) << "<tonode>" << childName << "</tonode> ";
895                   _out << "<toport>" << anIP->getName() << "</toport>" << endl;
896                   _out << indent(depth) << "</datalink>" << endl;
897                 }
898               else
899                 { // --- store info to create the link later, given the input port
900                   DEBTRACE( "For later" );
901                   struct DataLinkInfo aLink = { from, to, anOP, anIP, false };
902                   _mapOfDLtoCreate.insert(make_pair(anIP->getNumId(), aLink));
903                 }
904             }
905         }
906     }
907
908   // --- second pass, retreive links where the output port is inside the scope.
909
910   if (!dynamic_cast<Switch*>(node)) // xml parser does not take into account datalinks in a switch context
911     {
912       std::multimap<int, DataLinkInfo>::iterator pos;
913       for (pos = _mapOfDLtoCreate.begin(); pos != _mapOfDLtoCreate.end(); ++pos)
914         {
915           Node* to = (pos->second).to;
916           Node* child = node->isInMyDescendance(to);
917           if (child && (child->getNumId() != node->getNumId()))
918             {
919               InPort* anIP = (pos->second).inp;
920               int portId = anIP->getNumId();
921               Node* from = (pos->second).from;
922               child = node->isInMyDescendance(from);
923               if (child && (child->getNumId() != node->getNumId()))
924                 if((from->getNumId() != to->getNumId()) || dynamic_cast<Loop*>(node))
925                   {
926                     string childName = node->getChildName(from);
927                     OutPort *anOP = (pos->second).outp;
928                     (pos->second).toDelete = true;
929                     _out << indent(depth) << "<datalink control=\"false\">" << endl;
930                     _out << indent(depth+1) << "<fromnode>" << childName << "</fromnode> ";
931                     _out << "<fromport>" << anOP->getName() << "</fromport>" << endl;
932                     _out << indent(depth+1) << "<tonode>" << node->getChildName(to) << "</tonode> ";
933                     _out << "<toport>" << anIP->getName() << "</toport>" << endl;
934                     _out << indent(depth) << "</datalink>" << endl;
935                   }
936             }
937         }
938
939       // --- remove the link written from the multimap
940       
941       for (pos = _mapOfDLtoCreate.begin(); pos != _mapOfDLtoCreate.end();)
942         {
943           if ((pos->second).toDelete)
944             _mapOfDLtoCreate.erase(pos++); // be careful not to saw off the branch on which you are sitting!
945           else
946             ++pos;
947         }
948     }
949 }
950
951 void VisitorSaveSchema::writeSimpleStreamLinks(ComposedNode *node)
952 {
953   int depth = depthNode(node)+1;
954   list<Node*> setOfChildren =  node->edGetDirectDescendants();
955
956   // --- first pass,  write links where the input port is inside the node scope. Keep in memory others.
957
958   for (list<Node*>::iterator ic = setOfChildren.begin(); ic != setOfChildren.end(); ++ic)
959     {
960       Node* from = *ic;
961       if ( dynamic_cast<ComposedNode*>(from) ) continue;
962       list<OutputDataStreamPort*> listOP = from->getSetOfOutputDataStreamPort();
963       for (list<OutputDataStreamPort*>::iterator io = listOP.begin(); io != listOP.end(); ++io)
964         {
965           OutputDataStreamPort* anOP = *io;
966           set<InPort*> setIP = anOP->edSetInPort();
967           for (set<InPort*>::iterator iip = setIP.begin(); iip != setIP.end(); ++iip)
968             {
969               InPort *anIP = *iip;
970               Node* to = anIP->getNode();
971               DEBTRACE("from " << from->getName() << " outputPort " << anOP->getName()
972                        << " to " << to->getName() << " inputPort " << anIP->getName() );
973               Node* child = node->isInMyDescendance(to);
974               if (child && (child->getNumId() != node->getNumId())
975                   && (from->getNumId() != to->getNumId()))
976                 {
977                   DEBTRACE( "BINGO!" );
978                   string childName = node->getChildName(to);
979                   _out << indent(depth) << "<stream>" << endl;
980                   _out << indent(depth+1) << "<fromnode>" << node->getChildName(from) << "</fromnode> ";
981                   _out << "<fromport>" << anOP->getName() << "</fromport>" << endl;
982                   _out << indent(depth+1) << "<tonode>" << childName << "</tonode> ";
983                   _out << "<toport>" << anIP->getName() << "</toport>" << endl;
984
985                   std::map<std::string,std::string> aPropMap = dynamic_cast<InputDataStreamPort*>(anIP)->getProperties();
986                   for (std::map<std::string,std::string>::iterator itP = aPropMap.begin(); itP != aPropMap.end(); itP++)
987                     {
988                       string notAlinkProperty = "DependencyType";
989                       if (notAlinkProperty != (*itP).first)
990                         _out << indent(depth+1) << "<property name=\"" << (*itP).first << "\" value=\"" 
991                              << (*itP).second << "\"/>" << endl;
992                     }
993                   _out << indent(depth) << "</stream>" << endl;
994                 }
995               else
996                 { // --- store info to create the link later, given the input port
997                   DEBTRACE("For later" );
998                   struct StreamLinkInfo aLink = { from, to, anOP, anIP, false };
999                   _mapOfSLtoCreate.insert(make_pair(anIP->getNumId(), aLink));
1000                 }
1001             }
1002         }
1003     }
1004
1005   // --- second pass, retreive links where the output port is inside the scope.
1006
1007   if (!dynamic_cast<Switch*>(node)) // xml parser does not take into account datalinks in a switch context
1008     {
1009       std::multimap<int, StreamLinkInfo>::iterator pos;
1010       for (pos = _mapOfSLtoCreate.begin(); pos != _mapOfSLtoCreate.end(); ++pos)
1011         {
1012           Node* to = (pos->second).to;
1013           Node* child = node->isInMyDescendance(to);
1014           if (child && (child->getNumId() != node->getNumId()))
1015             {
1016               InPort* anIP = (pos->second).inp;
1017               int portId = anIP->getNumId();
1018               Node* from = (pos->second).from;
1019               child = node->isInMyDescendance(from);
1020               if (child && (child->getNumId() != node->getNumId()))
1021                 if((from->getNumId() != to->getNumId()) || dynamic_cast<Loop*>(node))
1022                   {
1023                     string childName = node->getChildName(from);
1024                     OutputDataStreamPort *anOP = (pos->second).outp;
1025                     (pos->second).toDelete = true;
1026                     _out << indent(depth) << "<stream>" << endl;
1027                     _out << indent(depth+1) << "<fromnode>" << childName << "</fromnode> ";
1028                     _out << "<fromport>" << anOP->getName() << "</fromport>" << endl;
1029                     _out << indent(depth+1) << "<tonode>" << node->getChildName(to) << "</tonode> ";
1030                     _out << "<toport>" << anIP->getName() << "</toport>" << endl;
1031
1032                     std::map<std::string,std::string> aPropMap = dynamic_cast<InputDataStreamPort*>(anIP)->getProperties();
1033                     for (std::map<std::string,std::string>::iterator itP = aPropMap.begin(); itP != aPropMap.end(); itP++)
1034                       _out << indent(depth+1) << "<property name=\"" << (*itP).first << "\" value=\"" 
1035                            << (*itP).second << "\"/>" << endl;
1036
1037                     _out << indent(depth) << "</stream>" << endl;
1038                   }
1039             }
1040         }
1041
1042       // --- remove the link written from the multimap
1043       
1044       for (pos = _mapOfSLtoCreate.begin(); pos != _mapOfSLtoCreate.end();)
1045         {
1046           if ((pos->second).toDelete)
1047             _mapOfSLtoCreate.erase(pos++); // be careful not to saw off the branch on which you are sitting!
1048           else
1049             ++pos;
1050         }
1051     }
1052 }
1053
1054 std::set<Node*> VisitorSaveSchema::getAllNodes(ComposedNode *node)
1055 {
1056   set<Node *> ret;
1057   list< Node *> setOfNode = node->edGetDirectDescendants();
1058   for(list<Node *>::iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
1059     {
1060       if ( dynamic_cast<ComposedNode*> (*iter) )
1061         {
1062           set<Node *> myCurrentSet = getAllNodes(dynamic_cast<ComposedNode*> (*iter));
1063           ret.insert(myCurrentSet.begin(),myCurrentSet.end());
1064           ret.insert(*iter);
1065         }
1066       else
1067         {
1068           list<ElementaryNode *> myCurrentSet=(*iter)->getRecursiveConstituents();
1069           ret.insert(myCurrentSet.begin(),myCurrentSet.end());
1070           ret.insert(*iter);
1071         }
1072     }
1073   return ret;
1074 }
1075
1076 void VisitorSaveSchema::writeParameters(Proc *proc)
1077 {
1078   //  set<Node*> nodeSet = proc->getAllRecursiveConstituents();
1079   set<Node*> nodeSet = getAllNodes(proc);
1080   for (set<Node*>::iterator iter = nodeSet.begin(); iter != nodeSet.end(); ++iter)
1081     {
1082       //       ElementaryNode *node = dynamic_cast<ElementaryNode*>(*iter);
1083       //       if (node)
1084       //         writeParametersNode(proc,node);
1085       writeParametersNode(proc,(*iter));
1086     }
1087 }
1088
1089 void VisitorSaveSchema::writeParametersNode(ComposedNode *proc, Node *node)
1090 {
1091   int depth = 1;
1092   list<InputPort *> setOfInputPort = node->getLocalInputPorts();
1093   list<InputPort *>::iterator iter;
1094   for(iter = setOfInputPort.begin(); iter != setOfInputPort.end(); ++iter)
1095     {
1096       if (!(*iter)->isEmpty())
1097         {
1098           _out << indent(depth) << "<parameter>" << endl;
1099           _out << indent(depth+1) << "<tonode>" << proc->getChildName(node) << "</tonode>";
1100           _out << "<toport>" << (*iter)->getName() << "</toport>" <<endl;
1101           try
1102             {
1103               _out << indent(depth+1) << (*iter)->dump();
1104             }
1105           catch (YACS::Exception &e)
1106             {
1107               _out << "<value><error><![CDATA[" << e.what() << "]]></error></value>" << endl;
1108             }
1109           _out << indent(depth) << "</parameter>" << endl;
1110         }
1111     }
1112 }
1113
1114 void VisitorSaveSchema::beginCase(Node* node)
1115 {
1116   Switch *myFather =dynamic_cast<Switch*>(node->getFather());
1117   if (myFather)
1118     {
1119       int depth = depthNode(node) -1;
1120       int myCase = myFather->getRankOfNode(node);
1121       if (myCase == Switch::ID_FOR_DEFAULT_NODE)
1122         _out << indent(depth) << "<default>" << endl;
1123       else
1124         _out << indent(depth) << "<case id=\"" << myCase << "\">" << endl;
1125     }
1126 }
1127
1128 void VisitorSaveSchema::endCase(Node* node)
1129 {
1130   Switch *myFather =dynamic_cast<Switch*>(node->getFather());
1131   if (myFather)
1132     {
1133       int depth = depthNode(node) -1;
1134       int myCase = myFather->getRankOfNode(node);
1135       if (myCase == Switch::ID_FOR_DEFAULT_NODE)
1136         _out << indent(depth) << "</default>" << endl;
1137       else
1138         _out << indent(depth) << "</case>" << endl;
1139     }
1140 }
1141
1142 int VisitorSaveSchema::depthNode(Node* node)
1143 {
1144   int depth = 0;
1145   ComposedNode *father = node->getFather();
1146   while (father)
1147     {
1148       depth +=1;
1149       if (dynamic_cast<Switch*>(father)) depth +=1;
1150       if (father->getNumId() == _root->getNumId()) break;
1151       father = father->getFather();
1152     }
1153   return depth;
1154 }
1155
1156 SchemaSave::SchemaSave(Proc* proc): _p(proc)
1157 {
1158   YASSERT(_p);
1159 }
1160
1161 void SchemaSave::save(std::string xmlSchemaFile)
1162 {
1163   VisitorSaveSchema vss(_p);
1164   vss.openFileSchema(xmlSchemaFile);
1165   _p->accept(&vss);
1166   vss.closeFileSchema();
1167 }