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