Xcos MVC: fix after 4b9d000e
[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                 controller.referenceObject(o);
995                 LinkAdapter newLink(controller, static_cast<model::Link*>(o));
996                 newLink.setFromInModel(diagram->getFrom()[i], controller);
997                 newLink.setToInModel(diagram->getTo()[i], controller);
998             }
999
1000             // Save the context
1001             std::vector<std::string> context;
1002             controller.getObjectProperty(diagram->getAdaptee()->id(), DIAGRAM, DIAGRAM_CONTEXT, context);
1003             controller.setObjectProperty(adaptor.getAdaptee()->id(), BLOCK, DIAGRAM_CONTEXT, context);
1004
1005             // Link the Superblock ports to their inner "port blocks"
1006             return setInnerBlocksRefs(adaptor, diagramChildren, controller);
1007         }
1008         else if (v->getType() == types::InternalType::ScilabMList)
1009         {
1010             ScicosID localAdaptee = controller.createObject(DIAGRAM);
1011             DiagramAdapter* diagram = new DiagramAdapter(controller, controller.getObject<model::Diagram>(localAdaptee));
1012             if (!diagram->setAsTList(v, controller))
1013             {
1014                 diagram->killMe();
1015                 return false;
1016             }
1017
1018             adaptor.setDiagram(diagram);
1019
1020             // set the diagram children as block children ; referencing them
1021             std::vector<ScicosID> diagramChildren;
1022             controller.getObjectProperty(diagram->getAdaptee()->id(), DIAGRAM, CHILDREN, diagramChildren);
1023             if (diagramChildren.empty())
1024             {
1025                 // bug_12998: If inserting an empty diagram in 'rpar', simulate an empty object
1026                 diagramChildren.push_back(ScicosID());
1027             }
1028             std::vector<ScicosID> oldDiagramChildren;
1029             controller.getObjectProperty(adaptor.getAdaptee()->id(), BLOCK, CHILDREN, oldDiagramChildren);
1030
1031             controller.setObjectProperty(adaptor.getAdaptee()->id(), BLOCK, CHILDREN, diagramChildren);
1032             {
1033                 std::sort(oldDiagramChildren.begin(), oldDiagramChildren.end());
1034                 for (const ScicosID id : diagramChildren)
1035                 {
1036                     if (id != 0 && !std::binary_search(oldDiagramChildren.begin(), oldDiagramChildren.end(), id))
1037                     {
1038                         auto o = controller.getObject(id);
1039                         controller.setObjectProperty(o->id(), o->kind(), PARENT_BLOCK, adaptor.getAdaptee()->id());
1040
1041                         controller.referenceObject(id);
1042                     }
1043                 }
1044
1045                 std::sort(diagramChildren.begin(), diagramChildren.end());
1046                 for (const ScicosID id : oldDiagramChildren)
1047                 {
1048                     if (id != 0 && !std::binary_search(diagramChildren.begin(), diagramChildren.end(), id))
1049                     {
1050                         auto o = controller.getObject(id);
1051                         controller.setObjectProperty(o->id(), o->kind(), PARENT_BLOCK, ScicosID());
1052
1053                         controller.deleteObject(id);
1054                     }
1055                 }
1056             }
1057
1058             // Link the Superblock ports to their inner "port blocks"
1059             return setInnerBlocksRefs(adaptor, diagramChildren, controller);
1060         }
1061         else
1062         {
1063             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : Real matrix expected.\n"), "model", "rpar");
1064             return false;
1065         }
1066     }
1067 };
1068
1069 double toDouble(const int a)
1070 {
1071     return static_cast<double>(a);
1072 }
1073
1074 struct ipar
1075 {
1076
1077     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1078     {
1079         ScicosID adaptee = adaptor.getAdaptee()->id();
1080
1081         std::vector<int> ipar;
1082         controller.getObjectProperty(adaptee, BLOCK, IPAR, ipar);
1083
1084         double *data;
1085         types::Double* o = new types::Double((int)ipar.size(), 1, &data);
1086
1087 #ifdef _MSC_VER
1088         std::transform(ipar.begin(), ipar.end(), stdext::checked_array_iterator<double*>(data, ipar.size()), toDouble);
1089 #else
1090         std::transform(ipar.begin(), ipar.end(), data, toDouble);
1091 #endif
1092         return o;
1093     }
1094
1095     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1096     {
1097         ScicosID adaptee = adaptor.getAdaptee()->id();
1098
1099         if (v->getType() == types::InternalType::ScilabList)
1100         {
1101             std::vector<int> ipar;
1102             controller.setObjectProperty(adaptee, BLOCK, IPAR, ipar);
1103             get_or_allocate_logger()->log(LOG_TRACE, _("Wrong type for field %s.%s : List clear previous value.\n"), "model", "ipar");
1104             return true;
1105         }
1106
1107         // FIXME: ScilabInts should be managed there
1108         if (v->getType() != types::InternalType::ScilabDouble)
1109         {
1110             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : Real matrix expected.\n"), "model", "ipar");
1111             return false;
1112         }
1113         types::Double* current = v->getAs<types::Double>();
1114         // Only allow vectors and empty matrices
1115         if (!current->isVector() && current->getSize() != 0)
1116         {
1117             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s : m-by-1 matrix expected.\n"), "model", "ipar");
1118             return false;
1119         }
1120
1121         std::vector<int> ipar (current->getSize());
1122         for (int i = 0; i < current->getSize(); ++i)
1123         {
1124             if (floor(current->get(i)) != current->get(i))
1125             {
1126                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for field %s.%s : Integer values expected.\n"), "model", "ipar");
1127                 return false;
1128             }
1129             ipar[i] = static_cast<int>(current->get(i));
1130         }
1131
1132         controller.setObjectProperty(adaptee, BLOCK, IPAR, ipar);
1133         return true;
1134     }
1135 };
1136
1137 struct opar
1138 {
1139
1140     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1141     {
1142         return get_with_vec2var(adaptor, controller, OPAR);
1143     }
1144
1145     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1146     {
1147         return set_with_var2vec(adaptor, v, controller, OPAR);
1148     }
1149 };
1150
1151 struct blocktype
1152 {
1153
1154     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1155     {
1156         ScicosID adaptee = adaptor.getAdaptee()->id();
1157
1158         std::string type;
1159         controller.getObjectProperty(adaptee, BLOCK, SIM_BLOCKTYPE, type);
1160
1161         types::String* o = new types::String(type.c_str());
1162         return o;
1163     }
1164
1165     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1166     {
1167         ScicosID adaptee = adaptor.getAdaptee()->id();
1168
1169         if (v->getType() != types::InternalType::ScilabString)
1170         {
1171             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : String expected.\n"), "model", "blocktype");
1172             return false;
1173         }
1174
1175         types::String* current = v->getAs<types::String>();
1176         if (current->getSize() != 1)
1177         {
1178             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s : String expected.\n"), "model", "blocktype");
1179             return false;
1180         }
1181
1182         char* c_str = wide_string_to_UTF8(current->get(0));
1183         std::string type (c_str);
1184         FREE(c_str);
1185
1186         // the value validation is performed on the model
1187         return controller.setObjectProperty(adaptee, BLOCK, SIM_BLOCKTYPE, type) != FAIL;
1188     }
1189 };
1190
1191 struct firing
1192 {
1193
1194     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1195     {
1196         return get_ports_property<ModelAdapter, FIRING>(adaptor, EVENT_OUTPUTS, controller);
1197     }
1198
1199     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1200     {
1201         return set_ports_property<ModelAdapter, FIRING>(adaptor, EVENT_OUTPUTS, controller, v);
1202     }
1203 };
1204
1205 struct dep_ut
1206 {
1207
1208     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1209     {
1210         ScicosID adaptee = adaptor.getAdaptee()->id();
1211
1212         std::vector<int> dep_ut;
1213         controller.getObjectProperty(adaptee, BLOCK, SIM_DEP_UT, dep_ut);
1214
1215         int* dep;
1216         types::Bool* o = new types::Bool(1, 2, &dep);
1217
1218         dep[0] = dep_ut[0];
1219         dep[1] = dep_ut[1];
1220
1221         return o;
1222     }
1223
1224     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1225     {
1226         ScicosID adaptee = adaptor.getAdaptee()->id();
1227
1228         if (v->getType() != types::InternalType::ScilabBool)
1229         {
1230             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : Boolean matrix expected.\n"), "model", "dep_ut");
1231             return false;
1232         }
1233
1234         types::Bool* current = v->getAs<types::Bool>();
1235         if (current->getSize() != 2)
1236         {
1237             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s : %d-by-%d expected.\n"), "model", "dep_ut", 1, 2);
1238             return false;
1239         }
1240
1241         std::vector<int> dep_ut (2);
1242         dep_ut[0] = current->get(0);
1243         dep_ut[1] = current->get(1);
1244
1245         controller.setObjectProperty(adaptee, BLOCK, SIM_DEP_UT, dep_ut);
1246         return true;
1247     }
1248 };
1249
1250 // Valid C identifier definition
1251 // https://msdn.microsoft.com/en-us/library/e7f8y25b.aspx
1252 bool isValidCIdentifier(const std::string& label)
1253 {
1254     auto is_nondigit = [](char c)
1255     {
1256         return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || '_' == c;
1257     };
1258     auto is_digit = [](char c)
1259     {
1260         return ('0' <= c && c <= '9');
1261     };
1262
1263     // is a valid but empty string
1264     if (label.empty())
1265     {
1266         return true;
1267     }
1268     // the first character should be a non digit
1269     if (!is_nondigit(label[0]))
1270     {
1271         return false;
1272     }
1273     // others  should be either a digit or a non digit
1274     auto found = std::find_if_not(label.begin(), label.end(), [is_nondigit, is_digit](char c)
1275     {
1276         return is_nondigit(c) || is_digit(c);
1277     } );
1278     return found == label.end();
1279 }
1280
1281 struct label
1282 {
1283     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1284     {
1285         ScicosID adaptee = adaptor.getAdaptee()->id();
1286
1287         std::string label;
1288         controller.getObjectProperty(adaptee, BLOCK, LABEL, label);
1289
1290         types::String* o = new types::String(1, 1);
1291
1292         // safety check ; the returned value should always be a valid C / modelica identifier
1293         if (isValidCIdentifier(label))
1294         {
1295             o->set(0, label.data());
1296         }
1297         else
1298         {
1299             o->set(0, "");
1300         }
1301         return o;
1302     }
1303
1304     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1305     {
1306         if (v->getType() != types::InternalType::ScilabString)
1307         {
1308             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : String expected.\n"), "model", "label");
1309             return false;
1310         }
1311
1312         types::String* current = v->getAs<types::String>();
1313         if (current->getSize() != 1)
1314         {
1315             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s : String expected.\n"), "model", "label");
1316             return false;
1317         }
1318
1319         ScicosID adaptee = adaptor.getAdaptee()->id();
1320
1321         char* c_str = wide_string_to_UTF8(current->get(0));
1322         std::string label(c_str);
1323         FREE(c_str);
1324
1325         if (!isValidCIdentifier(label))
1326         {
1327             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for field %s.%s : Valid C identifier expected.\n"), "model", "label");
1328             return false;
1329         }
1330
1331         controller.setObjectProperty(adaptee, BLOCK, LABEL, label);
1332         return true;
1333     }
1334 };
1335
1336 struct nzcross
1337 {
1338
1339     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1340     {
1341         ScicosID adaptee = adaptor.getAdaptee()->id();
1342
1343         std::vector<int> nzcross;
1344         controller.getObjectProperty(adaptee, BLOCK, NZCROSS, nzcross);
1345
1346         double *data;
1347         types::Double* o = new types::Double((int)nzcross.size(), 1, &data);
1348
1349 #ifdef _MSC_VER
1350         std::transform(nzcross.begin(), nzcross.end(), stdext::checked_array_iterator<double*>(data, nzcross.size()), toDouble);
1351 #else
1352         std::transform(nzcross.begin(), nzcross.end(), data, toDouble);
1353 #endif
1354         return o;
1355     }
1356
1357     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1358     {
1359         ScicosID adaptee = adaptor.getAdaptee()->id();
1360
1361         if (v->getType() != types::InternalType::ScilabDouble)
1362         {
1363             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : Real matrix expected.\n"), "model", "nzcross");
1364             return false;
1365         }
1366
1367         types::Double* current = v->getAs<types::Double>();
1368         // Only allow vectors and empty matrices
1369         if (!current->isVector() && current->getSize() != 0)
1370         {
1371             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s : m-by-1 expected.\n"), "model", "nzcross");
1372             return false;
1373         }
1374
1375         std::vector<int> nzcross (current->getSize());
1376         for (int i = 0; i < current->getSize(); ++i)
1377         {
1378             if (floor(current->get(i)) != current->get(i))
1379             {
1380                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for field %s.%s : Integer values expected.\n"), "model", "nzcross");
1381                 return false;
1382             }
1383             nzcross[i] = static_cast<int>(current->get(i));
1384         }
1385
1386         controller.setObjectProperty(adaptee, BLOCK, NZCROSS, nzcross);
1387         return true;
1388     }
1389 };
1390
1391 struct nmode
1392 {
1393
1394     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1395     {
1396         ScicosID adaptee = adaptor.getAdaptee()->id();
1397
1398         std::vector<int> nmode;
1399         controller.getObjectProperty(adaptee, BLOCK, NMODE, nmode);
1400
1401         double *data;
1402         types::Double* o = new types::Double((int)nmode.size(), 1, &data);
1403
1404 #ifdef _MSC_VER
1405         std::transform(nmode.begin(), nmode.end(), stdext::checked_array_iterator<double*>(data, nmode.size()), toDouble);
1406 #else
1407         std::transform(nmode.begin(), nmode.end(), data, toDouble);
1408 #endif
1409         return o;
1410     }
1411
1412     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1413     {
1414         ScicosID adaptee = adaptor.getAdaptee()->id();
1415
1416         if (v->getType() != types::InternalType::ScilabDouble)
1417         {
1418             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : Real matrix expected.\n"), "model", "nmode");
1419             return false;
1420         }
1421
1422         types::Double* current = v->getAs<types::Double>();
1423         // Only allow vectors and empty matrices
1424         if (!current->isVector() && current->getSize() != 0)
1425         {
1426             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s : m-by-1 expected.\n"), "model", "nzcross");
1427             return false;
1428         }
1429
1430         std::vector<int> nmode (current->getSize());
1431         for (int i = 0; i < current->getSize(); ++i)
1432         {
1433             if (floor(current->get(i)) != current->get(i))
1434             {
1435                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for field %s.%s : Integer values expected.\n"), "model", "nzcross");
1436                 return false;
1437             }
1438             nmode[i] = static_cast<int>(current->get(i));
1439         }
1440
1441         controller.setObjectProperty(adaptee, BLOCK, NMODE, nmode);
1442         return true;
1443     }
1444 };
1445
1446 struct equations
1447 {
1448
1449     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1450     {
1451         return get_with_vec2var(adaptor, controller, EQUATIONS);
1452     }
1453
1454     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1455     {
1456         return set_with_var2vec(adaptor, v, controller, EQUATIONS);
1457     }
1458 };
1459
1460 struct uid
1461 {
1462
1463     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1464     {
1465         ScicosID adaptee = adaptor.getAdaptee()->id();
1466
1467         std::string uid;
1468         controller.getObjectProperty(adaptee, BLOCK, UID, uid);
1469
1470         types::String* o = new types::String(1, 1);
1471         o->set(0, uid.data());
1472
1473         return o;
1474     }
1475
1476     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1477     {
1478         if (v->getType() != types::InternalType::ScilabString)
1479         {
1480             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : String expected.\n"), "model", "uid");
1481             return false;
1482         }
1483
1484         types::String* current = v->getAs<types::String>();
1485         if (current->getSize() != 1)
1486         {
1487             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s : String expected.\n"), "model", "uid");
1488             return false;
1489         }
1490
1491         ScicosID adaptee = adaptor.getAdaptee()->id();
1492
1493         char* c_str = wide_string_to_UTF8(current->get(0));
1494         std::string uid(c_str);
1495         FREE(c_str);
1496
1497         controller.setObjectProperty(adaptee, BLOCK, UID, uid);
1498         return true;
1499     }
1500 };
1501
1502 } /* namespace */
1503
1504 template<> property<ModelAdapter>::props_t property<ModelAdapter>::fields = property<ModelAdapter>::props_t();
1505 static void initialize_fields()
1506 {
1507     if (property<ModelAdapter>::properties_have_not_been_set())
1508     {
1509         property<ModelAdapter>::fields.reserve(23);
1510         property<ModelAdapter>::add_property(L"sim", &sim::get, &sim::set);
1511         property<ModelAdapter>::add_property(L"in", &in::get, &in::set);
1512         property<ModelAdapter>::add_property(L"in2", &in2::get, &in2::set);
1513         property<ModelAdapter>::add_property(L"intyp", &intyp::get, &intyp::set);
1514         property<ModelAdapter>::add_property(L"out", &out::get, &out::set);
1515         property<ModelAdapter>::add_property(L"out2", &out2::get, &out2::set);
1516         property<ModelAdapter>::add_property(L"outtyp", &outtyp::get, &outtyp::set);
1517         property<ModelAdapter>::add_property(L"evtin", &evtin::get, &evtin::set);
1518         property<ModelAdapter>::add_property(L"evtout", &evtout::get, &evtout::set);
1519         property<ModelAdapter>::add_property(L"state", &state::get, &state::set);
1520         property<ModelAdapter>::add_property(L"dstate", &dstate::get, &dstate::set);
1521         property<ModelAdapter>::add_property(L"odstate", &odstate::get, &odstate::set);
1522         property<ModelAdapter>::add_property(L"rpar", &rpar::get, &rpar::set);
1523         property<ModelAdapter>::add_property(L"ipar", &ipar::get, &ipar::set);
1524         property<ModelAdapter>::add_property(L"opar", &opar::get, &opar::set);
1525         property<ModelAdapter>::add_property(L"blocktype", &blocktype::get, &blocktype::set);
1526         property<ModelAdapter>::add_property(L"firing", &firing::get, &firing::set);
1527         property<ModelAdapter>::add_property(L"dep_ut", &dep_ut::get, &dep_ut::set);
1528         property<ModelAdapter>::add_property(L"label", &label::get, &label::set);
1529         property<ModelAdapter>::add_property(L"nzcross", &nzcross::get, &nzcross::set);
1530         property<ModelAdapter>::add_property(L"nmode", &nmode::get, &nmode::set);
1531         property<ModelAdapter>::add_property(L"equations", &equations::get, &equations::set);
1532         property<ModelAdapter>::add_property(L"uid", &uid::get, &uid::set);
1533     }
1534 }
1535
1536 ModelAdapter::ModelAdapter() :
1537     BaseAdapter<ModelAdapter, org_scilab_modules_scicos::model::Block>(),
1538     m_diagramAdapter(nullptr)
1539 {
1540     initialize_fields();
1541 }
1542
1543 ModelAdapter::ModelAdapter(const Controller& c, model::Block* adaptee, DiagramAdapter* diagramAdapter) :
1544     BaseAdapter<ModelAdapter, org_scilab_modules_scicos::model::Block>(c, adaptee),
1545     m_diagramAdapter(diagramAdapter)
1546 {
1547     initialize_fields();
1548 }
1549
1550 ModelAdapter::~ModelAdapter()
1551 {
1552     if (m_diagramAdapter)
1553     {
1554         m_diagramAdapter->killMe();
1555     }
1556 }
1557
1558 std::wstring ModelAdapter::getTypeStr()
1559 {
1560     return getSharedTypeStr();
1561 }
1562
1563 std::wstring ModelAdapter::getShortTypeStr()
1564 {
1565     return getSharedTypeStr();
1566 }
1567
1568 DiagramAdapter* ModelAdapter::getDiagram() const
1569 {
1570     return m_diagramAdapter;
1571 }
1572
1573 void ModelAdapter::setDiagram(DiagramAdapter* diagramAdapter)
1574 {
1575     // does not increment reference as this adapter does not own the DiagramAdapter
1576     m_diagramAdapter = diagramAdapter;
1577 }
1578
1579 } /* namespace view_scilab */
1580 } /* namespace org_scilab_modules_scicos */