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