75cc7d1bd36e078c58e0338a620611d5ebd0ba61
[scilab.git] / scilab / modules / scicos / src / cpp / view_scilab / ModelAdapter.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2014-2016 - Scilab Enterprises - Clement DAVID
4  * Copyright (C) 2017 - ESI Group - Clement DAVID
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17 #include <cwchar>
18 #include <cstring>
19
20 #include <string>
21 #include <vector>
22 #include <algorithm>
23 #include <sstream>
24
25 #include "bool.hxx"
26 #include "int.hxx"
27 #include "double.hxx"
28 #include "string.hxx"
29 #include "list.hxx"
30 #include "tlist.hxx"
31 #include "user.hxx"
32
33 #include "Controller.hxx"
34 #include "ModelAdapter.hxx"
35 #include "LinkAdapter.hxx"
36 #include "DiagramAdapter.hxx"
37
38 #include "view_scilab/Adapters.hxx"
39 #include "ports_management.hxx"
40 #include "utilities.hxx"
41 #include "controller_helpers.hxx"
42
43 #include "var2vec.hxx"
44 #include "vec2var.hxx"
45
46 extern "C" {
47 #include "sci_malloc.h"
48 #include "charEncoding.h"
49 #include "localization.h"
50 }
51
52 namespace org_scilab_modules_scicos
53 {
54 namespace view_scilab
55 {
56 namespace
57 {
58
59 const std::wstring modelica (L"modelica");
60 const std::wstring model (L"model");
61 const std::wstring inputs (L"inputs");
62 const std::wstring outputs (L"outputs");
63 const std::wstring parameters (L"parameters");
64
65 types::InternalType* get_with_vec2var(const ModelAdapter& adaptor, const Controller& controller, object_properties_t p)
66 {
67     ScicosID adaptee = adaptor.getAdaptee()->id();
68
69     std::vector<double> prop_content;
70     controller.getObjectProperty(adaptee, BLOCK, p, prop_content);
71
72     // Corner-case, the empty content is an empty double
73     if (prop_content.empty())
74     {
75         return types::Double::Empty();
76     }
77
78     // The returned value is a list
79     types::InternalType* res;
80     if (!vec2var(prop_content, res))
81     {
82         return nullptr;
83     }
84
85     return res;
86 }
87
88 bool set_with_var2vec(ModelAdapter& adaptor, types::InternalType* v, Controller& controller, object_properties_t p)
89 {
90     ScicosID adaptee = adaptor.getAdaptee()->id();
91
92     // corner-case the empty content is an empty-double
93     if (v->getType() == types::InternalType::ScilabDouble)
94     {
95         types::Double* current = v->getAs<types::Double>();
96         if (current->getSize() != 0)
97         {
98             return false;
99         }
100
101         // prop_content should be empty
102         std::vector<double> prop_content;
103         controller.setObjectProperty(adaptee, BLOCK, p, prop_content);
104         return true;
105     }
106
107     std::vector<double> prop_content;
108     if (!var2vec(v, prop_content))
109     {
110         return false;
111     }
112
113     controller.setObjectProperty(adaptee, BLOCK, p, prop_content);
114     return true;
115 }
116
117 struct sim
118 {
119
120     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
121     {
122         ScicosID adaptee = adaptor.getAdaptee()->id();
123
124         // First, extract the function Name
125         std::string name;
126         controller.getObjectProperty(adaptee, BLOCK, SIM_FUNCTION_NAME, name);
127         types::String* Name = new types::String(1, 1);
128         Name->set(0, name.data());
129
130         // Then the Api. If it is zero, then just return the Name. Otherwise, return a list containing both.
131         int api;
132         controller.getObjectProperty(adaptee, BLOCK, SIM_FUNCTION_API, api);
133
134         if (api == 0)
135         {
136             return Name;
137         }
138         else
139         {
140             types::Double* Api = new types::Double(static_cast<double>(api));
141             types::List* o = new types::List();
142             o->set(0, Name);
143             o->set(1, Api);
144             return o;
145         }
146     }
147
148     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
149     {
150         ScicosID adaptee = adaptor.getAdaptee()->id();
151
152         if (v->getType() == types::InternalType::ScilabString)
153         {
154             types::String* current = v->getAs<types::String>();
155             if (current->getSize() != 1)
156             {
157                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s : %d-by-%d expected.\n"), "model", "sim", 1, 1);
158                 return false;
159             }
160
161             char* c_str = wide_string_to_UTF8(current->get(0));
162             std::string name(c_str);
163             FREE(c_str);
164
165             // If the input is a scalar string, then the functionApi is 0.
166             int api = 0;
167
168             controller.setObjectProperty(adaptee, BLOCK, SIM_FUNCTION_NAME, name);
169             controller.setObjectProperty(adaptee, BLOCK, SIM_FUNCTION_API, api);
170         }
171         else if (v->getType() == types::InternalType::ScilabList)
172         {
173             // If the input is a 2-sized list, then it must be string and positive integer.
174             types::List* current = v->getAs<types::List>();
175             if (current->getSize() != 2)
176             {
177                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong length for field %s.%s : %d expected.\n"), "model", "sim", 2);
178                 return false;
179             }
180             if (current->get(0)->getType() != types::InternalType::ScilabString || current->get(1)->getType() != types::InternalType::ScilabDouble)
181             {
182                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : String matrix expected.\n"), "model", "sim");
183                 return false;
184             }
185
186             types::String* Name = current->get(0)->getAs<types::String>();
187             if (Name->getSize() != 1)
188             {
189                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s : %d-by-%d expected.\n"), "model", "sim(1)", 1, 1);
190                 return false;
191             }
192             char* c_str = wide_string_to_UTF8(Name->get(0));
193             std::string name(c_str);
194             FREE(c_str);
195
196             types::Double* Api = current->get(1)->getAs<types::Double>();
197             if (Api->getSize() != 1)
198             {
199                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s : %d-by-%d expected.\n"), "model", "sim(2)", 1, 1);
200                 return false;
201             }
202             double api = Api->get(0);
203             if (floor(api) != api)
204             {
205                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for field %s.%s : Round number expected.\n"), "model", "sim(2)");
206                 return false;
207             }
208             int api_int = static_cast<int>(api);
209
210             controller.setObjectProperty(adaptee, BLOCK, SIM_FUNCTION_NAME, name);
211             controller.setObjectProperty(adaptee, BLOCK, SIM_FUNCTION_API, api_int);
212         }
213         else
214         {
215             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : String matrix expected.\n"), "model", "sim");
216             return false;
217         }
218         return true;
219     }
220 };
221
222 struct in
223 {
224
225     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
226     {
227         return get_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, INPUTS, controller);
228     }
229
230     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
231     {
232         return update_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, INPUTS, controller, v);
233     }
234 };
235
236 struct in2
237 {
238
239     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
240     {
241         return get_ports_property<ModelAdapter, DATATYPE_COLS>(adaptor, INPUTS, controller);
242     }
243
244     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
245     {
246         return set_ports_property<ModelAdapter, DATATYPE_COLS>(adaptor, INPUTS, controller, v);
247     }
248 };
249
250 struct intyp
251 {
252
253     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
254     {
255         return get_ports_property<ModelAdapter, DATATYPE_TYPE>(adaptor, INPUTS, controller);
256     }
257
258     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
259     {
260         return set_ports_property<ModelAdapter, DATATYPE_TYPE>(adaptor, INPUTS, controller, v);
261     }
262 };
263
264 struct out
265 {
266
267     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
268     {
269         return get_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, OUTPUTS, controller);
270     }
271
272     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
273     {
274         return update_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, OUTPUTS, controller, v);
275     }
276 };
277
278 struct out2
279 {
280
281     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
282     {
283         return get_ports_property<ModelAdapter, DATATYPE_COLS>(adaptor, OUTPUTS, controller);
284     }
285
286     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
287     {
288         return set_ports_property<ModelAdapter, DATATYPE_COLS>(adaptor, OUTPUTS, controller, v);
289     }
290 };
291
292 struct outtyp
293 {
294
295     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
296     {
297         return get_ports_property<ModelAdapter, DATATYPE_TYPE>(adaptor, OUTPUTS, controller);
298     }
299
300     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
301     {
302         return set_ports_property<ModelAdapter, DATATYPE_TYPE>(adaptor, OUTPUTS, controller, v);
303     }
304 };
305
306 struct evtin
307 {
308
309     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
310     {
311         return get_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, EVENT_INPUTS, controller);
312     }
313
314     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
315     {
316         return update_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, EVENT_INPUTS, controller, v);
317     }
318 };
319
320 struct evtout
321 {
322
323     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
324     {
325         return get_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, EVENT_OUTPUTS, controller);
326     }
327
328     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
329     {
330         return update_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, EVENT_OUTPUTS, controller, v);
331     }
332 };
333
334 struct state
335 {
336
337     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
338     {
339         ScicosID adaptee = adaptor.getAdaptee()->id();
340
341         std::vector<double> state;
342         controller.getObjectProperty(adaptee, BLOCK, STATE, state);
343
344         double* data;
345         types::Double* o = new types::Double((int)state.size(), 1, &data);
346
347 #ifdef _MSC_VER
348         std::copy(state.begin(), state.end(), stdext::checked_array_iterator<double*>(data, state.size()));
349 #else
350         std::copy(state.begin(), state.end(), data);
351 #endif
352         return o;
353     }
354
355     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
356     {
357
358         if (v->getType() != types::InternalType::ScilabDouble)
359         {
360             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : Real matrix expected.\n"), "model", "state");
361             return false;
362         }
363
364         types::Double* current = v->getAs<types::Double>();
365         // Only allow vectors and empty matrices
366         if (!current->isVector() && current->getSize() != 0)
367         {
368             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong size for field %s.%s : %d-by-%d expected.\n"), "model", "state");
369             return false;
370         }
371
372         ScicosID adaptee = adaptor.getAdaptee()->id();
373
374         std::vector<double> state (current->getSize());
375         std::copy(current->getReal(), current->getReal() + current->getSize(), state.begin());
376
377         controller.setObjectProperty(adaptee, BLOCK, STATE, state);
378         return true;
379     }
380 };
381
382 struct dstate
383 {
384
385     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
386     {
387         ScicosID adaptee = adaptor.getAdaptee()->id();
388
389         std::vector<double> dstate;
390         controller.getObjectProperty(adaptee, BLOCK, DSTATE, dstate);
391
392         double* data;
393         types::Double* o = new types::Double((int)dstate.size(), 1, &data);
394
395 #ifdef _MSC_VER
396         std::copy(dstate.begin(), dstate.end(), stdext::checked_array_iterator<double*>(data, dstate.size()));
397 #else
398         std::copy(dstate.begin(), dstate.end(), data);
399 #endif
400         return o;
401     }
402
403     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
404     {
405         ScicosID adaptee = adaptor.getAdaptee()->id();
406
407         if (v->getType() == types::InternalType::ScilabString)
408         {
409             /*
410              * This seems to be a corner-case used for code generation on ScicosLab
411              */
412
413             types::String* current = v->getAs<types::String>();
414             if (current->getSize() != 1)
415             {
416                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : Real matrix expected.\n"), "model", "dstate");
417                 return false;
418             }
419
420             std::vector<double> dstate;
421             controller.setObjectProperty(adaptee, BLOCK, DSTATE, dstate);
422             return true;
423         }
424
425         if (v->getType() != types::InternalType::ScilabDouble)
426         {
427             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : Real matrix expected.\n"), "model", "dstate");
428             return false;
429         }
430         types::Double* current = v->getAs<types::Double>();
431         // Only allow vectors and empty matrices
432         if (!current->isVector() && current->getSize() != 0)
433         {
434             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s : m-by-1 expected.\n"), "model", "dstate");
435             return false;
436         }
437
438         std::vector<double> dstate (current->getSize());
439         std::copy(current->getReal(), current->getReal() + current->getSize(), dstate.begin());
440
441         controller.setObjectProperty(adaptee, BLOCK, DSTATE, dstate);
442         return true;
443     }
444 };
445
446 void decodeDims(std::vector<int>::iterator& prop_it, std::vector<int>& dims)
447 {
448     const int iDims = *prop_it++;
449     dims.resize(iDims);
450
451     memcpy(&dims[0], &(*prop_it), iDims * sizeof(int));
452     prop_it += iDims;
453 }
454
455 void encodeDims(std::vector<int>& prop_content, types::GenericType* v)
456 {
457     const int iDims = v->getDims();
458     prop_content.push_back(iDims);
459
460     const int index = (int)prop_content.size();
461     prop_content.resize(index + iDims);
462
463     memcpy(&prop_content[index], v->getDimsArray(), iDims * sizeof(int));
464 }
465
466 /**
467  * Calculate the length increment depending on the ::value_type of the buffer and the type of the Scilab type
468  *
469  * @param V buffer type which must have a ::value_type field
470  * @param T Scilab type
471  * @param v the instance on the Scilab type
472  * @return the number of V elements used to store the data
473  */
474 template<typename V, typename T>
475 size_t required_length(const V& /*it*/, T* v)
476 {
477     const size_t sizeof_prop_value = sizeof(typename V::value_type);
478     if (sizeof(typename T::type) >= sizeof_prop_value)
479     {
480         return v->getSize() * sizeof(typename T::type) / sizeof_prop_value;
481     }
482     else
483     {
484         // increase the size to contain enough space, manage the size_t rounding issue
485         return v->getSize() * sizeof(typename T::type) + (sizeof_prop_value - 1) / sizeof_prop_value;
486     }
487 }
488
489 template <typename T>
490 T* decode(std::vector<int>::iterator& prop_it)
491 {
492     std::vector<int> dims;
493     decodeDims(prop_it, dims);
494
495     T* v = new T(static_cast<int>(dims.size()), &dims[0]);
496     memcpy(v->get(), &(*prop_it), v->getSize() * sizeof(typename T::type));
497
498     prop_it += required_length(prop_it, v);
499     return v;
500 }
501
502 template <typename T>
503 bool encode(std::vector<int>& prop_content, T* v)
504 {
505     encodeDims(prop_content, v);
506
507     const int index = (int)prop_content.size();
508     const int len = (int)required_length(prop_content, v);
509     prop_content.resize(index + len);
510
511     // Using contiguity of the memory, we save the input into 'prop_content'
512     memcpy(&prop_content[index], v->get(), v->getSize() * sizeof(typename T::type));
513     return true;
514 }
515
516 template<>
517 types::Double* decode(std::vector<int>::iterator& prop_it)
518 {
519     std::vector<int> dims;
520     decodeDims(prop_it, dims);
521
522     bool isComplex = *prop_it++ != 0;
523
524     types::Double* v = new types::Double(static_cast<int>(dims.size()), &dims[0], isComplex);
525     memcpy(v->getReal(), &(*prop_it), v->getSize() * sizeof(double));
526
527     if (isComplex)
528     {
529         prop_it += required_length(prop_it, v);
530         memcpy(v->getImg(), &(*prop_it), v->getSize() * sizeof(double));
531     }
532
533     prop_it += required_length(prop_it, v);
534     return v;
535 }
536
537 bool encode(std::vector<int>& prop_content, types::Double* v)
538 {
539     encodeDims(prop_content, v);
540
541     // Flag for complex
542     prop_content.push_back(v->isComplex());
543
544     const int index = (int)prop_content.size();
545     const int len = (int)required_length(prop_content, v);
546     prop_content.resize(index + len);
547
548     // Using contiguity of the memory, we save the input into 'prop_content'
549     memcpy(&prop_content[index], v->get(), v->getSize() * sizeof(double));
550
551     if (v->isComplex())
552     {
553         prop_content.resize(index + 2 * len);
554         // Using contiguity of the memory, we save the input into 'prop_content'
555         memcpy(&prop_content[index + len], v->getImg(), v->getSize() * sizeof(double));
556     }
557
558     return true;
559 }
560
561 template<>
562 types::String* decode(std::vector<int>::iterator& prop_it)
563 {
564     std::vector<int> dims;
565     decodeDims(prop_it, dims);
566
567     types::String* v = new types::String(static_cast<int>(dims.size()), &dims[0]);
568     // retrieving the first value iterator
569     std::vector<int>::iterator strData = prop_it + v->getSize();
570
571     v->set(0, (char*) & (*strData));
572     strData += static_cast<size_t>(*prop_it++);
573     for (int i = 1; i < v->getSize(); i++)
574     {
575         v->set(i, (char*) & (*strData));
576
577         // increment the value iterator by the number of element
578         const size_t numberOfElem = static_cast<size_t>(*prop_it) - static_cast<size_t>(*(prop_it - 1)) ;
579         prop_it++;
580         strData += numberOfElem;
581     }
582
583     prop_it = strData;
584     return v;
585 }
586
587 bool encode(std::vector<int>& prop_content, types::String* v)
588 {
589     encodeDims(prop_content, v);
590
591     const int index = (int)prop_content.size();
592
593     std::vector<char*> utf8;
594     utf8.reserve(v->getSize());
595
596     std::vector<size_t> str_len;
597     str_len.reserve(v->getSize());
598
599     size_t offset = 0;
600     for (int i = 0; i < v->getSize(); i++)
601     {
602         char* str = wide_string_to_UTF8(v->get(i));
603         utf8.push_back(str);
604
605         // adding the '\0' byte to the len
606         const size_t len = strlen(str) + 1;
607         str_len.push_back(len);
608
609         offset += (len * sizeof(char) + sizeof(int) - 1) / sizeof(int);
610         prop_content.push_back((int)offset);
611     }
612
613     // reserve space for the string offsets and contents
614     prop_content.resize(index + v->getSize() + offset);
615
616     size_t len = str_len[0];
617     memcpy(&prop_content[index + v->getSize()], &(*utf8[0]), len * sizeof(char));
618     for (int i = 1; i < v->getSize(); i++)
619     {
620         len = str_len[i];
621         memcpy(&prop_content[index + v->getSize() + prop_content[index + i - 1]], &(*utf8[i]), len * sizeof(char));
622     }
623
624     // free all the string, after being copied
625     for (std::vector<char*>::iterator it = utf8.begin(); it != utf8.end(); it++)
626     {
627         FREE(*it);
628     }
629
630     return true;
631 }
632
633
634 template<>
635 types::List* decode(std::vector<int>::iterator& prop_it)
636 {
637     int length = *prop_it++;
638
639     types::List* list = new types::List();
640     for (int i = 0; i < length; i++)
641     {
642         switch (*prop_it++)
643         {
644             case types::InternalType::ScilabDouble:
645                 list->set(i, decode<types::Double>(prop_it));
646                 break;
647             case types::InternalType::ScilabInt8:
648                 list->set(i, decode<types::Int8>(prop_it));
649                 break;
650             case types::InternalType::ScilabUInt8:
651                 list->set(i, decode<types::UInt8>(prop_it));
652                 break;
653             case types::InternalType::ScilabInt16:
654                 list->set(i, decode<types::Int16>(prop_it));
655                 break;
656             case types::InternalType::ScilabUInt16:
657                 list->set(i, decode<types::UInt16>(prop_it));
658                 break;
659             case types::InternalType::ScilabInt32:
660                 list->set(i, decode<types::Int32>(prop_it));
661                 break;
662             case types::InternalType::ScilabUInt32:
663                 list->set(i, decode<types::UInt32>(prop_it));
664                 break;
665             case types::InternalType::ScilabInt64:
666                 list->set(i, decode<types::Int64>(prop_it));
667                 break;
668             case types::InternalType::ScilabUInt64:
669                 list->set(i, decode<types::UInt64>(prop_it));
670                 break;
671             case types::InternalType::ScilabString:
672                 list->set(i, decode<types::String>(prop_it));
673                 break;
674             case types::InternalType::ScilabBool:
675                 list->set(i, decode<types::Bool>(prop_it));
676                 break;
677             case types::InternalType::ScilabList:
678                 list->set(i, decode<types::List>(prop_it));
679                 break;
680         }
681     }
682     return list;
683 }
684
685 bool encode(std::vector<int>& prop_content, types::List* list)
686 {
687     // Save the number of list elements in the first element
688     prop_content.push_back(list->getSize());
689
690     for (int i = 0; i < list->getSize(); ++i)
691     {
692         // Insert a new element and save its variable type
693         prop_content.push_back(list->get(i)->getType());
694
695         switch (list->get(i)->getType())
696         {
697             case types::InternalType::ScilabDouble:
698                 encode(prop_content, list->get(i)->getAs<types::Double>());
699                 break;
700             case types::InternalType::ScilabInt8:
701                 encode(prop_content, list->get(i)->getAs<types::Int8>());
702                 break;
703             case types::InternalType::ScilabUInt8:
704                 encode(prop_content, list->get(i)->getAs<types::UInt8>());
705                 break;
706             case types::InternalType::ScilabInt16:
707                 encode(prop_content, list->get(i)->getAs<types::Int16>());
708                 break;
709             case types::InternalType::ScilabUInt16:
710                 encode(prop_content, list->get(i)->getAs<types::UInt16>());
711                 break;
712             case types::InternalType::ScilabInt32:
713                 encode(prop_content, list->get(i)->getAs<types::Int32>());
714                 break;
715             case types::InternalType::ScilabUInt32:
716                 encode(prop_content, list->get(i)->getAs<types::UInt32>());
717                 break;
718             case types::InternalType::ScilabInt64:
719                 encode(prop_content, list->get(i)->getAs<types::Int64>());
720                 break;
721             case types::InternalType::ScilabUInt64:
722                 encode(prop_content, list->get(i)->getAs<types::UInt64>());
723                 break;
724             case types::InternalType::ScilabString:
725                 encode(prop_content, list->get(i)->getAs<types::String>());
726                 break;
727             case types::InternalType::ScilabBool:
728                 encode(prop_content, list->get(i)->getAs<types::Bool>());
729                 break;
730             default:
731                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : List expected.\n"), "model", "props");
732                 return false;
733         }
734     }
735
736     return true;
737 }
738
739 struct odstate
740 {
741
742     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
743     {
744         return get_with_vec2var(adaptor, controller, ODSTATE);
745     }
746
747     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
748     {
749         return set_with_var2vec(adaptor, v, controller, ODSTATE);
750     }
751 };
752
753 /*
754  * When setting a diagram in 'rpar', the Superblock's ports must be consistent with the "port blocks" inside it.
755  * By "port blocks", we mean IN_f, OUT_f, CLKIN_f, CLKOUT_f, CLKINV_f, CLKOUTV_f, INIMPL_f and OUTIMPL_f.
756  */
757 bool setInnerBlocksRefs(ModelAdapter& adaptor, const std::vector<ScicosID>& children, Controller& controller)
758 {
759     const std::string input ("input");
760     const std::string output ("output");
761     const std::string inimpl ("inimpl");
762     const std::string outimpl ("outimpl");
763
764     ScicosID adaptee = adaptor.getAdaptee()->id();
765
766     for (std::vector<ScicosID>::const_iterator it = children.begin(); it != children.end(); ++it)
767     {
768         if (*it == ScicosID())
769         {
770             continue; // Rule out mlists (Deleted or Annotations)
771         }
772
773         if (controller.getObject(*it)->kind() == BLOCK) // Rule out Annotations and Links
774         {
775             std::string name;
776             controller.getObjectProperty(*it, BLOCK, SIM_FUNCTION_NAME, name);
777
778             // Find the "port blocks"
779             if (name == input || name == inimpl || name == output || name == outimpl)
780             {
781                 std::vector<int> ipar;
782                 controller.getObjectProperty(*it, BLOCK, IPAR, ipar);
783                 if (ipar.size() != 1)
784                 {
785                     std::string uid;
786                     controller.getObjectProperty(*it, BLOCK, UID, uid);
787                     get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for field %s.%s : %s (%s) has an invalid port number.\n"), "model", "rpar", name.c_str(), uid.c_str());
788                     return false;
789                 }
790                 int portIndex = ipar[0];
791
792                 // "name" is not enough to tell the event and data ports apart, so check the block's port.
793                 object_properties_t kind;
794                 std::vector<ScicosID> innerPort;
795                 if (name == input || name == inimpl)
796                 {
797                     controller.getObjectProperty(*it, BLOCK, OUTPUTS, innerPort);
798                     if (!innerPort.empty())
799                     {
800                         kind = INPUTS;
801                     }
802                     else
803                     {
804                         kind = EVENT_INPUTS;
805                     }
806                 }
807                 else
808                 {
809                     controller.getObjectProperty(*it, BLOCK, INPUTS, innerPort);
810                     if (!innerPort.empty())
811                     {
812                         kind = OUTPUTS;
813                     }
814                     else
815                     {
816                         kind = EVENT_OUTPUTS;
817                     }
818                 }
819
820                 std::vector<ScicosID> superPorts;
821                 controller.getObjectProperty(adaptee, BLOCK, kind, superPorts);
822                 if (static_cast<int>(superPorts.size()) < portIndex)
823                 {
824                     if (!superPorts.empty())
825                     {
826                         // Arbitrarily take the highest possible value in case the user enters a wrong number
827                         portIndex = (int)superPorts.size();
828                     }
829                     else
830                     {
831                         std::string uid;
832                         controller.getObjectProperty(*it, BLOCK, UID, uid);
833                         get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for field %s.%s : %s (%s) has an invalid port number.\n"), "model", "rpar", name.c_str(), uid.c_str());
834                         return false;
835                     }
836                 }
837
838                 ScicosID port = superPorts[portIndex - 1];
839
840                 // Check consistency of the implicitness between the inner and outer ports
841                 bool isImplicit;
842                 controller.getObjectProperty(port, PORT, IMPLICIT, isImplicit);
843                 if (name == input || name == output)
844                 {
845                     if (isImplicit)
846                     {
847                         std::string uid;
848                         controller.getObjectProperty(*it, BLOCK, UID, uid);
849                         get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for field %s.%s : %s (%s) has an invalid implicit port.\n"), "model", "rpar", name.c_str(), uid.c_str());
850                         return false;
851                     }
852                 }
853                 else
854                 {
855                     if (!isImplicit)
856                     {
857                         std::string uid;
858                         controller.getObjectProperty(*it, BLOCK, UID, uid);
859                         get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for field %s.%s : %s (%s) has an invalid explicit port.\n"), "model", "rpar", name.c_str(), uid.c_str());
860                         return false;
861                     }
862                 }
863
864                 controller.setObjectProperty(*it, BLOCK, PORT_REFERENCE, port);
865             }
866         }
867     }
868     return true;
869 }
870
871 struct rpar
872 {
873
874     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
875     {
876         ScicosID adaptee = adaptor.getAdaptee()->id();
877
878         std::vector<ScicosID> diagramChildren;
879         controller.getObjectProperty(adaptee, BLOCK, CHILDREN, diagramChildren);
880
881         if (diagramChildren.empty())
882         {
883             std::vector<double> rpar;
884             controller.getObjectProperty(adaptee, BLOCK, RPAR, rpar);
885
886             double *data;
887             types::Double* o = new types::Double((int)rpar.size(), 1, &data);
888 #ifdef _MSC_VER
889             std::copy(rpar.begin(), rpar.end(), stdext::checked_array_iterator<double*>(data, rpar.size()));
890 #else
891             std::copy(rpar.begin(), rpar.end(), data);
892 #endif
893             return o;
894         }
895         else // SuperBlock, return the contained diagram (allocating it on demand)
896         {
897             DiagramAdapter* d = new DiagramAdapter(controller, controller.referenceObject(adaptor.getAdaptee()));
898             return d;
899         }
900     }
901
902     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
903     {
904         ScicosID adaptee = adaptor.getAdaptee()->id();
905
906         if (v->getType() == types::InternalType::ScilabDouble)
907         {
908             types::Double* current = v->getAs<types::Double>();
909
910             std::vector<double> rpar (current->getSize());
911             for (int i = 0; i < current->getSize(); ++i)
912             {
913                 rpar[i] = current->get(i);
914             }
915
916             controller.setObjectProperty(adaptee, BLOCK, RPAR, rpar);
917             return true;
918         }
919         else if (v->getType() == types::InternalType::ScilabString)
920         {
921             // Allow Text blocks to define strings in rpar
922             return true;
923         }
924         else if (v->getType() == types::InternalType::ScilabUserType)
925         {
926             // Make sure the input describes a Diagram
927             const Adapters::adapters_index_t adapter_index = Adapters::instance().lookup_by_typename(v->getShortTypeStr());
928             if (adapter_index != Adapters::DIAGRAM_ADAPTER)
929             {
930                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : Diagram expected.\n"), "model", "rpar");
931                 return false;
932             }
933             const DiagramAdapter* diagram = v->getAs<DiagramAdapter>();
934             DiagramAdapter* superblock = new DiagramAdapter(controller, controller.referenceObject(adaptor.getAdaptee()));
935
936             // copy the values by name to preserve adaptors specific properties
937             superblock->copyProperties(*diagram, controller);
938
939             superblock->killMe();
940             return true;
941         }
942         else if (v->getType() == types::InternalType::ScilabMList)
943         {
944             DiagramAdapter* diagram = new DiagramAdapter(controller, controller.referenceObject(adaptor.getAdaptee()));
945             if (!diagram->setAsTList(v, controller))
946             {
947                 diagram->killMe();
948                 return false;
949             }
950
951             diagram->killMe();
952             return true;
953         }
954         else
955         {
956             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : Real matrix expected.\n"), "model", "rpar");
957             return false;
958         }
959     }
960 };
961
962 double toDouble(const int a)
963 {
964     return static_cast<double>(a);
965 }
966
967 struct ipar
968 {
969
970     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
971     {
972         ScicosID adaptee = adaptor.getAdaptee()->id();
973
974         std::vector<int> ipar;
975         controller.getObjectProperty(adaptee, BLOCK, IPAR, ipar);
976
977         double *data;
978         types::Double* o = new types::Double((int)ipar.size(), 1, &data);
979
980 #ifdef _MSC_VER
981         std::transform(ipar.begin(), ipar.end(), stdext::checked_array_iterator<double*>(data, ipar.size()), toDouble);
982 #else
983         std::transform(ipar.begin(), ipar.end(), data, toDouble);
984 #endif
985         return o;
986     }
987
988     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
989     {
990         ScicosID adaptee = adaptor.getAdaptee()->id();
991
992         if (v->getType() == types::InternalType::ScilabList)
993         {
994             std::vector<int> ipar;
995             controller.setObjectProperty(adaptee, BLOCK, IPAR, ipar);
996             get_or_allocate_logger()->log(LOG_TRACE, _("Wrong type for field %s.%s : List clear previous value.\n"), "model", "ipar");
997             return true;
998         }
999
1000         // FIXME: ScilabInts should be managed there
1001         if (v->getType() != types::InternalType::ScilabDouble)
1002         {
1003             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : Real matrix expected.\n"), "model", "ipar");
1004             return false;
1005         }
1006         types::Double* current = v->getAs<types::Double>();
1007         // Only allow vectors and empty matrices
1008         if (!current->isVector() && current->getSize() != 0)
1009         {
1010             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s : m-by-1 matrix expected.\n"), "model", "ipar");
1011             return false;
1012         }
1013
1014         std::vector<int> ipar (current->getSize());
1015         for (int i = 0; i < current->getSize(); ++i)
1016         {
1017             if (floor(current->get(i)) != current->get(i))
1018             {
1019                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for field %s.%s : Integer values expected.\n"), "model", "ipar");
1020                 return false;
1021             }
1022             ipar[i] = static_cast<int>(current->get(i));
1023         }
1024
1025         controller.setObjectProperty(adaptee, BLOCK, IPAR, ipar);
1026         return true;
1027     }
1028 };
1029
1030 struct opar
1031 {
1032
1033     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1034     {
1035         return get_with_vec2var(adaptor, controller, OPAR);
1036     }
1037
1038     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1039     {
1040         return set_with_var2vec(adaptor, v, controller, OPAR);
1041     }
1042 };
1043
1044 struct blocktype
1045 {
1046
1047     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1048     {
1049         ScicosID adaptee = adaptor.getAdaptee()->id();
1050
1051         std::string type;
1052         controller.getObjectProperty(adaptee, BLOCK, SIM_BLOCKTYPE, type);
1053
1054         types::String* o = new types::String(type.c_str());
1055         return o;
1056     }
1057
1058     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1059     {
1060         ScicosID adaptee = adaptor.getAdaptee()->id();
1061
1062         if (v->getType() != types::InternalType::ScilabString)
1063         {
1064             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : String expected.\n"), "model", "blocktype");
1065             return false;
1066         }
1067
1068         types::String* current = v->getAs<types::String>();
1069         if (current->getSize() != 1)
1070         {
1071             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s : String expected.\n"), "model", "blocktype");
1072             return false;
1073         }
1074
1075         char* c_str = wide_string_to_UTF8(current->get(0));
1076         std::string type (c_str);
1077         FREE(c_str);
1078
1079         // the value validation is performed on the model
1080         return controller.setObjectProperty(adaptee, BLOCK, SIM_BLOCKTYPE, type) != FAIL;
1081     }
1082 };
1083
1084 struct firing
1085 {
1086
1087     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1088     {
1089         return get_ports_property<ModelAdapter, FIRING>(adaptor, EVENT_OUTPUTS, controller);
1090     }
1091
1092     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1093     {
1094         return set_ports_property<ModelAdapter, FIRING>(adaptor, EVENT_OUTPUTS, controller, v);
1095     }
1096 };
1097
1098 struct dep_ut
1099 {
1100
1101     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1102     {
1103         ScicosID adaptee = adaptor.getAdaptee()->id();
1104
1105         std::vector<int> dep_ut;
1106         controller.getObjectProperty(adaptee, BLOCK, SIM_DEP_UT, dep_ut);
1107
1108         int* dep;
1109         types::Bool* o = new types::Bool(1, 2, &dep);
1110
1111         dep[0] = dep_ut[0];
1112         dep[1] = dep_ut[1];
1113
1114         return o;
1115     }
1116
1117     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1118     {
1119         ScicosID adaptee = adaptor.getAdaptee()->id();
1120
1121         if (v->getType() != types::InternalType::ScilabBool)
1122         {
1123             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : Boolean matrix expected.\n"), "model", "dep_ut");
1124             return false;
1125         }
1126
1127         types::Bool* current = v->getAs<types::Bool>();
1128         if (current->getSize() != 2)
1129         {
1130             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s : %d-by-%d expected.\n"), "model", "dep_ut", 1, 2);
1131             return false;
1132         }
1133
1134         std::vector<int> dep_ut (2);
1135         dep_ut[0] = current->get(0);
1136         dep_ut[1] = current->get(1);
1137
1138         controller.setObjectProperty(adaptee, BLOCK, SIM_DEP_UT, dep_ut);
1139         return true;
1140     }
1141 };
1142
1143 // Valid C identifier definition
1144 // https://msdn.microsoft.com/en-us/library/e7f8y25b.aspx
1145 bool isValidCIdentifier(const std::string& label)
1146 {
1147     auto is_nondigit = [](char c)
1148     {
1149         return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || '_' == c;
1150     };
1151     auto is_digit = [](char c)
1152     {
1153         return ('0' <= c && c <= '9');
1154     };
1155
1156     // is a valid but empty string
1157     if (label.empty())
1158     {
1159         return true;
1160     }
1161     // the first character should be a non digit
1162     if (!is_nondigit(label[0]))
1163     {
1164         return false;
1165     }
1166     // others  should be either a digit or a non digit
1167     auto found = std::find_if_not(label.begin(), label.end(), [is_nondigit, is_digit](char c)
1168     {
1169         return is_nondigit(c) || is_digit(c);
1170     } );
1171     return found == label.end();
1172 }
1173
1174 struct label
1175 {
1176     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1177     {
1178         ScicosID adaptee = adaptor.getAdaptee()->id();
1179
1180         ScicosID label;
1181         std::string description;
1182
1183         controller.getObjectProperty(adaptee, BLOCK, LABEL, label);
1184         if (label != ScicosID())
1185         {
1186             controller.getObjectProperty(label, ANNOTATION, DESCRIPTION, description);
1187         }
1188         else
1189         {
1190             controller.getObjectProperty(adaptee, BLOCK, DESCRIPTION, description);
1191         }
1192
1193         types::String* o = new types::String(1, 1);
1194
1195         // safety check ; the returned value should always be a valid C / modelica identifier
1196         if (isValidCIdentifier(description))
1197         {
1198             o->set(0, description.data());
1199         }
1200         else
1201         {
1202             o->set(0, "");
1203         }
1204         return o;
1205     }
1206
1207     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1208     {
1209         if (v->getType() != types::InternalType::ScilabString)
1210         {
1211             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : String expected.\n"), "model", "label");
1212             return false;
1213         }
1214
1215         types::String* current = v->getAs<types::String>();
1216         if (current->getSize() != 1)
1217         {
1218             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s : String expected.\n"), "model", "label");
1219             return false;
1220         }
1221
1222         ScicosID adaptee = adaptor.getAdaptee()->id();
1223
1224         char* c_str = wide_string_to_UTF8(current->get(0));
1225         std::string description(c_str);
1226         FREE(c_str);
1227
1228         // TODO: validate a C/Scilab identifier only
1229         //        if (!isValidCIdentifier(label))
1230         //        {
1231         //            get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for field %s.%s : Valid C identifier expected.\n"), "model", "label");
1232         //            return false;
1233         //        }
1234
1235         controller.setObjectProperty(adaptee, BLOCK, DESCRIPTION, description);
1236         return true;
1237     }
1238 };
1239
1240 struct nzcross
1241 {
1242
1243     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1244     {
1245         ScicosID adaptee = adaptor.getAdaptee()->id();
1246
1247         std::vector<int> nzcross;
1248         controller.getObjectProperty(adaptee, BLOCK, NZCROSS, nzcross);
1249
1250         double *data;
1251         types::Double* o = new types::Double((int)nzcross.size(), 1, &data);
1252
1253 #ifdef _MSC_VER
1254         std::transform(nzcross.begin(), nzcross.end(), stdext::checked_array_iterator<double*>(data, nzcross.size()), toDouble);
1255 #else
1256         std::transform(nzcross.begin(), nzcross.end(), data, toDouble);
1257 #endif
1258         return o;
1259     }
1260
1261     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1262     {
1263         ScicosID adaptee = adaptor.getAdaptee()->id();
1264
1265         if (v->getType() != types::InternalType::ScilabDouble)
1266         {
1267             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : Real matrix expected.\n"), "model", "nzcross");
1268             return false;
1269         }
1270
1271         types::Double* current = v->getAs<types::Double>();
1272         // Only allow vectors and empty matrices
1273         if (!current->isVector() && current->getSize() != 0)
1274         {
1275             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s : m-by-1 expected.\n"), "model", "nzcross");
1276             return false;
1277         }
1278
1279         std::vector<int> nzcross (current->getSize());
1280         for (int i = 0; i < current->getSize(); ++i)
1281         {
1282             if (floor(current->get(i)) != current->get(i))
1283             {
1284                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for field %s.%s : Integer values expected.\n"), "model", "nzcross");
1285                 return false;
1286             }
1287             nzcross[i] = static_cast<int>(current->get(i));
1288         }
1289
1290         controller.setObjectProperty(adaptee, BLOCK, NZCROSS, nzcross);
1291         return true;
1292     }
1293 };
1294
1295 struct nmode
1296 {
1297
1298     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1299     {
1300         ScicosID adaptee = adaptor.getAdaptee()->id();
1301
1302         std::vector<int> nmode;
1303         controller.getObjectProperty(adaptee, BLOCK, NMODE, nmode);
1304
1305         double *data;
1306         types::Double* o = new types::Double((int)nmode.size(), 1, &data);
1307
1308 #ifdef _MSC_VER
1309         std::transform(nmode.begin(), nmode.end(), stdext::checked_array_iterator<double*>(data, nmode.size()), toDouble);
1310 #else
1311         std::transform(nmode.begin(), nmode.end(), data, toDouble);
1312 #endif
1313         return o;
1314     }
1315
1316     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1317     {
1318         ScicosID adaptee = adaptor.getAdaptee()->id();
1319
1320         if (v->getType() != types::InternalType::ScilabDouble)
1321         {
1322             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : Real matrix expected.\n"), "model", "nmode");
1323             return false;
1324         }
1325
1326         types::Double* current = v->getAs<types::Double>();
1327         // Only allow vectors and empty matrices
1328         if (!current->isVector() && current->getSize() != 0)
1329         {
1330             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s : m-by-1 expected.\n"), "model", "nzcross");
1331             return false;
1332         }
1333
1334         std::vector<int> nmode (current->getSize());
1335         for (int i = 0; i < current->getSize(); ++i)
1336         {
1337             if (floor(current->get(i)) != current->get(i))
1338             {
1339                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for field %s.%s : Integer values expected.\n"), "model", "nzcross");
1340                 return false;
1341             }
1342             nmode[i] = static_cast<int>(current->get(i));
1343         }
1344
1345         controller.setObjectProperty(adaptee, BLOCK, NMODE, nmode);
1346         return true;
1347     }
1348 };
1349
1350 struct equations
1351 {
1352
1353     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1354     {
1355         return get_with_vec2var(adaptor, controller, EQUATIONS);
1356     }
1357
1358     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1359     {
1360         return set_with_var2vec(adaptor, v, controller, EQUATIONS);
1361     }
1362 };
1363
1364 struct uid
1365 {
1366
1367     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1368     {
1369         ScicosID adaptee = adaptor.getAdaptee()->id();
1370
1371         std::string uid;
1372         controller.getObjectProperty(adaptee, BLOCK, UID, uid);
1373
1374         types::String* o = new types::String(1, 1);
1375         o->set(0, uid.data());
1376
1377         return o;
1378     }
1379
1380     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1381     {
1382         if (v->getType() != types::InternalType::ScilabString)
1383         {
1384             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : String expected.\n"), "model", "uid");
1385             return false;
1386         }
1387
1388         types::String* current = v->getAs<types::String>();
1389         if (current->getSize() != 1)
1390         {
1391             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s : String expected.\n"), "model", "uid");
1392             return false;
1393         }
1394
1395         ScicosID adaptee = adaptor.getAdaptee()->id();
1396
1397         char* c_str = wide_string_to_UTF8(current->get(0));
1398         std::string uid(c_str);
1399         FREE(c_str);
1400
1401         controller.setObjectProperty(adaptee, BLOCK, UID, uid);
1402         return true;
1403     }
1404 };
1405
1406 } /* namespace */
1407
1408 template<> property<ModelAdapter>::props_t property<ModelAdapter>::fields = property<ModelAdapter>::props_t();
1409 static void initialize_fields()
1410 {
1411     if (property<ModelAdapter>::properties_have_not_been_set())
1412     {
1413         property<ModelAdapter>::fields.reserve(23);
1414         property<ModelAdapter>::add_property(L"sim", &sim::get, &sim::set);
1415         property<ModelAdapter>::add_property(L"in", &in::get, &in::set);
1416         property<ModelAdapter>::add_property(L"in2", &in2::get, &in2::set);
1417         property<ModelAdapter>::add_property(L"intyp", &intyp::get, &intyp::set);
1418         property<ModelAdapter>::add_property(L"out", &out::get, &out::set);
1419         property<ModelAdapter>::add_property(L"out2", &out2::get, &out2::set);
1420         property<ModelAdapter>::add_property(L"outtyp", &outtyp::get, &outtyp::set);
1421         property<ModelAdapter>::add_property(L"evtin", &evtin::get, &evtin::set);
1422         property<ModelAdapter>::add_property(L"evtout", &evtout::get, &evtout::set);
1423         property<ModelAdapter>::add_property(L"state", &state::get, &state::set);
1424         property<ModelAdapter>::add_property(L"dstate", &dstate::get, &dstate::set);
1425         property<ModelAdapter>::add_property(L"odstate", &odstate::get, &odstate::set);
1426         property<ModelAdapter>::add_property(L"rpar", &rpar::get, &rpar::set);
1427         property<ModelAdapter>::add_property(L"ipar", &ipar::get, &ipar::set);
1428         property<ModelAdapter>::add_property(L"opar", &opar::get, &opar::set);
1429         property<ModelAdapter>::add_property(L"blocktype", &blocktype::get, &blocktype::set);
1430         property<ModelAdapter>::add_property(L"firing", &firing::get, &firing::set);
1431         property<ModelAdapter>::add_property(L"dep_ut", &dep_ut::get, &dep_ut::set);
1432         property<ModelAdapter>::add_property(L"label", &label::get, &label::set);
1433         property<ModelAdapter>::add_property(L"nzcross", &nzcross::get, &nzcross::set);
1434         property<ModelAdapter>::add_property(L"nmode", &nmode::get, &nmode::set);
1435         property<ModelAdapter>::add_property(L"equations", &equations::get, &equations::set);
1436         property<ModelAdapter>::add_property(L"uid", &uid::get, &uid::set);
1437     }
1438 }
1439
1440 ModelAdapter::ModelAdapter() :
1441     BaseAdapter<ModelAdapter, org_scilab_modules_scicos::model::Block>()
1442 {
1443     initialize_fields();
1444 }
1445
1446 ModelAdapter::ModelAdapter(const Controller& c, model::Block* adaptee) :
1447     BaseAdapter<ModelAdapter, org_scilab_modules_scicos::model::Block>(c, adaptee)
1448 {
1449     initialize_fields();
1450 }
1451
1452 ModelAdapter::~ModelAdapter()
1453 {
1454 }
1455
1456 std::wstring ModelAdapter::getTypeStr() const
1457 {
1458     return getSharedTypeStr();
1459 }
1460
1461 std::wstring ModelAdapter::getShortTypeStr() const
1462 {
1463     return getSharedTypeStr();
1464 }
1465
1466 } /* namespace view_scilab */
1467 } /* namespace org_scilab_modules_scicos */