Salome HOME
Merge branch 'omu/Launcher9'
[modules/kernel.git] / src / SALOMESDS / SALOMESDS_PickelizedPyObjRdExtServer.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
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 "SALOMESDS_PickelizedPyObjRdExtServer.hxx"
22 #include "SALOMESDS_PickelizedPyObjRdExtInitServer.hxx"
23 #include "SALOMESDS_DataScopeServer.hxx"
24 #include "SALOMESDS_Exception.hxx"
25
26 #include <iostream>
27 #include <sstream>
28
29 using namespace SALOMESDS;
30
31 const char PickelizedPyObjRdExtServer::ACCESS_REPR[]="RdExt";
32
33 PickelizedPyObjRdExtServer::PickelizedPyObjRdExtServer(DataScopeServerBase *father, const std::string& varName, const SALOME::ByteVec& value):PickelizedPyObjServerModifiable(father,varName,value)
34 {
35 }
36
37 //! obj is consumed
38 PickelizedPyObjRdExtServer::PickelizedPyObjRdExtServer(DataScopeServerBase *father, const std::string& varName, PyObject *obj):PickelizedPyObjServerModifiable(father,varName,obj)
39 {
40 }
41
42 PickelizedPyObjRdExtServer::~PickelizedPyObjRdExtServer()
43 {
44 }
45
46 /*!
47  * Called remotely -> to protect against throw
48  */
49 SALOME::PickelizedPyObjRdExtServer_ptr PickelizedPyObjRdExtServer::invokePythonMethodOn(const char *method, const SALOME::ByteVec& args)
50 {
51   if(!_self)
52     throw Exception("PickelizedPyObjRdExtServer::invokePythonMethodOn : self is NULL !");
53   std::string argsCpp;
54   FromByteSeqToCpp(args,argsCpp);
55   PyObject *argsPy(getPyObjFromPickled(argsCpp));
56   checkRdExtnessOf(method,argsPy);
57   //
58   PyObject *selfMeth(PyObject_GetAttrString(_self,method));
59   if(!selfMeth)
60     {
61       std::ostringstream oss; oss << "PickelizedPyObjRdExtServer::invokePythonMethodOn : Method \"" << method << "\" is not available !";
62       throw Exception(oss.str());
63     }
64   PyObject *res(PyObject_CallObject(selfMeth,argsPy));// self can have been modified by this call !
65   Py_XDECREF(selfMeth);
66   Py_XDECREF(argsPy);
67   if(!res)
68     {
69       std::ostringstream oss; oss << "PickelizedPyObjRdExtServer::invokePythonMethodOn : Problem during invocation serverside of Method \"" << method << "\" !";
70       throw Exception(oss.str());
71     }
72   PickelizedPyObjRdExtServer *ret(new PickelizedPyObjRdExtServer(_father,DataScopeServer::BuildTmpVarNameFrom(getVarNameCpp()),res));
73   PortableServer::POA_var poa(_father->getPOA());
74   PortableServer::ObjectId_var id(poa->activate_object(ret));
75   CORBA::Object_var obj(poa->id_to_reference(id));
76   return SALOME::PickelizedPyObjRdExtServer::_narrow(obj);
77 }
78
79 PickelizedPyObjRdExtInitServer *PickelizedPyObjRdExtServer::buildInitInstanceFrom(const std::string& varName)
80 {
81   PyObject *pyobj(this->getPyObj()); Py_XINCREF(pyobj);
82   return new PickelizedPyObjRdExtInitServer(getFather(),varName,pyobj);
83 }
84
85 void PickelizedPyObjRdExtServer::checkRdExtnessOf(const std::string& methodName, PyObject *argsPy)
86 {
87   if(!_self)
88     {
89       Py_XDECREF(argsPy);
90       throw Exception("PickelizedPyObjRdExtServer::checkRdExtnessOf : self is NULL !");
91     }
92   if(PyTuple_Check(_self)==1 || PyBytes_Check(_self)==1 || PyLong_Check(_self)==1 || PyBool_Check(_self)==1 || PyFloat_Check(_self)==1)
93     return ;//_self is tuple, str, int or float -> immutable in python. So no method can break the RdExtness of _self.
94   if(PyList_Check(_self)==1)
95     checkListRdExtnessOf(methodName,argsPy);
96   else if(PyDict_Check(_self)==1)
97     checkDictRdExtnessOf(methodName,argsPy);
98   else
99     throw Exception("PickelizedPyObjRdExtServer::checkRdExtnessOf : Supported python types are [list,tuple,dict,str,int,float] !");
100 }
101
102 void PickelizedPyObjRdExtServer::checkListRdExtnessOf(const std::string& methodName, PyObject *argsPy)
103 {
104   static const char *THE_RDEXT_METH_OF_LIST[]={"__getitem__","append","extend","insert","reverse","sort"};
105   for(std::size_t i=0;i<sizeof(THE_RDEXT_METH_OF_LIST)/sizeof(const char *);i++)
106     if(methodName==THE_RDEXT_METH_OF_LIST[i])
107       return ;
108   Py_XDECREF(argsPy);
109   std::ostringstream oss; oss << "PickelizedPyObjRdExtServer::checkListRdExtnessOf : The method \"" << methodName << "\" is a method that can lead to a loss of data ! Supported method of \"list \"without loss of data are : __getitem__, append, extend, insert, reverse, sort !";
110   throw Exception(oss.str());
111 }
112
113 void PickelizedPyObjRdExtServer::checkDictRdExtnessOf(const std::string& methodName, PyObject *argsPy)
114 {
115   static const char *THE_RDEXT_METH_OF_DICT[]={"__getitem__","get","items","keys","setdefault","update","values"};
116   for(std::size_t i=0;i<sizeof(THE_RDEXT_METH_OF_DICT)/sizeof(const char *);i++)
117     if(methodName==THE_RDEXT_METH_OF_DICT[i])
118       return ;
119   if(methodName=="__setitem__")
120     {
121       checkDictSetitemRdExtness(argsPy);
122       return ;
123     }
124   Py_XDECREF(argsPy);
125   std::ostringstream oss; oss << "PickelizedPyObjRdExtServer::checkDictRdExtnessOf : The method \"" << methodName << "\" is a method that can lead to a loss of data ! Supported method of \"list \"without loss of data are : __getitem__, __setitem__(with conditions), get, items, keys, setdefault, update, values !";
126   throw Exception(oss.str());
127 }
128
129 void PickelizedPyObjRdExtServer::checkDictSetitemRdExtness(PyObject *argsPy)
130 {
131   if(PyTuple_Check(argsPy)==0)
132     {
133       Py_XDECREF(argsPy);
134       throw Exception("PickelizedPyObjRdExtServer::checkDictSetitemRdExtness : args of dic(self).__setitem__ is not a tuple !");
135     }
136   if(PyTuple_Size(argsPy)!=2)
137     {
138       Py_XDECREF(argsPy);
139       throw Exception("PickelizedPyObjRdExtServer::checkDictSetitemRdExtness : tuple of dic(self).__setitem__ has not a size equal to 2 !");
140     }
141   if(PyDict_GetItem(_self,PyTuple_GetItem(argsPy,0))!=0)
142     {// argsPy[0] is already a key of _self -> __setitem__ is NOT RdExt !
143       Py_XDECREF(argsPy);
144       throw Exception("PickelizedPyObjRdExtServer::checkDictSetitemRdExtness : specified key of __setitem__ already exists ! RdExt property is not applied !");
145     }
146 }
147
148 std::string PickelizedPyObjRdExtServer::getAccessStr() const
149 {
150   return std::string(ACCESS_REPR);
151 }
152
153
154 PickelizedPyObjRdExtInitServer *PickelizedPyObjRdExtFreeStyleServer::buildInitInstanceFrom(const std::string& varName)
155 {
156   PyObject *pyobj(this->getPyObj()); Py_XINCREF(pyobj);
157   return new PickelizedPyObjRdExtInitFreeStyleServer(getFather(),varName,pyobj,std::move(_sha1));
158 }