package ui.controller; import java.awt.Color; import java.awt.Point; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.LinkedList; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import TypeAdapter.AbstractCpsObjectAdapter; import TypeAdapter.ColorAdapter; import TypeAdapter.PositionAdapter; import classes.Category; import classes.CpsEdge; import classes.CpsUpperNode; import classes.AbstractCpsObject; import classes.HolonElement; import classes.HolonObject; import classes.HolonSwitch; import classes.IdCounter; import classes.Position; import sun.misc.Queue; import ui.model.Model; /** * Controller for Storage. * * @author Gruppe14 */ public class StoreController { public enum MODE { COMPLETE, PARTIAL } public enum TYPE { CATEGORY, CANVAS } public enum EDGETYPE { CANVAS, CONNECTION, NODE, OLD } public enum NUMTYPE { CATEGORY, OBJECT, ELEMENT, EDGE, CONNECTION, NODEEDGE, OLDEDGE, UNITGRAPH } public enum GRAPHTYPE { SWITCH, ELEMENT } private Model model; private Gson gson; private int nCat, nObj, nEle, nEdge, nConn, nNodeEdge, nOldEdge, nUnitGraph; /** * Constructor. * * @param model * the Model */ public StoreController(Model model) { this.model = model; initGson(); } /** * Writes the current State of the Modelling into a JSON File which can be * loaded. * * @param path * the Path * * @throws IOException * exception */ public void writeSaveFile(String path) throws IOException { initNumeration(); JsonObject file = new JsonObject(); initialize(MODE.COMPLETE, file); storeCategory(file); storeCanvas(file); FileWriter writer = new FileWriter(path); writer.write(gson.toJson(file)); writer.flush(); writer.close(); } /** * Writes the Autosave File. * * @param path * the Path * @throws IOException * Exception */ public void writeAutosaveFile(String path) throws IOException { initNumeration(); JsonObject file = new JsonObject(); initialize(MODE.PARTIAL, file); storeCanvas(file); FileWriter writer = new FileWriter(path); writer.write(gson.toJson(file)); writer.flush(); writer.close(); } /** * Write needed default parameter into the JsonObject. Can be extended later * on * * @param mode * @param file */ private void initialize(MODE mode, JsonObject file) { // TODO Auto-generated method stub switch (mode) { case COMPLETE: file.add("MODE", new JsonPrimitive(mode.name())); file.add("IDCOUNTER", new JsonPrimitive(IdCounter.getCounter())); file.add("CANVAS_SIZE_X", new JsonPrimitive(model.getCanvasX())); file.add("CANVAS_SIZE_Y", new JsonPrimitive(model.getCanvasY())); break; case PARTIAL: file.add("MODE", new JsonPrimitive(mode.name())); file.add("IDCOUNTER", new JsonPrimitive(IdCounter.getCounter())); break; default: break; } } /** * Store all Categories and Object into a Json File via Serialization * * @param file */ private void storeCategory(JsonObject file) { // TODO Auto-generated method stub for (Category cat : model.getCategories()) { String key = "CATEGORY" + getNumerator(NUMTYPE.CATEGORY); file.add(key, new JsonPrimitive(cat.getName())); for (AbstractCpsObject obj : cat.getObjects()) { file.add("CGOBJECT" + getNumerator(NUMTYPE.OBJECT), gson.toJsonTree(obj, AbstractCpsObject.class)); if (obj instanceof HolonObject) elementsToJson(TYPE.CATEGORY, gson, file, obj); } } } /** * Travers through all Objects via BFS and Stores everything relevant * * @param file */ private void storeCanvas(JsonObject file) { // TODO Auto-generated method stub Queue queue = new Queue<>(); AbstractCpsObject u = null; for (AbstractCpsObject cps : model.getObjectsOnCanvas()) { queue.enqueue(cps); } while (!queue.isEmpty()) { try { u = queue.dequeue(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } String key = "CVSOBJECT" + getNumerator(NUMTYPE.OBJECT); file.add(key, gson.toJsonTree(u, AbstractCpsObject.class)); edgeToJson(EDGETYPE.CONNECTION, file, u.getID(), u.getConnections()); if (u instanceof HolonObject) elementsToJson(TYPE.CANVAS, gson, file, u); if (u instanceof HolonSwitch) if (((HolonSwitch) u).getGraphPoints().size() != 0) unitgraphToJson(GRAPHTYPE.SWITCH, file, u.getID(), ((HolonSwitch) u).getGraphPoints()); if (u instanceof CpsUpperNode) { for (AbstractCpsObject adjacent : ((CpsUpperNode) u).getNodes()) { queue.enqueue(adjacent); } edgeToJson(EDGETYPE.NODE, file, u.getID(), ((CpsUpperNode) u).getNodeEdges()); edgeToJson(EDGETYPE.OLD, file, u.getID(), ((CpsUpperNode) u).getOldEdges()); } } edgeToJson(EDGETYPE.CANVAS, file, 0, model.getEdgesOnCanvas()); } /** * * @param type * @param gson * @param file * @param obj */ private void elementsToJson(TYPE type, Gson gson, JsonObject file, AbstractCpsObject obj) { // TODO Auto-generated method stub JsonObject temp = new JsonObject(); String key = null; for (HolonElement ele : ((HolonObject) obj).getElements()) { temp.add("properties", gson.toJsonTree(ele)); temp.add("ID", new JsonPrimitive(obj.getID())); switch (type) { case CANVAS: key = "CVSELEMENT" + getNumerator(NUMTYPE.ELEMENT); break; case CATEGORY: key = "CGELEMENT" + getNumerator(NUMTYPE.ELEMENT); break; default: break; } file.add(key, gson.toJsonTree(temp)); if (ele.getGraphPoints().size() != 0) unitgraphToJson(GRAPHTYPE.ELEMENT, file, ele.getId(), ele.getGraphPoints()); temp = new JsonObject(); } } /** * * @param ele */ private void unitgraphToJson(GRAPHTYPE type, JsonObject file, int id, LinkedList graph) { JsonObject temp = new JsonObject(); String key = null; for (int i = 0; i < graph.size(); i++) { temp.add("" + i, new JsonPrimitive(graph.get(i).x + ":" + graph.get(i).y)); } switch (type) { case SWITCH: key = "SWUNITGRAPH" + getNumerator(NUMTYPE.UNITGRAPH); break; case ELEMENT: key = "ELEUNITGRAPH" + getNumerator(NUMTYPE.UNITGRAPH); break; default: break; } temp.add("ID", new JsonPrimitive(id)); file.add(key, gson.toJsonTree(temp)); } /** * * @param type * @param file * @param id * @param arr */ private void edgeToJson(EDGETYPE type, JsonObject file, int id, ArrayList arr) { // TODO Auto-generated method stub String k = null; JsonObject temp = new JsonObject(); for (CpsEdge edge : arr) { temp.add("properties", gson.toJsonTree(edge)); temp.add("A", new JsonPrimitive(edge.getA().getID())); temp.add("B", new JsonPrimitive(edge.getB().getID())); switch (type) { case CANVAS: k = "CVSEDGE" + getNumerator(NUMTYPE.EDGE); break; case CONNECTION: k = "CONNEDGE" + getNumerator(NUMTYPE.CONNECTION); break; case NODE: k = "NODEEDGE" + getNumerator(NUMTYPE.NODEEDGE); temp.add("ID", new JsonPrimitive(id)); break; case OLD: k = "OLDEDGE" + getNumerator(NUMTYPE.OLDEDGE); temp.add("ID", new JsonPrimitive(id)); break; default: break; } file.add(k, gson.toJsonTree(temp)); temp = new JsonObject(); } } /** * Initialize the Gson with wanted parameters */ private void initGson() { // TODO Auto-generated method stub GsonBuilder builder = new GsonBuilder(); builder.excludeFieldsWithoutExposeAnnotation().serializeNulls().setPrettyPrinting(); builder.registerTypeAdapter(AbstractCpsObject.class, new AbstractCpsObjectAdapter()); builder.registerTypeAdapter(Position.class, new PositionAdapter()); builder.registerTypeAdapter(Color.class, new ColorAdapter()); // use the builder and make a instance of the Gson this.gson = builder.create(); } /** * Just initialize the Numerators for the Json Keys. Maybe bad Style.. */ private void initNumeration() { this.nCat = this.nObj = this.nEle = this.nEdge = this.nConn = this.nNodeEdge = this.nOldEdge = 0; } /** * Get the wanted numerator and increment it * * @param type * @return */ private int getNumerator(NUMTYPE type) { switch (type) { case CATEGORY: return nCat++; case OBJECT: return nObj++; case ELEMENT: return nEle++; case EDGE: return nEdge++; case CONNECTION: return nConn++; case NODEEDGE: return nNodeEdge++; case OLDEDGE: return nOldEdge++; case UNITGRAPH: return nUnitGraph++; default: break; } return -1; } }