Merge branch 'development' of
[Mograsim.git] / net.mograsim.logic.model.am2900 / src / net / mograsim / logic / model / examples / ReserializeJSONs.java
1 package net.mograsim.logic.model.examples;
2
3 import java.io.IOException;
4 import java.nio.file.Files;
5 import java.nio.file.Path;
6 import java.nio.file.Paths;
7 import java.util.Comparator;
8 import java.util.HashMap;
9 import java.util.Map;
10 import java.util.Map.Entry;
11 import java.util.Optional;
12 import java.util.Scanner;
13 import java.util.Set;
14 import java.util.function.Function;
15 import java.util.stream.Collectors;
16 import java.util.stream.Stream;
17
18 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
19 import net.mograsim.logic.model.am2900.Am2900Loader;
20 import net.mograsim.logic.model.model.LogicModelModifiable;
21 import net.mograsim.logic.model.model.components.ModelComponent;
22 import net.mograsim.logic.model.model.components.submodels.SubmodelComponent;
23 import net.mograsim.logic.model.model.components.submodels.SubmodelInterface;
24 import net.mograsim.logic.model.model.wires.ModelWire;
25 import net.mograsim.logic.model.model.wires.ModelWireCrossPoint;
26 import net.mograsim.logic.model.model.wires.MovablePin;
27 import net.mograsim.logic.model.model.wires.Pin;
28 import net.mograsim.logic.model.model.wires.PinUsage;
29 import net.mograsim.logic.model.serializing.DeserializedSubmodelComponent;
30 import net.mograsim.logic.model.serializing.IdentifyParams;
31 import net.mograsim.logic.model.serializing.IndirectModelComponentCreator;
32 import net.mograsim.logic.model.serializing.SubmodelComponentSerializer;
33 import net.mograsim.logic.model.snippets.highlevelstatehandlers.DefaultHighLevelStateHandler;
34
35 public class ReserializeJSONs
36 {
37         public static double GRIDSIZE = 2.5;
38         public static boolean changePinUsages = false;
39         public static boolean changeComponentNames = false;
40         public static boolean snapWCPs = true;
41         public static boolean warnNonSnappedPoints = true;
42
43         public static void main(String[] args) throws IOException
44         {
45                 Am2900Loader.setup();
46                 try (Scanner sysin = new Scanner(System.in))
47                 {
48                         System.out.print("Directory to search for JSONs in / JSON file to reserialize >");
49                         Path root = Paths.get(sysin.nextLine());
50                         if (!Files.exists(root))
51                                 throw new IllegalArgumentException("Path doesn't exist");
52                         if (Files.isRegularFile(root))
53                                 reserializeJSON(root, sysin);
54                         else
55                         {
56                                 System.out.print("Recursive? >");
57                                 boolean recursive = Boolean.valueOf(sysin.nextLine());
58                                 try (Stream<Path> jsons = recursive ? Files.walk(root) : Files.list(root))
59                                 {
60                                         jsons.filter(Files::isRegularFile).filter(p -> p.getFileName().toString().endsWith(".json"))
61                                                         .forEach(j -> reserializeJSON(j, sysin));
62                                 }
63                         }
64                 }
65         }
66
67         public static void reserializeJSON(Path componentPath, Scanner sysin)
68         {
69                 try
70                 {
71                         DeserializedSubmodelComponent comp = (DeserializedSubmodelComponent) IndirectModelComponentCreator
72                                         .createComponent(new LogicModelModifiable(), "jsonfile:" + componentPath.toString());
73                         System.out.println("Reserializing " + componentPath);
74                         if (changePinUsages)
75                                 comp.getSupermodelPins().entrySet().stream().sorted(Comparator.comparing(Entry::getKey)).map(Entry::getValue).forEach(pin ->
76                                 {
77                                         PinUsage usage = null;
78                                         while (usage == null)
79                                                 try
80                                                 {
81                                                         System.out.print("  Usage for interface pin " + pin.name + " (empty: " + pin.usage + ") >");
82                                                         String usageStr = sysin.nextLine().toUpperCase();
83                                                         usage = usageStr.equals("") ? pin.usage
84                                                                         : usageStr.equals("I") ? PinUsage.INPUT
85                                                                                         : usageStr.equals("O") ? PinUsage.OUTPUT
86                                                                                                         : usageStr.equals("T") ? PinUsage.TRISTATE : PinUsage.valueOf(usageStr);
87                                                 }
88                                                 catch (@SuppressWarnings("unused") IllegalArgumentException e)
89                                                 {
90                                                         System.err.println("  Illegal usage");
91                                                 }
92                                         setInterfacePinUsage(comp, pin, usage);
93                                 });
94                         LogicModelModifiable submodelModifiable = comp.getSubmodelModifiable();
95                         Map<String, String> componentNameRemapping = new HashMap<>();
96                         if (changeComponentNames)
97                         {
98                                 componentNameRemapping.put(SubmodelComponent.SUBMODEL_INTERFACE_NAME, SubmodelComponent.SUBMODEL_INTERFACE_NAME);
99                                 LogicModelModifiable tempModel = new LogicModelModifiable();
100                                 IdentifyParams iP = new IdentifyParams();
101                                 submodelModifiable.getComponentsByName().entrySet().stream()
102                                                 .filter(e -> !e.getKey().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME))
103                                                 .sorted(Comparator.comparing(Entry::getKey, ReserializeJSONs::compareStringsWithIntegers)).forEach(e ->
104                                                 {
105                                                         String oldName = e.getKey();
106                                                         ModelComponent subcomp = e.getValue();
107                                                         String defaultName = tempModel.getDefaultComponentName(subcomp);
108                                                         String newName = null;
109                                                         while (newName == null)
110                                                         {
111                                                                 System.out.print("  New name for component " + oldName + " of type " + subcomp.getIDForSerializing(iP)
112                                                                                 + " (empty: " + defaultName + ") >");
113                                                                 newName = sysin.nextLine();
114                                                                 if (newName.equals(""))
115                                                                         newName = defaultName;
116                                                                 if (tempModel.getComponentsByName().containsKey(newName))
117                                                                 {
118                                                                         System.err.println("  There already is a component with that name");
119                                                                         newName = null;
120                                                                 }
121                                                         }
122                                                         componentNameRemapping.put(oldName, newName);
123                                                         IndirectModelComponentCreator.createComponent(tempModel, subcomp.getIDForSerializing(iP),
124                                                                         subcomp.getParamsForSerializingJSON(iP), newName).moveTo(subcomp.getPosX(), subcomp.getPosY());
125                                                 });
126                                 SubmodelInterface tempSubmodelInterface = new SubmodelInterface(tempModel);
127                                 for (Pin p : submodelModifiable.getComponentsByName().get(SubmodelComponent.SUBMODEL_INTERFACE_NAME).getPins().values())
128                                         tempSubmodelInterface
129                                                         .addPin(new Pin(tempModel, tempSubmodelInterface, p.name, p.logicWidth, p.usage, p.getRelX(), p.getRelY()));
130                                 for (ModelWire w : submodelModifiable.getWiresByName().values())
131                                         createWire(componentNameRemapping::get, tempModel, w);
132
133                                 Optional<ModelComponent> o;
134                                 while ((o = submodelModifiable.getComponentsByName().values().stream()
135                                                 .filter(c -> !c.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME)).findAny()).isPresent())
136                                         submodelModifiable.destroyComponent(o.get());
137
138                                 tempModel.getComponentsByName().values().stream()
139                                                 .filter(c -> !c.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME))
140                                                 .forEach(c -> IndirectModelComponentCreator.createComponent(submodelModifiable, c.getIDForSerializing(iP),
141                                                                 c.getParamsForSerializingJSON(iP), c.getName()).moveTo(c.getPosX(), c.getPosY()));
142                                 for (ModelWire w : tempModel.getWiresByName().values())
143                                         createWire(Function.identity(), submodelModifiable, w);
144                         }
145                         if (snapWCPs)
146                                 submodelModifiable.getComponentsByName().values().stream().filter(c -> c instanceof ModelWireCrossPoint).forEach(c ->
147                                 {
148                                         double x = c.getPosX();
149                                         double y = c.getPosY();
150                                         c.moveTo(x % GRIDSIZE == 0 ? x - 1 : x, y % GRIDSIZE == 0 ? y - 1 : y);
151                                 });
152                         if (warnNonSnappedPoints)
153                         {
154                                 if (comp.getWidth() % GRIDSIZE != 0 || comp.getHeight() % GRIDSIZE != 0)
155                                         System.out.println("  Size is not snapped to grid: " + comp.getWidth() + "," + comp.getHeight());
156                                 submodelModifiable.getComponentsByName().values().forEach(c ->
157                                 {
158                                         double x = c.getPosX();
159                                         double y = c.getPosY();
160                                         if (c instanceof ModelWireCrossPoint)
161                                         {
162                                                 x++;
163                                                 y++;
164                                         }
165                                         if (x % GRIDSIZE != 0 || y % GRIDSIZE != 0)
166                                                 System.out.println("  Component " + c.getName() + " (type " + c.getIDForSerializing(new IdentifyParams())
167                                                                 + ") is not snapped to grid: " + x + "," + y);
168                                 });
169                                 submodelModifiable.getWiresByName().values().stream().forEach(w ->
170                                 {
171                                         Point[] p = w.getPath();
172                                         if (p != null)
173                                                 for (int i = 0; i < p.length; i++)
174                                                         if (p[i].x % GRIDSIZE != 0 || p[i].y % GRIDSIZE != 0)
175                                                                 System.out.println(
176                                                                                 "  Wire " + w.name + " path point #" + i + " is not snapped to grid: " + p[i].x + "," + p[i].y);
177                                 });
178                                 comp.getPins().values().forEach(p ->
179                                 {
180                                         if (p.getRelX() % GRIDSIZE != 0 || p.getRelY() % GRIDSIZE != 0)
181                                                 System.out.println("  Interface point " + p.name + " is not snapped to grid: " + p.getRelX() + "," + p.getRelY());
182                                 });
183                         }
184                         SubmodelComponentSerializer.serialize(comp, componentPath.toString());
185                         if (changeComponentNames && (comp.getHighLevelStateHandler() == null
186                                         || !(comp.getHighLevelStateHandler() instanceof DefaultHighLevelStateHandler)))
187                         {
188                                 System.out.println("  A non-default HighLevelStateHandler was detected. Check for changes there manually.");
189                                 System.out.print("  Empty line to continue to next component, old component name to get new component name >");
190                                 for (String line = sysin.nextLine(); !line.equals(""); line = sysin.nextLine())
191                                         System.out.println("  " + line + "->" + componentNameRemapping.get(line) + " >");
192                         }
193                 }
194                 catch (Exception e)
195                 {
196                         System.err.println("An error occurred visiting " + componentPath + ":");
197                         e.printStackTrace();
198                 }
199         }
200
201         private static ModelWire createWire(Function<String, String> componentNameRemapping, LogicModelModifiable tempModelForDefaultNames,
202                         ModelWire w)
203         {
204                 return new ModelWire(tempModelForDefaultNames, w.name,
205                                 getRemappedPin(componentNameRemapping, tempModelForDefaultNames, w.getPin1()),
206                                 getRemappedPin(componentNameRemapping, tempModelForDefaultNames, w.getPin2()), w.getPath());
207         }
208
209         private static Pin getRemappedPin(Function<String, String> componentNameRemapping, LogicModelModifiable tempModelForDefaultNames,
210                         Pin pin)
211         {
212                 return tempModelForDefaultNames.getComponentsByName().get(componentNameRemapping.apply(pin.component.getName())).getPin(pin.name);
213         }
214
215         private static int compareStringsWithIntegers(String a, String b)
216         {
217                 int aLoc = 0;
218                 int bLoc = 0;
219                 for (;;)
220                 {
221                         if (aLoc == a.length())
222                         {
223                                 if (bLoc == b.length())
224                                         return 0;
225                                 return -1;
226                         }
227                         if (bLoc == b.length())
228                                 return 1;
229                         int aInt = 0;
230                         int aIntLen = 0;
231                         char nextCharA;
232                         for (;;)
233                         {
234                                 nextCharA = a.charAt(aLoc++);
235                                 if (nextCharA < '0' || nextCharA > '9')
236                                         break;
237                                 aIntLen++;
238                                 aInt = aInt * 10 + nextCharA - '0';
239                                 if (aLoc == a.length())
240                                         break;
241                         }
242                         int bInt = 0;
243                         int bIntLen = 0;
244                         char nextCharB;
245                         for (;;)
246                         {
247                                 nextCharB = b.charAt(bLoc++);
248                                 if (nextCharB < '0' || nextCharB > '9')
249                                         break;
250                                 bIntLen++;
251                                 bInt = bInt * 10 + nextCharB - '0';
252                                 if (bLoc == b.length())
253                                         break;
254                         }
255                         if (aIntLen != 0)
256                         {
257                                 if (bIntLen == 0)
258                                         return -1;
259                                 int comp = Integer.compare(aInt, bInt);
260                                 if (comp != 0)
261                                         return comp;
262                         } else
263                         {
264                                 if (bIntLen != 0)
265                                         return 1;
266                                 int comp = Character.compare(nextCharA, nextCharB);
267                                 if (comp != 0)
268                                         return comp;
269                         }
270                 }
271         }
272
273         private static void setInterfacePinUsage(DeserializedSubmodelComponent comp, Pin interfacePin, PinUsage usage)
274         {
275                 Set<ModelWire> wiresConnectedToPin = comp.submodel.getWiresByName().values().stream()
276                                 .filter(w -> w.getPin1() == interfacePin || w.getPin2() == interfacePin).collect(Collectors.toSet());
277                 LogicModelModifiable submodelModifiable = comp.getSubmodelModifiable();
278                 wiresConnectedToPin.forEach(submodelModifiable::destroyWire);
279                 comp.removeSubmodelInterface(interfacePin.name);
280                 comp.addSubmodelInterface(new MovablePin(submodelModifiable, comp, interfacePin.name, interfacePin.logicWidth, usage,
281                                 interfacePin.getRelX(), interfacePin.getRelY()));
282                 wiresConnectedToPin.forEach(w -> new ModelWire(submodelModifiable, w.getPin1(), w.getPin2()));
283         }
284 }