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