1 // Copyright (C) 2006-2023 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 CORBA_CLIENT_HEADER(SALOME_ContainerManager)
123 #include <libxml/parser.h>
124 #include <omniORB4/CORBA.h>
130 #include "YacsTrace.hxx"
133 using namespace YACS::ENGINE;
135 std::unique_ptr<SALOME_NamingService_Container_Abstract> RuntimeSALOME::getNS()
137 std::unique_ptr<SALOME_NamingService_Container_Abstract> ret(new SALOME_NamingService_Wrapper);
141 void RuntimeSALOME::setRuntime(long flags, int argc, char* argv[]) // singleton creation (not thread safe!)
143 if (! Runtime::_singleton)
145 RuntimeSALOME* r=new RuntimeSALOME(flags, argc, argv);
146 Runtime::_singleton = r;
149 DEBTRACE("RuntimeSALOME::setRuntime() done !");
152 RuntimeSALOME* YACS::ENGINE::getSALOMERuntime()
154 YASSERT(RuntimeSALOME::getSingleton());
155 return dynamic_cast< RuntimeSALOME* >(RuntimeSALOME::getSingleton());
159 * Singleton creation, initialize converter map
162 RuntimeSALOME::RuntimeSALOME()
167 void RuntimeSALOME::initBuiltins()
169 //Fill the builtin catalog with nodes specific to the runtime
170 std::map<std::string,TypeCode*>& typeMap=_builtinCatalog->_typeMap;
171 std::map<std::string,Node*>& nodeMap=_builtinCatalog->_nodeMap;
172 std::map<std::string,ComposedNode*>& composednodeMap=_builtinCatalog->_composednodeMap;
173 std::map<std::string,ComponentDefinition*>& componentMap=_builtinCatalog->_componentMap;
174 nodeMap["PyFunction"]=new PyFuncNode("PyFunction");
175 nodeMap["PyScript"]=new PythonNode("PyScript");
176 nodeMap["CORBANode"]=new CORBANode("CORBANode");
177 nodeMap["XmlNode"]=new XmlNode("XmlNode");
178 nodeMap["SalomeNode"]=new SalomeNode("SalomeNode");
179 nodeMap["CppNode"]=new CppNode("CppNode");
180 nodeMap["SalomePythonNode"]=new SalomePythonNode("SalomePythonNode");
181 nodeMap["PresetNode"]=new PresetNode("PresetNode");
182 nodeMap["OutNode"]=new OutNode("OutNode");
183 nodeMap["StudyInNode"]=new StudyInNode("StudyInNode");
184 nodeMap["StudyOutNode"]=new StudyOutNode("StudyOutNode");
185 composednodeMap["OptimizerLoop"]=createOptimizerLoop("OptimizerLoop","","",true);
186 typeMap["dblevec"]= createSequenceTc("dblevec","dblevec",_tc_double);
187 typeMap["intvec"]= createSequenceTc("intvec","intvec",_tc_int);
188 typeMap["stringvec"]= createSequenceTc("stringvec","stringvec",_tc_string);
189 typeMap["boolvec"]= createSequenceTc("boolvec","boolvec",_tc_bool);
190 typeMap["seqdblevec"]= createSequenceTc("seqdblevec","seqdblevec",typeMap["dblevec"]);
191 typeMap["seqintvec"]= createSequenceTc("seqintvec","seqintvec",typeMap["intvec"]);
192 typeMap["seqstringvec"]= createSequenceTc("seqstringvec","seqstringvec",typeMap["stringvec"]);
193 typeMap["seqboolvec"]= createSequenceTc("seqboolvec","seqboolvec",typeMap["boolvec"]);
194 std::list<TypeCodeObjref *> ltc;
195 typeMap["pyobj"]= createInterfaceTc("python:obj:1.0","pyobj",ltc);
196 typeMap["seqpyobj"]= createSequenceTc("seqpyobj","seqpyobj",typeMap["pyobj"]);
197 composednodeMap["Bloc"]=createBloc("Bloc");
198 composednodeMap["Switch"]=createSwitch("Switch");
199 composednodeMap["WhileLoop"]=createWhileLoop("WhileLoop");
200 composednodeMap["ForLoop"]=createForLoop("ForLoop");
201 composednodeMap["ForEachLoop_double"]=createForEachLoop("ForEachLoop_double",Runtime::_tc_double);
202 composednodeMap["ForEachLoop_string"]=createForEachLoop("ForEachLoop_string",Runtime::_tc_string);
203 composednodeMap["ForEachLoop_int"]=createForEachLoop("ForEachLoop_int",Runtime::_tc_int);
204 composednodeMap["ForEachLoop_bool"]=createForEachLoop("ForEachLoop_bool",Runtime::_tc_bool);
205 composednodeMap["ForEachLoop_pyobj"]=createForEachLoop("ForEachLoop_pyobj",typeMap["pyobj"]);;
206 ENGINE::TypeCodeStruct *t = createStructTc("","Engines/dataref");
207 t->addMember("ref",_tc_string);
208 typeMap["dataref"]= t;
211 RuntimeSALOME::RuntimeSALOME(long flags, int argc, char* argv[])
213 // If all flags (apart the IsPyExt flags) are unset, force them to true
214 if ((flags - flags & RuntimeSALOME::IsPyExt) == 0)
215 flags += RuntimeSALOME::UseCorba + RuntimeSALOME::UsePython
216 + RuntimeSALOME::UseCpp + RuntimeSALOME::UseXml;
218 // Salome Nodes implies Corba Nodes
219 if (flags & RuntimeSALOME::UseSalome)
220 flags |= RuntimeSALOME::UseCorba;
222 // Corba Nodes implies Python Nodes
223 if (flags & RuntimeSALOME::UseCorba)
224 flags |= RuntimeSALOME::UsePython;
226 _useCorba = flags & RuntimeSALOME::UseCorba;
227 _usePython = flags & RuntimeSALOME::UsePython;
228 _useCpp = flags & RuntimeSALOME::UseCpp;
229 _useXml = flags & RuntimeSALOME::UseXml;
234 if (_useCpp) _setOfImplementation.insert(CppNode::IMPL_NAME);
235 if (_usePython) _setOfImplementation.insert(PythonNode::IMPL_NAME);
236 if (_useCorba) _setOfImplementation.insert(CORBANode::IMPL_NAME);
237 if (_useXml) _setOfImplementation.insert(XmlNode::IMPL_NAME);
238 init(flags, argc, argv);
241 RuntimeSALOME::~RuntimeSALOME()
243 DEBTRACE("RuntimeSALOME::~RuntimeSALOME");
244 // destroy catalog loader prototypes
245 std::map<std::string, CatalogLoader*>::const_iterator pt;
246 for(pt=_catalogLoaderFactoryMap.begin();pt!=_catalogLoaderFactoryMap.end();pt++)
250 _connectionManager.ShutdownWithExit();
253 void RuntimeSALOME::loadModulCatalog()
256 const char * SCRIPT = "from salome_kernel import list_of_catalogs_regarding_environement\n"
257 "import KernelModuleCatalog\n"
258 "KernelModuleCatalog.myModuleCatalog( list_of_catalogs_regarding_environement() )\n";
259 PyRun_SimpleString(SCRIPT);
262 //! CORBA and Python initialization
264 * \param flags contains several bits
265 * bit0 (ispyext) true when method is called from Python
266 * (Python initialization must not be done!)
267 * bit1 (UsePython) true if python nodes are needed
268 * bit1 (UseCorba) true if CORBA nodes are needed
269 * bit1 (UseXml) true if python nodes are needed
270 * bit1 (UseCpp) true if C++ nodes are needed
271 * bit1 (UseSalome) true if Salome nodes are needed
272 * \param argc number of command line arguments (used to initialize the Python interpreter)
273 * \param argv command line arguments (used to initialize the Python interpreter)
277 void RuntimeSALOME::init(long flags, int argc, char* argv[])
279 bool ispyext = flags & RuntimeSALOME::IsPyExt;
282 PortableServer::POA_var root_poa;
283 PortableServer::POAManager_var pman;
284 CORBA::Object_var obj;
285 int nbargs = 0; char **args = 0;
286 _orb = CORBA::ORB_init (nbargs, args);
287 obj = _orb->resolve_initial_references("RootPOA");
288 root_poa = PortableServer::POA::_narrow(obj);
289 pman = root_poa->the_POAManager();
293 DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
295 obj = _orb->resolve_initial_references("DynAnyFactory");
296 _dynFactory = DynamicAny::DynAnyFactory::_narrow(obj);
301 DEBTRACE("RuntimeSALOME::init, is python extension = " << ispyext);
303 // Initialize Python interpreter in embedded mode
304 if (!Py_IsInitialized())
306 #if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0
309 Py_InitializeEx(0); // do not install signal handlers
311 if (argc > 0 && argv != NULL)
313 wchar_t **changed_argv = new wchar_t*[argc];
314 for (int i = 0; i < argc; i++)
316 changed_argv[i] = Py_DecodeLocale(argv[i], NULL);
318 PySys_SetArgv(argc, changed_argv);
324 char defaultName[] = "SALOME_YACS_RUNTIME";
325 wchar_t **changed_pyArgv = new wchar_t*[pyArgc];
326 pyArgv[0] = defaultName;
327 for (int i = 0; i < pyArgc; i++)
329 changed_pyArgv[i] = Py_DecodeLocale(pyArgv[i], NULL);
331 PySys_SetArgv(pyArgc, changed_pyArgv);
333 #if PY_VERSION_HEX < 0x03070000
334 PyEval_InitThreads(); /* Create (and acquire) the interpreter lock (for threads)*/
336 PyEval_SaveThread(); /* Release the thread state */
337 //here we do not have the Global Interpreter Lock
340 PyObject *mainmod,*pyapi,*res ;
342 PyGILState_STATE gstate;
343 gstate = PyGILState_Ensure(); // acquire the Global Interpreter Lock
345 mainmod = PyImport_AddModule("__main__");
346 globals = PyModule_GetDict(mainmod);
347 /* globals is a borrowed reference */
349 if (PyDict_GetItemString(globals, "__builtins__") == NULL)
351 PyObject *bimod = PyImport_ImportModule("builtins");
352 if (bimod == NULL || PyDict_SetItemString(globals, "__builtins__", bimod) != 0)
353 Py_FatalError("can't add __builtins__ to __main__");
357 _bltins = PyEval_GetBuiltins(); /* borrowed ref */
363 _omnipy = PyImport_ImportModule((char*)"_omnipy");
367 PyErr_SetString(PyExc_ImportError, (char*)"Cannot import _omnipy");
370 pyapi = PyObject_GetAttrString(_omnipy, (char*)"API");
375 _api = (omniORBpyAPI*)PyCapsule_GetPointer(pyapi,"_omnipy.API");
378 res=PyRun_String("\n"
379 "from math import *\n"
381 "sys.path.insert(0,'.')\n"
382 "from omniORB import CORBA\n"
383 "from omniORB import any\n"
384 "orb = CORBA.ORB_init([], CORBA.ORB_ID)\n"
385 "#print(sys.getrefcount(orb))\n"
391 Py_file_input,globals,globals );
399 _pyorb = PyDict_GetItemString(globals,"orb");
400 /* PyDict_GetItemString returns a borrowed reference. There is no need to decref _pyorb */
403 pyany = PyDict_GetItemString(globals,"any");
404 /* PyDict_GetItemString returns a borrowed reference. There is no need to decref pyany */
407 DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
411 PyGILState_Release(gstate); // Release the Global Interpreter Lock
415 // initialize the catalogLoaderFactory map with the session one
416 _catalogLoaderFactoryMap["session"]=new SessionCataLoader;
420 void RuntimeSALOME::fini()
424 PyGILState_STATE gstate = PyGILState_Ensure();
426 DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
428 PyObject *mainmod, *globals;
429 mainmod = PyImport_AddModule("__main__");
430 globals = PyModule_GetDict(mainmod);
434 res=PyRun_String("orb.destroy()\n"
436 Py_file_input,globals,globals );
442 std::map<std::string,Node*>& nodeMap=_builtinCatalog->_nodeMap;
443 delete nodeMap["PyFunction"];
444 delete nodeMap["PyScript"];
445 delete nodeMap["SalomePythonNode"];
446 nodeMap.erase("PyFunction");
447 nodeMap.erase("PyScript");
448 nodeMap.erase("SalomePythonNode");
452 DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
460 DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
467 std::vector< std::pair<std::string,int> > RuntimeSALOME::getCatalogOfComputeNodes() const
469 CORBA::ORB_ptr orb(getOrb());
470 SALOME_NamingService_Wrapper namingService;
473 namingService.init_orb(orb);
475 catch(SALOME_Exception& e)
477 throw Exception("RuntimeSALOME::getCatalogOfComputeNodes : Unable to contact the SALOME Naming Service");
479 CORBA::Object_var obj(namingService.Resolve(SALOME_ResourcesManager::_ResourcesManagerNameInNS));
480 if(CORBA::is_nil(obj))
481 throw Exception("RuntimeSALOME::getCatalogOfComputeNodes : Unable to access to the resource manager !");
482 Engines::ResourcesManager_var resManager(Engines::ResourcesManager::_narrow(obj));
483 if(CORBA::is_nil(resManager))
484 throw Exception("RuntimeSALOME::getCatalogOfComputeNodes : Internal error ! The entry attached to the res manager in NS does not have right type !");
485 std::vector< std::pair<std::string,int> > ret;
486 Engines::ResourceParameters params;
488 params.hostname = "";
492 params.cpu_clock = 0;
494 params.nb_proc_per_node = 0;
496 params.can_launch_batch_jobs = false;
497 params.can_run_containers = true;
498 params.componentList.length(0);
501 Engines::ResourceList_var resourceList;
502 resourceList = resManager->GetFittingResources(params);
503 ret.reserve(resourceList->length());
504 for(int i = 0; i<resourceList->length(); i++)
506 const char* resource_name = resourceList[i];
507 std::string std_resource_name = resource_name;
508 Engines::ResourceDefinition_var resource_definition
509 = resManager->GetResourceDefinition(resource_name);
510 int nb_cores = resource_definition->nb_node *
511 resource_definition->nb_proc_per_node;
512 ret.push_back(std::pair<std::string,int>(resource_name, nb_cores));
515 catch(SALOME::SALOME_Exception& e)
518 message=e.details.text.in();
519 throw Exception(message);
525 std::string RuntimeSALOME::getVersion() const
527 #ifdef YACS_DEVELOPMENT
528 return CORBA::string_dup(YACS_VERSION_STR"dev");
530 return CORBA::string_dup(YACS_VERSION_STR);
534 Proc* RuntimeSALOME::createProc(const std::string& name)
536 return new SalomeProc(name);
539 TypeCode * RuntimeSALOME::createInterfaceTc(const std::string& id, const std::string& name,
540 std::list<TypeCodeObjref *> ltc)
543 if(id == "") myName = "IDL:" + name + ":1.0";
545 return TypeCode::interfaceTc(myName.c_str(),name.c_str(),ltc);
548 TypeCode * RuntimeSALOME::createSequenceTc(const std::string& id,
549 const std::string& name,
552 return TypeCode::sequenceTc(id.c_str(),name.c_str(),content);
555 TypeCodeStruct * RuntimeSALOME::createStructTc(const std::string& id, const std::string& name)
558 if(id == "") myName = "IDL:" + name + ":1.0";
560 return (TypeCodeStruct *)TypeCode::structTc(myName.c_str(),name.c_str());
563 Bloc* RuntimeSALOME::createBloc(const std::string& name)
565 return new Bloc(name);
568 WhileLoop* RuntimeSALOME::createWhileLoop(const std::string& name)
570 return new WhileLoop(name);
573 ForLoop* RuntimeSALOME::createForLoop(const std::string& name)
575 return new ForLoop(name);
578 OptimizerLoop* RuntimeSALOME::createOptimizerLoop(const std::string& name,const std::string& algLib,const std::string& factoryName,
579 bool algInitOnFile, const std::string& kind, Proc * procForTypes)
581 OptimizerLoop * ol = (kind == "base") ? new OptimizerLoop(name,algLib,factoryName,algInitOnFile, true, procForTypes) :
582 new SalomeOptimizerLoop(name,algLib,factoryName,algInitOnFile, true, procForTypes);
583 ol->edGetNbOfBranchesPort()->edInit(1);
587 DataNode* RuntimeSALOME::createInDataNode(const std::string& kind,const std::string& name)
592 node = new PresetNode(name);
595 else if(kind == "study" )
597 return new StudyInNode(name);
599 std::string msg="DataNode kind ("+kind+") unknown";
600 throw Exception(msg);
603 DataNode* RuntimeSALOME::createOutDataNode(const std::string& kind,const std::string& name)
607 return new OutNode(name);
609 else if(kind == "study" )
611 return new StudyOutNode(name);
614 std::string msg="OutDataNode kind ("+kind+") unknown";
615 throw Exception(msg);
618 InlineFuncNode* RuntimeSALOME::createFuncNode(const std::string& kind,const std::string& name)
620 InlineFuncNode* node;
621 if(kind == "" || kind == SalomeNode::KIND || kind == PythonNode::KIND)
623 node = new PyFuncNode(name);
626 if(kind == DistributedPythonNode::KIND)
627 return new DistributedPythonNode(name);
628 std::string msg="FuncNode kind ("+kind+") unknown";
629 throw Exception(msg);
632 InlineNode* RuntimeSALOME::createScriptNode(const std::string& kind,const std::string& name)
635 if(kind == "" || kind == SalomeNode::KIND || kind == PythonNode::KIND)
637 node = new PythonNode(name);
640 std::string msg="ScriptNode kind ("+kind+") unknown";
641 throw Exception(msg);
644 ServiceNode* RuntimeSALOME::createRefNode(const std::string& kind,const std::string& name)
647 if(kind == "" || kind == SalomeNode::KIND || kind == CORBANode::KIND)
649 node = new CORBANode(name);
652 else if(kind == XmlNode::KIND)
654 node = new XmlNode(name);
657 std::string msg="RefNode kind ("+kind+") unknown";
658 throw Exception(msg);
661 ServiceNode* RuntimeSALOME::createCompoNode(const std::string& kind,const std::string& name)
664 if(kind == "" || kind == SalomeNode::KIND )
666 node=new SalomeNode(name);
669 else if (kind == CppNode::KIND)
671 node = new CppNode(name);
674 std::string msg="CompoNode kind ("+kind+") unknown";
675 throw Exception(msg);
678 ServiceInlineNode *RuntimeSALOME::createSInlineNode(const std::string& kind, const std::string& name)
680 if(kind == "" || kind == SalomeNode::KIND )
681 return new SalomePythonNode(name);
682 std::string msg="CompoNode kind ("+kind+") unknown";
683 throw Exception(msg);
686 ComponentInstance* RuntimeSALOME::createComponentInstance(const std::string& name,
687 const std::string& kind)
689 ComponentInstance* compo;
690 if(kind == "" || kind == SalomeComponent::KIND)
691 return new SalomeComponent(name);
692 else if(kind == CORBAComponent::KIND)
693 return new CORBAComponent(name);
694 else if(kind == SalomePythonComponent::KIND)
695 return new SalomePythonComponent(name);
696 else if (kind == CppComponent::KIND)
697 return new CppComponent(name);
698 else if (kind == SalomeHPComponent::KIND)
699 return new SalomeHPComponent(name);
700 std::string msg="Component Instance kind ("+kind+") unknown";
701 throw Exception(msg);
704 Container *RuntimeSALOME::createContainer(const std::string& kind)
706 if(kind == "" || kind == SalomeContainer::KIND)
707 return new SalomeContainer;
708 if(kind==SalomeHPContainer::KIND)
709 return new SalomeHPContainer;
710 else if (kind == CppContainer::KIND)
711 return new CppContainer;
712 std::string msg="Container kind ("+kind+") unknown";
713 throw Exception(msg);
716 InputPort * RuntimeSALOME::createInputPort(const std::string& name,
717 const std::string& impl,
721 if(impl == CppNode::IMPL_NAME)
723 return new InputCppPort(name, node, type);
725 else if(impl == PythonNode::IMPL_NAME)
727 return new InputPyPort(name, node, type);
729 else if(impl == CORBANode::IMPL_NAME)
731 return new InputCorbaPort(name, node, type);
733 else if(impl == XmlNode::IMPL_NAME)
735 return new InputXmlPort(name, node, type);
740 msg << "Cannot create " << impl << " InputPort" ;
741 msg << " (" << __FILE__ << ":" << __LINE__ << ")";
742 throw Exception(msg.str());
746 OutputPort * RuntimeSALOME::createOutputPort(const std::string& name,
747 const std::string& impl,
751 if(impl == CppNode::IMPL_NAME)
753 return new OutputCppPort(name, node, type);
755 else if(impl == PythonNode::IMPL_NAME)
757 return new OutputPyPort(name, node, type);
759 else if(impl == CORBANode::IMPL_NAME)
761 return new OutputCorbaPort(name, node, type);
763 else if(impl == XmlNode::IMPL_NAME)
765 return new OutputXmlPort(name, node, type);
770 msg << "Cannot create " << impl << " OutputPort" ;
771 msg << " (" << __FILE__ << ":" << __LINE__ << ")";
772 throw Exception(msg.str());
776 InputDataStreamPort* RuntimeSALOME::createInputDataStreamPort(const std::string& name,
777 Node *node,TypeCode *type)
779 DEBTRACE("createInputDataStreamPort: " << name << " " << type->shortName());
780 if(type->kind() == Objref && std::string(type->shortName(),7) == "CALCIUM")
782 return new InputCalStreamPort(name,node,type);
786 return new InputDataStreamPort(name,node,type);
790 OutputDataStreamPort* RuntimeSALOME::createOutputDataStreamPort(const std::string& name,
791 Node *node,TypeCode *type)
793 DEBTRACE("createOutputDataStreamPort: " << name << " " << type->shortName());
794 if(type->kind() == Objref && std::string(type->shortName(),7) == "CALCIUM")
796 return new OutputCalStreamPort(name,node,type);
800 return new OutputDataStreamPort(name,node,type);
804 //! Main adapter function : adapt an InputPort to be able to connect it to an OutputPort with a possible different implementation
806 * \param source : InputPort to be adapted
807 * \param impl : new implementation (C++, python, CORBA, XML, Neutral)
808 * \param type : data type provided by the InputPort
809 * \param init : indicates if the adapted InputPort will be used for initialization (value true) or not (value false)
811 * \return : adapted InputPort
813 InputPort* RuntimeSALOME::adapt(InputPort* source,
814 const std::string& impl,
815 TypeCode * type,bool init)
817 string imp_source=source->getNode()->getImplementation();
818 if(imp_source == PythonNode::IMPL_NAME)
820 return adapt((InputPyPort*)source,impl,type,init);
822 else if(imp_source == CppNode::IMPL_NAME)
824 return adapt((InputCppPort*)source,impl,type,init);
826 else if(imp_source == CORBANode::IMPL_NAME)
828 return adapt((InputCorbaPort*)source,impl,type,init);
830 else if(imp_source == XmlNode::IMPL_NAME)
832 return adapt((InputXmlPort*)source,impl,type,init);
834 else if(imp_source == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
836 return adaptNeutral(source,impl,type,init);
841 msg << "Cannot adapt " << imp_source << " InputPort to " << impl;
842 msg << " (" << __FILE__ << ":" << __LINE__ << ")";
843 throw ConversionException(msg.str());
847 //! Adapter function for InPropertyPort
849 * \param source : InPropertyPort to be adapted
850 * \param impl : new implementation (C++, python, CORBA, XML, Neutral)
851 * \param type : data type provided by the InPropertyPort
852 * \param init : indicates if the adapted InPropertyPort will be used for initialization (value true) or not (value false)
854 * \return : adapted InputPort
856 InputPort* RuntimeSALOME::adapt(InPropertyPort* source,
857 const std::string& impl,
858 TypeCode * type,bool init)
860 return adaptNeutral((InputPort *)source,impl,type,init);
863 //! Adapt a Neutral input port to a Corba output port
865 * \param inport : Neutral input port to adapt to Corba type type
866 * \param type : output port type
867 * \return an adaptated input port of type InputCorbaPort
869 InputPort* RuntimeSALOME::adaptNeutralToCorba(InputPort* inport,
872 // BEWARE : using the generic check
873 if(inport->edGetType()->isAdaptable(type))
875 //the output data is convertible to inport type
876 return new CorbaNeutral(inport);
878 //non convertible type
880 msg << "Cannot connect Corba output port with type: " << type->id() ;
881 msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
883 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
885 throw ConversionException(msg.str());
888 //! Adapt a Neutral input port to a Python output port
890 * \param inport : input port to adapt to Python type type
891 * \param type : output port type
892 * \return an adaptated input port of type InputPyPort
894 InputPort* RuntimeSALOME::adaptNeutralToPython(InputPort* inport,
897 // BEWARE : using the generic check
898 if(inport->edGetType()->isAdaptable(type))
901 return new PyNeutral(inport);
903 //last chance : an py output that is seq[objref] can be connected to a neutral input objref (P13268)
904 else if(type->kind()==Sequence && type->contentType()->kind()==Objref && inport->edGetType()->kind()==Objref)
906 return new PyNeutral(inport);
908 //non convertible type
910 msg << "Cannot connect Python output port with type: " << type->id() ;
911 msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
913 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
915 throw ConversionException(msg.str());
918 //! Adapt a Neutral input port to a Xml output port
920 * \param inport : input port to adapt to Xml type type
921 * \param type : output port type
922 * \return an input port of type InputXmlPort
924 InputPort* RuntimeSALOME::adaptNeutralToXml(InputPort* inport,
927 // BEWARE : using the generic check
928 if(inport->edGetType()->isAdaptable(type))
931 return new XmlNeutral(inport);
933 //non convertible type
935 msg << "Cannot connect Xml output port with type: " << type->id() ;
936 msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
938 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
940 throw ConversionException(msg.str());
943 //! Adapt a Neutral input port to a C++ output port
945 * \param inport : input port to adapt to C++ type type
946 * \param type : output port type
947 * \return an input port of type InputCppPort
949 InputPort* RuntimeSALOME::adaptNeutralToCpp(InputPort* inport,
952 DEBTRACE("RuntimeSALOME::adaptNeutralToCpp(InputPort* inport" );
953 if(isAdaptableNeutralCpp(type,inport->edGetType()))
956 return new CppNeutral(inport);
958 //non convertible type
960 msg << "Cannot connect Cpp output port with type: " << type->id() ;
961 msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
963 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
965 throw ConversionException(msg.str());
968 //! Adapt a Neutral input port to connect it to an output port with a given implementation
970 * \param source : Neutral input port to adapt to implementation impl and type type
971 * \param impl : output port implementation (C++, Python, Corba, Xml or Neutral)
972 * \param type : output port supported type
973 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
974 * \return the adaptated port
976 InputPort* RuntimeSALOME::adaptNeutral(InputPort* source,
977 const std::string& impl,
978 TypeCode * type,bool init)
980 if(impl == CppNode::IMPL_NAME)
982 return adaptNeutralToCpp(source,type);
984 else if(impl == PythonNode::IMPL_NAME)
986 return adaptNeutralToPython(source,type);
988 else if(impl == CORBANode::IMPL_NAME)
990 return adaptNeutralToCorba(source,type);
992 else if(impl == XmlNode::IMPL_NAME )
994 return adaptNeutralToXml(source,type);
996 else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
999 return new NeutralInit(source);
1001 return new ProxyPort(source);
1004 msg << "Cannot connect InputPort : unknown implementation " << impl;
1005 msg << " (" <<__FILE__ << ":" <<__LINE__ << ")";
1006 throw ConversionException(msg.str());
1009 //! Adapt a XML input port to connect it to a CORBA output port
1011 * \param inport : input port to adapt to CORBA type type
1012 * \param type : type supported by output port
1013 * \return an adaptator port of type InputCorbaPort
1016 InputPort* RuntimeSALOME::adaptXmlToCorba(InputXmlPort* inport,
1019 if(isAdaptableXmlCorba(type,inport->edGetType()))
1021 //output type is convertible to input type
1022 return new CorbaXml(inport);
1024 //output type is not convertible
1026 msg << "Cannot connect Corba output port with type: " << type->id() ;
1027 msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1029 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1031 throw ConversionException(msg.str());
1034 //! Adapt a XML input port to a Python output port
1036 * \param inport : input port to adapt to Python type type
1037 * \param type : output port type
1038 * \return an adaptated input port of type InputPyPort
1040 InputPort* RuntimeSALOME::adaptXmlToPython(InputXmlPort* inport,
1043 if(inport->edGetType()->isAdaptable(type))
1045 //the output data is convertible to inport type
1046 return new PyXml(inport);
1048 //non convertible type
1050 msg << "Cannot connect Python output port with type: " << type->id() ;
1051 msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1053 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1055 throw ConversionException(msg.str());
1058 //! Adapt a XML input port to a C++ output port
1060 * \param inport : input port to adapt to C++ type type
1061 * \param type : output port type
1062 * \return an adaptated input port of type InputPyPort
1064 InputPort* RuntimeSALOME::adaptXmlToCpp(InputXmlPort* inport,
1067 DEBTRACE("RuntimeSALOME::adaptXmlToCpp(InputPort* inport" );
1068 DEBTRACE(type->kind() << " " << inport->edGetType()->kind() );
1069 if(type->isAdaptable(inport->edGetType()))
1071 //the output data is convertible to inport type
1072 return new CppXml(inport);
1074 //non convertible type
1076 msg << "Cannot connect Cpp output port with type: " << type->id() ;
1077 msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1079 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1081 throw ConversionException(msg.str());
1084 //! Adapt a XML input port to a Neutral output port
1086 * \param inport : input port to adapt to Neutral type type
1087 * \param type : output port type
1088 * \return an adaptated input port of type Neutralxxxx
1090 InputPort* RuntimeSALOME::adaptXmlToNeutral(InputXmlPort* inport,
1093 if(inport->edGetType()->isAdaptable(type))
1095 //the output data is convertible to inport type
1096 return new NeutralXml(inport);
1098 //non convertible type
1100 msg << "Cannot connect Xml InputPort to OutputNeutralPort : " ;
1101 msg << "(" <<__FILE__ << ":" <<__LINE__<< ")";
1102 throw ConversionException(msg.str());
1105 //! Adapt a XML input port to a Xml output port
1107 * \param inport : input port to adapt to Xml type type
1108 * \param type : output port type
1109 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1110 * \return an adaptated input port of type Xmlxxxx
1112 InputPort* RuntimeSALOME::adaptXmlToXml(InputXmlPort* inport,
1113 TypeCode * type,bool init)
1116 return new ProxyPort(inport);
1118 if(inport->edGetType()->isAdaptable(type))
1119 return new ProxyPort(inport);
1122 msg << "Cannot connect Xml output port with type: " << type->id() ;
1123 msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1125 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1127 throw ConversionException(msg.str());
1130 //! Adapt an Xml input port to an output port which implementation is given by impl
1132 * \param source : input port to adapt to implementation impl and type type
1133 * \param impl : output port implementation (C++, Python or Corba)
1134 * \param type : output port supported type
1135 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1136 * \return the adaptated port
1139 InputPort* RuntimeSALOME::adapt(InputXmlPort* source,
1140 const std::string& impl,
1141 TypeCode * type,bool init)
1143 if(impl == CORBANode::IMPL_NAME)
1145 return adaptXmlToCorba(source,type);
1147 else if(impl == PythonNode::IMPL_NAME)
1149 return adaptXmlToPython(source,type);
1151 else if(impl == CppNode::IMPL_NAME)
1153 return adaptXmlToCpp(source,type);
1155 else if(impl == XmlNode::IMPL_NAME )
1157 return adaptXmlToXml(source,type,init);
1159 else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1161 return adaptXmlToNeutral(source,type);
1166 msg << "Cannot connect InputXmlPort to " << impl << " implementation";
1167 msg << " (" << __FILE__ << ":" << __LINE__ << ")";
1168 throw ConversionException(msg.str());
1173 //! Adapt a CORBA input port to a CORBA output port
1175 * \param inport : input port to adapt to CORBA outport data type
1176 * \param type : outport data type
1177 * \return an adaptator port of type InputCORBAPort
1179 InputPort* RuntimeSALOME::adaptCorbaToCorba(InputCorbaPort* inport,
1182 if(type->isA(inport->edGetType()))
1184 //types are compatible : no conversion
1185 //outport data type is more specific than inport required type
1186 //so the inport can be used safely
1187 return new ProxyPort(inport);
1189 else if(isAdaptableCorbaCorba(type,inport->edGetType()))
1191 //ouport data can be converted to inport data type
1192 return new CorbaCorba(inport);
1194 //outport data can not be converted
1196 msg << "Cannot connect Corba output port with type: " << type->id() ;
1197 msg << " to CORBA input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1199 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1201 throw ConversionException(msg.str());
1204 //! Adapt a CORBA input port to a Python output port
1206 * \param inport : input port to adapt to Python type type
1207 * \param type : outport data type
1208 * \return an adaptator port of type InputPyPort
1211 InputPort* RuntimeSALOME::adaptCorbaToPython(InputCorbaPort* inport,
1214 if(inport->edGetType()->kind() == Double)
1216 if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaDouble(inport);
1218 else if(inport->edGetType()->kind() == Int)
1220 if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaInt(inport);
1222 else if(inport->edGetType()->kind() == String)
1224 if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaString(inport);
1226 else if(inport->edGetType()->kind() == Bool)
1228 if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaBool(inport);
1230 else if(inport->edGetType()->kind() == Objref )
1232 if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1234 return new PyCorbaObjref(inport);
1239 msg << "Cannot connect Python output port with type: " << type->id() ;
1240 msg << " to CORBA input port " << inport->getName() << " with incompatible objref type: " << inport->edGetType()->id();
1241 msg << " (" << __FILE__ << ":" <<__LINE__ << ")";
1242 throw ConversionException(msg.str());
1245 else if(inport->edGetType()->kind() == Sequence)
1247 if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1249 return new PyCorbaSequence(inport);
1254 msg << "Cannot convert this sequence type " ;
1255 msg << __FILE__ << ":" <<__LINE__;
1256 throw ConversionException(msg.str());
1259 else if(inport->edGetType()->kind() == YACS::ENGINE::Struct)
1261 if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1263 return new PyCorbaStruct(inport);
1268 msg << "Cannot convert this struct type " << type->id() << " to " << inport->edGetType()->id();
1269 msg << __FILE__ << ":" <<__LINE__;
1270 throw ConversionException(msg.str());
1273 // Adaptation not possible
1275 msg << "Cannot connect Python output port with type: " << type->id() ;
1276 msg << " to CORBA input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1278 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1280 throw ConversionException(msg.str());
1283 //! Adapt a CORBA input port to connect it to a XML output port
1285 * \param inport : input port to adapt to Xml type type
1286 * \param type : type supported by output port
1287 * \return an adaptator port of type InputXmlPort
1290 InputPort* RuntimeSALOME::adaptCorbaToXml(InputCorbaPort* inport,
1293 // BEWARE : using the generic check
1294 if(inport->edGetType()->isAdaptable(type))
1296 //output type is convertible to input type
1297 return new XmlCorba(inport);
1299 //output type is not convertible
1301 msg << "Cannot connect Xml output port with type: " << type->id() ;
1302 msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1304 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1306 throw ConversionException(msg.str());
1309 //! Adapt a CORBA input port to a C++ output port
1311 * \param inport : input port to adapt to C++ type type
1312 * \param type : outport data type
1313 * \return an adaptator port of type InputCPPPort
1316 InputPort* RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport,
1319 DEBTRACE("RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport" );
1320 if(isAdaptableCorbaCpp(type,inport->edGetType()))
1322 //output type is convertible to input type
1323 return new CppCorba(inport);
1325 //output type is not convertible
1327 msg << "Cannot connect Cpp output port with type: " << type->id() ;
1328 msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1330 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1332 throw ConversionException(msg.str());
1335 //! Adapt a CORBA input port to a neutral data
1337 * \param inport : InputPort to adapt to Neutral type type
1338 * \param type : outport data type
1339 * \return an adaptator port of type Neutralxxxx
1342 InputPort* RuntimeSALOME::adaptCorbaToNeutral(InputCorbaPort* inport,
1345 if(inport->edGetType()->kind() == Double)
1347 if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaDouble(inport);
1349 else if(inport->edGetType()->kind() == Int)
1351 if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaInt(inport);
1353 else if(inport->edGetType()->kind() == String)
1355 if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaString(inport);
1357 else if(inport->edGetType()->kind() == Bool)
1359 if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaBool(inport);
1361 else if(inport->edGetType()->kind() == Objref)
1363 if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaObjref(inport);
1365 else if(inport->edGetType()->kind() == Sequence)
1367 if(isAdaptableCorbaNeutral(type,inport->edGetType()))
1368 return new NeutralCorbaSequence(inport);
1372 msg << "Cannot convert this sequence type " ;
1373 msg << __FILE__ << ":" <<__LINE__;
1374 throw ConversionException(msg.str());
1377 else if(inport->edGetType()->kind() == Struct)
1379 if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaStruct(inport);
1382 // Adaptation not possible
1384 msg << "Cannot connect Neutral output port with type: " << type->id() ;
1385 msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1387 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1389 throw ConversionException(msg.str());
1392 //! Adapt a CORBA input port to an output which implementation and type are given by impl and type
1394 * \param source : input port to adapt to implementation impl and type type
1395 * \param impl : output port implementation (C++, Python or Corba)
1396 * \param type : outport data type
1397 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1398 * \return an adaptator port which type depends on impl
1401 InputPort* RuntimeSALOME::adapt(InputCorbaPort* source,
1402 const std::string& impl,
1403 TypeCode * type,bool init)
1405 if(impl == CppNode::IMPL_NAME)
1407 return adaptCorbaToCpp(source,type);
1409 else if(impl == PythonNode::IMPL_NAME)
1411 return adaptCorbaToPython(source,type);
1413 else if(impl == CORBANode::IMPL_NAME)
1416 return adaptCorbaToCorba(source,type);
1418 return adaptCorbaToCorba(source,type);
1420 else if(impl == XmlNode::IMPL_NAME )
1422 return adaptCorbaToXml(source,type);
1424 else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1426 return adaptCorbaToNeutral(source,type);
1431 msg << "Cannot connect InputCorbaPort : unknown implementation " ;
1432 msg << __FILE__ << ":" <<__LINE__;
1433 throw ConversionException(msg.str());
1437 //! Adapt a Python input port to a Python output port
1439 * No need to make conversion or cast.
1440 * Only check, it's possible.
1441 * \param inport : InputPort to adapt to Python type type
1442 * \param type : outport data type
1443 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1444 * \return an adaptator port of type InputPyPort
1447 InputPort* RuntimeSALOME::adaptPythonToPython(InputPyPort* inport,
1448 TypeCode * type,bool init)
1451 return new PyInit(inport);
1453 if(isAdaptablePyObjectPyObject(type,inport->edGetType()))
1455 //output data is convertible to input type
1456 //With python, no need to convert. Conversion will be done automatically
1457 //by the interpreter
1458 return new ProxyPort(inport);
1460 //output data is not convertible to input type
1462 msg << "Cannot connect Python output port with type: " << type->id() ;
1463 msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1465 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1467 throw ConversionException(msg.str());
1470 //! Adapt a Python input port to a C++ output port
1472 * \param inport : InputPort to adapt to C++ type type
1473 * \param type : outport data type
1474 * \return an adaptator port of C++ type (InputCppPort)
1477 InputPort* RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport,
1480 DEBTRACE("RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport" );
1481 if(isAdaptablePyObjectCpp(type,inport->edGetType()))
1483 //output type is convertible to input type
1484 return new CppPy(inport);
1486 //output type is not convertible
1488 msg << "Cannot connect Cpp output port with type: " << type->id() ;
1489 msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1491 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1493 throw ConversionException(msg.str());
1496 //! Adapt a Python input port to a Neutral data port
1498 * \param inport : InputPort to adapt to Neutral type type
1499 * \param type : outport data type
1500 * \return an adaptator port of Neutral type (Neutralxxxx)
1503 InputPort* RuntimeSALOME::adaptPythonToNeutral(InputPyPort* inport,
1506 if(inport->edGetType()->kind() == Double)
1508 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyDouble(inport);
1510 else if(inport->edGetType()->kind() == Int)
1512 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyInt(inport);
1514 else if(inport->edGetType()->kind() == String)
1516 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyString(inport);
1518 else if(inport->edGetType()->kind() == Bool)
1520 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyBool(inport);
1522 else if(inport->edGetType()->kind() == Objref)
1524 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyObjref(inport);
1526 else if(inport->edGetType()->kind() == Sequence)
1528 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))
1529 return new NeutralPySequence(inport);
1533 msg << "Cannot convert this sequence type " ;
1534 msg << __FILE__ << ":" <<__LINE__;
1535 throw ConversionException(msg.str());
1538 else if(inport->edGetType()->kind() == Struct)
1540 if(isAdaptablePyObjectNeutral(type,inport->edGetType())) return new NeutralPyStruct(inport);
1543 // Adaptation not possible
1545 msg << "Cannot connect Neutral output port with type: " << type->id() ;
1546 msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1548 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1550 throw ConversionException(msg.str());
1553 //! Adapt a Python input port to a Corba output port
1555 * Always convert the data
1556 * \param inport : InputPort to adapt to Corba type type
1557 * \param type : outport data type
1558 * \return an adaptator port of Corba type (InputCorbaPort)
1561 InputPort* RuntimeSALOME::adaptPythonToCorba(InputPyPort* inport,
1564 if(inport->edGetType()->kind() == Double)
1566 if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyDouble(inport);
1568 else if(inport->edGetType()->kind() == Int)
1570 if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyInt(inport);
1572 else if(inport->edGetType()->kind() == String)
1574 if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyString(inport);
1576 else if(inport->edGetType()->kind() == Bool)
1578 if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyBool(inport);
1580 else if(inport->edGetType()->kind() == Objref)
1582 if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1584 return new CorbaPyObjref(inport);
1589 msg << "Cannot connect InputCorbaPort : incompatible objref types " << type->id() << " " << inport->edGetType()->id();
1590 msg << " " << __FILE__ << ":" <<__LINE__;
1591 throw ConversionException(msg.str());
1594 else if(inport->edGetType()->kind() == Sequence)
1596 if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1598 return new CorbaPySequence(inport);
1603 msg << "Cannot convert this sequence type " ;
1604 msg << __FILE__ << ":" <<__LINE__;
1605 throw ConversionException(msg.str());
1608 else if(inport->edGetType()->kind() == YACS::ENGINE::Struct)
1610 if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1612 return new CorbaPyStruct(inport);
1617 msg << "Cannot convert this struct type " << type->id() << " to " << inport->edGetType()->id();
1618 msg << " " << __FILE__ << ":" <<__LINE__;
1619 throw ConversionException(msg.str());
1622 // Adaptation not possible
1624 msg << "Cannot connect Corba output port with type: " << type->id() ;
1625 msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1627 msg << " ("__FILE__ << ":" << __LINE__ << ")";
1629 throw ConversionException(msg.str());
1632 //! Adapt a Python input port to a Xml output port
1634 * \param inport : input port to adapt to Xml type type
1635 * \param type : output port type
1636 * \return an input port of type InputXmlPort
1639 InputPort* RuntimeSALOME::adaptPythonToXml(InputPyPort* inport,
1642 // BEWARE : using the generic check
1643 if(inport->edGetType()->isAdaptable(type))
1646 return new XmlPython(inport);
1648 //non convertible type
1650 msg << "Cannot connect Xml output port with type: " << type->id() ;
1651 msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1653 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1655 throw ConversionException(msg.str());
1658 //! Adapt a Python input port to an output port with a given implementation
1660 * \param source : input port to adapt to implementation impl and type type
1661 * \param impl : output port implementation (C++, Python or Corba)
1662 * \param type : output port type
1663 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1664 * \return adaptated input port
1667 InputPort* RuntimeSALOME::adapt(InputPyPort* source,
1668 const std::string& impl,
1669 TypeCode * type,bool init)
1671 if(impl == CppNode::IMPL_NAME)
1673 return adaptPythonToCpp(source,type);
1675 else if(impl == PythonNode::IMPL_NAME)
1677 return adaptPythonToPython(source,type,init);
1679 else if(impl == CORBANode::IMPL_NAME)
1681 return adaptPythonToCorba(source,type);
1683 else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1685 return adaptPythonToNeutral(source,type);
1687 else if(impl == XmlNode::IMPL_NAME)
1689 return adaptPythonToXml(source,type);
1694 msg << "Cannot connect InputPyPort : unknown implementation " << impl;
1695 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1696 throw ConversionException(msg.str());
1701 //! Adapt a C++ input port to connect it to a CORBA output port
1703 * \param inport : input port to adapt to CORBA type type
1704 * \param type : type supported by output port
1705 * \return an adaptator port of type InputCorbaPort
1708 InputPort* RuntimeSALOME::adaptCppToCorba(InputCppPort* inport,
1711 DEBTRACE("RuntimeSALOME::adaptCppToCorba(InputCppPort* inport)");
1712 if(isAdaptableCppCorba(type,inport->edGetType()))
1714 //output type is convertible to input type
1715 return new CorbaCpp(inport);
1717 //output type is not convertible
1719 msg << "Cannot connect Corba output port with type: " << type->id() ;
1720 msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1722 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1724 throw ConversionException(msg.str());
1727 //! Adapt a C++ input port to a Python output port
1729 * \param inport : input port to adapt to Python type type
1730 * \param type : output port type
1731 * \return an adaptated input port of type InputPyPort
1733 InputPort* RuntimeSALOME::adaptCppToPython(InputCppPort* inport,
1736 DEBTRACE("RuntimeSALOME::adaptCppToPython(InputCppPort* inport)");
1737 if(isAdaptableCppPyObject(type,inport->edGetType()))
1739 //output type is convertible to input type
1740 return new PyCpp(inport);
1742 //output type is not convertible
1744 msg << "Cannot connect Python output port with type: " << type->id() ;
1745 msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1747 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1749 throw ConversionException(msg.str());
1752 //! Adapt a C++ input port to a C++ output port
1754 * \param inport : input port to adapt to C++ type type
1755 * \param type : output port type
1756 * \return an adaptated input port of type InputPyPort
1758 InputPort* RuntimeSALOME::adaptCppToCpp(InputCppPort* inport,
1761 DEBTRACE("RuntimeSALOME::adaptCppToCpp(InputPort* inport" );
1762 DEBTRACE(type->kind() << " " << inport->edGetType()->kind() );
1763 if(type->isAdaptable(inport->edGetType()))
1765 //the output data is convertible to inport type
1766 return new CppCpp(inport);
1768 //non convertible type
1770 msg << "Cannot connect Cpp output port with type: " << type->id() ;
1771 msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1773 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1775 throw ConversionException(msg.str());
1778 //! Adapt a C++ input port to a Neutral output port
1780 * \param inport : input port to adapt to C++ type type
1781 * \param type : output port type
1782 * \return an adaptated input port of type InputPyPort
1784 InputPort* RuntimeSALOME::adaptCppToNeutral(InputCppPort* inport,
1787 DEBTRACE("RuntimeSALOME::adaptCppToNeutral(InputPort* inport" );
1788 DEBTRACE(type->kind() << " " << inport->edGetType()->kind() );
1789 if(type->isAdaptable(inport->edGetType()))
1791 //the output data is convertible to inport type
1792 return new NeutralCpp(inport);
1794 //non convertible type
1796 msg << "Cannot connect Neutral output port with type: " << type->id() ;
1797 msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1799 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1801 throw ConversionException(msg.str());
1804 InputPort* RuntimeSALOME::adaptCppToXml(InputCppPort* inport,
1807 DEBTRACE("RuntimeSALOME::adaptCppToXml(InputCppPort* inport" );
1808 if(isAdaptableCppXml(type,inport->edGetType()))
1811 return new XmlCpp(inport);
1813 //non convertible type
1815 msg << "Cannot connect Xml output port with type: " << type->id() ;
1816 msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1818 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1820 throw ConversionException(msg.str());
1823 //! Adapt a C++ input port to connect it to an output port with a given implementation
1825 * \param source : input port to adapt to implementation impl and type type
1826 * \param impl : output port implementation (C++, Python or Corba)
1827 * \param type : output port supported type
1828 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1829 * \return the adaptated port
1832 InputPort* RuntimeSALOME::adapt(InputCppPort* source,
1833 const std::string& impl,
1834 TypeCode * type,bool init)
1836 DEBTRACE("RuntimeSALOME::adapt(InputCppPort* source)");
1837 if(impl == CORBANode::IMPL_NAME)
1839 return adaptCppToCorba(source,type);
1841 else if(impl == PythonNode::IMPL_NAME)
1843 return adaptCppToPython(source,type);
1845 else if(impl == XmlNode::IMPL_NAME)
1847 return adaptCppToXml(source,type);
1849 else if(impl == CppNode::IMPL_NAME)
1851 return adaptCppToCpp(source, type);
1853 else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1855 return adaptCppToNeutral(source, type);
1860 msg << "Cannot connect InputCppPort to " << impl << " implementation";
1861 msg << " (" << __FILE__ << ":" << __LINE__ << ")";
1862 throw ConversionException(msg.str());
1866 // bool RuntimeSALOME::isCompatible(const OutputPort* outputPort,
1867 // const InputPort* inputPort)
1869 // bool result=true;
1873 CORBA::ORB_ptr RuntimeSALOME::getOrb() const
1878 PyObject * RuntimeSALOME::getPyOrb() const
1883 PyObject * RuntimeSALOME::getBuiltins() const
1888 DynamicAny::DynAnyFactory_ptr RuntimeSALOME::getDynFactory() const
1893 PyObject * RuntimeSALOME::get_omnipy()
1898 omniORBpyAPI* RuntimeSALOME::getApi()
1903 void* RuntimeSALOME::convertNeutral(TypeCode * type, Any *data)
1906 return (void *)convertNeutralPyObject(type,data);
1910 return (void *)Py_None;
1914 std::string RuntimeSALOME::convertNeutralAsString(TypeCode * type, Any *data)
1919 // The call to PyGILState_Ensure was moved here because there was also
1920 // a crash when calling convertNeutralPyObject with a sequence of pyobj.
1921 // see also the comment below.
1922 PyGILState_STATE gstate = PyGILState_Ensure();
1923 ob=convertNeutralPyObject(type,data);
1924 std::string s=convertPyObjectToString(ob);
1926 // Note (Renaud Barate, 8 jan 2013): With Python 2.7, this call to Py_DECREF causes a crash
1927 // (SIGSEGV) when ob is a sequence and the call is not protected with the global interpreter
1928 // lock. I thus added the call to PyGILState_Ensure / PyGILState_Release. It worked fine in
1929 // Python 2.6 without this call. If anyone finds the real reason of this bug and another fix,
1930 // feel free to change this code.
1931 //PyGILState_STATE gstate = PyGILState_Ensure();
1933 PyGILState_Release(gstate);
1942 std::string RuntimeSALOME::convertPyObjectToString(PyObject* ob)
1944 return YACS::ENGINE::convertPyObjectToString(ob);
1947 PyObject* RuntimeSALOME::convertStringToPyObject(const std::string& s)
1952 PyGILState_STATE gstate = PyGILState_Ensure();
1953 mainmod = PyImport_AddModule("__main__");
1954 globals = PyModule_GetDict(mainmod);
1955 PyObject* d = PyDict_New();
1956 //PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins());
1957 ob= PyRun_String( s.c_str(), Py_eval_input, globals, d);
1963 PyObject* new_stderr = newPyStdOut(error);
1964 PySys_SetObject((char *)"stderr", new_stderr);
1966 PySys_SetObject((char *)"stderr", PySys_GetObject((char *)"__stderr__"));
1967 Py_DECREF(new_stderr);
1968 PyGILState_Release(gstate);
1969 throw Exception(error);
1971 PyGILState_Release(gstate);