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