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