Salome HOME
Implementation of 0022326: [CEA 930] YACS: progression of a loop "ForEach"
[modules/yacs.git] / src / engine / Proc.cxx
1 // Copyright (C) 2006-2013  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
20 #include "Proc.hxx"
21 #include "ElementaryNode.hxx"
22 #include "Runtime.hxx"
23 #include "Container.hxx"
24 #include "ComponentInstance.hxx"
25 #include "InputPort.hxx"
26 #include "OutputPort.hxx"
27 #include "TypeCode.hxx"
28 #include "Logger.hxx"
29 #include "Visitor.hxx"
30 #include "VisitorSaveSchema.hxx"
31 #include "VisitorSaveState.hxx"
32 #include <sstream>
33 #include <set>
34
35 //#define _DEVDEBUG_
36 #include "YacsTrace.hxx"
37
38 using namespace std;
39 using namespace YACS::ENGINE;
40
41 /*! \class YACS::ENGINE::Proc
42  *  \brief Base class for all schema objects.
43  *
44  * This is an abstract class that must be specialized in runtime.
45  * \ingroup Nodes
46  */
47
48 Proc::Proc(const std::string& name):Bloc(name),_edition(false),_compoinstctr(0)
49 {
50   Runtime *theRuntime=getRuntime();
51   DEBTRACE("theRuntime->_tc_double->ref: " << theRuntime->_tc_double->getRefCnt());
52   DEBTRACE("theRuntime->_tc_int->ref: " << theRuntime->_tc_int->getRefCnt());
53   DEBTRACE("theRuntime->_tc_string->ref: " << theRuntime->_tc_string->getRefCnt());
54   DEBTRACE("theRuntime->_tc_bool->ref: " << theRuntime->_tc_bool->getRefCnt());
55   DEBTRACE("theRuntime->_tc_file->ref: " << theRuntime->_tc_file->getRefCnt());
56   theRuntime->_tc_double->incrRef();
57   theRuntime->_tc_string->incrRef();
58   theRuntime->_tc_int->incrRef();
59   theRuntime->_tc_bool->incrRef();
60   theRuntime->_tc_file->incrRef();
61   typeMap["double"]=theRuntime->_tc_double;
62   typeMap["string"]=theRuntime->_tc_string;
63   typeMap["int"]=theRuntime->_tc_int;
64   typeMap["bool"]=theRuntime->_tc_bool;
65   typeMap["file"]=theRuntime->_tc_file;
66 }
67
68 Proc::~Proc()
69 {
70   DEBTRACE("Proc::~Proc");
71   //for the moment all nodes are owned, so no need to manage their destruction
72   //nodeMap, inlineMap, serviceMap will be cleared automatically
73   //but we need to destroy TypeCodes
74   std::map<std::string, TypeCode *>::iterator pt;
75   for(pt=typeMap.begin();pt!=typeMap.end();pt++)
76     ((*pt).second)->decrRef();
77
78   //get rid of containers in container map
79   std::map<std::string, Container*>::const_iterator it;
80   for(it=containerMap.begin();it!=containerMap.end();it++)
81     ((*it).second)->decrRef();
82
83   //get rid of loggers in logger map
84   std::map<std::string, Logger*>::const_iterator lt;
85   for(lt=_loggers.begin();lt!=_loggers.end();lt++)
86     delete (*lt).second;
87 }
88
89 void Proc::writeDot(std::ostream &os) const
90 {
91   os << "digraph " << getQualifiedName() << " {\n" ;
92   os << "node [ style=\"filled\" ];\n" ;
93   os << "compound=true;";
94   os << "states [label=< <TABLE> <TR> <TD BGCOLOR=\"pink\" > Ready</TD> <TD BGCOLOR=\"magenta\" > Toload</TD> </TR> <TR> <TD BGCOLOR=\"magenta\" > Loaded</TD> <TD BGCOLOR=\"purple\" > Toactivate</TD> </TR> <TR> <TD BGCOLOR=\"blue\" > Activated</TD> <TD BGCOLOR=\"green\" > Done</TD> </TR> <TR> <TD BGCOLOR=\"red\" > Error</TD> <TD BGCOLOR=\"orange\" > Failed</TD> </TR> <TR> <TD BGCOLOR=\"grey\" > Disabled</TD> <TD BGCOLOR=\"white\" > Pause</TD> </TR> </TABLE>> \n shape = plaintext \n style = invis \n ];\n";
95
96   Bloc::writeDot(os);
97   os << "}\n" ;
98 }
99
100 std::ostream& operator<< (std::ostream& os, const Proc& p)
101 {
102   os << "Proc" ;
103   return os;
104 }
105
106 TypeCode *Proc::createType(const std::string& name, const std::string& kind)
107 {
108   TypeCode* t;
109   if(kind=="double")
110     t=getRuntime()->_tc_double;
111   else if(kind=="string")
112     t=getRuntime()->_tc_string;
113   else if(kind=="int")
114     t=getRuntime()->_tc_int;
115   else if(kind=="bool")
116     t=getRuntime()->_tc_bool;
117   else
118     throw Exception("Unknown kind");
119
120   if(typeMap.count(name)!=0)
121     typeMap[name]->decrRef();
122   t->incrRef();
123   typeMap[name]=t;
124   t->incrRef();
125   return t;
126 }
127
128 //! Create an object reference TypeCode 
129 /*!
130  * \param id: the TypeCode repository id
131  * \param name: the TypeCode name
132  * \param ltc: a liste of object reference TypeCode to use as base types for this type
133  * \return the created TypeCode
134  */
135 TypeCode *Proc::createInterfaceTc(const std::string& id, const std::string& name,
136                                   std::list<TypeCodeObjref *> ltc)
137 {
138   TypeCode* t = TypeCode::interfaceTc(id.c_str(),name.c_str(),ltc);
139   if(typeMap.count(name)!=0)
140     typeMap[name]->decrRef();
141   typeMap[name]=t;
142   t->incrRef();
143   return t;
144 }
145
146 //! Create a sequence TypeCode 
147 /*!
148  * \param id: the TypeCode repository id ("" for normal use)
149  * \param name: the TypeCode name
150  * \param content: the element TypeCode 
151  * \return the created TypeCode
152  */
153 TypeCode * Proc::createSequenceTc (const std::string& id, const std::string& name,
154                                    TypeCode *content)
155 {
156   TypeCode* t = TypeCode::sequenceTc(id.c_str(),name.c_str(),content);
157   if(typeMap.count(name)!=0)
158     typeMap[name]->decrRef();
159   typeMap[name]=t;
160   t->incrRef();
161   return t;
162 }
163
164 TypeCode * Proc::createStructTc (const std::string& id, const std::string& name)
165 {
166   TypeCode* t = TypeCode::structTc(id.c_str(),name.c_str());
167   if(typeMap.count(name)!=0)
168     typeMap[name]->decrRef();
169   typeMap[name]=t;
170   t->incrRef();
171   return t;
172 }
173
174 TypeCode * Proc::getTypeCode (const std::string& name)
175 {
176   TypeCode* aTC=0;
177   if(typeMap.count(name)==0)
178     aTC=getRuntime()->getTypeCode(name);
179   else
180     aTC=typeMap[name];
181
182   if(!aTC)
183     {
184       std::stringstream msg;
185       msg << "Type " << name << " does not exist" ;
186       msg << " (" <<__FILE__ << ":" << __LINE__ << ")";
187       throw Exception(msg.str());
188     }
189
190   return aTC;
191 }
192
193 void Proc::setTypeCode (const std::string& name,TypeCode *t)
194 {
195   if(typeMap.count(name)!=0)
196     typeMap[name]->decrRef();
197   typeMap[name]=t;
198   t->incrRef();
199 }
200
201
202 void Proc::accept(Visitor *visitor)
203 {
204   visitor->visitProc(this);
205 }
206
207 void Proc::setName(const std::string& name)
208 {
209   _name = name;
210 }
211
212 YACS::StatesForNode Proc::getNodeState(int numId)
213 {
214   if(YACS::ENGINE::Node::idMap.count(numId) == 0)
215     {
216       cerr << "Unknown node id " << numId << endl;
217       return YACS::UNDEFINED;
218     }
219   YACS::ENGINE::Node* node = YACS::ENGINE::Node::idMap[numId];
220   YACS::StatesForNode state = node->getEffectiveState();
221   return state;
222 }
223
224 std::string Proc::getNodeProgress(int numId)
225 {
226   std::string progress = "0";
227   if(YACS::ENGINE::Node::idMap.count(numId) == 0)
228     {
229       cerr << "Unknown node id " << numId << endl;
230     }
231   else if (YACS::ENGINE::ComposedNode* node = dynamic_cast<YACS::ENGINE::ComposedNode*>(YACS::ENGINE::Node::idMap[numId]))
232     progress = node->getProgress();
233   return progress;
234 }
235
236 std::string Proc::getXMLState(int numId)
237 {
238   if(YACS::ENGINE::Node::idMap.count(numId) == 0)
239     {
240       cerr << "Unknown node id " << numId << endl;
241       return "<state>unknown</state>";
242     }
243   YACS::ENGINE::Node* node = YACS::ENGINE::Node::idMap[numId];
244   stringstream msg;
245   msg << "<state>" << node->getEffectiveState() << "</state>";
246   msg << "<name>" << node->getQualifiedName() << "</name>";
247   msg << "<id>" << numId << "</id>";
248   return msg.str();
249 }
250
251 std::string Proc::getInPortValue(int nodeNumId, std::string portName)
252 {
253   DEBTRACE("Proc::getInPortValue " << nodeNumId << " " << portName);
254   stringstream msg;
255   if(YACS::ENGINE::Node::idMap.count(nodeNumId) == 0)
256     {
257       msg << "<value><error>unknown node id: " << nodeNumId << "</error></value>";
258       return msg.str();
259     }
260   try
261     {
262       YACS::ENGINE::Node* node = YACS::ENGINE::Node::idMap[nodeNumId];
263       InputPort * inputPort = node->getInputPort(portName);
264       return inputPort->getAsString();
265     }
266   catch(YACS::Exception& ex)
267     {
268       DEBTRACE("Proc::getInPortValue " << ex.what());
269       msg << "<value><error>" << ex.what() << "</error></value>";
270       return msg.str();
271     }
272 }
273
274 std::string Proc::setInPortValue(std::string nodeName, std::string portName, std::string value)
275 {
276   DEBTRACE("Proc::setInPortValue " << nodeName << " " << portName << " " << value);
277
278   try
279     {
280       YACS::ENGINE::Node* node = YACS::ENGINE::Proc::nodeMap[nodeName];
281       YACS::ENGINE::InputPort* inputPort = node->getInputPort(portName);
282
283       switch (inputPort->edGetType()->kind())
284         {
285           case Double:
286             {
287               double val = atof(value.c_str());
288               inputPort->edInit(val);
289             }
290           case Int:
291             {
292               int val = atoi(value.c_str());
293               inputPort->edInit(val);
294             }
295           case String:
296             inputPort->edInit(value.c_str());
297           case Bool:
298             {
299               bool val = (! value.compare("False") ) && (! value.compare("0") );
300               inputPort->edInit(val);
301             }
302           default:
303             DEBTRACE("Proc::setInPortValue: filtered type: " << inputPort->edGetType()->kind());
304         }
305       return value;
306     }
307   catch(YACS::Exception& ex)
308     {
309       DEBTRACE("Proc::setInPortValue " << ex.what());
310       stringstream msg;
311       msg << "<value><error>" << ex.what() << "</error></value>";
312       return msg.str();
313     }
314 }
315
316 std::string Proc::getOutPortValue(int nodeNumId, std::string portName)
317 {
318   DEBTRACE("Proc::getOutPortValue " << nodeNumId << " " << portName);
319   stringstream msg;
320   if(YACS::ENGINE::Node::idMap.count(nodeNumId) == 0)
321     {
322       msg << "<value><error>unknown node id: " << nodeNumId << "</error></value>";
323       return msg.str();
324     }
325   try
326     {
327       YACS::ENGINE::Node* node = YACS::ENGINE::Node::idMap[nodeNumId];
328       OutputPort * outputPort = node->getOutputPort(portName);
329       return outputPort->getAsString();
330     }
331   catch(YACS::Exception& ex)
332     {
333       DEBTRACE("Proc::getOutPortValue " << ex.what());
334       msg << "<value><error>" << ex.what() << "</error></value>";
335       return msg.str();
336     }
337 }
338
339 std::string Proc::getNodeErrorDetails(int nodeNumId)
340 {
341   DEBTRACE("Proc::getNodeErrorDetails " << nodeNumId);
342   stringstream msg;
343   if(YACS::ENGINE::Node::idMap.count(nodeNumId) == 0)
344     {
345       msg << "Unknown node id " << nodeNumId;
346       return msg.str();
347     }
348   YACS::ENGINE::Node* node = YACS::ENGINE::Node::idMap[nodeNumId];
349   return node->getErrorDetails();
350 }
351
352 std::string Proc::getNodeErrorReport(int nodeNumId)
353 {
354   DEBTRACE("Proc::getNodeErrorReport " << nodeNumId);
355   stringstream msg;
356   if(YACS::ENGINE::Node::idMap.count(nodeNumId) == 0)
357     {
358       msg << "Unknown node id " << nodeNumId;
359       return msg.str();
360     }
361   YACS::ENGINE::Node* node = YACS::ENGINE::Node::idMap[nodeNumId];
362   return node->getErrorReport();
363 }
364
365 std::string Proc::getNodeContainerLog(int nodeNumId)
366 {
367   DEBTRACE("Proc::getNodeContainerLog " << nodeNumId);
368   stringstream msg;
369   if(YACS::ENGINE::Node::idMap.count(nodeNumId) == 0)
370     {
371       msg << "Unknown node id " << nodeNumId;
372       return msg.str();
373     }
374   YACS::ENGINE::Node* node = YACS::ENGINE::Node::idMap[nodeNumId];
375   return node->getContainerLog();
376 }
377
378 std::list<int> Proc::getNumIds()
379 {
380   list<YACS::ENGINE::Node *> nodes = getAllRecursiveConstituents();
381   int len = nodes.size();
382   list<int> numids;
383   for( list<YACS::ENGINE::Node *>::const_iterator iter = nodes.begin();
384        iter != nodes.end(); iter++)
385     {
386       numids.push_back((*iter)->getNumId());
387     }
388   numids.push_back(this->getNumId());
389   return numids;
390 }
391
392 std::list<std::string> Proc::getIds()
393 {
394   list<YACS::ENGINE::Node *> nodes = getAllRecursiveConstituents();
395   int len = nodes.size();
396   list<string> ids;
397   for( list<YACS::ENGINE::Node *>::const_iterator iter = nodes.begin();
398        iter != nodes.end(); iter++)
399     {
400       ids.push_back(getChildName(*iter));
401     }
402   ids.push_back("_root_");
403   return ids;
404 }
405
406 Logger *Proc::getLogger(const std::string& name)
407 {
408   Logger* logger;
409   LoggerMap::const_iterator it = _loggers.find(name);
410
411   if (it != _loggers.end())
412   {
413     logger = it->second;
414   }
415   else
416   {
417     logger = new Logger(name);
418     _loggers[name]=logger;
419   }
420   return logger;
421 }
422
423 void Proc::setEdition(bool edition)
424 {
425   DEBTRACE("Proc::setEdition: " << edition);
426   _edition=edition;
427   if(_edition)
428     edUpdateState();
429 }
430 //! Sets Proc in modified state and update state if in edition mode
431 /*!
432  *
433  */
434 void Proc::modified()
435 {
436   DEBTRACE("Proc::modified() " << _edition);
437   _modified=1;
438   if(_edition)
439     edUpdateState();
440 }
441
442 //! Save Proc in XML schema file
443 /*!
444  * \param xmlSchemaFile: the file name
445  */
446 void Proc::saveSchema(std::string xmlSchemaFile)
447 {
448   VisitorSaveSchema vss(this);
449   vss.openFileSchema(xmlSchemaFile);
450   accept(&vss);
451   vss.closeFileSchema();
452 }
453
454 //! Save Proc state in XML state file
455 /*!
456  * \param xmlStateFile: the file name
457  */
458 void Proc::saveState(std::string xmlStateFile)
459 {
460   VisitorSaveState vst(this);
461   vst.openFileDump(xmlStateFile);
462   accept(&vst);
463   vst.closeFileDump();
464 }
465
466 //! Create a new Container and store it in containerMap
467 /*!
468  * \param name: the container name and key in containerMap
469  * \param kind: the container kind (depends on runtime)
470  * \return the created Container
471  */
472 Container* Proc::createContainer(const std::string& name,const std::string& kind)
473 {
474   Container* co=  getRuntime()->createContainer(kind);
475   co->setName(name);
476   if(containerMap.count(name)!=0)
477     containerMap[name]->decrRef();
478   containerMap[name]=co;
479   co->incrRef();
480   co->setProc(this);
481   return co;
482 }
483
484 //! Add a ComponentInstance into componentInstanceMap
485 /*!
486  * If the name == "", the component instance is automatically named with a unique (in the Proc) name
487  *
488  * \param inst: the component instance
489  * \param name: the component instance name
490  * \param restCtr: try to reuse instance number previously released, false by default
491  */
492 void Proc::addComponentInstance(ComponentInstance* inst, const std::string& name, bool resetCtr)
493 {
494   if(name != "")
495     {
496       inst->setName(name);
497       inst->setAnonymous(false);
498       if(componentInstanceMap.count(name)!=0)
499         componentInstanceMap[name]->decrRef();
500       componentInstanceMap[name]=inst;
501       inst->incrRef();
502     }
503   else
504     {
505       //automatic naming : componame_<_compoinstctr>
506       std::string instname;
507       std::string componame=inst->getCompoName();
508       if (resetCtr)
509         _compoinstctr = 0;        
510       while(1)
511         {
512           std::ostringstream buffer;
513           buffer << ++_compoinstctr;
514           instname=componame+"_"+buffer.str();
515           if(componentInstanceMap.count(instname)==0)
516             {
517               inst->setName(instname);
518               componentInstanceMap[instname]=inst;
519               inst->incrRef();
520               break;
521             }
522         }
523     }
524 }
525
526 //! Remove a componentInstance from the componentInstanceMap
527 /*!
528  * To be used for a componentInstance with no service nodes referenced.
529  *
530  * \param inst: the component instance
531  */
532 void Proc::removeComponentInstance(ComponentInstance* inst)
533 {
534   if (componentInstanceMap.count(inst->getInstanceName()))
535     {
536       componentInstanceMap.erase(inst->getInstanceName());
537       inst->decrRef();
538     }
539 }
540
541 //! Remove a container from the containerMap
542 /*!
543  * To be used for a container with no componentInstance referenced.
544  *
545  * \param cont: the container
546  */
547 void Proc::removeContainer(Container* cont)
548 {
549   if (containerMap.count(cont->getName()))
550     {
551       containerMap.erase(cont->getName());
552       cont->decrRef();
553     }
554 }
555
556 //! Create a new ComponentInstance and add it into componentInstanceMap
557 /*!
558  * If the name == "", the component instance is automatically named with a unique (in the Proc) name
559  *
560  * \param componame: the component name
561  * \param name: the component instance name
562  * \param kind: the component instance kind (depends on runtime)
563  * \return the created ComponentInstance
564  */
565 ComponentInstance* Proc::createComponentInstance(const std::string& componame, const std::string& name,const std::string& kind)
566 {
567   ComponentInstance* inst=  getRuntime()->createComponentInstance(componame,kind);
568   addComponentInstance(inst,name);
569   return inst;
570 }
571
572 //! Return the proc (this)
573 Proc* Proc::getProc()
574 {
575   return this;
576 }
577
578 //! Return the proc (this)
579 const Proc * Proc::getProc() const
580 {
581   return this;
582 }