2c9ac105a534cbc8d97a1acd36bb243ac3dc7103
[scilab.git] / scilab / modules / scicos / sci_gateway / cpp / sci_scicos_new.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2014-2014 - Scilab Enterprises - Clement DAVID
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15
16 #include <string>
17 #include <sstream>
18
19 #include "gw_scicos.hxx"
20
21 #include "types.hxx"
22 #include "int.hxx"
23 #include "string.hxx"
24 #include "tlist.hxx"
25 #include "mlist.hxx"
26 #include "list.hxx"
27 #include "function.hxx"
28
29 #include "view_scilab/Adapters.hxx"
30 #include "view_scilab/BaseAdapter.hxx"
31 #include "view_scilab/BlockAdapter.hxx"
32 #include "view_scilab/CprAdapter.hxx"
33 #include "view_scilab/DiagramAdapter.hxx"
34 #include "view_scilab/GraphicsAdapter.hxx"
35 #include "view_scilab/LinkAdapter.hxx"
36 #include "view_scilab/ModelAdapter.hxx"
37 #include "view_scilab/ParamsAdapter.hxx"
38 #include "view_scilab/ScsAdapter.hxx"
39 #include "view_scilab/StateAdapter.hxx"
40 #include "view_scilab/TextAdapter.hxx"
41
42 #include "utilities.hxx"
43 #include "Controller.hxx"
44 #include "model/Annotation.hxx"
45 #include "model/Block.hxx"
46 #include "model/Diagram.hxx"
47 #include "model/Link.hxx"
48
49 extern "C"
50 {
51 #include "Scierror.h"
52 #include "localization.h"
53 }
54
55 static const std::string funame = "scicos_new";
56
57 using namespace org_scilab_modules_scicos;
58
59 template<class Adaptor, class Adaptee>
60 types::InternalType * alloc_and_set(kind_t k, types::String* type_name, types::typed_list &in)
61 {
62     Controller controller;
63
64     // create the associated object
65     ScicosID o = controller.createObject(k);
66     Adaptor* adaptor = new Adaptor(controller, controller.getObject<Adaptee>(o));
67
68     // the first header entry is the type
69     for (int i = 1; i < (int)in.size(); i++)
70     {
71         std::wstring name (type_name->get(i));
72         if (!adaptor->setProperty(name, in[i], controller))
73         {
74             Scierror(999, _("%s: Wrong value for input argument #%d: unable to set \"%ls\".\n"), funame.data(), i, name.data());
75             delete adaptor;
76             return 0;
77         }
78     }
79
80     return adaptor;
81 }
82
83 template<class Adaptor, class Adaptee>
84 types::InternalType * alloc_and_set_as_tlist(types::String* type_name, types::typed_list &in)
85 {
86     // check header
87     // The default constructor should be implemented for this Adapter
88     Adaptor adaptor;
89     for (int i = 1; i < (int)in.size(); i++)
90     {
91         std::wstring name(type_name->get(i));
92         if (!adaptor.hasProperty(name))
93         {
94             Scierror(999, _("%s: Wrong value for input argument #%d: unable to set \"%ls\".\n"), funame.data(), i, name.data());
95             return 0;
96         }
97     }
98
99     // copy the data
100     types::TList* tlist = new types::TList();
101     tlist->set(0, type_name->clone());
102     for (int i = 1; i < (int)in.size(); i++)
103     {
104         tlist->set(i, in[i]);
105     }
106
107     return tlist;
108 }
109
110 template<class Adaptor, class Adaptee>
111 types::InternalType * alloc_and_set_as_mlist(types::String* type_name, types::typed_list &in)
112 {
113     // check header
114     // The default constructor should be implemented for this Adapter
115     Adaptor adaptor;
116     for (int i = 1; i < (int)in.size(); i++)
117     {
118         std::wstring name(type_name->get(i));
119         if (!adaptor.hasProperty(name))
120         {
121             Scierror(999, _("%s: Wrong value for input argument #%d: unable to set \"%ls\".\n"), funame.data(), i, name.data());
122             return 0;
123         }
124     }
125
126     // copy the data
127     types::MList* mlist = new types::MList();
128     mlist->set(0, type_name->clone());
129     for (int i = 1; i < (int)in.size(); i++)
130     {
131         mlist->set(i, in[i]);
132     }
133
134     return mlist;
135 }
136
137 static types::Function::ReturnValue allocate(types::typed_list &in, int _iRetCount, types::typed_list &out)
138 {
139     types::InternalType* type = in[0];
140
141     types::String* type_name = type->getAs<types::String>();
142     if (type_name->getRows() > 1)
143     {
144         Scierror(999, _("%s: Wrong size for input argument #%d: Row vector expected.\n"), funame.data(), 1);
145         return types::Function::Error;
146     }
147
148     if (type_name->getCols() != (int) in.size())
149     {
150         Scierror(999, _("%s: Wrong number of input argument: %d expected.\n"), funame.data(), type_name->getCols());
151         return types::Function::Error;
152     }
153
154     /*
155      * allocate the right adapter then try to set fields values
156      */
157
158     const view_scilab::Adapters::adapters_index_t adapter_index = view_scilab::Adapters::instance().lookup_by_typename(type_name->get(0));
159     types::InternalType* returnType;
160     switch (adapter_index)
161     {
162         case view_scilab::Adapters::BLOCK_ADAPTER:
163             returnType = alloc_and_set<view_scilab::BlockAdapter, model::Block>(BLOCK, type_name, in);
164             if (returnType == nullptr)
165             {
166                 return types::Function::Error;
167             }
168             break;
169         case view_scilab::Adapters::CPR_ADAPTER:
170             returnType = alloc_and_set_as_tlist<view_scilab::CprAdapter, model::Diagram>(type_name, in);
171             if (returnType == nullptr)
172             {
173                 return types::Function::Error;
174             }
175             break;
176         case view_scilab::Adapters::DIAGRAM_ADAPTER:
177             returnType = alloc_and_set<view_scilab::DiagramAdapter, model::Diagram>(DIAGRAM, type_name, in);
178             if (returnType == nullptr)
179             {
180                 return types::Function::Error;
181             }
182             break;
183         case view_scilab::Adapters::GRAPHIC_ADAPTER:
184             returnType = alloc_and_set_as_mlist<view_scilab::GraphicsAdapter, model::Block>(type_name, in);
185             if (returnType == nullptr)
186             {
187                 return types::Function::Error;
188             }
189             break;
190         case view_scilab::Adapters::LINK_ADAPTER:
191             returnType = alloc_and_set<view_scilab::LinkAdapter, model::Link>(LINK, type_name, in);
192             if (returnType == nullptr)
193             {
194                 return types::Function::Error;
195             }
196             break;
197         case view_scilab::Adapters::MODEL_ADAPTER:
198             returnType = alloc_and_set_as_mlist<view_scilab::ModelAdapter, model::Block>(type_name, in);
199             if (returnType == nullptr)
200             {
201                 return types::Function::Error;
202             }
203             break;
204         case view_scilab::Adapters::PARAMS_ADAPTER:
205             returnType = alloc_and_set_as_tlist<view_scilab::ParamsAdapter, model::Diagram>(type_name, in);
206             if (returnType == nullptr)
207             {
208                 return types::Function::Error;
209             }
210             break;
211         case view_scilab::Adapters::SCS_ADAPTER:
212             returnType = alloc_and_set<view_scilab::ScsAdapter, model::Diagram>(DIAGRAM, type_name, in);
213             if (returnType == nullptr)
214             {
215                 return types::Function::Error;
216             }
217             break;
218         case view_scilab::Adapters::STATE_ADAPTER:
219             returnType = alloc_and_set_as_tlist<view_scilab::StateAdapter, model::Diagram>(type_name, in);
220             if (returnType == nullptr)
221             {
222                 return types::Function::Error;
223             }
224             break;
225         case view_scilab::Adapters::TEXT_ADAPTER:
226             returnType = alloc_and_set<view_scilab::TextAdapter, model::Annotation>(ANNOTATION, type_name, in);
227             if (returnType == nullptr)
228             {
229                 return types::Function::Error;
230             }
231             break;
232         default:
233             Scierror(999, _("%s: Wrong value for input argument #%d:  \"%ls\" type is not managed.\n"), funame.data(), 1, type_name->get(0));
234             return types::Function::Error;
235     }
236     out.push_back(returnType);
237
238     return types::Function::OK;
239 }
240
241 static ScicosID get(types::GenericType* UIDs, int index)
242 {
243     ScicosID ret;
244
245     switch (UIDs->getType())
246     {
247         case types::InternalType::ScilabString:
248         {
249             wchar_t* str = UIDs->getAs<types::String>()->get(index);
250             std::wistringstream iss(str);
251             iss >> std::hex >> ret;
252             break;
253         }
254         case types::InternalType::ScilabInt64:
255             ret = UIDs->getAs<types::Int64>()->get(index);
256             break;
257         default:
258             ret = ScicosID();
259             break;
260     }
261
262     return ret;
263 }
264
265 static types::Function::ReturnValue get(types::GenericType* UIDs, int _iRetCount, types::typed_list &out)
266 {
267     if (UIDs->getSize() != _iRetCount)
268     {
269         Scierror(999, _("%s: Wrong size for input argument #%d: %dx%d expected.\n"), funame.data(), 1, _iRetCount, 1);
270         return types::Function::Error;
271     }
272
273
274     Controller controller;
275     types::Function::ReturnValue retValue = types::Function::OK;
276     for (int i = 0; i < _iRetCount; ++i)
277     {
278         ScicosID uid = get(UIDs, i);
279
280         // create the associated object
281         model::BaseObject* o = controller.getObject(uid);
282         if (o == nullptr)
283         {
284             Scierror(999, _("%s: Wrong value for input argument #%d: invalid UID.\n"), funame.data(), 1);
285             retValue = types::Function::Error;
286             break;
287         }
288
289         switch (o->kind())
290         {
291             case DIAGRAM:
292                 out.push_back(new view_scilab::DiagramAdapter(controller, static_cast<model::Diagram*>(controller.referenceObject(o))));
293                 break;
294             case BLOCK:
295                 out.push_back(new view_scilab::BlockAdapter(controller, static_cast<model::Block*>(controller.referenceObject(o))));
296                 break;
297             case LINK:
298                 out.push_back(new view_scilab::LinkAdapter(controller, static_cast<model::Link*>(controller.referenceObject(o))));
299                 break;
300             default:
301                 Scierror(999, _("%s: Wrong value for input argument #%d: not handled kind.\n"), funame.data(), 1);
302                 retValue = types::Function::Error;
303                 break;
304         }
305     }
306
307     if (retValue != types::Function::OK)
308     {
309         // something goes wrong, release the allocated data
310         for (types::typed_list::iterator it = out.begin(); it != out.end(); ++it)
311         {
312             delete *it;
313         }
314     }
315
316     return retValue;
317 }
318
319 types::Function::ReturnValue sci_scicos_new(types::typed_list &in, int _iRetCount, types::typed_list &out)
320 {
321     if (in.size() < 1)
322     {
323         Scierror(999, _("%s: Wrong number of input arguments: At least %d expected.\n"), funame.data(), 1);
324         return types::Function::Error;
325     }
326     if (_iRetCount > 1)
327     {
328         Scierror(999, _("%s: Wrong number of output arguments: %d expected.\n"), funame.data(), 1);
329         return types::Function::Error;
330     }
331
332     types::InternalType* type = in[0];
333     switch (type->getType())
334     {
335         case types::InternalType::ScilabString:
336             if (in.size() == 1)
337             {
338                 return get(type->getAs<types::String>(), _iRetCount, out);
339             }
340             else
341             {
342                 return allocate(in, _iRetCount, out);
343             }
344         case types::InternalType::ScilabInt64:
345             return get(type->getAs<types::Int64>(), _iRetCount, out);
346         default:
347             Scierror(999, _("%s: Wrong type for input argument #%d: String or ID expected.\n"), funame.data(), 1);
348             return types::Function::Error;
349     }
350 }
351