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