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