Restructured JSON (de)serializing: ViewModels can be (de)serialized too
[Mograsim.git] / net.mograsim.logic.model / src / net / mograsim / logic / model / serializing / SubmodelComponentSerializer.java
1 package net.mograsim.logic.model.serializing;
2
3 import java.io.IOException;
4
5 import com.google.gson.JsonElement;
6
7 import net.mograsim.logic.model.model.ViewModelModifiable;
8 import net.mograsim.logic.model.model.components.submodels.SubmodelComponent;
9 import net.mograsim.logic.model.model.wires.MovablePin;
10 import net.mograsim.logic.model.model.wires.Pin;
11 import net.mograsim.logic.model.serializing.SubmodelComponentParams.InterfacePinParams;
12 import net.mograsim.logic.model.snippets.HighLevelStateHandler;
13 import net.mograsim.logic.model.snippets.Renderer;
14 import net.mograsim.logic.model.snippets.SubmodelComponentSnippetSuppliers;
15 import net.mograsim.logic.model.util.JsonHandler;
16 import net.mograsim.logic.model.util.Version;
17
18 /**
19  * Creates {@link SubmodelComponent}s from {@link SubmodelComponentParams}
20  * 
21  * @author Fabian Stemmler
22  * @author Daniel Kirschten
23  */
24 public final class SubmodelComponentSerializer
25 {
26         public static final Version CURRENT_JSON_VERSION = Version.parseSemver("0.1.4");
27         // convenience methods
28
29         /**
30          * Like {@link #deserialize(ViewModelModifiable, SubmodelComponentParams)}, but first reading the {@link SubmodelComponentParams} from
31          * the given file path.
32          * 
33          * @author Daniel Kirschten
34          */
35         public static SubmodelComponent deserialize(ViewModelModifiable model, String sourcePath) throws IOException
36         {
37                 return deserialize(model, JsonHandler.readJson(sourcePath, SubmodelComponentParams.class));
38         }
39
40         /**
41          * Like {@link #deserialize(ViewModelModifiable, SubmodelComponentParams, String, JsonElement)}, but first reading the
42          * {@link SubmodelComponentParams} from the given file path.
43          * 
44          * @author Daniel Kirschten
45          */
46         public static SubmodelComponent deserialize(ViewModelModifiable model, String sourcePath, String idForSerializingOverride,
47                         JsonElement paramsForSerializingOverride) throws IOException
48         {
49                 return deserialize(model, JsonHandler.readJson(sourcePath, SubmodelComponentParams.class), idForSerializingOverride,
50                                 paramsForSerializingOverride);
51         }
52
53         /**
54          * Like {@link #deserialize(ViewModelModifiable, SubmodelComponentParams, String)}, but first reading the
55          * {@link SubmodelComponentParams} from the given file path.
56          * 
57          * @author Daniel Kirschten
58          */
59         public static SubmodelComponent deserialize(ViewModelModifiable model, String sourcePath, String name) throws IOException
60         {
61                 return deserialize(model, JsonHandler.readJson(sourcePath, SubmodelComponentParams.class), name);
62         }
63
64         /**
65          * Like {@link #deserialize(ViewModelModifiable, SubmodelComponentParams, String, String, JsonElement)}, but first reading the
66          * {@link SubmodelComponentParams} from the given file path.
67          * 
68          * @author Daniel Kirschten
69          */
70         public static SubmodelComponent deserialize(ViewModelModifiable model, String sourcePath, String name, String idForSerializingOverride,
71                         JsonElement paramsForSerializingOverride) throws IOException
72         {
73                 return deserialize(model, JsonHandler.readJson(sourcePath, SubmodelComponentParams.class), name, idForSerializingOverride,
74                                 paramsForSerializingOverride);
75         }
76
77         /**
78          * {@link #deserialize(ViewModelModifiable, SubmodelComponentParams, String, String, JsonElement)} with no
79          * <code>idForSerializingOverride</code> set and using the default name.
80          * 
81          * @author Daniel Kirschten
82          */
83         public static SubmodelComponent deserialize(ViewModelModifiable model, SubmodelComponentParams params)
84         {
85                 return deserialize(model, params, null, null, null);
86         }
87
88         /**
89          * {@link #deserialize(ViewModelModifiable, SubmodelComponentParams, String, String, JsonElement)} using the default name.
90          * 
91          * @author Daniel Kirschten
92          */
93         public static SubmodelComponent deserialize(ViewModelModifiable model, SubmodelComponentParams params, String idForSerializingOverride,
94                         JsonElement paramsForSerializingOverride)
95         {
96                 return deserialize(model, params, null, idForSerializingOverride, paramsForSerializingOverride);
97         }
98
99         /**
100          * {@link #deserialize(ViewModelModifiable, SubmodelComponentParams, String, String, JsonElement)} with no
101          * <code>idForSerializingOverride</code> set.
102          * 
103          * @author Daniel Kirschten
104          */
105         public static SubmodelComponent deserialize(ViewModelModifiable model, SubmodelComponentParams params, String name)
106         {
107                 return deserialize(model, params, name, null, null);
108         }
109
110         /**
111          * Like {@link #serialize(SubmodelComponent)}, but instead of returning the generated {@link SubmodelComponentParams} they are written
112          * to a file at the given path.
113          * 
114          * @author Daniel Kirschten
115          */
116         public static void serialize(SubmodelComponent comp, String targetPath) throws IOException
117         {
118                 JsonHandler.writeJson(serialize(comp), targetPath);
119         }
120
121         /**
122          * Like {@link #serialize(SubmodelComponent, IdentifierGetter)}, but instead of returning the generated {@link SubmodelComponentParams}
123          * they are written to a file at the given path.
124          * 
125          * @author Daniel Kirschten
126          */
127         public static void serialize(SubmodelComponent comp, IdentifierGetter idGetter, String targetPath) throws IOException
128         {
129                 JsonHandler.writeJson(serialize(comp, idGetter), targetPath);
130         }
131
132         /**
133          * {@link #serialize(SubmodelComponent, IdentifierGetter)} using a default {@link IdentifierGetter} (see <code>IdentifierGetter</code>'s
134          * {@link IdentifierGetter#IdentifierGetter() default constructor})
135          * 
136          * @author Daniel Kirschten
137          */
138         public static SubmodelComponentParams serialize(SubmodelComponent comp)
139         {
140                 return serialize(comp, new IdentifierGetter());
141         }
142
143         // "core" methods
144         /**
145          * Creates a {@link SubmodelComponent} from the specified {@link SubmodelComponentParams} with the given name.
146          * <p>
147          * When serializing a <code>SubmodelComponent</code>, it is undesired for every subcomponent to be serialized with its complete inner
148          * structure. Instead, these sub-<code>SubmodelComponent</code>s should be serialized with the ID and params which were used to
149          * determine the <code>SubmodelComponentParams</code> defining the sub-<code>SubmodelComponent</code>. Because of this, it is possible
150          * to override the ID and params used in {@link #serialize(SubmodelComponent, IdentifierGetter) serialize(...)} to describe this
151          * subcomponent. See there for details.
152          * 
153          * @author Fabian Stemmler
154          * @author Daniel Kirschten
155          */
156         @SuppressWarnings("unused") // for GUIWire being created
157         public static SubmodelComponent deserialize(ViewModelModifiable model, SubmodelComponentParams params, String name,
158                         String idForSerializingOverride, JsonElement paramsForSerializingOverride)
159         {
160                 DeserializedSubmodelComponent comp = new DeserializedSubmodelComponent(model, name, idForSerializingOverride,
161                                 paramsForSerializingOverride);
162                 comp.setSubmodelScale(params.innerScale);
163                 comp.setSize(params.width, params.height);
164                 for (InterfacePinParams iPinParams : params.interfacePins)
165                         comp.addSubmodelInterface(
166                                         new MovablePin(comp, iPinParams.name, iPinParams.logicWidth, iPinParams.location.x, iPinParams.location.y));
167                 ViewModelModifiable submodelModifiable = comp.getSubmodelModifiable();
168                 ViewModelSerializer.deserialize(comp.getSubmodelModifiable(), params.submodel);
169                 comp.setSymbolRenderer(SubmodelComponentSnippetSuppliers.symbolRendererSupplier.getSnippetSupplier(params.symbolRendererSnippetID)
170                                 .create(comp, params.symbolRendererParams));
171                 comp.setOutlineRenderer(SubmodelComponentSnippetSuppliers.outlineRendererSupplier
172                                 .getSnippetSupplier(params.outlineRendererSnippetID).create(comp, params.outlineRendererParams));
173                 comp.setHighLevelStateHandler(SubmodelComponentSnippetSuppliers.highLevelStateHandlerSupplier
174                                 .getSnippetSupplier(params.highLevelStateHandlerSnippetID).create(comp, params.highLevelStateHandlerParams));
175                 return comp;
176         }
177
178         /**
179          * Returns {@link SubmodelComponentParams}, which describe this {@link SubmodelComponent}. <br>
180          * See {@link ViewModelSerializer#serialize(net.mograsim.logic.model.model.ViewModel, IdentifierGetter)
181          * ViewModelSerializer.serialize(...)} for how subcomponents are serialized.<br>
182          * CodeSnippets are serialized using the ID defined by <code>idGetter</code> and the params obtained by the respective
183          * <coce>getParamsForSerializing</code> methods ({@link Renderer#getParamsForSerializing()}).
184          * 
185          * @author Fabian Stemmler
186          * @author Daniel Kirschten
187          */
188         public static SubmodelComponentParams serialize(SubmodelComponent comp, IdentifierGetter idGetter)
189         {
190                 SubmodelComponentParams params = new SubmodelComponentParams(CURRENT_JSON_VERSION);
191                 params.innerScale = comp.getSubmodelScale();
192                 params.submodel = ViewModelSerializer.serialize(comp.submodel, idGetter);
193
194                 params.width = comp.getWidth();
195                 params.height = comp.getHeight();
196
197                 InterfacePinParams[] iPins = new InterfacePinParams[comp.getPins().size()];
198                 int i = 0;
199                 for (Pin p : comp.getPins().values())
200                 {
201                         InterfacePinParams iPinParams = new InterfacePinParams();
202                         iPins[i] = iPinParams;
203                         iPinParams.location = p.getRelPos();
204                         iPinParams.name = p.name;
205                         iPinParams.logicWidth = p.logicWidth;
206                         i++;
207                 }
208                 params.interfacePins = iPins;
209
210                 Renderer symbolRenderer = comp.getSymbolRenderer();
211                 if (symbolRenderer != null)
212                 {
213                         params.symbolRendererSnippetID = idGetter.symbolRendererIDs.apply(symbolRenderer);
214                         params.symbolRendererParams = symbolRenderer.getParamsForSerializingJSON(idGetter);
215                 }
216
217                 Renderer outlineRenderer = comp.getOutlineRenderer();
218                 if (outlineRenderer != null)
219                 {
220                         params.outlineRendererSnippetID = idGetter.outlineRendererIDs.apply(outlineRenderer);
221                         params.outlineRendererParams = outlineRenderer.getParamsForSerializingJSON(idGetter);
222                 }
223
224                 HighLevelStateHandler highLevelStateHandler = comp.getHighLevelStateHandler();
225                 if (highLevelStateHandler != null)
226                 {
227                         params.highLevelStateHandlerSnippetID = idGetter.highLevelStateHandlerIDs.apply(highLevelStateHandler);
228                         params.highLevelStateHandlerParams = highLevelStateHandler.getParamsForSerializingJSON(idGetter);
229                 }
230
231                 return params;
232         }
233 }