|
@@ -17,465 +17,486 @@ import java.util.List;
|
|
|
|
|
|
/**
|
|
|
* Controller for Storage.
|
|
|
- *
|
|
|
+ *
|
|
|
* @author Gruppe14
|
|
|
*/
|
|
|
public class SaveController {
|
|
|
|
|
|
- private Model model;
|
|
|
- private int nCat, nObj, nEle, nEdge, nConn, nNodeEdge, nOldEdge, nUnitGraph, nStatsGraph;
|
|
|
-
|
|
|
- /**
|
|
|
- * Constructor.
|
|
|
- *
|
|
|
- * @param model
|
|
|
- * the Model
|
|
|
- */
|
|
|
- SaveController(Model model) {
|
|
|
- this.model = model;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Writes the current State of the Modelling into a JSON File which can be
|
|
|
- * loaded.
|
|
|
- *
|
|
|
- * @param path
|
|
|
- * the Path
|
|
|
- *
|
|
|
- * @throws IOException
|
|
|
- * exception
|
|
|
- */
|
|
|
- void writeSave(String path) throws IOException, ArchiveException {
|
|
|
-
|
|
|
- File dst = new File(path);
|
|
|
- File holonFile = File.createTempFile("tmp", ".json");
|
|
|
- holonFile.deleteOnExit();
|
|
|
- dst.delete();
|
|
|
-
|
|
|
- OutputStream output = new FileOutputStream(dst);
|
|
|
- ArchiveOutputStream stream = new ArchiveStreamFactory().createArchiveOutputStream(ArchiveStreamFactory.ZIP,
|
|
|
- output);
|
|
|
-
|
|
|
- initNumeration();
|
|
|
- JsonObject file = new JsonObject();
|
|
|
- initialize(MODE.COMPLETE, file);
|
|
|
- storeCategory(file);
|
|
|
- storeCanvas(file);
|
|
|
- storeStatistics(file);
|
|
|
- storeData(stream);
|
|
|
-
|
|
|
- FileWriter writer = new FileWriter(holonFile);
|
|
|
- writer.write(model.getGson().toJson(file));
|
|
|
- writer.flush();
|
|
|
- writer.close();
|
|
|
-
|
|
|
- addFileToSave(holonFile, stream, false);
|
|
|
-
|
|
|
- stream.finish();
|
|
|
- output.close();
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Writes the Autosave File.
|
|
|
- *
|
|
|
- * @param path
|
|
|
- * the Path
|
|
|
- * @throws IOException
|
|
|
- * Exception
|
|
|
- */
|
|
|
- void writeAutosave(String path) throws IOException {
|
|
|
-
|
|
|
- initNumeration();
|
|
|
- JsonObject file = new JsonObject();
|
|
|
- initialize(MODE.PARTIAL, file);
|
|
|
- storeCanvas(file);
|
|
|
-
|
|
|
- FileWriter writer = new FileWriter(path);
|
|
|
- writer.write(model.getGson().toJson(file));
|
|
|
-
|
|
|
- writer.flush();
|
|
|
- writer.close();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Writes the Category File in Case of Changes
|
|
|
- */
|
|
|
- void writeCategory(String path) throws IOException {
|
|
|
-
|
|
|
- initNumeration();
|
|
|
- JsonObject file = new JsonObject();
|
|
|
- initialize(MODE.CATEGORY, file);
|
|
|
- storeCategory(file);
|
|
|
-
|
|
|
- FileWriter writer = new FileWriter(path);
|
|
|
- writer.write(model.getGson().toJson(file));
|
|
|
-
|
|
|
- writer.flush();
|
|
|
- writer.close();
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Write needed default parameter into the JsonObject. Can be extended later
|
|
|
- * on
|
|
|
- */
|
|
|
- private void initialize(MODE mode, JsonObject file) {
|
|
|
- switch (mode) {
|
|
|
- case COMPLETE:
|
|
|
- file.add("MODE", new JsonPrimitive(mode.name()));
|
|
|
- file.add("IDCOUNTER", new JsonPrimitive(IdCounter.getCounter()));
|
|
|
- file.add("IDCOUNTERELEMENT", new JsonPrimitive(IdCounterElem.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()));
|
|
|
- file.add("IDCOUNTERELEMENT", new JsonPrimitive(IdCounterElem.getCounter()));
|
|
|
- file.add("CANVAS_SIZE_X", new JsonPrimitive(model.getCanvasX()));
|
|
|
- file.add("CANVAS_SIZE_Y", new JsonPrimitive(model.getCanvasY()));
|
|
|
- break;
|
|
|
- case CATEGORY:
|
|
|
- file.add("MODE", new JsonPrimitive(mode.name()));
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Store all Categories and Object into a Json File via Serialization
|
|
|
- */
|
|
|
- private void storeCategory(JsonObject file) {
|
|
|
- // forall categories store them into the jsontree
|
|
|
- for (Category cat : model.getCategories()) {
|
|
|
- String key = "CATEGORY" + getNumerator(NUMTYPE.CATEGORY);
|
|
|
-
|
|
|
- file.add(key, new JsonPrimitive(cat.getName()));
|
|
|
- // forall object in the category store them into the jsontree
|
|
|
- for (AbstractCpsObject obj : cat.getObjects()) {
|
|
|
- file.add("CGOBJECT" + getNumerator(NUMTYPE.OBJECT),
|
|
|
- model.getGson().toJsonTree(obj, AbstractCpsObject.class));
|
|
|
- // if its a holonobject add elements too
|
|
|
- if (obj instanceof HolonObject)
|
|
|
- elementsToJson(TYPE.CATEGORY, file, obj);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Travers through all Objects via BFS and Stores everything relevant
|
|
|
- */
|
|
|
- private void storeCanvas(JsonObject file) {
|
|
|
- ArrayDeque<AbstractCpsObject> queue = new ArrayDeque<>();
|
|
|
- AbstractCpsObject u = null;
|
|
|
- // put all objects into queue since there is not starting object
|
|
|
- for (AbstractCpsObject cps : model.getObjectsOnCanvas()) {
|
|
|
- queue.add(cps);
|
|
|
- }
|
|
|
- // while quene not empty
|
|
|
- while (!queue.isEmpty()) {
|
|
|
-
|
|
|
- // u = current node
|
|
|
- u = queue.pop();
|
|
|
- // add currentnode into jsontree
|
|
|
- String key = "CVSOBJECT" + getNumerator(NUMTYPE.OBJECT);
|
|
|
- file.add(key, model.getGson().toJsonTree(u, AbstractCpsObject.class));
|
|
|
- // and its connections too
|
|
|
- edgeToJson(EDGETYPE.CONNECTION, file, u.getId(), u.getConnections());
|
|
|
- // if holonobject elements too
|
|
|
- if (u instanceof HolonObject)
|
|
|
- elementsToJson(TYPE.CANVAS, file, u);
|
|
|
- // if switch graphpoints too
|
|
|
- if (u instanceof HolonSwitch)
|
|
|
- if (((HolonSwitch) u).getGraphPoints().size() != 0)
|
|
|
- unitgraphToJson(GRAPHTYPE.SWITCH, file, u.getId(), ((HolonSwitch) u).getGraphPoints());
|
|
|
- // if uppernode put all nodes inside the uppernode into queue
|
|
|
- if (u instanceof CpsUpperNode) {
|
|
|
- for (AbstractCpsObject adjacent : ((CpsUpperNode) u).getNodes()) {
|
|
|
- queue.add(adjacent);
|
|
|
- }
|
|
|
- // dont forget to add the nodeedges and oldedges
|
|
|
- edgeToJson(EDGETYPE.NODE, file, u.getId(), ((CpsUpperNode) u).getNodeEdges());
|
|
|
- edgeToJson(EDGETYPE.OLD, file, u.getId(), ((CpsUpperNode) u).getOldEdges());
|
|
|
- }
|
|
|
- }
|
|
|
- // lastly add canvasedges into json
|
|
|
- edgeToJson(EDGETYPE.CANVAS, file, 0, model.getEdgesOnCanvas());
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- private void storeStatistics(JsonObject file) {
|
|
|
- trackedToJson(file);
|
|
|
- statisticgraphToJson(file);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Save wanted Data
|
|
|
- */
|
|
|
- private void storeData(ArchiveOutputStream stream) throws IOException {
|
|
|
- File images = new File(System.getProperty("user.home") + "/.config/HolonGUI/Images");
|
|
|
- File background = new File(System.getProperty("user.home") + "/.config/HolonGUI/BackgroundImages");
|
|
|
- addFilesToSave(images, stream);
|
|
|
- addFilesToSave(background, stream);
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Stores Category or Canvas Elements into Json
|
|
|
- */
|
|
|
- void elementsToJson(TYPE type, JsonObject file, AbstractCpsObject obj) {
|
|
|
- JsonObject temp = new JsonObject();
|
|
|
- String key = null;
|
|
|
- // forall elements store them into json and include the id of the object
|
|
|
- for (HolonElement ele : ((HolonObject) obj).getElements()) {
|
|
|
- temp.add("properties", model.getGson().toJsonTree(ele));
|
|
|
- temp.add("ID", new JsonPrimitive(obj.getId()));
|
|
|
- // switch for deciding the key
|
|
|
- switch (type) {
|
|
|
- case CANVAS:
|
|
|
- key = "CVSELEMENT" + getNumerator(NUMTYPE.ELEMENT);
|
|
|
- break;
|
|
|
- case CATEGORY:
|
|
|
- key = "CGELEMENT" + getNumerator(NUMTYPE.ELEMENT);
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- file.add(key, model.getGson().toJsonTree(temp));
|
|
|
- // if there are gps add them into
|
|
|
- if (ele.getGraphPoints().size() != 0)
|
|
|
- unitgraphToJson(GRAPHTYPE.ELEMENT, file, ele.getId(), ele.getGraphPoints());
|
|
|
- temp = new JsonObject();
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Put the UnitGraphs of Switches or Elements into Json
|
|
|
- */
|
|
|
- void unitgraphToJson(GRAPHTYPE type, JsonObject file, int id, LinkedList<Point> graph) {
|
|
|
-
|
|
|
- JsonObject temp = new JsonObject();
|
|
|
- String key = null;
|
|
|
- // forall points add them
|
|
|
- for (int i = 0; i < graph.size(); i++) {
|
|
|
- temp.add("" + i, new JsonPrimitive(graph.get(i).x + ":" + graph.get(i).y));
|
|
|
- }
|
|
|
- // decide key
|
|
|
- switch (type) {
|
|
|
- case SWITCH:
|
|
|
- key = "SWUNITGRAPH" + getNumerator(NUMTYPE.UNITGRAPH);
|
|
|
- break;
|
|
|
- case ELEMENT:
|
|
|
- key = "ELEUNITGRAPH" + getNumerator(NUMTYPE.UNITGRAPH);
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- // add id of element so it can be found again
|
|
|
- temp.add("ID", new JsonPrimitive(id));
|
|
|
-
|
|
|
- file.add(key, model.getGson().toJsonTree(temp));
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Canvas-Edge, Connections, Node-Edge and Old-Edges to json
|
|
|
- */
|
|
|
- private void edgeToJson(EDGETYPE type, JsonObject file, int id, ArrayList<CpsEdge> arr) {
|
|
|
- String k = null;
|
|
|
- boolean b = false;
|
|
|
- JsonObject temp = new JsonObject();
|
|
|
-
|
|
|
- for (CpsEdge edge : arr) {
|
|
|
- // add properties and only the ids from a and b
|
|
|
- temp.add("properties", model.getGson().toJsonTree(edge));
|
|
|
- temp.add("A", new JsonPrimitive(edge.getA().getId()));
|
|
|
- temp.add("B", new JsonPrimitive(edge.getB().getId()));
|
|
|
-
|
|
|
- // Key and occasionally the id of Uppernode
|
|
|
- switch (type) {
|
|
|
- case CANVAS:
|
|
|
- k = "CVSEDGE" + getNumerator(NUMTYPE.EDGE);
|
|
|
- break;
|
|
|
- case CONNECTION:
|
|
|
- k = "CONNEDGE" + getNumerator(NUMTYPE.CONNECTION);
|
|
|
- break;
|
|
|
- case NODE:
|
|
|
- temp.add("ID", new JsonPrimitive(id));
|
|
|
- k = "NODEEDGE" + getNumerator(NUMTYPE.NODEEDGE);
|
|
|
- break;
|
|
|
- case OLD:
|
|
|
- temp.add("ID", new JsonPrimitive(id));
|
|
|
- k = "OLDEDGE" + getNumerator(NUMTYPE.OLDEDGE);
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- // lookup if the CVS, NODE or OLDEDGE are also connections
|
|
|
- if (edge.getA().getConnections().contains(edge) && edge.getA().getConnections().contains(edge)
|
|
|
- && !type.equals(EDGETYPE.CONNECTION))
|
|
|
- b = true;
|
|
|
- temp.add("connection", new JsonPrimitive(b));
|
|
|
- file.add(k, model.getGson().toJsonTree(temp));
|
|
|
- temp = new JsonObject();
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- private void trackedToJson(JsonObject file) {
|
|
|
- JsonObject temp = new JsonObject();
|
|
|
- String key = "TRACKED";
|
|
|
- // forall points add them
|
|
|
- for (int i = 0; i < model.getTrackingObj().size(); i++) {
|
|
|
- temp.add("" + i, new JsonPrimitive(model.getTrackingObj().get(i).getId()));
|
|
|
- }
|
|
|
-
|
|
|
- file.add(key, model.getGson().toJsonTree(temp));
|
|
|
- }
|
|
|
-
|
|
|
- private void statisticgraphToJson(JsonObject file) {
|
|
|
- JsonObject temp = new JsonObject();
|
|
|
-
|
|
|
- List<String> keys = new ArrayList<>(model.getGraphTable().keySet());
|
|
|
-
|
|
|
- for (String k : keys) {
|
|
|
- JsonObject dataSet = new JsonObject();
|
|
|
- for (int i = 0; i < model.getGraphTable().get(k).getStatGraph().getDataSets().size(); i++) {
|
|
|
- TrackedDataSet set = model.getGraphTable().get(k).getStatGraph().getDataSets().get(i);
|
|
|
- AbstractCpsObject cps = set.getCpsObject();
|
|
|
-
|
|
|
- dataSet.add("ID", (cps == null ? null : new JsonPrimitive(cps.getId())));
|
|
|
- dataSet.add("COLOR", model.getGson().toJsonTree(set.getColor(), Color.class));
|
|
|
- dataSet.add("PROPERTY", new JsonPrimitive(set.getProperty()));
|
|
|
- temp.add("" + i, model.getGson().toJsonTree(dataSet));
|
|
|
- dataSet = new JsonObject();
|
|
|
- }
|
|
|
- temp.add("KEY", new JsonPrimitive(k));
|
|
|
-
|
|
|
- file.add("STATSGRAPH" + getNumerator(NUMTYPE.STATSGRAPH), model.getGson().toJsonTree(temp));
|
|
|
- temp = new JsonObject();
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Differs Between Single file or whole Directory to Store
|
|
|
- */
|
|
|
- private void addFilesToSave(File src, ArchiveOutputStream stream) throws IOException {
|
|
|
- if (!src.exists())
|
|
|
- return;
|
|
|
-
|
|
|
- ArrayList<File> files = new ArrayList<>();
|
|
|
- files.addAll(Arrays.asList(src.listFiles()));
|
|
|
-
|
|
|
- for (File file : files) {
|
|
|
- if (file.isDirectory())
|
|
|
- addFilesToSave(file, stream);
|
|
|
- else
|
|
|
- addFileToSave(file, stream, true);
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Add a File into the Archive
|
|
|
- */
|
|
|
- private void addFileToSave(File src, ArchiveOutputStream stream, boolean dir) throws IOException {
|
|
|
- String entryName = (dir ? src.getCanonicalPath() : src.getName());
|
|
|
-
|
|
|
- entryName = checkOS(entryName);
|
|
|
-
|
|
|
- ZipArchiveEntry entry = new ZipArchiveEntry(entryName);
|
|
|
- stream.putArchiveEntry(entry);
|
|
|
- BufferedInputStream input = new BufferedInputStream(new FileInputStream(src));
|
|
|
-
|
|
|
- IOUtils.copy(input, stream);
|
|
|
- input.close();
|
|
|
- stream.closeArchiveEntry();
|
|
|
- }
|
|
|
-
|
|
|
- private String checkOS(String entryName) {
|
|
|
- String os = System.getProperty("os.name").toLowerCase();
|
|
|
- String ret = entryName;
|
|
|
- String partition = null;
|
|
|
-
|
|
|
- if (os.contains("windows")) {
|
|
|
- partition = ret.substring(0, ret.indexOf(":") + 1);
|
|
|
- ret = ret.replace(System.getProperty("user.home") + "\\.config\\HolonGUI\\", "");
|
|
|
- ret = ret.replace(partition, "");
|
|
|
- }
|
|
|
- if (os.contains("mac")) {
|
|
|
- // dosmth
|
|
|
- ret = ret.replace(System.getProperty("user.home") + "/.config/HolonGUI/", "");
|
|
|
- }
|
|
|
- if (os.contains("linux")) {
|
|
|
- // dosmth
|
|
|
- ret = ret.replace(System.getProperty("user.home") + "/.config/HolonGUI/", "");
|
|
|
- }
|
|
|
- if (os.contains("solaris")) {
|
|
|
- // dosmth
|
|
|
- }
|
|
|
- return ret;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Just initialize the Numerators for the Json Keys. Maybe bad Style..
|
|
|
- */
|
|
|
- void initNumeration() {
|
|
|
- this.nCat = this.nObj = this.nEle = this.nEdge = this.nConn = this.nNodeEdge = this.nOldEdge = this.nStatsGraph = 0;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Get the wanted numerator and increment it
|
|
|
- */
|
|
|
- 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++;
|
|
|
- case STATSGRAPH:
|
|
|
- return nStatsGraph++;
|
|
|
-
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- public enum MODE {
|
|
|
- COMPLETE, PARTIAL, CATEGORY
|
|
|
- }
|
|
|
-
|
|
|
- public enum TYPE {
|
|
|
- CATEGORY, CANVAS
|
|
|
- }
|
|
|
-
|
|
|
- public enum EDGETYPE {
|
|
|
- CANVAS, CONNECTION, NODE, OLD, LAYER
|
|
|
- }
|
|
|
-
|
|
|
- public enum NUMTYPE {
|
|
|
- CATEGORY, OBJECT, ELEMENT, EDGE, CONNECTION, NODEEDGE, OLDEDGE, UNITGRAPH, STATSGRAPH
|
|
|
- }
|
|
|
-
|
|
|
- public enum GRAPHTYPE {
|
|
|
- SWITCH, ELEMENT
|
|
|
- }
|
|
|
+ private Model model;
|
|
|
+ private int nCat, nObj, nEle, nEdge, nConn, nNodeEdge, nOldEdge, nUnitGraph, nStatsGraph;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Constructor.
|
|
|
+ *
|
|
|
+ * @param model the Model
|
|
|
+ */
|
|
|
+ SaveController(Model model) {
|
|
|
+ this.model = model;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Writes the current State of the Modelling into a JSON File which can be
|
|
|
+ * loaded.
|
|
|
+ *
|
|
|
+ * @param path the Path
|
|
|
+ * @throws IOException exception
|
|
|
+ */
|
|
|
+ void writeSave(String path) throws IOException, ArchiveException {
|
|
|
+
|
|
|
+ File dst = new File(path);
|
|
|
+ File holonFile = File.createTempFile("tmp", ".json");
|
|
|
+ holonFile.deleteOnExit();
|
|
|
+ dst.delete();
|
|
|
+
|
|
|
+ OutputStream output = new FileOutputStream(dst);
|
|
|
+ ArchiveOutputStream stream = new ArchiveStreamFactory().createArchiveOutputStream(ArchiveStreamFactory.ZIP,
|
|
|
+ output);
|
|
|
+
|
|
|
+ initNumeration();
|
|
|
+ JsonObject file = new JsonObject();
|
|
|
+ initialize(MODE.COMPLETE, file);
|
|
|
+ storeCategory(file);
|
|
|
+ storeCanvas(file);
|
|
|
+ storeStatistics(file);
|
|
|
+ storeData(stream);
|
|
|
+
|
|
|
+ FileWriter writer = new FileWriter(holonFile);
|
|
|
+ writer.write(model.getGson().toJson(file));
|
|
|
+ writer.flush();
|
|
|
+ writer.close();
|
|
|
+
|
|
|
+ addFileToSave(holonFile, stream, false);
|
|
|
+
|
|
|
+ stream.finish();
|
|
|
+ output.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Writes the windows status (its position and dimensions)
|
|
|
+ *
|
|
|
+ * @param path the Path where to save it
|
|
|
+ */
|
|
|
+ void writeWindowStatus(String path, int x, int y, int width, int height)
|
|
|
+ throws IOException, ArchiveException {
|
|
|
+ JsonObject file = new JsonObject();
|
|
|
+ initialize(MODE.SIZE, file);
|
|
|
+ storeWindowPosAndSize(file, x, y, width, height);
|
|
|
+
|
|
|
+ FileWriter writer = new FileWriter(path);
|
|
|
+ writer.write(model.getGson().toJson(file));
|
|
|
+ writer.flush();
|
|
|
+ writer.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Writes the Autosave File.
|
|
|
+ *
|
|
|
+ * @param path the Path
|
|
|
+ * @throws IOException Exception
|
|
|
+ */
|
|
|
+ void writeAutosave(String path) throws IOException {
|
|
|
+
|
|
|
+ initNumeration();
|
|
|
+ JsonObject file = new JsonObject();
|
|
|
+ initialize(MODE.PARTIAL, file);
|
|
|
+ storeCanvas(file);
|
|
|
+
|
|
|
+ FileWriter writer = new FileWriter(path);
|
|
|
+ writer.write(model.getGson().toJson(file));
|
|
|
+
|
|
|
+ writer.flush();
|
|
|
+ writer.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Writes the Category File in Case of Changes
|
|
|
+ */
|
|
|
+ void writeCategory(String path) throws IOException {
|
|
|
+
|
|
|
+ initNumeration();
|
|
|
+ JsonObject file = new JsonObject();
|
|
|
+ initialize(MODE.CATEGORY, file);
|
|
|
+ storeCategory(file);
|
|
|
+
|
|
|
+ FileWriter writer = new FileWriter(path);
|
|
|
+ writer.write(model.getGson().toJson(file));
|
|
|
+
|
|
|
+ writer.flush();
|
|
|
+ writer.close();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Write needed default parameter into the JsonObject. Can be extended later
|
|
|
+ * on
|
|
|
+ */
|
|
|
+ private void initialize(MODE mode, JsonObject file) {
|
|
|
+ switch (mode) {
|
|
|
+ case COMPLETE:
|
|
|
+ file.add("MODE", new JsonPrimitive(mode.name()));
|
|
|
+ file.add("IDCOUNTER", new JsonPrimitive(IdCounter.getCounter()));
|
|
|
+ file.add("IDCOUNTERELEMENT", new JsonPrimitive(IdCounterElem.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()));
|
|
|
+ file.add("IDCOUNTERELEMENT", new JsonPrimitive(IdCounterElem.getCounter()));
|
|
|
+ file.add("CANVAS_SIZE_X", new JsonPrimitive(model.getCanvasX()));
|
|
|
+ file.add("CANVAS_SIZE_Y", new JsonPrimitive(model.getCanvasY()));
|
|
|
+ break;
|
|
|
+ case CATEGORY:
|
|
|
+ file.add("MODE", new JsonPrimitive(mode.name()));
|
|
|
+ break;
|
|
|
+ case SIZE:
|
|
|
+ file.add("MODE", new JsonPrimitive(mode.name()));
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Store all Categories and Object into a Json File via Serialization
|
|
|
+ */
|
|
|
+ private void storeCategory(JsonObject file) {
|
|
|
+ // forall categories store them into the jsontree
|
|
|
+ for (Category cat : model.getCategories()) {
|
|
|
+ String key = "CATEGORY" + getNumerator(NUMTYPE.CATEGORY);
|
|
|
+
|
|
|
+ file.add(key, new JsonPrimitive(cat.getName()));
|
|
|
+ // forall object in the category store them into the jsontree
|
|
|
+ for (AbstractCpsObject obj : cat.getObjects()) {
|
|
|
+ file.add("CGOBJECT" + getNumerator(NUMTYPE.OBJECT),
|
|
|
+ model.getGson().toJsonTree(obj, AbstractCpsObject.class));
|
|
|
+ // if its a holonobject add elements too
|
|
|
+ if (obj instanceof HolonObject)
|
|
|
+ elementsToJson(TYPE.CATEGORY, file, obj);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void storeWindowPosAndSize(JsonObject file, int x, int y, int width, int height) {
|
|
|
+ file.add("POS_X", new JsonPrimitive(x));
|
|
|
+ file.add("POS_Y", new JsonPrimitive(y));
|
|
|
+ file.add("WIDTH", new JsonPrimitive(width));
|
|
|
+ file.add("HEIGHT", new JsonPrimitive(height));
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Travers through all Objects via BFS and Stores everything relevant
|
|
|
+ */
|
|
|
+ private void storeCanvas(JsonObject file) {
|
|
|
+ ArrayDeque<AbstractCpsObject> queue = new ArrayDeque<>();
|
|
|
+ AbstractCpsObject u = null;
|
|
|
+ // put all objects into queue since there is not starting object
|
|
|
+ for (AbstractCpsObject cps : model.getObjectsOnCanvas()) {
|
|
|
+ queue.add(cps);
|
|
|
+ }
|
|
|
+ // while quene not empty
|
|
|
+ while (!queue.isEmpty()) {
|
|
|
+
|
|
|
+ // u = current node
|
|
|
+ u = queue.pop();
|
|
|
+ // add currentnode into jsontree
|
|
|
+ String key = "CVSOBJECT" + getNumerator(NUMTYPE.OBJECT);
|
|
|
+ file.add(key, model.getGson().toJsonTree(u, AbstractCpsObject.class));
|
|
|
+ // and its connections too
|
|
|
+ edgeToJson(EDGETYPE.CONNECTION, file, u.getId(), u.getConnections());
|
|
|
+ // if holonobject elements too
|
|
|
+ if (u instanceof HolonObject)
|
|
|
+ elementsToJson(TYPE.CANVAS, file, u);
|
|
|
+ // if switch graphpoints too
|
|
|
+ if (u instanceof HolonSwitch)
|
|
|
+ if (((HolonSwitch) u).getGraphPoints().size() != 0)
|
|
|
+ unitgraphToJson(GRAPHTYPE.SWITCH, file, u.getId(), ((HolonSwitch) u).getGraphPoints());
|
|
|
+ // if uppernode put all nodes inside the uppernode into queue
|
|
|
+ if (u instanceof CpsUpperNode) {
|
|
|
+ for (AbstractCpsObject adjacent : ((CpsUpperNode) u).getNodes()) {
|
|
|
+ queue.add(adjacent);
|
|
|
+ }
|
|
|
+ // dont forget to add the nodeedges and oldedges
|
|
|
+ edgeToJson(EDGETYPE.NODE, file, u.getId(), ((CpsUpperNode) u).getNodeEdges());
|
|
|
+ edgeToJson(EDGETYPE.OLD, file, u.getId(), ((CpsUpperNode) u).getOldEdges());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // lastly add canvasedges into json
|
|
|
+ edgeToJson(EDGETYPE.CANVAS, file, 0, model.getEdgesOnCanvas());
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void storeStatistics(JsonObject file) {
|
|
|
+ trackedToJson(file);
|
|
|
+ statisticgraphToJson(file);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Save wanted Data
|
|
|
+ */
|
|
|
+ private void storeData(ArchiveOutputStream stream) throws IOException {
|
|
|
+ File images = new File(System.getProperty("user.home") + "/.config/HolonGUI/Images");
|
|
|
+ File background = new File(System.getProperty("user.home") + "/.config/HolonGUI/BackgroundImages");
|
|
|
+ addFilesToSave(images, stream);
|
|
|
+ addFilesToSave(background, stream);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Stores Category or Canvas Elements into Json
|
|
|
+ */
|
|
|
+ void elementsToJson(TYPE type, JsonObject file, AbstractCpsObject obj) {
|
|
|
+ JsonObject temp = new JsonObject();
|
|
|
+ String key = null;
|
|
|
+ // forall elements store them into json and include the id of the object
|
|
|
+ for (HolonElement ele : ((HolonObject) obj).getElements()) {
|
|
|
+ temp.add("properties", model.getGson().toJsonTree(ele));
|
|
|
+ temp.add("ID", new JsonPrimitive(obj.getId()));
|
|
|
+ // switch for deciding the key
|
|
|
+ switch (type) {
|
|
|
+ case CANVAS:
|
|
|
+ key = "CVSELEMENT" + getNumerator(NUMTYPE.ELEMENT);
|
|
|
+ break;
|
|
|
+ case CATEGORY:
|
|
|
+ key = "CGELEMENT" + getNumerator(NUMTYPE.ELEMENT);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ file.add(key, model.getGson().toJsonTree(temp));
|
|
|
+ // if there are gps add them into
|
|
|
+ if (ele.getGraphPoints().size() != 0)
|
|
|
+ unitgraphToJson(GRAPHTYPE.ELEMENT, file, ele.getId(), ele.getGraphPoints());
|
|
|
+ temp = new JsonObject();
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Put the UnitGraphs of Switches or Elements into Json
|
|
|
+ */
|
|
|
+ void unitgraphToJson(GRAPHTYPE type, JsonObject file, int id, LinkedList<Point> graph) {
|
|
|
+
|
|
|
+ JsonObject temp = new JsonObject();
|
|
|
+ String key = null;
|
|
|
+ // forall points add them
|
|
|
+ for (int i = 0; i < graph.size(); i++) {
|
|
|
+ temp.add("" + i, new JsonPrimitive(graph.get(i).x + ":" + graph.get(i).y));
|
|
|
+ }
|
|
|
+ // decide key
|
|
|
+ switch (type) {
|
|
|
+ case SWITCH:
|
|
|
+ key = "SWUNITGRAPH" + getNumerator(NUMTYPE.UNITGRAPH);
|
|
|
+ break;
|
|
|
+ case ELEMENT:
|
|
|
+ key = "ELEUNITGRAPH" + getNumerator(NUMTYPE.UNITGRAPH);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ // add id of element so it can be found again
|
|
|
+ temp.add("ID", new JsonPrimitive(id));
|
|
|
+
|
|
|
+ file.add(key, model.getGson().toJsonTree(temp));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Canvas-Edge, Connections, Node-Edge and Old-Edges to json
|
|
|
+ */
|
|
|
+ private void edgeToJson(EDGETYPE type, JsonObject file, int id, ArrayList<CpsEdge> arr) {
|
|
|
+ String k = null;
|
|
|
+ boolean b = false;
|
|
|
+ JsonObject temp = new JsonObject();
|
|
|
+
|
|
|
+ for (CpsEdge edge : arr) {
|
|
|
+ // add properties and only the ids from a and b
|
|
|
+ temp.add("properties", model.getGson().toJsonTree(edge));
|
|
|
+ temp.add("A", new JsonPrimitive(edge.getA().getId()));
|
|
|
+ temp.add("B", new JsonPrimitive(edge.getB().getId()));
|
|
|
+
|
|
|
+ // Key and occasionally the id of Uppernode
|
|
|
+ switch (type) {
|
|
|
+ case CANVAS:
|
|
|
+ k = "CVSEDGE" + getNumerator(NUMTYPE.EDGE);
|
|
|
+ break;
|
|
|
+ case CONNECTION:
|
|
|
+ k = "CONNEDGE" + getNumerator(NUMTYPE.CONNECTION);
|
|
|
+ break;
|
|
|
+ case NODE:
|
|
|
+ temp.add("ID", new JsonPrimitive(id));
|
|
|
+ k = "NODEEDGE" + getNumerator(NUMTYPE.NODEEDGE);
|
|
|
+ break;
|
|
|
+ case OLD:
|
|
|
+ temp.add("ID", new JsonPrimitive(id));
|
|
|
+ k = "OLDEDGE" + getNumerator(NUMTYPE.OLDEDGE);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ // lookup if the CVS, NODE or OLDEDGE are also connections
|
|
|
+ if (edge.getA().getConnections().contains(edge) && edge.getA().getConnections().contains(edge)
|
|
|
+ && !type.equals(EDGETYPE.CONNECTION))
|
|
|
+ b = true;
|
|
|
+ temp.add("connection", new JsonPrimitive(b));
|
|
|
+ file.add(k, model.getGson().toJsonTree(temp));
|
|
|
+ temp = new JsonObject();
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void trackedToJson(JsonObject file) {
|
|
|
+ JsonObject temp = new JsonObject();
|
|
|
+ String key = "TRACKED";
|
|
|
+ // forall points add them
|
|
|
+ for (int i = 0; i < model.getTrackingObj().size(); i++) {
|
|
|
+ temp.add("" + i, new JsonPrimitive(model.getTrackingObj().get(i).getId()));
|
|
|
+ }
|
|
|
+
|
|
|
+ file.add(key, model.getGson().toJsonTree(temp));
|
|
|
+ }
|
|
|
+
|
|
|
+ private void statisticgraphToJson(JsonObject file) {
|
|
|
+ JsonObject temp = new JsonObject();
|
|
|
+
|
|
|
+ List<String> keys = new ArrayList<>(model.getGraphTable().keySet());
|
|
|
+
|
|
|
+ for (String k : keys) {
|
|
|
+ JsonObject dataSet = new JsonObject();
|
|
|
+ for (int i = 0; i < model.getGraphTable().get(k).getStatGraph().getDataSets().size(); i++) {
|
|
|
+ TrackedDataSet set = model.getGraphTable().get(k).getStatGraph().getDataSets().get(i);
|
|
|
+ AbstractCpsObject cps = set.getCpsObject();
|
|
|
+
|
|
|
+ dataSet.add("ID", (cps == null ? null : new JsonPrimitive(cps.getId())));
|
|
|
+ dataSet.add("COLOR", model.getGson().toJsonTree(set.getColor(), Color.class));
|
|
|
+ dataSet.add("PROPERTY", new JsonPrimitive(set.getProperty()));
|
|
|
+ temp.add("" + i, model.getGson().toJsonTree(dataSet));
|
|
|
+ dataSet = new JsonObject();
|
|
|
+ }
|
|
|
+ temp.add("KEY", new JsonPrimitive(k));
|
|
|
+
|
|
|
+ file.add("STATSGRAPH" + getNumerator(NUMTYPE.STATSGRAPH), model.getGson().toJsonTree(temp));
|
|
|
+ temp = new JsonObject();
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Differs Between Single file or whole Directory to Store
|
|
|
+ */
|
|
|
+ private void addFilesToSave(File src, ArchiveOutputStream stream) throws IOException {
|
|
|
+ if (!src.exists())
|
|
|
+ return;
|
|
|
+
|
|
|
+ ArrayList<File> files = new ArrayList<>();
|
|
|
+ files.addAll(Arrays.asList(src.listFiles()));
|
|
|
+
|
|
|
+ for (File file : files) {
|
|
|
+ if (file.isDirectory())
|
|
|
+ addFilesToSave(file, stream);
|
|
|
+ else
|
|
|
+ addFileToSave(file, stream, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Add a File into the Archive
|
|
|
+ */
|
|
|
+ private void addFileToSave(File src, ArchiveOutputStream stream, boolean dir) throws IOException {
|
|
|
+ String entryName = (dir ? src.getCanonicalPath() : src.getName());
|
|
|
+
|
|
|
+ entryName = checkOS(entryName);
|
|
|
+
|
|
|
+ ZipArchiveEntry entry = new ZipArchiveEntry(entryName);
|
|
|
+ stream.putArchiveEntry(entry);
|
|
|
+ BufferedInputStream input = new BufferedInputStream(new FileInputStream(src));
|
|
|
+
|
|
|
+ IOUtils.copy(input, stream);
|
|
|
+ input.close();
|
|
|
+ stream.closeArchiveEntry();
|
|
|
+ }
|
|
|
+
|
|
|
+ private String checkOS(String entryName) {
|
|
|
+ String os = System.getProperty("os.name").toLowerCase();
|
|
|
+ String ret = entryName;
|
|
|
+ String partition = null;
|
|
|
+
|
|
|
+ if (os.contains("windows")) {
|
|
|
+ partition = ret.substring(0, ret.indexOf(":") + 1);
|
|
|
+ ret = ret.replace(System.getProperty("user.home") + "\\.config\\HolonGUI\\", "");
|
|
|
+ ret = ret.replace(partition, "");
|
|
|
+ }
|
|
|
+ if (os.contains("mac")) {
|
|
|
+ // dosmth
|
|
|
+ ret = ret.replace(System.getProperty("user.home") + "/.config/HolonGUI/", "");
|
|
|
+ }
|
|
|
+ if (os.contains("linux")) {
|
|
|
+ // dosmth
|
|
|
+ ret = ret.replace(System.getProperty("user.home") + "/.config/HolonGUI/", "");
|
|
|
+ }
|
|
|
+ if (os.contains("solaris")) {
|
|
|
+ // dosmth
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Just initialize the Numerators for the Json Keys. Maybe bad Style..
|
|
|
+ */
|
|
|
+ void initNumeration() {
|
|
|
+ this.nCat = this.nObj = this.nEle = this.nEdge = this.nConn = this.nNodeEdge = this.nOldEdge = this.nStatsGraph = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get the wanted numerator and increment it
|
|
|
+ */
|
|
|
+ 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++;
|
|
|
+ case STATSGRAPH:
|
|
|
+ return nStatsGraph++;
|
|
|
+
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ public enum MODE {
|
|
|
+ COMPLETE, PARTIAL, CATEGORY, SIZE,
|
|
|
+ }
|
|
|
+
|
|
|
+ public enum TYPE {
|
|
|
+ CATEGORY, CANVAS
|
|
|
+ }
|
|
|
+
|
|
|
+ public enum EDGETYPE {
|
|
|
+ CANVAS, CONNECTION, NODE, OLD, LAYER
|
|
|
+ }
|
|
|
+
|
|
|
+ public enum NUMTYPE {
|
|
|
+ CATEGORY, OBJECT, ELEMENT, EDGE, CONNECTION, NODEEDGE, OLDEDGE, UNITGRAPH, STATSGRAPH
|
|
|
+ }
|
|
|
+
|
|
|
+ public enum GRAPHTYPE {
|
|
|
+ SWITCH, ELEMENT
|
|
|
+ }
|
|
|
|
|
|
}
|