Xcos ecore: fix implicit, states and solvers
[scilab.git] / scilab / modules / scicos / src / cpp / XMIResource_load.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2016-2016 - Scilab Enterprises - Clement DAVID
4  *
5  * This file is hereby licensed under the terms of the GNU GPL v2.0,
6  * pursuant to article 5.3.4 of the CeCILL v.2.1.
7  * This file was originally licensed under the terms of the CeCILL v2.1,
8  * and continues to be available under such terms.
9  * For more information, see the COPYING file which you should have received
10  * along with this program.
11  */
12
13 #include "XMIResource.hxx"
14 #include "base64.hxx"
15
16 #include <cassert>
17 #include <string>
18 #include <vector>
19 #include <algorithm>
20 #include <cstdlib> // for atoi and atof
21 #include <cstring> // for strcmp and strchr
22
23 extern "C"
24 {
25 #include <libxml/tree.h>
26 #include <libxml/parser.h>
27 #include <libxml/xmlerror.h>
28 #include <libxml/xmlreader.h>
29
30 #include "sci_types.h"
31 #include "sciprint.h"
32 }
33
34 namespace org_scilab_modules_scicos
35 {
36
37 /**
38  * Display on the Scilab console
39  */
40 void console_print(void *, const char *msg, ...) LIBXML_ATTR_FORMAT(2, 3);
41 void console_print(void *, const char *msg, ...)
42 {
43     //print the message
44     va_list ap;
45     va_start(ap, msg);
46     scivprint(msg, ap);
47     va_end(ap);
48 }
49
50 /**
51  * Helper class to set / reset the XML parser state
52  */
53 struct LibXML2State
54 {
55     LibXML2State()
56     {
57         xmlGenericErrorFunc f = &console_print;
58         initGenericErrorDefaultFunc(&f);
59     }
60     ~LibXML2State()
61     {
62         initGenericErrorDefaultFunc(nullptr);
63     }
64 };
65
66 int XMIResource::load(const char* uri)
67 {
68     int ret;
69
70     LibXML2State state;
71
72     /*
73      * Allocate the reader object, this API is used as it is simpler to use than SAX2 :
74      *  * we have direct access to a node object
75      *  * Strings are interned by libxml2
76      *  * partial SAX2 callbacks are not supported by libxml2
77      */
78     xmlTextReaderPtr reader;
79     /* resolve xinclude and intern strings */
80     reader = xmlReaderForFile(uri, NULL, XML_PARSE_XINCLUDE | XML_PARSE_COMPACT);
81
82     /*
83      * Intern strings to speedup comparaison, this table can be generated using XPath on xcos.ecore .
84      */
85     constXcosNames[e_Annotation] = xmlTextReaderConstString(reader, BAD_CAST ("Annotation"));
86     constXcosNames[e_BaseObject] = xmlTextReaderConstString(reader, BAD_CAST ("BaseObject"));
87     constXcosNames[e_Block] = xmlTextReaderConstString(reader, BAD_CAST ("Block"));
88     constXcosNames[e_CompiledRepresentation] = xmlTextReaderConstString(reader, BAD_CAST ("CompiledRepresentation"));
89     constXcosNames[e_Diagram] = xmlTextReaderConstString(reader, BAD_CAST ("Diagram"));
90     constXcosNames[e_Geometry] = xmlTextReaderConstString(reader, BAD_CAST ("Geometry"));
91     constXcosNames[e_Layer] = xmlTextReaderConstString(reader, BAD_CAST ("Layer"));
92     constXcosNames[e_Link] = xmlTextReaderConstString(reader, BAD_CAST ("Link"));
93     constXcosNames[e_Point] = xmlTextReaderConstString(reader, BAD_CAST ("Point"));
94     constXcosNames[e_Port] = xmlTextReaderConstString(reader, BAD_CAST ("Port"));
95     constXcosNames[e_PortKind] = xmlTextReaderConstString(reader, BAD_CAST ("PortKind"));
96     constXcosNames[e_SimulationConfig] = xmlTextReaderConstString(reader, BAD_CAST ("SimulationConfig"));
97     constXcosNames[e_absoluteTolerance] = xmlTextReaderConstString(reader, BAD_CAST ("absoluteTolerance"));
98     constXcosNames[e_base64] = xmlTextReaderConstString(reader, BAD_CAST ("base64"));
99     constXcosNames[e_blocktype] = xmlTextReaderConstString(reader, BAD_CAST ("blocktype"));
100     constXcosNames[e_child] = xmlTextReaderConstString(reader, BAD_CAST ("child"));
101     constXcosNames[e_color] = xmlTextReaderConstString(reader, BAD_CAST ("color"));
102     constXcosNames[e_columns] = xmlTextReaderConstString(reader, BAD_CAST ("columns"));
103     constXcosNames[e_connectedSignal] = xmlTextReaderConstString(reader, BAD_CAST ("connectedSignal"));
104     constXcosNames[e_context] = xmlTextReaderConstString(reader, BAD_CAST ("context"));
105     constXcosNames[e_controlPoint] = xmlTextReaderConstString(reader, BAD_CAST ("controlPoint"));
106     constXcosNames[e_datatype] = xmlTextReaderConstString(reader, BAD_CAST ("datatype"));
107     constXcosNames[e_debugLevel] = xmlTextReaderConstString(reader, BAD_CAST ("debugLevel"));
108     constXcosNames[e_deltaH] = xmlTextReaderConstString(reader, BAD_CAST ("deltaH"));
109     constXcosNames[e_deltaT] = xmlTextReaderConstString(reader, BAD_CAST ("deltaT"));
110     constXcosNames[e_dependsOnT] = xmlTextReaderConstString(reader, BAD_CAST ("dependsOnT"));
111     constXcosNames[e_dependsOnU] = xmlTextReaderConstString(reader, BAD_CAST ("dependsOnU"));
112     constXcosNames[e_description] = xmlTextReaderConstString(reader, BAD_CAST ("description"));
113     constXcosNames[e_destinationPort] = xmlTextReaderConstString(reader, BAD_CAST ("destinationPort"));
114     constXcosNames[e_dstate] = xmlTextReaderConstString(reader, BAD_CAST ("dstate"));
115     constXcosNames[e_ein] = xmlTextReaderConstString(reader, BAD_CAST ("ein"));
116     constXcosNames[e_eout] = xmlTextReaderConstString(reader, BAD_CAST ("eout"));
117     constXcosNames[e_equations] = xmlTextReaderConstString(reader, BAD_CAST ("equations"));
118     constXcosNames[e_expression] = xmlTextReaderConstString(reader, BAD_CAST ("expression"));
119     constXcosNames[e_exprs] = xmlTextReaderConstString(reader, BAD_CAST ("exprs"));
120     constXcosNames[e_finalTime] = xmlTextReaderConstString(reader, BAD_CAST ("finalTime"));
121     constXcosNames[e_firing] = xmlTextReaderConstString(reader, BAD_CAST ("firing"));
122     constXcosNames[e_font] = xmlTextReaderConstString(reader, BAD_CAST ("font"));
123     constXcosNames[e_fontSize] = xmlTextReaderConstString(reader, BAD_CAST ("fontSize"));
124     constXcosNames[e_functionAPI] = xmlTextReaderConstString(reader, BAD_CAST ("functionAPI"));
125     constXcosNames[e_functionName] = xmlTextReaderConstString(reader, BAD_CAST ("functionName"));
126     constXcosNames[e_geometry] = xmlTextReaderConstString(reader, BAD_CAST ("geometry"));
127     constXcosNames[e_height] = xmlTextReaderConstString(reader, BAD_CAST ("height"));
128     constXcosNames[e_implicit] = xmlTextReaderConstString(reader, BAD_CAST ("implicit"));
129     constXcosNames[e_in] = xmlTextReaderConstString(reader, BAD_CAST ("in"));
130     constXcosNames[e_interfaceFunction] = xmlTextReaderConstString(reader, BAD_CAST ("interfaceFunction"));
131     constXcosNames[e_ipar] = xmlTextReaderConstString(reader, BAD_CAST ("ipar"));
132     constXcosNames[e_kind] = xmlTextReaderConstString(reader, BAD_CAST ("kind"));
133     constXcosNames[e_label] = xmlTextReaderConstString(reader, BAD_CAST ("label"));
134     constXcosNames[e_lineHeight] = xmlTextReaderConstString(reader, BAD_CAST ("lineHeight"));
135     constXcosNames[e_lineWidth] = xmlTextReaderConstString(reader, BAD_CAST ("lineWidth"));
136     constXcosNames[e_nmode] = xmlTextReaderConstString(reader, BAD_CAST ("nmode"));
137     constXcosNames[e_nzcross] = xmlTextReaderConstString(reader, BAD_CAST ("nzcross"));
138     constXcosNames[e_odstate] = xmlTextReaderConstString(reader, BAD_CAST ("odstate"));
139     constXcosNames[e_opar] = xmlTextReaderConstString(reader, BAD_CAST ("opar"));
140     constXcosNames[e_out] = xmlTextReaderConstString(reader, BAD_CAST ("out"));
141     constXcosNames[e_parent] = xmlTextReaderConstString(reader, BAD_CAST ("parent"));
142     constXcosNames[e_parentDiagram] = xmlTextReaderConstString(reader, BAD_CAST ("parentDiagram"));
143     constXcosNames[e_path] = xmlTextReaderConstString(reader, BAD_CAST ("path"));
144     constXcosNames[e_properties] = xmlTextReaderConstString(reader, BAD_CAST ("properties"));
145     constXcosNames[e_realtimeScale] = xmlTextReaderConstString(reader, BAD_CAST ("realtimeScale"));
146     constXcosNames[e_relativeTolerance] = xmlTextReaderConstString(reader, BAD_CAST ("relativeTolerance"));
147     constXcosNames[e_rows] = xmlTextReaderConstString(reader, BAD_CAST ("rows"));
148     constXcosNames[e_rpar] = xmlTextReaderConstString(reader, BAD_CAST ("rpar"));
149     constXcosNames[e_solver] = xmlTextReaderConstString(reader, BAD_CAST ("solver"));
150     constXcosNames[e_sourceBlock] = xmlTextReaderConstString(reader, BAD_CAST ("sourceBlock"));
151     constXcosNames[e_sourcePort] = xmlTextReaderConstString(reader, BAD_CAST ("sourcePort"));
152     constXcosNames[e_state] = xmlTextReaderConstString(reader, BAD_CAST ("state"));
153     constXcosNames[e_style] = xmlTextReaderConstString(reader, BAD_CAST ("style"));
154     constXcosNames[e_timeTolerance] = xmlTextReaderConstString(reader, BAD_CAST ("timeTolerance"));
155     constXcosNames[e_title] = xmlTextReaderConstString(reader, BAD_CAST ("title"));
156     constXcosNames[e_type] = xmlTextReaderConstString(reader, BAD_CAST ("type"));
157     constXcosNames[e_uid] = xmlTextReaderConstString(reader, BAD_CAST ("uid"));
158     constXcosNames[e_version] = xmlTextReaderConstString(reader, BAD_CAST ("version"));
159     constXcosNames[e_width] = xmlTextReaderConstString(reader, BAD_CAST ("width"));
160     constXcosNames[e_x] = xmlTextReaderConstString(reader, BAD_CAST ("x"));
161     constXcosNames[e_xcos] = xmlTextReaderConstString(reader, BAD_CAST ("xcos"));
162     constXcosNames[e_y] = xmlTextReaderConstString(reader, BAD_CAST ("y"));
163
164     xcosNamespaceUri = xmlTextReaderConstString(reader, BAD_CAST ("org.scilab.modules.xcos"));
165     xsiNamespaceUri = xmlTextReaderConstString(reader, BAD_CAST ("http://www.w3.org/2001/XMLSchema-instance"));
166
167     unresolved.clear();
168
169     /*
170      * Process the document
171      */
172     if (reader != NULL)
173     {
174         ret = xmlTextReaderRead(reader);
175         while (ret == 1)
176         {
177             ret = processNode(reader);
178             if (ret == 1)
179             {
180                 ret = xmlTextReaderRead(reader);
181             }
182         }
183         /*
184          * Once the document has been fully parsed check the validation results
185          */
186         if (xmlTextReaderIsValid(reader) < 0)
187         {
188             sciprint("Document %s does not validate\n", uri);
189         }
190         xmlFreeTextReader(reader);
191         if (ret < 0)
192         {
193             sciprint("%s : failed to parse\n", uri);
194             return ret;
195         }
196     }
197     else
198     {
199         sciprint("Unable to open %s\n", uri);
200         return -1;
201     }
202
203     /*
204      * After loading the XML file, resolve all references
205      */
206     for (const unresolvedReference& ref : unresolved)
207     {
208         auto it = references.find(ref.m_uid);
209         if (it != references.end())
210         {
211             controller.setObjectProperty(ref.m_id, ref.m_kind, ref.m_prop, it->second);
212
213             // change the link kind on re-connection
214             if (ref.m_kind == LINK)
215             {
216                 if (ref.m_prop == SOURCE_PORT || ref.m_prop == DESTINATION_PORT)
217                 {
218                     int kind;
219                     controller.getObjectProperty(it->second, PORT, PORT_KIND, kind);
220
221                     if (kind == PORT_EIN || kind == PORT_EOUT)
222                     {
223                         // this should be an event link
224                         controller.setObjectProperty(ref.m_id, LINK, COLOR, 5);
225                         controller.setObjectProperty(ref.m_id, LINK, KIND, -1);
226                     }
227                     else
228                     {
229                         bool isImplicit;
230                         controller.getObjectProperty(it->second, PORT, IMPLICIT, isImplicit);
231
232                         if (isImplicit)
233                         {
234                             // this should be a modelica link
235                             controller.setObjectProperty(ref.m_id, LINK, KIND, 2);
236                         }
237                     }
238                     // otherwise this should be a regular link
239                 }
240             }
241         }
242         else
243         {
244             sciprint("Unable to resolve %s\n", ref.m_uid.c_str());
245             return -1;
246         }
247     }
248
249     return ret;
250 }
251
252 /*
253  * Convert an XML UTF-8 string to a model string
254  */
255 std::string to_string(const xmlChar* xmlStr)
256 {
257     if (xmlStr == nullptr)
258     {
259         return "";
260     }
261
262     // the strings in the model are stored as UTF-8 as in libxml2
263     return std::string((const char*) xmlStr);
264 }
265
266 /*
267  * Convert an XML UTF-8 string to a model int
268  */
269 int to_int(const xmlChar* xmlStr)
270 {
271     if (xmlStr == nullptr)
272     {
273         return 0;
274     }
275
276     return std::atoi((const char*) xmlStr);
277 }
278
279 /*
280  * Convert an XML UTF-8 string to a model boolean
281  */
282 bool to_boolean(const xmlChar* xmlStr)
283 {
284     if (xmlStr == nullptr)
285     {
286         return 0;
287     }
288
289     return std::strcmp((const char*) xmlStr, "true") == 0;
290 }
291
292 /*
293  * Convert an XML UTF-8 string to a model double
294  */
295 double to_double(const xmlChar* xmlStr)
296 {
297     if (xmlStr == nullptr)
298     {
299         return 0.0;
300     }
301
302     return std::atof((const char*) xmlStr);
303 }
304
305 int XMIResource::loadDoubleArray(xmlTextReaderPtr reader, enum object_properties_t property, const model::BaseObject& o)
306 {
307     std::vector<double> v;
308     controller.getObjectProperty(o.id(), o.kind(), property, v);
309
310     v.push_back(to_double(xmlTextReaderConstValue(reader)));
311
312     controller.setObjectProperty(o.id(), o.kind(), property, v);
313     return 1;
314 }
315
316 int XMIResource::loadIntArray(xmlTextReaderPtr reader, enum object_properties_t property, const model::BaseObject& o)
317 {
318     std::vector<int> v;
319     controller.getObjectProperty(o.id(), o.kind(), property, v);
320
321     v.push_back(to_int(xmlTextReaderConstValue(reader)));
322
323     controller.setObjectProperty(o.id(), o.kind(), property, v);
324     return 1;
325 }
326
327 int XMIResource::loadStringArray(xmlTextReaderPtr reader, enum object_properties_t property, const model::BaseObject& o)
328 {
329     std::vector<std::string> v;
330     controller.getObjectProperty(o.id(), o.kind(), property, v);
331
332     v.push_back(to_string(xmlTextReaderConstValue(reader)));
333
334     controller.setObjectProperty(o.id(), o.kind(), property, v);
335     return 1;
336 }
337
338 /* helper function to encode simple string */
339 static std::vector<double> encode_string_vector(const std::vector<std::string>& v)
340 {
341     std::vector<double> ret;
342
343     // header
344     ret.push_back(sci_strings);
345
346     // serialize as a Scilab vector
347     ret.push_back(2); // MxN
348     ret.push_back(v.size()); // M
349     if (v.size() > 0)
350     {
351         ret.push_back(1);    // N
352     }
353     else
354     {
355         ret.push_back(0);
356     }
357
358     // reserve some space to store the length of each string (including the null terminating character)
359     ret.resize(ret.size() + v.size());
360
361     // store the index and the null terminated UTF-8 strings
362     size_t stringOffset = 0;
363     for (size_t i = 0; i < v.size(); ++i)
364     {
365         const std::string& str = v[i];
366         // length as a 64bit index (as we store on a double vector)
367         size_t len = ((str.size() + 1) * sizeof(char) + sizeof(double) - 1) / sizeof(double);
368
369         // insert the offset
370         auto it = ret.begin() + 4 + i;
371         stringOffset += len;
372         *it = stringOffset;
373
374         // reserve some space for the string
375         size_t size = ret.size();
376         ret.resize(size + len);
377
378         // copy the UTF-8 encoded values (\0 terminated thanks to the resize)
379         std::memcpy(ret.data() + size, str.data(), str.size());
380     }
381
382     return ret;
383 }
384
385 /* helper function to decode simple string */
386 static std::vector<std::string> decode_string_vector(const std::vector<double>& v)
387 {
388     std::vector<std::string> exprs;
389
390     if (v.size() < 3)
391     {
392         return exprs;
393     }
394
395     // decode header
396     int type = v[0];
397     int iDims = v[1];
398     if (type != sci_strings )
399     {
400         return exprs;
401     }
402     if (iDims < 2)
403     {
404         return exprs;
405     }
406
407     // number of elements (setup the first one)
408     int iElements = v[2];
409     for (int i = 1; i < iDims; ++i)
410     {
411         iElements *= v[2 + i];
412     }
413
414     if (iElements == 0)
415     {
416         return exprs;
417     }
418
419     // decode UTF-8 strings
420     char* pString = (char*) (v.data() + 2 + iDims + iElements);
421     size_t len = static_cast<size_t>(v[2 + iDims]);
422     for (int i = 1; i < iElements; i++)
423     {
424         exprs.emplace_back(pString);
425
426         pString = (char*) (v.data() + 2 + iDims + iElements + len);
427         len = static_cast<size_t>(v[2 + iDims + i]);
428     }
429     exprs.emplace_back(pString);
430
431     return exprs;
432 }
433
434 int XMIResource::loadEncodedStringArray(xmlTextReaderPtr reader, enum object_properties_t property, const model::BaseObject& o)
435 {
436     std::vector<double> v;
437     controller.getObjectProperty(o.id(), o.kind(), property, v);
438
439     std::vector<std::string> exprsAsString = decode_string_vector(v);
440     exprsAsString.push_back(to_string(xmlTextReaderConstValue(reader)));
441
442     controller.setObjectProperty(o.id(), o.kind(), property, encode_string_vector(exprsAsString));
443     return 1;
444 }
445
446 int XMIResource::loadBase64(xmlTextReaderPtr reader, enum object_properties_t property, const model::BaseObject& o)
447 {
448     // iterate on attributes
449     for (int rc = xmlTextReaderMoveToFirstAttribute(reader); rc > 0; rc = xmlTextReaderMoveToNextAttribute(reader))
450     {
451         auto found = std::find(constXcosNames.begin(), constXcosNames.end(), xmlTextReaderConstName(reader));
452         enum xcosNames current = static_cast<enum xcosNames>(std::distance(constXcosNames.begin(), found));
453
454         switch (current)
455         {
456             case e_base64:
457             {
458                 const xmlChar* base64 = xmlTextReaderConstValue(reader);
459                 std::vector<double> v = base64::decode<std::vector<double> >(to_string(base64));
460                 controller.setObjectProperty(o.id(), o.kind(), property, v);
461                 break;
462             }
463             default:
464                 // ignore other parameters
465                 // TODO: Does other metamodels might be managed there ?
466                 break;
467         }
468     }
469
470     return 1;
471 }
472
473 int XMIResource::loadDatatype(xmlTextReaderPtr reader, const model::BaseObject& o)
474 {
475     assert(o.kind() == PORT);
476
477     std::vector<int> datatype;
478     controller.getObjectProperty(o.id(), o.kind(), DATATYPE, datatype);
479
480     // iterate on attributes
481     for (int rc = xmlTextReaderMoveToFirstAttribute(reader); rc > 0; rc = xmlTextReaderMoveToNextAttribute(reader))
482     {
483         auto found = std::find(constXcosNames.begin(), constXcosNames.end(), xmlTextReaderConstName(reader));
484         enum xcosNames current = static_cast<enum xcosNames>(std::distance(constXcosNames.begin(), found));
485         switch (current)
486         {
487             case e_type:
488                 datatype[2]  = to_double(xmlTextReaderConstValue(reader));
489                 break;
490             case e_rows:
491                 datatype[0]  = to_double(xmlTextReaderConstValue(reader));
492                 break;
493             case e_columns:
494                 datatype[1]  = to_double(xmlTextReaderConstValue(reader));
495                 break;
496             default:
497                 // ignore other parameters
498                 // TODO: Does other metamodels might be managed there ?
499                 break;
500         }
501     }
502
503     controller.setObjectProperty(o.id(), o.kind(), DATATYPE, datatype);
504     return 1;
505 }
506
507 int XMIResource::loadPoint(xmlTextReaderPtr reader, const model::BaseObject& o)
508 {
509     assert(o.kind() == LINK);
510
511     std::vector<double> points;
512     controller.getObjectProperty(o.id(), o.kind(), CONTROL_POINTS, points);
513
514     // iterate on attributes
515     for (int rc = xmlTextReaderMoveToFirstAttribute(reader); rc > 0; rc = xmlTextReaderMoveToNextAttribute(reader))
516     {
517         auto found = std::find(constXcosNames.begin(), constXcosNames.end(), xmlTextReaderConstName(reader));
518         enum xcosNames current = static_cast<enum xcosNames>(std::distance(constXcosNames.begin(), found));
519         switch (current)
520         {
521             case e_x:
522                 points.push_back(to_double(xmlTextReaderConstValue(reader)));
523                 break;
524             case e_y:
525                 points.push_back(to_double(xmlTextReaderConstValue(reader)));
526                 break;
527             default:
528                 // ignore other parameters
529                 // TODO: Does other metamodels might be managed there ?
530                 break;
531         }
532     }
533
534     controller.setObjectProperty(o.id(), o.kind(), CONTROL_POINTS, points);
535     return 1;
536 }
537
538 int XMIResource::loadGeometry(xmlTextReaderPtr reader, const model::BaseObject& o)
539 {
540     assert(o.kind() == BLOCK || o.kind() == ANNOTATION || o.kind() == LINK);
541
542     std::vector<double> geom;
543     controller.getObjectProperty(o.id(), o.kind(), GEOMETRY, geom);
544     geom.resize(4);
545
546     // iterate on attributes
547     for (int rc = xmlTextReaderMoveToFirstAttribute(reader); rc > 0; rc = xmlTextReaderMoveToNextAttribute(reader))
548     {
549         auto found = std::find(constXcosNames.begin(), constXcosNames.end(), xmlTextReaderConstName(reader));
550         enum xcosNames current = static_cast<enum xcosNames>(std::distance(constXcosNames.begin(), found));
551         switch (current)
552         {
553             case e_x:
554                 geom[0] = to_double(xmlTextReaderConstValue(reader));
555                 break;
556             case e_y:
557                 geom[1] = to_double(xmlTextReaderConstValue(reader));
558                 break;
559             case e_width:
560                 geom[2] = to_double(xmlTextReaderConstValue(reader));
561                 break;
562             case e_height:
563                 geom[3] = to_double(xmlTextReaderConstValue(reader));
564                 break;
565             default:
566                 // ignore other parameters
567                 // TODO: Does other metamodels might be managed there ?
568                 break;
569         }
570     }
571
572     controller.setObjectProperty(o.id(), o.kind(), GEOMETRY, geom);
573     return 1;
574 }
575
576 int XMIResource::loadAbstractBaseObject(xmlTextReaderPtr reader, const model::BaseObject& o)
577 {
578     assert(o.kind() == BLOCK || o.kind() == ANNOTATION || o.kind() == LINK);
579
580     // abstract Layer is not decoded there as it has no attribute
581
582     // iterate on attributes
583     for (int rc = xmlTextReaderMoveToFirstAttribute(reader); rc > 0; rc = xmlTextReaderMoveToNextAttribute(reader))
584     {
585         auto found = std::find(constXcosNames.begin(), constXcosNames.end(), xmlTextReaderConstName(reader));
586         enum xcosNames current = static_cast<enum xcosNames>(std::distance(constXcosNames.begin(), found));
587         switch (current)
588         {
589             case e_uid:
590             {
591                 std::string uid = to_string(xmlTextReaderConstValue(reader));
592                 controller.setObjectProperty(o.id(), o.kind(), UID, uid);
593                 references.insert(std::make_pair(uid, o.id()));
594                 break;
595             }
596             case e_parentDiagram:
597             {
598                 // not lookup needed ; only one diagram is serialized at a time
599                 controller.setObjectProperty(o.id(), o.kind(), PARENT_DIAGRAM, root);
600                 break;
601             }
602             case e_parent:
603             {
604                 // not lookup needed thanks to the XML hierarchy
605                 const model::BaseObject& parent = *(processed.end() - 2);
606                 controller.setObjectProperty(o.id(), o.kind(), PARENT_BLOCK, parent.id());
607                 break;
608             }
609             default:
610                 // ignore other parameters
611                 // TODO: Does other metamodels might be managed there ?
612                 break;
613         }
614     }
615
616     return 1;
617 }
618
619 int XMIResource::loadDiagram(xmlTextReaderPtr reader, const model::BaseObject& o)
620 {
621     assert(o.kind() == DIAGRAM);
622
623     // abstract Layer is not decoded there as it has no attribute
624
625     // iterate on attributes
626     for (int rc = xmlTextReaderMoveToFirstAttribute(reader); rc > 0; rc = xmlTextReaderMoveToNextAttribute(reader))
627     {
628         auto found = std::find(constXcosNames.begin(), constXcosNames.end(), xmlTextReaderConstName(reader));
629         enum xcosNames current = static_cast<enum xcosNames>(std::distance(constXcosNames.begin(), found));
630         switch (current)
631         {
632             case e_title:
633                 controller.setObjectProperty(o.id(), o.kind(), TITLE, to_string(xmlTextReaderConstValue(reader)));
634                 break;
635             case e_path:
636                 controller.setObjectProperty(o.id(), o.kind(), PATH, to_string(xmlTextReaderConstValue(reader)));
637                 break;
638             case e_debugLevel:
639                 controller.setObjectProperty(o.id(), o.kind(), DEBUG_LEVEL, to_int(xmlTextReaderConstValue(reader)));
640                 break;
641             case e_version:
642                 controller.setObjectProperty(o.id(), o.kind(), VERSION_NUMBER, to_string(xmlTextReaderConstValue(reader)));
643                 break;
644             default:
645                 // ignore other parameters
646                 // TODO: Does other metamodels might be managed there ?
647                 break;
648         }
649     }
650
651     return 1;
652 }
653
654 int XMIResource::loadSimulationConfig(xmlTextReaderPtr reader, const model::BaseObject& o)
655 {
656     assert(o.kind() == DIAGRAM);
657
658     std::vector<double> properties;
659     controller.getObjectProperty(o.id(), o.kind(), PROPERTIES, properties);
660     properties.resize(8);
661
662     // iterate on attributes
663     for (int rc = xmlTextReaderMoveToFirstAttribute(reader); rc > 0; rc = xmlTextReaderMoveToNextAttribute(reader))
664     {
665         auto found = std::find(constXcosNames.begin(), constXcosNames.end(), xmlTextReaderConstName(reader));
666         enum xcosNames current = static_cast<enum xcosNames>(std::distance(constXcosNames.begin(), found));
667         switch (current)
668         {
669             case e_finalTime:
670                 properties[0] = to_double(xmlTextReaderConstValue(reader));
671                 break;
672             case e_absoluteTolerance:
673                 properties[1] = to_double(xmlTextReaderConstValue(reader));
674                 break;
675             case e_relativeTolerance:
676                 properties[2] = to_double(xmlTextReaderConstValue(reader));
677                 break;
678             case e_timeTolerance:
679                 properties[3] = to_double(xmlTextReaderConstValue(reader));
680                 break;
681             case e_deltaT:
682                 properties[4] = to_double(xmlTextReaderConstValue(reader));
683                 break;
684             case e_realtimeScale:
685                 properties[5] = to_double(xmlTextReaderConstValue(reader));
686                 break;
687             case e_solver:
688                 properties[6] = to_double(xmlTextReaderConstValue(reader));
689                 break;
690             case e_deltaH:
691                 properties[7] = to_double(xmlTextReaderConstValue(reader));
692                 break;
693             default:
694                 // ignore other parameters
695                 // TODO: Does other metamodels might be managed there ?
696                 break;
697         }
698     }
699
700     controller.setObjectProperty(o.id(), o.kind(), PROPERTIES, properties);
701     return 1;
702 }
703
704 int XMIResource::loadBlock(xmlTextReaderPtr reader, const model::BaseObject& o)
705 {
706     assert(o.kind() == BLOCK);
707
708     // load the base class
709     int ret = loadAbstractBaseObject(reader, o);
710     if (ret != 1)
711     {
712         return ret;
713     }
714
715     // Layer has no attribute so there is no need to decode it there
716     // Geometry is handled as an element
717
718     // iterate on attributes
719     for (int rc = xmlTextReaderMoveToFirstAttribute(reader); rc > 0; rc = xmlTextReaderMoveToNextAttribute(reader))
720     {
721         auto found = std::find(constXcosNames.begin(), constXcosNames.end(), xmlTextReaderConstName(reader));
722         enum xcosNames current = static_cast<enum xcosNames>(std::distance(constXcosNames.begin(), found));
723         switch (current)
724         {
725             case e_description:
726                 controller.setObjectProperty(o.id(), o.kind(), DESCRIPTION, to_string(xmlTextReaderConstValue(reader)));
727                 break;
728             case e_label:
729                 controller.setObjectProperty(o.id(), o.kind(), LABEL, to_string(xmlTextReaderConstValue(reader)));
730                 break;
731             case e_style:
732                 controller.setObjectProperty(o.id(), o.kind(), STYLE, to_string(xmlTextReaderConstValue(reader)));
733                 break;
734             case e_interfaceFunction:
735                 controller.setObjectProperty(o.id(), o.kind(), INTERFACE_FUNCTION, to_string(xmlTextReaderConstValue(reader)));
736                 break;
737             case e_functionName:
738                 controller.setObjectProperty(o.id(), o.kind(), SIM_FUNCTION_NAME, to_string(xmlTextReaderConstValue(reader)));
739                 break;
740             case e_functionAPI:
741                 controller.setObjectProperty(o.id(), o.kind(), SIM_FUNCTION_API, to_int(xmlTextReaderConstValue(reader)));
742                 break;
743             case e_dependsOnT:
744             {
745                 std::vector<int> dep_ut;
746                 controller.getObjectProperty(o.id(), o.kind(), SIM_DEP_UT, dep_ut);
747                 dep_ut.resize(2);
748
749                 dep_ut[1] = to_int(xmlTextReaderConstValue(reader));
750                 controller.setObjectProperty(o.id(), o.kind(), SIM_DEP_UT, dep_ut);
751                 break;
752             }
753             case e_dependsOnU:
754             {
755                 std::vector<int> dep_ut;
756                 controller.getObjectProperty(o.id(), o.kind(), SIM_DEP_UT, dep_ut);
757                 dep_ut.resize(2);
758
759                 dep_ut[0] = to_int(xmlTextReaderConstValue(reader));
760                 controller.setObjectProperty(o.id(), o.kind(), SIM_DEP_UT, dep_ut);
761                 break;
762             }
763             case e_blocktype:
764                 controller.setObjectProperty(o.id(), o.kind(), SIM_BLOCKTYPE, to_string(xmlTextReaderConstValue(reader)));
765                 break;
766             default:
767                 // ignore other parameters
768                 // TODO: Does other metamodels might be managed there ?
769                 break;
770         }
771     }
772
773     /*
774      * Reset some properties loaded as array and initialized with non-empty value
775      */
776     std::vector<int> empty_int_array;
777     controller.setObjectProperty(o.id(), o.kind(), NZCROSS, empty_int_array);
778     controller.setObjectProperty(o.id(), o.kind(), NMODE, empty_int_array);
779
780     return 1;
781 }
782
783 int XMIResource::loadPort(xmlTextReaderPtr reader, const model::BaseObject& o)
784 {
785     assert(o.kind() == PORT);
786
787     // ignore datatype as it is managed as an XML node
788
789     // iterate on attributes
790     for (int rc = xmlTextReaderMoveToFirstAttribute(reader); rc > 0; rc = xmlTextReaderMoveToNextAttribute(reader))
791     {
792         auto found = std::find(constXcosNames.begin(), constXcosNames.end(), xmlTextReaderConstName(reader));
793         enum xcosNames current = static_cast<enum xcosNames>(std::distance(constXcosNames.begin(), found));
794         switch (current)
795         {
796             case e_uid:
797             {
798                 std::string uid = to_string(xmlTextReaderConstValue(reader));
799                 controller.setObjectProperty(o.id(), o.kind(), UID, uid);
800                 references.insert(std::make_pair(uid, o.id()));
801                 break;
802             }
803             case e_firing:
804                 controller.setObjectProperty(o.id(), o.kind(), FIRING, to_double(xmlTextReaderConstValue(reader)));
805                 break;
806             case e_sourceBlock:
807             {
808                 // not lookup needed thanks to the XML hierarchy
809                 break;
810             }
811             case e_kind:
812             {
813                 std::string portKindStr = to_string(xmlTextReaderConstValue(reader));
814                 int k;
815                 if ("in" == portKindStr)
816                 {
817                     k = PORT_IN;
818                 }
819                 else if ("out" == portKindStr)
820                 {
821                     k = PORT_OUT;
822                 }
823                 else if ("ein" == portKindStr)
824                 {
825                     k = PORT_EIN;
826                 }
827                 else if ("eout" == portKindStr)
828                 {
829                     k = PORT_EOUT;
830                 }
831                 else
832                 {
833                     k = PORT_UNDEF;
834                 }
835                 controller.setObjectProperty(o.id(), o.kind(), PORT_KIND, k);
836                 break;
837             }
838             case e_implicit:
839                 controller.setObjectProperty(o.id(), o.kind(), IMPLICIT, to_boolean(xmlTextReaderConstValue(reader)));
840                 break;
841             case e_connectedSignal:
842                 // will be resolved later
843                 unresolved.push_back(
844                     unresolvedReference(o.id(), o.kind(), CONNECTED_SIGNALS,
845                                         to_string(xmlTextReaderConstValue(reader))));
846                 break;
847             case e_style:
848                 controller.setObjectProperty(o.id(), o.kind(), STYLE, to_string(xmlTextReaderConstValue(reader)));
849                 break;
850             case e_label:
851                 controller.setObjectProperty(o.id(), o.kind(), LABEL, to_string(xmlTextReaderConstValue(reader)));
852                 break;
853             default:
854                 // ignore other parameters
855                 // TODO: Does other metamodels might be managed there ?
856                 break;
857         }
858     }
859
860     return 1;
861 }
862
863 int XMIResource::loadLink(xmlTextReaderPtr reader, const model::BaseObject& o)
864 {
865     assert(o.kind() == LINK);
866
867     // load the base class
868     int ret = loadAbstractBaseObject(reader, o);
869     if (ret != 1)
870     {
871         return ret;
872     }
873
874     // geometry is handled as in independent node
875     // controlPoint is handled as in independent node
876
877     // iterate on attributes
878     for (int rc = xmlTextReaderMoveToFirstAttribute(reader); rc > 0; rc = xmlTextReaderMoveToNextAttribute(reader))
879     {
880         auto found = std::find(constXcosNames.begin(), constXcosNames.end(), xmlTextReaderConstName(reader));
881         enum xcosNames current = static_cast<enum xcosNames>(std::distance(constXcosNames.begin(), found));
882         switch (current)
883         {
884             case e_uid:
885             {
886                 std::string uid = to_string(xmlTextReaderConstValue(reader));
887                 controller.setObjectProperty(o.id(), o.kind(), UID, uid);
888                 references.insert(std::make_pair(uid, o.id()));
889                 break;
890             }
891             case e_sourcePort:
892                 // will be resolved later
893                 unresolved.push_back(
894                     unresolvedReference(o.id(), o.kind(), SOURCE_PORT, to_string(xmlTextReaderConstValue(reader))));
895                 break;
896             case e_destinationPort:
897                 // will be resolved later
898                 unresolved.push_back(
899                     unresolvedReference(o.id(), o.kind(), DESTINATION_PORT,
900                                         to_string(xmlTextReaderConstValue(reader))));
901                 break;
902             case e_style:
903                 controller.setObjectProperty(o.id(), o.kind(), STYLE, to_string(xmlTextReaderConstValue(reader)));
904                 break;
905             case e_label:
906                 controller.setObjectProperty(o.id(), o.kind(), LABEL, to_string(xmlTextReaderConstValue(reader)));
907                 break;
908             case e_lineWidth:
909             {
910                 std::vector<double> thick;
911                 controller.getObjectProperty(o.id(), o.kind(), THICK, thick);
912                 thick[0] = to_double(xmlTextReaderConstValue(reader));
913                 controller.setObjectProperty(o.id(), o.kind(), THICK, thick);
914                 break;
915             }
916             case e_lineHeight:
917             {
918                 std::vector<double> thick;
919                 controller.getObjectProperty(o.id(), o.kind(), THICK, thick);
920                 thick[1] = to_double(xmlTextReaderConstValue(reader));
921                 controller.setObjectProperty(o.id(), o.kind(), THICK, thick);
922                 break;
923             }
924             case e_color:
925                 controller.setObjectProperty(o.id(), o.kind(), COLOR, to_int(xmlTextReaderConstValue(reader)));
926                 break;
927             default:
928                 // ignore other parameters
929                 // TODO: Does other metamodels might be managed there ?
930                 break;
931         }
932     }
933
934     return ret;
935 }
936
937 int XMIResource::loadAnnotation(xmlTextReaderPtr reader, const model::BaseObject& o)
938 {
939     assert(o.kind() == ANNOTATION);
940
941     // load the base class
942     int ret = loadAbstractBaseObject(reader, o);
943     if (ret != 1)
944     {
945         return ret;
946     }
947
948     // geometry is handled as a node
949
950     // iterate on attributes
951     for (int rc = xmlTextReaderMoveToFirstAttribute(reader); rc > 0; rc = xmlTextReaderMoveToNextAttribute(reader))
952     {
953         auto found = std::find(constXcosNames.begin(), constXcosNames.end(), xmlTextReaderConstName(reader));
954         enum xcosNames current = static_cast<enum xcosNames>(std::distance(constXcosNames.begin(), found));
955         switch (current)
956         {
957             case e_description:
958                 controller.setObjectProperty(o.id(), o.kind(), DESCRIPTION, to_string(xmlTextReaderConstValue(reader)));
959                 break;
960             case e_font:
961                 controller.setObjectProperty(o.id(), o.kind(), FONT, to_string(xmlTextReaderConstValue(reader)));
962                 break;
963             case e_fontSize:
964                 controller.setObjectProperty(o.id(), o.kind(), FONT_SIZE, to_string(xmlTextReaderConstValue(reader)));
965                 break;
966             case e_style:
967                 controller.setObjectProperty(o.id(), o.kind(), STYLE, to_string(xmlTextReaderConstValue(reader)));
968                 break;
969             default:
970                 // ignore other parameters
971                 // TODO: Does other metamodels might be managed there ?
972                 break;
973         }
974     }
975
976     return ret;
977 }
978
979 int XMIResource::processNode(xmlTextReaderPtr reader)
980 {
981     // manage only xcos related XML nodes
982     const xmlChar* nsURI = xmlTextReaderConstNamespaceUri(reader);
983     if (nsURI == xcosNamespaceUri || nsURI == nullptr)
984     {
985         xmlReaderTypes nodeType = (xmlReaderTypes) xmlTextReaderNodeType(reader);
986         switch (nodeType)
987         {
988             case XML_READER_TYPE_NONE:
989                 return 1;
990             case XML_READER_TYPE_ELEMENT:
991                 return processElement(reader);
992             case XML_READER_TYPE_ATTRIBUTE:
993                 sciprint("xmlReader attributes node not supported\n");
994                 return -1;
995             case XML_READER_TYPE_TEXT:
996                 return processText(reader);
997             case XML_READER_TYPE_CDATA:
998                 return processText(reader);
999             case XML_READER_TYPE_ENTITY_REFERENCE:
1000                 sciprint("xmlReader entity reference not supported\n");
1001                 return -1;
1002             case XML_READER_TYPE_ENTITY:
1003                 sciprint("xmlReader entity not supported\n");
1004                 return -1;
1005             case XML_READER_TYPE_PROCESSING_INSTRUCTION:
1006                 sciprint("xmlReader processing instruction not supported\n");
1007                 return -1;
1008             case XML_READER_TYPE_COMMENT:
1009                 return 1;
1010             case XML_READER_TYPE_DOCUMENT:
1011                 return 1;
1012             case XML_READER_TYPE_DOCUMENT_TYPE:
1013                 sciprint("xmlReader document type not supported\n");
1014                 return -1;
1015             case XML_READER_TYPE_DOCUMENT_FRAGMENT:
1016                 sciprint("xmlReader document fragment not supported\n");
1017                 return -1;
1018             case XML_READER_TYPE_NOTATION:
1019                 sciprint("xmlReader notation not supported\n");
1020                 return -1;
1021             case XML_READER_TYPE_WHITESPACE:
1022                 sciprint("xmlReader whitespace not supported\n");
1023                 return -1;
1024             case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
1025                 return 1; // ignore indent or end-of-line
1026             case XML_READER_TYPE_END_ELEMENT:
1027                 return processEndElement(reader);
1028             case XML_READER_TYPE_END_ENTITY:
1029                 sciprint("xmlReader end entity not supported\n");
1030                 return -1;
1031             case XML_READER_TYPE_XML_DECLARATION:
1032                 sciprint("xmlReader XML declaration not supported\n");
1033                 return -1;
1034         }
1035     }
1036     else
1037     {
1038         // TODO mixed model should be preserved in some way and restored back on XMIResource_save.cpp .
1039     }
1040     sciprint("unable to process node\n");
1041     return -1;
1042 }
1043
1044 int XMIResource::processElement(xmlTextReaderPtr reader)
1045 {
1046     const xmlChar *name = xmlTextReaderConstLocalName(reader);
1047     parent = NB_XCOS_NAMES;
1048
1049     // lookup for known node names
1050     // thanks to the string intern-ing, the pointer comparison could be used
1051     auto found = std::find(constXcosNames.begin(), constXcosNames.end(), name);
1052     enum xcosNames current = static_cast<enum xcosNames>(std::distance(constXcosNames.begin(), found));
1053     switch (current)
1054     {
1055         case e_Diagram:
1056         {
1057             // the root diagram should be decoded
1058             model::BaseObject o(root, DIAGRAM);
1059
1060             processed.push_back(o);
1061             return loadDiagram(reader, o);
1062         }
1063         case e_child:
1064         {
1065             // this is a child of a diagram, resolve the type and call the loaders
1066             // iterate on attributes to lookup for EMF type
1067
1068             // iterate on attributes
1069             for (int rc = xmlTextReaderMoveToFirstAttribute(reader); rc > 0; rc = xmlTextReaderMoveToNextAttribute(reader))
1070             {
1071                 const xmlChar* nsURI  = xmlTextReaderConstNamespaceUri(reader);
1072                 if (nsURI != xsiNamespaceUri)
1073                 {
1074                     continue;
1075                 }
1076
1077                 auto foundName = std::find(constXcosNames.begin(), constXcosNames.end(), xmlTextReaderConstLocalName(reader));
1078                 enum xcosNames currentName = static_cast<enum xcosNames>(std::distance(constXcosNames.begin(), foundName));
1079                 if (currentName != e_type)
1080                 {
1081                     continue;
1082                 }
1083
1084                 const xmlChar* value = xmlTextReaderConstValue(reader);
1085                 const xmlChar* valueWithoutPrefix = BAD_CAST(std::strchr((const char*) value, ':'));
1086                 if (valueWithoutPrefix == nullptr)
1087                 {
1088                     valueWithoutPrefix = value;
1089                 }
1090                 else
1091                 {
1092                     // remove the leading ':'
1093                     valueWithoutPrefix = valueWithoutPrefix + 1;
1094                 }
1095                 const xmlChar* interned = xmlTextReaderConstString(reader, valueWithoutPrefix);
1096
1097                 auto found = std::find(constXcosNames.begin(), constXcosNames.end(), interned);
1098                 enum xcosNames current = static_cast<enum xcosNames>(std::distance(constXcosNames.begin(), found));
1099                 switch (current)
1100                 {
1101                     case e_Block:
1102                     {
1103                         ScicosID o = controller.createObject(BLOCK);
1104
1105                         // assign the child
1106                         model::BaseObject parent = processed.back();
1107
1108                         controller.referenceObject(o);
1109                         controller.setObjectProperty(o, BLOCK, PARENT_DIAGRAM, root);
1110                         if (parent.kind() == BLOCK)
1111                         {
1112                             controller.setObjectProperty(o, BLOCK, PARENT_BLOCK, parent.id());
1113                         }
1114                         std::vector<ScicosID> children;
1115                         controller.getObjectProperty(parent.id(), parent.kind(), CHILDREN, children);
1116                         children.push_back(o);
1117                         controller.setObjectProperty(parent.id(), parent.kind(), CHILDREN, children);
1118
1119                         model::BaseObject child(o, BLOCK);
1120                         processed.push_back(child);
1121                         return loadBlock(reader, child);
1122                     }
1123                     case e_Link:
1124                     {
1125                         ScicosID o = controller.createObject(LINK);
1126
1127                         // assign the child
1128                         model::BaseObject parent = processed.back();
1129
1130                         controller.referenceObject(o);
1131                         controller.setObjectProperty(o, LINK, PARENT_DIAGRAM, root);
1132                         if (parent.kind() == BLOCK)
1133                         {
1134                             controller.setObjectProperty(o, LINK, PARENT_BLOCK, parent.id());
1135                         }
1136                         std::vector<ScicosID> children;
1137                         controller.getObjectProperty(parent.id(), parent.kind(), CHILDREN, children);
1138                         children.push_back(o);
1139                         controller.setObjectProperty(parent.id(), parent.kind(), CHILDREN, children);
1140
1141                         model::BaseObject child(o, LINK);
1142                         processed.push_back(child);
1143                         return loadLink(reader, child);
1144                     }
1145                     case e_Annotation:
1146                     {
1147                         ScicosID o = controller.createObject(ANNOTATION);
1148
1149                         // assign the child
1150                         model::BaseObject parent = processed.back();
1151
1152                         controller.referenceObject(o);
1153                         controller.setObjectProperty(o, ANNOTATION, PARENT_DIAGRAM, root);
1154                         if (parent.kind() == BLOCK)
1155                         {
1156                             controller.setObjectProperty(o, ANNOTATION, PARENT_BLOCK, parent.id());
1157                         }
1158                         std::vector<ScicosID> children;
1159                         controller.getObjectProperty(parent.id(), parent.kind(), CHILDREN, children);
1160                         children.push_back(o);
1161                         controller.setObjectProperty(parent.id(), parent.kind(), CHILDREN, children);
1162
1163                         model::BaseObject child(o, ANNOTATION);
1164                         return loadAnnotation(reader, child);
1165                     }
1166                     default:
1167                         sciprint("Not handled child type=%s at line %d\n", *found,
1168                                  xmlTextReaderGetParserLineNumber(reader) - 1);
1169                         return -1;
1170                 }
1171             }
1172             break;
1173         }
1174         case e_in: // no break on purpose
1175         case e_out: // no break on purpose
1176         case e_ein: // no break on purpose
1177         case e_eout:
1178         {
1179             ScicosID o = controller.createObject(PORT);
1180
1181             enum object_properties_t p;
1182             switch (current)
1183             {
1184                 case e_in:
1185                     p = INPUTS;
1186                     break;
1187                 case e_out:
1188                     p = OUTPUTS;
1189                     break;
1190                 case e_ein:
1191                     p = EVENT_INPUTS;
1192                     break;
1193                 case e_eout:
1194                     p = EVENT_OUTPUTS;
1195                     break;
1196                 default:
1197                     return -1;
1198             }
1199
1200             model::BaseObject parent = processed.back();
1201             // add the port them to the parent
1202             controller.setObjectProperty(o, PORT, SOURCE_BLOCK, parent.id());
1203
1204             std::vector<ScicosID> ports;
1205             controller.getObjectProperty(parent.id(), parent.kind(), p, ports);
1206             ports.push_back(o);
1207             controller.setObjectProperty(parent.id(), parent.kind(), p, ports);
1208
1209             // decode content
1210             model::BaseObject child(o, PORT);
1211             processed.push_back(child);
1212             return loadPort(reader, child);
1213         }
1214         case e_geometry:
1215             // geometry is used for rectangle coordinates of its parent
1216             return loadGeometry(reader, processed.back());
1217         case e_nzcross:
1218             // nzcross is a Block property
1219             if (!xmlTextReaderIsEmptyElement(reader))
1220             {
1221                 parent = current;
1222             }
1223             return 1;
1224         case e_nmode:
1225             // nmode is a Block property
1226             if (!xmlTextReaderIsEmptyElement(reader))
1227             {
1228                 parent = current;
1229             }
1230             return 1;
1231         case e_rpar:
1232             // rpar is a Block property
1233             if (!xmlTextReaderIsEmptyElement(reader))
1234             {
1235                 parent = current;
1236             }
1237             return 1;
1238         case e_ipar:
1239             // ipar is a Block property
1240             if (!xmlTextReaderIsEmptyElement(reader))
1241             {
1242                 parent = current;
1243             }
1244             return 1;
1245         case e_opar:
1246             // ipar is a Block property
1247             return loadBase64(reader, OPAR, processed.back());
1248         case e_state:
1249             // state is a Block property
1250             if (!xmlTextReaderIsEmptyElement(reader))
1251             {
1252                 parent = current;
1253             }
1254             return 1;
1255         case e_dstate:
1256             // dstate is a Block property
1257             if (!xmlTextReaderIsEmptyElement(reader))
1258             {
1259                 parent = current;
1260             }
1261             return 1;
1262         case e_odstate:
1263             // odstate is a Block property
1264             return loadBase64(reader, ODSTATE, processed.back());
1265         case e_equations:
1266             // equation is a Block property
1267             return loadBase64(reader, EQUATIONS, processed.back());
1268         case e_expression:
1269             // expression is a Block property
1270             if (!xmlTextReaderIsEmptyElement(reader))
1271             {
1272                 parent = current;
1273             }
1274             return 1;
1275         case e_exprs:
1276             // exprs is a Block property
1277             return loadBase64(reader, EXPRS, processed.back());
1278         case e_controlPoint:
1279             // controlPoint is a link property
1280             return loadPoint(reader, processed.back());
1281         case e_context:
1282             // context is a Layer property
1283             if (!xmlTextReaderIsEmptyElement(reader))
1284             {
1285                 parent = current;
1286             }
1287             return 1;
1288         case e_properties:
1289             // properties is a Diagram property
1290             return loadSimulationConfig(reader, processed.back());
1291         case e_datatype:
1292             // datatype is a Port property
1293             return loadDatatype(reader, processed.back());
1294         default:
1295             sciprint("Unknown \"%s\" element name at line %d\n", name, xmlTextReaderGetParserLineNumber(reader) - 1);
1296             return -1;
1297     }
1298
1299     return 1;
1300 }
1301
1302 int XMIResource::processText(xmlTextReaderPtr reader)
1303 {
1304     int ret;
1305
1306     switch (parent)
1307     {
1308         case e_nzcross:
1309             // nzcross is a Block property
1310             ret = loadIntArray(reader, NZCROSS, processed.back());
1311             break;
1312         case e_nmode:
1313             // nmode is a Block property
1314             ret = loadIntArray(reader, NMODE, processed.back());
1315             break;
1316         case e_rpar:
1317             // rpar is a Block property
1318             ret = loadDoubleArray(reader, RPAR, processed.back());
1319             break;
1320         case e_ipar:
1321             // ipar is a Block property
1322             ret = loadIntArray(reader, IPAR, processed.back());
1323             break;
1324         case e_state:
1325             // state is a Block property
1326             ret = loadDoubleArray(reader, STATE, processed.back());
1327             break;
1328         case e_dstate:
1329             // dstate is a Block property
1330             ret = loadDoubleArray(reader, DSTATE, processed.back());
1331             break;
1332         case e_expression:
1333             // expression is a Block property
1334             ret = loadEncodedStringArray(reader, EXPRS, processed.back());
1335             break;
1336         case e_context:
1337             // context is a Layer property
1338             ret = loadStringArray(reader, DIAGRAM_CONTEXT, processed.back());
1339             break;
1340         case e_datatype:
1341             // datatype is a port property
1342             ret = loadIntArray(reader, DATATYPE, processed.back());
1343             break;
1344         default:
1345             sciprint("Unable to decode text value at line %d\n", xmlTextReaderGetParserLineNumber(reader) - 1);
1346             ret = -1;
1347             break;
1348     }
1349
1350     return ret;
1351 }
1352
1353 int XMIResource::processEndElement(xmlTextReaderPtr)
1354 {
1355     if (parent == NB_XCOS_NAMES)
1356     {
1357         processed.pop_back();
1358     }
1359     else
1360     {
1361         parent = NB_XCOS_NAMES;
1362     }
1363
1364     return 1;
1365 }
1366
1367 } /* namespace org_scilab_modules_xcos */