Salome HOME
Fix a crash when initializing a ForEachLoop_pyobj.
[modules/yacs.git] / src / runtime / RuntimeSALOME.cxx
1 // Copyright (C) 2006-2015  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 //#define REFCNT
21 //
22 #ifdef REFCNT
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>
28 #endif
29
30 #include "yacsconfig.h"
31 #include "YACS_version.h"
32 #include "RuntimeSALOME.hxx"
33 #include "SALOMEDispatcher.hxx"
34 #include "Proc.hxx"
35 #include "TypeCode.hxx"
36 #include "WhileLoop.hxx"
37 #include "ForLoop.hxx"
38 #include "ForEachLoop.hxx"
39 #include "SalomeOptimizerLoop.hxx"
40 #include "Bloc.hxx"
41 #include "InputPort.hxx"
42 #include "OutputPort.hxx"
43 #include "PresetPorts.hxx"
44 #include "InputDataStreamPort.hxx"
45 #include "OutputDataStreamPort.hxx"
46 #include "SalomeProc.hxx"
47 #include "PyStdout.hxx"
48 //Catalog Loaders
49 #include "SessionCataLoader.hxx"
50
51 //Components
52 #include "CORBAComponent.hxx"
53 #include "SalomeComponent.hxx"
54 #include "SalomeHPComponent.hxx"
55 #include "SalomePythonComponent.hxx"
56 #include "CppComponent.hxx"
57
58 #include "SalomeContainer.hxx"
59 #include "CppContainer.hxx"
60 #include "SalomeHPContainer.hxx"
61
62 //Nodes
63 #include "PythonNode.hxx"
64 #include "CORBANode.hxx"
65 #include "XMLNode.hxx"
66 #include "CppNode.hxx"
67 #include "PresetNode.hxx"
68 #include "OutNode.hxx"
69 #include "StudyNodes.hxx"
70 #include "SalomePythonNode.hxx"
71 #include "DistributedPythonNode.hxx"
72
73 //CORBA proxy ports
74 #include "CORBACORBAConv.hxx"
75 #include "CORBAPythonConv.hxx"
76 #include "CORBAXMLConv.hxx"
77 #include "CORBACppConv.hxx"
78 #include "CORBANeutralConv.hxx"
79
80 #include "TypeConversions.hxx"
81 //Python proxy ports
82 #include "PythonCORBAConv.hxx"
83 #include "PythonXMLConv.hxx"
84 #include "PythonCppConv.hxx"
85 #include "PythonNeutralConv.hxx"
86 #include "PythonInitConv.hxx"
87
88 //Neutral proxy ports
89 #include "NeutralCORBAConv.hxx"
90 #include "NeutralPythonConv.hxx"
91 #include "NeutralXMLConv.hxx"
92 #include "NeutralCppConv.hxx"
93 #include "NeutralInitConv.hxx"
94
95 //C++ proxy ports
96 #include "CppCORBAConv.hxx"
97 #include "CppPythonConv.hxx"
98 #include "CppXMLConv.hxx"
99 #include "CppCppConv.hxx"
100 #include "CppNeutralConv.hxx"
101
102 //XML proxy ports
103 #include "XMLCORBAConv.hxx"
104 #include "XMLPythonConv.hxx"
105 #include "XMLCppConv.hxx"
106 #include "XMLNeutralConv.hxx"
107
108 //Calcium specific ports
109 #include "CalStreamPort.hxx"
110
111 #ifdef SALOME_KERNEL
112 #include "SALOME_NamingService.hxx"
113 #include "SALOME_LifeCycleCORBA.hxx"
114 #endif
115   
116 #include <libxml/parser.h>
117 #include <omniORB4/CORBA.h>
118 #include <iostream>
119 #include <sstream>
120 #include <cassert>
121
122 //#define _DEVDEBUG_
123 #include "YacsTrace.hxx"
124
125 using namespace std;
126 using namespace YACS::ENGINE;
127
128 void RuntimeSALOME::setRuntime(long flags, int argc, char* argv[]) // singleton creation (not thread safe!)
129 {
130   if (! Runtime::_singleton)
131     {
132       RuntimeSALOME* r=new RuntimeSALOME(flags, argc, argv);
133       Runtime::_singleton = r;
134       r->initBuiltins();
135     }
136   DEBTRACE("RuntimeSALOME::setRuntime() done !");
137 }
138
139 RuntimeSALOME* YACS::ENGINE::getSALOMERuntime()
140 {
141   YASSERT(Runtime::_singleton);
142   return dynamic_cast< RuntimeSALOME* >(Runtime::_singleton);
143 }
144
145 /**
146  *  Singleton creation, initialize converter map
147  */
148   
149 RuntimeSALOME::RuntimeSALOME()
150 {
151   YASSERT(0);
152 }
153
154 void RuntimeSALOME::initBuiltins()
155 {
156   //Fill the builtin catalog with nodes specific to the runtime
157   std::map<std::string,TypeCode*>& typeMap=_builtinCatalog->_typeMap;
158   std::map<std::string,Node*>& nodeMap=_builtinCatalog->_nodeMap;
159   std::map<std::string,ComposedNode*>& composednodeMap=_builtinCatalog->_composednodeMap;
160   std::map<std::string,ComponentDefinition*>& componentMap=_builtinCatalog->_componentMap;
161   nodeMap["PyFunction"]=new PyFuncNode("PyFunction");
162   nodeMap["PyScript"]=new PythonNode("PyScript");
163   nodeMap["CORBANode"]=new CORBANode("CORBANode");
164   nodeMap["XmlNode"]=new XmlNode("XmlNode");
165   nodeMap["SalomeNode"]=new SalomeNode("SalomeNode");
166   nodeMap["CppNode"]=new CppNode("CppNode");
167   nodeMap["SalomePythonNode"]=new SalomePythonNode("SalomePythonNode");
168   nodeMap["PresetNode"]=new PresetNode("PresetNode");
169   nodeMap["OutNode"]=new OutNode("OutNode");
170   nodeMap["StudyInNode"]=new StudyInNode("StudyInNode");
171   nodeMap["StudyOutNode"]=new StudyOutNode("StudyOutNode");
172   composednodeMap["OptimizerLoop"]=createOptimizerLoop("OptimizerLoop","","",true);
173   typeMap["dblevec"]= createSequenceTc("dblevec","dblevec",_tc_double);
174   typeMap["intvec"]= createSequenceTc("intvec","intvec",_tc_int);
175   typeMap["stringvec"]= createSequenceTc("stringvec","stringvec",_tc_string);
176   typeMap["boolvec"]= createSequenceTc("boolvec","boolvec",_tc_bool);
177   typeMap["seqdblevec"]= createSequenceTc("seqdblevec","seqdblevec",typeMap["dblevec"]);
178   typeMap["seqintvec"]= createSequenceTc("seqintvec","seqintvec",typeMap["intvec"]);
179   typeMap["seqstringvec"]= createSequenceTc("seqstringvec","seqstringvec",typeMap["stringvec"]);
180   typeMap["seqboolvec"]= createSequenceTc("seqboolvec","seqboolvec",typeMap["boolvec"]);
181   std::list<TypeCodeObjref *> ltc;
182   typeMap["pyobj"]= createInterfaceTc("python:obj:1.0","pyobj",ltc);
183   typeMap["seqpyobj"]= createSequenceTc("seqpyobj","seqpyobj",typeMap["pyobj"]);
184   composednodeMap["ForEachLoop_pyobj"]=createForEachLoop("ForEachLoop_pyobj",typeMap["pyobj"]);;
185   ENGINE::TypeCodeStruct *t = createStructTc("","Engines/dataref");
186   t->addMember("ref",_tc_string);
187   typeMap["dataref"]= t;
188 }
189
190 RuntimeSALOME::RuntimeSALOME(long flags, int argc, char* argv[])
191 {
192   // If all flags (apart the IsPyExt flags) are unset, force them to true
193   if ((flags - flags & RuntimeSALOME::IsPyExt) == 0)
194     flags += RuntimeSALOME::UseCorba + RuntimeSALOME::UsePython
195           +  RuntimeSALOME::UseCpp + RuntimeSALOME::UseXml;
196
197   // Salome Nodes implies Corba Nodes
198   if (flags & RuntimeSALOME::UseSalome)
199     flags |= RuntimeSALOME::UseCorba;
200
201   // Corba Nodes implies Python Nodes
202   if (flags & RuntimeSALOME::UseCorba)
203     flags |= RuntimeSALOME::UsePython;
204
205   _useCorba = flags & RuntimeSALOME::UseCorba;
206   _usePython = flags & RuntimeSALOME::UsePython;
207   _useCpp = flags & RuntimeSALOME::UseCpp;
208   _useXml = flags & RuntimeSALOME::UseXml;
209
210   /* Init libxml */
211   xmlInitParser();
212
213   if (_useCpp)    _setOfImplementation.insert(CppNode::IMPL_NAME);
214   if (_usePython) _setOfImplementation.insert(PythonNode::IMPL_NAME);
215   if (_useCorba)  _setOfImplementation.insert(CORBANode::IMPL_NAME);
216   if (_useXml)    _setOfImplementation.insert(XmlNode::IMPL_NAME);
217   init(flags, argc, argv);
218 }
219
220 RuntimeSALOME::~RuntimeSALOME()
221 {
222   DEBTRACE("RuntimeSALOME::~RuntimeSALOME");
223   // destroy catalog loader prototypes
224   std::map<std::string, CatalogLoader*>::const_iterator pt;
225   for(pt=_catalogLoaderFactoryMap.begin();pt!=_catalogLoaderFactoryMap.end();pt++)
226     {
227       delete (*pt).second;
228     }
229 }
230
231 //! CORBA and Python initialization
232 /*!
233  *  \param flags contains several bits
234  *            bit0 (ispyext) true when method is called from Python
235  *                           (Python initialization must not be done!)
236  *            bit1 (UsePython) true if python nodes are needed
237  *            bit1 (UseCorba)  true if CORBA nodes are needed
238  *            bit1 (UseXml)    true if python nodes are needed
239  *            bit1 (UseCpp)    true if C++ nodes are needed
240  *            bit1 (UseSalome) true if Salome nodes are needed
241  *  \param argc number of command line arguments (used to initialize the Python interpreter)
242  *  \param argv command line arguments (used to initialize the Python interpreter)
243  *
244  */
245
246 void RuntimeSALOME::init(long flags, int argc, char* argv[])
247 {
248   bool ispyext = flags & RuntimeSALOME::IsPyExt;
249   if (_useCorba)
250     {
251       PortableServer::POA_var root_poa;
252       PortableServer::POAManager_var pman;
253       CORBA::Object_var obj;
254       int nbargs = 0; char **args = 0;
255       _orb = CORBA::ORB_init (nbargs, args);
256       obj = _orb->resolve_initial_references("RootPOA");
257       root_poa = PortableServer::POA::_narrow(obj);
258       pman = root_poa->the_POAManager();
259       pman->activate();
260
261 #ifdef REFCNT
262       DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
263 #endif
264       obj = _orb->resolve_initial_references("DynAnyFactory");
265       _dynFactory = DynamicAny::DynAnyFactory::_narrow(obj);
266     }
267
268   if (_usePython)
269     {
270       DEBTRACE("RuntimeSALOME::init, is python extension = " << ispyext);
271
272       // Initialize Python interpreter in embedded mode
273       if (!Py_IsInitialized())
274         {
275 #if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0
276           Py_Initialize(); 
277 #else
278           Py_InitializeEx(0); // do not install signal handlers
279 #endif
280           if (argc > 0 && argv != NULL)
281             PySys_SetArgv(argc, argv);
282           else
283             {
284               int pyArgc = 1;
285               char* pyArgv[1];
286               char defaultName[] = "SALOME_YACS_RUNTIME";
287               pyArgv[0] = defaultName;
288               PySys_SetArgv(pyArgc, pyArgv);
289             }
290           PyEval_InitThreads(); /* Create (and acquire) the interpreter lock (for threads)*/
291           PyEval_SaveThread(); /* Release the thread state */
292           //here we do not have the Global Interpreter Lock
293         }
294
295       PyObject *mainmod,*pyapi,*res ;
296       PyObject *globals;
297       PyGILState_STATE gstate;
298       gstate = PyGILState_Ensure(); // acquire the Global Interpreter Lock
299     
300       mainmod = PyImport_AddModule("__main__");
301       globals = PyModule_GetDict(mainmod);
302       /* globals is a borrowed reference */
303   
304       if (PyDict_GetItemString(globals, "__builtins__") == NULL) 
305         {
306           PyObject *bimod = PyImport_ImportModule("__builtin__");
307           if (bimod == NULL || PyDict_SetItemString(globals, "__builtins__", bimod) != 0)
308             Py_FatalError("can't add __builtins__ to __main__");
309           Py_DECREF(bimod);
310         }
311
312       _bltins = PyEval_GetBuiltins();  /* borrowed ref */
313
314       if (_useCorba)
315         {
316
317           //init section
318           _omnipy = PyImport_ImportModule((char*)"_omnipy");
319           if (!_omnipy)
320             {
321               PyErr_Print();
322               PyErr_SetString(PyExc_ImportError, (char*)"Cannot import _omnipy");
323               goto out;
324             }
325           pyapi = PyObject_GetAttrString(_omnipy, (char*)"API");
326           if (!pyapi)
327             {
328               goto out;
329             }
330           _api = (omniORBpyAPI*)PyCObject_AsVoidPtr(pyapi);
331           Py_DECREF(pyapi);
332
333           res=PyRun_String("\n"
334                            "from math import *\n"
335                            "import sys\n"
336                            "sys.path.insert(0,'.')\n"
337                            "from omniORB import CORBA\n"
338                            "from omniORB import any\n"
339                            "orb = CORBA.ORB_init([], CORBA.ORB_ID)\n"
340                            "#print sys.getrefcount(orb)\n"
341                            "try:\n"
342                            "  import SALOME\n"
343                            "except:\n"
344                            "  pass\n"
345                            "\n",
346                            Py_file_input,globals,globals );
347           if(res == NULL)
348             {
349               PyErr_Print();
350               goto out;
351             }
352           Py_DECREF(res);
353
354           _pyorb = PyDict_GetItemString(globals,"orb");
355           /* PyDict_GetItemString returns a borrowed reference. There is no need to decref _pyorb */
356
357           PyObject *pyany;
358           pyany = PyDict_GetItemString(globals,"any");
359           /* PyDict_GetItemString returns a borrowed reference. There is no need to decref pyany */
360
361 #ifdef REFCNT
362           DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
363 #endif
364         }
365       out:
366         PyGILState_Release(gstate); // Release the Global Interpreter Lock
367     }
368   if (_useCorba)
369     {
370       // initialize the catalogLoaderFactory map with the session one
371       _catalogLoaderFactoryMap["session"]=new SessionCataLoader;
372     }
373 }
374
375 void RuntimeSALOME::fini()
376 {
377   if (_usePython)
378     {
379       PyGILState_STATE gstate = PyGILState_Ensure();
380 #ifdef REFCNT
381       DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
382 #endif
383       PyObject *mainmod, *globals;
384       mainmod = PyImport_AddModule("__main__");
385       globals = PyModule_GetDict(mainmod);
386       if (_useCorba)
387         {
388           PyObject* res;
389           res=PyRun_String("orb.destroy()\n"
390                            "\n",
391                            Py_file_input,globals,globals );
392           if(res == NULL)
393             PyErr_Print();
394           else
395             Py_DECREF(res);
396         }
397       std::map<std::string,Node*>& nodeMap=_builtinCatalog->_nodeMap;
398       delete nodeMap["PyFunction"];
399       delete nodeMap["PyScript"];
400       delete nodeMap["SalomePythonNode"];
401       nodeMap.erase("PyFunction");
402       nodeMap.erase("PyScript");
403       nodeMap.erase("SalomePythonNode");
404
405       Py_Finalize();
406 #ifdef REFCNT
407       DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
408 #endif
409     }
410   else
411     {
412       if (_useCorba)
413         {
414 #ifdef REFCNT
415           DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
416 #endif
417           _orb->destroy();
418         }
419     }
420 }
421
422 std::string RuntimeSALOME::getVersion() const
423 {
424 #ifdef YACS_DEVELOPMENT
425   return CORBA::string_dup(YACS_VERSION_STR"dev");
426 #else
427   return CORBA::string_dup(YACS_VERSION_STR);
428 #endif
429 }
430
431 Proc* RuntimeSALOME::createProc(const std::string& name)
432 {
433   return new SalomeProc(name);
434 }
435
436 TypeCode * RuntimeSALOME::createInterfaceTc(const std::string& id, const std::string& name,
437                                             std::list<TypeCodeObjref *> ltc)
438 {
439   std::string myName;
440   if(id == "") myName = "IDL:" + name + ":1.0";
441   else myName = id;
442   return TypeCode::interfaceTc(myName.c_str(),name.c_str(),ltc);
443 }
444
445 TypeCode * RuntimeSALOME::createSequenceTc(const std::string& id,
446                                            const std::string& name,
447                                            TypeCode *content)
448 {
449   return TypeCode::sequenceTc(id.c_str(),name.c_str(),content);
450 };
451
452 TypeCodeStruct * RuntimeSALOME::createStructTc(const std::string& id, const std::string& name)
453 {
454   std::string myName;
455   if(id == "") myName = "IDL:" + name + ":1.0";
456   else myName = id;
457   return (TypeCodeStruct *)TypeCode::structTc(myName.c_str(),name.c_str());
458 }
459
460 Bloc* RuntimeSALOME::createBloc(const std::string& name)
461 {
462   return new Bloc(name);
463 }
464
465 WhileLoop* RuntimeSALOME::createWhileLoop(const std::string& name)
466 {
467   return new WhileLoop(name);
468 }
469
470 ForLoop* RuntimeSALOME::createForLoop(const std::string& name)
471 {
472   return new ForLoop(name);
473 }
474
475 OptimizerLoop* RuntimeSALOME::createOptimizerLoop(const std::string& name,const std::string& algLib,const std::string& factoryName,
476                                                   bool algInitOnFile, const std::string& kind, Proc * procForTypes)
477 {
478   OptimizerLoop * ol = (kind == "base") ? new OptimizerLoop(name,algLib,factoryName,algInitOnFile, true, procForTypes) :
479                                           new SalomeOptimizerLoop(name,algLib,factoryName,algInitOnFile, true, procForTypes);
480   ol->edGetNbOfBranchesPort()->edInit(1);
481   return ol;
482 }
483
484 DataNode* RuntimeSALOME::createInDataNode(const std::string& kind,const std::string& name)
485 {
486   DataNode* node;
487   if(kind == "" )
488     {
489       node = new PresetNode(name);
490       return node;
491     }
492   else if(kind == "study" )
493     {
494       return new StudyInNode(name);
495     }
496   std::string msg="DataNode kind ("+kind+") unknown";
497   throw Exception(msg);
498 }
499
500 DataNode* RuntimeSALOME::createOutDataNode(const std::string& kind,const std::string& name)
501 {
502   if(kind == "" )
503     {
504       return new OutNode(name);
505     }
506   else if(kind == "study" )
507     {
508       return new StudyOutNode(name);
509     }
510
511   std::string msg="OutDataNode kind ("+kind+") unknown";
512   throw Exception(msg);
513 }
514
515 InlineFuncNode* RuntimeSALOME::createFuncNode(const std::string& kind,const std::string& name)
516 {
517   InlineFuncNode* node;
518   if(kind == "" || kind == SalomeNode::KIND || kind == PythonNode::KIND)
519     {
520       node = new PyFuncNode(name);
521       return node;
522     }
523   if(kind == DistributedPythonNode::KIND)
524     return new DistributedPythonNode(name);
525   std::string msg="FuncNode kind ("+kind+") unknown";
526   throw Exception(msg);
527 }
528
529 InlineNode* RuntimeSALOME::createScriptNode(const std::string& kind,const std::string& name)
530 {
531   InlineNode* node;
532   if(kind == "" || kind == SalomeNode::KIND || kind == PythonNode::KIND)
533     {
534       node = new PythonNode(name);
535       return node;
536     }
537   std::string msg="ScriptNode kind ("+kind+") unknown";
538   throw Exception(msg);
539 }
540
541 ServiceNode* RuntimeSALOME::createRefNode(const std::string& kind,const std::string& name)
542 {
543   ServiceNode* node;
544   if(kind == "" || kind == SalomeNode::KIND || kind == CORBANode::KIND)
545     {
546       node = new CORBANode(name);
547       return node;
548     }
549   else if(kind == XmlNode::KIND)
550     {
551       node = new XmlNode(name);
552       return node;
553     }
554   std::string msg="RefNode kind ("+kind+") unknown";
555   throw Exception(msg);
556 }
557
558 ServiceNode* RuntimeSALOME::createCompoNode(const std::string& kind,const std::string& name)
559 {
560   ServiceNode* node;
561   if(kind == "" || kind == SalomeNode::KIND )
562     {
563       node=new SalomeNode(name);
564       return node;
565     }
566   else if (kind == CppNode::KIND) 
567     {
568       node = new CppNode(name);
569       return node;
570     }
571   std::string msg="CompoNode kind ("+kind+") unknown";
572   throw Exception(msg);
573 }
574
575 ServiceInlineNode *RuntimeSALOME::createSInlineNode(const std::string& kind, const std::string& name)
576 {
577   if(kind == "" || kind == SalomeNode::KIND )
578     return new SalomePythonNode(name);
579   std::string msg="CompoNode kind ("+kind+") unknown";
580   throw Exception(msg);
581 }
582
583 ComponentInstance* RuntimeSALOME::createComponentInstance(const std::string& name,
584                                                           const std::string& kind)
585 {
586   ComponentInstance* compo;
587   if(kind == "" || kind == SalomeComponent::KIND) 
588     return new SalomeComponent(name);
589   else if(kind == CORBAComponent::KIND)
590     return new CORBAComponent(name);
591   else if(kind == SalomePythonComponent::KIND)
592     return new SalomePythonComponent(name);
593   else if (kind == CppComponent::KIND)
594     return new CppComponent(name);
595   else if (kind == SalomeHPComponent::KIND)
596     return new SalomeHPComponent(name);
597   std::string msg="Component Instance kind ("+kind+") unknown";
598   throw Exception(msg);
599 }
600
601 Container *RuntimeSALOME::createContainer(const std::string& kind)
602 {
603   if(kind == "" || kind == SalomeContainer::KIND)
604     return new SalomeContainer;
605   if(kind==SalomeHPContainer::KIND)
606     return new SalomeHPContainer;
607   else if (kind == CppContainer::KIND)
608     return new CppContainer;
609   std::string msg="Container kind ("+kind+") unknown";
610   throw Exception(msg);
611 }
612
613 InputPort * RuntimeSALOME::createInputPort(const std::string& name,
614                                            const std::string& impl,
615                                            Node * node,
616                                            TypeCode * type)
617 {
618   if(impl == CppNode::IMPL_NAME)
619     {
620       return new InputCppPort(name, node, type);
621     }
622   else if(impl == PythonNode::IMPL_NAME)
623     {
624       return new InputPyPort(name, node, type);
625     }
626   else if(impl == CORBANode::IMPL_NAME)
627     {
628       return new InputCorbaPort(name, node, type);
629     }
630   else if(impl == XmlNode::IMPL_NAME)
631     {
632       return new InputXmlPort(name, node, type);
633     }
634   else
635     {
636       stringstream msg;
637       msg << "Cannot create " << impl << " InputPort" ;
638       msg << " ("__FILE__ << ":" << __LINE__ << ")";
639       throw Exception(msg.str());
640     }
641 }
642
643 OutputPort * RuntimeSALOME::createOutputPort(const std::string& name,
644                                              const std::string& impl,
645                                              Node * node,
646                                              TypeCode * type)
647 {
648   if(impl == CppNode::IMPL_NAME)
649     {
650       return new OutputCppPort(name, node, type);
651     }
652   else if(impl == PythonNode::IMPL_NAME)
653     {
654       return new OutputPyPort(name, node, type);
655     }
656   else if(impl == CORBANode::IMPL_NAME)
657     {
658       return new OutputCorbaPort(name, node, type);
659     }
660   else if(impl == XmlNode::IMPL_NAME)
661     {
662       return new OutputXmlPort(name, node, type);
663     }
664   else
665     {
666       stringstream msg;
667       msg << "Cannot create " << impl << " OutputPort" ;
668       msg << " ("__FILE__ << ":" << __LINE__ << ")";
669       throw Exception(msg.str());
670     }
671 }
672
673 InputDataStreamPort* RuntimeSALOME::createInputDataStreamPort(const std::string& name,
674                                                               Node *node,TypeCode *type)
675 {
676   DEBTRACE("createInputDataStreamPort: " << name << " " << type->shortName());
677   if(type->kind() == Objref && std::string(type->shortName(),7) == "CALCIUM")
678     {
679       return new InputCalStreamPort(name,node,type);
680     }
681   else
682     {
683       return new InputDataStreamPort(name,node,type);
684     }
685 }
686
687 OutputDataStreamPort* RuntimeSALOME::createOutputDataStreamPort(const std::string& name,
688                                                                 Node *node,TypeCode *type)
689 {
690   DEBTRACE("createOutputDataStreamPort: " << name << " " << type->shortName());
691   if(type->kind() == Objref && std::string(type->shortName(),7) == "CALCIUM")
692     {
693       return new OutputCalStreamPort(name,node,type);
694     }
695   else
696     {
697       return new OutputDataStreamPort(name,node,type);
698     }
699 }
700
701 //! Main adapter function : adapt an InputPort to be able to connect it to an OutputPort with a possible different implementation 
702 /*!
703  *  \param source : InputPort to be adapted
704  *  \param impl : new implementation (C++, python, CORBA, XML, Neutral)
705  *  \param type : data type provided by the InputPort
706  *  \param init : indicates if the adapted InputPort will be used for initialization (value true) or not (value false)
707  * 
708  * \return : adapted InputPort
709  */
710 InputPort* RuntimeSALOME::adapt(InputPort* source,
711                                 const std::string& impl,
712                                 TypeCode * type,bool init) throw (ConversionException)
713 {
714   string imp_source=source->getNode()->getImplementation();
715   if(imp_source == PythonNode::IMPL_NAME)
716     {
717       return adapt((InputPyPort*)source,impl,type,init);
718     }
719   else if(imp_source == CppNode::IMPL_NAME)
720     {
721       return adapt((InputCppPort*)source,impl,type,init);
722     }
723   else if(imp_source == CORBANode::IMPL_NAME)
724     {
725       return adapt((InputCorbaPort*)source,impl,type,init);
726     }
727   else if(imp_source == XmlNode::IMPL_NAME)
728     {
729       return adapt((InputXmlPort*)source,impl,type,init);
730     }
731   else if(imp_source == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
732     {
733       return adaptNeutral(source,impl,type,init);
734     }
735   else
736     {
737       stringstream msg;
738       msg << "Cannot adapt " << imp_source << " InputPort to " << impl;
739       msg << " ("__FILE__ << ":" << __LINE__ << ")";
740       throw ConversionException(msg.str());
741     }
742 }
743
744 //! Adapter function for InPropertyPort
745 /*!
746  *  \param source : InPropertyPort to be adapted
747  *  \param impl : new implementation (C++, python, CORBA, XML, Neutral)
748  *  \param type : data type provided by the InPropertyPort
749  *  \param init : indicates if the adapted InPropertyPort will be used for initialization (value true) or not (value false)
750  * 
751  * \return : adapted InputPort
752  */
753 InputPort* RuntimeSALOME::adapt(InPropertyPort* source,
754                                 const std::string& impl,
755                                 TypeCode * type,bool init) throw (ConversionException)
756 {
757   return adaptNeutral((InputPort *)source,impl,type,init);
758 }
759
760 //! Adapt a Neutral input port to a Corba output port
761 /*!
762  *   \param inport : Neutral input port to adapt to Corba type type
763  *   \param type : output port type
764  *   \return an adaptated input port of type InputCorbaPort
765  */
766 InputPort* RuntimeSALOME::adaptNeutralToCorba(InputPort* inport,
767                       TypeCode * type) throw (ConversionException)
768 {
769   // BEWARE : using the generic check
770   if(inport->edGetType()->isAdaptable(type))
771     {
772       //the output data is convertible to inport type
773       return new CorbaNeutral(inport);
774     }
775   //non convertible type
776   stringstream msg;
777   msg << "Cannot connect Corba output port with type: " << type->id() ;
778   msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
779 #ifdef _DEVDEBUG_
780   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
781 #endif
782   throw ConversionException(msg.str());
783 }
784
785 //! Adapt a Neutral input port to a Python output port
786 /*!
787  *   \param inport : input port to adapt to Python type type
788  *   \param type : output port type
789  *   \return an adaptated input port of type InputPyPort
790  */
791 InputPort* RuntimeSALOME::adaptNeutralToPython(InputPort* inport,
792                       TypeCode * type) throw (ConversionException)
793 {
794   // BEWARE : using the generic check
795   if(inport->edGetType()->isAdaptable(type))
796     {
797       //convertible type
798       return new PyNeutral(inport);
799     }
800   //non convertible type
801   stringstream msg;
802   msg << "Cannot connect Python output port with type: " << type->id() ;
803   msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
804 #ifdef _DEVDEBUG_
805   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
806 #endif
807   throw ConversionException(msg.str());
808 }
809
810 //! Adapt a Neutral input port to a Xml output port 
811 /*!
812  *   \param inport : input port to adapt to Xml type type
813  *   \param type : output port type
814  *   \return an input port of type InputXmlPort
815  */
816 InputPort* RuntimeSALOME::adaptNeutralToXml(InputPort* inport,
817                       TypeCode * type) throw (ConversionException)
818 {
819   // BEWARE : using the generic check
820   if(inport->edGetType()->isAdaptable(type))
821     {
822       //convertible type
823       return new XmlNeutral(inport);
824     }
825   //non convertible type
826   stringstream msg;
827   msg << "Cannot connect Xml output port with type: " << type->id() ;
828   msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
829 #ifdef _DEVDEBUG_
830   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
831 #endif
832   throw ConversionException(msg.str());
833 }
834
835 //! Adapt a Neutral input port to a C++ output port 
836 /*!
837  *   \param inport : input port to adapt to C++ type type
838  *   \param type : output port type
839  *   \return an input port of type InputCppPort
840  */
841 InputPort* RuntimeSALOME::adaptNeutralToCpp(InputPort* inport,
842                       TypeCode * type) throw (ConversionException)
843 {
844   DEBTRACE("RuntimeSALOME::adaptNeutralToCpp(InputPort* inport" );
845   if(isAdaptableNeutralCpp(type,inport->edGetType()))
846     {
847       //convertible type
848       return new CppNeutral(inport);
849     }
850   //non convertible type
851   stringstream msg;
852   msg << "Cannot connect Cpp output port with type: " << type->id() ;
853   msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
854 #ifdef _DEVDEBUG_
855   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
856 #endif
857   throw ConversionException(msg.str());
858 }
859
860 //! Adapt a Neutral input port to connect it to an output port with a given implementation
861 /*!
862  *   \param source : Neutral input port to adapt to implementation impl and type type
863  *   \param impl : output port implementation (C++, Python, Corba, Xml or Neutral)
864  *   \param type : output port supported type
865  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
866  *   \return       the adaptated port
867  */
868 InputPort* RuntimeSALOME::adaptNeutral(InputPort* source,
869                                        const std::string& impl,
870                                        TypeCode * type,bool init) throw (ConversionException)
871 {
872   if(impl == CppNode::IMPL_NAME)
873     {
874       return adaptNeutralToCpp(source,type);
875     }
876   else if(impl == PythonNode::IMPL_NAME)
877     {
878       return adaptNeutralToPython(source,type);
879     }
880   else if(impl == CORBANode::IMPL_NAME)
881     {
882       return adaptNeutralToCorba(source,type);
883     }
884   else if(impl == XmlNode::IMPL_NAME )
885     {
886       return adaptNeutralToXml(source,type);
887     }
888   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
889     {
890       if(init)
891         return new NeutralInit(source);
892       else
893         return new ProxyPort(source);
894     }
895   stringstream msg;
896   msg << "Cannot connect InputPort : unknown implementation " << impl;
897   msg << " (" <<__FILE__ << ":" <<__LINE__ << ")";
898   throw ConversionException(msg.str());
899 }
900
901 //! Adapt a XML input port to connect it to a CORBA output port 
902 /*!
903  *   \param inport : input port to adapt to CORBA type type
904  *   \param type : type supported by output port
905  *   \return an adaptator port of type InputCorbaPort 
906  */
907
908 InputPort* RuntimeSALOME::adaptXmlToCorba(InputXmlPort* inport,
909                                           TypeCode * type) throw (ConversionException)
910 {
911   if(isAdaptableXmlCorba(type,inport->edGetType()))
912     {
913       //output type is convertible to input type
914       return new CorbaXml(inport);
915     }
916   //output type is not convertible
917   stringstream msg;
918   msg << "Cannot connect Corba output port with type: " << type->id() ;
919   msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
920 #ifdef _DEVDEBUG_
921   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
922 #endif
923   throw ConversionException(msg.str());
924 }
925
926 //! Adapt a XML input port to a Python output port
927 /*!
928  *   \param inport : input port to adapt to Python type type
929  *   \param type : output port type
930  *   \return an adaptated input port of type InputPyPort
931  */
932 InputPort* RuntimeSALOME::adaptXmlToPython(InputXmlPort* inport,
933                       TypeCode * type) throw (ConversionException)
934 {
935   if(inport->edGetType()->isAdaptable(type))
936     {
937       //the output data is convertible to inport type
938       return new PyXml(inport);
939     }
940   //non convertible type
941   stringstream msg;
942   msg << "Cannot connect Python output port with type: " << type->id() ;
943   msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
944 #ifdef _DEVDEBUG_
945   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
946 #endif
947   throw ConversionException(msg.str());
948 }
949
950 //! Adapt a XML input port to a C++ output port
951 /*!
952  *   \param inport : input port to adapt to C++ type type
953  *   \param type : output port type
954  *   \return an adaptated input port of type InputPyPort
955  */
956 InputPort* RuntimeSALOME::adaptXmlToCpp(InputXmlPort* inport,
957                       TypeCode * type) throw (ConversionException)
958 {
959   DEBTRACE("RuntimeSALOME::adaptXmlToCpp(InputPort* inport" );
960   DEBTRACE(type->kind() << "   " << inport->edGetType()->kind() );
961   if(type->isAdaptable(inport->edGetType()))
962     {
963       //the output data is convertible to inport type
964       return new CppXml(inport);
965     }
966   //non convertible type
967   stringstream msg;
968   msg << "Cannot connect Cpp output port with type: " << type->id() ;
969   msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
970 #ifdef _DEVDEBUG_
971   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
972 #endif
973   throw ConversionException(msg.str());
974 }
975
976 //! Adapt a XML input port to a Neutral output port
977 /*!
978  *   \param inport : input port to adapt to Neutral type type
979  *   \param type : output port type
980  *   \return an adaptated input port of type Neutralxxxx
981  */
982 InputPort* RuntimeSALOME::adaptXmlToNeutral(InputXmlPort* inport,
983                       TypeCode * type) throw (ConversionException)
984 {
985   if(inport->edGetType()->isAdaptable(type))
986     {
987       //the output data is convertible to inport type
988       return new NeutralXml(inport);
989     }
990   //non convertible type
991   stringstream msg;
992   msg << "Cannot connect Xml InputPort to OutputNeutralPort : " ;
993   msg << "(" <<__FILE__ << ":" <<__LINE__<< ")";
994   throw ConversionException(msg.str());
995 }
996
997 //! Adapt a XML input port to a Xml output port
998 /*!
999  *   \param inport : input port to adapt to Xml type type
1000  *   \param type : output port type
1001  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1002  *   \return an adaptated input port of type Xmlxxxx
1003  */
1004 InputPort* RuntimeSALOME::adaptXmlToXml(InputXmlPort* inport,
1005                       TypeCode * type,bool init) throw (ConversionException)
1006 {
1007   if(init)
1008     return new ProxyPort(inport);
1009
1010   if(inport->edGetType()->isAdaptable(type))
1011     return new ProxyPort(inport);
1012
1013   stringstream msg;
1014   msg << "Cannot connect Xml output port with type: " << type->id() ;
1015   msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1016 #ifdef _DEVDEBUG_
1017   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1018 #endif
1019   throw ConversionException(msg.str());
1020 }
1021
1022 //! Adapt an Xml input port to an output port which implementation is given by impl
1023 /*!
1024  *   \param source : input port to adapt to implementation impl and type type
1025  *   \param impl : output port implementation (C++, Python or Corba)
1026  *   \param type : output port supported type
1027  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1028  *   \return       the adaptated port
1029  */
1030
1031 InputPort* RuntimeSALOME::adapt(InputXmlPort* source,
1032                                 const std::string& impl,
1033                                 TypeCode * type,bool init) throw (ConversionException)
1034 {
1035   if(impl == CORBANode::IMPL_NAME)
1036     {
1037       return adaptXmlToCorba(source,type);
1038     }
1039   else if(impl == PythonNode::IMPL_NAME)
1040     {
1041       return adaptXmlToPython(source,type);
1042     }
1043   else if(impl == CppNode::IMPL_NAME)
1044     {
1045       return adaptXmlToCpp(source,type);
1046     }
1047   else if(impl == XmlNode::IMPL_NAME )
1048     {
1049       return adaptXmlToXml(source,type,init);
1050     }
1051   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1052     {
1053       return adaptXmlToNeutral(source,type);
1054     }
1055   else
1056     {
1057       stringstream msg;
1058       msg << "Cannot connect InputXmlPort to " << impl << " implementation";
1059       msg << " ("__FILE__ << ":" << __LINE__ << ")";
1060       throw ConversionException(msg.str());
1061     }
1062 }
1063
1064
1065 //! Adapt a CORBA input port to a CORBA output port 
1066 /*!
1067  *   \param inport : input port to adapt to CORBA outport data type
1068  *   \param type : outport data type 
1069  *   \return an adaptator port of type InputCORBAPort 
1070  */
1071 InputPort* RuntimeSALOME::adaptCorbaToCorba(InputCorbaPort* inport,
1072                                             TypeCode * type) throw (ConversionException)
1073 {
1074   if(type->isA(inport->edGetType()))
1075     {
1076       //types are compatible : no conversion 
1077       //outport data type is more specific than inport required type
1078       //so the inport can be used safely 
1079       return new ProxyPort(inport);
1080     }
1081   else if(isAdaptableCorbaCorba(type,inport->edGetType()))
1082     {
1083       //ouport data can be converted to inport data type
1084       return new CorbaCorba(inport);
1085     }
1086   //outport data can not be converted
1087   stringstream msg;
1088   msg << "Cannot connect Corba output port with type: " << type->id() ;
1089   msg << " to CORBA input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1090 #ifdef _DEVDEBUG_
1091   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1092 #endif
1093   throw ConversionException(msg.str());
1094 }
1095
1096 //! Adapt a CORBA input port to a Python output port 
1097 /*!
1098  *   \param inport : input port to adapt to Python type type
1099  *   \param type : outport data type 
1100  *   \return an adaptator port of type InputPyPort 
1101  */
1102
1103 InputPort* RuntimeSALOME::adaptCorbaToPython(InputCorbaPort* inport,
1104                                              TypeCode * type) throw (ConversionException)
1105 {
1106   if(inport->edGetType()->kind() == Double)
1107     {
1108       if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaDouble(inport);
1109     }
1110   else if(inport->edGetType()->kind() == Int)
1111     {
1112       if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaInt(inport);
1113     }
1114   else if(inport->edGetType()->kind() == String)
1115     {
1116       if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaString(inport);
1117     }
1118   else if(inport->edGetType()->kind() == Bool)
1119     {
1120       if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaBool(inport);
1121     }
1122   else if(inport->edGetType()->kind() == Objref )
1123     {
1124       if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1125         {
1126           return new PyCorbaObjref(inport);
1127         }
1128       else
1129         {
1130           stringstream msg;
1131           msg << "Cannot connect Python output port with type: " << type->id() ;
1132           msg << " to CORBA input port " << inport->getName() << " with incompatible objref type: " << inport->edGetType()->id();
1133           msg << " (" << __FILE__ << ":" <<__LINE__ << ")";
1134           throw ConversionException(msg.str());
1135         }
1136     }
1137   else if(inport->edGetType()->kind() == Sequence)
1138     {
1139       if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1140         {
1141           return new PyCorbaSequence(inport);
1142         }
1143       else
1144         {
1145           stringstream msg;
1146           msg << "Cannot convert this sequence type " ;
1147           msg << __FILE__ << ":" <<__LINE__;
1148           throw ConversionException(msg.str());
1149         }
1150     }
1151   else if(inport->edGetType()->kind() == YACS::ENGINE::Struct)
1152     {
1153       if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1154         {
1155           return new PyCorbaStruct(inport);
1156         }
1157       else
1158         {
1159           stringstream msg;
1160           msg << "Cannot convert this struct type " << type->id() << " to " << inport->edGetType()->id();
1161           msg << __FILE__ << ":" <<__LINE__;
1162           throw ConversionException(msg.str());
1163         }
1164     }
1165   // Adaptation not possible
1166   stringstream msg;
1167   msg << "Cannot connect Python output port with type: " << type->id() ;
1168   msg << " to CORBA input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1169 #ifdef _DEVDEBUG_
1170   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1171 #endif
1172   throw ConversionException(msg.str());
1173 }
1174
1175 //! Adapt a CORBA input port to connect it to a XML output port 
1176 /*!
1177  *   \param inport : input port to adapt to Xml type type
1178  *   \param type : type supported by output port
1179  *   \return an adaptator port of type InputXmlPort 
1180  */
1181
1182 InputPort* RuntimeSALOME::adaptCorbaToXml(InputCorbaPort* inport,
1183                                           TypeCode * type) throw (ConversionException)
1184 {
1185   // BEWARE : using the generic check
1186   if(inport->edGetType()->isAdaptable(type))
1187     {
1188       //output type is convertible to input type
1189       return new XmlCorba(inport);
1190     }
1191   //output type is not convertible
1192   stringstream msg;
1193   msg << "Cannot connect Xml output port with type: " << type->id() ;
1194   msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1195 #ifdef _DEVDEBUG_
1196   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1197 #endif
1198   throw ConversionException(msg.str());
1199 }
1200
1201 //! Adapt a CORBA input port to a C++ output port 
1202 /*!
1203  *   \param inport : input port to adapt to C++ type type
1204  *   \param type : outport data type 
1205  *   \return an adaptator port of type InputCPPPort 
1206  */
1207
1208 InputPort* RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport,
1209                                           TypeCode * type) throw (ConversionException)
1210 {
1211   DEBTRACE("RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport" );
1212   if(isAdaptableCorbaCpp(type,inport->edGetType()))
1213     {
1214       //output type is convertible to input type
1215       return new CppCorba(inport);
1216     }
1217   //output type is not convertible
1218   stringstream msg;
1219   msg << "Cannot connect Cpp output port with type: " << type->id() ;
1220   msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1221 #ifdef _DEVDEBUG_
1222   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1223 #endif
1224   throw ConversionException(msg.str());
1225 }
1226
1227 //! Adapt a CORBA input port to a neutral data 
1228 /*!
1229  *   \param inport : InputPort to adapt to Neutral type type
1230  *   \param type : outport data type 
1231  *   \return an adaptator port of type Neutralxxxx
1232  */
1233
1234 InputPort* RuntimeSALOME::adaptCorbaToNeutral(InputCorbaPort* inport,
1235                                               TypeCode * type) throw (ConversionException)
1236 {
1237   if(inport->edGetType()->kind() == Double)
1238     {
1239       if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaDouble(inport);
1240     }
1241   else if(inport->edGetType()->kind() == Int)
1242     {
1243       if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaInt(inport);
1244     }
1245   else if(inport->edGetType()->kind() == String)
1246     {
1247       if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaString(inport);
1248     }
1249   else if(inport->edGetType()->kind() == Bool)
1250     {
1251       if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaBool(inport);
1252     }
1253   else if(inport->edGetType()->kind() == Objref)
1254     {
1255       if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaObjref(inport);
1256     }
1257   else if(inport->edGetType()->kind() == Sequence)
1258     {
1259       if(isAdaptableCorbaNeutral(type,inport->edGetType()))
1260         return new NeutralCorbaSequence(inport);
1261       else
1262         {
1263           stringstream msg;
1264           msg << "Cannot convert this sequence type " ;
1265           msg << __FILE__ << ":" <<__LINE__;
1266           throw ConversionException(msg.str());
1267         }
1268     }
1269   else if(inport->edGetType()->kind() == Struct)
1270     {
1271       if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaStruct(inport);
1272     }
1273
1274   // Adaptation not possible
1275   stringstream msg;
1276   msg << "Cannot connect Neutral output port with type: " << type->id() ;
1277   msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1278 #ifdef _DEVDEBUG_
1279   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1280 #endif
1281   throw ConversionException(msg.str());
1282 }
1283
1284 //! Adapt a CORBA input port to an output which implementation and type are given by impl and type
1285 /*!
1286  *   \param source : input port to adapt to implementation impl and type type
1287  *   \param impl : output port implementation (C++, Python or Corba)
1288  *   \param type : outport data type 
1289  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1290  *   \return an adaptator port which type depends on impl
1291  */
1292
1293 InputPort* RuntimeSALOME::adapt(InputCorbaPort* source,
1294                                 const std::string& impl,
1295                                 TypeCode * type,bool init) throw (ConversionException)
1296 {
1297   if(impl == CppNode::IMPL_NAME)
1298     {
1299       return adaptCorbaToCpp(source,type);
1300     }
1301   else if(impl == PythonNode::IMPL_NAME)
1302     {
1303       return adaptCorbaToPython(source,type);
1304     }
1305   else if(impl == CORBANode::IMPL_NAME)
1306     {
1307       if(init)
1308         return adaptCorbaToCorba(source,type);
1309       else
1310         return adaptCorbaToCorba(source,type);
1311     }
1312   else if(impl == XmlNode::IMPL_NAME )
1313     {
1314       return adaptCorbaToXml(source,type);
1315     }
1316   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1317     {
1318       return adaptCorbaToNeutral(source,type);
1319     }
1320   else
1321     {
1322       stringstream msg;
1323       msg << "Cannot connect InputCorbaPort : unknown implementation " ;
1324       msg << __FILE__ << ":" <<__LINE__;
1325       throw ConversionException(msg.str());
1326     }
1327 }
1328
1329 //! Adapt a Python input port to a Python output port
1330 /*!
1331  * No need to make conversion or cast. 
1332  * Only check, it's possible.
1333  *   \param inport : InputPort to adapt to Python type type
1334  *   \param type : outport data type 
1335  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1336  *   \return an adaptator port of type InputPyPort 
1337  */
1338
1339 InputPort* RuntimeSALOME::adaptPythonToPython(InputPyPort* inport,
1340                                               TypeCode * type,bool init) throw (ConversionException)
1341 {
1342   if(init)
1343     return new PyInit(inport);
1344
1345   if(isAdaptablePyObjectPyObject(type,inport->edGetType()))
1346     {
1347       //output data is convertible to input type
1348       //With python, no need to convert. Conversion will be done automatically
1349       //by the interpreter
1350       return new ProxyPort(inport);
1351     }
1352   //output data is not convertible to input type
1353   stringstream msg;
1354   msg << "Cannot connect Python output port with type: " << type->id() ;
1355   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1356 #ifdef _DEVDEBUG_
1357   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1358 #endif
1359   throw ConversionException(msg.str());
1360 }
1361
1362 //! Adapt a Python input port to a C++ output port
1363 /*!
1364  *   \param inport : InputPort to adapt to C++ type type
1365  *   \param type : outport data type 
1366  *   \return an adaptator port of C++ type (InputCppPort)
1367  */
1368
1369 InputPort* RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport,
1370                                            TypeCode * type) throw (ConversionException)
1371 {
1372   DEBTRACE("RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport" );
1373   if(isAdaptablePyObjectCpp(type,inport->edGetType()))
1374     {
1375       //output type is convertible to input type
1376       return new CppPy(inport);
1377     }
1378   //output type is not convertible
1379   stringstream msg;
1380   msg << "Cannot connect Cpp output port with type: " << type->id() ;
1381   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1382 #ifdef _DEVDEBUG_
1383   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1384 #endif
1385   throw ConversionException(msg.str());
1386 }
1387
1388 //! Adapt a Python input port to a Neutral data port
1389 /*!
1390  *   \param inport : InputPort to adapt to Neutral type type
1391  *   \param type : outport data type 
1392  *   \return an adaptator port of Neutral type (Neutralxxxx)
1393  */
1394
1395 InputPort* RuntimeSALOME::adaptPythonToNeutral(InputPyPort* inport,
1396                                                TypeCode * type) throw (ConversionException)
1397 {
1398   if(inport->edGetType()->kind() == Double)
1399     {
1400       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyDouble(inport);
1401     }
1402   else if(inport->edGetType()->kind() == Int)
1403     {
1404       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyInt(inport);
1405     }
1406   else if(inport->edGetType()->kind() == String)
1407     {
1408       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyString(inport);
1409     }
1410   else if(inport->edGetType()->kind() == Bool)
1411     {
1412       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyBool(inport);
1413     }
1414   else if(inport->edGetType()->kind() == Objref)
1415     {
1416       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyObjref(inport);
1417     }
1418   else if(inport->edGetType()->kind() == Sequence)
1419     {
1420       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))
1421         return new NeutralPySequence(inport);
1422       else
1423         {
1424           stringstream msg;
1425           msg << "Cannot convert this sequence type " ;
1426           msg << __FILE__ << ":" <<__LINE__;
1427           throw ConversionException(msg.str());
1428         }
1429     }
1430   else if(inport->edGetType()->kind() == Struct)
1431     {
1432       if(isAdaptablePyObjectNeutral(type,inport->edGetType())) return new NeutralPyStruct(inport);
1433     }
1434
1435   // Adaptation not possible
1436   stringstream msg;
1437   msg << "Cannot connect Neutral output port with type: " << type->id() ;
1438   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1439 #ifdef _DEVDEBUG_
1440   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1441 #endif
1442   throw ConversionException(msg.str());
1443 }
1444
1445 //! Adapt a Python input port to a Corba output port
1446 /*!
1447  * Always convert the data
1448  *   \param inport : InputPort to adapt to Corba type type
1449  *   \param type : outport data type 
1450  *   \return an adaptator port of Corba type (InputCorbaPort)
1451  */
1452
1453 InputPort* RuntimeSALOME::adaptPythonToCorba(InputPyPort* inport,
1454                                              TypeCode * type) throw (ConversionException)
1455 {
1456   if(inport->edGetType()->kind() == Double)
1457     {
1458       if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyDouble(inport);
1459     }
1460   else if(inport->edGetType()->kind() == Int)
1461     {
1462       if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyInt(inport);
1463     }
1464   else if(inport->edGetType()->kind() == String)
1465     {
1466       if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyString(inport);
1467     }
1468   else if(inport->edGetType()->kind() == Bool)
1469     {
1470       if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyBool(inport);
1471     }
1472   else if(inport->edGetType()->kind() == Objref)
1473     {
1474       if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1475         {
1476           return new CorbaPyObjref(inport);
1477         }
1478       else
1479         {
1480           stringstream msg;
1481           msg << "Cannot connect InputCorbaPort : incompatible objref types " << type->id() << " " << inport->edGetType()->id();
1482           msg << " " << __FILE__ << ":" <<__LINE__;
1483           throw ConversionException(msg.str());
1484         }
1485     }
1486   else if(inport->edGetType()->kind() == Sequence)
1487     {
1488       if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1489         {
1490           return new CorbaPySequence(inport);
1491         }
1492       else
1493         {
1494           stringstream msg;
1495           msg << "Cannot convert this sequence type " ;
1496           msg << __FILE__ << ":" <<__LINE__;
1497           throw ConversionException(msg.str());
1498         }
1499     }
1500   else if(inport->edGetType()->kind() == YACS::ENGINE::Struct)
1501     {
1502       if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1503         {
1504           return new CorbaPyStruct(inport);
1505         }
1506       else
1507         {
1508           stringstream msg;
1509           msg << "Cannot convert this struct type " << type->id() << " to " << inport->edGetType()->id();
1510           msg << " " << __FILE__ << ":" <<__LINE__;
1511           throw ConversionException(msg.str());
1512         }
1513     }
1514   // Adaptation not possible
1515   stringstream msg;
1516   msg << "Cannot connect Corba output port with type: " << type->id() ;
1517   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1518 #ifdef _DEVDEBUG_
1519   msg << " ("__FILE__ << ":" << __LINE__ << ")";
1520 #endif
1521   throw ConversionException(msg.str());
1522 }
1523
1524 //! Adapt a Python input port to a Xml output port 
1525 /*!
1526  *   \param inport : input port to adapt to Xml type type
1527  *   \param type : output port type
1528  *   \return an input port of type InputXmlPort
1529  */
1530
1531 InputPort* RuntimeSALOME::adaptPythonToXml(InputPyPort* inport,
1532                                           TypeCode * type) throw (ConversionException)
1533 {
1534   // BEWARE : using the generic check
1535   if(inport->edGetType()->isAdaptable(type))
1536     {
1537       //convertible type
1538       return new XmlPython(inport);
1539     }
1540   //non convertible type
1541   stringstream msg;
1542   msg << "Cannot connect Xml output port with type: " << type->id() ;
1543   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1544 #ifdef _DEVDEBUG_
1545   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1546 #endif
1547   throw ConversionException(msg.str());
1548 }
1549
1550 //! Adapt a Python input port to an output port with a given implementation
1551 /*!
1552  *   \param source : input port to adapt to implementation impl and type type
1553  *   \param impl : output port implementation (C++, Python or Corba)
1554  *   \param type : output port type
1555  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1556  *   \return     adaptated input port
1557  */
1558
1559 InputPort* RuntimeSALOME::adapt(InputPyPort* source,
1560                                 const std::string& impl,
1561                                 TypeCode * type,bool init) throw (ConversionException)
1562 {
1563   if(impl == CppNode::IMPL_NAME)
1564     {
1565       return adaptPythonToCpp(source,type);
1566     }
1567   else if(impl == PythonNode::IMPL_NAME)
1568     {
1569       return adaptPythonToPython(source,type,init);
1570     }
1571   else if(impl == CORBANode::IMPL_NAME)
1572     {
1573       return adaptPythonToCorba(source,type);
1574     }
1575   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1576     {
1577       return adaptPythonToNeutral(source,type);
1578     }
1579   else if(impl == XmlNode::IMPL_NAME)
1580     {
1581       return adaptPythonToXml(source,type);
1582     }
1583   else
1584     {
1585       stringstream msg;
1586       msg << "Cannot connect InputPyPort : unknown implementation " << impl;
1587       msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1588       throw ConversionException(msg.str());
1589     }
1590 }
1591
1592
1593 //! Adapt a C++ input port to connect it to a CORBA output port
1594 /*!
1595  *   \param inport : input port to adapt to CORBA type type
1596  *   \param type : type supported by output port
1597  *   \return an adaptator port of type InputCorbaPort
1598  */
1599
1600 InputPort* RuntimeSALOME::adaptCppToCorba(InputCppPort* inport,
1601                                           TypeCode * type) throw (ConversionException)
1602 {
1603   DEBTRACE("RuntimeSALOME::adaptCppToCorba(InputCppPort* inport)");
1604   if(isAdaptableCppCorba(type,inport->edGetType()))
1605     {
1606       //output type is convertible to input type
1607       return new CorbaCpp(inport);
1608     }
1609   //output type is not convertible
1610   stringstream msg;
1611   msg << "Cannot connect Corba output port with type: " << type->id() ;
1612   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1613 #ifdef _DEVDEBUG_
1614   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1615 #endif
1616   throw ConversionException(msg.str());
1617 }
1618
1619 //! Adapt a C++ input port to a Python output port
1620 /*!
1621  *   \param inport : input port to adapt to Python type type
1622  *   \param type : output port type
1623  *   \return an adaptated input port of type InputPyPort
1624  */
1625 InputPort* RuntimeSALOME::adaptCppToPython(InputCppPort* inport,
1626                       TypeCode * type) throw (ConversionException)
1627 {
1628   DEBTRACE("RuntimeSALOME::adaptCppToPython(InputCppPort* inport)");
1629   if(isAdaptableCppPyObject(type,inport->edGetType()))
1630     {
1631       //output type is convertible to input type
1632       return new PyCpp(inport);
1633     }
1634   //output type is not convertible
1635   stringstream msg;
1636   msg << "Cannot connect Python output port with type: " << type->id() ;
1637   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1638 #ifdef _DEVDEBUG_
1639   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1640 #endif
1641   throw ConversionException(msg.str());
1642 }
1643
1644 //! Adapt a C++ input port to a C++ output port
1645 /*!
1646  *   \param inport : input port to adapt to C++ type type
1647  *   \param type : output port type
1648  *   \return an adaptated input port of type InputPyPort
1649  */
1650 InputPort* RuntimeSALOME::adaptCppToCpp(InputCppPort* inport,
1651                       TypeCode * type) throw (ConversionException)
1652 {
1653   DEBTRACE("RuntimeSALOME::adaptCppToCpp(InputPort* inport" );
1654   DEBTRACE(type->kind() << "   " << inport->edGetType()->kind() );
1655   if(type->isAdaptable(inport->edGetType()))
1656     {
1657       //the output data is convertible to inport type
1658       return new CppCpp(inport);
1659     }
1660   //non convertible type
1661   stringstream msg;
1662   msg << "Cannot connect Cpp output port with type: " << type->id() ;
1663   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1664 #ifdef _DEVDEBUG_
1665   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1666 #endif
1667   throw ConversionException(msg.str());
1668 }
1669
1670 //! Adapt a C++ input port to a Neutral output port
1671 /*!
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
1675  */
1676 InputPort* RuntimeSALOME::adaptCppToNeutral(InputCppPort* inport,
1677                       TypeCode * type) throw (ConversionException)
1678 {
1679   DEBTRACE("RuntimeSALOME::adaptCppToNeutral(InputPort* inport" );
1680   DEBTRACE(type->kind() << "   " << inport->edGetType()->kind() );
1681   if(type->isAdaptable(inport->edGetType()))
1682     {
1683       //the output data is convertible to inport type
1684       return new NeutralCpp(inport);
1685     }
1686   //non convertible type
1687   stringstream msg;
1688   msg << "Cannot connect Neutral output port with type: " << type->id() ;
1689   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1690 #ifdef _DEVDEBUG_
1691   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1692 #endif
1693   throw ConversionException(msg.str());
1694 }
1695
1696 InputPort* RuntimeSALOME::adaptCppToXml(InputCppPort* inport,
1697                       TypeCode * type) throw (ConversionException)
1698 {
1699   DEBTRACE("RuntimeSALOME::adaptCppToXml(InputCppPort* inport" );
1700   if(isAdaptableCppXml(type,inport->edGetType()))
1701     {
1702       //convertible type
1703       return new XmlCpp(inport);
1704     }
1705   //non convertible type
1706   stringstream msg;
1707   msg << "Cannot connect Xml output port with type: " << type->id() ;
1708   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1709 #ifdef _DEVDEBUG_
1710   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1711 #endif
1712    throw ConversionException(msg.str());
1713 }
1714
1715 //! Adapt a C++ input port to connect it to an output port with a given implementation
1716 /*!
1717  *   \param source : input port to adapt to implementation impl and type type
1718  *   \param impl : output port implementation (C++, Python or Corba)
1719  *   \param type : output port supported type
1720  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1721  *   \return       the adaptated port
1722  */
1723
1724 InputPort* RuntimeSALOME::adapt(InputCppPort* source,
1725                                 const std::string& impl,
1726                                 TypeCode * type,bool init) throw (ConversionException)
1727 {
1728   DEBTRACE("RuntimeSALOME::adapt(InputCppPort* source)");
1729   if(impl == CORBANode::IMPL_NAME)
1730     {
1731       return adaptCppToCorba(source,type);
1732     }
1733   else if(impl == PythonNode::IMPL_NAME)
1734     {
1735       return adaptCppToPython(source,type);
1736     }
1737   else if(impl == XmlNode::IMPL_NAME)
1738     {
1739       return adaptCppToXml(source,type);
1740     }
1741   else if(impl == CppNode::IMPL_NAME)
1742     {
1743       return adaptCppToCpp(source, type);
1744     }
1745   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1746     {
1747       return adaptCppToNeutral(source, type);
1748     }
1749   else
1750     {
1751       stringstream msg;
1752       msg << "Cannot connect InputCppPort to " << impl << " implementation";
1753       msg << " ("__FILE__ << ":" << __LINE__ << ")";
1754       throw ConversionException(msg.str());
1755     }
1756 }
1757
1758 // bool RuntimeSALOME::isCompatible(const OutputPort* outputPort, 
1759 //                               const InputPort*  inputPort)
1760 // {
1761 //   bool result=true;
1762 //   return result;
1763 // }
1764
1765 CORBA::ORB_ptr RuntimeSALOME::getOrb()
1766 {
1767   return _orb;
1768 }
1769
1770 PyObject * RuntimeSALOME::getPyOrb()
1771 {
1772   return _pyorb;
1773 }
1774
1775 PyObject * RuntimeSALOME::getBuiltins()
1776 {
1777   return _bltins;
1778 }
1779
1780 DynamicAny::DynAnyFactory_ptr RuntimeSALOME::getDynFactory()
1781 {
1782   return _dynFactory;
1783 }
1784
1785 PyObject * RuntimeSALOME::get_omnipy()
1786 {
1787   return _omnipy;
1788 }
1789
1790 omniORBpyAPI* RuntimeSALOME::getApi()
1791 {
1792   return _api;
1793 }
1794
1795 void* RuntimeSALOME::convertNeutral(TypeCode * type, Any *data)
1796 {
1797   if(data)
1798     return (void *)convertNeutralPyObject(type,data);
1799   else
1800     {
1801       Py_INCREF(Py_None);
1802       return (void *)Py_None;
1803     }
1804 }
1805
1806 std::string RuntimeSALOME::convertNeutralAsString(TypeCode * type, Any *data)
1807 {
1808   PyObject* ob;
1809   if(data)
1810     {
1811       // The call to PyGILState_Ensure was moved here because there was also
1812       // a crash when calling convertNeutralPyObject with a sequence of pyobj.
1813       // see also the comment below.
1814       PyGILState_STATE gstate = PyGILState_Ensure();
1815       ob=convertNeutralPyObject(type,data);
1816       std::string s=convertPyObjectToString(ob);
1817
1818       // Note (Renaud Barate, 8 jan 2013): With Python 2.7, this call to Py_DECREF causes a crash
1819       // (SIGSEGV) when ob is a sequence and the call is not protected with the global interpreter
1820       // lock. I thus added the call to PyGILState_Ensure / PyGILState_Release. It worked fine in
1821       // Python 2.6 without this call. If anyone finds the real reason of this bug and another fix,
1822       // feel free to change this code.
1823       //PyGILState_STATE gstate = PyGILState_Ensure();
1824       Py_DECREF(ob);
1825       PyGILState_Release(gstate);
1826       return s;
1827     }
1828   else
1829     {
1830       return "None";
1831     }
1832 }
1833
1834 std::string RuntimeSALOME::convertPyObjectToString(PyObject* ob)
1835 {
1836   return YACS::ENGINE::convertPyObjectToString(ob);
1837 }
1838
1839 PyObject* RuntimeSALOME::convertStringToPyObject(const std::string& s)
1840 {
1841   PyObject *mainmod;
1842   PyObject *globals;
1843   PyObject* ob;
1844   PyGILState_STATE gstate = PyGILState_Ensure();
1845   mainmod = PyImport_AddModule("__main__");
1846   globals = PyModule_GetDict(mainmod);
1847   PyObject* d = PyDict_New();
1848   //PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins());
1849   ob= PyRun_String( s.c_str(), Py_eval_input, globals, d);
1850   Py_DECREF(d);
1851   if(ob==NULL)
1852     {
1853       //exception
1854       std::string error;
1855       PyObject* new_stderr = newPyStdOut(error);
1856       PySys_SetObject((char *)"stderr", new_stderr);
1857       PyErr_Print();
1858       PySys_SetObject((char *)"stderr", PySys_GetObject((char *)"__stderr__"));
1859       Py_DECREF(new_stderr);
1860       PyGILState_Release(gstate);
1861       throw Exception(error);
1862     }
1863   PyGILState_Release(gstate);
1864   return ob;
1865 }