Salome HOME
Copyright update: 2016
[modules/yacs.git] / src / yacsloader / LoadState.cxx
1 // Copyright (C) 2006-2016  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "LoadState.hxx"
21 #include "Proc.hxx"
22 #include "Node.hxx"
23 #include "ForLoop.hxx"
24 #include "WhileLoop.hxx"
25 #include "Switch.hxx"
26 #include "InGate.hxx"
27 #include "Runtime.hxx"
28 #include "InputPort.hxx"
29 #include "ElementaryNode.hxx"
30
31 #include <iostream>
32 #include <string>
33 #include <cstdlib>
34 #include <cstdarg>
35 #include <cassert>
36
37 //#define _DEVDEBUG_
38 #include "YacsTrace.hxx"
39
40 using namespace YACS::ENGINE;
41 using namespace std;
42
43 XMLReadState    stateParser::_state;
44 std::string     stateParser::_what;
45 std::stack<XMLReadState> stateParser::_stackState;
46 Proc* stateParser::_p;
47 Runtime* stateParser::_runtime;
48 std::map<std::string, YACS::StatesForNode> stateParser::_nodeStateValue;
49 std::map<std::string, YACS::StatesForNode> stateParser::_nodeStates;
50
51 // ----------------------------------------------------------------------------
52 void stateParser::setProc(Proc* p)
53 {
54   _p= p;
55 }
56
57 void stateParser::setRuntime(Runtime* runtime)
58 {
59   _runtime = runtime;
60 }
61
62 void stateParser::init(const xmlChar** p, xmlParserBase* father)
63 {
64   DEBTRACE("stateParser::init()");
65   _state = XMLNOCONTEXT;
66   _father = father;
67   _stackState.push(_state);
68   _nodeStateValue["READY"] =YACS::READY;
69   _nodeStateValue["TOLOAD"] =YACS::TOLOAD;
70   _nodeStateValue["LOADED"] =YACS::LOADED;
71   _nodeStateValue["TOACTIVATE"] =YACS::TOACTIVATE;
72   _nodeStateValue["ACTIVATED"] =YACS::ACTIVATED;
73   _nodeStateValue["DESACTIVATED"] =YACS::DESACTIVATED;
74   _nodeStateValue["DONE"] =YACS::DONE;
75   _nodeStateValue["SUSPENDED"] =YACS::SUSPENDED;
76   _nodeStateValue["LOADFAILED"] =YACS::LOADFAILED;
77   _nodeStateValue["EXECFAILED"] =YACS::EXECFAILED;
78   _nodeStateValue["PAUSE"] =YACS::PAUSE;
79   _nodeStateValue["INTERNALERR"] =YACS::INTERNALERR;
80   _nodeStateValue["DISABLED"] =YACS::DISABLED;
81   _nodeStateValue["FAILED"] =YACS::FAILED;
82   _nodeStateValue["ERROR"] =YACS::ERROR;
83 }
84
85
86 void stateParser::onStart (const XML_Char* elem, const xmlChar** p)
87 {
88   DEBTRACE("stateParser::onStart");
89   string element(elem);
90   stateParser *parser = 0;
91   if (element == "graphState") parser = new graphParser();
92   else
93     { 
94       _what = "expected <graphState>, got <" + element + ">";
95       _state = XMLFATALERROR;
96       stopParse(_what);
97     }
98   if (parser)
99     {
100       _stackParser.push(parser);
101       XML_SetUserData(_xmlParser, parser);
102       parser->init(p);
103     }
104 }
105
106
107 void stateParser::onEnd   (const XML_Char* name)
108 {
109   _stackState.pop();
110   _state = _stackState.top();
111   //cerr << "end " << name << " " << _stackParser.size() << " " << _state << endl;
112 }
113
114
115 void stateParser::charData(std::string data)
116 {
117   //cerr << "data " << data << endl;
118 }
119
120 // ----------------------------------------------------------------------------
121
122 void graphParser::init(const xmlChar** p, xmlParserBase* father)
123 {
124   //  DEBTRACE("graphParser::init()");
125   _state = XMLINGRAPH;
126   _father = father;
127   _stackState.push(_state);
128   if (p) getAttributes(p);
129 }
130
131 void graphParser::onStart (const XML_Char* elem, const xmlChar** p)
132 {
133   string element(elem);
134   stateParser *parser = 0;
135   if (element == "node") parser = new nodeParser();
136   else
137     { 
138       _what = "expected <node>, got <" + element + ">";
139       _state = XMLFATALERROR;
140       stopParse(_what);
141     }
142   if (parser)
143     {
144       _stackParser.push(parser);
145       XML_SetUserData(_xmlParser, parser);
146       parser->init(p, this);
147     }
148 }
149
150
151 void graphParser::onEnd   (const XML_Char* name)
152 {
153   std::map<std::string, YACS::StatesForNode>::const_iterator it;
154   for (it = _nodeStates.begin(); it != _nodeStates.end(); it++)
155     {
156       Node *node =0;
157       string nodeName = it->first;
158       DEBTRACE("nodeName = " << nodeName);
159       if(_p->getName() == nodeName)
160         node = _p;
161       else
162         node = _p->getChildByName(nodeName);
163
164       InGate* inGate = node->getInGate();
165       list<OutGate*> backlinks = inGate->getBackLinks();
166       for (list<OutGate*>::iterator io = backlinks.begin(); io != backlinks.end(); io++)
167         {
168           Node* fromNode = (*io)->getNode();
169           string fromName;
170           if (fromNode == _p) fromName = fromNode->getName();
171           else fromName = _p->getChildName(fromNode);
172           if (_nodeStates[fromName] == YACS::DONE)
173             {
174               DEBTRACE("   fromNode = " << fromName);
175               inGate->setPrecursorDone(*io);
176             }
177         }
178     }
179   stateParser::onEnd(name);
180 }
181
182 // ----------------------------------------------------------------------------
183
184 class outputParser: public stateParser
185 {
186 public:
187   virtual void init(const xmlChar** p, xmlParserBase* father=0)
188   {
189     //DEBTRACE("outputParser::init()");
190     _state = XMLNOCONTEXT;
191     _father = father;
192     YASSERT( dynamic_cast<nodeParser*> (father));
193     _stackState.push(_state);
194     if (p) getAttributes(p);
195   }
196   virtual void onStart (const XML_Char* elem, const xmlChar** p)
197   {
198     //DEBTRACE("outputParser::onStart" << elem);
199     string element(elem);
200     stateParser *parser = 0;
201     if      (element == "name")      parser = new attrParser();
202     else if (element == "value")     parser = new valueParser();
203     else
204     { 
205       _what = "expected name or value, got <" + element + ">";
206       _state = XMLFATALERROR;
207       stopParse(_what);
208     }
209     if (parser)
210     {
211       _stackParser.push(parser);
212       XML_SetUserData(_xmlParser, parser);
213       parser->init(p, this);
214     }
215   }
216   virtual void onEnd   (const XML_Char* name)
217   {
218     //DEBTRACE("outputParser::onEnd" << elem);
219     //DEBTRACE("portName: " << _mapAttrib["name"] << "value: " << _data );
220     stateParser::onEnd(name);
221   }
222   virtual void addData(std::string /*value*/)
223   {
224     //DEBTRACE("outputParser::addData" << elem);
225   }
226 };
227
228 // ----------------------------------------------------------------------------
229
230 void nodeParser::init(const xmlChar** p, xmlParserBase* father)
231 {
232   DEBTRACE("nodeParser::init()");
233   _state = XMLINNODE;
234   _father = father;
235   _stackState.push(_state);
236   if (p) getAttributes(p);
237 }
238
239
240 void nodeParser::onStart (const XML_Char* elem, const xmlChar** p)
241 {
242   DEBTRACE("nodeParser::onStart" << elem);
243   string element(elem);
244   stateParser *parser = 0;
245   if (element == "inputPort")      parser = new portParser();
246   else if (element == "name")      parser = new attrParser();
247   else if (element == "state")     parser = new attrParser();
248   else if (element == "nsteps")    parser = new attrParser();
249   else if (element == "nbdone")    parser = new attrParser();
250   else if (element == "condition") parser = new attrParser();
251   else if (element == "outputPort") parser = new outputParser();
252   else
253     { 
254       _what = "expected name, state or inputPort, got <" + element + ">";
255       _state = XMLFATALERROR;
256       stopParse(_what);
257     }
258   if (parser)
259     {
260       _stackParser.push(parser);
261       XML_SetUserData(_xmlParser, parser);
262       parser->init(p, this);
263     }
264 }
265
266 void nodeParser::onEnd   (const XML_Char* name)
267 {
268   string nodeName = _mapAttrib["name"];
269   string nodeType = _mapAttrib["type"];
270   string nodeState = _mapAttrib["state"];
271   DEBTRACE( "nodeName: " << nodeName << " nodeType: " << nodeType << " nodeState: " << nodeState );
272 //   for (std::map< std::string, Node * >::iterator it=_p->nodeMap.begin(); it != _p->nodeMap.end(); it++)
273 //     cerr << "nodeMap: " << it->first << endl;
274   _nodeStates[nodeName] = _nodeStateValue[nodeState];
275   Node *node =0;
276   if(_p->getName() == nodeName)
277     node=_p;
278   else 
279     node = _p->getChildByName(nodeName);
280
281   YASSERT(_nodeStateValue.find(nodeState) != _nodeStateValue.end());
282   YACS::ENGINE::StateLoader(node, _nodeStateValue[nodeState]);
283
284   if (nodeType == "forLoop")
285     {
286       if (_mapAttrib.find("nsteps") == _mapAttrib.end())
287         {
288           _what = "no attribute nsteps in forLoop " + _mapAttrib["name"];
289           _state = XMLFATALERROR;
290           stopParse(_what);
291         }
292       int nsteps =  atoi(_mapAttrib["nsteps"].c_str());
293
294       if (_mapAttrib.find("nbdone") == _mapAttrib.end())
295         {
296           _what = "no attribute nbdone in forLoop " + _mapAttrib["name"];
297           _state = XMLFATALERROR;
298           stopParse(_what);
299         }
300       int nbdone =  atoi(_mapAttrib["nbdone"].c_str());
301       DEBTRACE("nsteps = " << nsteps << ", nbdone = " << nbdone);
302
303       ForLoop* loop = dynamic_cast<ForLoop*>(node);
304       if (!loop)
305         {
306           _what = "node is not a ForLoop: " + _mapAttrib["name"];
307           _state = XMLFATALERROR;
308           stopParse(_what);
309         }
310       loop->edGetNbOfTimesInputPort()->edInit(nsteps);
311       YACS::ENGINE::NbDoneLoader(loop, nbdone);
312     }
313
314   else if (nodeType == "whileLoop")
315     {
316       if (_mapAttrib.find("nbdone") == _mapAttrib.end())
317         {
318           _what = "no attribute nbdone in forLoop " + _mapAttrib["name"];
319           _state = XMLFATALERROR;
320           stopParse(_what);
321         }
322       int nbdone =  atoi(_mapAttrib["nbdone"].c_str());
323
324       if (_mapAttrib.find("condition") == _mapAttrib.end())
325         {
326           _what = "no attribute condition in forLoop " + _mapAttrib["name"];
327           _state = XMLFATALERROR;
328           stopParse(_what);
329         }
330       bool condition =  atoi(_mapAttrib["condition"].c_str());
331       DEBTRACE("condition = " << condition << ", nbdone = " << nbdone);
332
333       WhileLoop* loop = dynamic_cast<WhileLoop*>(node);
334       if (!loop)
335         {
336           _what = "node is not a WhileLoop: " + _mapAttrib["name"];
337           _state = XMLFATALERROR;
338           stopParse(_what);
339         }
340       loop->edGetConditionPort()->edInit(condition);
341       YACS::ENGINE::NbDoneLoader(loop, nbdone);
342     }
343
344   else if (nodeType == "switch")
345     {
346       if (_mapAttrib.find("condition") == _mapAttrib.end())
347         {
348           _what = "no attribute condition in switch " + _mapAttrib["name"];
349           _state = XMLFATALERROR;
350           stopParse(_what);
351         }
352       int condition =  atoi(_mapAttrib["condition"].c_str());
353       DEBTRACE("condition = " << condition);
354
355       Switch* mySwitch = dynamic_cast<Switch*>(node);
356       if (!mySwitch)
357         {
358           _what = "node is not a Switch: " + _mapAttrib["name"];
359           _state = XMLFATALERROR;
360           stopParse(_what);
361         }
362       mySwitch->edGetConditionPort()->edInit(condition);
363     }
364
365   stateParser::onEnd(name);
366 }
367
368 // ----------------------------------------------------------------------------
369
370 void attrParser::init(const xmlChar** p, xmlParserBase* father)
371 {
372   DEBTRACE("attrParser::init()");
373   //_state = XMLINNODE;
374   _father = father;
375   _stackState.push(_state); // keep current state
376   if (p) getAttributes(p);
377 }
378
379
380 void attrParser::onStart (const XML_Char* elem, const xmlChar** p)
381 {
382   string element(elem);
383   _what = "expected nothing, got <" + element + ">";
384   _state = XMLFATALERROR;
385   stopParse(_what);
386 }
387
388 void attrParser::charData(std::string data)
389 {
390   _attrValue = data;
391 }
392
393 void attrParser::onEnd   (const XML_Char* name)
394 {
395   // cerr << "end attrParser " << name << " " << _stackParser.size() << endl;
396   YASSERT(_father);
397   _father->setAttribute((char*)name, _attrValue);
398   stateParser::onEnd(name);
399 }
400
401 // ----------------------------------------------------------------------------
402
403 void portParser::init(const xmlChar** p, xmlParserBase* father)
404 {
405   DEBTRACE("portParser::init()");
406   _state = XMLINPORT;
407   _father = father;
408   YASSERT( dynamic_cast<nodeParser*> (father));
409   _stackState.push(_state);
410   if (p) getAttributes(p);
411 }
412
413
414 void portParser::onStart (const XML_Char* elem, const xmlChar** p)
415 {
416   DEBTRACE("portParser::onStart" << elem);
417   string element(elem);
418   stateParser *parser = 0;
419   if      (element == "name")      parser = new attrParser();
420   else if (element == "value")     parser = new valueParser();
421   else
422     { 
423       _what = "expected name or value, got <" + element + ">";
424       _state = XMLFATALERROR;
425       stopParse(_what);
426     }
427   if (parser)
428     {
429       _stackParser.push(parser);
430       XML_SetUserData(_xmlParser, parser);
431       parser->init(p, this);
432     }
433 }
434
435 void portParser::addData(std::string value)
436 {
437   _data = value;
438 }
439
440 void portParser::onEnd   (const XML_Char* name)
441 {
442   DEBTRACE("portName: " << _mapAttrib["name"] << "value: " << _data );
443   string nodeName = _father->getAttribute("name");
444   string nodeType = _father->getAttribute("type");
445   Node *node = _p->getChildByName(nodeName);
446   if (nodeType == "elementaryNode")
447     {
448       ElementaryNode* eNode = dynamic_cast<ElementaryNode*>(node);
449       YASSERT(eNode);
450       InputPort *port = eNode->getInputPort(_mapAttrib["name"]);
451       if(_data != "")
452         port->edInit("XML",_data.c_str());
453     }
454   else if (nodeType == "forLoop")
455     {
456       string what="no way to set a port value on port " +  _mapAttrib["name"];
457       what += " in node " + nodeName + " of type " + nodeType;
458       throw Exception(what);
459     }
460   else if (nodeType == "whileLoop")
461     {
462       string what="no way to set a port value on port " +  _mapAttrib["name"];
463       what += " in node " + nodeName + " of type " + nodeType;
464       throw Exception(what);
465     }
466   else if (nodeType == "switch")
467     {
468       string what="no way to set a port value on port " +  _mapAttrib["name"];
469       what += " in node " + nodeName + " of type " + nodeType;
470       throw Exception(what);
471     }
472   else if (nodeType == "foreachLoop")
473     {
474       string what="no way to set a port value on port " +  _mapAttrib["name"];
475       what += " in node " + nodeName + " of type " + nodeType;
476       throw Exception(what);
477     }
478   else 
479     {
480       string what="no way to set a port value on port " +  _mapAttrib["name"];
481       what += " in node " + nodeName + " of type " + nodeType;
482       throw Exception(what);
483     }
484
485   stateParser::onEnd(name);
486 }
487
488 // ----------------------------------------------------------------------------
489
490 void valueParser::init(const xmlChar** p, xmlParserBase* father)
491 {
492   DEBTRACE("valueParser::init()");
493   _state = XMLINVALUE;
494   _father = father;
495   _stackState.push(_state);
496   if (p) getAttributes(p);
497 }
498
499
500 void valueParser::onStart (const XML_Char* elem, const xmlChar** p)
501 {
502   string element(elem);
503   DEBTRACE("value type " << element );
504   stateParser *parser = 0;
505   if      (element == "data")      parser = new dataParser();
506   else if (element == "array")     parser = new arrayParser();
507   else                             parser = new simpleTypeParser();
508   if (parser)
509     {
510       _stackParser.push(parser);
511       XML_SetUserData(_xmlParser, parser);
512       parser->init(p, this);
513     }
514 }
515
516 void valueParser::addData(std::string value)
517 {
518   _data = "<value>" + value + "</value>";
519 }
520
521 void valueParser::onEnd   (const XML_Char* name)
522 {
523   DEBTRACE( _data );
524   _father->addData(_data);
525   string elem = (char *) name;
526   //if (elem == "value" || elem == "data" || elem == "array")
527   stateParser::onEnd(name);
528   //else YASSERT(0); //DEBTRACE("valueParser::onEnd " << elem);
529 }
530
531 // ----------------------------------------------------------------------------
532
533 void arrayParser::init(const xmlChar** p, xmlParserBase* father)
534 {
535   DEBTRACE("arrayParser::init()");
536   _state = XMLINVALUE;
537   _father = father;
538   _stackState.push(_state);
539   if (p) getAttributes(p);
540 }
541
542
543 void arrayParser::onStart (const XML_Char* elem, const xmlChar** p)
544 {
545   string element(elem);
546   DEBTRACE("array type " << element);
547   stateParser *parser = 0;
548   if      (element == "data")      parser = new dataParser();
549   else
550     { 
551       _what = "expected data, got <" + element + ">";
552       _state = XMLFATALERROR;
553       stopParse(_what);
554     }
555   if (parser)
556     {
557       _stackParser.push(parser);
558       XML_SetUserData(_xmlParser, parser);
559       parser->init(p, this);
560     }
561 }
562
563 void arrayParser::addData(std::string value)
564 {
565   string val = "<array>" + value + "</array>";
566   _data = val;
567 }
568
569
570 void arrayParser::onEnd   (const XML_Char* name)
571 {
572   // cerr << "arrayParser::onEnd " << name << endl;
573   // cerr << _data << endl;
574   _father->addData(_data);
575   stateParser::onEnd(name);
576 }
577
578 // ----------------------------------------------------------------------------
579
580 void dataParser::init(const xmlChar** p, xmlParserBase* father)
581 {
582   DEBTRACE("dataParser::init()");
583   _state = XMLINVALUE;
584   _father = father;
585   _stackState.push(_state);
586   if (p) getAttributes(p);
587 }
588
589
590 void dataParser::onStart (const XML_Char* elem, const xmlChar** p)
591 {
592   string element(elem);
593   DEBTRACE("data type " << element );
594   stateParser *parser = 0;
595   if      (element == "value")      parser = new valueParser();
596   else
597     { 
598       _what = "expected value, got <" + element + ">";
599       _state = XMLFATALERROR;
600       stopParse(_what);
601     }
602   if (parser)
603     {
604       _stackParser.push(parser);
605       XML_SetUserData(_xmlParser, parser);
606       parser->init(p, this);
607     }
608 }
609
610 void dataParser::addData(std::string value)
611 {
612   _dataList.push_back(value);
613 }
614
615 void dataParser::onEnd   (const XML_Char* name)
616 {
617   // cerr << "dataParser::onEnd " << name << endl;
618   string val = "<data>";
619   while (!_dataList.empty())
620     {
621       val += _dataList.front();
622       _dataList.pop_front();
623     }
624   val += "</data>";
625   // cerr << val << endl;
626   _father->addData(val);
627   stateParser::onEnd(name);
628 }
629
630 // ----------------------------------------------------------------------------
631
632 void simpleTypeParser::init(const xmlChar** p, xmlParserBase* father)
633 {
634   DEBTRACE("simpleTypeParser::init()");
635   _state = XMLINVALUE;
636   _father = father;
637   _stackState.push(_state);
638   if (p) getAttributes(p);
639 }
640
641 void simpleTypeParser::onStart (const XML_Char* elem, const xmlChar** p)
642 {
643   string element(elem);
644   _what = "expected nothing, got <" + element + ">";
645   _state = XMLFATALERROR;
646   stopParse(_what);
647 }
648
649 void simpleTypeParser::onEnd   (const XML_Char* name)
650 {
651   string val = string("<") + (char*) name + ">" + _data + "</"  + (char*) name +">";
652   DEBTRACE( val );
653   _father->addData(val);
654   stateParser::onEnd(name);
655 }
656
657 void simpleTypeParser::charData(std::string data)
658 {
659   _data = _data + data;
660 }
661
662
663
664 // ----------------------------------------------------------------------------
665
666 stateLoader::stateLoader(xmlParserBase* parser,
667                          YACS::ENGINE::Proc* p) : xmlReader(parser)
668 {
669   _runtime = getRuntime();
670   _p = p;
671 }
672
673 void stateLoader::parse(std::string xmlState)
674 {
675   DEBTRACE("stateLoader::parse");
676   stateParser *parser = dynamic_cast<stateParser*> (_rootParser);
677   parser->setProc(_p);
678   parser->setRuntime(_runtime);
679
680   xmlReader::parse(xmlState);
681
682   DEBTRACE(parser->_state);
683   switch (parser->_state)
684     {
685     case XMLNOCONTEXT:
686     case XMLDONE:
687       {
688         DEBTRACE("parse OK");
689         break;
690       }
691     case XMLFATALERROR:
692       {
693         string what = "Abort Parse: " + parser->_what;
694         throw Exception(what);
695         break;
696       }
697     default:
698       {
699         string what = "Abort Parse: unknown execution problem";
700         throw Exception(what);
701         break;
702       }
703     }
704 }
705
706 void YACS::ENGINE::loadState(YACS::ENGINE::Proc *p,const std::string& xmlStateFile)
707 {
708   DEBTRACE("YACS::ENGINE::loadState");
709   p->init();
710   p->exUpdateState();
711   stateParser* rootParser = new stateParser();
712   stateLoader myStateLoader(rootParser, p);
713   myStateLoader.parse(xmlStateFile);
714 }