package ui.controller; import java.awt.Color; import java.awt.Point; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.stream.Collectors; import java.util.zip.ZipException; import java.util.zip.ZipInputStream; import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.ArchiveException; import org.apache.commons.compress.archivers.ArchiveInputStream; import org.apache.commons.compress.archivers.ArchiveStreamFactory; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.utils.IOUtils; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; 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.IdCounterElem; import classes.Position; import ui.model.Model; /** * Controller for the Loading. * * @author Gruppe14 */ public class LoadController { /** * enum Mode. */ public enum MODE { COMPLETE, PARTIAL, CATEGORY } public enum EDGETYPE { CANVAS, CONNECTION, NODE, OLD } public enum GRAPHTYPE { SWITCH, ELEMENT } private Model model; private CategoryController cgC; private CanvasController cvsC; private ObjectController objC; private NodeController uppC; private MultiPurposeController mpC; private Gson gson; private JsonParser parser; /** * Constructor. * * @param model * Model * @param cg * CategoryController * @param cvs * CanvasController * @param obj * ObjectController * @param mp * MultiPurposeController */ public LoadController(Model model, CategoryController cg, CanvasController cvs, ObjectController obj, NodeController uppC, MultiPurposeController mp) { this.model = model; this.cgC = cg; this.cvsC = cvs; this.objC = obj; this.uppC = uppC; this.mpC = mp; initGson(); } /** * Reads the the JSON File and load the state into the Model. * * @param path * the Path * @throws IOException * exception */ public void readSave(String path) throws IOException, ArchiveException, ZipException { File src = new File(path); File folder = readArchive(path, src); folder.deleteOnExit(); String trim = folder.getPath().substring(0, folder.getPath().lastIndexOf(folder.getName()) + folder.getName().length()); forwardFiles(folder, trim); } public void readJson(String path) throws IOException { JsonObject json = (JsonObject) parser.parse(new FileReader(path)); // get all keys via stream List keys = getKeys(json); List edges = keys.stream().filter(key -> key.contains("EDGE")) .collect(Collectors.toCollection(ArrayList::new)); HashMap objDispatch = new HashMap<>(); HashMap eleDispatch = new HashMap<>(); initialize(keys, json); forwardObjects(keys, json, objDispatch, eleDispatch); forwardEdges(edges, json, objDispatch); } /** * Loads the Files from the Savefile * * @param folder * @param trim * @throws IOException */ private void forwardFiles(File folder, String trim) throws IOException { // TODO Auto-generated method stub for (File file : folder.listFiles()) { File dst = new File(System.getProperty("user.home") + "/HolonGUI/" + file.getPath().replace(trim, "")); if (file.getName().contains(".json")) readJson(file.getPath()); else if (file.isDirectory()) forwardFiles(file, trim); else { dst.getParentFile().mkdirs(); Files.copy(file.toPath(), dst.toPath(), StandardCopyOption.REPLACE_EXISTING); } } } /** * distribute the Edges * * @param edges * @param json * @param objDispatch */ private void forwardEdges(List edges, JsonObject json, HashMap objDispatch) { // TODO Auto-generated method stub List conn = new ArrayList<>(); for (String edge : edges) { if (edge.contains("CVSEDGE")) loadEdge(EDGETYPE.CANVAS, json.get(edge), objDispatch); if (edge.contains("CONNEDGE")) conn.add(edge); if (edge.contains("NODE")) loadEdge(EDGETYPE.NODE, json.get(edge), objDispatch); if (edge.contains("OLD")) loadEdge(EDGETYPE.OLD, json.get(edge), objDispatch); } for (String edge : conn) { loadEdge(EDGETYPE.CONNECTION, json.get(edge), objDispatch); } } /** * Distribute the given keys for right processing * * @param keys * @param json * @param objDispatch * @param eleDispatch */ private void forwardObjects(List keys, JsonObject json, HashMap objDispatch, HashMap eleDispatch) { // TODO Auto-generated method stub for (String key : keys) { if (key.contains("CATEGORY")) loadCategory(json.get(key)); if (key.contains("CGOBJECT")) loadCategoryObject(json.get(key)); if (key.contains("CGELEMENT")) loadCategoryElements(json.get(key)); if (key.contains("CVSOBJECT")) loadCanvasObject(json.get(key), objDispatch); if (key.contains("CVSELEMENT")) loadCanvasElements(json.get(key), objDispatch, eleDispatch); if (key.contains("SWUNITGRAPH")) loadUnitGraph(GRAPHTYPE.SWITCH, json.get(key), objDispatch, null); if (key.contains("ELEUNITGRAPH")) loadUnitGraph(GRAPHTYPE.ELEMENT, json.get(key), null, eleDispatch); if (key.contains("TRACKED")) loadTracked(json.get(key), objDispatch); } } /** * Init the Global Parameters * * @param keys * @param json */ private void initialize(List keys, JsonObject json) { switch (MODE.valueOf(json.get("MODE").getAsString())) { case COMPLETE: model.setCvsObjIdx(new HashMap()); model.setObjectsOnCanvas(new ArrayList()); model.setEdgesOnCanvas(new ArrayList()); model.setTrackingObj(new ArrayList<>()); model.setCanvasX(json.get("CANVAS_SIZE_X").getAsInt()); model.setCanvasX(json.get("CANVAS_SIZE_Y").getAsInt()); IdCounter.setCounter(json.get("IDCOUNTER").getAsInt()); IdCounterElem.setCounter(json.get("IDCOUNTERELEMENT").getAsInt()); break; case PARTIAL: model.setCvsObjIdx(new HashMap()); model.setObjectsOnCanvas(new ArrayList()); model.setEdgesOnCanvas(new ArrayList()); model.setCanvasX(json.get("CANVAS_SIZE_X").getAsInt()); model.setCanvasX(json.get("CANVAS_SIZE_Y").getAsInt()); IdCounter.setCounter(json.get("IDCOUNTER").getAsInt()); IdCounterElem.setCounter(json.get("IDCOUNTERELEMENT").getAsInt()); break; case CATEGORY: model.setCgIdx(new HashMap()); model.setCategories(new ArrayList()); default: break; } } /** * Load a given Category * * @param jsonElement */ private void loadCategory(JsonElement jsonElement) { // TODO Auto-generated method stub if (mpC.searchCat(jsonElement.getAsString()) == null) cgC.addCategory(new Category(jsonElement.getAsString())); } /** * Load a given Object in Category by Deserialization * * @param jsonElement */ private void loadCategoryObject(JsonElement jsonElement) { // TODO Auto-generated method stub AbstractCpsObject temp = gson.fromJson(jsonElement.getAsJsonObject(), AbstractCpsObject.class); temp.setImage(checkOS(temp.getImage())); initObjects(temp); if (mpC.searchCatObj(mpC.searchCat(temp.getSav()), temp.getObjName()) != null) cgC.deleteObject(temp.getSav(), temp.getObjName()); cgC.addObject(mpC.searchCat(temp.getSav()), temp); } private String refreshPath(String image) { // TODO Auto-generated method stub if (!image.contains("/HolonGUI/")) return image; return (System.getProperty("user.home") + image.substring(image.indexOf("/HolonGUI/"), image.length())) .replace("\\", "/"); } /** * Load a given Element in Category by Deserialization * * @param jsonElement */ private void loadCategoryElements(JsonElement jsonElement) { // TODO Auto-generated method stub HolonElement temp = gson.fromJson(jsonElement.getAsJsonObject().get("properties").getAsJsonObject(), HolonElement.class); initElements(temp); objC.addElementIntoCategoryObject(temp.getSav(), temp.getObj(), temp); } /** * Load a given Object in Canvas by Deserialization * * @param jsonElement * @param objDispatch */ private void loadCanvasObject(JsonElement jsonElement, HashMap objDispatch) { // TODO Auto-generated method stub AbstractCpsObject temp = gson.fromJson(jsonElement.getAsJsonObject(), AbstractCpsObject.class); initObjects(temp); temp.setImage(checkOS(temp.getImage())); // if its stored before on the canvas just put it there if (temp.getSav().equals("CVS")) { cvsC.addObject(temp); } else { // else look up the table and put it into the right Uppernode CpsUpperNode temp2 = (CpsUpperNode) objDispatch.get(Integer.parseInt(temp.getSav())); uppC.addObjectInUpperNode(temp, temp2); } objDispatch.put(temp.getId(), temp); } /** * Load a given Element in Canvas by Deserialization * * @param jsonElement * @param objDispatch * @param eleDispatch */ private void loadCanvasElements(JsonElement jsonElement, HashMap objDispatch, HashMap eleDispatch) { // TODO Auto-generated method stub JsonObject object = jsonElement.getAsJsonObject(); HolonElement temp = gson.fromJson(object.get("properties"), HolonElement.class); initElements(temp); // id which Object it was stored before int stored = object.get("ID").getAsInt(); // lookup that object HolonObject temp2 = (HolonObject) objDispatch.get(stored); // add it objC.addElement(temp2, temp); // store element also inside a table eleDispatch.put(temp.getId(), temp); } /** * Load a given Edge by Deserialization * * @param type * @param jsonElement * @param objDispatch */ private void loadEdge(EDGETYPE type, JsonElement jsonElement, HashMap objDispatch) { // TODO Auto-generated method stub JsonObject object = jsonElement.getAsJsonObject(); CpsEdge temp = gson.fromJson(object.get("properties"), CpsEdge.class); initCpsEdge(temp); // look for A and B inside the Table temp.setA(objDispatch.get(object.get("A").getAsInt())); temp.setB(objDispatch.get(object.get("B").getAsInt())); int sav = 0; switch (type) { case CANVAS: // if in canvas add it into the canvas but delete connection before model.getEdgesOnCanvas().add(temp); break; case CONNECTION: // if no duplicates in connection store them into the given A and B if (!uppC.lookforDuplicates(temp.getA(), temp.getB(), temp.getA().getConnections())) temp.getA().getConnections().add(temp); if (!uppC.lookforDuplicates(temp.getA(), temp.getB(), temp.getB().getConnections())) temp.getB().getConnections().add(temp); break; case NODE: // put it into given nodeofnode sav = object.get("ID").getAsInt(); ((CpsUpperNode) objDispatch.get(sav)).getNodeEdges().add(temp); break; case OLD: // same as above sav = object.get("ID").getAsInt(); ((CpsUpperNode) objDispatch.get(sav)).getOldEdges().add(temp); break; default: break; } if (object.get("connection").getAsBoolean() && !type.equals(EDGETYPE.CONNECTION)) { temp.getA().getConnections().add(temp); temp.getB().getConnections().add(temp); } } /** * Load a Unitgraph by Deserialization * * @param type * @param jsonElement * @param objDispatch * @param eleDispatch */ private void loadUnitGraph(GRAPHTYPE type, JsonElement jsonElement, HashMap objDispatch, HashMap eleDispatch) { // TODO Auto-generated method stub JsonObject object = jsonElement.getAsJsonObject(); List keys = getKeys(object); String p = null; int mid, x, y = 0; LinkedList graphpoint = new LinkedList<>(); int sav = 0; // foreach Point in the graph restore it for (String k : keys) { if (!k.equals("ID")) { p = object.get(k).getAsString(); mid = p.indexOf(':'); x = Integer.parseInt(p.substring(0, mid)); y = Integer.parseInt(p.substring(mid + 1, p.length())); graphpoint.add(new Point(x, y)); } else // else its an ID sav = object.get(k).getAsInt(); } switch (type) { case SWITCH: HolonSwitch sw = (HolonSwitch) objDispatch.get(sav); sw.setGraphPoints(graphpoint); break; case ELEMENT: HolonElement ele = eleDispatch.get(sav); ele.setGraphPoints(graphpoint); break; default: break; } } private void loadTracked(JsonElement jsonElement, HashMap objDispatch) { // TODO Auto-generated method stub JsonObject object = jsonElement.getAsJsonObject(); List keys = getKeys(object); for (String k : keys) { int id = object.get(k).getAsInt(); model.getTrackingObj().add(objDispatch.get(id)); model.addObjectsToGraphListeners(); if (objDispatch.get(id) instanceof HolonObject) { ((HolonObject) objDispatch.get(id)).updateTrackingInfo(); } } } /** * Initialize the Gson with wanted parameters */ private void initGson() { // TODO Auto-generated method stub GsonBuilder builder = new GsonBuilder(); builder.serializeNulls(); 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(); this.parser = new JsonParser(); } private File readArchive(String path, File src) throws IOException, ArchiveException { File tmp = Files.createTempDirectory("tmpHolon").toFile(); tmp.deleteOnExit(); InputStream input = new FileInputStream(src); ArchiveInputStream stream = new ArchiveStreamFactory().createArchiveInputStream(ArchiveStreamFactory.ZIP, input); ArchiveEntry entry = stream.getNextEntry(); while (entry != null) { // String entryName = checkOS(entry.getName()); File file = new File(tmp, entry.getName()); file.getParentFile().mkdirs(); OutputStream output = new FileOutputStream(file); IOUtils.copy(stream, output); output.close(); // file.createNewFile(); entry = stream.getNextEntry(); } stream.close(); input.close(); return tmp; } private String checkOS(String entryName) { // TODO Auto-generated method stub String os = System.getProperty("os.name").toLowerCase(); String ret = entryName; String partition = System.getProperty("user.home"); if (!ret.contains("HolonGUI")) return ret; if (os.contains("windows")) { ret = ret.replace("/", "\\"); ret = System.getProperty("user.home") + ret.substring(ret.indexOf("\\HolonGUI\\"), ret.length()); } if (os.contains("mac")) { // dosmth ret = ret.replace("\\", "/"); ret = System.getProperty("user.home") + ret.substring(ret.indexOf("/HolonGUI/"), ret.length()); } if (os.contains("linux")) { // dosmth ret = ret.replace("\\", "/"); ret = System.getProperty("user.home") + ret.substring(ret.indexOf("/HolonGUI/"), ret.length()); } if (os.contains("solaris")) { // dosmth } return ret; } /** * Init new Arrays which havent been serialized along the object * * @param obj */ public void initObjects(AbstractCpsObject obj) { obj.setConnections(new ArrayList()); obj.setTags(new ArrayList()); obj.setPseudoTags(new ArrayList()); if (obj instanceof HolonObject) { ((HolonObject) obj).setElements(new ArrayList()); ((HolonObject) obj).setEleIdx(new HashMap()); ((HolonObject) obj).setTrackingProd(new float[100]); ((HolonObject) obj).setTrackingCons(new float[100]); } if (obj instanceof HolonSwitch) { ((HolonSwitch) obj).setActiveAt(true); ((HolonSwitch) obj).setGraphPoints(new LinkedList()); } if (obj instanceof CpsUpperNode) { ((CpsUpperNode) obj).setNodes(new ArrayList()); ((CpsUpperNode) obj).setNodeEdges(new ArrayList()); ((CpsUpperNode) obj).setOldEdges(new ArrayList()); ((CpsUpperNode) obj).setNodesIdx(new HashMap()); } } /** * Init Elements * * @param ele */ public void initElements(HolonElement ele) { ele.setEnergyAt(ele.getEnergy()); ele.setGraphPoints(new LinkedList()); } /** * Init Edges * * @param edge */ public void initCpsEdge(CpsEdge edge) { edge.setTags(new ArrayList()); edge.setPseudoTag(new ArrayList()); edge.setA(null); edge.setB(null); } /** * Get Set of Keys * * @param json * @return */ public List getKeys(JsonObject json) { return json.entrySet().stream().map(i -> i.getKey()).collect(Collectors.toCollection(ArrayList::new)); } }