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