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