Save/Load

* implemented saving/loading of graphical graph
* fixed save/load graph
* fixed and improved tests
This commit is contained in:
2019-06-14 21:36:31 +02:00
parent e9f7375ca4
commit 1a06692f02
11 changed files with 231 additions and 77 deletions

View File

@@ -1,16 +1,18 @@
package berack96.sim.util.graph;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import berack96.sim.util.graph.models.GraphSaveStructure;
import berack96.sim.util.graph.visit.VisitInfo;
import berack96.sim.util.graph.visit.VisitStrategy;
@@ -548,22 +550,65 @@ public interface Graph<V, W extends Number> extends Iterable<V> {
*/
Map<V, List<Edge<V, W>>> distance(V source) throws NullPointerException, IllegalArgumentException;
/**
* Save the Graph passed as input to a file inserted as parameter.<br>
* The resulting file is a Json string representing all the graph.<br>
* If the directory for getting through the file do not exist,<br>
* then it is created.
*
* @param graph the graph to save
* @param file the name of the file
* @throws IOException for various reason that appear in the message, but the most common is that the file is not found.
*/
static void save(Graph<?, ?> graph, String file) throws IOException {
save(graph, "", file);
}
static <V, W extends Number> void save(Graph<V, W> graph, String other, String file) throws IOException {
GraphSaveStructure<V, W> save = new GraphSaveStructure<>(graph, other);
/**
* Save the Graph passed as input to a file inserted as parameter.<br>
* The resulting file is a Json string representing all the graph.<br>
* If the directory for getting through the file do not exist,<br>
* then it is created.<br>
* The additional parameter is used if you want to save other as well as the graph.
*
* @param graph the graph to save
* @param other other things to save
* @param file the name of the file
* @throws IOException for various reason that appear in the message, but the most common is that the file is not found.
*/
static void save(Graph<?, ?> graph, String other, String file) throws IOException {
GraphSaveStructure save = new GraphSaveStructure(graph, other);
int slash = file.lastIndexOf("\\");
if(slash == -1)
slash = file.lastIndexOf("/");
if(slash != -1) {
String dir = file.substring(0, slash);
File fDir = new File(dir);
fDir.mkdirs();
}
FileWriter writer = new FileWriter(file);
GSON.toJson(save, writer);
writer.close();
}
@SuppressWarnings("unchecked")
static <V, W extends Number> String load(Graph<V, W> graph, String file, Class<V> classV, Class<W> classW) throws IOException {
graph.removeAllVertex();
/**
* Load an already saved graph in an instance of a graph.
* Before loading the graph, it is emptied.
*
* @param <V> the parameter needed for the vertex
* @param <W> the parameter needed for the weight
* @param graph the graph to load with
* @param file the file where the graph is saved
* @param classV the class used for the Vertex
* @param classW the class used for the Weight
* @return the string saved in other, if any
* @throws IOException for any possible reason, the most common: the file doesn't exist
* @throws NullPointerException if the graph is null
* @throws JsonSyntaxException if the file is malformed or corrupted
*/
static <V, W extends Number> String load(Graph<V, W> graph, String file, Class<V> classV, Class<W> classW) throws IOException, NullPointerException, JsonSyntaxException {
FileReader reader = new FileReader(file);
StringBuilder fileContent = new StringBuilder();
int c;
@@ -571,55 +616,23 @@ public interface Graph<V, W extends Number> extends Iterable<V> {
while((c = reader.read()) != -1)
fileContent.append((char)c);
reader.close();
GraphSaveStructure<V, W> save = GSON.fromJson(fileContent.toString(), GraphSaveStructure.class);
GraphSaveStructure save = GSON.fromJson(fileContent.toString(), GraphSaveStructure.class);
graph.removeAllVertex();
for(String str : save.vertices)
graph.addVertex(GSON.fromJson(str, classV));
for(int i = 0; i<save.edges.src.size(); i++) {
V s = GSON.fromJson(save.edges.src.get(i), classV);
V d = GSON.fromJson(save.edges.dest.get(i), classV);
W w = GSON.fromJson(save.edges.weight.get(i), classW);
graph.addEdge(s, d, w);
}
for(int i = 0; i<save.edges.length; i++)
graph.addEdge(
GSON.fromJson(save.edges[i].src, classV),
GSON.fromJson(save.edges[i].dest, classV),
GSON.fromJson(save.edges[i].weight, classW));
/*
for(int i = 0; i<save.marks.length; i++)
graph.mark(GSON.fromJson(save.marks[i].vert, classV), save.marks[i].mark);
*/
return save.other;
}
class GraphSaveStructure<V, W extends Number> {
public GraphSaveStructure() {}
protected GraphSaveStructure(Graph<V, W> graph, String other) {
vertices = new LinkedList<>();
for(V v: graph.vertices())
vertices.add(GSON.toJson(v));
edges = new EdgeSaveStructure<>(graph.edges());
this.other = other;
}
public List<String> vertices;
public EdgeSaveStructure<V, W> edges;
public String other;
}
class EdgeSaveStructure<V, W extends Number> {
public EdgeSaveStructure() {}
protected EdgeSaveStructure(Collection<Edge<V, W>> edges) {
src = new LinkedList<>();
dest = new LinkedList<>();
weight = new LinkedList<>();
for(Edge<V, W> ed : edges) {
src.add(GSON.toJson(ed.getSource()));
dest.add(GSON.toJson(ed.getDestination()));
weight.add(GSON.toJson(ed.getWeight()));
}
}
public List<String> src;
public List<String> dest;
public List<String> weight;
}
// TODO maybe -> STATIC saveOnFile(orString) INSTANCE loadFromFile(orString), but need JSON parser
// TODO maybe, but i don't think so... STATIC DISTANCE V* -> V*
}

View File

@@ -0,0 +1,20 @@
package berack96.sim.util.graph.models;
/**
* Support class used for saving a Graph in a file.
*
* @author Berack96
*
*/
public class EdgeSaveStructure {
public EdgeSaveStructure() {}
protected EdgeSaveStructure(String s, String d, String w) {
this.src = s;
this.dest = d;
this.weight = w;
}
public String src;
public String dest;
public String weight;
}

View File

@@ -0,0 +1,41 @@
package berack96.sim.util.graph.models;
import berack96.sim.util.graph.Edge;
import berack96.sim.util.graph.Graph;
/**
* Support class used for saving a Graph in a file.
*
* @author Berack96
*
*/
public class GraphSaveStructure {
public GraphSaveStructure() {}
public GraphSaveStructure(Graph<?, ?> graph, String other) {
this.vertices = new String[graph.numberOfVertices()];
int i = 0;
for(Object o: graph.vertices()) {
this.vertices[i] = Graph.GSON.toJson(o);
i++;
}
this.edges = new EdgeSaveStructure[graph.numberOfEdges()];
i = 0;
for (Edge<?, ?> edge : graph.edges()) {
this.edges[i] = new EdgeSaveStructure(
Graph.GSON.toJson(edge.getSource()),
Graph.GSON.toJson(edge.getDestination()),
Graph.GSON.toJson(edge.getWeight())
);
i++;
}
this.other = other;
}
public String[] vertices;
public EdgeSaveStructure[] edges;
//public MarkSaveStructure[] marks;
public String other;
}

View File

@@ -0,0 +1,18 @@
package berack96.sim.util.graph.models;
/**
* Support class used for saving a Graph in a file.
*
* @author Berack96
*
*/
public class MarkSaveStructure {
public MarkSaveStructure() {}
protected MarkSaveStructure(String v, Object m) {
this.vert = v;
this.mark = m;
}
public String vert;
public Object mark;
}

View File

@@ -153,7 +153,6 @@ public class GraphInfo<V, W extends Number> extends JPanel {
graphPanel.save(fileText.getText());
textResult.setText("");
} catch (IOException e1) {
e1.printStackTrace();
textResult.setText(e1.getMessage());
}
});
@@ -163,7 +162,6 @@ public class GraphInfo<V, W extends Number> extends JPanel {
graphPanel.load(fileText.getText());
textResult.setText("");
} catch (IOException e1) {
e1.printStackTrace();
textResult.setText(e1.getMessage());
}
});

View File

@@ -31,6 +31,8 @@ public class GraphPanel<V, W extends Number> extends Component {
private static final long serialVersionUID = 1L;
private final GraphicalView<VertexComponent<V>> vertexRender;
private final GraphicalView<EdgeComponent<V, W>> edgeRender;
private final Class<V> classV;
private final Class<W> classW;
private final Container vertices = new Container();
private final Container edges = new Container();
@@ -40,9 +42,11 @@ public class GraphPanel<V, W extends Number> extends Component {
private GraphListener old = null;
public GraphPanel(GraphicalView<VertexComponent<V>> vertexRender, GraphicalView<EdgeComponent<V, W>> edgeRender) {
public GraphPanel(GraphicalView<VertexComponent<V>> vertexRender, GraphicalView<EdgeComponent<V, W>> edgeRender, Class<V> classV, Class<W> classW) {
this.vertexRender = vertexRender;
this.edgeRender = edgeRender;
this.classV = classV;
this.classW = classW;
}
public Graph<V, W> getGraph() {
@@ -166,17 +170,19 @@ public class GraphPanel<V, W extends Number> extends Component {
}
public void load(String fileName) throws IOException {
String saveContent = Graph.load(graph, fileName);
String saveContent = Graph.load(graph, fileName, classV, classW);
GraphGraphicalSave save = Graph.GSON.fromJson(saveContent, GraphGraphicalSave.class);
vertices.removeAll();
edges.removeAll();
for(int i = 0; i<save.vertices.size(); i++) {
V v = save.vertices.get(i);
Point p = save.points.get(i);
for(int i = 0; i<save.vertices.length; i++) {
V v = Graph.GSON.fromJson(save.vertices[i], classV);
Point p = save.points[i];
addVertex(p, v);
}
save.vertices.forEach(v -> graph.getEdgesOut(v).forEach(e -> addEdge(e)));
for(String v : save.vertices)
graph.getEdgesOut(Graph.GSON.fromJson(v, classV)).forEach(e -> addEdge(e));
repaint();
}
@@ -226,16 +232,34 @@ public class GraphPanel<V, W extends Number> extends Component {
class GraphGraphicalSave {
public GraphGraphicalSave() {}
protected GraphGraphicalSave(Container vertices) {
this.vertices = new LinkedList<>();
this.points = new LinkedList<>();
List<String> v = new LinkedList<>();
List<Point> p = new LinkedList<>();
for(Component vertex : vertices.getComponents()) {
this.points.add(new Point(vertex.getX(), vertex.getY()));
this.vertices.add(((VertexComponent<V>) vertex).vertex.getValue());
Point temp = new Point(vertex.getX(), vertex.getY());
temp.x += vertex.getWidth() / 2;
temp.y += vertex.getHeight() / 2;
p.add(temp);
v.add(Graph.GSON.toJson(((VertexComponent<V>) vertex).vertex.getValue()));
}
int i = 0;
this.vertices = new String[v.size()];
for(String s : v) {
this.vertices[i] = s;
i++;
}
i = 0;
this.points = new Point[p.size()];
for(Point pt : p) {
this.points[i] = pt;
i++;
}
}
public List<V> vertices;
public List<Point> points;
public String[] vertices;
public Point[] points;
}
}

View File

@@ -23,7 +23,7 @@ public class GraphWindow<V, W extends Number> extends JFrame {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
GraphPanel<Integer, Integer> panel = new GraphPanel<>(new VertexView<>(), new EdgeView<>());
GraphPanel<Integer, Integer> panel = new GraphPanel<>(new VertexView<>(), new EdgeView<>(), Integer.class, Integer.class);
GraphWindow<Integer, Integer> win = new GraphWindow<>(panel, new VertexIntListener(panel), new EdgeIntListener<>(panel));
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); // full screen
dim.setSize(dim.width / 2, dim.height / 2);

View File

@@ -9,7 +9,8 @@ import java.awt.*;
* @author Berack96
*/
public interface GraphicalView<O> {
/**
/**
* Box where the object is sensible at listeners (like Hitbox)
*
* @param obj the object to draw
@@ -17,7 +18,7 @@ public interface GraphicalView<O> {
* @return a rectangle where the object is sensible to the listeners
*/
Rectangle getBox(O obj, Point center);
/**
* The paint function, aka the part where you can draw things (like Mesh)
*