Salome HOME
fc81b541800c743a15f27aa0ba0c7db694036c39
[modules/yacs.git] / src / evalyfx / YACSEvalPort.cxx
1 // Copyright (C) 2012-2020  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 // Author : Anthony Geay (EDF R&D)
20
21 #include "YACSEvalPort.hxx"
22 #include "YACSEvalSeqAny.hxx"
23 #include "OutputPort.hxx"
24 #include "InputPort.hxx"
25 #include "TypeCode.hxx"
26
27 #include "CORBAPorts.hxx"
28 #include "PythonPorts.hxx"
29 #include "AnyInputPort.hxx"
30
31 #include <limits>
32 #include <sstream>
33 #include <typeinfo>
34
35 const char YACSEvalAnyDouble::TYPE_REPR[]="double";
36
37 const char YACSEvalAnyInt::TYPE_REPR[]="int";
38
39 int YACSEvalAnyDouble::toInt() const
40 {
41   throw YACS::Exception("YACSEvalAnyDouble::toInt : invalid type requested !");
42 }
43
44 double YACSEvalAnyDouble::toDouble() const
45 {
46   return _v;
47 }
48
49 YACSEvalAnyDouble *YACSEvalAnyDouble::deepCpy() const
50 {
51   return new YACSEvalAnyDouble(*this);
52 }
53
54 int YACSEvalAnyInt::toInt() const
55 {
56   return _v;
57 }
58
59 double YACSEvalAnyInt::toDouble() const
60 {
61   throw YACS::Exception("YACSEvalAnyInt::toDouble : invalid type requested !");
62 }
63
64 YACSEvalAnyInt *YACSEvalAnyInt::deepCpy() const
65 {
66   return new YACSEvalAnyInt(*this);
67 }
68
69 bool YACSEvalPort::IsInputPortPublishable(const YACS::ENGINE::InputPort *port)
70 {
71   YACS::ENGINE::TypeCode *tc(port->edGetType());
72   if(!tc)
73     throw YACS::Exception("YACSEvalPort::IsInPortPublishable : null type code !");
74   if(tc->kind()==YACS::ENGINE::Double || tc->kind()==YACS::ENGINE::Int)
75     return true;
76   if(tc->kind()==YACS::ENGINE::String)
77     {
78       if(port->edIsManuallyInitialized())
79         return false;
80     }
81   return true;
82 }
83
84 bool YACSEvalPort::IsOutputPortPublishable(const YACS::ENGINE::OutputPort *port)
85 {
86   YACS::ENGINE::TypeCode *tc(port->edGetType());
87   if(!tc)
88     throw YACS::Exception("YACSEvalPort::IsOutputPortPublishable : null type code !");
89   return tc->kind()==YACS::ENGINE::Double || tc->kind()==YACS::ENGINE::Int;
90 }
91
92 std::string YACSEvalPort::GetTypeOfData(const YACS::ENGINE::DataPort *port)
93 {
94   YACS::ENGINE::TypeCode *tc(port->edGetType());
95   if(!tc)
96     throw YACS::Exception("YACSEvalPort::GetTypeOfData : null type code !");
97   if(tc->kind()==YACS::ENGINE::Double)
98     return std::string(YACSEvalAnyDouble::TYPE_REPR);
99   if(tc->kind()==YACS::ENGINE::Int)
100     return std::string(YACSEvalAnyInt::TYPE_REPR);
101   throw YACS::Exception("YACSEvalPort::GetTypeOfData : Unrecognized type of data ! Must be int or double for the moment !");
102 }
103
104 YACSEvalInputPort::YACSEvalInputPort(YACS::ENGINE::InputPort *ptr):_ptr(ptr),_mySeq(0),_isRandom(false),_isLocked(false),_undergroundPort(0)
105 {
106   GetTypeOfData(_ptr);
107 }
108
109 std::string YACSEvalInputPort::getName() const
110 {
111   return _ptr->getName();
112 }
113
114 std::string YACSEvalInputPort::getTypeOfData() const
115 {
116   return GetTypeOfData(_ptr);
117 }
118
119 bool YACSEvalInputPort::isOKForLock() const
120 {
121   if(_isLocked)
122     return true;
123   return hasDefaultValueDefined();
124 }
125
126 bool YACSEvalInputPort::isLocked() const
127 {
128   return _isLocked;
129 }
130
131 bool YACSEvalInputPort::hasDefaultValueDefined() const
132 {
133   return _ptr->edIsManuallyInitialized();
134 }
135
136 /*!
137  * The caller has the ownership of the returned instance.
138  */
139 YACSEvalAny *YACSEvalInputPort::getDefaultValueDefined() const
140 {
141   if(!hasDefaultValueDefined())
142     throw YACS::Exception("YACSEvalInputPort::getDefaultValueDefined : no default value defined !");
143   _ptr->exRestoreInit();
144   YACS::ENGINE::InputPyPort *i0(dynamic_cast<YACS::ENGINE::InputPyPort *>(_ptr));
145   if(i0)
146     {
147       PyObject *data(i0->getPyObj());
148       if(!data)
149         throw YACS::Exception("YACSEvalInputPort::getDefaultValueDefined : internal error !");
150       if(PyFloat_Check(data))
151         return new YACSEvalAnyDouble(PyFloat_AsDouble(data));
152       if(PyLong_Check(data))
153         return new YACSEvalAnyInt((int)PyLong_AsLong(data));
154       throw YACS::Exception("YACSEvalInputPort::getDefaultValueDefined : unmanaged types different from int and double for py !");
155     }
156   YACS::ENGINE::AnyInputPort *i1(dynamic_cast<YACS::ENGINE::AnyInputPort *>(_ptr));
157   if(i1)
158     {
159       YACS::ENGINE::Any *data(i1->getValue());
160       return convertFromInternalAnyToExternal(data);
161     }
162   YACS::ENGINE::InputCorbaPort *i2(dynamic_cast<YACS::ENGINE::InputCorbaPort *>(_ptr));
163   if(i2)
164     {
165       CORBA::Any *data(i2->getAny());
166       if(!data)
167         throw YACS::Exception("YACSEvalInputPort::getDefaultValueDefined : internal error # 3 !");
168       std::string td(getTypeOfData());
169       if(td==YACSEvalAnyDouble::TYPE_REPR)
170         {
171           CORBA::Double v;
172           if((*data)>>=v)
173             return new YACSEvalAnyDouble(v);
174           else
175             throw YACS::Exception("YACSEvalInputPort::getDefaultValueDefined : internal error # 31 !");
176         }
177       if(td==YACSEvalAnyInt::TYPE_REPR)
178         {
179           CORBA::Long v;
180           if((*data)>>=v)
181             return new YACSEvalAnyInt(v);
182           else
183             throw YACS::Exception("YACSEvalInputPort::getDefaultValueDefined : internal error # 32 !");
184         }
185     }
186   std::ostringstream oss;
187   oss << "YACSEvalInputPort::getDefaultValueDefined : Please contact anthony.geay@edf.fr with -> \"" << typeid(*_ptr).name() << "\" !";
188   throw YACS::Exception(oss.str());
189 }
190
191 /*!
192  * This method does not steal the ownership of \a parameter (a deep copy is performed).
193  */
194 void YACSEvalInputPort::setDefaultValue(const YACSEvalAny *parameter)
195 {
196   checkForNonConstMethod();
197   if(parameter)
198     {
199       if(parameter->getTypeOfData()!=getTypeOfData())
200         {
201           std::ostringstream oss; oss << "YACSEvalInputPort::setParameter : Type of data mismatch ! Expecting \"" << getTypeOfData() << "\" having \"" <<  parameter->getTypeOfData() << "\" !";
202           throw YACS::Exception(oss.str());
203         }
204     }
205   //
206   YACS::ENGINE::InputPyPort *i0(dynamic_cast<YACS::ENGINE::InputPyPort *>(_ptr));
207   YACS::ENGINE::AnyInputPort *i1(dynamic_cast<YACS::ENGINE::AnyInputPort *>(_ptr));
208   YACS::ENGINE::InputCorbaPort *i2(dynamic_cast<YACS::ENGINE::InputCorbaPort *>(_ptr));
209   if(parameter)
210     {
211       const YACSEvalAnyDouble *par0(dynamic_cast<const YACSEvalAnyDouble *>(parameter));
212       const YACSEvalAnyInt *par1(dynamic_cast<const YACSEvalAnyInt *>(parameter));
213       if(i0)
214         {
215           if(par0)
216             {
217               PyObject *obj(PyFloat_FromDouble(par0->toDouble()));
218               i0->put(obj);
219               Py_XDECREF(obj);
220             }
221           else if(par1)
222             {
223               PyObject *obj(PyLong_FromLong(par1->toInt()));
224               i0->put(obj);
225               Py_XDECREF(obj);
226             }
227           else
228             throw YACS::Exception("YACSEvalInputPort::setDefaultValueDefined : unmanaged types different from int and double for py !");
229         }
230       else if(i1)
231         {
232           if(par0)
233             {
234               YACS::ENGINE::AtomAny *v(YACS::ENGINE::AtomAny::New(par0->toDouble()));
235               i1->put(v);
236               v->decrRef();
237             }
238           else if(par1)
239             {
240               YACS::ENGINE::AtomAny *v(YACS::ENGINE::AtomAny::New(par1->toInt()));
241               i1->put(v);
242               v->decrRef();
243             }
244           else
245             throw YACS::Exception("YACSEvalInputPort::setDefaultValueDefined : unmanaged types different from int and double for yacsport !");
246         }
247       else if(i2)
248         {
249           CORBA::Any v;
250           if(par0)
251             v<<=par0->toDouble();
252           else if(par1)
253             v<<=(CORBA::Short)par1->toInt();
254           else
255             throw YACS::Exception("YACSEvalInputPort::setDefaultValueDefined : unmanaged types different from int and double for corbaport !");
256           i2->put(&v);
257         }
258       else
259         {
260           std::ostringstream oss;
261           oss << "YACSEvalInputPort::getDefaultValueDefined : Please contact anthony.geay@edf.fr with -> \"" << typeid(*_ptr).name() << "\" !";
262           throw YACS::Exception(oss.str());
263         }
264       _ptr->exSaveInit();
265     }
266   else
267     _ptr->edRemoveManInit();
268 }
269
270 void YACSEvalInputPort::setSequenceOfValuesToEval(const YACSEvalSeqAny *vals)
271 {
272   if(!_isRandom && _isLocked)
273     throw YACS::Exception("YACSEvalInputPort::setSequenceOfValuesToEval : trying to set a sequence on a var not declared as random !");
274   //checkForNonConstMethod not called here because it is a special non const method !
275   if(!vals)
276     throw YACS::Exception("YACSEvalInputPort::setSequenceOfValuesToEval : input is NULL !");
277   if(vals==_mySeq)
278     return ;
279   if(_mySeq)
280     delete _mySeq;
281   _mySeq=vals->copy();
282   _isRandom=true;
283 }
284
285 bool YACSEvalInputPort::hasSequenceOfValuesToEval() const
286 {
287   return (_mySeq!=0);
288 }
289
290 void YACSEvalInputPort::declareRandomnessStatus(bool isRandom)
291 {
292   checkForNonConstMethod();
293   _isRandom=isRandom;
294   if(!_isRandom)
295     _undergroundPort=0;
296 }
297
298 std::size_t YACSEvalInputPort::initializeUndergroundWithSeq() const
299 {
300   if(!_undergroundPort)
301     throw YACS::Exception("YACSEvalInputPort::initializeUndergroundWithSeq : internal error ! this input has not been locked properly ! Need to be locked !");
302   if(!_mySeq)
303     throw YACS::Exception("YACSEvalInputPort::initializeUndergroundWithSeq : this is not set as a sequence !");
304   _mySeq->initialize(_undergroundPort);
305   return _mySeq->size();
306 }
307
308 YACSEvalInputPort::~YACSEvalInputPort()
309 {
310   delete _mySeq;
311 }
312
313 void YACSEvalInputPort::setUndergroundPortToBeSet(YACS::ENGINE::InputPyPort *p) const
314 {
315   if(!_isRandom)
316     throw YACS::Exception("YACSEvalInputPort::setUndergroundPortToBeSet : trying to set a non random var !");
317   _undergroundPort=p;
318 }
319
320 YACSEvalAny *YACSEvalInputPort::convertFromInternalAnyToExternal(YACS::ENGINE::Any *data) const
321 {
322   if(!data)
323     throw YACS::Exception("YACSEvalInputPort::convertFromInternalAnyToExternal : internal error # 2 !");
324   YACS::ENGINE::AtomAny *data2(dynamic_cast<YACS::ENGINE::AtomAny *>(data));
325   if(!data2)
326     throw YACS::Exception("YACSEvalInputPort::convertFromInternalAnyToExternal : internal error # 21 !");
327   std::string td(getTypeOfData());
328   if(td==YACSEvalAnyDouble::TYPE_REPR)
329     return new YACSEvalAnyDouble(data2->getDoubleValue());
330   if(td==YACSEvalAnyInt::TYPE_REPR)
331     return new YACSEvalAnyInt(data2->getIntValue());
332   throw YACS::Exception("YACSEvalInputPort::convertFromInternalAnyToExternal : unmanaged types different from int and double for any !");
333 }
334
335 void YACSEvalInputPort::checkForNonConstMethod() const
336 {
337   if(_isLocked)
338     throw YACS::Exception("YACSEvalInputPort::checkForNonConstMethod : trying to modify a locked input ! To release it call unlockAll on YACSEvalYFX instance owning this !");
339 }
340
341 YACSEvalOutputPort::YACSEvalOutputPort(YACS::ENGINE::OutputPort *ptr):_ptr(ptr),_isQOfInt(false)
342 {
343   GetTypeOfData(_ptr);
344 }
345
346 std::string YACSEvalOutputPort::getName() const
347 {
348   return _ptr->getName();
349 }
350
351 std::string YACSEvalOutputPort::getTypeOfData() const
352 {
353   return GetTypeOfData(_ptr);
354 }