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