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