Xcos: reintroduce a private xcosDiagramToScilab
[scilab.git] / scilab / modules / xcos / src / java / org / scilab / modules / xcos / io / sax / RawDataHandler.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2015-2015 - Scilab Enterprises - Clement DAVID
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
10  *
11  */
12
13 package org.scilab.modules.xcos.io.sax;
14
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.Map;
19
20 import org.scilab.modules.types.ScilabBoolean;
21 import org.scilab.modules.types.ScilabDouble;
22 import org.scilab.modules.types.ScilabInteger;
23 import org.scilab.modules.types.ScilabIntegerTypeEnum;
24 import org.scilab.modules.types.ScilabList;
25 import org.scilab.modules.types.ScilabMList;
26 import org.scilab.modules.types.ScilabString;
27 import org.scilab.modules.types.ScilabTList;
28 import org.scilab.modules.types.ScilabType;
29 import org.scilab.modules.xcos.ObjectProperties;
30 import org.scilab.modules.xcos.VectorOfDouble;
31 import org.scilab.modules.xcos.VectorOfString;
32 import org.scilab.modules.xcos.graph.model.ScicosObjectOwner;
33 import org.scilab.modules.xcos.graph.model.XcosCell;
34 import org.xml.sax.Attributes;
35
36 import com.mxgraph.model.mxGeometry;
37 import com.mxgraph.util.mxPoint;
38
39 class RawDataHandler implements ScilabHandler {
40
41     static class RawDataDescriptor {
42         final ObjectProperties as;
43         final HandledElement found;
44         final String scilabClass;
45         final Object value;
46
47         public RawDataDescriptor(ObjectProperties as, HandledElement found, String scilabClass, Object container) {
48             // defensive programming
49             if (as == null) {
50                 throw new IllegalArgumentException();
51             }
52
53             this.as = as;
54             this.found = found;
55             this.scilabClass = scilabClass;
56             this.value = container;
57         }
58     }
59
60     private final SAXHandler saxHandler;
61     private final Map<String, ObjectProperties> propertyMap;
62
63     /**
64      * Default constructor
65      * @param saxHandler the shared sax handler
66      */
67     RawDataHandler(SAXHandler saxHandler) {
68         this.saxHandler = saxHandler;
69
70         Map<String, ObjectProperties> localPropertyMap = new HashMap<>();
71         localPropertyMap.put("context", ObjectProperties.DIAGRAM_CONTEXT);
72         localPropertyMap.put("dState", ObjectProperties.DSTATE);
73         localPropertyMap.put("equations", ObjectProperties.EQUATIONS);
74         localPropertyMap.put("exprs", ObjectProperties.EXPRS);
75         localPropertyMap.put("integerParameters", ObjectProperties.IPAR);
76         localPropertyMap.put("nbZerosCrossing", ObjectProperties.NZCROSS);
77         localPropertyMap.put("nmode", ObjectProperties.NMODE);
78         localPropertyMap.put("objectsParameters", ObjectProperties.OPAR);
79         localPropertyMap.put("oDState", ObjectProperties.ODSTATE);
80         localPropertyMap.put("points", ObjectProperties.CONTROL_POINTS);
81         localPropertyMap.put("realParameters", ObjectProperties.RPAR);
82         localPropertyMap.put("state", ObjectProperties.STATE);
83         propertyMap = Collections.unmodifiableMap(localPropertyMap);
84     }
85
86     /*
87      * Implement the ScilabHandler interface to decode the data
88      */
89
90     public Object startElement(HandledElement found, Attributes atts) {
91         String v;
92
93         switch (found) {
94             case ScilabBoolean:
95             // no break on purpose
96             case ScilabDouble:
97             // no break on purpose
98             case ScilabInteger:
99             // no break on purpose
100             case ScilabString:
101             // no break on purpose
102             case Array: {
103                 String as = atts.getValue("as");
104
105                 /*
106                  * first : try to retrieve the already decoded binary data
107                  */
108                 boolean binary = false;
109                 int position = -1;
110
111                 v = atts.getValue("binary");
112                 if (v != null) {
113                     binary = Boolean.valueOf(v);
114                 }
115                 v = atts.getValue("position");
116                 if (v != null) {
117                     position = Integer.valueOf(v);
118                 }
119
120                 if (binary && (0 <= position && position < saxHandler.dictionary.size())) {
121                     return new RawDataDescriptor(propertyMap.get(as), found, null, saxHandler.dictionary.get(position));
122                 }
123
124                 /*
125                  * otherwise : this is not a binary, decode it
126                  */
127                 int height = 0;
128                 int width = 0;
129                 String scilabClass = "ScilabDouble";
130
131                 v = atts.getValue("height");
132                 if (v != null) {
133                     height = Integer.valueOf(v);
134                 }
135                 v = atts.getValue("width");
136                 if (v != null) {
137                     width = Integer.valueOf(v);
138                 }
139                 v = atts.getValue("scilabClass");
140                 if (v != null) {
141                     scilabClass = v;
142                 }
143
144                 // allocate the right class and push it to a descriptor
145                 final Object container = allocateDataType(found, atts, height, width, scilabClass);
146                 return new RawDataDescriptor(propertyMap.get(as), found, scilabClass, container);
147             }
148             case add: {
149                 // defensive programming
150                 if (!(saxHandler.parents.peek() instanceof RawDataDescriptor)) {
151                     return null;
152                 }
153                 RawDataDescriptor fieldValue = (RawDataDescriptor) saxHandler.parents.peek();
154
155                 switch (fieldValue.as) {
156                     case DIAGRAM_CONTEXT: {
157                         @SuppressWarnings("unchecked")
158                         ArrayList<String> container = ((ArrayList<String>) fieldValue.value);
159                         container.add(atts.getValue("value"));
160                         break;
161                     }
162                     default:
163                         break;
164                 }
165                 break;
166             }
167             case data: {
168                 // defensive programming
169                 if (!(saxHandler.parents.peek() instanceof RawDataDescriptor)) {
170                     return null;
171                 }
172                 RawDataDescriptor fieldValue = (RawDataDescriptor) saxHandler.parents.peek();
173
174                 /*
175                  * Decode the position and then switch per container klass
176                  */
177
178                 int column = 0;
179                 int line = 0;
180
181                 v = atts.getValue("column");
182                 if (v != null) {
183                     column = Integer.valueOf(v);
184                 }
185                 v = atts.getValue("line");
186                 if (v != null) {
187                     line = Integer.valueOf(v);
188                 }
189
190                 switch (fieldValue.found) {
191                     case ScilabBoolean: {
192                         ScilabBoolean localScilabValue = ((ScilabBoolean) fieldValue.value);
193                         boolean[][] data = localScilabValue.getData();
194
195                         v = atts.getValue("value");
196                         if (v != null) {
197                             data[line][column] = Boolean.valueOf(v);
198                         }
199                         break;
200                     }
201                     case ScilabDouble: {
202                         ScilabDouble localScilabValue = ((ScilabDouble) fieldValue.value);
203                         double[][] realPartData = localScilabValue.getRealPart();
204                         double[][] imaginaryPartData = localScilabValue.getImaginaryPart();
205
206                         v = atts.getValue("realPart");
207                         if (v != null) {
208                             realPartData[line][column] = Double.valueOf(v);
209                         }
210
211                         v = atts.getValue("imaginaryPart");
212                         if (v != null) {
213                             // allocate the imaginary part on demand
214                             if (imaginaryPartData == null) {
215                                 imaginaryPartData = new double[localScilabValue.getHeight()][localScilabValue.getWidth()];
216                                 localScilabValue.setImaginaryPart(imaginaryPartData);
217                             }
218
219                             imaginaryPartData[line][column] = Double.valueOf(v);
220                         }
221                         break;
222                     }
223                     case ScilabInteger: {
224                         ScilabInteger localScilabValue = ((ScilabInteger) fieldValue.value);
225                         ScilabIntegerTypeEnum precision = localScilabValue.getPrec();
226
227                         v = atts.getValue("value");
228                         if (v != null) {
229                             switch (precision) {
230                                 case sci_int8:
231                                 case sci_uint8:
232                                     localScilabValue.getDataAsByte()[line][column] = Byte.valueOf(v);
233                                     break;
234                                 case sci_int16:
235                                 case sci_uint16:
236                                     localScilabValue.getDataAsShort()[line][column] = Short.valueOf(v);
237                                     break;
238                                 case sci_int32:
239                                 case sci_uint32:
240                                     localScilabValue.getDataAsInt()[line][column] = Integer.valueOf(v);
241                                     break;
242                                 case sci_int64:
243                                 case sci_uint64:
244                                     localScilabValue.getDataAsLong()[line][column] = Long.valueOf(v);
245                                     break;
246                             }
247                         }
248                         break;
249                     }
250                     case ScilabString: {
251                         ScilabString localScilabValue = ((ScilabString) fieldValue.value);
252                         String[][] data = localScilabValue.getData();
253                         data[line][column] = atts.getValue("value");
254                         break;
255                     }
256                     default:
257                         break;
258                 }
259             }
260             default:
261                 throw new IllegalArgumentException();
262         }
263
264         return null;
265     }
266
267     /**
268      * Allocate a {@link ScilabType} datatype accordingly to the decoded descriptors
269      * @param found the decoded element
270      * @param atts the attributes of the element
271      * @param height decoded height
272      * @param width decoded width
273      * @param scilabClass decoded scilabClass
274      * @return the container
275      */
276     private Object allocateDataType(HandledElement found, Attributes atts, int height, int width, String scilabClass) {
277         String v;
278         final Object container;
279         switch (found) {
280             case ScilabBoolean:
281                 container = new ScilabBoolean(new boolean[height][width]);
282                 break;
283             case ScilabDouble:
284                 container = new ScilabDouble(new double[height][width]);
285                 break;
286             case ScilabInteger:
287                 v = atts.getValue("intPrecision");
288                 if (v != null) {
289                     boolean unsigned = true;
290                     switch (ScilabIntegerTypeEnum.valueOf(v)) {
291                         case sci_int8:
292                             unsigned = false;
293                         // no break on purpose
294                         case sci_uint8:
295                             container = new ScilabInteger(new byte[height][width], unsigned);
296                             break;
297                         case sci_int16:
298                             unsigned = false;
299                         // no break on purpose
300                         case sci_uint16:
301                             container = new ScilabInteger(new short[height][width], unsigned);
302                             break;
303                         case sci_int32:
304                             unsigned = false;
305                         // no break on purpose
306                         case sci_uint32:
307                             container = new ScilabInteger(new int[height][width], unsigned);
308                             break;
309                         case sci_int64:
310                             unsigned = false;
311                         // no break on purpose
312                         case sci_uint64:
313                             container = new ScilabInteger(new long[height][width], unsigned);
314                             break;
315                         default:
316                             container = new ScilabInteger(new long[height][width], false);
317                             break;
318                     }
319                 } else {
320                     container = new ScilabInteger(new long[height][width], false);
321                 }
322                 break;
323             case ScilabString:
324                 container = new ScilabString(new String[height][width]);
325                 break;
326             default: // case Array
327                 if ("ScilabMList".equals(scilabClass)) {
328                     container = new ScilabMList();
329                 } else if ("ScilabTList".equals(scilabClass)) {
330                     container = new ScilabTList();
331                 } else if ("ScilabList".equals(scilabClass)) {
332                     container = new ScilabList();
333                 } else {
334                     container = new ArrayList<>();
335                 }
336                 break;
337         }
338         return container;
339     }
340
341     public void endElement(HandledElement found) {
342         switch (found) {
343             case Array:
344             // no break on purpose
345             case ScilabBoolean:
346             // no break on purpose
347             case ScilabDouble:
348             // no break on purpose
349             case ScilabInteger:
350             // no break on purpose
351             case ScilabString: {
352                 // defensive programming
353                 if (!(saxHandler.parents.peek() instanceof RawDataDescriptor)) {
354                     return;
355                 }
356                 RawDataDescriptor fieldValue = (RawDataDescriptor) saxHandler.parents.peek();
357                 Object parent = saxHandler.parents.peek(1);
358
359                 switch (fieldValue.as) {
360                     case CONTROL_POINTS: {
361                         // defensive programming
362                         if (!(parent instanceof mxGeometry)) {
363                             return;
364                         }
365                         mxGeometry geom = (mxGeometry) parent;
366
367                         @SuppressWarnings("unchecked")
368                         ArrayList<mxPoint> value = (ArrayList<mxPoint>) fieldValue.value;
369                         geom.setPoints(value);
370                         break;
371                     }
372                     case DIAGRAM_CONTEXT: {
373                         // defensive programming
374                         if (!(parent instanceof ScicosObjectOwner)) {
375                             return;
376                         }
377                         ScicosObjectOwner diagram = (ScicosObjectOwner) parent;
378
379                         @SuppressWarnings("unchecked")
380                         ArrayList<String> value = (ArrayList<String>) fieldValue.value;
381                         VectorOfString ctx = new VectorOfString(value.size());
382                         for (int i = 0; i < value.size(); i++) {
383                             ctx.set(i, value.get(i));
384                         }
385                         saxHandler.controller.setObjectProperty(diagram.getUID(), diagram.getKind(), ObjectProperties.DIAGRAM_CONTEXT, ctx);
386                         break;
387                     }
388                     case DSTATE:
389                     case NZCROSS:
390                     case NMODE:
391                     case IPAR:
392                     case RPAR: {
393                         // defensive programming
394                         if (!(parent instanceof XcosCell)) {
395                             return;
396                         }
397                         XcosCell cell = (XcosCell) parent;
398                         if (!(fieldValue.value instanceof ScilabDouble)) {
399                             // FIXME decode the rpar as a subdiagram using the legacy decoders
400                             return;
401                         }
402                         ScilabDouble value = (ScilabDouble) fieldValue.value;
403
404                         VectorOfDouble vec = new VectorOfDouble(value.getHeight());
405                         for (int i = 0; i < value.getHeight(); i++) {
406                             vec.set(i, value.getRealElement(i, 0));
407                         }
408
409                         saxHandler.controller.setObjectProperty(cell.getUID(), cell.getKind(), ObjectProperties.RPAR, vec);
410                         break;
411                     }
412                     case EQUATIONS:
413                     case ODSTATE: {
414                         // defensive programming
415                         if (!(parent instanceof XcosCell)) {
416                             return;
417                         }
418                         XcosCell cell = (XcosCell) parent;
419                         ScilabList value = (ScilabList) fieldValue.value;
420
421                         if (value.size() > 0) {
422                             System.err.println("RawDataHandler value not decoded: " + fieldValue.as);
423                         }
424                         break;
425                     }
426                     default:
427                         System.err.println("RawDataHandler not handled: " + fieldValue.as);
428                         break;
429                 }
430                 break;
431             }
432             case add:
433                 break;
434             case data:
435                 break;
436             default:
437                 throw new IllegalArgumentException();
438         }
439     }
440
441     /*
442      * Convert the decoded data to a var2vec encoded value
443      */
444
445     private static void addMatrixHeader(VectorOfDouble vec, ScilabType var) {
446         vec.add(var.getType().swigValue());
447         vec.add(2); // we do not manage hypermatrices yet
448         vec.add(var.getHeight());
449         vec.add(var.getWidth());
450     }
451
452     public static VectorOfDouble var2vec(VectorOfDouble vec, ScilabBoolean var) {
453         addMatrixHeader(vec, var);
454
455
456         return vec;
457     }
458
459     public static VectorOfDouble var2vec(VectorOfDouble vec, ScilabDouble var) {
460         addMatrixHeader(vec, var);
461
462         // FIXME encode the values
463
464         return vec;
465     }
466
467     public static VectorOfDouble var2vec(VectorOfDouble vec, ScilabInteger var) {
468         addMatrixHeader(vec, var);
469
470         // FIXME encode the values
471
472         return vec;
473     }
474
475     public static VectorOfDouble var2vec(VectorOfDouble vec, ScilabString var) {
476         addMatrixHeader(vec, var);
477
478         // FIXME encode the values
479
480         return vec;
481     }
482
483     public static VectorOfDouble var2vec(VectorOfDouble vec, ScilabList var) {
484
485
486         // FIXME encode the values
487
488         return vec;
489     }
490
491     public static VectorOfDouble var2vec(VectorOfDouble vec, ScilabTList var) {
492
493
494         // FIXME encode the values
495
496         return vec;
497     }
498
499     public static VectorOfDouble var2vec(VectorOfDouble vec, ScilabMList var) {
500
501
502         // FIXME encode the values
503
504         return vec;
505     }
506 }