Salome HOME
d79209674d296cd8a4364bd0efc5f126a0bc2cf4
[modules/yacs.git] / src / runtime / CORBAPorts.cxx
1 // Copyright (C) 2006-2021  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 #endif
28
29 #include "RuntimeSALOME.hxx"
30 #include "TypeConversions.hxx"
31 #include "TypeCode.hxx"
32 #include "AutoLocker.hxx"
33 #include "CORBAPorts.hxx"
34 #include "PythonPorts.hxx"
35 #include "ServiceNode.hxx"
36 #include "ComponentInstance.hxx"
37 #include "SALOME_GenericObj.hh"
38
39 #include <iostream>
40 #include <sstream>
41
42 //#define _DEVDEBUG_
43 #include "YacsTrace.hxx"
44
45 using namespace YACS::ENGINE;
46 using namespace std;
47
48 void releaseObj(CORBA::Any& data)
49 {
50   CORBA::Object_var obj;
51   if(data >>= CORBA::Any::to_object(obj))
52     {
53       SALOME::GenericObj_var gobj;
54       try
55         {
56           gobj=SALOME::GenericObj::_narrow(obj);
57         }
58       catch(const CORBA::SystemException& )
59         {
60           return;
61         }
62       if(!CORBA::is_nil(gobj))
63         {
64           DEBTRACE("It's a SALOME::GenericObj");
65           gobj->UnRegister();
66         }
67       else
68           DEBTRACE("It's a CORBA::Object but not a SALOME::GenericObj");
69     }
70   else
71     DEBTRACE("It's not a CORBA::Object");
72 }
73
74 void registerObj(CORBA::Any& data)
75 {
76   CORBA::Object_var obj;
77   if(data >>= CORBA::Any::to_object(obj))
78     {
79       SALOME::GenericObj_var gobj;
80       try
81         {
82           gobj=SALOME::GenericObj::_narrow(obj);
83         }
84       catch(const CORBA::SystemException& )
85         {
86           return;
87         }
88       if(!CORBA::is_nil(gobj))
89         {
90           DEBTRACE("It's a SALOME::GenericObj");
91           gobj->Register();
92         }
93       else
94           DEBTRACE("It's a CORBA::Object but not a SALOME::GenericObj");
95     }
96   else
97     DEBTRACE("It's not a CORBA::Object");
98 }
99
100 InputCorbaPort::InputCorbaPort(const std::string& name,
101                                Node *node,
102                                TypeCode * type)
103   : InputPort(name, node, type), DataPort(name, node, type), Port(node), _initData(0)
104 {
105   _orb = getSALOMERuntime()->getOrb();
106 }
107
108 InputCorbaPort::InputCorbaPort(const InputCorbaPort& other, Node *newHelder):InputPort(other,newHelder),DataPort(other,newHelder),Port(other,newHelder),
109                                                                              _initData(0)
110 {
111   _orb = getSALOMERuntime()->getOrb();
112   if(other._initData)
113     {
114       _initData=new CORBA::Any;
115       *_initData=*(other._initData);
116     }
117   _data=other._data;
118 }
119
120 InputCorbaPort::~InputCorbaPort()
121 {
122   delete _initData;
123   // Release or not release : all GenericObj are deleted when the input port is deleted
124   releaseObj(_data);
125 }
126
127 bool InputCorbaPort::edIsManuallyInitialized() const
128 {
129   return _initData!=0;
130 }
131
132 void InputCorbaPort::edRemoveManInit()
133 {
134   delete _initData;
135   _initData=0;
136   InputPort::edRemoveManInit();
137 }
138
139 void InputCorbaPort::put(const void *data)
140 {
141   put((CORBA::Any *)data);
142 }
143
144 void display(CORBA::Any* data)
145 {
146   CORBA::TypeCode_var tc=data->type();
147   switch(tc->kind())
148     {
149     case CORBA::tk_double:
150       CORBA::Double d;
151       *data >>= d;
152       DEBTRACE( "Double: " << d );
153       break;
154     case CORBA::tk_long:
155       CORBA::Long l;
156       *data >>= l;
157       DEBTRACE( "Int: " << l );
158       break;
159     default:
160       break;
161     }
162 }
163
164 void InputCorbaPort::releaseData()
165 {//do nothing - to be implemented
166 }
167
168 void InputCorbaPort::put(CORBA::Any *data)
169 {
170 #ifdef REFCNT
171   DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)data->pd_tc.in())->pd_ref_count);
172 #endif
173   YACS::BASES::AutoLocker<YACS::BASES::Mutex> lock(&_mutex);
174 #ifdef _DEVDEBUG_
175   display(data);
176 #endif
177
178   releaseObj(_data);
179
180   // make a copy of the any (protect against deletion of any source)
181   _data=*data;
182   _stringRef="";
183
184   registerObj(_data);
185
186 #ifdef REFCNT
187   DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)_data.pd_tc.in())->pd_ref_count);
188 #endif
189 }
190
191 InputPort *InputCorbaPort::clone(Node *newHelder) const
192 {
193   return new InputCorbaPort(*this,newHelder);
194 }
195
196 void *InputCorbaPort::get() const 
197 {
198   return (void *)&_data;
199 }
200
201 bool InputCorbaPort::isEmpty()
202 {
203   CORBA::TypeCode_var tc=_data.type();
204   return tc->equivalent(CORBA::_tc_null);
205 }
206
207 CORBA::Any * InputCorbaPort::getAny()
208 {
209   // --- return a pointer to internal any
210   return &_data;
211 }
212
213 PyObject * InputCorbaPort::getPyObj()
214 {
215   YACS::BASES::AutoLocker<YACS::BASES::Mutex> lock(&_mutex);
216   CORBA::TypeCode_var tc=getAny()->type();
217   if (!tc->equivalent(CORBA::_tc_null))
218     return convertCorbaPyObject(edGetType(),getAny());
219   else
220     {
221       Py_INCREF(Py_None);
222       return Py_None;
223     }
224 }
225
226 std::string InputCorbaPort::getAsString()
227 {
228   InterpreterUnlocker loc;
229   PyObject* ob=getPyObj();
230   std::string s=convertPyObjectToString(ob);
231   Py_DECREF(ob);
232   return s;
233 }
234
235
236 //! Save the current data value for further reinitialization of the port
237 /*!
238  *
239  */
240 void InputCorbaPort::exSaveInit()
241 {
242   if(_initData)
243     delete _initData;
244   _initData=new CORBA::Any;
245   *_initData=_data;
246 }
247
248 //! Restore the saved data value to current data value
249 /*!
250  * If no data has been saved (_initData == 0) don't restore
251  */
252 void InputCorbaPort::exRestoreInit()
253 {
254   if(!_initData)return;
255   put(_initData);
256 }
257
258 std::string InputCorbaPort::dump()
259 {
260   CORBA::TypeCode_var tc=_data.type();
261   if (tc->equivalent(CORBA::_tc_null))
262     return "<value>nil</value>";
263   if (edGetType()->kind() != YACS::ENGINE::Objref)
264     return convertCorbaXml(edGetType(), &_data);
265   if (! _stringRef.empty())
266     return _stringRef;
267   else 
268     return convertCorbaXml(edGetType(), &_data);
269 //     {
270 //       stringstream msg;
271 //       msg << "Cannot retreive init string reference string for port " << _name
272 //           << " on node " << _node->getName();
273 //       throw Exception(msg.str());      
274 //     }
275 }
276
277 std::string InputCorbaPort::valToStr()
278 {
279   int isString = PyBytes_Check(getPyObj());
280   PyObject *strPyObj = PyObject_Str(getPyObj());
281   string val = PyBytes_AsString(strPyObj);
282   if (isString)
283     val = "\"" + val + "\"";
284   Py_DECREF(strPyObj);
285   return val;
286 }
287
288 void InputCorbaPort::valFromStr(std::string valstr)
289 {
290 }
291
292 OutputCorbaPort::OutputCorbaPort(const std::string& name,
293                                  Node *node,
294                                  TypeCode * type)
295   : OutputPort(name, node, type), DataPort(name, node, type), Port(node)
296 {
297   _orb = getSALOMERuntime()->getOrb();
298 }
299
300 OutputCorbaPort::OutputCorbaPort(const OutputCorbaPort& other, Node *newHelder):OutputPort(other,newHelder),DataPort(other,newHelder),Port(other,newHelder)
301 {
302   _orb = getSALOMERuntime()->getOrb();
303 }
304
305 OutputCorbaPort::~OutputCorbaPort()
306 {
307   DEBTRACE(getName());
308   // Release or not release : all GenericObj are deleted when the output port is deleted
309   releaseObj(_data);
310 #ifdef REFCNT
311   DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)_data.pd_tc.in())->pd_ref_count);
312   DEBTRACE("refcount CORBA tc_double: " << ((omni::TypeCode_base*)CORBA::_tc_double)->pd_ref_count);
313 #endif
314 }
315
316 void OutputCorbaPort::put(const void *data)
317 {
318   put((CORBA::Any *)data);
319 }
320
321 void OutputCorbaPort::put(CORBA::Any *data)
322 {
323   InputPort *p;
324
325   {  
326     YACS::BASES::AutoLocker<YACS::BASES::Mutex> lock(&_mutex);
327 #ifdef REFCNT
328     DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)data->pd_tc.in())->pd_ref_count);
329 #endif
330 #ifdef REFCNT
331     DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)_data.pd_tc.in())->pd_ref_count);
332 #endif
333
334     releaseObj(_data);
335
336     _data=*data;
337
338     //no registerObj : we steal the output reference of the node
339   }
340
341 #ifdef REFCNT
342   DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)_data.pd_tc.in())->pd_ref_count);
343 #endif
344   OutputPort::put(data);
345 #ifdef REFCNT
346   DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)data->pd_tc.in())->pd_ref_count);
347 #endif
348 #ifdef REFCNT
349   DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)_data.pd_tc.in())->pd_ref_count);
350 #endif
351 }
352
353 OutputPort *OutputCorbaPort::clone(Node *newHelder) const
354 {
355   return new OutputCorbaPort(*this,newHelder);
356 }
357
358 CORBA::Any * OutputCorbaPort::getAny()
359 {
360   // return a pointer to the internal any
361   return &_data;
362 }
363
364 CORBA::Any * OutputCorbaPort::getAnyOut() 
365 {
366   CORBA::Any* a=new CORBA::Any;
367   DynType kind=edGetType()->kind();
368   CORBA::TypeCode_var t;
369
370   if(kind == Int)
371     {
372       a->replace(CORBA::_tc_long, (void*) 0);
373     }
374   else if(kind == String)
375     {
376       a->replace(CORBA::_tc_string, (void*) 0);
377     }
378   else if(kind == Double)
379     {
380       a->replace(CORBA::_tc_double, (void*) 0);
381     }
382   else if(kind == Objref)
383     {
384       t = getCorbaTC(edGetType());
385       a->replace(t, (void*) 0);
386     }
387   else if(kind == Sequence)
388     {
389       t = getCorbaTC(edGetType());
390       a->replace(t, (void*) 0);
391     }
392   else if(kind == Struct)
393     {
394       t = getCorbaTC(edGetType());
395 #ifdef REFCNT
396   DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)t.in())->pd_ref_count);
397 #endif
398       a->replace(t, (void*) 0);
399 #ifdef REFCNT
400   DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)t.in())->pd_ref_count);
401 #endif
402     }
403   else if(kind == Bool)
404     {
405       a->replace(CORBA::_tc_boolean, (void*) 0);
406     }
407   else if(kind == NONE)
408     {
409       stringstream msg;
410       msg << "Cannot set Any Out for None" << __FILE__ << ":" << __LINE__;
411       throw Exception(msg.str());
412     }
413   else
414     {
415       stringstream msg;
416       msg << "Cannot set Any Out for unknown type" << __FILE__
417           << ":" << __LINE__;
418       throw Exception(msg.str());
419     }
420     
421   DEBTRACE( "getAnyOut:a: " << a );
422 #ifdef REFCNT
423   DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)a->pd_tc.in())->pd_ref_count);
424 #endif
425   return a;
426 }
427
428 PyObject * OutputCorbaPort::getPyObj()
429 {
430   YACS::BASES::AutoLocker<YACS::BASES::Mutex> lock(&_mutex);
431   CORBA::TypeCode_var tc=getAny()->type();
432   if (!tc->equivalent(CORBA::_tc_null))
433     return convertCorbaPyObject(edGetType(),getAny());
434   else
435     {
436       Py_INCREF(Py_None);
437       return Py_None;
438     }
439 }
440
441 std::string OutputCorbaPort::getAsString()
442 {
443   InterpreterUnlocker loc;
444   PyObject* ob=getPyObj();
445   std::string s=convertPyObjectToString(ob);
446   Py_DECREF(ob);
447   return s;
448 }
449
450 std::string OutputCorbaPort::dump()
451 {
452   CORBA::TypeCode_var tc=_data.type();
453   if (tc->equivalent(CORBA::_tc_null))
454     return "<value>nil</value>";
455   string xmldump = convertCorbaXml(edGetType(), &_data);
456   return xmldump;
457 }
458 namespace YACS {
459   namespace ENGINE {
460     ostream& operator<<(ostream& os, const OutputCorbaPort& p)
461     {
462       CORBA::Double l;
463       p._data>>=l;
464       os << p._name << " : " << l ;
465       return os;
466     }
467   };
468 };
469
470 std::string OutputCorbaPort::valToStr()
471 {
472   PyObject *strPyObj = PyObject_Str(getPyObj());
473   string val = PyBytes_AsString(strPyObj);
474   Py_DECREF(strPyObj);
475   return val;
476 }
477
478 void OutputCorbaPort::valFromStr(std::string valstr)
479 {
480 }
481