* Bug #15072 fixed: The context was stored as a root diagram attribute instead of...
[scilab.git] / scilab / modules / xcos / src / java / org / scilab / modules / xcos / io / writer / CustomWriter.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2015-2015 - Scilab Enterprises - Clement DAVID
4  * Copyright (C) 2017 - ESI Group - Clement DAVID
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16 package org.scilab.modules.xcos.io.writer;
17
18 import java.rmi.server.UID;
19
20 import javax.xml.stream.XMLStreamException;
21
22 import org.scilab.modules.xcos.Kind;
23 import org.scilab.modules.xcos.ObjectProperties;
24 import org.scilab.modules.xcos.VectorOfDouble;
25 import org.scilab.modules.xcos.VectorOfInt;
26 import org.scilab.modules.xcos.VectorOfScicosID;
27 import org.scilab.modules.xcos.Xcos;
28 import org.scilab.modules.xcos.graph.ScicosParameters;
29 import org.scilab.modules.xcos.io.HandledElement;
30
31 public class CustomWriter extends ScilabWriter {
32     private static final String SEP = " - ";
33
34     public CustomWriter(XcosWriter writer) {
35         super(writer);
36     }
37
38     @Override
39     public void write(long uid, Kind kind) throws XMLStreamException {
40         String[] str = new String[1];
41         int[] integer = new int[1];
42         VectorOfDouble vDouble = new VectorOfDouble();
43         VectorOfScicosID children = new VectorOfScicosID();
44
45         switch (kind) {
46             case DIAGRAM:
47                 shared.stream.writeStartDocument();
48                 shared.stream.writeStartElement(HandledElement.XcosDiagram.name());
49
50                 /*
51                  * Write diagram content
52                  */
53                 shared.controller.getObjectProperty(uid, kind, ObjectProperties.DEBUG_LEVEL, integer);
54                 shared.stream.writeAttribute("debugLevel", Integer.toString(integer[0]));
55
56                 // write simulation properties
57                 shared.controller.getObjectProperty(uid, kind, ObjectProperties.PROPERTIES, vDouble);
58                 String prop;
59
60                 prop = Double.toString(vDouble.get(ScicosParameters.FINAL_INTEGRATION_TIME));
61                 shared.stream.writeAttribute("finalIntegrationTime", prop);
62                 prop = Double.toString(vDouble.get(ScicosParameters.INTEGRATOR_ABSOLUTE_TOLERANCE));
63                 shared.stream.writeAttribute("integratorAbsoluteTolerance", prop);
64                 prop = Double.toString(vDouble.get(ScicosParameters.INTEGRATOR_RELATIVE_TOLERANCE));
65                 shared.stream.writeAttribute("integratorRelativeTolerance", prop);
66                 prop = Double.toString(vDouble.get(ScicosParameters.TOLERANCE_ON_TIME));
67                 shared.stream.writeAttribute("toleranceOnTime", prop);
68                 prop = Double.toString(vDouble.get(ScicosParameters.MAX_INTEGRATION_TIME_INTERVAL));
69                 shared.stream.writeAttribute("maxIntegrationTimeInterval", prop);
70                 prop = Double.toString(vDouble.get(ScicosParameters.MAXIMUM_STEP_SIZE));
71                 shared.stream.writeAttribute("maximumStepSize", prop);
72                 prop = Double.toString(vDouble.get(ScicosParameters.REAL_TIME_SCALING));
73                 shared.stream.writeAttribute("realTimeScaling", prop);
74                 prop = Double.toString(vDouble.get(ScicosParameters.SOLVER));
75                 shared.stream.writeAttribute("solver", prop);
76
77                 // write the graphical part and children
78                 shared.controller.getObjectProperty(uid, kind, ObjectProperties.CHILDREN, children);
79                 String zeroUID = new UID((short) 0).toString();
80                 shared.uniqueUIDs.add(zeroUID);
81                 writeDiagramAndSuperDiagramContent(uid, kind, children, zeroUID);
82
83                 shared.stream.writeEndElement();
84                 shared.stream.writeEndDocument();
85
86                 // post processing for binary data handling
87                 shared.rawDataWriter.fillSharedDictionary();
88                 break;
89             case BLOCK:
90                 shared.controller.getObjectProperty(uid, kind, ObjectProperties.CHILDREN, children);
91                 if (children.size() > 0) {
92                     shared.stream.writeStartElement(HandledElement.SuperBlockDiagram.name());
93                     shared.stream.writeAttribute("as", "child");
94                     writeDiagramAndSuperDiagramContent(uid, kind, children, shared.layers.peek());
95                     shared.stream.writeEndElement(); // SuperBlockDiagram
96                 }
97                 break;
98             case PORT:
99                 // the orientation is not encoded on the model but propagated inside the style
100                 break;
101             default:
102                 break;
103         }
104     }
105
106     private void writeDiagramAndSuperDiagramContent(long uid, Kind kind, VectorOfScicosID children, String parentUID) throws XMLStreamException {
107         VectorOfInt colors = new VectorOfInt();
108         shared.controller.getObjectProperty(uid, kind, ObjectProperties.COLOR, colors);
109         shared.stream.writeAttribute("background", Integer.toString(colors.get(0)));
110         shared.stream.writeAttribute("gridEnabled", Integer.toString(colors.get(1)));
111
112         String[] str = new String[1];
113         shared.controller.getObjectProperty(uid, kind, ObjectProperties.TITLE, str);
114         shared.stream.writeAttribute("title", str[0]);
115
116         /*
117          * Add a version comment at the top layer
118          */
119         if (kind == Kind.DIAGRAM) {
120             final Package p = Package.getPackage("org.scilab.modules.xcos");
121             String comment = new StringBuilder().append(Xcos.TRADENAME).append(SEP).append(Xcos.VERSION).append(SEP)
122             .append(p.getSpecificationVersion()).append(SEP).append(p.getImplementationVersion()).toString();
123             shared.stream.writeComment(comment);
124         }
125
126         /*
127          * encode some content then the children
128          */
129         shared.rawDataWriter.writeContext(uid, kind);
130
131         /*
132          * Generate uniques but predictables UIDs
133          */
134         String[] parent = parentUID.split(":");
135         long uidCounter = 1;
136         String rootUID = parent[0] + ":" + Long.toString(Long.parseLong(parent[1], 16) + uidCounter, 16) + ":" + parent[2];
137         for (; shared.uniqueUIDs.contains(rootUID); uidCounter++) {
138             rootUID = parent[0] + ":" + Long.toString(Long.parseLong(parent[1], 16) + uidCounter, 16) + ":" + parent[2];
139         }
140         shared.uniqueUIDs.add(rootUID);
141         String layerUID = parent[0] + ":" + Long.toString(Long.parseLong(parent[1], 16) + uidCounter, 16) + ":" + parent[2];
142         for (; shared.uniqueUIDs.contains(layerUID); uidCounter++) {
143             layerUID = parent[0] + ":" + Long.toString(Long.parseLong(parent[1], 16) + uidCounter, 16) + ":" + parent[2];
144         }
145         shared.uniqueUIDs.add(layerUID);
146         shared.layers.push(layerUID);
147
148         // children header
149         shared.stream.writeStartElement("mxGraphModel");
150         shared.stream.writeAttribute("as", "model");
151         shared.stream.writeStartElement("root");
152         shared.stream.writeEmptyElement("mxCell");
153         shared.stream.writeAttribute("id", rootUID);
154         shared.stream.writeEmptyElement("mxCell");
155         shared.stream.writeAttribute("id", layerUID);
156         shared.stream.writeAttribute("parent", rootUID);
157
158         // loop on all children, encode the blocks and ports then the links
159         VectorOfInt kinds = new VectorOfInt();
160         shared.controller.sortAndFillKind(children, kinds);
161
162         final int len = children.size();
163         for (int i = 0; i < len; i++) {
164             long child = children.get(i);
165             Kind childKind = Kind.values()[kinds.get(i)];
166             shared.write(child, childKind);
167         }
168
169         shared.layers.pop();
170         shared.stream.writeEndElement(); // root
171         shared.stream.writeEndElement(); // mxGraphModel
172         shared.stream.writeEmptyElement("mxCell");
173         shared.stream.writeAttribute("as", "defaultParent");
174         shared.stream.writeAttribute("id", layerUID);
175         shared.stream.writeAttribute("parent", rootUID);
176     }
177 }