Xcos MVC: partially revert b667d7aa
[scilab.git] / scilab / modules / scicos / src / cpp / view_scilab / ModelAdapter.cpp.orig
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 <<<<<<< HEAD
34 =======
35 #include "Adapters.hxx"
36 #include "LinkAdapter.hxx"
37 >>>>>>> f7b3897... Xcos MVC: Fixed objects content for compatibility between Scicos and Xcos
38 #include "ModelAdapter.hxx"
39
40 #include "view_scilab/Adapters.hxx"
41 #include "DiagramAdapter.hxx"
42 #include "ports_management.hxx"
43 #include "utilities.hxx"
44 #include "controller_helpers.hxx"
45
46 #include "var2vec.hxx"
47 #include "vec2var.hxx"
48
49 extern "C" {
50 #include "sci_malloc.h"
51 #include "charEncoding.h"
52 #include "localization.h"
53 }
54
55 namespace org_scilab_modules_scicos
56 {
57 namespace view_scilab
58 {
59 namespace
60 {
61
62 const std::wstring modelica (L"modelica");
63 const std::wstring model (L"model");
64 const std::wstring inputs (L"inputs");
65 const std::wstring outputs (L"outputs");
66 const std::wstring parameters (L"parameters");
67
68 struct sim
69 {
70
71     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
72     {
73         ScicosID adaptee = adaptor.getAdaptee()->id();
74
75         // First, extract the function Name
76         std::string name;
77         controller.getObjectProperty(adaptee, BLOCK, SIM_FUNCTION_NAME, name);
78         types::String* Name = new types::String(1, 1);
79         Name->set(0, name.data());
80
81         // Then the Api. If it is zero, then just return the Name. Otherwise, return a list containing both.
82         int api;
83         controller.getObjectProperty(adaptee, BLOCK, SIM_FUNCTION_API, api);
84
85         if (api == 0)
86         {
87             return Name;
88         }
89         else
90         {
91             types::Double* Api = new types::Double(static_cast<double>(api));
92             types::List* o = new types::List();
93             o->set(0, Name);
94             o->set(1, Api);
95             return o;
96         }
97     }
98
99     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
100     {
101         ScicosID adaptee = adaptor.getAdaptee()->id();
102
103         if (v->getType() == types::InternalType::ScilabString)
104         {
105             types::String* current = v->getAs<types::String>();
106             if (current->getSize() != 1)
107             {
108                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s: %d-by-%d expected.\n"), "model", "sim", 1, 1);
109                 return false;
110             }
111
112             char* c_str = wide_string_to_UTF8(current->get(0));
113             std::string name(c_str);
114             FREE(c_str);
115
116             // If the input is a scalar string, then the functionApi is 0.
117             int api = 0;
118
119             controller.setObjectProperty(adaptee, BLOCK, SIM_FUNCTION_NAME, name);
120             controller.setObjectProperty(adaptee, BLOCK, SIM_FUNCTION_API, api);
121         }
122         else if (v->getType() == types::InternalType::ScilabList)
123         {
124             // If the input is a 2-sized list, then it must be string and positive integer.
125             types::List* current = v->getAs<types::List>();
126             if (current->getSize() != 2)
127             {
128                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong length for field %s.%s: %d expected.\n"), "model", "sim", 2);
129                 return false;
130             }
131             if (current->get(0)->getType() != types::InternalType::ScilabString || current->get(1)->getType() != types::InternalType::ScilabDouble)
132             {
133                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : string expected.\n"), "model", "sim");
134                 return false;
135             }
136
137             types::String* Name = current->get(0)->getAs<types::String>();
138             if (Name->getSize() != 1)
139             {
140                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s: %d-by-%d expected.\n"), "model", "sim(1)", 1, 1);
141                 return false;
142             }
143             char* c_str = wide_string_to_UTF8(Name->get(0));
144             std::string name(c_str);
145             FREE(c_str);
146
147             types::Double* Api = current->get(1)->getAs<types::Double>();
148             if (Api->getSize() != 1)
149             {
150                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s: %d-by-%d expected.\n"), "model", "sim(2)", 1, 1);
151                 return false;
152             }
153             double api = Api->get(0);
154             if (floor(api) != api)
155             {
156                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for field %s.%s: Round number expected.\n"), "model", "sim(2)");
157                 return false;
158             }
159             int api_int = static_cast<int>(api);
160
161             controller.setObjectProperty(adaptee, BLOCK, SIM_FUNCTION_NAME, name);
162             controller.setObjectProperty(adaptee, BLOCK, SIM_FUNCTION_API, api_int);
163         }
164         else
165         {
166             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : string expected.\n"), "model", "sim");
167             return false;
168         }
169         return true;
170     }
171 };
172
173 struct in
174 {
175
176     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
177     {
178         return get_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, INPUTS, controller);
179     }
180
181     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
182     {
183         return update_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, INPUTS, controller, v);
184     }
185 };
186
187 struct in2
188 {
189
190     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
191     {
192         return get_ports_property<ModelAdapter, DATATYPE_COLS>(adaptor, INPUTS, controller);
193     }
194
195     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
196     {
197         return set_ports_property<ModelAdapter, DATATYPE_COLS>(adaptor, INPUTS, controller, v);
198     }
199 };
200
201 struct intyp
202 {
203
204     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
205     {
206         return get_ports_property<ModelAdapter, DATATYPE_TYPE>(adaptor, INPUTS, controller);
207     }
208
209     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
210     {
211         return set_ports_property<ModelAdapter, DATATYPE_TYPE>(adaptor, INPUTS, controller, v);
212     }
213 };
214
215 struct out
216 {
217
218     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
219     {
220         return get_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, OUTPUTS, controller);
221     }
222
223     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
224     {
225         return update_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, OUTPUTS, controller, v);
226     }
227 };
228
229 struct out2
230 {
231
232     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
233     {
234         return get_ports_property<ModelAdapter, DATATYPE_COLS>(adaptor, OUTPUTS, controller);
235     }
236
237     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
238     {
239         return set_ports_property<ModelAdapter, DATATYPE_COLS>(adaptor, OUTPUTS, controller, v);
240     }
241 };
242
243 struct outtyp
244 {
245
246     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
247     {
248         return get_ports_property<ModelAdapter, DATATYPE_TYPE>(adaptor, OUTPUTS, controller);
249     }
250
251     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
252     {
253         return set_ports_property<ModelAdapter, DATATYPE_TYPE>(adaptor, OUTPUTS, controller, v);
254     }
255 };
256
257 struct evtin
258 {
259
260     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
261     {
262         return get_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, EVENT_INPUTS, controller);
263     }
264
265     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
266     {
267         return update_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, EVENT_INPUTS, controller, v);
268     }
269 };
270
271 struct evtout
272 {
273
274     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
275     {
276         return get_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, EVENT_OUTPUTS, controller);
277     }
278
279     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
280     {
281         return update_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, EVENT_OUTPUTS, controller, v);
282     }
283 };
284
285 struct state
286 {
287
288     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
289     {
290         ScicosID adaptee = adaptor.getAdaptee()->id();
291
292         std::vector<double> state;
293         controller.getObjectProperty(adaptee, BLOCK, STATE, state);
294
295         double* data;
296         types::Double* o = new types::Double((int)state.size(), 1, &data);
297
298 #ifdef _MSC_VER
299         std::copy(state.begin(), state.end(), stdext::checked_array_iterator<double*>(data, state.size()));
300 #else
301         std::copy(state.begin(), state.end(), data);
302 #endif
303         return o;
304     }
305
306     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
307     {
308
309         if (v->getType() != types::InternalType::ScilabDouble)
310         {
311             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Real matrix expected.\n"), "model", "state");
312             return false;
313         }
314
315         types::Double* current = v->getAs<types::Double>();
316         // Only allow vectors and empty matrices
317         if (!current->isVector() && current->getSize() != 0)
318         {
319             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong size for field %s.%s: %d-by-%d expected.\n"), "model", "state");
320             return false;
321         }
322
323         ScicosID adaptee = adaptor.getAdaptee()->id();
324
325         std::vector<double> state (current->getSize());
326         std::copy(current->getReal(), current->getReal() + current->getSize(), state.begin());
327
328         controller.setObjectProperty(adaptee, BLOCK, STATE, state);
329         return true;
330     }
331 };
332
333 struct dstate
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> dstate;
341         controller.getObjectProperty(adaptee, BLOCK, DSTATE, dstate);
342
343         double* data;
344         types::Double* o = new types::Double((int)dstate.size(), 1, &data);
345
346 #ifdef _MSC_VER
347         std::copy(dstate.begin(), dstate.end(), stdext::checked_array_iterator<double*>(data, dstate.size()));
348 #else
349         std::copy(dstate.begin(), dstate.end(), data);
350 #endif
351         return o;
352     }
353
354     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
355     {
356         ScicosID adaptee = adaptor.getAdaptee()->id();
357
358         if (v->getType() == types::InternalType::ScilabString)
359         {
360             /*
361              * This seems to be a corner-case used for code generation on ScicosLab
362              */
363
364             types::String* current = v->getAs<types::String>();
365             if (current->getSize() != 1)
366             {
367                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Real matrix expected.\n"), "model", "dstate");
368                 return false;
369             }
370
371             std::vector<double> dstate;
372             controller.setObjectProperty(adaptee, BLOCK, DSTATE, dstate);
373             return true;
374         }
375
376         if (v->getType() != types::InternalType::ScilabDouble)
377         {
378             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Real matrix expected.\n"), "model", "dstate");
379             return false;
380         }
381         types::Double* current = v->getAs<types::Double>();
382         // Only allow vectors and empty matrices
383         if (!current->isVector() && current->getSize() != 0)
384         {
385             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s: m-by-1 expected.\n"), "model", "dstate");
386             return false;
387         }
388
389         std::vector<double> dstate (current->getSize());
390         std::copy(current->getReal(), current->getReal() + current->getSize(), dstate.begin());
391
392         controller.setObjectProperty(adaptee, BLOCK, DSTATE, dstate);
393         return true;
394     }
395 };
396
397 void decodeDims(std::vector<int>::iterator& prop_it, std::vector<int>& dims)
398 {
399     const int iDims = *prop_it++;
400     dims.resize(iDims);
401
402     memcpy(&dims[0], &(*prop_it), iDims * sizeof(int));
403     prop_it += iDims;
404 }
405
406 void encodeDims(std::vector<int>& prop_content, types::GenericType* v)
407 {
408     const int iDims = v->getDims();
409     prop_content.push_back(iDims);
410
411     const int index = prop_content.size();
412     prop_content.resize(index + iDims);
413
414     memcpy(&prop_content[index], v->getDimsArray(), iDims * sizeof(int));
415 }
416
417 /**
418  * Calculate the length increment depending on the ::value_type of the buffer and the type of the Scilab type
419  *
420  * @param V buffer type which must have a ::value_type field
421  * @param T Scilab type
422  * @param v the instance on the Scilab type
423  * @return the number of V elements used to store the data
424  */
425 template<typename V, typename T>
426 size_t required_length(const V& /*it*/, T* v)
427 {
428     const size_t sizeof_prop_value = sizeof(typename V::value_type);
429     if (sizeof(typename T::type) >= sizeof_prop_value)
430     {
431         return v->getSize() * sizeof(typename T::type) / sizeof_prop_value;
432     }
433     else
434     {
435         // increase the size to contain enough space, manage the size_t rounding issue
436         return v->getSize() * sizeof(typename T::type) + (sizeof_prop_value - 1) / sizeof_prop_value;
437     }
438 }
439
440 template <typename T>
441 T* decode(std::vector<int>::iterator& prop_it)
442 {
443     std::vector<int> dims;
444     decodeDims(prop_it, dims);
445
446     T* v = new T(static_cast<int>(dims.size()), &dims[0]);
447     memcpy(v->get(), &(*prop_it), v->getSize() * sizeof(typename T::type));
448
449     prop_it += required_length(prop_it, v);
450     return v;
451 }
452
453 template <typename T>
454 bool encode(std::vector<int>& prop_content, T* v)
455 {
456     encodeDims(prop_content, v);
457
458     const int index = prop_content.size();
459     const int len = required_length(prop_content, v);
460     prop_content.resize(index + len);
461
462     // Using contiguity of the memory, we save the input into 'prop_content'
463     memcpy(&prop_content[index], v->get(), v->getSize() * sizeof(typename T::type));
464     return true;
465 }
466
467 template<>
468 types::Double* decode(std::vector<int>::iterator& prop_it)
469 {
470     std::vector<int> dims;
471     decodeDims(prop_it, dims);
472
473     bool isComplex = *prop_it++;
474
475     types::Double* v = new types::Double(static_cast<int>(dims.size()), &dims[0], isComplex);
476     memcpy(v->getReal(), &(*prop_it), v->getSize() * sizeof(double));
477
478     if (isComplex)
479     {
480         prop_it += required_length(prop_it, v);
481         memcpy(v->getImg(), &(*prop_it), v->getSize() * sizeof(double));
482     }
483
484     prop_it += required_length(prop_it, v);
485     return v;
486 }
487
488 bool encode(std::vector<int>& prop_content, types::Double* v)
489 {
490     encodeDims(prop_content, v);
491
492     // Flag for complex
493     prop_content.push_back(v->isComplex());
494
495     const int index = prop_content.size();
496     const int len = required_length(prop_content, v);
497     prop_content.resize(index + len);
498
499     // Using contiguity of the memory, we save the input into 'prop_content'
500     memcpy(&prop_content[index], v->get(), v->getSize() * sizeof(double));
501
502     if (v->isComplex())
503     {
504         prop_content.resize(index + 2 * len);
505         // Using contiguity of the memory, we save the input into 'prop_content'
506         memcpy(&prop_content[index + len], v->getImg(), v->getSize() * sizeof(double));
507     }
508
509     return true;
510 }
511
512 template<>
513 types::String* decode(std::vector<int>::iterator& prop_it)
514 {
515     std::vector<int> dims;
516     decodeDims(prop_it, dims);
517
518     types::String* v = new types::String(static_cast<int>(dims.size()), &dims[0]);
519     // retrieving the first value iterator
520     std::vector<int>::iterator strData = prop_it + v->getSize();
521
522     v->set(0, (char*) & (*strData));
523     strData += static_cast<size_t>(*prop_it++);
524     for (int i = 1; i < v->getSize(); i++)
525     {
526         v->set(i, (char*) & (*strData));
527
528         // increment the value iterator by the number of element
529         const size_t numberOfElem = static_cast<size_t>(*prop_it) - static_cast<size_t>(*(prop_it - 1)) ;
530         prop_it++;
531         strData += numberOfElem;
532     }
533
534     prop_it = strData;
535     return v;
536 }
537
538 bool encode(std::vector<int>& prop_content, types::String* v)
539 {
540     encodeDims(prop_content, v);
541
542     const int index = prop_content.size();
543
544     std::vector<char*> utf8;
545     utf8.reserve(v->getSize());
546
547     std::vector<size_t> str_len;
548     str_len.reserve(v->getSize());
549
550     int offset = 0;
551     for (int i = 0; i < v->getSize(); i++)
552     {
553         char* str = wide_string_to_UTF8(v->get(i));
554         utf8.push_back(str);
555
556         // adding the '\0' byte to the len
557         const size_t len = strlen(str) + 1;
558         str_len.push_back(len);
559
560         offset += (len * sizeof(char) + sizeof(int) - 1) / sizeof(int);
561         prop_content.push_back(offset);
562     }
563
564     // reserve space for the string offsets and contents
565     prop_content.resize(index + v->getSize() + offset);
566
567     size_t len = str_len[0];
568     memcpy(&prop_content[index + v->getSize()], &(*utf8[0]), len * sizeof(char));
569     for (int i = 1; i < v->getSize(); i++)
570     {
571         len = str_len[i];
572         memcpy(&prop_content[index + v->getSize() + prop_content[index + i - 1]], &(*utf8[i]), len * sizeof(char));
573     }
574
575     // free all the string, after being copied
576     for (std::vector<char*>::iterator it = utf8.begin(); it != utf8.end(); it++)
577     {
578         FREE(*it);
579     }
580
581     return true;
582 }
583
584
585 template<>
586 types::List* decode(std::vector<int>::iterator& prop_it)
587 {
588     int length = *prop_it++;
589
590     types::List* list = new types::List();
591     for (int i = 0; i < length; i++)
592     {
593         switch (*prop_it++)
594         {
595             case types::InternalType::ScilabDouble:
596                 list->set(i, decode<types::Double>(prop_it));
597                 break;
598             case types::InternalType::ScilabInt8:
599                 list->set(i, decode<types::Int8>(prop_it));
600                 break;
601             case types::InternalType::ScilabUInt8:
602                 list->set(i, decode<types::UInt8>(prop_it));
603                 break;
604             case types::InternalType::ScilabInt16:
605                 list->set(i, decode<types::Int16>(prop_it));
606                 break;
607             case types::InternalType::ScilabUInt16:
608                 list->set(i, decode<types::UInt16>(prop_it));
609                 break;
610             case types::InternalType::ScilabInt32:
611                 list->set(i, decode<types::Int32>(prop_it));
612                 break;
613             case types::InternalType::ScilabUInt32:
614                 list->set(i, decode<types::UInt32>(prop_it));
615                 break;
616             case types::InternalType::ScilabInt64:
617                 list->set(i, decode<types::Int64>(prop_it));
618                 break;
619             case types::InternalType::ScilabUInt64:
620                 list->set(i, decode<types::UInt64>(prop_it));
621                 break;
622             case types::InternalType::ScilabString:
623                 list->set(i, decode<types::String>(prop_it));
624                 break;
625             case types::InternalType::ScilabBool:
626                 list->set(i, decode<types::Bool>(prop_it));
627                 break;
628             case types::InternalType::ScilabList:
629                 list->set(i, decode<types::List>(prop_it));
630                 break;
631         }
632     }
633     return list;
634 }
635
636 bool encode(std::vector<int>& prop_content, types::List* list)
637 {
638     // Save the number of list elements in the first element
639     prop_content.push_back(list->getSize());
640
641     for (int i = 0; i < list->getSize(); ++i)
642     {
643         // Insert a new element and save its variable type
644         prop_content.push_back(list->get(i)->getType());
645
646         switch (list->get(i)->getType())
647         {
648             case types::InternalType::ScilabDouble:
649                 encode(prop_content, list->get(i)->getAs<types::Double>());
650                 break;
651             case types::InternalType::ScilabInt8:
652                 encode(prop_content, list->get(i)->getAs<types::Int8>());
653                 break;
654             case types::InternalType::ScilabUInt8:
655                 encode(prop_content, list->get(i)->getAs<types::UInt8>());
656                 break;
657             case types::InternalType::ScilabInt16:
658                 encode(prop_content, list->get(i)->getAs<types::Int16>());
659                 break;
660             case types::InternalType::ScilabUInt16:
661                 encode(prop_content, list->get(i)->getAs<types::UInt16>());
662                 break;
663             case types::InternalType::ScilabInt32:
664                 encode(prop_content, list->get(i)->getAs<types::Int32>());
665                 break;
666             case types::InternalType::ScilabUInt32:
667                 encode(prop_content, list->get(i)->getAs<types::UInt32>());
668                 break;
669             case types::InternalType::ScilabInt64:
670                 encode(prop_content, list->get(i)->getAs<types::Int64>());
671                 break;
672             case types::InternalType::ScilabUInt64:
673                 encode(prop_content, list->get(i)->getAs<types::UInt64>());
674                 break;
675             case types::InternalType::ScilabString:
676                 encode(prop_content, list->get(i)->getAs<types::String>());
677                 break;
678             case types::InternalType::ScilabBool:
679                 encode(prop_content, list->get(i)->getAs<types::Bool>());
680                 break;
681             default:
682                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: List expected.\n"), "model", "props");
683                 return false;
684         }
685     }
686
687     return true;
688 }
689
690 struct odstate
691 {
692
693     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
694     {
695         ScicosID adaptee = adaptor.getAdaptee()->id();
696
697         std::vector<double> prop_content;
698         controller.getObjectProperty(adaptee, BLOCK, ODSTATE, prop_content);
699
700         // Corner-case, the empty content is an empty double
701         if (prop_content.empty())
702         {
703             return types::Double::Empty();
704         }
705
706         // The returned value is a list
707         types::InternalType* res;
708         if (!vec2var(prop_content, res))
709         {
710             return 0;
711         }
712
713         return res;
714     }
715
716     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
717     {
718         ScicosID adaptee = adaptor.getAdaptee()->id();
719
720         // corner-case the empty content is an empty-double
721         if (v->getType() == types::InternalType::ScilabDouble)
722         {
723             types::Double* current = v->getAs<types::Double>();
724             if (current->getSize() != 0)
725             {
726                 return false;
727             }
728
729             // prop_content is empty
730             std::vector<double> prop_content;
731             controller.setObjectProperty(adaptee, BLOCK, ODSTATE, prop_content);
732             return true;
733         }
734
735         std::vector<double> prop_content;
736         if (!var2vec(v, prop_content))
737         {
738             return false;
739         }
740
741         controller.setObjectProperty(adaptee, BLOCK, ODSTATE, prop_content);
742         return true;
743     }
744 };
745
746 /*
747  * When setting a diagram in 'rpar', the Superblock's ports must be consistent with the "port blocks" inside it.
748  * By "port blocks", we mean IN_f, OUT_f, CLKIN_f, CLKOUT_f, CLKINV_f, CLKOUTV_f, INIMPL_f and OUTIMPL_f.
749  */
750 bool setInnerBlocksRefs(ModelAdapter& adaptor, const std::vector<ScicosID>& children, Controller& controller)
751 {
752     const std::string input ("input");
753     const std::string output ("output");
754     const std::string inimpl ("inimpl");
755     const std::string outimpl ("outimpl");
756
757     ScicosID adaptee = adaptor.getAdaptee()->id();
758
759     for (std::vector<ScicosID>::const_iterator it = children.begin(); it != children.end(); ++it)
760     {
761         if (*it == ScicosID())
762         {
763             continue; // Rule out mlists (Deleted or Annotations)
764         }
765
766         if (controller.getObject(*it)->kind() == BLOCK) // Rule out Annotations and Links
767         {
768             std::string name;
769             controller.getObjectProperty(*it, BLOCK, SIM_FUNCTION_NAME, name);
770
771             // Find the "port blocks"
772             if (name == input || name == inimpl || name == output || name == outimpl)
773             {
774                 std::vector<int> ipar;
775                 controller.getObjectProperty(*it, BLOCK, IPAR, ipar);
776                 if (ipar.size() != 1)
777                 {
778                     std::string uid;
779                     controller.getObjectProperty(*it, BLOCK, UID, uid);
780                     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());
781                     return false;
782                 }
783                 int portIndex = ipar[0];
784
785                 // "name" is not enough to tell the event and data ports apart, so check the block's port.
786                 object_properties_t kind;
787                 std::vector<ScicosID> innerPort;
788                 if (name == input || name == inimpl)
789                 {
790                     controller.getObjectProperty(*it, BLOCK, OUTPUTS, innerPort);
791                     if (!innerPort.empty())
792                     {
793                         kind = INPUTS;
794                     }
795                     else
796                     {
797                         kind = EVENT_INPUTS;
798                     }
799                 }
800                 else
801                 {
802                     controller.getObjectProperty(*it, BLOCK, INPUTS, innerPort);
803                     if (!innerPort.empty())
804                     {
805                         kind = OUTPUTS;
806                     }
807                     else
808                     {
809                         kind = EVENT_OUTPUTS;
810                     }
811                 }
812
813                 std::vector<ScicosID> superPorts;
814                 controller.getObjectProperty(adaptee, BLOCK, kind, superPorts);
815                 if (static_cast<int>(superPorts.size()) < portIndex)
816                 {
817                     if (!superPorts.empty())
818                     {
819                         // Arbitrarily take the highest possible value in case the user enters a wrong number
820                         portIndex = superPorts.size();
821                     }
822                     else
823                     {
824                         std::string uid;
825                         controller.getObjectProperty(*it, BLOCK, UID, uid);
826                         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());
827                         return false;
828                     }
829                 }
830
831                 ScicosID port = superPorts[portIndex - 1];
832
833                 // Check consistency of the implicitness between the inner and outer ports
834                 bool isImplicit;
835                 controller.getObjectProperty(port, PORT, IMPLICIT, isImplicit);
836                 if (name == input || name == output)
837                 {
838                     if (isImplicit)
839                     {
840                         std::string uid;
841                         controller.getObjectProperty(*it, BLOCK, UID, uid);
842                         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());
843                         return false;
844                     }
845                 }
846                 else
847                 {
848                     if (!isImplicit)
849                     {
850                         std::string uid;
851                         controller.getObjectProperty(*it, BLOCK, UID, uid);
852                         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());
853                         return false;
854                     }
855                 }
856
857                 controller.setObjectProperty(*it, BLOCK, PORT_REFERENCE, port);
858             }
859         }
860     }
861     return true;
862 }
863
864 struct rpar
865 {
866
867     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
868     {
869         ScicosID adaptee = adaptor.getAdaptee()->id();
870
871         std::vector<ScicosID> diagramChildren;
872         controller.getObjectProperty(adaptee, BLOCK, CHILDREN, diagramChildren);
873
874         if (diagramChildren.empty())
875         {
876             std::vector<double> rpar;
877             controller.getObjectProperty(adaptee, BLOCK, RPAR, rpar);
878
879             double *data;
880             types::Double* o = new types::Double((int)rpar.size(), 1, &data);
881 #ifdef _MSC_VER
882             std::copy(rpar.begin(), rpar.end(), stdext::checked_array_iterator<double*>(data, rpar.size()));
883 #else
884             std::copy(rpar.begin(), rpar.end(), data);
885 #endif
886             return o;
887         }
888         else // SuperBlock, return the contained diagram (allocating it on demand)
889         {
890             DiagramAdapter* diagram = adaptor.getDiagram();
891
892             /*
893              * FIXME: Sync all diagram children as the blocks might be modified by xcos
894              */
895
896             return diagram;
897         }
898     }
899
900     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
901     {
902         ScicosID adaptee = adaptor.getAdaptee()->id();
903
904         if (v->getType() == types::InternalType::ScilabDouble)
905         {
906             types::Double* current = v->getAs<types::Double>();
907
908             std::vector<double> rpar (current->getSize());
909             for (int i = 0; i < current->getSize(); ++i)
910             {
911                 rpar[i] = current->get(i);
912             }
913
914             controller.setObjectProperty(adaptee, BLOCK, RPAR, rpar);
915             return true;
916         }
917         else if (v->getType() == types::InternalType::ScilabString)
918         {
919             // Allow Text blocks to define strings in rpar
920             return true;
921         }
922         else if (v->getType() == types::InternalType::ScilabUserType)
923         {
924             // Make sure the input describes a Diagram
925             const Adapters::adapters_index_t adapter_index = Adapters::instance().lookup_by_typename(v->getShortTypeStr());
926             if (adapter_index != Adapters::DIAGRAM_ADAPTER)
927             {
928                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Diagram expected.\n"), "model", "rpar");
929                 return false;
930             }
931
932             // Translate 'v' to an DiagramAdapter
933             DiagramAdapter* diagram = v->getAs<DiagramAdapter>();
934
935             adaptor.setDiagram(diagram);
936
937             // Set the diagram children as block children
938             std::vector<ScicosID> diagramChildren;
939             controller.getObjectProperty(diagram->getAdaptee()->id(), DIAGRAM, CHILDREN, diagramChildren);
940             if (diagramChildren.empty())
941             {
942                 // bug_12998: If inserting an empty diagram in 'rpar', simulate an empty object
943                 diagramChildren.push_back(ScicosID());
944             }
945             std::vector<ScicosID> oldDiagramChildren;
946             controller.getObjectProperty(adaptor.getAdaptee()->id(), BLOCK, CHILDREN, oldDiagramChildren);
947
948             std::sort(oldDiagramChildren.begin(), oldDiagramChildren.end());
949             std::vector<ScicosID> clonedChildren;
950             std::vector<ScicosID> clonedLinks;
951             for (const ScicosID & id : diagramChildren)
952             {
953                 if (id != 0 && !std::binary_search(oldDiagramChildren.begin(), oldDiagramChildren.end(), id))
954                 {
955                     ScicosID cloneID = controller.cloneObject(id, true);
956                     auto o = controller.getObject(cloneID);
957                     controller.setObjectProperty(o->id(), o->kind(), PARENT_BLOCK, adaptor.getAdaptee()->id());
958
959                     clonedChildren.push_back(cloneID);
960                     if (o->kind() == LINK)
961                     {
962                         clonedLinks.push_back(cloneID);
963                     }
964                 }
965             }
966             controller.setObjectProperty(adaptor.getAdaptee()->id(), BLOCK, CHILDREN, clonedChildren);
967
968             std::sort(diagramChildren.begin(), diagramChildren.end());
969             for (const ScicosID & id : oldDiagramChildren)
970             {
971                 if (id != 0 && !std::binary_search(diagramChildren.begin(), diagramChildren.end(), id))
972                 {
973                     auto o = controller.getObject(id);
974                     controller.setObjectProperty(o->id(), o->kind(), PARENT_BLOCK, ScicosID());
975
976                     controller.deleteObject(id);
977                 }
978             }
979
980             // After cloning the diagram elements, re-sync the link information
981             for (int i = 0; i < static_cast<int>(clonedLinks.size()); ++i)
982             {
983                 auto o = controller.getObject(clonedLinks[i]);
984                 LinkAdapter* newLink = new LinkAdapter(controller, static_cast<model::Link*>(o));
985                 newLink->setFromInModel(diagram->getFrom()[i], controller);
986                 newLink->setToInModel(diagram->getTo()[i], controller);
987             }
988
989             // Save the context
990             std::vector<std::string> context;
991             controller.getObjectProperty(diagram->getAdaptee()->id(), DIAGRAM, DIAGRAM_CONTEXT, context);
992             controller.setObjectProperty(adaptor.getAdaptee()->id(), BLOCK, DIAGRAM_CONTEXT, context);
993
994             // Link the Superblock ports to their inner "port blocks"
995             return setInnerBlocksRefs(adaptor, diagramChildren, controller);
996         }
997         else if (v->getType() == types::InternalType::ScilabMList)
998         {
999             ScicosID localAdaptee = controller.createObject(DIAGRAM);
1000             DiagramAdapter* diagram = new DiagramAdapter(controller, controller.getObject<model::Diagram>(localAdaptee));
1001             if (!diagram->setAsTList(v, controller))
1002             {
1003                 diagram->killMe();
1004                 return false;
1005             }
1006
1007             adaptor.setDiagram(diagram);
1008
1009             // set the diagram children as block children ; referencing them
1010             std::vector<ScicosID> diagramChildren;
1011             controller.getObjectProperty(diagram->getAdaptee()->id(), DIAGRAM, CHILDREN, diagramChildren);
1012             if (diagramChildren.empty())
1013             {
1014                 // bug_12998: If inserting an empty diagram in 'rpar', simulate an empty object
1015                 diagramChildren.push_back(ScicosID());
1016             }
1017             std::vector<ScicosID> oldDiagramChildren;
1018             controller.getObjectProperty(adaptor.getAdaptee()->id(), BLOCK, CHILDREN, oldDiagramChildren);
1019
1020             controller.setObjectProperty(adaptor.getAdaptee()->id(), BLOCK, CHILDREN, diagramChildren);
1021             {
1022                 std::sort(oldDiagramChildren.begin(), oldDiagramChildren.end());
1023                 for (const ScicosID id : diagramChildren)
1024                 {
1025                     if (id != 0 && !std::binary_search(oldDiagramChildren.begin(), oldDiagramChildren.end(), id))
1026                     {
1027                         auto o = controller.getObject(id);
1028                         controller.setObjectProperty(o->id(), o->kind(), PARENT_BLOCK, adaptor.getAdaptee()->id());
1029
1030                         controller.referenceObject(id);
1031                     }
1032                 }
1033
1034                 std::sort(diagramChildren.begin(), diagramChildren.end());
1035                 for (const ScicosID id : oldDiagramChildren)
1036                 {
1037                     if (id != 0 && !std::binary_search(diagramChildren.begin(), diagramChildren.end(), id))
1038                     {
1039                         auto o = controller.getObject(id);
1040                         controller.setObjectProperty(o->id(), o->kind(), PARENT_BLOCK, ScicosID());
1041
1042                         controller.deleteObject(id);
1043                     }
1044                 }
1045             }
1046
1047             // Link the Superblock ports to their inner "port blocks"
1048             return setInnerBlocksRefs(adaptor, diagramChildren, controller);
1049         }
1050         else
1051         {
1052             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Real matrix expected.\n"), "model", "rpar");
1053             return false;
1054         }
1055     }
1056 };
1057
1058 double toDouble(const int a)
1059 {
1060     return static_cast<double>(a);
1061 }
1062
1063 struct ipar
1064 {
1065
1066     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1067     {
1068         ScicosID adaptee = adaptor.getAdaptee()->id();
1069
1070         std::vector<int> ipar;
1071         controller.getObjectProperty(adaptee, BLOCK, IPAR, ipar);
1072
1073         double *data;
1074         types::Double* o = new types::Double((int)ipar.size(), 1, &data);
1075
1076 #ifdef _MSC_VER
1077         std::transform(ipar.begin(), ipar.end(), stdext::checked_array_iterator<double*>(data, ipar.size()), toDouble);
1078 #else
1079         std::transform(ipar.begin(), ipar.end(), data, toDouble);
1080 #endif
1081         return o;
1082     }
1083
1084     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1085     {
1086         ScicosID adaptee = adaptor.getAdaptee()->id();
1087
1088         if (v->getType() == types::InternalType::ScilabList)
1089         {
1090             std::vector<int> ipar;
1091             controller.setObjectProperty(adaptee, BLOCK, IPAR, ipar);
1092             get_or_allocate_logger()->log(LOG_TRACE, _("Wrong type for field %s.%s: List clear previous value.\n"), "model", "ipar");
1093             return true;
1094         }
1095
1096         // FIXME: ScilabInts should be managed there
1097         if (v->getType() != types::InternalType::ScilabDouble)
1098         {
1099             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Real matrix expected.\n"), "model", "ipar");
1100             return false;
1101         }
1102         types::Double* current = v->getAs<types::Double>();
1103         // Only allow vectors and empty matrices
1104         if (!current->isVector() && current->getSize() != 0)
1105         {
1106             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s: m-by-1 matrix expected.\n"), "model", "ipar");
1107             return false;
1108         }
1109
1110         std::vector<int> ipar (current->getSize());
1111         for (int i = 0; i < current->getSize(); ++i)
1112         {
1113             if (floor(current->get(i)) != current->get(i))
1114             {
1115                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for field %s.%s: Integer values expected.\n"), "model", "ipar");
1116                 return false;
1117             }
1118             ipar[i] = static_cast<int>(current->get(i));
1119         }
1120
1121         controller.setObjectProperty(adaptee, BLOCK, IPAR, ipar);
1122         return true;
1123     }
1124 };
1125
1126 struct opar
1127 {
1128
1129     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1130     {
1131         ScicosID adaptee = adaptor.getAdaptee()->id();
1132
1133         std::vector<double> prop_content;
1134         controller.getObjectProperty(adaptee, BLOCK, OPAR, prop_content);
1135
1136         // Corner-case, the empty content is an empty double
1137         if (prop_content.empty())
1138         {
1139             return types::Double::Empty();
1140         }
1141
1142         // The returned value is a list
1143         types::InternalType* res;
1144         if (!vec2var(prop_content, res))
1145         {
1146             return 0;
1147         }
1148
1149         return res;
1150     }
1151
1152     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1153     {
1154         ScicosID adaptee = adaptor.getAdaptee()->id();
1155
1156         // corner-case the empty content is an empty-double
1157         if (v->getType() == types::InternalType::ScilabDouble)
1158         {
1159             types::Double* current = v->getAs<types::Double>();
1160             if (current->getSize() != 0)
1161             {
1162                 return false;
1163             }
1164
1165             // prop_content should be empty
1166             std::vector<double> prop_content;
1167             controller.setObjectProperty(adaptee, BLOCK, OPAR, prop_content);
1168             return true;
1169         }
1170
1171         std::vector<double> prop_content;
1172         if (!var2vec(v, prop_content))
1173         {
1174             return false;
1175         }
1176
1177         controller.setObjectProperty(adaptee, BLOCK, OPAR, prop_content);
1178         return true;
1179     }
1180 };
1181
1182 struct blocktype
1183 {
1184
1185     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1186     {
1187         ScicosID adaptee = adaptor.getAdaptee()->id();
1188
1189         std::string type;
1190         controller.getObjectProperty(adaptee, BLOCK, SIM_BLOCKTYPE, type);
1191
1192         types::String* o = new types::String(type.c_str());
1193         return o;
1194     }
1195
1196     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1197     {
1198         ScicosID adaptee = adaptor.getAdaptee()->id();
1199
1200         if (v->getType() != types::InternalType::ScilabString)
1201         {
1202             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: String expected.\n"), "model", "blocktype");
1203             return false;
1204         }
1205
1206         types::String* current = v->getAs<types::String>();
1207         if (current->getSize() != 1)
1208         {
1209             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s: String expected.\n"), "model", "blocktype");
1210             return false;
1211         }
1212
1213         char* c_str = wide_string_to_UTF8(current->get(0));
1214         std::string type (c_str);
1215         FREE(c_str);
1216
1217         // the value validation is performed on the model
1218         return controller.setObjectProperty(adaptee, BLOCK, SIM_BLOCKTYPE, type) != FAIL;
1219     }
1220 };
1221
1222 struct firing
1223 {
1224
1225     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1226     {
1227         return get_ports_property<ModelAdapter, FIRING>(adaptor, EVENT_OUTPUTS, controller);
1228     }
1229
1230     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1231     {
1232         return set_ports_property<ModelAdapter, FIRING>(adaptor, EVENT_OUTPUTS, controller, v);
1233     }
1234 };
1235
1236 struct dep_ut
1237 {
1238
1239     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1240     {
1241         ScicosID adaptee = adaptor.getAdaptee()->id();
1242
1243         std::vector<int> dep_ut;
1244         controller.getObjectProperty(adaptee, BLOCK, SIM_DEP_UT, dep_ut);
1245
1246         int* dep;
1247         types::Bool* o = new types::Bool(1, 2, &dep);
1248
1249         dep[0] = dep_ut[0];
1250         dep[1] = dep_ut[1];
1251
1252         return o;
1253     }
1254
1255     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1256     {
1257         ScicosID adaptee = adaptor.getAdaptee()->id();
1258
1259         if (v->getType() != types::InternalType::ScilabBool)
1260         {
1261             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Boolean matrix expected.\n"), "model", "dep_ut");
1262             return false;
1263         }
1264
1265         types::Bool* current = v->getAs<types::Bool>();
1266         if (current->getSize() != 2)
1267         {
1268             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s: %d-by-%d expected.\n"), "model", "dep_ut", 1, 2);
1269             return false;
1270         }
1271
1272         std::vector<int> dep_ut (2);
1273         dep_ut[0] = current->get(0);
1274         dep_ut[1] = current->get(1);
1275
1276         controller.setObjectProperty(adaptee, BLOCK, SIM_DEP_UT, dep_ut);
1277         return true;
1278     }
1279 };
1280
1281 struct label
1282 {
1283
1284     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1285     {
1286         ScicosID adaptee = adaptor.getAdaptee()->id();
1287
1288         std::string label;
1289         controller.getObjectProperty(adaptee, BLOCK, LABEL, label);
1290
1291         types::String* o = new types::String(1, 1);
1292         o->set(0, label.data());
1293
1294         return o;
1295     }
1296
1297     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1298     {
1299         if (v->getType() != types::InternalType::ScilabString)
1300         {
1301             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: String expected.\n"), "model", "label");
1302             return false;
1303         }
1304
1305         types::String* current = v->getAs<types::String>();
1306         if (current->getSize() != 1)
1307         {
1308             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s: String expected.\n"), "model", "label");
1309             return false;
1310         }
1311
1312         ScicosID adaptee = adaptor.getAdaptee()->id();
1313
1314         char* c_str = wide_string_to_UTF8(current->get(0));
1315         std::string label(c_str);
1316         FREE(c_str);
1317
1318         controller.setObjectProperty(adaptee, BLOCK, LABEL, label);
1319         return true;
1320     }
1321 };
1322
1323 struct nzcross
1324 {
1325
1326     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1327     {
1328         ScicosID adaptee = adaptor.getAdaptee()->id();
1329
1330         std::vector<int> nzcross;
1331         controller.getObjectProperty(adaptee, BLOCK, NZCROSS, nzcross);
1332
1333         double *data;
1334         types::Double* o = new types::Double((int)nzcross.size(), 1, &data);
1335
1336 #ifdef _MSC_VER
1337         std::transform(nzcross.begin(), nzcross.end(), stdext::checked_array_iterator<double*>(data, nzcross.size()), toDouble);
1338 #else
1339         std::transform(nzcross.begin(), nzcross.end(), data, toDouble);
1340 #endif
1341         return o;
1342     }
1343
1344     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1345     {
1346         ScicosID adaptee = adaptor.getAdaptee()->id();
1347
1348         if (v->getType() != types::InternalType::ScilabDouble)
1349         {
1350             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Real matrix expected.\n"), "model", "nzcross");
1351             return false;
1352         }
1353
1354         types::Double* current = v->getAs<types::Double>();
1355         // Only allow vectors and empty matrices
1356         if (!current->isVector() && current->getSize() != 0)
1357         {
1358             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s: m-by-1 expected.\n"), "model", "nzcross");
1359             return false;
1360         }
1361
1362         std::vector<int> nzcross (current->getSize());
1363         for (int i = 0; i < current->getSize(); ++i)
1364         {
1365             if (floor(current->get(i)) != current->get(i))
1366             {
1367                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for field %s.%s: Integer values expected.\n"), "model", "nzcross");
1368                 return false;
1369             }
1370             nzcross[i] = static_cast<int>(current->get(i));
1371         }
1372
1373         controller.setObjectProperty(adaptee, BLOCK, NZCROSS, nzcross);
1374         return true;
1375     }
1376 };
1377
1378 struct nmode
1379 {
1380
1381     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1382     {
1383         ScicosID adaptee = adaptor.getAdaptee()->id();
1384
1385         std::vector<int> nmode;
1386         controller.getObjectProperty(adaptee, BLOCK, NMODE, nmode);
1387
1388         double *data;
1389         types::Double* o = new types::Double((int)nmode.size(), 1, &data);
1390
1391 #ifdef _MSC_VER
1392         std::transform(nmode.begin(), nmode.end(), stdext::checked_array_iterator<double*>(data, nmode.size()), toDouble);
1393 #else
1394         std::transform(nmode.begin(), nmode.end(), data, toDouble);
1395 #endif
1396         return o;
1397     }
1398
1399     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1400     {
1401         ScicosID adaptee = adaptor.getAdaptee()->id();
1402
1403         if (v->getType() != types::InternalType::ScilabDouble)
1404         {
1405             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Real matrix expected.\n"), "model", "nmode");
1406             return false;
1407         }
1408
1409         types::Double* current = v->getAs<types::Double>();
1410         // Only allow vectors and empty matrices
1411         if (!current->isVector() && current->getSize() != 0)
1412         {
1413             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s: m-by-1 expected.\n"), "model", "nzcross");
1414             return false;
1415         }
1416
1417         std::vector<int> nmode (current->getSize());
1418         for (int i = 0; i < current->getSize(); ++i)
1419         {
1420             if (floor(current->get(i)) != current->get(i))
1421             {
1422                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for field %s.%s: Integer values expected.\n"), "model", "nzcross");
1423                 return false;
1424             }
1425             nmode[i] = static_cast<int>(current->get(i));
1426         }
1427
1428         controller.setObjectProperty(adaptee, BLOCK, NMODE, nmode);
1429         return true;
1430     }
1431 };
1432
1433 struct equations
1434 {
1435
1436     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1437     {
1438         ScicosID adaptee = adaptor.getAdaptee()->id();
1439
1440         std::vector<std::string> equations;
1441         controller.getObjectProperty(adaptee, BLOCK, EQUATIONS, equations);
1442
1443         if (equations.size() == 0)
1444         {
1445             return new types::List();
1446         }
1447
1448         types::TList* o = new types::TList();
1449
1450         // Header, starting with "modelica"
1451         types::String* header = new types::String(1, 5);
1452         header->set(0, modelica.c_str());
1453         header->set(1, model.c_str());
1454         header->set(2, inputs.c_str());
1455         header->set(3, outputs.c_str());
1456         header->set(4, parameters.c_str());
1457         o->set(0, header);
1458
1459         // 'model'
1460         if (equations[0].c_str() == std::string())
1461         {
1462             o->set(1, types::Double::Empty());
1463         }
1464         else
1465         {
1466             types::String* modelField = new types::String(1, 1);
1467             modelField->set(0, equations[0].c_str());
1468             o->set(1, modelField);
1469         }
1470
1471         // 'inputs'
1472         std::istringstream inputsSizeStr (equations[1]);
1473         int inputsSize;
1474         inputsSizeStr >> inputsSize;
1475         if (inputsSize <= 0 || inputsSize > int(equations.size() - 2))
1476         {
1477             types::Double* inputsField = types::Double::Empty();
1478             o->set(2, inputsField);
1479
1480             // fall back to a safe value for future indexing
1481             inputsSize = 0;
1482         }
1483         else
1484         {
1485             types::String* inputsField = new types::String(inputsSize, 1);
1486             for (int i = 0; i < inputsSize; ++i)
1487             {
1488                 inputsField->set(i, equations[i + 2].c_str());
1489             }
1490             o->set(2, inputsField);
1491         }
1492
1493         // 'outputs'
1494         std::istringstream outputsSizeStr (equations[2 + inputsSize]);
1495         int outputsSize;
1496         outputsSizeStr >> outputsSize;
1497         if (outputsSize <= 0 || outputsSize > int(equations.size() - 3 - inputsSize))
1498         {
1499             types::Double* outputsField = types::Double::Empty();
1500             o->set(3, outputsField);
1501
1502             // fall back to a safe value for future indexing
1503             outputsSize = 0;
1504         }
1505         else
1506         {
1507             types::String* outputsField = new types::String(outputsSize, 1);
1508             for (int i = 0; i < outputsSize; ++i)
1509             {
1510                 outputsField->set(i, equations[i + 3 + inputsSize].c_str());
1511             }
1512             o->set(3, outputsField);
1513         }
1514
1515         // 'parameters'
1516         types::List* parametersField = new types::List();
1517
1518         // 'parameters' names
1519         std::istringstream parametersSizeStr (equations[3 + inputsSize + outputsSize]);
1520         int parametersSize;
1521         parametersSizeStr >> parametersSize;
1522         if (parametersSize <= 0 || parametersSize > int(equations.size() - 4 - inputsSize - outputsSize))
1523         {
1524             types::Double* parametersNames = types::Double::Empty();
1525             parametersField->set(0, parametersNames);
1526
1527             // fall back to a safe value for future indexing
1528             parametersSize = 0;
1529         }
1530         else
1531         {
1532             types::String* parametersNames = new types::String(parametersSize, 1);
1533             for (int i = 0; i < parametersSize; ++i)
1534             {
1535                 parametersNames->set(i, equations[i + 4 + inputsSize + outputsSize].c_str());
1536             }
1537             parametersField->set(0, parametersNames);
1538         }
1539
1540         // 'parameters' values
1541         types::List* parametersValues = new types::List();
1542         for (int i = 0; i < parametersSize; ++i)
1543         {
1544             std::istringstream parametersValueStr (equations[i + 4 + inputsSize + outputsSize + parametersSize]);
1545             double parametersVal;
1546             parametersValueStr >> parametersVal;
1547             types::Double* parametersValue = new types::Double(parametersVal);
1548             parametersValues->set(i, parametersValue);
1549         }
1550         parametersField->set(1, parametersValues);
1551         parametersValues->killMe();
1552
1553         // 'parameters' states (optional, only check its presence if at least one parameter is present)
1554         if (parametersSize != 0)
1555         {
1556             std::string parametersStatesBool (equations[4 + inputsSize + outputsSize + 2 * parametersSize]);
1557             if (strcmp(parametersStatesBool.c_str(), "T") == 0) // Check the presence of the "states" field
1558             {
1559                 types::Double* parametersStates = new types::Double(parametersSize, 1);
1560                 for (int i = 0; i < parametersSize; ++i)
1561                 {
1562                     std::istringstream parametersStateStr (equations[i + 5 + inputsSize + outputsSize + 2 * parametersSize]);
1563                     double parametersState;
1564                     parametersStateStr >> parametersState;
1565                     parametersStates->set(i, parametersState);
1566                 }
1567                 parametersField->set(2, parametersStates);
1568             }
1569         }
1570
1571         o->set(4, parametersField);
1572         parametersField->killMe();
1573
1574         return o;
1575     }
1576
1577     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1578     {
1579         ScicosID adaptee = adaptor.getAdaptee()->id();
1580
1581         if (v->getType() == types::InternalType::ScilabList)
1582         {
1583             types::List* current = v->getAs<types::List>();
1584             if (current->getSize() != 0)
1585             {
1586                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1587                 return false;
1588             }
1589             return true;
1590         }
1591
1592         if (v->getType() != types::InternalType::ScilabTList)
1593         {
1594             return false;
1595         }
1596
1597         types::TList* current = v->getAs<types::TList>();
1598
1599         // Check the header
1600         types::String* header = current->getFieldNames();
1601         if (header->getSize() != 5)
1602         {
1603             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1604             return false;
1605         }
1606         if (header->get(0) != modelica)
1607         {
1608             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1609             return false;
1610         }
1611         if (header->get(1) != model)
1612         {
1613             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1614             return false;
1615         }
1616         if (header->get(2) != inputs)
1617         {
1618             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1619             return false;
1620         }
1621         if (header->get(3) != outputs)
1622         {
1623             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1624             return false;
1625         }
1626         if (header->get(4) != parameters)
1627         {
1628             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1629             return false;
1630         }
1631
1632         char* c_str; // Temporary buffer used for conversions
1633
1634         // 'model'
1635         std::vector<std::string> equations;
1636         if (current->get(1)->getType() == types::InternalType::ScilabString)
1637         {
1638             types::String* modelField = current->get(1)->getAs<types::String>();
1639             if (modelField->getSize() != 1)
1640             {
1641                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1642                 return false;
1643             }
1644
1645             c_str = wide_string_to_UTF8(modelField->get(0));
1646             std::string modelFieldStored(c_str);
1647             FREE(c_str);
1648             equations.push_back(modelFieldStored);
1649         }
1650         else if (current->get(1)->getType() == types::InternalType::ScilabDouble)
1651         {
1652             types::Double* modelFieldDouble = current->get(1)->getAs<types::Double>();
1653             if (modelFieldDouble->getSize() != 0)
1654             {
1655                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1656                 return false;
1657             }
1658
1659             // An empty matrix stores an empty string, which will later be translated back to an empty matrix
1660             equations.push_back(std::string());
1661         }
1662         else
1663         {
1664             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1665             return false;
1666         }
1667
1668         // 'inputs'
1669         size_t inputsSize;
1670         if (current->get(2)->getType() == types::InternalType::ScilabDouble)
1671         {
1672             types::Double* inputsField = current->get(2)->getAs<types::Double>();
1673             if (inputsField->getSize() != 0)
1674             {
1675                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1676                 return false;
1677             }
1678
1679             inputsSize = 0;
1680             std::ostringstream strInputs;
1681             strInputs << inputsSize;
1682             std::string inputsSizeStr = strInputs.str();
1683             equations.push_back(inputsSizeStr); // When 'inputs'=[], just insert "0" in 'equations'
1684         }
1685         else
1686         {
1687             if (current->get(2)->getType() != types::InternalType::ScilabString)
1688             {
1689                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1690                 return false;
1691             }
1692
1693             types::String* inputsField = current->get(2)->getAs<types::String>();
1694             inputsSize = inputsField->getSize();
1695             equations.resize(equations.size() + 1 + inputsSize);
1696             std::ostringstream strInputs;
1697             strInputs << inputsSize;
1698             std::string inputsSizeStr = strInputs.str();
1699             equations[1] = inputsSizeStr; // Saving the size of the 'inputs' field'
1700             for (size_t i = 0; i < inputsSize; ++i)
1701             {
1702                 c_str = wide_string_to_UTF8(inputsField->get(static_cast<int>(i)));
1703                 std::string inputsFieldStored(c_str);
1704                 FREE(c_str);
1705                 equations[i + 2] = inputsFieldStored;
1706             }
1707         }
1708
1709         // 'outputs'
1710         size_t outputsSize;
1711         if (current->get(3)->getType() == types::InternalType::ScilabDouble)
1712         {
1713             types::Double* outputsField = current->get(3)->getAs<types::Double>();
1714             if (outputsField->getSize() != 0)
1715             {
1716                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1717                 return false;
1718             }
1719
1720             outputsSize = 0;
1721             std::ostringstream strOutputs;
1722             strOutputs << outputsSize;
1723             std::string outputsSizeStr = strOutputs.str();
1724             equations.push_back(outputsSizeStr); // When 'outputs'=[], just insert "0" in 'equations'
1725         }
1726         else
1727         {
1728             if (current->get(3)->getType() != types::InternalType::ScilabString)
1729             {
1730                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1731                 return false;
1732             }
1733
1734             types::String* outputsField = current->get(3)->getAs<types::String>();
1735             outputsSize = outputsField->getSize();
1736             equations.resize(equations.size() + 1 + outputsSize);
1737             std::ostringstream strOutputs;
1738             strOutputs << outputsSize;
1739             std::string outputsSizeStr = strOutputs.str();
1740             equations[2 + inputsSize] = outputsSizeStr; // Saving the size of the 'outputs' field'
1741             for (size_t i = 0; i < outputsSize; ++i)
1742             {
1743                 c_str = wide_string_to_UTF8(outputsField->get(static_cast<int>(i)));
1744                 std::string outputsFieldStored(c_str);
1745                 FREE(c_str);
1746                 equations[i + 3 + inputsSize] = outputsFieldStored;
1747             }
1748         }
1749
1750         // 'parameters'
1751         int parametersIndex = 4;
1752         if (current->get(parametersIndex)->getType() == types::InternalType::ScilabDouble)
1753         {
1754             // For backward compatibility sake, allow the presence of an empty matrix here
1755             types::Double* emptyMatrix = current->get(parametersIndex)->getAs<types::Double>();
1756             if (emptyMatrix->getSize() != 0)
1757             {
1758                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1759                 return false;
1760             }
1761
1762             parametersIndex++;
1763         }
1764
1765         if (current->get(parametersIndex)->getType() != types::InternalType::ScilabList)
1766         {
1767             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1768             return false;
1769         }
1770
1771         types::List* list = current->get(parametersIndex)->getAs<types::List>();
1772         if (list->getSize() != 2 && list->getSize() != 3)
1773         {
1774             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1775             return false;
1776         }
1777
1778         // 'parameters' names
1779         size_t parametersSize;
1780         if (list->get(0)->getType() == types::InternalType::ScilabDouble)
1781         {
1782             types::Double* parametersNames = list->get(0)->getAs<types::Double>();
1783             if (parametersNames->getSize() != 0)
1784             {
1785                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1786                 return false;
1787             }
1788
1789             // When 'parameters(1)'=[], just insert "0" in 'equations', set in the model and return
1790             parametersSize = 0;
1791             std::ostringstream strParameters;
1792             strParameters << parametersSize;
1793             std::string parametersSizeStr = strParameters.str();
1794             equations.push_back(parametersSizeStr);
1795
1796             controller.setObjectProperty(adaptee, BLOCK, EQUATIONS, equations);
1797             return true;
1798         }
1799         else
1800         {
1801             if (list->get(0)->getType() != types::InternalType::ScilabString)
1802             {
1803                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1804                 return false;
1805             }
1806
1807             types::String* parametersNames = list->get(0)->getAs<types::String>();
1808             parametersSize = parametersNames->getSize();
1809             equations.resize(equations.size() + 1 + parametersSize);
1810             std::ostringstream strParameters;
1811             strParameters << parametersSize;
1812             std::string parametersSizeStr = strParameters.str();
1813             equations[3 + inputsSize + outputsSize] = parametersSizeStr; // Saving the size of the 'parameters' field'
1814             for (size_t i = 0; i < parametersSize; ++i)
1815             {
1816                 c_str = wide_string_to_UTF8(parametersNames->get(static_cast<int>(i)));
1817                 std::string parametersName(c_str);
1818                 FREE(c_str);
1819                 equations[i + 4 + inputsSize + outputsSize] = parametersName;
1820             }
1821         }
1822
1823         // 'parameters' values
1824         if (list->get(1)->getType() == types::InternalType::ScilabDouble)
1825         {
1826             types::Double* parameterVal = list->get(1)->getAs<types::Double>();
1827             if (parameterVal->getSize() != static_cast<int>(parametersSize))
1828             {
1829                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1830                 return false;
1831             }
1832
1833             for (size_t i = 0; i < parametersSize; ++i)
1834             {
1835                 std::ostringstream strParameterVal;
1836                 strParameterVal << parameterVal->get(static_cast<int>(i));
1837                 std::string parameterValStr = strParameterVal.str();
1838                 equations.push_back(parameterValStr);
1839             }
1840         }
1841         else
1842         {
1843             if (list->get(1)->getType() != types::InternalType::ScilabList)
1844             {
1845                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1846                 return false;
1847             }
1848
1849             types::List* list2 = list->get(1)->getAs<types::List>();
1850             if (list2->getSize() != static_cast<int>(parametersSize))
1851             {
1852                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1853                 return false;
1854             }
1855
1856             equations.resize(equations.size() + parametersSize);
1857             for (size_t i = 0; i < parametersSize; ++i)
1858             {
1859                 if (list2->get(static_cast<int>(i))->getType() != types::InternalType::ScilabDouble)
1860                 {
1861                     get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1862                     return false;
1863                 }
1864
1865                 types::Double* parametersVal = list2->get(static_cast<int>(i))->getAs<types::Double>();
1866                 if (parametersVal->getSize() != 1)
1867                 {
1868                     get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Equation expected.\n"), "model", "equations");
1869                     return false;
1870                 }
1871
1872                 std::ostringstream strParametersVal;
1873                 strParametersVal << parametersVal->get(0);
1874                 std::string parametersValStr = strParametersVal.str();
1875                 equations[i + 4 + inputsSize + outputsSize + parametersSize] = parametersValStr;
1876             }
1877         }
1878
1879         // 'parameters' states (optional)
1880         equations.push_back("F"); // String boolean to indicate the presence, or not, of a "states" field
1881         if (list->getSize() == 3)
1882         {
1883             equations.back() = "T";
1884             if (list->get(2)->getType() != types::InternalType::ScilabDouble)
1885             {
1886                 return false;
1887             }
1888
1889             types::Double* parameterStates = list->get(2)->getAs<types::Double>();
1890             if (parameterStates->getSize() != static_cast<int>(parametersSize))
1891             {
1892                 return false;
1893             }
1894
1895             for (size_t i = 0; i < parametersSize; ++i)
1896             {
1897                 std::ostringstream strParameterStates;
1898                 strParameterStates << parameterStates->get(static_cast<int>(i));
1899                 std::string parameterStatesStr = strParameterStates.str();
1900                 equations.push_back(parameterStatesStr);
1901             }
1902         }
1903
1904         controller.setObjectProperty(adaptee, BLOCK, EQUATIONS, equations);
1905         return true;
1906     }
1907 };
1908
1909 struct uid
1910 {
1911
1912     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1913     {
1914         ScicosID adaptee = adaptor.getAdaptee()->id();
1915
1916         std::string uid;
1917         controller.getObjectProperty(adaptee, BLOCK, UID, uid);
1918
1919         types::String* o = new types::String(1, 1);
1920         o->set(0, uid.data());
1921
1922         return o;
1923     }
1924
1925     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1926     {
1927         if (v->getType() != types::InternalType::ScilabString)
1928         {
1929             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: String expected.\n"), "model", "uid");
1930             return false;
1931         }
1932
1933         types::String* current = v->getAs<types::String>();
1934         if (current->getSize() != 1)
1935         {
1936             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s: String expected.\n"), "model", "uid");
1937             return false;
1938         }
1939
1940         ScicosID adaptee = adaptor.getAdaptee()->id();
1941
1942         char* c_str = wide_string_to_UTF8(current->get(0));
1943         std::string uid(c_str);
1944         FREE(c_str);
1945
1946         controller.setObjectProperty(adaptee, BLOCK, UID, uid);
1947         return true;
1948     }
1949 };
1950
1951 } /* namespace */
1952
1953 template<> property<ModelAdapter>::props_t property<ModelAdapter>::fields = property<ModelAdapter>::props_t();
1954 static void initialize_fields()
1955 {
1956     if (property<ModelAdapter>::properties_have_not_been_set())
1957     {
1958         property<ModelAdapter>::fields.reserve(23);
1959         property<ModelAdapter>::add_property(L"sim", &sim::get, &sim::set);
1960         property<ModelAdapter>::add_property(L"in", &in::get, &in::set);
1961         property<ModelAdapter>::add_property(L"in2", &in2::get, &in2::set);
1962         property<ModelAdapter>::add_property(L"intyp", &intyp::get, &intyp::set);
1963         property<ModelAdapter>::add_property(L"out", &out::get, &out::set);
1964         property<ModelAdapter>::add_property(L"out2", &out2::get, &out2::set);
1965         property<ModelAdapter>::add_property(L"outtyp", &outtyp::get, &outtyp::set);
1966         property<ModelAdapter>::add_property(L"evtin", &evtin::get, &evtin::set);
1967         property<ModelAdapter>::add_property(L"evtout", &evtout::get, &evtout::set);
1968         property<ModelAdapter>::add_property(L"state", &state::get, &state::set);
1969         property<ModelAdapter>::add_property(L"dstate", &dstate::get, &dstate::set);
1970         property<ModelAdapter>::add_property(L"odstate", &odstate::get, &odstate::set);
1971         property<ModelAdapter>::add_property(L"rpar", &rpar::get, &rpar::set);
1972         property<ModelAdapter>::add_property(L"ipar", &ipar::get, &ipar::set);
1973         property<ModelAdapter>::add_property(L"opar", &opar::get, &opar::set);
1974         property<ModelAdapter>::add_property(L"blocktype", &blocktype::get, &blocktype::set);
1975         property<ModelAdapter>::add_property(L"firing", &firing::get, &firing::set);
1976         property<ModelAdapter>::add_property(L"dep_ut", &dep_ut::get, &dep_ut::set);
1977         property<ModelAdapter>::add_property(L"label", &label::get, &label::set);
1978         property<ModelAdapter>::add_property(L"nzcross", &nzcross::get, &nzcross::set);
1979         property<ModelAdapter>::add_property(L"nmode", &nmode::get, &nmode::set);
1980         property<ModelAdapter>::add_property(L"equations", &equations::get, &equations::set);
1981         property<ModelAdapter>::add_property(L"uid", &uid::get, &uid::set);
1982     }
1983 }
1984
1985 ModelAdapter::ModelAdapter() :
1986     BaseAdapter<ModelAdapter, org_scilab_modules_scicos::model::Block>(),
1987     m_diagramAdapter(nullptr)
1988 {
1989     initialize_fields();
1990 }
1991 ModelAdapter::ModelAdapter(const Controller& c, model::Block* adaptee, DiagramAdapter* diagramAdapter) :
1992     BaseAdapter<ModelAdapter, org_scilab_modules_scicos::model::Block>(c, adaptee),
1993     m_diagramAdapter(diagramAdapter)
1994 {
1995     initialize_fields();
1996 }
1997
1998 ModelAdapter::~ModelAdapter()
1999 {
2000 }
2001
2002 std::wstring ModelAdapter::getTypeStr()
2003 {
2004     return getSharedTypeStr();
2005 }
2006
2007 std::wstring ModelAdapter::getShortTypeStr()
2008 {
2009     return getSharedTypeStr();
2010 }
2011
2012 DiagramAdapter* ModelAdapter::getDiagram() const
2013 {
2014     return m_diagramAdapter;
2015 }
2016
2017 void ModelAdapter::setDiagram(DiagramAdapter* diagramAdapter)
2018 {
2019     // Does not increment reference as this adapter does not own the DiagramAdapter
2020     m_diagramAdapter = diagramAdapter;
2021 }
2022
2023 } /* namespace view_scilab */
2024 } /* namespace org_scilab_modules_scicos */