Salome HOME
Copyright update 2022
[modules/yacs.git] / src / runtime / StudyPorts.cxx
1 // Copyright (C) 2006-2022  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 "StudyPorts.hxx"
21 #include "TypeCode.hxx"
22 #include "Node.hxx"
23 #include "Proc.hxx"
24 #include "ComponentInstance.hxx"
25 #include "SalomeComponent.hxx"
26 #include "RuntimeSALOME.hxx"
27
28 #include "SALOMEDS_Attributes.hh"
29 #include "SALOME_KernelServices.hxx"
30
31 #include <iostream>
32 #include <iomanip>
33 #include <cstdlib>
34
35 //#define _DEVDEBUG_
36 #include "YacsTrace.hxx"
37
38
39 namespace YACS
40 {
41 namespace ENGINE
42 {
43
44 /*! \class YACS::ENGINE::OutputStudyPort
45  *  \brief Class for Study output Ports
46  *
47  * \ingroup Ports
48  *
49  * \see StudyInNode
50  */
51
52 OutputStudyPort::OutputStudyPort(const std::string& name,  Node* node, TypeCode* type)
53   : OutputXmlPort(name, node, type),
54     DataPort(name, node, type),
55     Port(node)
56 {
57 }
58
59 OutputStudyPort::OutputStudyPort(const OutputStudyPort& other, Node *newHelder)
60   : OutputXmlPort(other,newHelder),
61     DataPort(other,newHelder),
62     Port(other,newHelder),_storeData(other._storeData)
63 {
64 }
65
66 OutputPort* OutputStudyPort::clone(Node *newHelder) const
67 {
68   return new OutputStudyPort(*this,newHelder);
69 }
70
71 void OutputStudyPort::setData(const std::string& data)
72 {
73   _storeData = data;
74   DEBTRACE( "OutputStudyPort::setData " << _storeData );
75   modified();
76 }
77
78 std::string OutputStudyPort::getData()
79 {
80   DEBTRACE("OutputStudyPort::getData " << _storeData);
81   return _storeData;
82 }
83
84 void OutputStudyPort::putIOR(const std::string& ior)
85 {
86   DEBTRACE("OutputStudyPort::putIOR " << ior);
87   if(ior.substr(0,7) == "<value>")
88     {
89       put(ior.c_str());
90     }
91   else
92     {
93       int tk=edGetType()->kind();
94       std::string value;
95       switch(tk)
96         {
97         case Double:
98           value="<value><double>"+ior+"</double></value>";
99           break;
100         case Int:
101           value="<value><int>"+ior+"</int></value>";
102           break;
103         case String:
104           value="<value><string>"+ior+"</string></value>";
105           break;
106         case Bool:
107           value="<value><boolean>"+ior+"</boolean></value>";
108           break;
109         case Objref:
110           value="<value><objref>"+ior+"</objref></value>";
111           break;
112         case Sequence:
113         case Array:
114         case Struct:
115         default:
116           break;
117         }
118       put(value.c_str());
119     }
120 }
121
122 std::string OutputStudyPort::dump()
123 {
124   DEBTRACE( "OutputStudyPort::dump " << _storeData );
125   DEBTRACE( "OutputStudyPort::dump " << _data );
126   //return "<value><string>"+_storeData+"</string></value>";
127   return _data;
128 }
129
130 std::string OutputStudyPort::getPyObj()
131 {
132   return getData();
133 }
134 std::string OutputStudyPort::getAsString()
135 {
136   return getData();
137 }
138
139 void OutputStudyPort::getDataFromStudy()
140 {
141       std::string data = getData();
142       DEBTRACE("data: " << data );
143       //try an id
144       SALOMEDS::SObject_var aSO = KERNEL::getStudyServant()->FindObjectID(data.c_str());
145       if(CORBA::is_nil(aSO))
146         {
147           //try a path
148           aSO=KERNEL::getStudyServant()->FindObjectByPath(data.c_str());
149           if(CORBA::is_nil(aSO))
150             {
151               std::stringstream msg;
152               msg << "Execution problem: no id or path: " << data << " in study";
153               throw Exception(msg.str());
154             }
155         }
156
157       CORBA::String_var path=KERNEL::getStudyServant()->GetObjectPath(aSO);
158       DEBTRACE(path);
159       CORBA::String_var id=aSO->GetID();
160       DEBTRACE(id);
161       //CORBA::Object_var sobj=aSO->GetObject();
162
163       SALOMEDS::GenericAttribute_var aGAttr;
164       CORBA::String_var value;
165
166       if(edGetType()->kind()==Objref)
167         {
168           if ( aSO->FindAttribute( aGAttr, "AttributeIOR" ) )
169             {
170               SALOMEDS::AttributeIOR_var anAttr = SALOMEDS::AttributeIOR::_narrow( aGAttr );
171               value=anAttr->Value();
172               putIOR((const char*)value);
173             }
174           else
175             {
176               //Problem !!!
177               std::string error="Execution problem: no AttributeIOR in study object: ";
178               error=error+data;
179               throw Exception(error);
180             }
181         }
182       else if(edGetType()->kind()==Double )
183         {
184           if ( aSO->FindAttribute( aGAttr, "AttributeReal" ) )
185             {
186               SALOMEDS::AttributeReal_var anAttr = SALOMEDS::AttributeReal::_narrow( aGAttr );
187               CORBA::Double d=anAttr->Value();
188               std::stringstream msg;
189               msg << "<value><double>" << std::setprecision(16) << d << "</double></value>";
190               put(msg.str().c_str());
191             }
192           else
193             {
194               std::string error="Execution problem: no AttributeReal in study object: ";
195               throw Exception(error+data);
196             }
197         }
198       else if(edGetType()->kind()== Int)
199         {
200           if ( aSO->FindAttribute( aGAttr, "AttributeInteger" ) )
201             {
202               SALOMEDS::AttributeInteger_var anAttr = SALOMEDS::AttributeInteger::_narrow( aGAttr );
203               CORBA::Long l=anAttr->Value();
204               std::stringstream msg;
205               msg << "<value><int>" << l << "</int></value>";
206               put(msg.str().c_str());
207             }
208           else
209             {
210               std::string error="Execution problem: no AttributeInteger in study object: ";
211               throw Exception(error+data);
212             }
213         }
214       else
215         {
216           if ( aSO->FindAttribute( aGAttr, "AttributeComment" ) )
217             {
218               SALOMEDS::AttributeComment_var anAttr = SALOMEDS::AttributeComment::_narrow( aGAttr );
219               value=anAttr->Value();
220               DEBTRACE(value);
221               putIOR((const char*)value);
222             }
223           else
224             {
225               std::string error="Execution problem: no AttributeComment in study object: ";
226               throw Exception(error+data);
227             }
228         }
229 }
230
231
232
233
234 SALOMEDS::SObject_ptr findOrCreateSoWithName(SALOMEDS::StudyBuilder_ptr builder,
235                                              SALOMEDS::SObject_ptr sobj, const std::string& name)
236 {
237   SALOMEDS::ChildIterator_var anIterator= KERNEL::getStudyServant()->NewChildIterator(sobj);
238   SALOMEDS::GenericAttribute_var anAttr;
239   SALOMEDS::AttributeName_var namAttr ;
240   SALOMEDS::SObject_var result=SALOMEDS::SObject::_nil();
241
242   for (; anIterator->More(); anIterator->Next())
243     {
244       SALOMEDS::SObject_var anObj=anIterator->Value();
245       if(anObj->FindAttribute(anAttr, "AttributeName"))
246         {
247           namAttr = SALOMEDS::AttributeName::_narrow( anAttr );
248           CORBA::String_var value=namAttr->Value();
249           if(name == (const char*)value)
250             {
251               result=anObj;
252               break;
253             }
254         }
255     }
256   if(CORBA::is_nil(result))
257     {
258       //create it
259       result = builder->NewObject( sobj );
260       anAttr=builder->FindOrCreateAttribute(result,"AttributeName");
261       namAttr = SALOMEDS::AttributeName::_narrow( anAttr );
262       namAttr->SetValue(name.c_str());
263     }
264   return result._retn();
265 }
266
267 /*! \class YACS::ENGINE::InputStudyPort
268  *  \brief Class for Study input Ports
269  *
270  * \ingroup Ports
271  *
272  * \see StudyOutNode
273  */
274
275 InputStudyPort::InputStudyPort(const std::string& name,  Node* node, TypeCode* type)
276   : InputXmlPort(name, node, type),
277     DataPort(name, node, type),
278     Port(node)
279 {
280 }
281
282 InputStudyPort::InputStudyPort(const InputStudyPort& other, Node *newHelder)
283   : InputXmlPort(other,newHelder),
284     DataPort(other,newHelder),
285     Port(other,newHelder),_storeData(other._storeData)
286 {
287 }
288
289 InputPort* InputStudyPort::clone(Node *newHelder) const
290 {
291   return new InputStudyPort(*this,newHelder);
292 }
293
294 void InputStudyPort::setData(const std::string& data)
295 {
296   _storeData = data;
297   DEBTRACE( "InputStudyPort::setData " << _storeData );
298   modified();
299 }
300
301 std::string InputStudyPort::getData()
302 {
303   DEBTRACE("InputStudyPort::getData " << _storeData);
304   return _storeData;
305 }
306
307 std::string InputStudyPort::getIOR()
308 {
309   switch(edGetType()->kind())
310    {
311    case Objref:
312      return splitXML(_data);
313    default:
314      return _data;
315    }
316 }
317
318 std::string InputStudyPort::splitXML(const std::string& s)
319 {
320   // <value><tag>content</tag></value>
321   std::string::size_type begin = s.find_first_of("<"); // <value>
322   begin = s.find_first_of(">",begin); // end of <value>
323   begin = s.find_first_of("<",begin); // beginning of <tag>
324   begin = s.find_first_of(">",begin); // end of <tag>
325   begin = s.find_first_not_of("> ",begin); // beginning of content
326   std::string::size_type last = s.find_first_of("<",begin); // beginning of </tag>
327   return s.substr(begin,last-begin);
328 }
329
330 std::string InputStudyPort::dump()
331 {
332   DEBTRACE( "InputStudyPort::dump " << _storeData );
333   DEBTRACE( "InputStudyPort::dump " << _data );
334   //return "<value><string>"+_storeData+"</string></value>";
335   return _data;
336 }
337 std::string InputStudyPort::getPyObj()
338 {
339   return getData();
340 }
341 std::string InputStudyPort::getAsString()
342 {
343   return getData();
344 }
345
346 void InputStudyPort::putDataInStudy(SALOMEDS::StudyBuilder_var aBuilder)
347 {
348   SALOMEDS::GenericAttribute_var aGAttr;
349   SALOMEDS::SObject_var aSO ;
350   SALOMEDS::AttributeName_var anAttr ;
351   SALOMEDS::AttributeIOR_var iorAttr ;
352   SALOMEDS::SComponent_var       aFather;
353
354   std::string data = getData();
355   DEBTRACE("data: " << data );
356   //try to find an existing id (i:j:k...)
357   aSO = KERNEL::getStudyServant()->FindObjectID(data.c_str());
358   if(CORBA::is_nil(aSO))
359     {
360       // the id does not exist. Try to create it by id
361       aSO=KERNEL::getStudyServant()->CreateObjectID(data.c_str());
362       if(!CORBA::is_nil(aSO))
363         {
364           aGAttr=aBuilder->FindOrCreateAttribute(aSO,"AttributeName");
365           anAttr = SALOMEDS::AttributeName::_narrow( aGAttr );
366           anAttr->SetValue(getName().c_str());
367         }
368     }
369
370   if(CORBA::is_nil(aSO))
371     {
372       //try to publish the object with a given path
373       std::string name; // the component instance name
374       std::string objname; // the object name (eventually with "/")
375       std::string::size_type begin = data.find_first_not_of("/");
376       std::string::size_type pos=data.find_first_of("/", begin);
377       if (pos != std::string::npos)
378         {
379           name=data.substr(begin,pos-begin);
380           objname=data.substr(pos+1);
381         }
382       else
383         {
384           name=data.substr(begin);
385           objname="";
386         }
387       std::string pname="/"+name;
388       DEBTRACE(pname);
389       DEBTRACE(objname);
390
391       Proc* proc=getNode()->getProc();
392       if(proc->componentInstanceMap.count(name)!=0)
393         {
394           // There is a component instance with this name. Is it a Salome component or not ?
395           ComponentInstance* compo=proc->componentInstanceMap[name];
396           if(SalomeComponent* scompo=dynamic_cast<SalomeComponent*>(compo))
397             {
398                   //It's a Salome component, make it the right way : component name, component instance reference, ...
399               CORBA::Object_var compovar= scompo->getCompoPtr();
400               SALOMEDS::Driver_var aDriver = SALOMEDS::Driver::_narrow(compovar);
401               if ( !CORBA::is_nil( aDriver ) )
402                 {
403                   //It's a Salome component that implements the Driver interface. Use it to publish in study
404                   CORBA::ORB_ptr orb;
405                   CORBA::Object_var anObject;
406                   try
407                     {
408                           orb = getSALOMERuntime()->getOrb();
409                           anObject=orb->string_to_object(getIOR().c_str());
410                     }
411                   catch ( ... ) 
412                     {
413                       std::cerr << "Execution problem: can not get the object to publish" << std::endl;
414                       return;
415                     }
416                   if ( aDriver->CanPublishInStudy( anObject ) ) 
417                     {
418                           //It's fine use the driver to publish
419                           SALOMEDS::SObject_var aTmpSO; // initialized to nil
420                           try 
421                             {
422                               aTmpSO = aDriver->PublishInStudy(aTmpSO, anObject,objname.c_str() );
423                               return;
424                             }
425                           catch ( ... ) 
426                             {
427                               std::cerr << "Execution problem: error in PublishInStudy" << std::endl;
428                               return;
429                             }
430                     }
431                 }
432             }
433         }
434
435       // Does component entry exist ?
436       aSO=KERNEL::getStudyServant()->FindObjectByPath(pname.c_str());
437       if(CORBA::is_nil(aSO))
438         {
439           // We have not been able to publish the object with Salome Driver, make it the light way
440           aFather=aBuilder->NewComponent(name.c_str());
441           if(CORBA::is_nil(aFather))
442             {
443               std::cerr << "Execution problem: can not create component: " + name << std::endl;
444               return;
445             }
446           aGAttr=aBuilder->FindOrCreateAttribute(aFather,"AttributeName");
447           anAttr = SALOMEDS::AttributeName::_narrow( aGAttr );
448           anAttr->SetValue(name.c_str());
449           aSO=KERNEL::getStudyServant()->FindObjectByPath(pname.c_str());
450         }
451
452       begin=data.find_first_not_of("/",pos);
453       while (begin != std::string::npos)
454         {
455           pos = data.find_first_of("/", begin);
456           if (pos != std::string::npos)
457             name=data.substr(begin,pos-begin);
458           else
459             name=data.substr(begin);
460           aSO=findOrCreateSoWithName(aBuilder,aSO,name);
461           begin=data.find_first_not_of("/",pos);
462         }
463     }
464
465   if(CORBA::is_nil(aSO))
466     {
467       std::cerr << "Execution problem: can not create id or path: " + data + " in study" << std::endl;
468       return;
469     }
470
471   std::string value;
472   SALOMEDS::AttributeComment_var commentAttr ;
473   SALOMEDS::AttributeReal_var realAttr ;
474   SALOMEDS::AttributeInteger_var intAttr ;
475   SALOMEDS::AttributeString_var stringAttr ;
476   double d;
477   long v;
478   switch(edGetType()->kind())
479     {
480       case Objref:
481              value=getIOR();
482              DEBTRACE(value);
483              aGAttr=aBuilder->FindOrCreateAttribute(aSO,"AttributeIOR");
484              iorAttr = SALOMEDS::AttributeIOR::_narrow( aGAttr );
485              iorAttr->SetValue(value.c_str());
486              break;
487       case Double:
488              value=splitXML(dump());
489              DEBTRACE(value);
490              aGAttr=aBuilder->FindOrCreateAttribute(aSO,"AttributeReal");
491              realAttr = SALOMEDS::AttributeReal::_narrow( aGAttr );
492              d=atof(value.c_str());
493              realAttr->SetValue(d);
494              break;
495       case Int:
496              value=splitXML(dump());
497              DEBTRACE(value);
498              aGAttr=aBuilder->FindOrCreateAttribute(aSO,"AttributeInteger");
499              intAttr = SALOMEDS::AttributeInteger::_narrow( aGAttr );
500              v=atol(value.c_str());
501              intAttr->SetValue(v);
502              break;
503       case String:
504       case Bool:
505              value=splitXML(dump());
506              DEBTRACE(value);
507              aGAttr=aBuilder->FindOrCreateAttribute(aSO,"AttributeComment");
508              commentAttr = SALOMEDS::AttributeComment::_narrow( aGAttr );
509              commentAttr->SetValue(value.c_str());
510              break;
511       default:
512              value=dump();
513              DEBTRACE(value);
514              aGAttr=aBuilder->FindOrCreateAttribute(aSO,"AttributeComment");
515              commentAttr = SALOMEDS::AttributeComment::_narrow( aGAttr );
516              commentAttr->SetValue(value.c_str());
517     }
518 }
519
520 } //end namespace ENGINE
521 } //end namespace YACS