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