1 // Copyright (C) 2006-2021 CEA/DEN, EDF R&D
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"
64 #include "PythonNode.hxx"
65 #include "CORBANode.hxx"
66 #include "XMLNode.hxx"
67 #include "CppNode.hxx"
68 #include "PresetNode.hxx"
69 #include "OutNode.hxx"
70 #include "StudyNodes.hxx"
71 #include "SalomePythonNode.hxx"
72 #include "DistributedPythonNode.hxx"
75 #include "CORBACORBAConv.hxx"
76 #include "CORBAPythonConv.hxx"
77 #include "CORBAXMLConv.hxx"
78 #include "CORBACppConv.hxx"
79 #include "CORBANeutralConv.hxx"
81 #include "TypeConversions.hxx"
83 #include "PythonCORBAConv.hxx"
84 #include "PythonXMLConv.hxx"
85 #include "PythonCppConv.hxx"
86 #include "PythonNeutralConv.hxx"
87 #include "PythonInitConv.hxx"
90 #include "NeutralCORBAConv.hxx"
91 #include "NeutralPythonConv.hxx"
92 #include "NeutralXMLConv.hxx"
93 #include "NeutralCppConv.hxx"
94 #include "NeutralInitConv.hxx"
97 #include "CppCORBAConv.hxx"
98 #include "CppPythonConv.hxx"
99 #include "CppXMLConv.hxx"
100 #include "CppCppConv.hxx"
101 #include "CppNeutralConv.hxx"
104 #include "XMLCORBAConv.hxx"
105 #include "XMLPythonConv.hxx"
106 #include "XMLCppConv.hxx"
107 #include "XMLNeutralConv.hxx"
109 //Calcium specific ports
110 #include "CalStreamPort.hxx"
113 #include "SALOME_NamingService_Wrapper.hxx"
114 #include "SALOME_LifeCycleCORBA.hxx"
115 #include "SALOME_ResourcesManager.hxx"
116 #include "SALOME_ContainerManager.hxx"
117 #include "SALOMEconfig.h"
118 #include CORBA_CLIENT_HEADER(SALOME_ContainerManager)
122 #include <libxml/parser.h>
123 #include <omniORB4/CORBA.h>
129 #include "YacsTrace.hxx"
132 using namespace YACS::ENGINE;
134 std::unique_ptr<SALOME_NamingService_Container_Abstract> RuntimeSALOME::getNS()
136 std::unique_ptr<SALOME_NamingService_Container_Abstract> ret(new SALOME_NamingService_Wrapper);
140 void RuntimeSALOME::setRuntime(long flags, int argc, char* argv[]) // singleton creation (not thread safe!)
142 if (! Runtime::_singleton)
144 RuntimeSALOME* r=new RuntimeSALOME(flags, argc, argv);
145 Runtime::_singleton = r;
148 DEBTRACE("RuntimeSALOME::setRuntime() done !");
151 RuntimeSALOME* YACS::ENGINE::getSALOMERuntime()
153 YASSERT(RuntimeSALOME::getSingleton());
154 return dynamic_cast< RuntimeSALOME* >(RuntimeSALOME::getSingleton());
158 * Singleton creation, initialize converter map
161 RuntimeSALOME::RuntimeSALOME()
166 void RuntimeSALOME::initBuiltins()
168 //Fill the builtin catalog with nodes specific to the runtime
169 std::map<std::string,TypeCode*>& typeMap=_builtinCatalog->_typeMap;
170 std::map<std::string,Node*>& nodeMap=_builtinCatalog->_nodeMap;
171 std::map<std::string,ComposedNode*>& composednodeMap=_builtinCatalog->_composednodeMap;
172 std::map<std::string,ComponentDefinition*>& componentMap=_builtinCatalog->_componentMap;
173 nodeMap["PyFunction"]=new PyFuncNode("PyFunction");
174 nodeMap["PyScript"]=new PythonNode("PyScript");
175 nodeMap["CORBANode"]=new CORBANode("CORBANode");
176 nodeMap["XmlNode"]=new XmlNode("XmlNode");
177 nodeMap["SalomeNode"]=new SalomeNode("SalomeNode");
178 nodeMap["CppNode"]=new CppNode("CppNode");
179 nodeMap["SalomePythonNode"]=new SalomePythonNode("SalomePythonNode");
180 nodeMap["PresetNode"]=new PresetNode("PresetNode");
181 nodeMap["OutNode"]=new OutNode("OutNode");
182 nodeMap["StudyInNode"]=new StudyInNode("StudyInNode");
183 nodeMap["StudyOutNode"]=new StudyOutNode("StudyOutNode");
184 composednodeMap["OptimizerLoop"]=createOptimizerLoop("OptimizerLoop","","",true);
185 typeMap["dblevec"]= createSequenceTc("dblevec","dblevec",_tc_double);
186 typeMap["intvec"]= createSequenceTc("intvec","intvec",_tc_int);
187 typeMap["stringvec"]= createSequenceTc("stringvec","stringvec",_tc_string);
188 typeMap["boolvec"]= createSequenceTc("boolvec","boolvec",_tc_bool);
189 typeMap["seqdblevec"]= createSequenceTc("seqdblevec","seqdblevec",typeMap["dblevec"]);
190 typeMap["seqintvec"]= createSequenceTc("seqintvec","seqintvec",typeMap["intvec"]);
191 typeMap["seqstringvec"]= createSequenceTc("seqstringvec","seqstringvec",typeMap["stringvec"]);
192 typeMap["seqboolvec"]= createSequenceTc("seqboolvec","seqboolvec",typeMap["boolvec"]);
193 std::list<TypeCodeObjref *> ltc;
194 typeMap["pyobj"]= createInterfaceTc("python:obj:1.0","pyobj",ltc);
195 typeMap["seqpyobj"]= createSequenceTc("seqpyobj","seqpyobj",typeMap["pyobj"]);
196 composednodeMap["Bloc"]=createBloc("Bloc");
197 composednodeMap["Switch"]=createSwitch("Switch");
198 composednodeMap["WhileLoop"]=createWhileLoop("WhileLoop");
199 composednodeMap["ForLoop"]=createForLoop("ForLoop");
200 composednodeMap["ForEachLoop_double"]=createForEachLoop("ForEachLoop_double",Runtime::_tc_double);
201 composednodeMap["ForEachLoop_string"]=createForEachLoop("ForEachLoop_string",Runtime::_tc_string);
202 composednodeMap["ForEachLoop_int"]=createForEachLoop("ForEachLoop_int",Runtime::_tc_int);
203 composednodeMap["ForEachLoop_bool"]=createForEachLoop("ForEachLoop_bool",Runtime::_tc_bool);
204 composednodeMap["ForEachLoop_pyobj"]=createForEachLoop("ForEachLoop_pyobj",typeMap["pyobj"]);;
205 ENGINE::TypeCodeStruct *t = createStructTc("","Engines/dataref");
206 t->addMember("ref",_tc_string);
207 typeMap["dataref"]= t;
210 RuntimeSALOME::RuntimeSALOME(long flags, int argc, char* argv[])
212 // If all flags (apart the IsPyExt flags) are unset, force them to true
213 if ((flags - flags & RuntimeSALOME::IsPyExt) == 0)
214 flags += RuntimeSALOME::UseCorba + RuntimeSALOME::UsePython
215 + RuntimeSALOME::UseCpp + RuntimeSALOME::UseXml;
217 // Salome Nodes implies Corba Nodes
218 if (flags & RuntimeSALOME::UseSalome)
219 flags |= RuntimeSALOME::UseCorba;
221 // Corba Nodes implies Python Nodes
222 if (flags & RuntimeSALOME::UseCorba)
223 flags |= RuntimeSALOME::UsePython;
225 _useCorba = flags & RuntimeSALOME::UseCorba;
226 _usePython = flags & RuntimeSALOME::UsePython;
227 _useCpp = flags & RuntimeSALOME::UseCpp;
228 _useXml = flags & RuntimeSALOME::UseXml;
233 if (_useCpp) _setOfImplementation.insert(CppNode::IMPL_NAME);
234 if (_usePython) _setOfImplementation.insert(PythonNode::IMPL_NAME);
235 if (_useCorba) _setOfImplementation.insert(CORBANode::IMPL_NAME);
236 if (_useXml) _setOfImplementation.insert(XmlNode::IMPL_NAME);
237 init(flags, argc, argv);
240 RuntimeSALOME::~RuntimeSALOME()
242 DEBTRACE("RuntimeSALOME::~RuntimeSALOME");
243 // destroy catalog loader prototypes
244 std::map<std::string, CatalogLoader*>::const_iterator pt;
245 for(pt=_catalogLoaderFactoryMap.begin();pt!=_catalogLoaderFactoryMap.end();pt++)
251 //! CORBA and Python initialization
253 * \param flags contains several bits
254 * bit0 (ispyext) true when method is called from Python
255 * (Python initialization must not be done!)
256 * bit1 (UsePython) true if python nodes are needed
257 * bit1 (UseCorba) true if CORBA nodes are needed
258 * bit1 (UseXml) true if python nodes are needed
259 * bit1 (UseCpp) true if C++ nodes are needed
260 * bit1 (UseSalome) true if Salome nodes are needed
261 * \param argc number of command line arguments (used to initialize the Python interpreter)
262 * \param argv command line arguments (used to initialize the Python interpreter)
266 void RuntimeSALOME::init(long flags, int argc, char* argv[])
268 bool ispyext = flags & RuntimeSALOME::IsPyExt;
271 PortableServer::POA_var root_poa;
272 PortableServer::POAManager_var pman;
273 CORBA::Object_var obj;
274 int nbargs = 0; char **args = 0;
275 _orb = CORBA::ORB_init (nbargs, args);
276 obj = _orb->resolve_initial_references("RootPOA");
277 root_poa = PortableServer::POA::_narrow(obj);
278 pman = root_poa->the_POAManager();
282 DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
284 obj = _orb->resolve_initial_references("DynAnyFactory");
285 _dynFactory = DynamicAny::DynAnyFactory::_narrow(obj);
290 DEBTRACE("RuntimeSALOME::init, is python extension = " << ispyext);
292 // Initialize Python interpreter in embedded mode
293 if (!Py_IsInitialized())
295 #if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0
298 Py_InitializeEx(0); // do not install signal handlers
300 if (argc > 0 && argv != NULL)
302 wchar_t **changed_argv = new wchar_t*[argc];
303 for (int i = 0; i < argc; i++)
305 changed_argv[i] = Py_DecodeLocale(argv[i], NULL);
307 PySys_SetArgv(argc, changed_argv);
313 char defaultName[] = "SALOME_YACS_RUNTIME";
314 wchar_t **changed_pyArgv = new wchar_t*[pyArgc];
315 pyArgv[0] = defaultName;
316 for (int i = 0; i < pyArgc; i++)
318 changed_pyArgv[i] = Py_DecodeLocale(pyArgv[i], NULL);
320 PySys_SetArgv(pyArgc, changed_pyArgv);
322 #if PY_VERSION_HEX < 0x03070000
323 PyEval_InitThreads(); /* Create (and acquire) the interpreter lock (for threads)*/
325 PyEval_SaveThread(); /* Release the thread state */
326 //here we do not have the Global Interpreter Lock
329 PyObject *mainmod,*pyapi,*res ;
331 PyGILState_STATE gstate;
332 gstate = PyGILState_Ensure(); // acquire the Global Interpreter Lock
334 mainmod = PyImport_AddModule("__main__");
335 globals = PyModule_GetDict(mainmod);
336 /* globals is a borrowed reference */
338 if (PyDict_GetItemString(globals, "__builtins__") == NULL)
340 PyObject *bimod = PyImport_ImportModule("builtins");
341 if (bimod == NULL || PyDict_SetItemString(globals, "__builtins__", bimod) != 0)
342 Py_FatalError("can't add __builtins__ to __main__");
346 _bltins = PyEval_GetBuiltins(); /* borrowed ref */
352 _omnipy = PyImport_ImportModule((char*)"_omnipy");
356 PyErr_SetString(PyExc_ImportError, (char*)"Cannot import _omnipy");
359 pyapi = PyObject_GetAttrString(_omnipy, (char*)"API");
364 _api = (omniORBpyAPI*)PyCapsule_GetPointer(pyapi,"_omnipy.API");
367 res=PyRun_String("\n"
368 "from math import *\n"
370 "sys.path.insert(0,'.')\n"
371 "from omniORB import CORBA\n"
372 "from omniORB import any\n"
373 "orb = CORBA.ORB_init([], CORBA.ORB_ID)\n"
374 "#print(sys.getrefcount(orb))\n"
380 Py_file_input,globals,globals );
388 _pyorb = PyDict_GetItemString(globals,"orb");
389 /* PyDict_GetItemString returns a borrowed reference. There is no need to decref _pyorb */
392 pyany = PyDict_GetItemString(globals,"any");
393 /* PyDict_GetItemString returns a borrowed reference. There is no need to decref pyany */
396 DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
400 PyGILState_Release(gstate); // Release the Global Interpreter Lock
404 // initialize the catalogLoaderFactory map with the session one
405 _catalogLoaderFactoryMap["session"]=new SessionCataLoader;
409 void RuntimeSALOME::fini()
413 PyGILState_STATE gstate = PyGILState_Ensure();
415 DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
417 PyObject *mainmod, *globals;
418 mainmod = PyImport_AddModule("__main__");
419 globals = PyModule_GetDict(mainmod);
423 res=PyRun_String("orb.destroy()\n"
425 Py_file_input,globals,globals );
431 std::map<std::string,Node*>& nodeMap=_builtinCatalog->_nodeMap;
432 delete nodeMap["PyFunction"];
433 delete nodeMap["PyScript"];
434 delete nodeMap["SalomePythonNode"];
435 nodeMap.erase("PyFunction");
436 nodeMap.erase("PyScript");
437 nodeMap.erase("SalomePythonNode");
441 DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
449 DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
456 std::vector< std::pair<std::string,int> > RuntimeSALOME::getCatalogOfComputeNodes() const
458 CORBA::ORB_ptr orb(getOrb());
459 SALOME_NamingService_Wrapper namingService;
462 namingService.init_orb(orb);
464 catch(SALOME_Exception& e)
466 throw Exception("RuntimeSALOME::getCatalogOfComputeNodes : Unable to contact the SALOME Naming Service");
468 CORBA::Object_var obj(namingService.Resolve(SALOME_ResourcesManager::_ResourcesManagerNameInNS));
469 if(CORBA::is_nil(obj))
470 throw Exception("RuntimeSALOME::getCatalogOfComputeNodes : Unable to access to the resource manager !");
471 Engines::ResourcesManager_var resManager(Engines::ResourcesManager::_narrow(obj));
472 if(CORBA::is_nil(resManager))
473 throw Exception("RuntimeSALOME::getCatalogOfComputeNodes : Internal error ! The entry attached to the res manager in NS does not have right type !");
474 std::vector< std::pair<std::string,int> > ret;
475 Engines::ResourceParameters params;
477 params.hostname = "";
481 params.cpu_clock = 0;
483 params.nb_proc_per_node = 0;
485 params.can_launch_batch_jobs = false;
486 params.can_run_containers = true;
487 params.componentList.length(0);
490 Engines::ResourceList_var resourceList;
491 resourceList = resManager->GetFittingResources(params);
492 ret.reserve(resourceList->length());
493 for(int i = 0; i<resourceList->length(); i++)
495 const char* resource_name = resourceList[i];
496 std::string std_resource_name = resource_name;
497 Engines::ResourceDefinition_var resource_definition
498 = resManager->GetResourceDefinition(resource_name);
499 int nb_cores = resource_definition->nb_node *
500 resource_definition->nb_proc_per_node;
501 ret.push_back(std::pair<std::string,int>(resource_name, nb_cores));
504 catch(SALOME::SALOME_Exception& e)
507 message=e.details.text.in();
508 throw Exception(message);
514 std::string RuntimeSALOME::getVersion() const
516 #ifdef YACS_DEVELOPMENT
517 return CORBA::string_dup(YACS_VERSION_STR"dev");
519 return CORBA::string_dup(YACS_VERSION_STR);
523 Proc* RuntimeSALOME::createProc(const std::string& name)
525 return new SalomeProc(name);
528 TypeCode * RuntimeSALOME::createInterfaceTc(const std::string& id, const std::string& name,
529 std::list<TypeCodeObjref *> ltc)
532 if(id == "") myName = "IDL:" + name + ":1.0";
534 return TypeCode::interfaceTc(myName.c_str(),name.c_str(),ltc);
537 TypeCode * RuntimeSALOME::createSequenceTc(const std::string& id,
538 const std::string& name,
541 return TypeCode::sequenceTc(id.c_str(),name.c_str(),content);
544 TypeCodeStruct * RuntimeSALOME::createStructTc(const std::string& id, const std::string& name)
547 if(id == "") myName = "IDL:" + name + ":1.0";
549 return (TypeCodeStruct *)TypeCode::structTc(myName.c_str(),name.c_str());
552 Bloc* RuntimeSALOME::createBloc(const std::string& name)
554 return new Bloc(name);
557 WhileLoop* RuntimeSALOME::createWhileLoop(const std::string& name)
559 return new WhileLoop(name);
562 ForLoop* RuntimeSALOME::createForLoop(const std::string& name)
564 return new ForLoop(name);
567 OptimizerLoop* RuntimeSALOME::createOptimizerLoop(const std::string& name,const std::string& algLib,const std::string& factoryName,
568 bool algInitOnFile, const std::string& kind, Proc * procForTypes)
570 OptimizerLoop * ol = (kind == "base") ? new OptimizerLoop(name,algLib,factoryName,algInitOnFile, true, procForTypes) :
571 new SalomeOptimizerLoop(name,algLib,factoryName,algInitOnFile, true, procForTypes);
572 ol->edGetNbOfBranchesPort()->edInit(1);
576 DataNode* RuntimeSALOME::createInDataNode(const std::string& kind,const std::string& name)
581 node = new PresetNode(name);
584 else if(kind == "study" )
586 return new StudyInNode(name);
588 std::string msg="DataNode kind ("+kind+") unknown";
589 throw Exception(msg);
592 DataNode* RuntimeSALOME::createOutDataNode(const std::string& kind,const std::string& name)
596 return new OutNode(name);
598 else if(kind == "study" )
600 return new StudyOutNode(name);
603 std::string msg="OutDataNode kind ("+kind+") unknown";
604 throw Exception(msg);
607 InlineFuncNode* RuntimeSALOME::createFuncNode(const std::string& kind,const std::string& name)
609 InlineFuncNode* node;
610 if(kind == "" || kind == SalomeNode::KIND || kind == PythonNode::KIND)
612 node = new PyFuncNode(name);
615 if(kind == DistributedPythonNode::KIND)
616 return new DistributedPythonNode(name);
617 std::string msg="FuncNode kind ("+kind+") unknown";
618 throw Exception(msg);
621 InlineNode* RuntimeSALOME::createScriptNode(const std::string& kind,const std::string& name)
624 if(kind == "" || kind == SalomeNode::KIND || kind == PythonNode::KIND)
626 node = new PythonNode(name);
629 std::string msg="ScriptNode kind ("+kind+") unknown";
630 throw Exception(msg);
633 ServiceNode* RuntimeSALOME::createRefNode(const std::string& kind,const std::string& name)
636 if(kind == "" || kind == SalomeNode::KIND || kind == CORBANode::KIND)
638 node = new CORBANode(name);
641 else if(kind == XmlNode::KIND)
643 node = new XmlNode(name);
646 std::string msg="RefNode kind ("+kind+") unknown";
647 throw Exception(msg);
650 ServiceNode* RuntimeSALOME::createCompoNode(const std::string& kind,const std::string& name)
653 if(kind == "" || kind == SalomeNode::KIND )
655 node=new SalomeNode(name);
658 else if (kind == CppNode::KIND)
660 node = new CppNode(name);
663 std::string msg="CompoNode kind ("+kind+") unknown";
664 throw Exception(msg);
667 ServiceInlineNode *RuntimeSALOME::createSInlineNode(const std::string& kind, const std::string& name)
669 if(kind == "" || kind == SalomeNode::KIND )
670 return new SalomePythonNode(name);
671 std::string msg="CompoNode kind ("+kind+") unknown";
672 throw Exception(msg);
675 ComponentInstance* RuntimeSALOME::createComponentInstance(const std::string& name,
676 const std::string& kind)
678 ComponentInstance* compo;
679 if(kind == "" || kind == SalomeComponent::KIND)
680 return new SalomeComponent(name);
681 else if(kind == CORBAComponent::KIND)
682 return new CORBAComponent(name);
683 else if(kind == SalomePythonComponent::KIND)
684 return new SalomePythonComponent(name);
685 else if (kind == CppComponent::KIND)
686 return new CppComponent(name);
687 else if (kind == SalomeHPComponent::KIND)
688 return new SalomeHPComponent(name);
689 std::string msg="Component Instance kind ("+kind+") unknown";
690 throw Exception(msg);
693 Container *RuntimeSALOME::createContainer(const std::string& kind)
695 if(kind == "" || kind == SalomeContainer::KIND)
696 return new SalomeContainer;
697 if(kind==SalomeHPContainer::KIND)
698 return new SalomeHPContainer;
699 else if (kind == CppContainer::KIND)
700 return new CppContainer;
701 std::string msg="Container kind ("+kind+") unknown";
702 throw Exception(msg);
705 InputPort * RuntimeSALOME::createInputPort(const std::string& name,
706 const std::string& impl,
710 if(impl == CppNode::IMPL_NAME)
712 return new InputCppPort(name, node, type);
714 else if(impl == PythonNode::IMPL_NAME)
716 return new InputPyPort(name, node, type);
718 else if(impl == CORBANode::IMPL_NAME)
720 return new InputCorbaPort(name, node, type);
722 else if(impl == XmlNode::IMPL_NAME)
724 return new InputXmlPort(name, node, type);
729 msg << "Cannot create " << impl << " InputPort" ;
730 msg << " (" << __FILE__ << ":" << __LINE__ << ")";
731 throw Exception(msg.str());
735 OutputPort * RuntimeSALOME::createOutputPort(const std::string& name,
736 const std::string& impl,
740 if(impl == CppNode::IMPL_NAME)
742 return new OutputCppPort(name, node, type);
744 else if(impl == PythonNode::IMPL_NAME)
746 return new OutputPyPort(name, node, type);
748 else if(impl == CORBANode::IMPL_NAME)
750 return new OutputCorbaPort(name, node, type);
752 else if(impl == XmlNode::IMPL_NAME)
754 return new OutputXmlPort(name, node, type);
759 msg << "Cannot create " << impl << " OutputPort" ;
760 msg << " (" << __FILE__ << ":" << __LINE__ << ")";
761 throw Exception(msg.str());
765 InputDataStreamPort* RuntimeSALOME::createInputDataStreamPort(const std::string& name,
766 Node *node,TypeCode *type)
768 DEBTRACE("createInputDataStreamPort: " << name << " " << type->shortName());
769 if(type->kind() == Objref && std::string(type->shortName(),7) == "CALCIUM")
771 return new InputCalStreamPort(name,node,type);
775 return new InputDataStreamPort(name,node,type);
779 OutputDataStreamPort* RuntimeSALOME::createOutputDataStreamPort(const std::string& name,
780 Node *node,TypeCode *type)
782 DEBTRACE("createOutputDataStreamPort: " << name << " " << type->shortName());
783 if(type->kind() == Objref && std::string(type->shortName(),7) == "CALCIUM")
785 return new OutputCalStreamPort(name,node,type);
789 return new OutputDataStreamPort(name,node,type);
793 //! Main adapter function : adapt an InputPort to be able to connect it to an OutputPort with a possible different implementation
795 * \param source : InputPort to be adapted
796 * \param impl : new implementation (C++, python, CORBA, XML, Neutral)
797 * \param type : data type provided by the InputPort
798 * \param init : indicates if the adapted InputPort will be used for initialization (value true) or not (value false)
800 * \return : adapted InputPort
802 InputPort* RuntimeSALOME::adapt(InputPort* source,
803 const std::string& impl,
804 TypeCode * type,bool init)
806 string imp_source=source->getNode()->getImplementation();
807 if(imp_source == PythonNode::IMPL_NAME)
809 return adapt((InputPyPort*)source,impl,type,init);
811 else if(imp_source == CppNode::IMPL_NAME)
813 return adapt((InputCppPort*)source,impl,type,init);
815 else if(imp_source == CORBANode::IMPL_NAME)
817 return adapt((InputCorbaPort*)source,impl,type,init);
819 else if(imp_source == XmlNode::IMPL_NAME)
821 return adapt((InputXmlPort*)source,impl,type,init);
823 else if(imp_source == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
825 return adaptNeutral(source,impl,type,init);
830 msg << "Cannot adapt " << imp_source << " InputPort to " << impl;
831 msg << " (" << __FILE__ << ":" << __LINE__ << ")";
832 throw ConversionException(msg.str());
836 //! Adapter function for InPropertyPort
838 * \param source : InPropertyPort to be adapted
839 * \param impl : new implementation (C++, python, CORBA, XML, Neutral)
840 * \param type : data type provided by the InPropertyPort
841 * \param init : indicates if the adapted InPropertyPort will be used for initialization (value true) or not (value false)
843 * \return : adapted InputPort
845 InputPort* RuntimeSALOME::adapt(InPropertyPort* source,
846 const std::string& impl,
847 TypeCode * type,bool init)
849 return adaptNeutral((InputPort *)source,impl,type,init);
852 //! Adapt a Neutral input port to a Corba output port
854 * \param inport : Neutral input port to adapt to Corba type type
855 * \param type : output port type
856 * \return an adaptated input port of type InputCorbaPort
858 InputPort* RuntimeSALOME::adaptNeutralToCorba(InputPort* inport,
861 // BEWARE : using the generic check
862 if(inport->edGetType()->isAdaptable(type))
864 //the output data is convertible to inport type
865 return new CorbaNeutral(inport);
867 //non convertible type
869 msg << "Cannot connect Corba output port with type: " << type->id() ;
870 msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
872 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
874 throw ConversionException(msg.str());
877 //! Adapt a Neutral input port to a Python output port
879 * \param inport : input port to adapt to Python type type
880 * \param type : output port type
881 * \return an adaptated input port of type InputPyPort
883 InputPort* RuntimeSALOME::adaptNeutralToPython(InputPort* inport,
886 // BEWARE : using the generic check
887 if(inport->edGetType()->isAdaptable(type))
890 return new PyNeutral(inport);
892 //last chance : an py output that is seq[objref] can be connected to a neutral input objref (P13268)
893 else if(type->kind()==Sequence && type->contentType()->kind()==Objref && inport->edGetType()->kind()==Objref)
895 return new PyNeutral(inport);
897 //non convertible type
899 msg << "Cannot connect Python output port with type: " << type->id() ;
900 msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
902 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
904 throw ConversionException(msg.str());
907 //! Adapt a Neutral input port to a Xml output port
909 * \param inport : input port to adapt to Xml type type
910 * \param type : output port type
911 * \return an input port of type InputXmlPort
913 InputPort* RuntimeSALOME::adaptNeutralToXml(InputPort* inport,
916 // BEWARE : using the generic check
917 if(inport->edGetType()->isAdaptable(type))
920 return new XmlNeutral(inport);
922 //non convertible type
924 msg << "Cannot connect Xml output port with type: " << type->id() ;
925 msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
927 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
929 throw ConversionException(msg.str());
932 //! Adapt a Neutral input port to a C++ output port
934 * \param inport : input port to adapt to C++ type type
935 * \param type : output port type
936 * \return an input port of type InputCppPort
938 InputPort* RuntimeSALOME::adaptNeutralToCpp(InputPort* inport,
941 DEBTRACE("RuntimeSALOME::adaptNeutralToCpp(InputPort* inport" );
942 if(isAdaptableNeutralCpp(type,inport->edGetType()))
945 return new CppNeutral(inport);
947 //non convertible type
949 msg << "Cannot connect Cpp output port with type: " << type->id() ;
950 msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
952 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
954 throw ConversionException(msg.str());
957 //! Adapt a Neutral input port to connect it to an output port with a given implementation
959 * \param source : Neutral input port to adapt to implementation impl and type type
960 * \param impl : output port implementation (C++, Python, Corba, Xml or Neutral)
961 * \param type : output port supported type
962 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
963 * \return the adaptated port
965 InputPort* RuntimeSALOME::adaptNeutral(InputPort* source,
966 const std::string& impl,
967 TypeCode * type,bool init)
969 if(impl == CppNode::IMPL_NAME)
971 return adaptNeutralToCpp(source,type);
973 else if(impl == PythonNode::IMPL_NAME)
975 return adaptNeutralToPython(source,type);
977 else if(impl == CORBANode::IMPL_NAME)
979 return adaptNeutralToCorba(source,type);
981 else if(impl == XmlNode::IMPL_NAME )
983 return adaptNeutralToXml(source,type);
985 else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
988 return new NeutralInit(source);
990 return new ProxyPort(source);
993 msg << "Cannot connect InputPort : unknown implementation " << impl;
994 msg << " (" <<__FILE__ << ":" <<__LINE__ << ")";
995 throw ConversionException(msg.str());
998 //! Adapt a XML input port to connect it to a CORBA output port
1000 * \param inport : input port to adapt to CORBA type type
1001 * \param type : type supported by output port
1002 * \return an adaptator port of type InputCorbaPort
1005 InputPort* RuntimeSALOME::adaptXmlToCorba(InputXmlPort* inport,
1008 if(isAdaptableXmlCorba(type,inport->edGetType()))
1010 //output type is convertible to input type
1011 return new CorbaXml(inport);
1013 //output type is not convertible
1015 msg << "Cannot connect Corba output port with type: " << type->id() ;
1016 msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1018 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1020 throw ConversionException(msg.str());
1023 //! Adapt a XML input port to a Python output port
1025 * \param inport : input port to adapt to Python type type
1026 * \param type : output port type
1027 * \return an adaptated input port of type InputPyPort
1029 InputPort* RuntimeSALOME::adaptXmlToPython(InputXmlPort* inport,
1032 if(inport->edGetType()->isAdaptable(type))
1034 //the output data is convertible to inport type
1035 return new PyXml(inport);
1037 //non convertible type
1039 msg << "Cannot connect Python output port with type: " << type->id() ;
1040 msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1042 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1044 throw ConversionException(msg.str());
1047 //! Adapt a XML input port to a C++ output port
1049 * \param inport : input port to adapt to C++ type type
1050 * \param type : output port type
1051 * \return an adaptated input port of type InputPyPort
1053 InputPort* RuntimeSALOME::adaptXmlToCpp(InputXmlPort* inport,
1056 DEBTRACE("RuntimeSALOME::adaptXmlToCpp(InputPort* inport" );
1057 DEBTRACE(type->kind() << " " << inport->edGetType()->kind() );
1058 if(type->isAdaptable(inport->edGetType()))
1060 //the output data is convertible to inport type
1061 return new CppXml(inport);
1063 //non convertible type
1065 msg << "Cannot connect Cpp output port with type: " << type->id() ;
1066 msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1068 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1070 throw ConversionException(msg.str());
1073 //! Adapt a XML input port to a Neutral output port
1075 * \param inport : input port to adapt to Neutral type type
1076 * \param type : output port type
1077 * \return an adaptated input port of type Neutralxxxx
1079 InputPort* RuntimeSALOME::adaptXmlToNeutral(InputXmlPort* inport,
1082 if(inport->edGetType()->isAdaptable(type))
1084 //the output data is convertible to inport type
1085 return new NeutralXml(inport);
1087 //non convertible type
1089 msg << "Cannot connect Xml InputPort to OutputNeutralPort : " ;
1090 msg << "(" <<__FILE__ << ":" <<__LINE__<< ")";
1091 throw ConversionException(msg.str());
1094 //! Adapt a XML input port to a Xml output port
1096 * \param inport : input port to adapt to Xml type type
1097 * \param type : output port type
1098 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1099 * \return an adaptated input port of type Xmlxxxx
1101 InputPort* RuntimeSALOME::adaptXmlToXml(InputXmlPort* inport,
1102 TypeCode * type,bool init)
1105 return new ProxyPort(inport);
1107 if(inport->edGetType()->isAdaptable(type))
1108 return new ProxyPort(inport);
1111 msg << "Cannot connect Xml output port with type: " << type->id() ;
1112 msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1114 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1116 throw ConversionException(msg.str());
1119 //! Adapt an Xml input port to an output port which implementation is given by impl
1121 * \param source : input port to adapt to implementation impl and type type
1122 * \param impl : output port implementation (C++, Python or Corba)
1123 * \param type : output port supported type
1124 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1125 * \return the adaptated port
1128 InputPort* RuntimeSALOME::adapt(InputXmlPort* source,
1129 const std::string& impl,
1130 TypeCode * type,bool init)
1132 if(impl == CORBANode::IMPL_NAME)
1134 return adaptXmlToCorba(source,type);
1136 else if(impl == PythonNode::IMPL_NAME)
1138 return adaptXmlToPython(source,type);
1140 else if(impl == CppNode::IMPL_NAME)
1142 return adaptXmlToCpp(source,type);
1144 else if(impl == XmlNode::IMPL_NAME )
1146 return adaptXmlToXml(source,type,init);
1148 else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1150 return adaptXmlToNeutral(source,type);
1155 msg << "Cannot connect InputXmlPort to " << impl << " implementation";
1156 msg << " (" << __FILE__ << ":" << __LINE__ << ")";
1157 throw ConversionException(msg.str());
1162 //! Adapt a CORBA input port to a CORBA output port
1164 * \param inport : input port to adapt to CORBA outport data type
1165 * \param type : outport data type
1166 * \return an adaptator port of type InputCORBAPort
1168 InputPort* RuntimeSALOME::adaptCorbaToCorba(InputCorbaPort* inport,
1171 if(type->isA(inport->edGetType()))
1173 //types are compatible : no conversion
1174 //outport data type is more specific than inport required type
1175 //so the inport can be used safely
1176 return new ProxyPort(inport);
1178 else if(isAdaptableCorbaCorba(type,inport->edGetType()))
1180 //ouport data can be converted to inport data type
1181 return new CorbaCorba(inport);
1183 //outport data can not be converted
1185 msg << "Cannot connect Corba output port with type: " << type->id() ;
1186 msg << " to CORBA input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1188 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1190 throw ConversionException(msg.str());
1193 //! Adapt a CORBA input port to a Python output port
1195 * \param inport : input port to adapt to Python type type
1196 * \param type : outport data type
1197 * \return an adaptator port of type InputPyPort
1200 InputPort* RuntimeSALOME::adaptCorbaToPython(InputCorbaPort* inport,
1203 if(inport->edGetType()->kind() == Double)
1205 if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaDouble(inport);
1207 else if(inport->edGetType()->kind() == Int)
1209 if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaInt(inport);
1211 else if(inport->edGetType()->kind() == String)
1213 if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaString(inport);
1215 else if(inport->edGetType()->kind() == Bool)
1217 if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaBool(inport);
1219 else if(inport->edGetType()->kind() == Objref )
1221 if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1223 return new PyCorbaObjref(inport);
1228 msg << "Cannot connect Python output port with type: " << type->id() ;
1229 msg << " to CORBA input port " << inport->getName() << " with incompatible objref type: " << inport->edGetType()->id();
1230 msg << " (" << __FILE__ << ":" <<__LINE__ << ")";
1231 throw ConversionException(msg.str());
1234 else if(inport->edGetType()->kind() == Sequence)
1236 if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1238 return new PyCorbaSequence(inport);
1243 msg << "Cannot convert this sequence type " ;
1244 msg << __FILE__ << ":" <<__LINE__;
1245 throw ConversionException(msg.str());
1248 else if(inport->edGetType()->kind() == YACS::ENGINE::Struct)
1250 if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1252 return new PyCorbaStruct(inport);
1257 msg << "Cannot convert this struct type " << type->id() << " to " << inport->edGetType()->id();
1258 msg << __FILE__ << ":" <<__LINE__;
1259 throw ConversionException(msg.str());
1262 // Adaptation not possible
1264 msg << "Cannot connect Python output port with type: " << type->id() ;
1265 msg << " to CORBA input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1267 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1269 throw ConversionException(msg.str());
1272 //! Adapt a CORBA input port to connect it to a XML output port
1274 * \param inport : input port to adapt to Xml type type
1275 * \param type : type supported by output port
1276 * \return an adaptator port of type InputXmlPort
1279 InputPort* RuntimeSALOME::adaptCorbaToXml(InputCorbaPort* inport,
1282 // BEWARE : using the generic check
1283 if(inport->edGetType()->isAdaptable(type))
1285 //output type is convertible to input type
1286 return new XmlCorba(inport);
1288 //output type is not convertible
1290 msg << "Cannot connect Xml output port with type: " << type->id() ;
1291 msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1293 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1295 throw ConversionException(msg.str());
1298 //! Adapt a CORBA input port to a C++ output port
1300 * \param inport : input port to adapt to C++ type type
1301 * \param type : outport data type
1302 * \return an adaptator port of type InputCPPPort
1305 InputPort* RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport,
1308 DEBTRACE("RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport" );
1309 if(isAdaptableCorbaCpp(type,inport->edGetType()))
1311 //output type is convertible to input type
1312 return new CppCorba(inport);
1314 //output type is not convertible
1316 msg << "Cannot connect Cpp output port with type: " << type->id() ;
1317 msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1319 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1321 throw ConversionException(msg.str());
1324 //! Adapt a CORBA input port to a neutral data
1326 * \param inport : InputPort to adapt to Neutral type type
1327 * \param type : outport data type
1328 * \return an adaptator port of type Neutralxxxx
1331 InputPort* RuntimeSALOME::adaptCorbaToNeutral(InputCorbaPort* inport,
1334 if(inport->edGetType()->kind() == Double)
1336 if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaDouble(inport);
1338 else if(inport->edGetType()->kind() == Int)
1340 if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaInt(inport);
1342 else if(inport->edGetType()->kind() == String)
1344 if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaString(inport);
1346 else if(inport->edGetType()->kind() == Bool)
1348 if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaBool(inport);
1350 else if(inport->edGetType()->kind() == Objref)
1352 if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaObjref(inport);
1354 else if(inport->edGetType()->kind() == Sequence)
1356 if(isAdaptableCorbaNeutral(type,inport->edGetType()))
1357 return new NeutralCorbaSequence(inport);
1361 msg << "Cannot convert this sequence type " ;
1362 msg << __FILE__ << ":" <<__LINE__;
1363 throw ConversionException(msg.str());
1366 else if(inport->edGetType()->kind() == Struct)
1368 if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaStruct(inport);
1371 // Adaptation not possible
1373 msg << "Cannot connect Neutral output port with type: " << type->id() ;
1374 msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1376 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1378 throw ConversionException(msg.str());
1381 //! Adapt a CORBA input port to an output which implementation and type are given by impl and type
1383 * \param source : input port to adapt to implementation impl and type type
1384 * \param impl : output port implementation (C++, Python or Corba)
1385 * \param type : outport data type
1386 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1387 * \return an adaptator port which type depends on impl
1390 InputPort* RuntimeSALOME::adapt(InputCorbaPort* source,
1391 const std::string& impl,
1392 TypeCode * type,bool init)
1394 if(impl == CppNode::IMPL_NAME)
1396 return adaptCorbaToCpp(source,type);
1398 else if(impl == PythonNode::IMPL_NAME)
1400 return adaptCorbaToPython(source,type);
1402 else if(impl == CORBANode::IMPL_NAME)
1405 return adaptCorbaToCorba(source,type);
1407 return adaptCorbaToCorba(source,type);
1409 else if(impl == XmlNode::IMPL_NAME )
1411 return adaptCorbaToXml(source,type);
1413 else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1415 return adaptCorbaToNeutral(source,type);
1420 msg << "Cannot connect InputCorbaPort : unknown implementation " ;
1421 msg << __FILE__ << ":" <<__LINE__;
1422 throw ConversionException(msg.str());
1426 //! Adapt a Python input port to a Python output port
1428 * No need to make conversion or cast.
1429 * Only check, it's possible.
1430 * \param inport : InputPort to adapt to Python type type
1431 * \param type : outport data type
1432 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1433 * \return an adaptator port of type InputPyPort
1436 InputPort* RuntimeSALOME::adaptPythonToPython(InputPyPort* inport,
1437 TypeCode * type,bool init)
1440 return new PyInit(inport);
1442 if(isAdaptablePyObjectPyObject(type,inport->edGetType()))
1444 //output data is convertible to input type
1445 //With python, no need to convert. Conversion will be done automatically
1446 //by the interpreter
1447 return new ProxyPort(inport);
1449 //output data is not convertible to input type
1451 msg << "Cannot connect Python output port with type: " << type->id() ;
1452 msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1454 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1456 throw ConversionException(msg.str());
1459 //! Adapt a Python input port to a C++ output port
1461 * \param inport : InputPort to adapt to C++ type type
1462 * \param type : outport data type
1463 * \return an adaptator port of C++ type (InputCppPort)
1466 InputPort* RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport,
1469 DEBTRACE("RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport" );
1470 if(isAdaptablePyObjectCpp(type,inport->edGetType()))
1472 //output type is convertible to input type
1473 return new CppPy(inport);
1475 //output type is not convertible
1477 msg << "Cannot connect Cpp output port with type: " << type->id() ;
1478 msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1480 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1482 throw ConversionException(msg.str());
1485 //! Adapt a Python input port to a Neutral data port
1487 * \param inport : InputPort to adapt to Neutral type type
1488 * \param type : outport data type
1489 * \return an adaptator port of Neutral type (Neutralxxxx)
1492 InputPort* RuntimeSALOME::adaptPythonToNeutral(InputPyPort* inport,
1495 if(inport->edGetType()->kind() == Double)
1497 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyDouble(inport);
1499 else if(inport->edGetType()->kind() == Int)
1501 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyInt(inport);
1503 else if(inport->edGetType()->kind() == String)
1505 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyString(inport);
1507 else if(inport->edGetType()->kind() == Bool)
1509 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyBool(inport);
1511 else if(inport->edGetType()->kind() == Objref)
1513 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyObjref(inport);
1515 else if(inport->edGetType()->kind() == Sequence)
1517 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))
1518 return new NeutralPySequence(inport);
1522 msg << "Cannot convert this sequence type " ;
1523 msg << __FILE__ << ":" <<__LINE__;
1524 throw ConversionException(msg.str());
1527 else if(inport->edGetType()->kind() == Struct)
1529 if(isAdaptablePyObjectNeutral(type,inport->edGetType())) return new NeutralPyStruct(inport);
1532 // Adaptation not possible
1534 msg << "Cannot connect Neutral output port with type: " << type->id() ;
1535 msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1537 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1539 throw ConversionException(msg.str());
1542 //! Adapt a Python input port to a Corba output port
1544 * Always convert the data
1545 * \param inport : InputPort to adapt to Corba type type
1546 * \param type : outport data type
1547 * \return an adaptator port of Corba type (InputCorbaPort)
1550 InputPort* RuntimeSALOME::adaptPythonToCorba(InputPyPort* inport,
1553 if(inport->edGetType()->kind() == Double)
1555 if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyDouble(inport);
1557 else if(inport->edGetType()->kind() == Int)
1559 if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyInt(inport);
1561 else if(inport->edGetType()->kind() == String)
1563 if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyString(inport);
1565 else if(inport->edGetType()->kind() == Bool)
1567 if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyBool(inport);
1569 else if(inport->edGetType()->kind() == Objref)
1571 if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1573 return new CorbaPyObjref(inport);
1578 msg << "Cannot connect InputCorbaPort : incompatible objref types " << type->id() << " " << inport->edGetType()->id();
1579 msg << " " << __FILE__ << ":" <<__LINE__;
1580 throw ConversionException(msg.str());
1583 else if(inport->edGetType()->kind() == Sequence)
1585 if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1587 return new CorbaPySequence(inport);
1592 msg << "Cannot convert this sequence type " ;
1593 msg << __FILE__ << ":" <<__LINE__;
1594 throw ConversionException(msg.str());
1597 else if(inport->edGetType()->kind() == YACS::ENGINE::Struct)
1599 if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1601 return new CorbaPyStruct(inport);
1606 msg << "Cannot convert this struct type " << type->id() << " to " << inport->edGetType()->id();
1607 msg << " " << __FILE__ << ":" <<__LINE__;
1608 throw ConversionException(msg.str());
1611 // Adaptation not possible
1613 msg << "Cannot connect Corba output port with type: " << type->id() ;
1614 msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1616 msg << " ("__FILE__ << ":" << __LINE__ << ")";
1618 throw ConversionException(msg.str());
1621 //! Adapt a Python input port to a Xml output port
1623 * \param inport : input port to adapt to Xml type type
1624 * \param type : output port type
1625 * \return an input port of type InputXmlPort
1628 InputPort* RuntimeSALOME::adaptPythonToXml(InputPyPort* inport,
1631 // BEWARE : using the generic check
1632 if(inport->edGetType()->isAdaptable(type))
1635 return new XmlPython(inport);
1637 //non convertible type
1639 msg << "Cannot connect Xml output port with type: " << type->id() ;
1640 msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1642 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1644 throw ConversionException(msg.str());
1647 //! Adapt a Python input port to an output port with a given implementation
1649 * \param source : input port to adapt to implementation impl and type type
1650 * \param impl : output port implementation (C++, Python or Corba)
1651 * \param type : output port type
1652 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1653 * \return adaptated input port
1656 InputPort* RuntimeSALOME::adapt(InputPyPort* source,
1657 const std::string& impl,
1658 TypeCode * type,bool init)
1660 if(impl == CppNode::IMPL_NAME)
1662 return adaptPythonToCpp(source,type);
1664 else if(impl == PythonNode::IMPL_NAME)
1666 return adaptPythonToPython(source,type,init);
1668 else if(impl == CORBANode::IMPL_NAME)
1670 return adaptPythonToCorba(source,type);
1672 else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1674 return adaptPythonToNeutral(source,type);
1676 else if(impl == XmlNode::IMPL_NAME)
1678 return adaptPythonToXml(source,type);
1683 msg << "Cannot connect InputPyPort : unknown implementation " << impl;
1684 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1685 throw ConversionException(msg.str());
1690 //! Adapt a C++ input port to connect it to a CORBA output port
1692 * \param inport : input port to adapt to CORBA type type
1693 * \param type : type supported by output port
1694 * \return an adaptator port of type InputCorbaPort
1697 InputPort* RuntimeSALOME::adaptCppToCorba(InputCppPort* inport,
1700 DEBTRACE("RuntimeSALOME::adaptCppToCorba(InputCppPort* inport)");
1701 if(isAdaptableCppCorba(type,inport->edGetType()))
1703 //output type is convertible to input type
1704 return new CorbaCpp(inport);
1706 //output type is not convertible
1708 msg << "Cannot connect Corba output port with type: " << type->id() ;
1709 msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1711 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1713 throw ConversionException(msg.str());
1716 //! Adapt a C++ input port to a Python output port
1718 * \param inport : input port to adapt to Python type type
1719 * \param type : output port type
1720 * \return an adaptated input port of type InputPyPort
1722 InputPort* RuntimeSALOME::adaptCppToPython(InputCppPort* inport,
1725 DEBTRACE("RuntimeSALOME::adaptCppToPython(InputCppPort* inport)");
1726 if(isAdaptableCppPyObject(type,inport->edGetType()))
1728 //output type is convertible to input type
1729 return new PyCpp(inport);
1731 //output type is not convertible
1733 msg << "Cannot connect Python output port with type: " << type->id() ;
1734 msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1736 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1738 throw ConversionException(msg.str());
1741 //! Adapt a C++ input port to a C++ output port
1743 * \param inport : input port to adapt to C++ type type
1744 * \param type : output port type
1745 * \return an adaptated input port of type InputPyPort
1747 InputPort* RuntimeSALOME::adaptCppToCpp(InputCppPort* inport,
1750 DEBTRACE("RuntimeSALOME::adaptCppToCpp(InputPort* inport" );
1751 DEBTRACE(type->kind() << " " << inport->edGetType()->kind() );
1752 if(type->isAdaptable(inport->edGetType()))
1754 //the output data is convertible to inport type
1755 return new CppCpp(inport);
1757 //non convertible type
1759 msg << "Cannot connect Cpp output port with type: " << type->id() ;
1760 msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1762 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1764 throw ConversionException(msg.str());
1767 //! Adapt a C++ input port to a Neutral output port
1769 * \param inport : input port to adapt to C++ type type
1770 * \param type : output port type
1771 * \return an adaptated input port of type InputPyPort
1773 InputPort* RuntimeSALOME::adaptCppToNeutral(InputCppPort* inport,
1776 DEBTRACE("RuntimeSALOME::adaptCppToNeutral(InputPort* inport" );
1777 DEBTRACE(type->kind() << " " << inport->edGetType()->kind() );
1778 if(type->isAdaptable(inport->edGetType()))
1780 //the output data is convertible to inport type
1781 return new NeutralCpp(inport);
1783 //non convertible type
1785 msg << "Cannot connect Neutral output port with type: " << type->id() ;
1786 msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1788 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1790 throw ConversionException(msg.str());
1793 InputPort* RuntimeSALOME::adaptCppToXml(InputCppPort* inport,
1796 DEBTRACE("RuntimeSALOME::adaptCppToXml(InputCppPort* inport" );
1797 if(isAdaptableCppXml(type,inport->edGetType()))
1800 return new XmlCpp(inport);
1802 //non convertible type
1804 msg << "Cannot connect Xml output port with type: " << type->id() ;
1805 msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1807 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1809 throw ConversionException(msg.str());
1812 //! Adapt a C++ input port to connect it to an output port with a given implementation
1814 * \param source : input port to adapt to implementation impl and type type
1815 * \param impl : output port implementation (C++, Python or Corba)
1816 * \param type : output port supported type
1817 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1818 * \return the adaptated port
1821 InputPort* RuntimeSALOME::adapt(InputCppPort* source,
1822 const std::string& impl,
1823 TypeCode * type,bool init)
1825 DEBTRACE("RuntimeSALOME::adapt(InputCppPort* source)");
1826 if(impl == CORBANode::IMPL_NAME)
1828 return adaptCppToCorba(source,type);
1830 else if(impl == PythonNode::IMPL_NAME)
1832 return adaptCppToPython(source,type);
1834 else if(impl == XmlNode::IMPL_NAME)
1836 return adaptCppToXml(source,type);
1838 else if(impl == CppNode::IMPL_NAME)
1840 return adaptCppToCpp(source, type);
1842 else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1844 return adaptCppToNeutral(source, type);
1849 msg << "Cannot connect InputCppPort to " << impl << " implementation";
1850 msg << " (" << __FILE__ << ":" << __LINE__ << ")";
1851 throw ConversionException(msg.str());
1855 // bool RuntimeSALOME::isCompatible(const OutputPort* outputPort,
1856 // const InputPort* inputPort)
1858 // bool result=true;
1862 CORBA::ORB_ptr RuntimeSALOME::getOrb() const
1867 PyObject * RuntimeSALOME::getPyOrb() const
1872 PyObject * RuntimeSALOME::getBuiltins() const
1877 DynamicAny::DynAnyFactory_ptr RuntimeSALOME::getDynFactory() const
1882 PyObject * RuntimeSALOME::get_omnipy()
1887 omniORBpyAPI* RuntimeSALOME::getApi()
1892 void* RuntimeSALOME::convertNeutral(TypeCode * type, Any *data)
1895 return (void *)convertNeutralPyObject(type,data);
1899 return (void *)Py_None;
1903 std::string RuntimeSALOME::convertNeutralAsString(TypeCode * type, Any *data)
1908 // The call to PyGILState_Ensure was moved here because there was also
1909 // a crash when calling convertNeutralPyObject with a sequence of pyobj.
1910 // see also the comment below.
1911 PyGILState_STATE gstate = PyGILState_Ensure();
1912 ob=convertNeutralPyObject(type,data);
1913 std::string s=convertPyObjectToString(ob);
1915 // Note (Renaud Barate, 8 jan 2013): With Python 2.7, this call to Py_DECREF causes a crash
1916 // (SIGSEGV) when ob is a sequence and the call is not protected with the global interpreter
1917 // lock. I thus added the call to PyGILState_Ensure / PyGILState_Release. It worked fine in
1918 // Python 2.6 without this call. If anyone finds the real reason of this bug and another fix,
1919 // feel free to change this code.
1920 //PyGILState_STATE gstate = PyGILState_Ensure();
1922 PyGILState_Release(gstate);
1931 std::string RuntimeSALOME::convertPyObjectToString(PyObject* ob)
1933 return YACS::ENGINE::convertPyObjectToString(ob);
1936 PyObject* RuntimeSALOME::convertStringToPyObject(const std::string& s)
1941 PyGILState_STATE gstate = PyGILState_Ensure();
1942 mainmod = PyImport_AddModule("__main__");
1943 globals = PyModule_GetDict(mainmod);
1944 PyObject* d = PyDict_New();
1945 //PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins());
1946 ob= PyRun_String( s.c_str(), Py_eval_input, globals, d);
1952 PyObject* new_stderr = newPyStdOut(error);
1953 PySys_SetObject((char *)"stderr", new_stderr);
1955 PySys_SetObject((char *)"stderr", PySys_GetObject((char *)"__stderr__"));
1956 Py_DECREF(new_stderr);
1957 PyGILState_Release(gstate);
1958 throw Exception(error);
1960 PyGILState_Release(gstate);