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