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