1 // Copyright (C) 2006-2016 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.hxx"
114 #include "SALOME_LifeCycleCORBA.hxx"
117 #include <libxml/parser.h>
118 #include <omniORB4/CORBA.h>
124 #include "YacsTrace.hxx"
127 using namespace YACS::ENGINE;
129 void RuntimeSALOME::setRuntime(long flags, int argc, char* argv[]) // singleton creation (not thread safe!)
131 if (! Runtime::_singleton)
133 RuntimeSALOME* r=new RuntimeSALOME(flags, argc, argv);
134 Runtime::_singleton = r;
137 DEBTRACE("RuntimeSALOME::setRuntime() done !");
140 RuntimeSALOME* YACS::ENGINE::getSALOMERuntime()
142 YASSERT(RuntimeSALOME::getSingleton());
143 return dynamic_cast< RuntimeSALOME* >(RuntimeSALOME::getSingleton());
147 * Singleton creation, initialize converter map
150 RuntimeSALOME::RuntimeSALOME()
155 void RuntimeSALOME::initBuiltins()
157 //Fill the builtin catalog with nodes specific to the runtime
158 std::map<std::string,TypeCode*>& typeMap=_builtinCatalog->_typeMap;
159 std::map<std::string,Node*>& nodeMap=_builtinCatalog->_nodeMap;
160 std::map<std::string,ComposedNode*>& composednodeMap=_builtinCatalog->_composednodeMap;
161 std::map<std::string,ComponentDefinition*>& componentMap=_builtinCatalog->_componentMap;
162 nodeMap["PyFunction"]=new PyFuncNode("PyFunction");
163 nodeMap["PyScript"]=new PythonNode("PyScript");
164 nodeMap["CORBANode"]=new CORBANode("CORBANode");
165 nodeMap["XmlNode"]=new XmlNode("XmlNode");
166 nodeMap["SalomeNode"]=new SalomeNode("SalomeNode");
167 nodeMap["CppNode"]=new CppNode("CppNode");
168 nodeMap["SalomePythonNode"]=new SalomePythonNode("SalomePythonNode");
169 nodeMap["PresetNode"]=new PresetNode("PresetNode");
170 nodeMap["OutNode"]=new OutNode("OutNode");
171 nodeMap["StudyInNode"]=new StudyInNode("StudyInNode");
172 nodeMap["StudyOutNode"]=new StudyOutNode("StudyOutNode");
173 composednodeMap["OptimizerLoop"]=createOptimizerLoop("OptimizerLoop","","",true);
174 typeMap["dblevec"]= createSequenceTc("dblevec","dblevec",_tc_double);
175 typeMap["intvec"]= createSequenceTc("intvec","intvec",_tc_int);
176 typeMap["stringvec"]= createSequenceTc("stringvec","stringvec",_tc_string);
177 typeMap["boolvec"]= createSequenceTc("boolvec","boolvec",_tc_bool);
178 typeMap["seqdblevec"]= createSequenceTc("seqdblevec","seqdblevec",typeMap["dblevec"]);
179 typeMap["seqintvec"]= createSequenceTc("seqintvec","seqintvec",typeMap["intvec"]);
180 typeMap["seqstringvec"]= createSequenceTc("seqstringvec","seqstringvec",typeMap["stringvec"]);
181 typeMap["seqboolvec"]= createSequenceTc("seqboolvec","seqboolvec",typeMap["boolvec"]);
182 std::list<TypeCodeObjref *> ltc;
183 typeMap["pyobj"]= createInterfaceTc("python:obj:1.0","pyobj",ltc);
184 typeMap["seqpyobj"]= createSequenceTc("seqpyobj","seqpyobj",typeMap["pyobj"]);
185 composednodeMap["Bloc"]=createBloc("Bloc");
186 composednodeMap["Switch"]=createSwitch("Switch");
187 composednodeMap["WhileLoop"]=createWhileLoop("WhileLoop");
188 composednodeMap["ForLoop"]=createForLoop("ForLoop");
189 composednodeMap["ForEachLoop_double"]=createForEachLoop("ForEachLoop_double",Runtime::_tc_double);
190 composednodeMap["ForEachLoop_string"]=createForEachLoop("ForEachLoop_string",Runtime::_tc_string);
191 composednodeMap["ForEachLoop_int"]=createForEachLoop("ForEachLoop_int",Runtime::_tc_int);
192 composednodeMap["ForEachLoop_bool"]=createForEachLoop("ForEachLoop_bool",Runtime::_tc_bool);
193 composednodeMap["ForEachLoop_pyobj"]=createForEachLoop("ForEachLoop_pyobj",typeMap["pyobj"]);;
194 ENGINE::TypeCodeStruct *t = createStructTc("","Engines/dataref");
195 t->addMember("ref",_tc_string);
196 typeMap["dataref"]= t;
199 RuntimeSALOME::RuntimeSALOME(long flags, int argc, char* argv[])
201 // If all flags (apart the IsPyExt flags) are unset, force them to true
202 if ((flags - flags & RuntimeSALOME::IsPyExt) == 0)
203 flags += RuntimeSALOME::UseCorba + RuntimeSALOME::UsePython
204 + RuntimeSALOME::UseCpp + RuntimeSALOME::UseXml;
206 // Salome Nodes implies Corba Nodes
207 if (flags & RuntimeSALOME::UseSalome)
208 flags |= RuntimeSALOME::UseCorba;
210 // Corba Nodes implies Python Nodes
211 if (flags & RuntimeSALOME::UseCorba)
212 flags |= RuntimeSALOME::UsePython;
214 _useCorba = flags & RuntimeSALOME::UseCorba;
215 _usePython = flags & RuntimeSALOME::UsePython;
216 _useCpp = flags & RuntimeSALOME::UseCpp;
217 _useXml = flags & RuntimeSALOME::UseXml;
222 if (_useCpp) _setOfImplementation.insert(CppNode::IMPL_NAME);
223 if (_usePython) _setOfImplementation.insert(PythonNode::IMPL_NAME);
224 if (_useCorba) _setOfImplementation.insert(CORBANode::IMPL_NAME);
225 if (_useXml) _setOfImplementation.insert(XmlNode::IMPL_NAME);
226 init(flags, argc, argv);
229 RuntimeSALOME::~RuntimeSALOME()
231 DEBTRACE("RuntimeSALOME::~RuntimeSALOME");
232 // destroy catalog loader prototypes
233 std::map<std::string, CatalogLoader*>::const_iterator pt;
234 for(pt=_catalogLoaderFactoryMap.begin();pt!=_catalogLoaderFactoryMap.end();pt++)
240 //! CORBA and Python initialization
242 * \param flags contains several bits
243 * bit0 (ispyext) true when method is called from Python
244 * (Python initialization must not be done!)
245 * bit1 (UsePython) true if python nodes are needed
246 * bit1 (UseCorba) true if CORBA nodes are needed
247 * bit1 (UseXml) true if python nodes are needed
248 * bit1 (UseCpp) true if C++ nodes are needed
249 * bit1 (UseSalome) true if Salome nodes are needed
250 * \param argc number of command line arguments (used to initialize the Python interpreter)
251 * \param argv command line arguments (used to initialize the Python interpreter)
255 void RuntimeSALOME::init(long flags, int argc, char* argv[])
257 bool ispyext = flags & RuntimeSALOME::IsPyExt;
260 PortableServer::POA_var root_poa;
261 PortableServer::POAManager_var pman;
262 CORBA::Object_var obj;
263 int nbargs = 0; char **args = 0;
264 _orb = CORBA::ORB_init (nbargs, args);
265 obj = _orb->resolve_initial_references("RootPOA");
266 root_poa = PortableServer::POA::_narrow(obj);
267 pman = root_poa->the_POAManager();
271 DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
273 obj = _orb->resolve_initial_references("DynAnyFactory");
274 _dynFactory = DynamicAny::DynAnyFactory::_narrow(obj);
279 DEBTRACE("RuntimeSALOME::init, is python extension = " << ispyext);
281 // Initialize Python interpreter in embedded mode
282 if (!Py_IsInitialized())
284 #if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0
287 Py_InitializeEx(0); // do not install signal handlers
289 if (argc > 0 && argv != NULL)
291 wchar_t **changed_argv = new wchar_t*[argc];
292 for (int i = 0; i < argc; i++)
294 changed_argv[i] = Py_DecodeLocale(argv[i], NULL);
296 PySys_SetArgv(argc, changed_argv);
302 char defaultName[] = "SALOME_YACS_RUNTIME";
303 wchar_t **changed_pyArgv = new wchar_t*[pyArgc];
304 pyArgv[0] = defaultName;
305 for (int i = 0; i < pyArgc; i++)
307 changed_pyArgv[i] = Py_DecodeLocale(pyArgv[i], NULL);
309 PySys_SetArgv(pyArgc, changed_pyArgv);
311 PyEval_InitThreads(); /* Create (and acquire) the interpreter lock (for threads)*/
312 PyEval_SaveThread(); /* Release the thread state */
313 //here we do not have the Global Interpreter Lock
316 PyObject *mainmod,*pyapi,*res ;
318 PyGILState_STATE gstate;
319 gstate = PyGILState_Ensure(); // acquire the Global Interpreter Lock
321 mainmod = PyImport_AddModule("__main__");
322 globals = PyModule_GetDict(mainmod);
323 /* globals is a borrowed reference */
325 if (PyDict_GetItemString(globals, "__builtins__") == NULL)
327 PyObject *bimod = PyImport_ImportModule("builtins");
328 if (bimod == NULL || PyDict_SetItemString(globals, "__builtins__", bimod) != 0)
329 Py_FatalError("can't add __builtins__ to __main__");
333 _bltins = PyEval_GetBuiltins(); /* borrowed ref */
339 _omnipy = PyImport_ImportModule((char*)"_omnipy");
343 PyErr_SetString(PyExc_ImportError, (char*)"Cannot import _omnipy");
346 pyapi = PyObject_GetAttrString(_omnipy, (char*)"API");
351 _api = (omniORBpyAPI*)PyCapsule_GetPointer(pyapi,"_omnipy.API");
354 res=PyRun_String("\n"
355 "from math import *\n"
357 "sys.path.insert(0,'.')\n"
358 "from omniORB import CORBA\n"
359 "from omniORB import any\n"
360 "orb = CORBA.ORB_init([], CORBA.ORB_ID)\n"
361 "#print(sys.getrefcount(orb))\n"
367 Py_file_input,globals,globals );
375 _pyorb = PyDict_GetItemString(globals,"orb");
376 /* PyDict_GetItemString returns a borrowed reference. There is no need to decref _pyorb */
379 pyany = PyDict_GetItemString(globals,"any");
380 /* PyDict_GetItemString returns a borrowed reference. There is no need to decref pyany */
383 DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
387 PyGILState_Release(gstate); // Release the Global Interpreter Lock
391 // initialize the catalogLoaderFactory map with the session one
392 _catalogLoaderFactoryMap["session"]=new SessionCataLoader;
396 void RuntimeSALOME::fini()
400 PyGILState_STATE gstate = PyGILState_Ensure();
402 DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
404 PyObject *mainmod, *globals;
405 mainmod = PyImport_AddModule("__main__");
406 globals = PyModule_GetDict(mainmod);
410 res=PyRun_String("orb.destroy()\n"
412 Py_file_input,globals,globals );
418 std::map<std::string,Node*>& nodeMap=_builtinCatalog->_nodeMap;
419 delete nodeMap["PyFunction"];
420 delete nodeMap["PyScript"];
421 delete nodeMap["SalomePythonNode"];
422 nodeMap.erase("PyFunction");
423 nodeMap.erase("PyScript");
424 nodeMap.erase("SalomePythonNode");
428 DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
436 DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
443 std::string RuntimeSALOME::getVersion() const
445 #ifdef YACS_DEVELOPMENT
446 return CORBA::string_dup(YACS_VERSION_STR"dev");
448 return CORBA::string_dup(YACS_VERSION_STR);
452 Proc* RuntimeSALOME::createProc(const std::string& name)
454 return new SalomeProc(name);
457 TypeCode * RuntimeSALOME::createInterfaceTc(const std::string& id, const std::string& name,
458 std::list<TypeCodeObjref *> ltc)
461 if(id == "") myName = "IDL:" + name + ":1.0";
463 return TypeCode::interfaceTc(myName.c_str(),name.c_str(),ltc);
466 TypeCode * RuntimeSALOME::createSequenceTc(const std::string& id,
467 const std::string& name,
470 return TypeCode::sequenceTc(id.c_str(),name.c_str(),content);
473 TypeCodeStruct * RuntimeSALOME::createStructTc(const std::string& id, const std::string& name)
476 if(id == "") myName = "IDL:" + name + ":1.0";
478 return (TypeCodeStruct *)TypeCode::structTc(myName.c_str(),name.c_str());
481 Bloc* RuntimeSALOME::createBloc(const std::string& name)
483 return new Bloc(name);
486 WhileLoop* RuntimeSALOME::createWhileLoop(const std::string& name)
488 return new WhileLoop(name);
491 ForLoop* RuntimeSALOME::createForLoop(const std::string& name)
493 return new ForLoop(name);
496 OptimizerLoop* RuntimeSALOME::createOptimizerLoop(const std::string& name,const std::string& algLib,const std::string& factoryName,
497 bool algInitOnFile, const std::string& kind, Proc * procForTypes)
499 OptimizerLoop * ol = (kind == "base") ? new OptimizerLoop(name,algLib,factoryName,algInitOnFile, true, procForTypes) :
500 new SalomeOptimizerLoop(name,algLib,factoryName,algInitOnFile, true, procForTypes);
501 ol->edGetNbOfBranchesPort()->edInit(1);
505 DataNode* RuntimeSALOME::createInDataNode(const std::string& kind,const std::string& name)
510 node = new PresetNode(name);
513 else if(kind == "study" )
515 return new StudyInNode(name);
517 std::string msg="DataNode kind ("+kind+") unknown";
518 throw Exception(msg);
521 DataNode* RuntimeSALOME::createOutDataNode(const std::string& kind,const std::string& name)
525 return new OutNode(name);
527 else if(kind == "study" )
529 return new StudyOutNode(name);
532 std::string msg="OutDataNode kind ("+kind+") unknown";
533 throw Exception(msg);
536 InlineFuncNode* RuntimeSALOME::createFuncNode(const std::string& kind,const std::string& name)
538 InlineFuncNode* node;
539 if(kind == "" || kind == SalomeNode::KIND || kind == PythonNode::KIND)
541 node = new PyFuncNode(name);
544 if(kind == DistributedPythonNode::KIND)
545 return new DistributedPythonNode(name);
546 std::string msg="FuncNode kind ("+kind+") unknown";
547 throw Exception(msg);
550 InlineNode* RuntimeSALOME::createScriptNode(const std::string& kind,const std::string& name)
553 if(kind == "" || kind == SalomeNode::KIND || kind == PythonNode::KIND)
555 node = new PythonNode(name);
558 std::string msg="ScriptNode kind ("+kind+") unknown";
559 throw Exception(msg);
562 ServiceNode* RuntimeSALOME::createRefNode(const std::string& kind,const std::string& name)
565 if(kind == "" || kind == SalomeNode::KIND || kind == CORBANode::KIND)
567 node = new CORBANode(name);
570 else if(kind == XmlNode::KIND)
572 node = new XmlNode(name);
575 std::string msg="RefNode kind ("+kind+") unknown";
576 throw Exception(msg);
579 ServiceNode* RuntimeSALOME::createCompoNode(const std::string& kind,const std::string& name)
582 if(kind == "" || kind == SalomeNode::KIND )
584 node=new SalomeNode(name);
587 else if (kind == CppNode::KIND)
589 node = new CppNode(name);
592 std::string msg="CompoNode kind ("+kind+") unknown";
593 throw Exception(msg);
596 ServiceInlineNode *RuntimeSALOME::createSInlineNode(const std::string& kind, const std::string& name)
598 if(kind == "" || kind == SalomeNode::KIND )
599 return new SalomePythonNode(name);
600 std::string msg="CompoNode kind ("+kind+") unknown";
601 throw Exception(msg);
604 ComponentInstance* RuntimeSALOME::createComponentInstance(const std::string& name,
605 const std::string& kind)
607 ComponentInstance* compo;
608 if(kind == "" || kind == SalomeComponent::KIND)
609 return new SalomeComponent(name);
610 else if(kind == CORBAComponent::KIND)
611 return new CORBAComponent(name);
612 else if(kind == SalomePythonComponent::KIND)
613 return new SalomePythonComponent(name);
614 else if (kind == CppComponent::KIND)
615 return new CppComponent(name);
616 else if (kind == SalomeHPComponent::KIND)
617 return new SalomeHPComponent(name);
618 std::string msg="Component Instance kind ("+kind+") unknown";
619 throw Exception(msg);
622 Container *RuntimeSALOME::createContainer(const std::string& kind)
624 if(kind == "" || kind == SalomeContainer::KIND)
625 return new SalomeContainer;
626 if(kind==SalomeHPContainer::KIND)
627 return new SalomeHPContainer;
628 else if (kind == CppContainer::KIND)
629 return new CppContainer;
630 std::string msg="Container kind ("+kind+") unknown";
631 throw Exception(msg);
634 InputPort * RuntimeSALOME::createInputPort(const std::string& name,
635 const std::string& impl,
639 if(impl == CppNode::IMPL_NAME)
641 return new InputCppPort(name, node, type);
643 else if(impl == PythonNode::IMPL_NAME)
645 return new InputPyPort(name, node, type);
647 else if(impl == CORBANode::IMPL_NAME)
649 return new InputCorbaPort(name, node, type);
651 else if(impl == XmlNode::IMPL_NAME)
653 return new InputXmlPort(name, node, type);
658 msg << "Cannot create " << impl << " InputPort" ;
659 msg << " (" << __FILE__ << ":" << __LINE__ << ")";
660 throw Exception(msg.str());
664 OutputPort * RuntimeSALOME::createOutputPort(const std::string& name,
665 const std::string& impl,
669 if(impl == CppNode::IMPL_NAME)
671 return new OutputCppPort(name, node, type);
673 else if(impl == PythonNode::IMPL_NAME)
675 return new OutputPyPort(name, node, type);
677 else if(impl == CORBANode::IMPL_NAME)
679 return new OutputCorbaPort(name, node, type);
681 else if(impl == XmlNode::IMPL_NAME)
683 return new OutputXmlPort(name, node, type);
688 msg << "Cannot create " << impl << " OutputPort" ;
689 msg << " (" << __FILE__ << ":" << __LINE__ << ")";
690 throw Exception(msg.str());
694 InputDataStreamPort* RuntimeSALOME::createInputDataStreamPort(const std::string& name,
695 Node *node,TypeCode *type)
697 DEBTRACE("createInputDataStreamPort: " << name << " " << type->shortName());
698 if(type->kind() == Objref && std::string(type->shortName(),7) == "CALCIUM")
700 return new InputCalStreamPort(name,node,type);
704 return new InputDataStreamPort(name,node,type);
708 OutputDataStreamPort* RuntimeSALOME::createOutputDataStreamPort(const std::string& name,
709 Node *node,TypeCode *type)
711 DEBTRACE("createOutputDataStreamPort: " << name << " " << type->shortName());
712 if(type->kind() == Objref && std::string(type->shortName(),7) == "CALCIUM")
714 return new OutputCalStreamPort(name,node,type);
718 return new OutputDataStreamPort(name,node,type);
722 //! Main adapter function : adapt an InputPort to be able to connect it to an OutputPort with a possible different implementation
724 * \param source : InputPort to be adapted
725 * \param impl : new implementation (C++, python, CORBA, XML, Neutral)
726 * \param type : data type provided by the InputPort
727 * \param init : indicates if the adapted InputPort will be used for initialization (value true) or not (value false)
729 * \return : adapted InputPort
731 InputPort* RuntimeSALOME::adapt(InputPort* source,
732 const std::string& impl,
733 TypeCode * type,bool init) throw (ConversionException)
735 string imp_source=source->getNode()->getImplementation();
736 if(imp_source == PythonNode::IMPL_NAME)
738 return adapt((InputPyPort*)source,impl,type,init);
740 else if(imp_source == CppNode::IMPL_NAME)
742 return adapt((InputCppPort*)source,impl,type,init);
744 else if(imp_source == CORBANode::IMPL_NAME)
746 return adapt((InputCorbaPort*)source,impl,type,init);
748 else if(imp_source == XmlNode::IMPL_NAME)
750 return adapt((InputXmlPort*)source,impl,type,init);
752 else if(imp_source == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
754 return adaptNeutral(source,impl,type,init);
759 msg << "Cannot adapt " << imp_source << " InputPort to " << impl;
760 msg << " (" << __FILE__ << ":" << __LINE__ << ")";
761 throw ConversionException(msg.str());
765 //! Adapter function for InPropertyPort
767 * \param source : InPropertyPort to be adapted
768 * \param impl : new implementation (C++, python, CORBA, XML, Neutral)
769 * \param type : data type provided by the InPropertyPort
770 * \param init : indicates if the adapted InPropertyPort will be used for initialization (value true) or not (value false)
772 * \return : adapted InputPort
774 InputPort* RuntimeSALOME::adapt(InPropertyPort* source,
775 const std::string& impl,
776 TypeCode * type,bool init) throw (ConversionException)
778 return adaptNeutral((InputPort *)source,impl,type,init);
781 //! Adapt a Neutral input port to a Corba output port
783 * \param inport : Neutral input port to adapt to Corba type type
784 * \param type : output port type
785 * \return an adaptated input port of type InputCorbaPort
787 InputPort* RuntimeSALOME::adaptNeutralToCorba(InputPort* inport,
788 TypeCode * type) throw (ConversionException)
790 // BEWARE : using the generic check
791 if(inport->edGetType()->isAdaptable(type))
793 //the output data is convertible to inport type
794 return new CorbaNeutral(inport);
796 //non convertible type
798 msg << "Cannot connect Corba output port with type: " << type->id() ;
799 msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
801 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
803 throw ConversionException(msg.str());
806 //! Adapt a Neutral input port to a Python output port
808 * \param inport : input port to adapt to Python type type
809 * \param type : output port type
810 * \return an adaptated input port of type InputPyPort
812 InputPort* RuntimeSALOME::adaptNeutralToPython(InputPort* inport,
813 TypeCode * type) throw (ConversionException)
815 // BEWARE : using the generic check
816 if(inport->edGetType()->isAdaptable(type))
819 return new PyNeutral(inport);
821 //last chance : an py output that is seq[objref] can be connected to a neutral input objref (P13268)
822 else if(type->kind()==Sequence && type->contentType()->kind()==Objref && inport->edGetType()->kind()==Objref)
824 return new PyNeutral(inport);
826 //non convertible type
828 msg << "Cannot connect Python output port with type: " << type->id() ;
829 msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
831 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
833 throw ConversionException(msg.str());
836 //! Adapt a Neutral input port to a Xml output port
838 * \param inport : input port to adapt to Xml type type
839 * \param type : output port type
840 * \return an input port of type InputXmlPort
842 InputPort* RuntimeSALOME::adaptNeutralToXml(InputPort* inport,
843 TypeCode * type) throw (ConversionException)
845 // BEWARE : using the generic check
846 if(inport->edGetType()->isAdaptable(type))
849 return new XmlNeutral(inport);
851 //non convertible type
853 msg << "Cannot connect Xml output port with type: " << type->id() ;
854 msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
856 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
858 throw ConversionException(msg.str());
861 //! Adapt a Neutral input port to a C++ output port
863 * \param inport : input port to adapt to C++ type type
864 * \param type : output port type
865 * \return an input port of type InputCppPort
867 InputPort* RuntimeSALOME::adaptNeutralToCpp(InputPort* inport,
868 TypeCode * type) throw (ConversionException)
870 DEBTRACE("RuntimeSALOME::adaptNeutralToCpp(InputPort* inport" );
871 if(isAdaptableNeutralCpp(type,inport->edGetType()))
874 return new CppNeutral(inport);
876 //non convertible type
878 msg << "Cannot connect Cpp output port with type: " << type->id() ;
879 msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
881 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
883 throw ConversionException(msg.str());
886 //! Adapt a Neutral input port to connect it to an output port with a given implementation
888 * \param source : Neutral input port to adapt to implementation impl and type type
889 * \param impl : output port implementation (C++, Python, Corba, Xml or Neutral)
890 * \param type : output port supported type
891 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
892 * \return the adaptated port
894 InputPort* RuntimeSALOME::adaptNeutral(InputPort* source,
895 const std::string& impl,
896 TypeCode * type,bool init) throw (ConversionException)
898 if(impl == CppNode::IMPL_NAME)
900 return adaptNeutralToCpp(source,type);
902 else if(impl == PythonNode::IMPL_NAME)
904 return adaptNeutralToPython(source,type);
906 else if(impl == CORBANode::IMPL_NAME)
908 return adaptNeutralToCorba(source,type);
910 else if(impl == XmlNode::IMPL_NAME )
912 return adaptNeutralToXml(source,type);
914 else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
917 return new NeutralInit(source);
919 return new ProxyPort(source);
922 msg << "Cannot connect InputPort : unknown implementation " << impl;
923 msg << " (" <<__FILE__ << ":" <<__LINE__ << ")";
924 throw ConversionException(msg.str());
927 //! Adapt a XML input port to connect it to a CORBA output port
929 * \param inport : input port to adapt to CORBA type type
930 * \param type : type supported by output port
931 * \return an adaptator port of type InputCorbaPort
934 InputPort* RuntimeSALOME::adaptXmlToCorba(InputXmlPort* inport,
935 TypeCode * type) throw (ConversionException)
937 if(isAdaptableXmlCorba(type,inport->edGetType()))
939 //output type is convertible to input type
940 return new CorbaXml(inport);
942 //output type is not convertible
944 msg << "Cannot connect Corba output port with type: " << type->id() ;
945 msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
947 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
949 throw ConversionException(msg.str());
952 //! Adapt a XML input port to a Python output port
954 * \param inport : input port to adapt to Python type type
955 * \param type : output port type
956 * \return an adaptated input port of type InputPyPort
958 InputPort* RuntimeSALOME::adaptXmlToPython(InputXmlPort* inport,
959 TypeCode * type) throw (ConversionException)
961 if(inport->edGetType()->isAdaptable(type))
963 //the output data is convertible to inport type
964 return new PyXml(inport);
966 //non convertible type
968 msg << "Cannot connect Python output port with type: " << type->id() ;
969 msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
971 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
973 throw ConversionException(msg.str());
976 //! Adapt a XML input port to a C++ output port
978 * \param inport : input port to adapt to C++ type type
979 * \param type : output port type
980 * \return an adaptated input port of type InputPyPort
982 InputPort* RuntimeSALOME::adaptXmlToCpp(InputXmlPort* inport,
983 TypeCode * type) throw (ConversionException)
985 DEBTRACE("RuntimeSALOME::adaptXmlToCpp(InputPort* inport" );
986 DEBTRACE(type->kind() << " " << inport->edGetType()->kind() );
987 if(type->isAdaptable(inport->edGetType()))
989 //the output data is convertible to inport type
990 return new CppXml(inport);
992 //non convertible type
994 msg << "Cannot connect Cpp output port with type: " << type->id() ;
995 msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
997 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
999 throw ConversionException(msg.str());
1002 //! Adapt a XML input port to a Neutral output port
1004 * \param inport : input port to adapt to Neutral type type
1005 * \param type : output port type
1006 * \return an adaptated input port of type Neutralxxxx
1008 InputPort* RuntimeSALOME::adaptXmlToNeutral(InputXmlPort* inport,
1009 TypeCode * type) throw (ConversionException)
1011 if(inport->edGetType()->isAdaptable(type))
1013 //the output data is convertible to inport type
1014 return new NeutralXml(inport);
1016 //non convertible type
1018 msg << "Cannot connect Xml InputPort to OutputNeutralPort : " ;
1019 msg << "(" <<__FILE__ << ":" <<__LINE__<< ")";
1020 throw ConversionException(msg.str());
1023 //! Adapt a XML input port to a Xml output port
1025 * \param inport : input port to adapt to Xml type type
1026 * \param type : output port type
1027 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1028 * \return an adaptated input port of type Xmlxxxx
1030 InputPort* RuntimeSALOME::adaptXmlToXml(InputXmlPort* inport,
1031 TypeCode * type,bool init) throw (ConversionException)
1034 return new ProxyPort(inport);
1036 if(inport->edGetType()->isAdaptable(type))
1037 return new ProxyPort(inport);
1040 msg << "Cannot connect Xml output port with type: " << type->id() ;
1041 msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1043 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1045 throw ConversionException(msg.str());
1048 //! Adapt an Xml input port to an output port which implementation is given by impl
1050 * \param source : input port to adapt to implementation impl and type type
1051 * \param impl : output port implementation (C++, Python or Corba)
1052 * \param type : output port supported type
1053 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1054 * \return the adaptated port
1057 InputPort* RuntimeSALOME::adapt(InputXmlPort* source,
1058 const std::string& impl,
1059 TypeCode * type,bool init) throw (ConversionException)
1061 if(impl == CORBANode::IMPL_NAME)
1063 return adaptXmlToCorba(source,type);
1065 else if(impl == PythonNode::IMPL_NAME)
1067 return adaptXmlToPython(source,type);
1069 else if(impl == CppNode::IMPL_NAME)
1071 return adaptXmlToCpp(source,type);
1073 else if(impl == XmlNode::IMPL_NAME )
1075 return adaptXmlToXml(source,type,init);
1077 else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1079 return adaptXmlToNeutral(source,type);
1084 msg << "Cannot connect InputXmlPort to " << impl << " implementation";
1085 msg << " (" << __FILE__ << ":" << __LINE__ << ")";
1086 throw ConversionException(msg.str());
1091 //! Adapt a CORBA input port to a CORBA output port
1093 * \param inport : input port to adapt to CORBA outport data type
1094 * \param type : outport data type
1095 * \return an adaptator port of type InputCORBAPort
1097 InputPort* RuntimeSALOME::adaptCorbaToCorba(InputCorbaPort* inport,
1098 TypeCode * type) throw (ConversionException)
1100 if(type->isA(inport->edGetType()))
1102 //types are compatible : no conversion
1103 //outport data type is more specific than inport required type
1104 //so the inport can be used safely
1105 return new ProxyPort(inport);
1107 else if(isAdaptableCorbaCorba(type,inport->edGetType()))
1109 //ouport data can be converted to inport data type
1110 return new CorbaCorba(inport);
1112 //outport data can not be converted
1114 msg << "Cannot connect Corba output port with type: " << type->id() ;
1115 msg << " to CORBA input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1117 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1119 throw ConversionException(msg.str());
1122 //! Adapt a CORBA input port to a Python output port
1124 * \param inport : input port to adapt to Python type type
1125 * \param type : outport data type
1126 * \return an adaptator port of type InputPyPort
1129 InputPort* RuntimeSALOME::adaptCorbaToPython(InputCorbaPort* inport,
1130 TypeCode * type) throw (ConversionException)
1132 if(inport->edGetType()->kind() == Double)
1134 if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaDouble(inport);
1136 else if(inport->edGetType()->kind() == Int)
1138 if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaInt(inport);
1140 else if(inport->edGetType()->kind() == String)
1142 if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaString(inport);
1144 else if(inport->edGetType()->kind() == Bool)
1146 if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaBool(inport);
1148 else if(inport->edGetType()->kind() == Objref )
1150 if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1152 return new PyCorbaObjref(inport);
1157 msg << "Cannot connect Python output port with type: " << type->id() ;
1158 msg << " to CORBA input port " << inport->getName() << " with incompatible objref type: " << inport->edGetType()->id();
1159 msg << " (" << __FILE__ << ":" <<__LINE__ << ")";
1160 throw ConversionException(msg.str());
1163 else if(inport->edGetType()->kind() == Sequence)
1165 if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1167 return new PyCorbaSequence(inport);
1172 msg << "Cannot convert this sequence type " ;
1173 msg << __FILE__ << ":" <<__LINE__;
1174 throw ConversionException(msg.str());
1177 else if(inport->edGetType()->kind() == YACS::ENGINE::Struct)
1179 if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1181 return new PyCorbaStruct(inport);
1186 msg << "Cannot convert this struct type " << type->id() << " to " << inport->edGetType()->id();
1187 msg << __FILE__ << ":" <<__LINE__;
1188 throw ConversionException(msg.str());
1191 // Adaptation not possible
1193 msg << "Cannot connect Python output port with type: " << type->id() ;
1194 msg << " to CORBA input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1196 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1198 throw ConversionException(msg.str());
1201 //! Adapt a CORBA input port to connect it to a XML output port
1203 * \param inport : input port to adapt to Xml type type
1204 * \param type : type supported by output port
1205 * \return an adaptator port of type InputXmlPort
1208 InputPort* RuntimeSALOME::adaptCorbaToXml(InputCorbaPort* inport,
1209 TypeCode * type) throw (ConversionException)
1211 // BEWARE : using the generic check
1212 if(inport->edGetType()->isAdaptable(type))
1214 //output type is convertible to input type
1215 return new XmlCorba(inport);
1217 //output type is not convertible
1219 msg << "Cannot connect Xml output port with type: " << type->id() ;
1220 msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1222 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1224 throw ConversionException(msg.str());
1227 //! Adapt a CORBA input port to a C++ output port
1229 * \param inport : input port to adapt to C++ type type
1230 * \param type : outport data type
1231 * \return an adaptator port of type InputCPPPort
1234 InputPort* RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport,
1235 TypeCode * type) throw (ConversionException)
1237 DEBTRACE("RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport" );
1238 if(isAdaptableCorbaCpp(type,inport->edGetType()))
1240 //output type is convertible to input type
1241 return new CppCorba(inport);
1243 //output type is not convertible
1245 msg << "Cannot connect Cpp output port with type: " << type->id() ;
1246 msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1248 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1250 throw ConversionException(msg.str());
1253 //! Adapt a CORBA input port to a neutral data
1255 * \param inport : InputPort to adapt to Neutral type type
1256 * \param type : outport data type
1257 * \return an adaptator port of type Neutralxxxx
1260 InputPort* RuntimeSALOME::adaptCorbaToNeutral(InputCorbaPort* inport,
1261 TypeCode * type) throw (ConversionException)
1263 if(inport->edGetType()->kind() == Double)
1265 if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaDouble(inport);
1267 else if(inport->edGetType()->kind() == Int)
1269 if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaInt(inport);
1271 else if(inport->edGetType()->kind() == String)
1273 if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaString(inport);
1275 else if(inport->edGetType()->kind() == Bool)
1277 if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaBool(inport);
1279 else if(inport->edGetType()->kind() == Objref)
1281 if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaObjref(inport);
1283 else if(inport->edGetType()->kind() == Sequence)
1285 if(isAdaptableCorbaNeutral(type,inport->edGetType()))
1286 return new NeutralCorbaSequence(inport);
1290 msg << "Cannot convert this sequence type " ;
1291 msg << __FILE__ << ":" <<__LINE__;
1292 throw ConversionException(msg.str());
1295 else if(inport->edGetType()->kind() == Struct)
1297 if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaStruct(inport);
1300 // Adaptation not possible
1302 msg << "Cannot connect Neutral output port with type: " << type->id() ;
1303 msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1305 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1307 throw ConversionException(msg.str());
1310 //! Adapt a CORBA input port to an output which implementation and type are given by impl and type
1312 * \param source : input port to adapt to implementation impl and type type
1313 * \param impl : output port implementation (C++, Python or Corba)
1314 * \param type : outport data type
1315 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1316 * \return an adaptator port which type depends on impl
1319 InputPort* RuntimeSALOME::adapt(InputCorbaPort* source,
1320 const std::string& impl,
1321 TypeCode * type,bool init) throw (ConversionException)
1323 if(impl == CppNode::IMPL_NAME)
1325 return adaptCorbaToCpp(source,type);
1327 else if(impl == PythonNode::IMPL_NAME)
1329 return adaptCorbaToPython(source,type);
1331 else if(impl == CORBANode::IMPL_NAME)
1334 return adaptCorbaToCorba(source,type);
1336 return adaptCorbaToCorba(source,type);
1338 else if(impl == XmlNode::IMPL_NAME )
1340 return adaptCorbaToXml(source,type);
1342 else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1344 return adaptCorbaToNeutral(source,type);
1349 msg << "Cannot connect InputCorbaPort : unknown implementation " ;
1350 msg << __FILE__ << ":" <<__LINE__;
1351 throw ConversionException(msg.str());
1355 //! Adapt a Python input port to a Python output port
1357 * No need to make conversion or cast.
1358 * Only check, it's possible.
1359 * \param inport : InputPort to adapt to Python type type
1360 * \param type : outport data type
1361 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1362 * \return an adaptator port of type InputPyPort
1365 InputPort* RuntimeSALOME::adaptPythonToPython(InputPyPort* inport,
1366 TypeCode * type,bool init) throw (ConversionException)
1369 return new PyInit(inport);
1371 if(isAdaptablePyObjectPyObject(type,inport->edGetType()))
1373 //output data is convertible to input type
1374 //With python, no need to convert. Conversion will be done automatically
1375 //by the interpreter
1376 return new ProxyPort(inport);
1378 //output data is not convertible to input type
1380 msg << "Cannot connect Python output port with type: " << type->id() ;
1381 msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1383 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1385 throw ConversionException(msg.str());
1388 //! Adapt a Python input port to a C++ output port
1390 * \param inport : InputPort to adapt to C++ type type
1391 * \param type : outport data type
1392 * \return an adaptator port of C++ type (InputCppPort)
1395 InputPort* RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport,
1396 TypeCode * type) throw (ConversionException)
1398 DEBTRACE("RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport" );
1399 if(isAdaptablePyObjectCpp(type,inport->edGetType()))
1401 //output type is convertible to input type
1402 return new CppPy(inport);
1404 //output type is not convertible
1406 msg << "Cannot connect Cpp output port with type: " << type->id() ;
1407 msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1409 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1411 throw ConversionException(msg.str());
1414 //! Adapt a Python input port to a Neutral data port
1416 * \param inport : InputPort to adapt to Neutral type type
1417 * \param type : outport data type
1418 * \return an adaptator port of Neutral type (Neutralxxxx)
1421 InputPort* RuntimeSALOME::adaptPythonToNeutral(InputPyPort* inport,
1422 TypeCode * type) throw (ConversionException)
1424 if(inport->edGetType()->kind() == Double)
1426 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyDouble(inport);
1428 else if(inport->edGetType()->kind() == Int)
1430 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyInt(inport);
1432 else if(inport->edGetType()->kind() == String)
1434 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyString(inport);
1436 else if(inport->edGetType()->kind() == Bool)
1438 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyBool(inport);
1440 else if(inport->edGetType()->kind() == Objref)
1442 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyObjref(inport);
1444 else if(inport->edGetType()->kind() == Sequence)
1446 if(isAdaptablePyObjectNeutral(type,inport->edGetType()))
1447 return new NeutralPySequence(inport);
1451 msg << "Cannot convert this sequence type " ;
1452 msg << __FILE__ << ":" <<__LINE__;
1453 throw ConversionException(msg.str());
1456 else if(inport->edGetType()->kind() == Struct)
1458 if(isAdaptablePyObjectNeutral(type,inport->edGetType())) return new NeutralPyStruct(inport);
1461 // Adaptation not possible
1463 msg << "Cannot connect Neutral output port with type: " << type->id() ;
1464 msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1466 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1468 throw ConversionException(msg.str());
1471 //! Adapt a Python input port to a Corba output port
1473 * Always convert the data
1474 * \param inport : InputPort to adapt to Corba type type
1475 * \param type : outport data type
1476 * \return an adaptator port of Corba type (InputCorbaPort)
1479 InputPort* RuntimeSALOME::adaptPythonToCorba(InputPyPort* inport,
1480 TypeCode * type) throw (ConversionException)
1482 if(inport->edGetType()->kind() == Double)
1484 if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyDouble(inport);
1486 else if(inport->edGetType()->kind() == Int)
1488 if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyInt(inport);
1490 else if(inport->edGetType()->kind() == String)
1492 if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyString(inport);
1494 else if(inport->edGetType()->kind() == Bool)
1496 if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyBool(inport);
1498 else if(inport->edGetType()->kind() == Objref)
1500 if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1502 return new CorbaPyObjref(inport);
1507 msg << "Cannot connect InputCorbaPort : incompatible objref types " << type->id() << " " << inport->edGetType()->id();
1508 msg << " " << __FILE__ << ":" <<__LINE__;
1509 throw ConversionException(msg.str());
1512 else if(inport->edGetType()->kind() == Sequence)
1514 if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1516 return new CorbaPySequence(inport);
1521 msg << "Cannot convert this sequence type " ;
1522 msg << __FILE__ << ":" <<__LINE__;
1523 throw ConversionException(msg.str());
1526 else if(inport->edGetType()->kind() == YACS::ENGINE::Struct)
1528 if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1530 return new CorbaPyStruct(inport);
1535 msg << "Cannot convert this struct type " << type->id() << " to " << inport->edGetType()->id();
1536 msg << " " << __FILE__ << ":" <<__LINE__;
1537 throw ConversionException(msg.str());
1540 // Adaptation not possible
1542 msg << "Cannot connect Corba output port with type: " << type->id() ;
1543 msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1545 msg << " ("__FILE__ << ":" << __LINE__ << ")";
1547 throw ConversionException(msg.str());
1550 //! Adapt a Python input port to a Xml output port
1552 * \param inport : input port to adapt to Xml type type
1553 * \param type : output port type
1554 * \return an input port of type InputXmlPort
1557 InputPort* RuntimeSALOME::adaptPythonToXml(InputPyPort* inport,
1558 TypeCode * type) throw (ConversionException)
1560 // BEWARE : using the generic check
1561 if(inport->edGetType()->isAdaptable(type))
1564 return new XmlPython(inport);
1566 //non convertible type
1568 msg << "Cannot connect Xml output port with type: " << type->id() ;
1569 msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1571 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1573 throw ConversionException(msg.str());
1576 //! Adapt a Python input port to an output port with a given implementation
1578 * \param source : input port to adapt to implementation impl and type type
1579 * \param impl : output port implementation (C++, Python or Corba)
1580 * \param type : output port type
1581 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1582 * \return adaptated input port
1585 InputPort* RuntimeSALOME::adapt(InputPyPort* source,
1586 const std::string& impl,
1587 TypeCode * type,bool init) throw (ConversionException)
1589 if(impl == CppNode::IMPL_NAME)
1591 return adaptPythonToCpp(source,type);
1593 else if(impl == PythonNode::IMPL_NAME)
1595 return adaptPythonToPython(source,type,init);
1597 else if(impl == CORBANode::IMPL_NAME)
1599 return adaptPythonToCorba(source,type);
1601 else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1603 return adaptPythonToNeutral(source,type);
1605 else if(impl == XmlNode::IMPL_NAME)
1607 return adaptPythonToXml(source,type);
1612 msg << "Cannot connect InputPyPort : unknown implementation " << impl;
1613 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1614 throw ConversionException(msg.str());
1619 //! Adapt a C++ input port to connect it to a CORBA output port
1621 * \param inport : input port to adapt to CORBA type type
1622 * \param type : type supported by output port
1623 * \return an adaptator port of type InputCorbaPort
1626 InputPort* RuntimeSALOME::adaptCppToCorba(InputCppPort* inport,
1627 TypeCode * type) throw (ConversionException)
1629 DEBTRACE("RuntimeSALOME::adaptCppToCorba(InputCppPort* inport)");
1630 if(isAdaptableCppCorba(type,inport->edGetType()))
1632 //output type is convertible to input type
1633 return new CorbaCpp(inport);
1635 //output type is not convertible
1637 msg << "Cannot connect Corba output port with type: " << type->id() ;
1638 msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1640 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1642 throw ConversionException(msg.str());
1645 //! Adapt a C++ input port to a Python output port
1647 * \param inport : input port to adapt to Python type type
1648 * \param type : output port type
1649 * \return an adaptated input port of type InputPyPort
1651 InputPort* RuntimeSALOME::adaptCppToPython(InputCppPort* inport,
1652 TypeCode * type) throw (ConversionException)
1654 DEBTRACE("RuntimeSALOME::adaptCppToPython(InputCppPort* inport)");
1655 if(isAdaptableCppPyObject(type,inport->edGetType()))
1657 //output type is convertible to input type
1658 return new PyCpp(inport);
1660 //output type is not convertible
1662 msg << "Cannot connect Python output port with type: " << type->id() ;
1663 msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1665 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1667 throw ConversionException(msg.str());
1670 //! Adapt a C++ input port to a C++ output port
1672 * \param inport : input port to adapt to C++ type type
1673 * \param type : output port type
1674 * \return an adaptated input port of type InputPyPort
1676 InputPort* RuntimeSALOME::adaptCppToCpp(InputCppPort* inport,
1677 TypeCode * type) throw (ConversionException)
1679 DEBTRACE("RuntimeSALOME::adaptCppToCpp(InputPort* inport" );
1680 DEBTRACE(type->kind() << " " << inport->edGetType()->kind() );
1681 if(type->isAdaptable(inport->edGetType()))
1683 //the output data is convertible to inport type
1684 return new CppCpp(inport);
1686 //non convertible type
1688 msg << "Cannot connect Cpp output port with type: " << type->id() ;
1689 msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1691 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1693 throw ConversionException(msg.str());
1696 //! Adapt a C++ input port to a Neutral output port
1698 * \param inport : input port to adapt to C++ type type
1699 * \param type : output port type
1700 * \return an adaptated input port of type InputPyPort
1702 InputPort* RuntimeSALOME::adaptCppToNeutral(InputCppPort* inport,
1703 TypeCode * type) throw (ConversionException)
1705 DEBTRACE("RuntimeSALOME::adaptCppToNeutral(InputPort* inport" );
1706 DEBTRACE(type->kind() << " " << inport->edGetType()->kind() );
1707 if(type->isAdaptable(inport->edGetType()))
1709 //the output data is convertible to inport type
1710 return new NeutralCpp(inport);
1712 //non convertible type
1714 msg << "Cannot connect Neutral output port with type: " << type->id() ;
1715 msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1717 msg << " ("<<__FILE__ << ":" << __LINE__<<")";
1719 throw ConversionException(msg.str());
1722 InputPort* RuntimeSALOME::adaptCppToXml(InputCppPort* inport,
1723 TypeCode * type) throw (ConversionException)
1725 DEBTRACE("RuntimeSALOME::adaptCppToXml(InputCppPort* inport" );
1726 if(isAdaptableCppXml(type,inport->edGetType()))
1729 return new XmlCpp(inport);
1731 //non convertible type
1733 msg << "Cannot connect Xml 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 connect it to an output port with a given implementation
1743 * \param source : input port to adapt to implementation impl and type type
1744 * \param impl : output port implementation (C++, Python or Corba)
1745 * \param type : output port supported type
1746 * \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1747 * \return the adaptated port
1750 InputPort* RuntimeSALOME::adapt(InputCppPort* source,
1751 const std::string& impl,
1752 TypeCode * type,bool init) throw (ConversionException)
1754 DEBTRACE("RuntimeSALOME::adapt(InputCppPort* source)");
1755 if(impl == CORBANode::IMPL_NAME)
1757 return adaptCppToCorba(source,type);
1759 else if(impl == PythonNode::IMPL_NAME)
1761 return adaptCppToPython(source,type);
1763 else if(impl == XmlNode::IMPL_NAME)
1765 return adaptCppToXml(source,type);
1767 else if(impl == CppNode::IMPL_NAME)
1769 return adaptCppToCpp(source, type);
1771 else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1773 return adaptCppToNeutral(source, type);
1778 msg << "Cannot connect InputCppPort to " << impl << " implementation";
1779 msg << " (" << __FILE__ << ":" << __LINE__ << ")";
1780 throw ConversionException(msg.str());
1784 // bool RuntimeSALOME::isCompatible(const OutputPort* outputPort,
1785 // const InputPort* inputPort)
1787 // bool result=true;
1791 CORBA::ORB_ptr RuntimeSALOME::getOrb()
1796 PyObject * RuntimeSALOME::getPyOrb()
1801 PyObject * RuntimeSALOME::getBuiltins()
1806 DynamicAny::DynAnyFactory_ptr RuntimeSALOME::getDynFactory()
1811 PyObject * RuntimeSALOME::get_omnipy()
1816 omniORBpyAPI* RuntimeSALOME::getApi()
1821 void* RuntimeSALOME::convertNeutral(TypeCode * type, Any *data)
1824 return (void *)convertNeutralPyObject(type,data);
1828 return (void *)Py_None;
1832 std::string RuntimeSALOME::convertNeutralAsString(TypeCode * type, Any *data)
1837 // The call to PyGILState_Ensure was moved here because there was also
1838 // a crash when calling convertNeutralPyObject with a sequence of pyobj.
1839 // see also the comment below.
1840 PyGILState_STATE gstate = PyGILState_Ensure();
1841 ob=convertNeutralPyObject(type,data);
1842 std::string s=convertPyObjectToString(ob);
1844 // Note (Renaud Barate, 8 jan 2013): With Python 2.7, this call to Py_DECREF causes a crash
1845 // (SIGSEGV) when ob is a sequence and the call is not protected with the global interpreter
1846 // lock. I thus added the call to PyGILState_Ensure / PyGILState_Release. It worked fine in
1847 // Python 2.6 without this call. If anyone finds the real reason of this bug and another fix,
1848 // feel free to change this code.
1849 //PyGILState_STATE gstate = PyGILState_Ensure();
1851 PyGILState_Release(gstate);
1860 std::string RuntimeSALOME::convertPyObjectToString(PyObject* ob)
1862 return YACS::ENGINE::convertPyObjectToString(ob);
1865 PyObject* RuntimeSALOME::convertStringToPyObject(const std::string& s)
1870 PyGILState_STATE gstate = PyGILState_Ensure();
1871 mainmod = PyImport_AddModule("__main__");
1872 globals = PyModule_GetDict(mainmod);
1873 PyObject* d = PyDict_New();
1874 //PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins());
1875 ob= PyRun_String( s.c_str(), Py_eval_input, globals, d);
1881 PyObject* new_stderr = newPyStdOut(error);
1882 PySys_SetObject((char *)"stderr", new_stderr);
1884 PySys_SetObject((char *)"stderr", PySys_GetObject((char *)"__stderr__"));
1885 Py_DECREF(new_stderr);
1886 PyGILState_Release(gstate);
1887 throw Exception(error);
1889 PyGILState_Release(gstate);