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