1 // Copyright (C) 2006-2024 CEA, EDF
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #define private public
24 #define protected public
25 #include <omniORB4/CORBA.h>
26 #include <omniORB4/internal/typecode.h>
27 #include <omniORB4/internal/corbaOrb.h>
30 #include "yacsconfig.h"
31 #include "YACS_version.h"
32 #include "RuntimeSALOME.hxx"
33 #include "SALOMEDispatcher.hxx"
35 #include "TypeCode.hxx"
36 #include "WhileLoop.hxx"
37 #include "ForLoop.hxx"
38 #include "ForEachLoop.hxx"
39 #include "SalomeOptimizerLoop.hxx"
41 #include "InputPort.hxx"
42 #include "OutputPort.hxx"
43 #include "PresetPorts.hxx"
44 #include "InputDataStreamPort.hxx"
45 #include "OutputDataStreamPort.hxx"
47 #include "SalomeProc.hxx"
48 #include "PyStdout.hxx"
50 #include "SessionCataLoader.hxx"
53 #include "CORBAComponent.hxx"
54 #include "SalomeComponent.hxx"
55 #include "SalomeHPComponent.hxx"
56 #include "SalomePythonComponent.hxx"
57 #include "CppComponent.hxx"
59 #include "SalomeContainer.hxx"
60 #include "CppContainer.hxx"
61 #include "SalomeHPContainer.hxx"
62 #include "PythonCppUtils.hxx"
65 #include "PythonNode.hxx"
66 #include "CORBANode.hxx"
67 #include "XMLNode.hxx"
68 #include "CppNode.hxx"
69 #include "PresetNode.hxx"
70 #include "OutNode.hxx"
71 #include "StudyNodes.hxx"
72 #include "SalomePythonNode.hxx"
73 #include "DistributedPythonNode.hxx"
76 #include "CORBACORBAConv.hxx"
77 #include "CORBAPythonConv.hxx"
78 #include "CORBAXMLConv.hxx"
79 #include "CORBACppConv.hxx"
80 #include "CORBANeutralConv.hxx"
82 #include "TypeConversions.hxx"
84 #include "PythonCORBAConv.hxx"
85 #include "PythonXMLConv.hxx"
86 #include "PythonCppConv.hxx"
87 #include "PythonNeutralConv.hxx"
88 #include "PythonInitConv.hxx"
91 #include "NeutralCORBAConv.hxx"
92 #include "NeutralPythonConv.hxx"
93 #include "NeutralXMLConv.hxx"
94 #include "NeutralCppConv.hxx"
95 #include "NeutralInitConv.hxx"
98 #include "CppCORBAConv.hxx"
99 #include "CppPythonConv.hxx"
100 #include "CppXMLConv.hxx"
101 #include "CppCppConv.hxx"
102 #include "CppNeutralConv.hxx"
105 #include "XMLCORBAConv.hxx"
106 #include "XMLPythonConv.hxx"
107 #include "XMLCppConv.hxx"
108 #include "XMLNeutralConv.hxx"
110 //Calcium specific ports
111 #include "CalStreamPort.hxx"
114 #include "SALOME_NamingService_Wrapper.hxx"
115 #include "SALOME_LifeCycleCORBA.hxx"
116 #include "SALOME_ResourcesManager.hxx"
117 #include "SALOME_ContainerManager.hxx"
118 #include "SALOMEconfig.h"
119 #include "SALOME_Embedded_NamingService.hxx"
120 #include CORBA_CLIENT_HEADER(SALOME_ContainerManager)
124 #include <libxml/parser.h>
125 #include <omniORB4/CORBA.h>
133 #include "YacsTrace.hxx"
136 using namespace YACS::ENGINE;
138 std::unique_ptr<SALOME_NamingService_Container_Abstract> RuntimeSALOME::getNS()
140 std::unique_ptr<SALOME_NamingService_Container_Abstract> ret(new SALOME_NamingService_Wrapper);
144 void RuntimeSALOME::setRuntime(long flags, int argc, char* argv[]) // singleton creation (not thread safe!)
146 if (! Runtime::_singleton)
148 RuntimeSALOME* r=new RuntimeSALOME(flags, argc, argv);
149 Runtime::_singleton = r;
152 DEBTRACE("RuntimeSALOME::setRuntime() done !");
155 RuntimeSALOME* YACS::ENGINE::getSALOMERuntime()
157 YASSERT(RuntimeSALOME::getSingleton());
158 return dynamic_cast< RuntimeSALOME* >(RuntimeSALOME::getSingleton());
162 * Singleton creation, initialize converter map
165 RuntimeSALOME::RuntimeSALOME()
170 void RuntimeSALOME::initBuiltins()
172 //Fill the builtin catalog with nodes specific to the runtime
173 std::map<std::string,TypeCode*>& typeMap=_builtinCatalog->_typeMap;
174 std::map<std::string,Node*>& nodeMap=_builtinCatalog->_nodeMap;
175 std::map<std::string,ComposedNode*>& composednodeMap=_builtinCatalog->_composednodeMap;
176 std::map<std::string,ComponentDefinition*>& componentMap=_builtinCatalog->_componentMap;
177 nodeMap["PyFunction"]=new PyFuncNode("PyFunction");
178 nodeMap["PyScript"]=new PythonNode("PyScript");
179 nodeMap["CORBANode"]=new CORBANode("CORBANode");
180 nodeMap["XmlNode"]=new XmlNode("XmlNode");
181 nodeMap["SalomeNode"]=new SalomeNode("SalomeNode");
182 nodeMap["CppNode"]=new CppNode("CppNode");
183 nodeMap["SalomePythonNode"]=new SalomePythonNode("SalomePythonNode");
184 nodeMap["PresetNode"]=new PresetNode("PresetNode");
185 nodeMap["OutNode"]=new OutNode("OutNode");
186 nodeMap["StudyInNode"]=new StudyInNode("StudyInNode");
187 nodeMap["StudyOutNode"]=new StudyOutNode("StudyOutNode");
188 composednodeMap["OptimizerLoop"]=createOptimizerLoop("OptimizerLoop","","",true);
189 typeMap["dblevec"]= createSequenceTc("dblevec","dblevec",_tc_double);
190 typeMap["intvec"]= createSequenceTc("intvec","intvec",_tc_int);
191 typeMap["stringvec"]= createSequenceTc("stringvec","stringvec",_tc_string);
192 typeMap["boolvec"]= createSequenceTc("boolvec","boolvec",_tc_bool);
193 typeMap["seqdblevec"]= createSequenceTc("seqdblevec","seqdblevec",typeMap["dblevec"]);
194 typeMap["seqintvec"]= createSequenceTc("seqintvec","seqintvec",typeMap["intvec"]);
195 typeMap["seqstringvec"]= createSequenceTc("seqstringvec","seqstringvec",typeMap["stringvec"]);
196 typeMap["seqboolvec"]= createSequenceTc("seqboolvec","seqboolvec",typeMap["boolvec"]);
197 std::list<TypeCodeObjref *> ltc;
198 typeMap["pyobj"]= createInterfaceTc("python:obj:1.0","pyobj",ltc);
199 typeMap["seqpyobj"]= createSequenceTc("seqpyobj","seqpyobj",typeMap["pyobj"]);
200 composednodeMap["Bloc"]=createBloc("Bloc");
201 composednodeMap["Switch"]=createSwitch("Switch");
202 composednodeMap["WhileLoop"]=createWhileLoop("WhileLoop");
203 composednodeMap["ForLoop"]=createForLoop("ForLoop");
204 composednodeMap["ForEachLoop_double"]=createForEachLoop("ForEachLoop_double",Runtime::_tc_double);
205 composednodeMap["ForEachLoop_string"]=createForEachLoop("ForEachLoop_string",Runtime::_tc_string);
206 composednodeMap["ForEachLoop_int"]=createForEachLoop("ForEachLoop_int",Runtime::_tc_int);
207 composednodeMap["ForEachLoop_bool"]=createForEachLoop("ForEachLoop_bool",Runtime::_tc_bool);
208 composednodeMap["ForEachLoop_pyobj"]=createForEachLoop("ForEachLoop_pyobj",typeMap["pyobj"]);;
209 ENGINE::TypeCodeStruct *t = createStructTc("","Engines/dataref");
210 t->addMember("ref",_tc_string);
211 typeMap["dataref"]= t;
214 RuntimeSALOME::RuntimeSALOME(long flags, int argc, char* argv[])
216 // If all flags (apart the IsPyExt flags) are unset, force them to true
217 if ((flags - flags & RuntimeSALOME::IsPyExt) == 0)
218 flags += RuntimeSALOME::UseCorba + RuntimeSALOME::UsePython
219 + RuntimeSALOME::UseCpp + RuntimeSALOME::UseXml;
221 // Salome Nodes implies Corba Nodes
222 if (flags & RuntimeSALOME::UseSalome)
223 flags |= RuntimeSALOME::UseCorba;
225 // Corba Nodes implies Python Nodes
226 if (flags & RuntimeSALOME::UseCorba)
227 flags |= RuntimeSALOME::UsePython;
229 _useCorba = flags & RuntimeSALOME::UseCorba;
230 _usePython = flags & RuntimeSALOME::UsePython;
231 _useCpp = flags & RuntimeSALOME::UseCpp;
232 _useXml = flags & RuntimeSALOME::UseXml;
237 if (_useCpp) _setOfImplementation.insert(CppNode::IMPL_NAME);
238 if (_usePython) _setOfImplementation.insert(PythonNode::IMPL_NAME);
239 if (_useCorba) _setOfImplementation.insert(CORBANode::IMPL_NAME);
240 if (_useXml) _setOfImplementation.insert(XmlNode::IMPL_NAME);
241 init(flags, argc, argv);
244 RuntimeSALOME::~RuntimeSALOME()
246 DEBTRACE("RuntimeSALOME::~RuntimeSALOME");
247 // destroy catalog loader prototypes
248 std::map<std::string, CatalogLoader*>::const_iterator pt;
249 for(pt=_catalogLoaderFactoryMap.begin();pt!=_catalogLoaderFactoryMap.end();pt++)
253 _connectionManager.ShutdownWithExit();
256 void RuntimeSALOME::loadModulCatalog()
259 const char * SCRIPT = "from salome_kernel import list_of_catalogs_regarding_environement\n"
260 "import KernelModuleCatalog\n"
261 "KernelModuleCatalog.myModuleCatalog( list_of_catalogs_regarding_environement() )\n";
262 PyRun_SimpleString(SCRIPT);
265 //! CORBA and Python initialization
267 * \param flags contains several bits
268 * bit0 (ispyext) true when method is called from Python
269 * (Python initialization must not be done!)
270 * bit1 (UsePython) true if python nodes are needed
271 * bit1 (UseCorba) true if CORBA nodes are needed
272 * bit1 (UseXml) true if python nodes are needed
273 * bit1 (UseCpp) true if C++ nodes are needed
274 * bit1 (UseSalome) true if Salome nodes are needed
275 * \param argc number of command line arguments (used to initialize the Python interpreter)
276 * \param argv command line arguments (used to initialize the Python interpreter)
280 void RuntimeSALOME::init(long flags, int argc, char* argv[])
282 bool ispyext = flags & RuntimeSALOME::IsPyExt;
285 PortableServer::POA_var root_poa;
286 PortableServer::POAManager_var pman;
287 CORBA::Object_var obj;
288 int nbargs = 0; char **args = 0;
289 _orb = CORBA::ORB_init (nbargs, args);
290 obj = _orb->resolve_initial_references("RootPOA");
291 root_poa = PortableServer::POA::_narrow(obj);
292 pman = root_poa->the_POAManager();
296 DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
298 obj = _orb->resolve_initial_references("DynAnyFactory");
299 _dynFactory = DynamicAny::DynAnyFactory::_narrow(obj);
304 DEBTRACE("RuntimeSALOME::init, is python extension = " << ispyext);
306 // Initialize Python interpreter in embedded mode
307 if (!Py_IsInitialized())
309 #if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0
312 Py_InitializeEx(0); // do not install signal handlers
314 if (argc > 0 && argv != NULL)
316 wchar_t **changed_argv = new wchar_t*[argc];
317 for (int i = 0; i < argc; i++)
319 changed_argv[i] = Py_DecodeLocale(argv[i], NULL);
321 PySys_SetArgv(argc, changed_argv);
327 char defaultName[] = "SALOME_YACS_RUNTIME";
328 wchar_t **changed_pyArgv = new wchar_t*[pyArgc];
329 pyArgv[0] = defaultName;
330 for (int i = 0; i < pyArgc; i++)
332 changed_pyArgv[i] = Py_DecodeLocale(pyArgv[i], NULL);
334 PySys_SetArgv(pyArgc, changed_pyArgv);
336 #if PY_VERSION_HEX < 0x03070000
337 PyEval_InitThreads(); /* Create (and acquire) the interpreter lock (for threads)*/
339 PyEval_SaveThread(); /* Release the thread state */
340 //here we do not have the Global Interpreter Lock
343 PyObject *mainmod,*pyapi,*res ;
345 PyGILState_STATE gstate;
346 gstate = PyGILState_Ensure(); // acquire the Global Interpreter Lock
348 mainmod = PyImport_AddModule("__main__");
349 globals = PyModule_GetDict(mainmod);
350 /* globals is a borrowed reference */
352 if (PyDict_GetItemString(globals, "__builtins__") == NULL)
354 PyObject *bimod = PyImport_ImportModule("builtins");
355 if (bimod == NULL || PyDict_SetItemString(globals, "__builtins__", bimod) != 0)
356 Py_FatalError("can't add __builtins__ to __main__");
360 _bltins = PyEval_GetBuiltins(); /* borrowed ref */
366 _omnipy = PyImport_ImportModule((char*)"_omnipy");
370 PyErr_SetString(PyExc_ImportError, (char*)"Cannot import _omnipy");
373 pyapi = PyObject_GetAttrString(_omnipy, (char*)"API");
378 _api = (omniORBpyAPI*)PyCapsule_GetPointer(pyapi,"_omnipy.API");
381 res=PyRun_String("\n"
382 "from math import *\n"
384 "sys.path.insert(0,'.')\n"
385 "from omniORB import CORBA\n"
386 "from omniORB import any\n"
387 "orb = CORBA.ORB_init([], CORBA.ORB_ID)\n"
388 "#print(sys.getrefcount(orb))\n"
394 Py_file_input,globals,globals );
402 _pyorb = PyDict_GetItemString(globals,"orb");
403 /* PyDict_GetItemString returns a borrowed reference. There is no need to decref _pyorb */
406 pyany = PyDict_GetItemString(globals,"any");
407 /* PyDict_GetItemString returns a borrowed reference. There is no need to decref pyany */
410 DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
414 PyGILState_Release(gstate); // Release the Global Interpreter Lock
418 // initialize the catalogLoaderFactory map with the session one
419 _catalogLoaderFactoryMap["session"]=new SessionCataLoader;
423 void RuntimeSALOME::fini(bool isFinalizingPython)
427 PyGILState_STATE gstate = PyGILState_Ensure();
429 DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
431 PyObject *mainmod, *globals;
432 mainmod = PyImport_AddModule("__main__");
433 globals = PyModule_GetDict(mainmod);
437 res=PyRun_String("orb.destroy()\n"
439 Py_file_input,globals,globals );
445 std::map<std::string,Node*>& nodeMap=_builtinCatalog->_nodeMap;
446 delete nodeMap["PyFunction"];
447 delete nodeMap["PyScript"];
448 delete nodeMap["SalomePythonNode"];
449 nodeMap.erase("PyFunction");
450 nodeMap.erase("PyScript");
451 nodeMap.erase("SalomePythonNode");
453 if( isFinalizingPython )
456 DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
464 DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
471 PyObject *RuntimeSALOME::launchSubProcess(const std::vector<std::string>& cmds)
473 std::ostringstream oss; oss << "from subprocess import Popen" << std::endl;
474 oss << "p = Popen([";
475 for(auto i = 0 ; i < cmds.size() ; ++i)
477 oss << " " << "\"" << cmds[i] << "\"";
478 if(i < cmds.size()-1)
485 AutoPyRef context = PyDict_New();
486 PyDict_SetItemString( context, "__builtins__", getBuiltins() );
487 std::string errorDetails;
490 PythonNode::ExecuteLocalInternal(oss.str().c_str(),context,errorDetails);
492 catch(const YACS::Exception& e)
494 std::cerr << e.what() << std::endl << errorDetails << std::endl;
497 PyObject *ret = PyDict_GetItemString(context,"p");
503 std::vector< std::pair<std::string,int> > RuntimeSALOME::getCatalogOfComputeNodes() const
505 CORBA::ORB_ptr orb(getOrb());
506 SALOME_NamingService_Wrapper namingService;
509 namingService.init_orb(orb);
511 catch(SALOME_Exception& e)
513 throw Exception("RuntimeSALOME::getCatalogOfComputeNodes : Unable to contact the SALOME Naming Service");
515 CORBA::Object_var obj(namingService.Resolve(SALOME_ResourcesManager::_ResourcesManagerNameInNS));
516 if(CORBA::is_nil(obj))
517 throw Exception("RuntimeSALOME::getCatalogOfComputeNodes : Unable to access to the resource manager !");
518 Engines::ResourcesManager_var resManager(Engines::ResourcesManager::_narrow(obj));
519 if(CORBA::is_nil(resManager))
520 throw Exception("RuntimeSALOME::getCatalogOfComputeNodes : Internal error ! The entry attached to the res manager in NS does not have right type !");
521 std::vector< std::pair<std::string,int> > ret;
522 Engines::ResourceParameters params;
524 params.hostname = "";
528 params.cpu_clock = 0;
530 params.nb_proc_per_node = 0;
532 params.can_launch_batch_jobs = false;
533 params.can_run_containers = true;
534 params.componentList.length(0);
537 Engines::ResourceList_var resourceList;
538 resourceList = resManager->GetFittingResources(params);
539 ret.reserve(resourceList->length());
540 for(int i = 0; i<resourceList->length(); i++)
542 const char* resource_name = resourceList[i];
543 std::string std_resource_name = resource_name;
544 Engines::ResourceDefinition_var resource_definition
545 = resManager->GetResourceDefinition(resource_name);
546 int nb_cores = resource_definition->nb_node *
547 resource_definition->nb_proc_per_node;
548 ret.push_back(std::pair<std::string,int>(resource_name, nb_cores));
551 catch(SALOME::SALOME_Exception& e)
554 message=e.details.text.in();
555 throw Exception(message);
561 std::string RuntimeSALOME::getVersion() const
563 #ifdef YACS_DEVELOPMENT
564 return CORBA::string_dup(YACS_VERSION_STR"dev");
566 return CORBA::string_dup(YACS_VERSION_STR);
570 Proc* RuntimeSALOME::createProc(const std::string& name)
572 return new SalomeProc(name);
575 TypeCode * RuntimeSALOME::createInterfaceTc(const std::string& id, const std::string& name,
576 std::list<TypeCodeObjref *> ltc)
579 if(id == "") myName = "IDL:" + name + ":1.0";
581 return TypeCode::interfaceTc(myName.c_str(),name.c_str(),ltc);
584 TypeCode * RuntimeSALOME::createSequenceTc(const std::string& id,
585 const std::string& name,
588 return TypeCode::sequenceTc(id.c_str(),name.c_str(),content);
591 TypeCodeStruct * RuntimeSALOME::createStructTc(const std::string& id, const std::string& name)
594 if(id == "") myName = "IDL:" + name + ":1.0";
596 return (TypeCodeStruct *)TypeCode::structTc(myName.c_str(),name.c_str());
599 Bloc* RuntimeSALOME::createBloc(const std::string& name)
601 return new Bloc(name);
604 WhileLoop* RuntimeSALOME::createWhileLoop(const std::string& name)
606 return new WhileLoop(name);
609 ForLoop* RuntimeSALOME::createForLoop(const std::string& name)
611 return new ForLoop(name);
614 OptimizerLoop* RuntimeSALOME::createOptimizerLoop(const std::string& name,const std::string& algLib,const std::string& factoryName,
615 bool algInitOnFile, const std::string& kind, Proc * procForTypes)
617 OptimizerLoop * ol = (kind == "base") ? new OptimizerLoop(name,algLib,factoryName,algInitOnFile, true, procForTypes) :
618 new SalomeOptimizerLoop(name,algLib,factoryName,algInitOnFile, true, procForTypes);
619 ol->edGetNbOfBranchesPort()->edInit(1);
623 DataNode* RuntimeSALOME::createInDataNode(const std::string& kind,const std::string& name)
628 node = new PresetNode(name);
631 else if(kind == "study" )
633 return new StudyInNode(name);
635 std::string msg="DataNode kind ("+kind+") unknown";
636 throw Exception(msg);
639 DataNode* RuntimeSALOME::createOutDataNode(const std::string& kind,const std::string& name)
643 return new OutNode(name);
645 else if(kind == "study" )
647 return new StudyOutNode(name);
650 std::string msg="OutDataNode kind ("+kind+") unknown";
651 throw Exception(msg);
654 InlineFuncNode* RuntimeSALOME::createFuncNode(const std::string& kind,const std::string& name)
656 InlineFuncNode* node;
657 if(kind == "" || kind == SalomeNode::KIND || kind == PythonNode::KIND)
659 node = new PyFuncNode(name);
662 if(kind == DistributedPythonNode::KIND)
663 return new DistributedPythonNode(name);
664 std::string msg="FuncNode kind ("+kind+") unknown";
665 throw Exception(msg);
668 InlineNode* RuntimeSALOME::createScriptNode(const std::string& kind,const std::string& name)
671 if(kind == "" || kind == SalomeNode::KIND || kind == PythonNode::KIND)
673 node = new PythonNode(name);
676 std::string msg="ScriptNode kind ("+kind+") unknown";
677 throw Exception(msg);
680 ServiceNode* RuntimeSALOME::createRefNode(const std::string& kind,const std::string& name)
683 if(kind == "" || kind == SalomeNode::KIND || kind == CORBANode::KIND)
685 node = new CORBANode(name);
688 else if(kind == XmlNode::KIND)
690 node = new XmlNode(name);
693 std::string msg="RefNode kind ("+kind+") unknown";
694 throw Exception(msg);
697 ServiceNode* RuntimeSALOME::createCompoNode(const std::string& kind,const std::string& name)
700 if(kind == "" || kind == SalomeNode::KIND )
702 node=new SalomeNode(name);
705 else if (kind == CppNode::KIND)
707 node = new CppNode(name);
710 std::string msg="CompoNode kind ("+kind+") unknown";
711 throw Exception(msg);
714 ServiceInlineNode *RuntimeSALOME::createSInlineNode(const std::string& kind, const std::string& name)
716 if(kind == "" || kind == SalomeNode::KIND )
717 return new SalomePythonNode(name);
718 std::string msg="CompoNode kind ("+kind+") unknown";
719 throw Exception(msg);
722 ComponentInstance* RuntimeSALOME::createComponentInstance(const std::string& name,
723 const std::string& kind)
725 ComponentInstance* compo;
726 if(kind == "" || kind == SalomeComponent::KIND)
727 return new SalomeComponent(name);
728 else if(kind == CORBAComponent::KIND)
729 return new CORBAComponent(name);
730 else if(kind == SalomePythonComponent::KIND)
731 return new SalomePythonComponent(name);
732 else if (kind == CppComponent::KIND)
733 return new CppComponent(name);
734 else if (kind == SalomeHPComponent::KIND)
735 return new SalomeHPComponent(name);
736 std::string msg="Component Instance kind ("+kind+") unknown";
737 throw Exception(msg);
740 Container *RuntimeSALOME::createContainer(const std::string& kind)
742 if(kind == "" || kind == SalomeContainer::KIND)
743 return new SalomeContainer;
744 if(kind==SalomeHPContainer::KIND)
745 return new SalomeHPContainer;
746 else if (kind == CppContainer::KIND)
747 return new CppContainer;
748 std::string msg="Container kind ("+kind+") unknown";
749 throw Exception(msg);
752 InputPort * RuntimeSALOME::createInputPort(const std::string& name,
753 const std::string& impl,
757 if(impl == CppNode::IMPL_NAME)
759 return new InputCppPort(name, node, type);
761 else if(impl == PythonNode::IMPL_NAME)
763 return new InputPyPort(name, node, type);
765 else if(impl == CORBANode::IMPL_NAME)
767 return new InputCorbaPort(name, node, type);
769 else if(impl == XmlNode::IMPL_NAME)
771 return new InputXmlPort(name, node, type);
776 msg << "Cannot create " << impl << " InputPort" ;
777 msg << " (" << __FILE__ << ":" << __LINE__ << ")";
778 throw Exception(msg.str());
782 OutputPort * RuntimeSALOME::createOutputPort(const std::string& name,
783 const std::string& impl,
787 if(impl == CppNode::IMPL_NAME)
789 return new OutputCppPort(name, node, type);
791 else if(impl == PythonNode::IMPL_NAME)
793 return new OutputPyPort(name, node, type);
795 else if(impl == CORBANode::IMPL_NAME)
797 return new OutputCorbaPort(name, node, type);
799 else if(impl == XmlNode::IMPL_NAME)
801 return new OutputXmlPort(name, node, type);
806 msg << "Cannot create " << impl << " OutputPort" ;
807 msg << " (" << __FILE__ << ":" << __LINE__ << ")";
808 throw Exception(msg.str());
812 InputDataStreamPort* RuntimeSALOME::createInputDataStreamPort(const std::string& name,
813 Node *node,TypeCode *type)
815 DEBTRACE("createInputDataStreamPort: " << name << " " << type->shortName());
816 if(type->kind() == Objref && std::string(type->shortName(),7) == "CALCIUM")
818 return new InputCalStreamPort(name,node,type);
822 return new InputDataStreamPort(name,node,type);
826 OutputDataStreamPort* RuntimeSALOME::createOutputDataStreamPort(const std::string& name,
827 Node *node,TypeCode *type)
829 DEBTRACE("createOutputDataStreamPort: " << name << " " << type->shortName());
830 if(type->kind() == Objref && std::string(type->shortName(),7) == "CALCIUM")
832 return new OutputCalStreamPort(name,node,type);
836 return new OutputDataStreamPort(name,node,type);
840 //! Main adapter function : adapt an InputPort to be able to connect it to an OutputPort with a possible different implementation
842 * \param source : InputPort to be adapted
843 * \param impl : new implementation (C++, python, CORBA, XML, Neutral)
844 * \param type : data type provided by the InputPort
845 * \param init : indicates if the adapted InputPort will be used for initialization (value true) or not (value false)
847 * \return : adapted InputPort
849 InputPort* RuntimeSALOME::adapt(InputPort* source,
850 const std::string& impl,
851 TypeCode * type,bool init)
853 string imp_source=source->getNode()->getImplementation();
854 if(imp_source == PythonNode::IMPL_NAME)
856 return adapt((InputPyPort*)source,impl,type,init);
858 else if(imp_source == CppNode::IMPL_NAME)
860 return adapt((InputCppPort*)source,impl,type,init);
862 else if(imp_source == CORBANode::IMPL_NAME)
864 return adapt((InputCorbaPort*)source,impl,type,init);
866 else if(imp_source == XmlNode::IMPL_NAME)
868 return adapt((InputXmlPort*)source,impl,type,init);
870 else if(imp_source == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
872 return adaptNeutral(source,impl,type,init);
877 msg << "Cannot adapt " << imp_source << " InputPort to " << impl;
878 msg << " (" << __FILE__ << ":" << __LINE__ << ")";
879 throw ConversionException(msg.str());
883 //! Adapter function for InPropertyPort
885 * \param source : InPropertyPort to be adapted
886 * \param impl : new implementation (C++, python, CORBA, XML, Neutral)
887 * \param type : data type provided by the InPropertyPort
888 * \param init : indicates if the adapted InPropertyPort will be used for initialization (value true) or not (value false)
890 * \return : adapted InputPort
892 InputPort* RuntimeSALOME::adapt(InPropertyPort* source,
893 const std::string& impl,
894 TypeCode * type,bool init)
896 return adaptNeutral((InputPort *)source,impl,type,init);
899 //! Adapt a Neutral input port to a Corba output port
901 * \param inport : Neutral input port to adapt to Corba type type
902 * \param type : output port type
903 * \return an adaptated input port of type InputCorbaPort
905 InputPort* RuntimeSALOME::adaptNeutralToCorba(InputPort* inport,
908 // BEWARE : using the generic check
909 if(inport->edGetType()->isAdaptable(type))
911 //the output data is convertible to inport type
912 return new CorbaNeutral(inport);
914 //non convertible type
916 msg << "Cannot connect Corba output port with type: " << type->id() ;
917 msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
919 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
921 throw ConversionException(msg.str());
924 //! Adapt a Neutral input port to a Python output port
926 * \param inport : input port to adapt to Python type type
927 * \param type : output port type
928 * \return an adaptated input port of type InputPyPort
930 InputPort* RuntimeSALOME::adaptNeutralToPython(InputPort* inport,
933 // BEWARE : using the generic check
934 if(inport->edGetType()->isAdaptable(type))
937 return new PyNeutral(inport);
939 //last chance : an py output that is seq[objref] can be connected to a neutral input objref (P13268)
940 else if(type->kind()==Sequence && type->contentType()->kind()==Objref && inport->edGetType()->kind()==Objref)
942 return new PyNeutral(inport);
944 //non convertible type
946 msg << "Cannot connect Python output port with type: " << type->id() ;
947 msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
949 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
951 throw ConversionException(msg.str());
954 //! Adapt a Neutral input port to a Xml output port
956 * \param inport : input port to adapt to Xml type type
957 * \param type : output port type
958 * \return an input port of type InputXmlPort
960 InputPort* RuntimeSALOME::adaptNeutralToXml(InputPort* inport,
963 // BEWARE : using the generic check
964 if(inport->edGetType()->isAdaptable(type))
967 return new XmlNeutral(inport);
969 //non convertible type
971 msg << "Cannot connect Xml output port with type: " << type->id() ;
972 msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
974 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
976 throw ConversionException(msg.str());
979 //! Adapt a Neutral input port to a C++ output port
981 * \param inport : input port to adapt to C++ type type
982 * \param type : output port type
983 * \return an input port of type InputCppPort
985 InputPort* RuntimeSALOME::adaptNeutralToCpp(InputPort* inport,
988 DEBTRACE("RuntimeSALOME::adaptNeutralToCpp(InputPort* inport" );
989 if(isAdaptableNeutralCpp(type,inport->edGetType()))
992 return new CppNeutral(inport);
994 //non convertible type
996 msg << "Cannot connect Cpp output port with type: " << type->id() ;
997 msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
999 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1001 throw ConversionException(msg.str());
1004 //! Adapt a Neutral input port to connect it to an output port with a given implementation
1006 * \param source : Neutral input port to adapt to implementation impl and type type
1007 * \param impl : output port implementation (C++, Python, Corba, Xml or Neutral)
1008 * \param type : output port supported type
1009 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1010 * \return the adaptated port
1012 InputPort* RuntimeSALOME::adaptNeutral(InputPort* source,
1013 const std::string& impl,
1014 TypeCode * type,bool init)
1016 if(impl == CppNode::IMPL_NAME)
1018 return adaptNeutralToCpp(source,type);
1020 else if(impl == PythonNode::IMPL_NAME)
1022 return adaptNeutralToPython(source,type);
1024 else if(impl == CORBANode::IMPL_NAME)
1026 return adaptNeutralToCorba(source,type);
1028 else if(impl == XmlNode::IMPL_NAME )
1030 return adaptNeutralToXml(source,type);
1032 else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1035 return new NeutralInit(source);
1037 return new ProxyPort(source);
1040 msg << "Cannot connect InputPort : unknown implementation " << impl;
1041 msg << " (" <<__FILE__ << ":" <<__LINE__ << ")";
1042 throw ConversionException(msg.str());
1045 //! Adapt a XML input port to connect it to a CORBA output port
1047 * \param inport : input port to adapt to CORBA type type
1048 * \param type : type supported by output port
1049 * \return an adaptator port of type InputCorbaPort
1052 InputPort* RuntimeSALOME::adaptXmlToCorba(InputXmlPort* inport,
1055 if(isAdaptableXmlCorba(type,inport->edGetType()))
1057 //output type is convertible to input type
1058 return new CorbaXml(inport);
1060 //output type is not convertible
1062 msg << "Cannot connect Corba output port with type: " << type->id() ;
1063 msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1065 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1067 throw ConversionException(msg.str());
1070 //! Adapt a XML input port to a Python output port
1072 * \param inport : input port to adapt to Python type type
1073 * \param type : output port type
1074 * \return an adaptated input port of type InputPyPort
1076 InputPort* RuntimeSALOME::adaptXmlToPython(InputXmlPort* inport,
1079 if(inport->edGetType()->isAdaptable(type))
1081 //the output data is convertible to inport type
1082 return new PyXml(inport);
1084 //non convertible type
1086 msg << "Cannot connect Python output port with type: " << type->id() ;
1087 msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1089 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1091 throw ConversionException(msg.str());
1094 //! Adapt a XML input port to a C++ output port
1096 * \param inport : input port to adapt to C++ type type
1097 * \param type : output port type
1098 * \return an adaptated input port of type InputPyPort
1100 InputPort* RuntimeSALOME::adaptXmlToCpp(InputXmlPort* inport,
1103 DEBTRACE("RuntimeSALOME::adaptXmlToCpp(InputPort* inport" );
1104 DEBTRACE(type->kind() << " " << inport->edGetType()->kind() );
1105 if(type->isAdaptable(inport->edGetType()))
1107 //the output data is convertible to inport type
1108 return new CppXml(inport);
1110 //non convertible type
1112 msg << "Cannot connect Cpp output port with type: " << type->id() ;
1113 msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1115 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1117 throw ConversionException(msg.str());
1120 //! Adapt a XML input port to a Neutral output port
1122 * \param inport : input port to adapt to Neutral type type
1123 * \param type : output port type
1124 * \return an adaptated input port of type Neutralxxxx
1126 InputPort* RuntimeSALOME::adaptXmlToNeutral(InputXmlPort* inport,
1129 if(inport->edGetType()->isAdaptable(type))
1131 //the output data is convertible to inport type
1132 return new NeutralXml(inport);
1134 //non convertible type
1136 msg << "Cannot connect Xml InputPort to OutputNeutralPort : " ;
1137 msg << "(" <<__FILE__ << ":" <<__LINE__<< ")";
1138 throw ConversionException(msg.str());
1141 //! Adapt a XML input port to a Xml output port
1143 * \param inport : input port to adapt to Xml type type
1144 * \param type : output port type
1145 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1146 * \return an adaptated input port of type Xmlxxxx
1148 InputPort* RuntimeSALOME::adaptXmlToXml(InputXmlPort* inport,
1149 TypeCode * type,bool init)
1152 return new ProxyPort(inport);
1154 if(inport->edGetType()->isAdaptable(type))
1155 return new ProxyPort(inport);
1158 msg << "Cannot connect Xml output port with type: " << type->id() ;
1159 msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1161 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1163 throw ConversionException(msg.str());
1166 //! Adapt an Xml input port to an output port which implementation is given by impl
1168 * \param source : input port to adapt to implementation impl and type type
1169 * \param impl : output port implementation (C++, Python or Corba)
1170 * \param type : output port supported type
1171 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1172 * \return the adaptated port
1175 InputPort* RuntimeSALOME::adapt(InputXmlPort* source,
1176 const std::string& impl,
1177 TypeCode * type,bool init)
1179 if(impl == CORBANode::IMPL_NAME)
1181 return adaptXmlToCorba(source,type);
1183 else if(impl == PythonNode::IMPL_NAME)
1185 return adaptXmlToPython(source,type);
1187 else if(impl == CppNode::IMPL_NAME)
1189 return adaptXmlToCpp(source,type);
1191 else if(impl == XmlNode::IMPL_NAME )
1193 return adaptXmlToXml(source,type,init);
1195 else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1197 return adaptXmlToNeutral(source,type);
1202 msg << "Cannot connect InputXmlPort to " << impl << " implementation";
1203 msg << " (" << __FILE__ << ":" << __LINE__ << ")";
1204 throw ConversionException(msg.str());
1209 //! Adapt a CORBA input port to a CORBA output port
1211 * \param inport : input port to adapt to CORBA outport data type
1212 * \param type : outport data type
1213 * \return an adaptator port of type InputCORBAPort
1215 InputPort* RuntimeSALOME::adaptCorbaToCorba(InputCorbaPort* inport,
1218 if(type->isA(inport->edGetType()))
1220 //types are compatible : no conversion
1221 //outport data type is more specific than inport required type
1222 //so the inport can be used safely
1223 return new ProxyPort(inport);
1225 else if(isAdaptableCorbaCorba(type,inport->edGetType()))
1227 //ouport data can be converted to inport data type
1228 return new CorbaCorba(inport);
1230 //outport data can not be converted
1232 msg << "Cannot connect Corba output port with type: " << type->id() ;
1233 msg << " to CORBA input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1235 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1237 throw ConversionException(msg.str());
1240 //! Adapt a CORBA input port to a Python output port
1242 * \param inport : input port to adapt to Python type type
1243 * \param type : outport data type
1244 * \return an adaptator port of type InputPyPort
1247 InputPort* RuntimeSALOME::adaptCorbaToPython(InputCorbaPort* inport,
1250 if(inport->edGetType()->kind() == Double)
1252 if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaDouble(inport);
1254 else if(inport->edGetType()->kind() == Int)
1256 if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaInt(inport);
1258 else if(inport->edGetType()->kind() == String)
1260 if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaString(inport);
1262 else if(inport->edGetType()->kind() == Bool)
1264 if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaBool(inport);
1266 else if(inport->edGetType()->kind() == Objref )
1268 if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1270 return new PyCorbaObjref(inport);
1275 msg << "Cannot connect Python output port with type: " << type->id() ;
1276 msg << " to CORBA input port " << inport->getName() << " with incompatible objref type: " << inport->edGetType()->id();
1277 msg << " (" << __FILE__ << ":" <<__LINE__ << ")";
1278 throw ConversionException(msg.str());
1281 else if(inport->edGetType()->kind() == Sequence)
1283 if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1285 return new PyCorbaSequence(inport);
1290 msg << "Cannot convert this sequence type " ;
1291 msg << __FILE__ << ":" <<__LINE__;
1292 throw ConversionException(msg.str());
1295 else if(inport->edGetType()->kind() == YACS::ENGINE::Struct)
1297 if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1299 return new PyCorbaStruct(inport);
1304 msg << "Cannot convert this struct type " << type->id() << " to " << inport->edGetType()->id();
1305 msg << __FILE__ << ":" <<__LINE__;
1306 throw ConversionException(msg.str());
1309 // Adaptation not possible
1311 msg << "Cannot connect Python output port with type: " << type->id() ;
1312 msg << " to CORBA input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1314 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1316 throw ConversionException(msg.str());
1319 //! Adapt a CORBA input port to connect it to a XML output port
1321 * \param inport : input port to adapt to Xml type type
1322 * \param type : type supported by output port
1323 * \return an adaptator port of type InputXmlPort
1326 InputPort* RuntimeSALOME::adaptCorbaToXml(InputCorbaPort* inport,
1329 // BEWARE : using the generic check
1330 if(inport->edGetType()->isAdaptable(type))
1332 //output type is convertible to input type
1333 return new XmlCorba(inport);
1335 //output type is not convertible
1337 msg << "Cannot connect Xml output port with type: " << type->id() ;
1338 msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1340 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1342 throw ConversionException(msg.str());
1345 //! Adapt a CORBA input port to a C++ output port
1347 * \param inport : input port to adapt to C++ type type
1348 * \param type : outport data type
1349 * \return an adaptator port of type InputCPPPort
1352 InputPort* RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport,
1355 DEBTRACE("RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport" );
1356 if(isAdaptableCorbaCpp(type,inport->edGetType()))
1358 //output type is convertible to input type
1359 return new CppCorba(inport);
1361 //output type is not convertible
1363 msg << "Cannot connect Cpp output port with type: " << type->id() ;
1364 msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1366 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1368 throw ConversionException(msg.str());
1371 //! Adapt a CORBA input port to a neutral data
1373 * \param inport : InputPort to adapt to Neutral type type
1374 * \param type : outport data type
1375 * \return an adaptator port of type Neutralxxxx
1378 InputPort* RuntimeSALOME::adaptCorbaToNeutral(InputCorbaPort* inport,
1381 if(inport->edGetType()->kind() == Double)
1383 if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaDouble(inport);
1385 else if(inport->edGetType()->kind() == Int)
1387 if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaInt(inport);
1389 else if(inport->edGetType()->kind() == String)
1391 if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaString(inport);
1393 else if(inport->edGetType()->kind() == Bool)
1395 if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaBool(inport);
1397 else if(inport->edGetType()->kind() == Objref)
1399 if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaObjref(inport);
1401 else if(inport->edGetType()->kind() == Sequence)
1403 if(isAdaptableCorbaNeutral(type,inport->edGetType()))
1404 return new NeutralCorbaSequence(inport);
1408 msg << "Cannot convert this sequence type " ;
1409 msg << __FILE__ << ":" <<__LINE__;
1410 throw ConversionException(msg.str());
1413 else if(inport->edGetType()->kind() == Struct)
1415 if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaStruct(inport);
1418 // Adaptation not possible
1420 msg << "Cannot connect Neutral output port with type: " << type->id() ;
1421 msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1423 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1425 throw ConversionException(msg.str());
1428 //! Adapt a CORBA input port to an output which implementation and type are given by impl and type
1430 * \param source : input port to adapt to implementation impl and type type
1431 * \param impl : output port implementation (C++, Python or Corba)
1432 * \param type : outport data type
1433 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1434 * \return an adaptator port which type depends on impl
1437 InputPort* RuntimeSALOME::adapt(InputCorbaPort* source,
1438 const std::string& impl,
1439 TypeCode * type,bool init)
1441 if(impl == CppNode::IMPL_NAME)
1443 return adaptCorbaToCpp(source,type);
1445 else if(impl == PythonNode::IMPL_NAME)
1447 return adaptCorbaToPython(source,type);
1449 else if(impl == CORBANode::IMPL_NAME)
1452 return adaptCorbaToCorba(source,type);
1454 return adaptCorbaToCorba(source,type);
1456 else if(impl == XmlNode::IMPL_NAME )
1458 return adaptCorbaToXml(source,type);
1460 else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1462 return adaptCorbaToNeutral(source,type);
1467 msg << "Cannot connect InputCorbaPort : unknown implementation " ;
1468 msg << __FILE__ << ":" <<__LINE__;
1469 throw ConversionException(msg.str());
1473 //! Adapt a Python input port to a Python output port
1475 * No need to make conversion or cast.
1476 * Only check, it's possible.
1477 * \param inport : InputPort to adapt to Python type type
1478 * \param type : outport data type
1479 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1480 * \return an adaptator port of type InputPyPort
1483 InputPort* RuntimeSALOME::adaptPythonToPython(InputPyPort* inport,
1484 TypeCode * type,bool init)
1487 return new PyInit(inport);
1489 if(isAdaptablePyObjectPyObject(type,inport->edGetType()))
1491 //output data is convertible to input type
1492 //With python, no need to convert. Conversion will be done automatically
1493 //by the interpreter
1494 return new ProxyPort(inport);
1496 //output data is not convertible to input type
1498 msg << "Cannot connect Python output port with type: " << type->id() ;
1499 msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1501 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1503 throw ConversionException(msg.str());
1506 //! Adapt a Python input port to a C++ output port
1508 * \param inport : InputPort to adapt to C++ type type
1509 * \param type : outport data type
1510 * \return an adaptator port of C++ type (InputCppPort)
1513 InputPort* RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport,
1516 DEBTRACE("RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport" );
1517 if(isAdaptablePyObjectCpp(type,inport->edGetType()))
1519 //output type is convertible to input type
1520 return new CppPy(inport);
1522 //output type is not convertible
1524 msg << "Cannot connect Cpp output port with type: " << type->id() ;
1525 msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1527 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1529 throw ConversionException(msg.str());
1532 //! Adapt a Python input port to a Neutral data port
1534 * \param inport : InputPort to adapt to Neutral type type
1535 * \param type : outport data type
1536 * \return an adaptator port of Neutral type (Neutralxxxx)
1539 InputPort* RuntimeSALOME::adaptPythonToNeutral(InputPyPort* inport,
1542 if(inport->edGetType()->kind() == Double)
1544 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyDouble(inport);
1546 else if(inport->edGetType()->kind() == Int)
1548 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyInt(inport);
1550 else if(inport->edGetType()->kind() == String)
1552 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyString(inport);
1554 else if(inport->edGetType()->kind() == Bool)
1556 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyBool(inport);
1558 else if(inport->edGetType()->kind() == Objref)
1560 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyObjref(inport);
1562 else if(inport->edGetType()->kind() == Sequence)
1564 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))
1565 return new NeutralPySequence(inport);
1569 msg << "Cannot convert this sequence type " ;
1570 msg << __FILE__ << ":" <<__LINE__;
1571 throw ConversionException(msg.str());
1574 else if(inport->edGetType()->kind() == Struct)
1576 if(isAdaptablePyObjectNeutral(type,inport->edGetType())) return new NeutralPyStruct(inport);
1579 // Adaptation not possible
1581 msg << "Cannot connect Neutral output port with type: " << type->id() ;
1582 msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1584 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1586 throw ConversionException(msg.str());
1589 //! Adapt a Python input port to a Corba output port
1591 * Always convert the data
1592 * \param inport : InputPort to adapt to Corba type type
1593 * \param type : outport data type
1594 * \return an adaptator port of Corba type (InputCorbaPort)
1597 InputPort* RuntimeSALOME::adaptPythonToCorba(InputPyPort* inport,
1600 if(inport->edGetType()->kind() == Double)
1602 if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyDouble(inport);
1604 else if(inport->edGetType()->kind() == Int)
1606 if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyInt(inport);
1608 else if(inport->edGetType()->kind() == String)
1610 if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyString(inport);
1612 else if(inport->edGetType()->kind() == Bool)
1614 if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyBool(inport);
1616 else if(inport->edGetType()->kind() == Objref)
1618 if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1620 return new CorbaPyObjref(inport);
1625 msg << "Cannot connect InputCorbaPort : incompatible objref types " << type->id() << " " << inport->edGetType()->id();
1626 msg << " " << __FILE__ << ":" <<__LINE__;
1627 throw ConversionException(msg.str());
1630 else if(inport->edGetType()->kind() == Sequence)
1632 if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1634 return new CorbaPySequence(inport);
1639 msg << "Cannot convert this sequence type " ;
1640 msg << __FILE__ << ":" <<__LINE__;
1641 throw ConversionException(msg.str());
1644 else if(inport->edGetType()->kind() == YACS::ENGINE::Struct)
1646 if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1648 return new CorbaPyStruct(inport);
1653 msg << "Cannot convert this struct type " << type->id() << " to " << inport->edGetType()->id();
1654 msg << " " << __FILE__ << ":" <<__LINE__;
1655 throw ConversionException(msg.str());
1658 // Adaptation not possible
1660 msg << "Cannot connect Corba output port with type: " << type->id() ;
1661 msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1663 msg << " ("__FILE__ << ":" << __LINE__ << ")";
1665 throw ConversionException(msg.str());
1668 //! Adapt a Python input port to a Xml output port
1670 * \param inport : input port to adapt to Xml type type
1671 * \param type : output port type
1672 * \return an input port of type InputXmlPort
1675 InputPort* RuntimeSALOME::adaptPythonToXml(InputPyPort* inport,
1678 // BEWARE : using the generic check
1679 if(inport->edGetType()->isAdaptable(type))
1682 return new XmlPython(inport);
1684 //non convertible type
1686 msg << "Cannot connect Xml output port with type: " << type->id() ;
1687 msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1689 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1691 throw ConversionException(msg.str());
1694 //! Adapt a Python input port to an output port with a given implementation
1696 * \param source : input port to adapt to implementation impl and type type
1697 * \param impl : output port implementation (C++, Python or Corba)
1698 * \param type : output port type
1699 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1700 * \return adaptated input port
1703 InputPort* RuntimeSALOME::adapt(InputPyPort* source,
1704 const std::string& impl,
1705 TypeCode * type,bool init)
1707 if(impl == CppNode::IMPL_NAME)
1709 return adaptPythonToCpp(source,type);
1711 else if(impl == PythonNode::IMPL_NAME)
1713 return adaptPythonToPython(source,type,init);
1715 else if(impl == CORBANode::IMPL_NAME)
1717 return adaptPythonToCorba(source,type);
1719 else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1721 return adaptPythonToNeutral(source,type);
1723 else if(impl == XmlNode::IMPL_NAME)
1725 return adaptPythonToXml(source,type);
1730 msg << "Cannot connect InputPyPort : unknown implementation " << impl;
1731 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1732 throw ConversionException(msg.str());
1737 //! Adapt a C++ input port to connect it to a CORBA output port
1739 * \param inport : input port to adapt to CORBA type type
1740 * \param type : type supported by output port
1741 * \return an adaptator port of type InputCorbaPort
1744 InputPort* RuntimeSALOME::adaptCppToCorba(InputCppPort* inport,
1747 DEBTRACE("RuntimeSALOME::adaptCppToCorba(InputCppPort* inport)");
1748 if(isAdaptableCppCorba(type,inport->edGetType()))
1750 //output type is convertible to input type
1751 return new CorbaCpp(inport);
1753 //output type is not convertible
1755 msg << "Cannot connect Corba output port with type: " << type->id() ;
1756 msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1758 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1760 throw ConversionException(msg.str());
1763 //! Adapt a C++ input port to a Python output port
1765 * \param inport : input port to adapt to Python type type
1766 * \param type : output port type
1767 * \return an adaptated input port of type InputPyPort
1769 InputPort* RuntimeSALOME::adaptCppToPython(InputCppPort* inport,
1772 DEBTRACE("RuntimeSALOME::adaptCppToPython(InputCppPort* inport)");
1773 if(isAdaptableCppPyObject(type,inport->edGetType()))
1775 //output type is convertible to input type
1776 return new PyCpp(inport);
1778 //output type is not convertible
1780 msg << "Cannot connect Python output port with type: " << type->id() ;
1781 msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1783 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1785 throw ConversionException(msg.str());
1788 //! Adapt a C++ input port to a C++ output port
1790 * \param inport : input port to adapt to C++ type type
1791 * \param type : output port type
1792 * \return an adaptated input port of type InputPyPort
1794 InputPort* RuntimeSALOME::adaptCppToCpp(InputCppPort* inport,
1797 DEBTRACE("RuntimeSALOME::adaptCppToCpp(InputPort* inport" );
1798 DEBTRACE(type->kind() << " " << inport->edGetType()->kind() );
1799 if(type->isAdaptable(inport->edGetType()))
1801 //the output data is convertible to inport type
1802 return new CppCpp(inport);
1804 //non convertible type
1806 msg << "Cannot connect Cpp output port with type: " << type->id() ;
1807 msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1809 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1811 throw ConversionException(msg.str());
1814 //! Adapt a C++ input port to a Neutral output port
1816 * \param inport : input port to adapt to C++ type type
1817 * \param type : output port type
1818 * \return an adaptated input port of type InputPyPort
1820 InputPort* RuntimeSALOME::adaptCppToNeutral(InputCppPort* inport,
1823 DEBTRACE("RuntimeSALOME::adaptCppToNeutral(InputPort* inport" );
1824 DEBTRACE(type->kind() << " " << inport->edGetType()->kind() );
1825 if(type->isAdaptable(inport->edGetType()))
1827 //the output data is convertible to inport type
1828 return new NeutralCpp(inport);
1830 //non convertible type
1832 msg << "Cannot connect Neutral output port with type: " << type->id() ;
1833 msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1835 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1837 throw ConversionException(msg.str());
1840 InputPort* RuntimeSALOME::adaptCppToXml(InputCppPort* inport,
1843 DEBTRACE("RuntimeSALOME::adaptCppToXml(InputCppPort* inport" );
1844 if(isAdaptableCppXml(type,inport->edGetType()))
1847 return new XmlCpp(inport);
1849 //non convertible type
1851 msg << "Cannot connect Xml output port with type: " << type->id() ;
1852 msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1854 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1856 throw ConversionException(msg.str());
1859 //! Adapt a C++ input port to connect it to an output port with a given implementation
1861 * \param source : input port to adapt to implementation impl and type type
1862 * \param impl : output port implementation (C++, Python or Corba)
1863 * \param type : output port supported type
1864 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1865 * \return the adaptated port
1868 InputPort* RuntimeSALOME::adapt(InputCppPort* source,
1869 const std::string& impl,
1870 TypeCode * type,bool init)
1872 DEBTRACE("RuntimeSALOME::adapt(InputCppPort* source)");
1873 if(impl == CORBANode::IMPL_NAME)
1875 return adaptCppToCorba(source,type);
1877 else if(impl == PythonNode::IMPL_NAME)
1879 return adaptCppToPython(source,type);
1881 else if(impl == XmlNode::IMPL_NAME)
1883 return adaptCppToXml(source,type);
1885 else if(impl == CppNode::IMPL_NAME)
1887 return adaptCppToCpp(source, type);
1889 else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1891 return adaptCppToNeutral(source, type);
1896 msg << "Cannot connect InputCppPort to " << impl << " implementation";
1897 msg << " (" << __FILE__ << ":" << __LINE__ << ")";
1898 throw ConversionException(msg.str());
1902 // bool RuntimeSALOME::isCompatible(const OutputPort* outputPort,
1903 // const InputPort* inputPort)
1905 // bool result=true;
1909 CORBA::ORB_ptr RuntimeSALOME::getOrb() const
1915 * Retrieve from custom NS the entry. Custom NS is supposed to be hosted in current process.
1916 * This method try to emulate CORBA ns convention : "corbaname:rir:#test.my_context/Echo.Object" is converted into "Echo"
1918 * See Engines::EmbeddedNamingService
1920 CORBA::Object_var RuntimeSALOME::getFromNS(const char *entry) const
1922 CORBA::Object_var ret;
1923 std::string entryCpp(entry);
1924 if(entryCpp.substr(0,4) == "IOR:")
1926 ret = _orb->string_to_object( entry );
1930 auto pos = entryCpp.find_last_of('/');
1931 std::string entry1( entryCpp.substr(pos+1,std::string::npos) );
1932 pos = entry1.find_last_of('.');
1933 std::string entry2( entry1.substr(0,pos) );
1934 Engines::EmbeddedNamingService_var ns = GetEmbeddedNamingService();
1935 std::unique_ptr<Engines::IORType> iorRet( ns->Resolve( entry2.c_str() ) );
1936 auto len = iorRet->length();
1937 std::unique_ptr<char[]> iorTrans(new char[len+1]); iorTrans[len] = '\0';
1938 for(auto i = 0 ; i < len ; ++i) iorTrans[i] = (*iorRet)[i];
1939 ret = _orb->string_to_object(iorTrans.get());
1944 PyObject * RuntimeSALOME::getPyOrb() const
1949 PyObject * RuntimeSALOME::getBuiltins() const
1954 DynamicAny::DynAnyFactory_ptr RuntimeSALOME::getDynFactory() const
1959 PyObject * RuntimeSALOME::get_omnipy()
1964 omniORBpyAPI* RuntimeSALOME::getApi()
1969 void* RuntimeSALOME::convertNeutral(TypeCode * type, Any *data)
1972 return (void *)convertNeutralPyObject(type,data);
1976 return (void *)Py_None;
1980 std::string RuntimeSALOME::convertNeutralAsString(TypeCode * type, Any *data)
1985 // The call to PyGILState_Ensure was moved here because there was also
1986 // a crash when calling convertNeutralPyObject with a sequence of pyobj.
1987 // see also the comment below.
1988 PyGILState_STATE gstate = PyGILState_Ensure();
1989 ob=convertNeutralPyObject(type,data);
1990 std::string s=convertPyObjectToString(ob);
1992 // Note (Renaud Barate, 8 jan 2013): With Python 2.7, this call to Py_DECREF causes a crash
1993 // (SIGSEGV) when ob is a sequence and the call is not protected with the global interpreter
1994 // lock. I thus added the call to PyGILState_Ensure / PyGILState_Release. It worked fine in
1995 // Python 2.6 without this call. If anyone finds the real reason of this bug and another fix,
1996 // feel free to change this code.
1997 //PyGILState_STATE gstate = PyGILState_Ensure();
1999 PyGILState_Release(gstate);
2008 std::string RuntimeSALOME::convertPyObjectToString(PyObject* ob)
2010 return YACS::ENGINE::convertPyObjectToString(ob);
2013 PyObject* RuntimeSALOME::convertStringToPyObject(const std::string& s)
2018 PyGILState_STATE gstate = PyGILState_Ensure();
2019 mainmod = PyImport_AddModule("__main__");
2020 globals = PyModule_GetDict(mainmod);
2021 PyObject* d = PyDict_New();
2022 //PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins());
2023 ob= PyRun_String( s.c_str(), Py_eval_input, globals, d);
2029 PyObject* new_stderr = newPyStdOut(error);
2030 PySys_SetObject((char *)"stderr", new_stderr);
2032 PySys_SetObject((char *)"stderr", PySys_GetObject((char *)"__stderr__"));
2033 Py_DECREF(new_stderr);
2034 PyGILState_Release(gstate);
2035 throw Exception(error);
2037 PyGILState_Release(gstate);