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