Salome HOME
Update copyrights 2014.
[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       map<string, string> properties = (it->second)->getProperties();
703       map<string, string>::iterator itm;
704       for(itm = properties.begin(); itm != properties.end(); ++itm)
705         _out << indent(depth+1) << "<property name=\"" << (*itm).first
706              << "\" value=\"" << (*itm).second << "\"/>" << endl;
707       _out << indent(depth) << "</container>"  << endl;
708     }
709 }
710
711
712 void VisitorSaveSchema::writeInputPorts(Node *node)
713 {
714   int depth = depthNode(node)+1;
715   list<InputPort*> listOfInputPorts = node->getSetOfInputPort();
716   for (list<InputPort*>::iterator it = listOfInputPorts.begin(); it != listOfInputPorts.end(); ++it)
717     {
718       _out << indent(depth) << "<inport name=\"" << (*it)->getName() << "\" type=\"" 
719            << (*it)->edGetType()->name() << "\"/>" << endl;
720     }
721 }
722
723 void VisitorSaveSchema::writeInputDataStreamPorts(Node *node)
724 {
725   int depth = depthNode(node)+1;
726   list<InputDataStreamPort*> listOfInputPorts = node->getSetOfInputDataStreamPort();
727   for (list<InputDataStreamPort*>::iterator it = listOfInputPorts.begin(); it != listOfInputPorts.end(); ++it)
728     {
729       std::map<std::string,std::string> aPropMap = (*it)->getProperties();
730       if ( aPropMap.empty() )
731         _out << indent(depth) << "<instream name=\"" << (*it)->getName() << "\" type=\"" 
732              << (*it)->edGetType()->name() << "\"/>" << endl;
733       else
734         {
735           _out << indent(depth) << "<instream name=\"" << (*it)->getName() << "\" type=\"" 
736                << (*it)->edGetType()->name() << "\">" << endl;
737           for (std::map<std::string,std::string>::iterator itP = aPropMap.begin(); itP != aPropMap.end(); itP++)
738             _out << indent(depth+1) << "<property name=\"" << (*itP).first << "\" value=\"" 
739                  << (*itP).second << "\"/>" << endl;
740           _out << indent(depth) << "</instream>" << endl;
741         }
742     }
743 }
744
745 void VisitorSaveSchema::writeOutputPorts(Node *node)
746 {
747   int depth = depthNode(node)+1;
748   list<OutputPort*> listOfOutputPorts = node->getSetOfOutputPort();
749   for (list<OutputPort*>::iterator it = listOfOutputPorts.begin(); it != listOfOutputPorts.end(); ++it)
750     {
751       _out << indent(depth) << "<outport name=\"" << (*it)->getName() << "\" type=\"" 
752            << (*it)->edGetType()->name() << "\"/>" << endl;
753     }
754 }
755
756 void VisitorSaveSchema::writeOutputDataStreamPorts(Node *node)
757 {
758   int depth = depthNode(node)+1;
759   list<OutputDataStreamPort*> listOfOutputPorts = node->getSetOfOutputDataStreamPort();
760   for (list<OutputDataStreamPort*>::iterator it = listOfOutputPorts.begin(); it != listOfOutputPorts.end(); ++it)
761     {
762       std::map<std::string,std::string> aPropMap = (*it)->getProperties();
763       if ( aPropMap.empty() )
764         _out << indent(depth) << "<outstream name=\"" << (*it)->getName() << "\" type=\"" 
765              << (*it)->edGetType()->name() << "\"/>" << endl;
766       else
767         {
768           _out << indent(depth) << "<outstream name=\"" << (*it)->getName() << "\" type=\"" 
769                << (*it)->edGetType()->name() << "\">" << endl;
770           for (std::map<std::string,std::string>::iterator itP = aPropMap.begin(); itP != aPropMap.end(); itP++)
771             _out << indent(depth+1) << "<property name=\"" << (*itP).first << "\" value=\"" 
772                  << (*itP).second << "\"/>" << endl;
773           _out << indent(depth) << "</outstream>" << endl;
774         }
775     }
776 }
777
778 void VisitorSaveSchema::writeControls(ComposedNode *node)
779 {
780   int depth = depthNode(node)+1;
781   list<Node*> setOfChildren =  node->edGetDirectDescendants();
782   for (list<Node*>::iterator ic = setOfChildren.begin(); ic != setOfChildren.end(); ++ic)
783     {
784       // --- Control links from direct descendant to nodes inside the bloc
785       set<InGate*> setOfInGates = (*ic)->getOutGate()->edSetInGate();
786       for (set<InGate*>::iterator ig = setOfInGates.begin(); ig != setOfInGates.end(); ++ig)
787         {
788           Node *to = (*ig)->getNode();
789           if (node->isInMyDescendance(to))
790             {
791               Node *from = (*ic);
792               _out << indent(depth) << "<control> <fromnode>" << node->getChildName(from) << "</fromnode> ";
793               _out << "<tonode>" << node->getChildName(to) << "</tonode> </control>" << endl;
794             }
795         }
796       // --- Control links from nodes inside the bloc to direct descendant
797       //     avoid links between direct descendants (already done above)
798       list<OutGate*> listOfOutGates = (*ic)->getInGate()->getBackLinks();
799       for (list<OutGate*>::iterator ig = listOfOutGates.begin(); ig != listOfOutGates.end(); ++ig)
800         {
801           Node *from = (*ig)->getNode();
802           if ((node->isInMyDescendance(from)) && (from->getFather()->getNumId() != node->getNumId()))
803             {
804               Node *to = *ic;
805               _out << indent(depth) << "<control> <fromnode>" << node->getChildName(from) << "</fromnode> ";
806               _out << "<tonode>" << node->getChildName(to) << "</tonode> </control>" << endl;
807             }
808         }
809     }
810 }
811
812 /*!
813  * Write simple data links from and to direct children of node (grand children already done).
814  * First, for all output ports of direct children, write links where the input port is inside
815  * the node scope. Keep in memory the links where the input port is outside the node scope.
816  * Second, retreive links where the output port is inside the scope, using the links kept in memory
817  * and not yet written.
818  */
819 void VisitorSaveSchema::writeSimpleDataLinks(ComposedNode *node)
820 {
821   int depth = depthNode(node)+1;
822   list<Node*> setOfChildren =  node->edGetDirectDescendants();
823
824   list<Node*> setOfChildrenPlusSplitters = setOfChildren;
825
826   for (list<Node*>::iterator ic = setOfChildren.begin(); ic != setOfChildren.end(); ++ic)
827     // add "splitter" node of ForEachLoop nodes to the set of children
828     if ( dynamic_cast<ForEachLoop*>( *ic ) )
829       {
830         Node *nodeToInsert=(*ic)->getChildByName(ForEachLoop::NAME_OF_SPLITTERNODE);
831         if(find(setOfChildrenPlusSplitters.begin(),setOfChildrenPlusSplitters.end(),nodeToInsert)==setOfChildrenPlusSplitters.end())
832           setOfChildrenPlusSplitters.push_back(nodeToInsert);
833       }
834   
835   // --- first pass,  write links where the input port is inside the node scope. Keep in memory others.
836   
837   for (list<Node*>::iterator ic = setOfChildrenPlusSplitters.begin(); ic != setOfChildrenPlusSplitters.end(); ++ic)
838     {
839       Node* from = *ic;
840       list<OutputPort*> listOP = from->getLocalOutputPorts();
841       for (list<OutputPort*>::iterator io = listOP.begin(); io != listOP.end(); ++io)
842         {
843           OutputPort* anOP = *io;
844           set<InPort*> setIP = anOP->edSetInPort();
845           for (set<InPort*>::iterator iip = setIP.begin(); iip != setIP.end(); ++iip)
846             {
847               InPort *anIP = *iip;
848               Node* to = anIP->getNode();
849               DEBTRACE("from " << from->getName() << " outputPort " << anOP->getName()
850                        << " to " << to->getName() << " inputPort " << anIP->getName() );
851               Node* child = node->isInMyDescendance(to);
852               if (child && (child->getNumId() != node->getNumId())
853                   && (from->getNumId() != to->getNumId()))
854                 {
855                   DEBTRACE( "BINGO!" );
856
857                   string fromName;
858                   if ( dynamic_cast<SplitterNode*>(from) && dynamic_cast<ForEachLoop*>(from->getFather()) )
859                     fromName = from->getFather()->getName();
860                   else
861                     fromName = node->getChildName(from);
862
863                   string childName;
864                   if ( dynamic_cast<SplitterNode*>(to) && dynamic_cast<ForEachLoop*>(to->getFather()) )
865                     childName = node->getChildName(to->getFather());
866                   else
867                     childName = node->getChildName(to);
868                   _out << indent(depth) << "<datalink control=\"false\">" << endl;
869                   _out << indent(depth+1) << "<fromnode>" << fromName << "</fromnode> ";
870                   _out << "<fromport>" << anOP->getName() << "</fromport>" << endl;
871                   _out << indent(depth+1) << "<tonode>" << childName << "</tonode> ";
872                   _out << "<toport>" << anIP->getName() << "</toport>" << endl;
873                   _out << indent(depth) << "</datalink>" << endl;
874                 }
875               else
876                 { // --- store info to create the link later, given the input port
877                   DEBTRACE( "For later" );
878                   struct DataLinkInfo aLink = { from, to, anOP, anIP, false };
879                   _mapOfDLtoCreate.insert(make_pair(anIP->getNumId(), aLink));
880                 }
881             }
882         }
883     }
884
885   // --- second pass, retreive links where the output port is inside the scope.
886
887   if (!dynamic_cast<Switch*>(node)) // xml parser does not take into account datalinks in a switch context
888     {
889       std::multimap<int, DataLinkInfo>::iterator pos;
890       for (pos = _mapOfDLtoCreate.begin(); pos != _mapOfDLtoCreate.end(); ++pos)
891         {
892           Node* to = (pos->second).to;
893           Node* child = node->isInMyDescendance(to);
894           if (child && (child->getNumId() != node->getNumId()))
895             {
896               InPort* anIP = (pos->second).inp;
897               int portId = anIP->getNumId();
898               Node* from = (pos->second).from;
899               child = node->isInMyDescendance(from);
900               if (child && (child->getNumId() != node->getNumId()))
901                 if((from->getNumId() != to->getNumId()) || dynamic_cast<Loop*>(node))
902                   {
903                     string childName = node->getChildName(from);
904                     OutPort *anOP = (pos->second).outp;
905                     (pos->second).toDelete = true;
906                     _out << indent(depth) << "<datalink control=\"false\">" << endl;
907                     _out << indent(depth+1) << "<fromnode>" << childName << "</fromnode> ";
908                     _out << "<fromport>" << anOP->getName() << "</fromport>" << endl;
909                     _out << indent(depth+1) << "<tonode>" << node->getChildName(to) << "</tonode> ";
910                     _out << "<toport>" << anIP->getName() << "</toport>" << endl;
911                     _out << indent(depth) << "</datalink>" << endl;
912                   }
913             }
914         }
915
916       // --- remove the link written from the multimap
917       
918       for (pos = _mapOfDLtoCreate.begin(); pos != _mapOfDLtoCreate.end();)
919         {
920           if ((pos->second).toDelete)
921             _mapOfDLtoCreate.erase(pos++); // be careful not to saw off the branch on which you are sitting!
922           else
923             ++pos;
924         }
925     }
926 }
927
928 void VisitorSaveSchema::writeSimpleStreamLinks(ComposedNode *node)
929 {
930   int depth = depthNode(node)+1;
931   list<Node*> setOfChildren =  node->edGetDirectDescendants();
932
933   // --- first pass,  write links where the input port is inside the node scope. Keep in memory others.
934
935   for (list<Node*>::iterator ic = setOfChildren.begin(); ic != setOfChildren.end(); ++ic)
936     {
937       Node* from = *ic;
938       if ( dynamic_cast<ComposedNode*>(from) ) continue;
939       list<OutputDataStreamPort*> listOP = from->getSetOfOutputDataStreamPort();
940       for (list<OutputDataStreamPort*>::iterator io = listOP.begin(); io != listOP.end(); ++io)
941         {
942           OutputDataStreamPort* anOP = *io;
943           set<InPort*> setIP = anOP->edSetInPort();
944           for (set<InPort*>::iterator iip = setIP.begin(); iip != setIP.end(); ++iip)
945             {
946               InPort *anIP = *iip;
947               Node* to = anIP->getNode();
948               DEBTRACE("from " << from->getName() << " outputPort " << anOP->getName()
949                        << " to " << to->getName() << " inputPort " << anIP->getName() );
950               Node* child = node->isInMyDescendance(to);
951               if (child && (child->getNumId() != node->getNumId())
952                   && (from->getNumId() != to->getNumId()))
953                 {
954                   DEBTRACE( "BINGO!" );
955                   string childName = node->getChildName(to);
956                   _out << indent(depth) << "<stream>" << endl;
957                   _out << indent(depth+1) << "<fromnode>" << node->getChildName(from) << "</fromnode> ";
958                   _out << "<fromport>" << anOP->getName() << "</fromport>" << endl;
959                   _out << indent(depth+1) << "<tonode>" << childName << "</tonode> ";
960                   _out << "<toport>" << anIP->getName() << "</toport>" << endl;
961
962                   std::map<std::string,std::string> aPropMap = dynamic_cast<InputDataStreamPort*>(anIP)->getProperties();
963                   for (std::map<std::string,std::string>::iterator itP = aPropMap.begin(); itP != aPropMap.end(); itP++)
964                     {
965                       string notAlinkProperty = "DependencyType";
966                       if (notAlinkProperty != (*itP).first)
967                         _out << indent(depth+1) << "<property name=\"" << (*itP).first << "\" value=\"" 
968                              << (*itP).second << "\"/>" << endl;
969                     }
970                   _out << indent(depth) << "</stream>" << endl;
971                 }
972               else
973                 { // --- store info to create the link later, given the input port
974                   DEBTRACE("For later" );
975                   struct StreamLinkInfo aLink = { from, to, anOP, anIP, false };
976                   _mapOfSLtoCreate.insert(make_pair(anIP->getNumId(), aLink));
977                 }
978             }
979         }
980     }
981
982   // --- second pass, retreive links where the output port is inside the scope.
983
984   if (!dynamic_cast<Switch*>(node)) // xml parser does not take into account datalinks in a switch context
985     {
986       std::multimap<int, StreamLinkInfo>::iterator pos;
987       for (pos = _mapOfSLtoCreate.begin(); pos != _mapOfSLtoCreate.end(); ++pos)
988         {
989           Node* to = (pos->second).to;
990           Node* child = node->isInMyDescendance(to);
991           if (child && (child->getNumId() != node->getNumId()))
992             {
993               InPort* anIP = (pos->second).inp;
994               int portId = anIP->getNumId();
995               Node* from = (pos->second).from;
996               child = node->isInMyDescendance(from);
997               if (child && (child->getNumId() != node->getNumId()))
998                 if((from->getNumId() != to->getNumId()) || dynamic_cast<Loop*>(node))
999                   {
1000                     string childName = node->getChildName(from);
1001                     OutputDataStreamPort *anOP = (pos->second).outp;
1002                     (pos->second).toDelete = true;
1003                     _out << indent(depth) << "<stream>" << endl;
1004                     _out << indent(depth+1) << "<fromnode>" << childName << "</fromnode> ";
1005                     _out << "<fromport>" << anOP->getName() << "</fromport>" << endl;
1006                     _out << indent(depth+1) << "<tonode>" << node->getChildName(to) << "</tonode> ";
1007                     _out << "<toport>" << anIP->getName() << "</toport>" << endl;
1008
1009                     std::map<std::string,std::string> aPropMap = dynamic_cast<InputDataStreamPort*>(anIP)->getProperties();
1010                     for (std::map<std::string,std::string>::iterator itP = aPropMap.begin(); itP != aPropMap.end(); itP++)
1011                       _out << indent(depth+1) << "<property name=\"" << (*itP).first << "\" value=\"" 
1012                            << (*itP).second << "\"/>" << endl;
1013
1014                     _out << indent(depth) << "</stream>" << endl;
1015                   }
1016             }
1017         }
1018
1019       // --- remove the link written from the multimap
1020       
1021       for (pos = _mapOfSLtoCreate.begin(); pos != _mapOfSLtoCreate.end();)
1022         {
1023           if ((pos->second).toDelete)
1024             _mapOfSLtoCreate.erase(pos++); // be careful not to saw off the branch on which you are sitting!
1025           else
1026             ++pos;
1027         }
1028     }
1029 }
1030
1031 std::set<Node*> VisitorSaveSchema::getAllNodes(ComposedNode *node)
1032 {
1033   set<Node *> ret;
1034   list< Node *> setOfNode = node->edGetDirectDescendants();
1035   for(list<Node *>::iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
1036     {
1037       if ( dynamic_cast<ComposedNode*> (*iter) )
1038         {
1039           set<Node *> myCurrentSet = getAllNodes(dynamic_cast<ComposedNode*> (*iter));
1040           ret.insert(myCurrentSet.begin(),myCurrentSet.end());
1041           ret.insert(*iter);
1042         }
1043       else
1044         {
1045           list<ElementaryNode *> myCurrentSet=(*iter)->getRecursiveConstituents();
1046           ret.insert(myCurrentSet.begin(),myCurrentSet.end());
1047           ret.insert(*iter);
1048         }
1049     }
1050   return ret;
1051 }
1052
1053 void VisitorSaveSchema::writeParameters(Proc *proc)
1054 {
1055   //  set<Node*> nodeSet = proc->getAllRecursiveConstituents();
1056   set<Node*> nodeSet = getAllNodes(proc);
1057   for (set<Node*>::iterator iter = nodeSet.begin(); iter != nodeSet.end(); ++iter)
1058     {
1059       //       ElementaryNode *node = dynamic_cast<ElementaryNode*>(*iter);
1060       //       if (node)
1061       //         writeParametersNode(proc,node);
1062       writeParametersNode(proc,(*iter));
1063     }
1064 }
1065
1066 void VisitorSaveSchema::writeParametersNode(ComposedNode *proc, Node *node)
1067 {
1068   int depth = 1;
1069   list<InputPort *> setOfInputPort = node->getLocalInputPorts();
1070   if (ForEachLoop* foreach = dynamic_cast<ForEachLoop*>(node))
1071     {
1072       DEBTRACE("writeParametersNode foreach");
1073       setOfInputPort.push_back( foreach->edGetSeqOfSamplesPort());
1074     }
1075   list<InputPort *>::iterator iter;
1076   for(iter = setOfInputPort.begin(); iter != setOfInputPort.end(); ++iter)
1077     {
1078       if (!(*iter)->isEmpty())
1079         {
1080           _out << indent(depth) << "<parameter>" << endl;
1081           _out << indent(depth+1) << "<tonode>" << proc->getChildName(node) << "</tonode>";
1082           _out << "<toport>" << (*iter)->getName() << "</toport>" <<endl;
1083           try
1084             {
1085               _out << indent(depth+1) << (*iter)->dump();
1086             }
1087           catch (YACS::Exception &e)
1088             {
1089               _out << "<value><error><![CDATA[" << e.what() << "]]></error></value>" << endl;
1090             }
1091           _out << indent(depth) << "</parameter>" << endl;
1092         }
1093     }
1094 }
1095
1096 void VisitorSaveSchema::beginCase(Node* node)
1097 {
1098   Switch *myFather =dynamic_cast<Switch*>(node->getFather());
1099   if (myFather)
1100     {
1101       int depth = depthNode(node) -1;
1102       int myCase = myFather->getRankOfNode(node);
1103       if (myCase == Switch::ID_FOR_DEFAULT_NODE)
1104         _out << indent(depth) << "<default>" << endl;
1105       else
1106         _out << indent(depth) << "<case id=\"" << myCase << "\">" << endl;
1107     }
1108 }
1109
1110 void VisitorSaveSchema::endCase(Node* node)
1111 {
1112   Switch *myFather =dynamic_cast<Switch*>(node->getFather());
1113   if (myFather)
1114     {
1115       int depth = depthNode(node) -1;
1116       int myCase = myFather->getRankOfNode(node);
1117       if (myCase == Switch::ID_FOR_DEFAULT_NODE)
1118         _out << indent(depth) << "</default>" << endl;
1119       else
1120         _out << indent(depth) << "</case>" << endl;
1121     }
1122 }
1123
1124 int VisitorSaveSchema::depthNode(Node* node)
1125 {
1126   int depth = 0;
1127   ComposedNode *father = node->getFather();
1128   while (father)
1129     {
1130       depth +=1;
1131       if (dynamic_cast<Switch*>(father)) depth +=1;
1132       if (father->getNumId() == _root->getNumId()) break;
1133       father = father->getFather();
1134     }
1135   return depth;
1136 }
1137
1138 SchemaSave::SchemaSave(Proc* proc): _p(proc)
1139 {
1140   YASSERT(_p);
1141 }
1142
1143 void SchemaSave::save(std::string xmlSchemaFile)
1144 {
1145   VisitorSaveSchema vss(_p);
1146   vss.openFileSchema(xmlSchemaFile);
1147   _p->accept(&vss);
1148   vss.closeFileSchema();
1149 }