Salome HOME
mergefrom branch BR_V511_PR tag mergeto_trunk_03feb09
[modules/yacs.git] / src / yacsloader / loopParsers.hxx
1 //  Copyright (C) 2006-2008  CEA/DEN, EDF R&D
2 //
3 //  This library is free software; you can redistribute it and/or
4 //  modify it under the terms of the GNU Lesser General Public
5 //  License as published by the Free Software Foundation; either
6 //  version 2.1 of the License.
7 //
8 //  This library is distributed in the hope that it will be useful,
9 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 //  Lesser General Public License for more details.
12 //
13 //  You should have received a copy of the GNU Lesser General Public
14 //  License along with this library; if not, write to the Free Software
15 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 #ifndef _LOOPPARSER_HXX_
20 #define _LOOPPARSER_HXX_
21
22 #include "parserBase.hxx"
23
24 #include "Bloc.hxx"
25 #include "Proc.hxx"
26 #include "Logger.hxx"
27 #include "Exception.hxx"
28 #include "InlineNode.hxx"
29 #include "ServiceNode.hxx"
30 #include "ServiceInlineNode.hxx"
31 #include "OutputDataStreamPort.hxx"
32 #include "InputDataStreamPort.hxx"
33 #include "ForLoop.hxx"
34 #include "WhileLoop.hxx"
35 #include "Switch.hxx"
36 #include "ForEachLoop.hxx"
37
38 #include <vector>
39 #include <string>
40 #include <sstream>
41
42 namespace YACS
43 {
44
45 template <class T=ENGINE::Loop*>
46 struct looptypeParser:parser
47 {
48   void onStart(const XML_Char* el, const XML_Char** attr);
49   void onEnd(const char *el,parser* child);
50   virtual void buildAttr(const XML_Char** attr);
51   virtual void pre ();
52   virtual void name (const std::string& name);
53   virtual void state (const std::string& name);
54   virtual void property (const myprop& prop);
55   virtual void inline_ (ENGINE::InlineNode* const& n);
56   virtual void sinline (ENGINE::ServiceInlineNode* const& n);
57   virtual void service (ENGINE::ServiceNode* const& n);
58   virtual void node (ENGINE::InlineNode* const& n);
59   virtual void forloop (ENGINE::ForLoop* const& b);
60   virtual void foreach (ENGINE::ForEachLoop* const& b);
61   virtual void while_ (ENGINE::WhileLoop* const& b);
62   virtual void switch_ (ENGINE::Switch* const& b);
63   virtual void bloc (ENGINE::Bloc* const& b);
64   virtual void datalink (const mylink& l);
65   std::string _state;
66   T _cnode;
67   std::vector<T> _cnodes;
68 };
69
70 }
71
72 namespace YACS
73 {
74   // A loop can contain forloop, whileloop or foreachloop
75   // We must respect the order : definition of loop, then while, for, .. and then onStart, onEnd for loop !!!
76   //
77   static std::string t3[]={"inline","sinline","service","node","forloop","foreach","while","switch","bloc",""};
78
79 template <class T>
80 void looptypeParser<T>::buildAttr(const XML_Char** attr)
81     {
82       this->required("name",attr);
83       for (int i = 0; attr[i]; i += 2) 
84         {
85           if(std::string(attr[i]) == "name")name(attr[i+1]);
86           if(std::string(attr[i]) == "state")state(attr[i+1]);
87         }
88     }
89 template <class T>
90 void looptypeParser<T>::pre ()
91     {
92       _state="";
93       _cnode=0;
94     }
95 template <class T>
96 void looptypeParser<T>::name (const std::string& name)
97     {
98       DEBTRACE( "bloc_name: " << name );
99     }
100 template <class T>
101 void looptypeParser<T>::state (const std::string& name)
102     {
103       DEBTRACE( "bloc_state: " << name );
104       _state=name;
105     }
106 template <class T>
107 void looptypeParser<T>::property (const myprop& prop)
108     {
109       DEBTRACE( "property_set" << prop._name << prop._value );
110     }
111
112 template <class T>
113 void looptypeParser<T>::inline_ (ENGINE::InlineNode* const& n)
114     {
115       DEBTRACE( "loop_inline" << n->getName() );
116       _cnode->edSetNode(n);
117       std::string fullname=currentProc->names.back()+ n->getName();
118       currentProc->nodeMap[fullname]=n;
119       currentProc->inlineMap[fullname]=n;
120     }
121 template <class T>
122 void looptypeParser<T>::sinline (ENGINE::ServiceInlineNode* const& n)
123     {
124       DEBTRACE( "loop_sinline" << n->getName() )             
125       _cnode->edSetNode(n);
126       std::string fullname=currentProc->names.back()+ n->getName();
127       currentProc->nodeMap[fullname]=n;
128       currentProc->serviceMap[fullname]=n;
129     }
130 template <class T>
131 void looptypeParser<T>::service (ENGINE::ServiceNode* const& n)
132     {
133       DEBTRACE( "loop_service" << n->getName() )             
134       _cnode->edSetNode(n);
135       std::string fullname=currentProc->names.back()+ n->getName();
136       currentProc->nodeMap[fullname]=n;
137       currentProc->serviceMap[fullname]=n;
138     }
139 template <class T>
140 void looptypeParser<T>::node (ENGINE::InlineNode* const& n)
141     {
142       DEBTRACE( "loop_node" << n->getName() )             
143       _cnode->edSetNode(n);
144       std::string fullname=currentProc->names.back()+ n->getName();
145       currentProc->nodeMap[fullname]=n;
146       currentProc->inlineMap[fullname]=n;
147     }
148 template <class T>
149 void looptypeParser<T>::forloop (ENGINE::ForLoop* const& b)
150     {
151       DEBTRACE( "loop_forloop" << b->getName() )             
152       _cnode->edSetNode(b);
153       std::string fullname=currentProc->names.back()+ b->getName();
154       currentProc->nodeMap[fullname]=b;
155     }
156 template <class T>
157 void looptypeParser<T>::foreach (ENGINE::ForEachLoop* const& b)
158     {
159       DEBTRACE("loop_foreach" << b->getName())
160       _cnode->edSetNode(b);
161       std::string fullname=currentProc->names.back()+ b->getName();
162       currentProc->nodeMap[fullname]=b;
163       fullname += ".splitter";
164       currentProc->nodeMap[fullname]=b->getChildByShortName("splitter");
165     }
166 template <class T>
167 void looptypeParser<T>::while_ (ENGINE::WhileLoop* const& b)
168     {
169       DEBTRACE( "loop_while: " << b->getName() )             
170       _cnode->edSetNode(b);
171       std::string fullname=currentProc->names.back()+ b->getName();
172       currentProc->nodeMap[fullname]=b;
173     }
174 template <class T>
175 void looptypeParser<T>::switch_ (ENGINE::Switch* const& b)
176     {
177       DEBTRACE( "loop_switch: " << b->getName() )             
178       _cnode->edSetNode(b);
179       std::string fullname=currentProc->names.back()+ b->getName();
180       currentProc->nodeMap[fullname]=b;
181     }
182 template <class T>
183 void looptypeParser<T>::bloc (ENGINE::Bloc* const& b)
184     {
185       DEBTRACE( "loop_bloc " << b->getName() )             
186       _cnode->edSetNode(b);
187       std::string fullname=currentProc->names.back()+ b->getName();
188       currentProc->nodeMap[fullname]=b;
189     }
190
191 template <class T>
192 void looptypeParser<T>::datalink (const mylink& l)
193     {
194       DEBTRACE( "loop_datalink: " << l.fromnode() << l.fromport() << l.tonode() << l.toport())
195       std::string msg;
196
197       //Try only relative name for from node
198       std::string fromname = currentProc->names.back()+l.fromnode();
199       if(currentProc->nodeMap.count(fromname) == 0)
200         {
201           msg="from node " + l.fromnode() + " does not exist in data link: ";
202           msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")";
203           this->logError(msg);
204           return;
205         }
206       //Try relative name for to node and then absolute one
207       std::string toname = currentProc->names.back()+l.tonode();
208       if(currentProc->nodeMap.count(toname) == 0)
209         {
210           //It's not a relative name. Try an absolute one (I think it's not possible)
211           toname=l.tonode();
212           if(currentProc->nodeMap.count(toname) == 0)
213             {
214               // The TO node does not exist -> error
215               msg="to node " + l.tonode() + " does not exist in data link: ";
216               msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")";
217               this->logError(msg);
218               return;
219             }
220         }
221       // We only link local node and other nodes (relative or absolute name in this order)
222       DEBTRACE(fromname <<":"<<l.fromport()<<toname<<":"<<l.toport());
223       try
224         {
225           if (l.withControl())
226             _cnode->edAddDFLink(currentProc->nodeMap[fromname]->getOutputPort(l.fromport()),
227                                 currentProc->nodeMap[toname]->getInputPort(l.toport()));
228           else
229             _cnode->edAddLink(currentProc->nodeMap[fromname]->getOutputPort(l.fromport()),
230                               currentProc->nodeMap[toname]->getInputPort(l.toport()));
231         }
232       catch(Exception& e)
233         {
234             this->logError(e.what());
235         }
236     }
237
238
239 }
240
241 namespace YACS
242 {
243
244   // While loop specialization
245
246 template <class T=ENGINE::WhileLoop*>
247 struct whilelooptypeParser:looptypeParser<T>
248 {
249   static whilelooptypeParser<T> whileloopParser;
250   virtual void name (const std::string& name);
251   virtual T post();
252 };
253
254 template <class T> whilelooptypeParser<T> whilelooptypeParser<T>::whileloopParser;
255
256 template <class T>
257 void whilelooptypeParser<T>::name (const std::string& name)
258     {
259       DEBTRACE( "while_name: " << name )             
260       std::string fullname=currentProc->names.back()+name;
261       this->_cnode=theRuntime->createWhileLoop(name);
262       currentProc->nodeMap[fullname]=this->_cnode;
263       this->_cnodes.push_back(this->_cnode);
264       currentProc->names.push_back(fullname+'.');
265     }
266
267 template <class T>
268 T whilelooptypeParser<T>::post()
269     {
270       DEBTRACE( "while_post" << this->_cnode->getName() )             
271       ENGINE::InputPort *cond=this->_cnode->edGetConditionPort();
272       cond->edInit(true);
273       T b=this->_cnode;
274       this->_cnodes.pop_back();
275       currentProc->names.pop_back();
276       this->_cnode=this->_cnodes.back();
277       return b;
278     }
279 }
280
281
282
283
284 namespace YACS
285 {
286   // For loop specialization
287
288 template <class T=ENGINE::ForLoop*>
289 struct forlooptypeParser:looptypeParser<T>
290 {
291   static forlooptypeParser<T> forloopParser;
292   virtual void buildAttr(const XML_Char** attr);
293   virtual void name (const std::string& name);
294   virtual void nsteps (const int& n);
295   virtual T post();
296   int _nsteps;
297 };
298
299 template <class T> forlooptypeParser<T> forlooptypeParser<T>::forloopParser;
300
301 template <class T>
302 void forlooptypeParser<T>::buildAttr(const XML_Char** attr)
303     {
304       this->required("name",attr);
305       for (int i = 0; attr[i]; i += 2) 
306         {
307           if(std::string(attr[i]) == "name")name(attr[i+1]);
308           if(std::string(attr[i]) == "state")this->state(attr[i+1]);
309           if(std::string(attr[i]) == "nsteps")nsteps(atoi(attr[i+1]));
310         }
311     }
312
313 template <class T>
314   void forlooptypeParser<T>::name (const std::string& name)
315     {
316       DEBTRACE( "forloop_name: " << name );
317       std::string fullname=currentProc->names.back()+name;
318       this->_cnode=theRuntime->createForLoop(name);
319       currentProc->nodeMap[fullname]=this->_cnode;
320       this->_cnodes.push_back(this->_cnode);
321       currentProc->names.push_back(fullname+'.');
322       _nsteps=0;
323     }
324
325 template <class T>
326 void forlooptypeParser<T>::nsteps (const int& n)
327     {
328       DEBTRACE( "forloop_nsteps: " << n )             
329       if(!this->_cnode)
330           throw Exception("Node name must be defined before nsteps");
331       ENGINE::InputPort *iNbTimes=this->_cnode->edGetNbOfTimesInputPort();
332       iNbTimes->edInit(n);
333     }
334
335 template <class T>
336    T forlooptypeParser<T>::post()
337     {
338       DEBTRACE( "forloop_post" )             
339       T b=this->_cnode;
340       this->_cnodes.pop_back();
341       currentProc->names.pop_back();
342       this->_cnode=this->_cnodes.back();
343       return b;
344     }
345
346 }
347
348 namespace YACS
349 {
350   // Foreach loop specialization
351
352 template <class T=ENGINE::ForEachLoop*>
353 struct foreachlooptypeParser:looptypeParser<T>
354 {
355   static foreachlooptypeParser<T> foreachloopParser;
356
357   virtual void buildAttr(const XML_Char** attr)
358     {
359       this->required("name",attr);
360       this->required("type",attr);
361       for (int i = 0; attr[i]; i += 2) 
362         {
363           if(std::string(attr[i]) == "name")name(attr[i+1]);
364           if(std::string(attr[i]) == "state")this->state(attr[i+1]);
365           if(std::string(attr[i]) == "nbranch")nbranch(atoi(attr[i+1]));
366           if(std::string(attr[i]) == "type")datatype(attr[i+1]);
367         }
368       postAttr();
369     }
370   virtual void pre ()
371     {
372       _nbranch=0;
373       this->looptypeParser<T>::pre();
374     }
375   virtual void name (const std::string& name)
376     {
377       DEBTRACE("foreach_name: " << name)
378       _name=name;
379       _fullname=currentProc->names.back()+name;
380     }
381   virtual void nbranch (const int& n)
382     {
383       DEBTRACE("foreach_nbranch: " << n )
384       _nbranch=n;
385     }
386   virtual void datatype (const std::string& type)
387     {
388       DEBTRACE("foreach_datatype: "<< type)
389       _datatype=type;
390     }
391   virtual void postAttr()
392     {
393       if(currentProc->typeMap.count(_datatype)==0)
394       {
395         //Check if the typecode is defined in the runtime
396         YACS::ENGINE::TypeCode* t=theRuntime->getTypeCode(_datatype);
397         if(t==0)
398         {
399           std::stringstream msg;
400           msg << "Type "<< _datatype <<" does not exist"<<" ("<<__FILE__<<":"<<__LINE__<< ")";
401           throw Exception(msg.str());
402         }
403         else
404         {
405           currentProc->typeMap[_datatype]=t;
406           t->incrRef();
407         }
408       }
409       this->_cnode=theRuntime->createForEachLoop(_name,currentProc->typeMap[_datatype]);
410       //set number of branches
411       if(_nbranch > 0)this->_cnode->edGetNbOfBranchesPort()->edInit(_nbranch);
412       this->_cnodes.push_back(this->_cnode);
413       currentProc->names.push_back(_fullname + '.');
414     }
415   virtual T post()
416     {
417       DEBTRACE("foreach_post" << this->_cnode->getName())
418       T b=this->_cnode;
419       this->_cnodes.pop_back();
420       currentProc->names.pop_back();
421       if(this->_cnodes.size() == 0)
422         this->_cnode=0;
423       else
424         this->_cnode=this->_cnodes.back();
425       return b;
426     }
427   int _nbranch;
428   std::string _fullname;
429   std::string _name;
430   std::string _datatype;
431 };
432
433 template <class T> foreachlooptypeParser<T> foreachlooptypeParser<T>::foreachloopParser;
434
435 }
436
437 #include "blocParsers.hxx"
438 #include "switchParsers.hxx"
439
440 namespace YACS
441 {
442
443 template <class T>
444 void looptypeParser<T>::onStart(const XML_Char* el, const XML_Char** attr)
445 {
446   DEBTRACE( "looptypeParser::onStart: " << el )
447   std::string element(el);
448   this->maxcount("inline",1,element);
449   this->maxcount("sinline",1,element);
450   this->maxcount("service",1,element);
451   this->maxcount("node",1,element);
452   this->maxcount("forloop",1,element);
453   this->maxcount("foreach",1,element);
454   this->maxcount("while",1,element);
455   this->maxcount("switch",1,element);
456   this->maxcount("bloc",1,element);
457   this->maxchoice(t3,1,element);
458   parser* pp=&parser::main_parser;
459   if(element == "property")pp=&propertytypeParser::propertyParser;
460   else if(element == "inline")pp=&inlinetypeParser<>::inlineParser;
461   else if(element == "sinline")pp=&sinlinetypeParser<>::sinlineParser;
462   else if(element == "service")pp=&servicetypeParser<>::serviceParser;
463   else if(element == "node")pp=&nodetypeParser<>::nodeParser;
464
465   else if(element == "forloop")pp=&forlooptypeParser<>::forloopParser;
466   else if(element == "foreach")pp=&foreachlooptypeParser<>::foreachloopParser;
467   else if(element == "while")pp=&whilelooptypeParser<>::whileloopParser;
468   else if(element == "switch")pp=&switchtypeParser::switchParser;
469   else if(element == "bloc")pp=&bloctypeParser<>::blocParser;
470   else if(element == "datalink")pp=&linktypeParser<>::linkParser;
471   this->SetUserDataAndPush(pp);
472   pp->init();
473   pp->pre();
474   pp->buildAttr(attr);
475 }
476
477 template <class T>
478 void looptypeParser<T>::onEnd(const char *el,parser* child)
479 {
480   DEBTRACE( "looptypeParser::onEnd: " << el )
481   std::string element(el);
482   if(element == "property")property(((propertytypeParser*)child)->post());
483   else if(element == "inline")inline_(((inlinetypeParser<>*)child)->post());
484   else if(element == "sinline")sinline(((sinlinetypeParser<>*)child)->post());
485   else if(element == "service")service(((servicetypeParser<>*)child)->post());
486   else if(element == "node")node(((nodetypeParser<>*)child)->post());
487
488   else if(element == "forloop")forloop(((forlooptypeParser<>*)child)->post());
489   else if(element == "foreach")foreach(((foreachlooptypeParser<>*)child)->post());
490   else if(element == "while")while_(((whilelooptypeParser<>*)child)->post());
491   else if(element == "switch")switch_(((switchtypeParser*)child)->post());
492   else if(element == "bloc")bloc(((bloctypeParser<>*)child)->post());
493
494   else if(element == "datalink") datalink(((linktypeParser<>*)child)->post());
495 }
496
497 }
498 #endif