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