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