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