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