From 6cd7a4897aa0b9ecca8a97e761476a00d0917090 Mon Sep 17 00:00:00 2001 From: Dimitris Anyfadakis Date: Mon, 1 Apr 2024 19:41:48 +0200 Subject: [PATCH] Add functionality to view the SVG diagram of PlantUML --- pom.xml | 5 + src/main/java/controller/Controller.java | 64 ++++++----- src/main/java/controller/ControllerType.java | 12 +- .../java/controller/DiagramController.java | 6 + .../java/manager/ClassDiagramManager.java | 35 +++--- src/main/java/manager/DiagramManager.java | 7 ++ .../java/manager/PackageDiagramManager.java | 19 +++- src/main/java/manager/SourceProject.java | 2 +- src/main/java/model/diagram/ClassDiagram.java | 9 +- .../diagram/GraphClassDiagramConverter.java | 6 +- .../diagram/GraphPackageDiagramConverter.java | 6 +- .../java/model/diagram/PackageDiagram.java | 11 +- .../java/model/diagram/ShadowCleaner.java | 24 ++-- .../ClassDiagramArrangementManager.java | 23 ++-- .../DiagramArrangementManager.java | 33 ++++++ .../DiagramArrangementManagerInterface.java | 29 ----- .../PackageDiagramArrangementManager.java | 12 +- .../AdvancedFruchtermanReingold.java | 11 +- .../algorithms/AdvancedSpring.java | 21 +--- .../algorithms/FruchtermanReingold.java | 21 +--- .../arrangement/algorithms/KamadaKawai.java | 21 +--- .../algorithms/LayoutAlgorithm.java | 8 +- .../algorithms/LayoutAlgorithmType.java | 16 ++- .../arrangement/algorithms/Spring.java | 31 ++---- .../arrangement/algorithms/Sugiyama.java | 60 ++++------ .../arrangement/geometry/DiagramGeometry.java | 16 +-- .../exportation/CoordinatesUpdater.java | 14 +-- .../GraphMLClassDiagramExporter.java | 2 +- .../GraphMLPackageDiagramExporter.java | 2 +- .../PlantUMLClassDiagramImageExporter.java | 8 +- .../PlantUMLClassDiagramTextExporter.java | 3 +- .../PlantUMLPackageDiagramImageExporter.java | 14 +-- .../PlantUMLPackageDiagramTextExporter.java | 8 +- .../graphml/GraphMLClassifierVertex.java | 14 +-- .../graphml/GraphMLClassifierVertexArc.java | 3 +- .../graphml/GraphMLPackageVertexArc.java | 4 +- .../model/diagram/graphml/GraphMLSyntax.java | 2 +- .../diagram/graphml/GraphMLSyntaxIds.java | 1 + .../javafx/JavaFXClassVisualization.java | 6 +- .../javafx/JavaFXPackageDiagramLoader.java | 10 +- .../javafx/JavaFXPackageVisualization.java | 18 +-- .../plantuml/PlantUMLClassifierVertex.java | 52 ++++----- .../plantuml/PlantUMLClassifierVertexArc.java | 19 ++-- .../plantuml/PlantUMLPackageVertex.java | 5 +- .../plantuml/PlantUMLPackageVertexArc.java | 17 ++- .../diagram/svg/PlantUMLClassDiagram.java | 61 ++++++++++ .../diagram/svg/PlantUMLPackageDiagram.java | 86 +++++++++++++++ src/main/java/model/graph/ModifierType.java | 11 +- src/main/java/model/graph/VertexType.java | 9 +- src/main/java/parser/Interpreter.java | 104 +++++++++--------- src/main/java/parser/PackageNodeCleaner.java | 12 +- .../parser/factory/ProjectParserFactory.java | 3 +- src/main/java/parser/tree/LeafNode.java | 4 +- src/main/java/view/DiagramCreation.java | 51 ++++++--- .../java/view/DiagramCreationController.java | 9 +- src/main/java/view/DiagramVisualization.java | 67 ++++++++++- .../view/DiagramVisualizationController.java | 9 +- .../resources/fxml/DiagramCreationView.fxml | 5 + .../java/manager/ClassDiagramManagerTest.java | 4 +- .../model/GraphClassDiagramConverterTest.java | 11 +- .../GraphMLClassDiagramExporterTest.java | 4 +- .../JavaFXPackageDiagramExporterTest.java | 47 ++++---- ...PlantUMLClassDiagramImageExporterTest.java | 81 ++++++++++---- .../PlantUMLClassDiagramSvgTest.java | 48 ++++++++ .../PlantUMLClassDiagramTextExporterTest.java | 33 +++--- .../PlantUMLPackageDiagramSvgTest.java | 63 +++++++++++ src/test/java/parser/FileVisitorTest.java | 8 +- src/test/java/parser/InterpreterTest.java | 64 +++++------ 68 files changed, 889 insertions(+), 615 deletions(-) create mode 100644 src/main/java/model/diagram/arrangement/DiagramArrangementManager.java delete mode 100644 src/main/java/model/diagram/arrangement/DiagramArrangementManagerInterface.java create mode 100644 src/main/java/model/diagram/svg/PlantUMLClassDiagram.java create mode 100644 src/main/java/model/diagram/svg/PlantUMLPackageDiagram.java create mode 100644 src/test/java/model/exportation/PlantUMLClassDiagramSvgTest.java create mode 100644 src/test/java/model/exportation/PlantUMLPackageDiagramSvgTest.java diff --git a/pom.xml b/pom.xml index bde2e0b..0324407 100644 --- a/pom.xml +++ b/pom.xml @@ -130,6 +130,11 @@ maven-assembly-plugin 3.6.0 + + org.apache.xmlgraphics + batik-all + 1.17 + diff --git a/src/main/java/controller/Controller.java b/src/main/java/controller/Controller.java index a53747e..02670ed 100644 --- a/src/main/java/controller/Controller.java +++ b/src/main/java/controller/Controller.java @@ -1,6 +1,7 @@ package controller; import com.brunomnsilva.smartgraph.graphview.SmartGraphPanel; +import manager.DiagramManager; import manager.SourceProject; import java.io.File; @@ -11,24 +12,23 @@ public interface Controller { /** - * This method creates the tree of the project by calling the DiagramManager's createTree method. + * This method creates the tree of the project by calling {@link DiagramManager#createSourceProject(Path)}. * * @param sourcePackagePath the project's source package path - * @return the SourceProject created + * @return the {@link SourceProject} created. */ SourceProject createTree(Path sourcePackagePath); /** - * This method converts the created tree to a diagram, by creating the corresponding DiagramManager - * based on the type of the graph, i.e. package or class and then calling the createDiagram - * method of the DiagramManager. + * This method converts the created tree to a diagram, + * by calling {@link DiagramManager#convertTreeToDiagram(List)} with the given arguments. * - * @param chosenFileNames the names of the files selected by the designer to be included in the diagram + * @param chosenFileNames the names of the files selected by the designer to be included in the diagram. */ void convertTreeToDiagram(List chosenFileNames); /** - * This method arranges the diagram by calling the DiagramManager's arrangeDiagram method. + * This method arranges the diagram by calling the {@link DiagramManager#arrangeDiagram()}. */ void arrangeDiagram(); @@ -39,59 +39,69 @@ public interface Controller SmartGraphPanel applySpecificLayout(String choice); /** - * This method exports the diagram to a GraphML file by calling - * the DiagramManager's exportDiagramToGraphML method. + * This method exports the diagram to a GraphML file + * by calling {@link DiagramManager#exportDiagramToGraphML(Path)}. * - * @param graphMLSavePath the selected path by the designer where the diagram will be saved - * @return the created File in which the diagram was saved + * @param graphMLSavePath the selected path by the designer where the diagram will be saved. + * @return the created File in which the diagram was saved. */ File exportDiagramToGraphML(Path graphMLSavePath); /** - * This method saves the diagram to a text file by calling the DiagramManager's saveDiagram method. + * This method saves the diagram to a text file + * by calling {@link DiagramManager#saveDiagram(Path)}. * - * @param graphSavePath the selected path by the designer where the diagram will be saved - * @return the created File in which the diagram was saved + * @param graphSavePath the selected path by the designer where the diagram will be saved. + * @return the created File in which the diagram was saved. */ File saveDiagram(Path graphSavePath); /** - * This method loads a diagram from a text file by calling the DiagramManager's loadDiagram method. + * This method loads a diagram from a text file + * by calling {@link DiagramManager#loadDiagram(Path)}. * - * @param graphSavePath the file's path where the diagram is saved + * @param graphSavePath the file's path where the diagram is saved. */ void loadDiagram(Path graphSavePath); /** - * This method creates the JavaFX graphView by calling the DiagramManager's visualizeJavaFXGraph method. + * This method creates the JavaFX graphView + * by calling {@link DiagramManager#visualizeJavaFXGraph()}. * - * @return the created graphView {@link SmartGraphPanel} + * @return the created graphView {@link SmartGraphPanel}. */ SmartGraphPanel visualizeJavaFXGraph(); /** - * This method creates the loaded Diagram's JavaFX graphView by calling - * the DiagramManager's visualizeLoadedJavaFXGraph method. + * // TODO: Write a Javadoc when this is done. + * @param dpi the dpi of the screen? + * @return + */ + String visualizeSvgGraph(int dpi); + + /** + * This method creates the loaded Diagram's JavaFX graphView + * by calling {@link DiagramManager#visualizeJavaFXGraph()}. * - * @return the created graphView + * @return the created {@link SmartGraphPanel}. */ SmartGraphPanel visualizeLoadedJavaFXGraph(); /** - * This method exports the diagram as an image with the help of PlantUML by calling - * the DiagramManager's exportPlantUMLDiagram method. + * This method exports the diagram as an image with the help of PlantUML + * by calling {@link DiagramManager#exportPlantUMLImage(Path)}. * * @param graphSavePath the selected path by the designer where the diagram's image will be saved - * @return the created PlantUML diagram + * @return the exported PlantUML diagram. */ File exportPlantUMLDiagram(Path graphSavePath); /** - * This method saves the PlantUML code to a text file by calling - * the DiagramManager's exportPlantUMLText method. + * This method saves the PlantUML code to a text file + * by calling {@link DiagramManager#exportPlantUMLText(Path)}}. * * @param textSavePath the selected path by the designer where the text file will be saved - * @return the created PlantUML text file + * @return the exported PlantUML text file. */ File exportPlantUMLText(Path textSavePath); diff --git a/src/main/java/controller/ControllerType.java b/src/main/java/controller/ControllerType.java index 3a8891e..b83ee5e 100644 --- a/src/main/java/controller/ControllerType.java +++ b/src/main/java/controller/ControllerType.java @@ -1,8 +1,8 @@ package controller; -import java.util.Collections; -import java.util.HashMap; +import java.util.Arrays; import java.util.Map; +import java.util.stream.Collectors; public enum ControllerType { @@ -12,12 +12,8 @@ public enum ControllerType static { - Map map = new HashMap<>(); - for (ControllerType controllerType : ControllerType.values()) - { - map.put(controllerType.toString().toLowerCase(), controllerType); - } - CONTROLLER_TYPE = Collections.unmodifiableMap(map); + CONTROLLER_TYPE = Arrays.stream(ControllerType.values()) + .collect(Collectors.toMap(ControllerType::toString, controllerType -> controllerType)); } public static ControllerType get(String controllerType) diff --git a/src/main/java/controller/DiagramController.java b/src/main/java/controller/DiagramController.java index 2c5d7af..f19c143 100644 --- a/src/main/java/controller/DiagramController.java +++ b/src/main/java/controller/DiagramController.java @@ -74,6 +74,12 @@ public SmartGraphPanel visualizeJavaFXGraph() return diagramManager.visualizeJavaFXGraph(); } + @Override + public String visualizeSvgGraph(int dpi) + { + return diagramManager.visualizeSvgGraph(dpi); + } + @Override public SmartGraphPanel visualizeLoadedJavaFXGraph() { diff --git a/src/main/java/manager/ClassDiagramManager.java b/src/main/java/manager/ClassDiagramManager.java index 83d6548..af3d80f 100644 --- a/src/main/java/manager/ClassDiagramManager.java +++ b/src/main/java/manager/ClassDiagramManager.java @@ -5,7 +5,7 @@ import model.diagram.ClassDiagram; import model.diagram.ShadowCleaner; import model.diagram.arrangement.ClassDiagramArrangementManager; -import model.diagram.arrangement.DiagramArrangementManagerInterface; +import model.diagram.arrangement.DiagramArrangementManager; import model.diagram.arrangement.geometry.DiagramGeometry; import model.diagram.exportation.CoordinatesUpdater; import model.diagram.exportation.DiagramExporter; @@ -16,6 +16,7 @@ import model.diagram.javafx.JavaFXClassDiagramLoader; import model.diagram.javafx.JavaFXClassVisualization; import model.diagram.javafx.JavaFXVisualization; +import model.diagram.svg.PlantUMLClassDiagram; import org.javatuples.Pair; import java.io.File; @@ -27,7 +28,7 @@ public class ClassDiagramManager implements DiagramManager { private ClassDiagram classDiagram; - private DiagramArrangementManagerInterface classDiagramArrangement; + private DiagramArrangementManager classDiagramArrangement; private Collection> vertexCollection; private SmartGraphPanel graphView; @@ -76,6 +77,14 @@ public SmartGraphPanel visualizeJavaFXGraph() } + @Override + public String visualizeSvgGraph(int dpi) + { + PlantUMLClassDiagram plantUMLClassDiagram = new PlantUMLClassDiagram(classDiagram); + return plantUMLClassDiagram.toSvg(dpi); + } + + @Override public SmartGraphPanel visualizeLoadedJavaFXGraph() { @@ -137,21 +146,13 @@ public void loadDiagram(Path graphSavePath) } - public ClassDiagram getClassDiagram() - { - return classDiagram; - } - @Override public SmartGraphPanel applyLayout() { DiagramGeometry nodesGeometry = classDiagram.getDiagramGeometry(); for (Vertex vertex : vertexCollection) { - if (!nodesGeometry.containsKey(vertex.element())) - { - continue; - } + if (!nodesGeometry.containsKey(vertex.element())) continue; Pair coordinates = nodesGeometry.getVertexGeometry(vertex.element()); graphView.setVertexPosition(vertex, coordinates.getValue0(), coordinates.getValue1()); @@ -163,13 +164,10 @@ public SmartGraphPanel applyLayout() @Override public SmartGraphPanel applySpecificLayout(String choice) { - DiagramGeometry nodesGeometry = classDiagramArrangement.applyNewLayout(choice); + DiagramGeometry nodesGeometry = classDiagramArrangement.applyLayout(choice); for (Vertex vertex : vertexCollection) { - if (!nodesGeometry.containsKey(vertex.element())) - { - continue; - } + if (!nodesGeometry.containsKey(vertex.element())) continue; Pair coordinates = nodesGeometry.getVertexGeometry(vertex.element()); graphView.setVertexPosition(vertex, @@ -180,4 +178,9 @@ public SmartGraphPanel applySpecificLayout(String choice) return graphView; } + public ClassDiagram getClassDiagram() + { + return classDiagram; + } + } diff --git a/src/main/java/manager/DiagramManager.java b/src/main/java/manager/DiagramManager.java index acd3fb7..bc9c46b 100644 --- a/src/main/java/manager/DiagramManager.java +++ b/src/main/java/manager/DiagramManager.java @@ -70,6 +70,13 @@ public interface DiagramManager */ SmartGraphPanel visualizeJavaFXGraph(); + /** + * TODO: Add Javadoc when this is done. + * @param dpi the screen's dpi? + * @return + */ + String visualizeSvgGraph(int dpi); + /** * This method is responsible for exporting the diagram to a PlantUML image diagram. * diff --git a/src/main/java/manager/PackageDiagramManager.java b/src/main/java/manager/PackageDiagramManager.java index f615aa1..dc21ae2 100644 --- a/src/main/java/manager/PackageDiagramManager.java +++ b/src/main/java/manager/PackageDiagramManager.java @@ -4,7 +4,7 @@ import com.brunomnsilva.smartgraph.graphview.SmartGraphPanel; import com.google.gson.JsonParseException; import model.diagram.PackageDiagram; -import model.diagram.arrangement.DiagramArrangementManagerInterface; +import model.diagram.arrangement.DiagramArrangementManager; import model.diagram.arrangement.PackageDiagramArrangementManager; import model.diagram.arrangement.geometry.DiagramGeometry; import model.diagram.exportation.CoordinatesUpdater; @@ -16,6 +16,7 @@ import model.diagram.javafx.JavaFXPackageDiagramLoader; import model.diagram.javafx.JavaFXPackageVisualization; import model.diagram.javafx.JavaFXVisualization; +import model.diagram.svg.PlantUMLPackageDiagram; import org.javatuples.Pair; import java.io.File; @@ -30,9 +31,9 @@ public class PackageDiagramManager implements DiagramManager private static final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); - private PackageDiagram packageDiagram; - private DiagramArrangementManagerInterface packageDiagramArrangement; - private Collection> vertexCollection; + private PackageDiagram packageDiagram; + private DiagramArrangementManager packageDiagramArrangement; + private Collection> vertexCollection; private SmartGraphPanel graphView; @@ -78,6 +79,14 @@ public SmartGraphPanel visualizeJavaFXGraph() } + @Override + public String visualizeSvgGraph(int dpi) + { + PlantUMLPackageDiagram plantUMLPackageDiagram = new PlantUMLPackageDiagram(packageDiagram); + return plantUMLPackageDiagram.toSvg(dpi); + } + + @Override public SmartGraphPanel visualizeLoadedJavaFXGraph() { @@ -163,7 +172,7 @@ public SmartGraphPanel applyLayout() @Override public SmartGraphPanel applySpecificLayout(String choice) { - DiagramGeometry nodesGeometry = packageDiagramArrangement.applyNewLayout(choice); + DiagramGeometry nodesGeometry = packageDiagramArrangement.applyLayout(choice); for (Vertex vertex : vertexCollection) { if (!nodesGeometry.containsKey(vertex.element())) diff --git a/src/main/java/manager/SourceProject.java b/src/main/java/manager/SourceProject.java index 94edec1..a0b982f 100644 --- a/src/main/java/manager/SourceProject.java +++ b/src/main/java/manager/SourceProject.java @@ -30,7 +30,7 @@ public void createPackageGraph(Path sourcePackagePath, } // Only used for testing. - // TODO remove it completely. + // TODO: remove it completely. protected Interpreter getInterpreter() { return interpreter; diff --git a/src/main/java/model/diagram/ClassDiagram.java b/src/main/java/model/diagram/ClassDiagram.java index c51870c..c552290 100644 --- a/src/main/java/model/diagram/ClassDiagram.java +++ b/src/main/java/model/diagram/ClassDiagram.java @@ -62,13 +62,10 @@ private List getChosenNodes(List chosenClassesNames) Optional optionalSinkVertex = sinkVertices .values() .stream() - .filter(sinkVertex -> sinkVertex.getName().equals(chosenClass)) + .filter(it -> it.getName().equals(chosenClass)) .findFirst(); - if (optionalSinkVertex.isEmpty()) - { - continue; - } - chosenClasses.add(optionalSinkVertex.get()); + + optionalSinkVertex.ifPresent(chosenClasses::add); } return chosenClasses; } diff --git a/src/main/java/model/diagram/GraphClassDiagramConverter.java b/src/main/java/model/diagram/GraphClassDiagramConverter.java index 1afe767..92c3df4 100644 --- a/src/main/java/model/diagram/GraphClassDiagramConverter.java +++ b/src/main/java/model/diagram/GraphClassDiagramConverter.java @@ -29,10 +29,8 @@ public Map>> convertGraphToClassDiag adjacencyList.put(classifierVertex, new HashSet<>()); for (Arc arc : classifierVertex.getArcs()) { - if (!sinkVertices.contains(arc.targetVertex())) - { - continue; - } + if (!sinkVertices.contains(arc.targetVertex())) continue; + adjacencyList.get(arc.sourceVertex()).add(arc); } } diff --git a/src/main/java/model/diagram/GraphPackageDiagramConverter.java b/src/main/java/model/diagram/GraphPackageDiagramConverter.java index 1ae36db..aba613b 100644 --- a/src/main/java/model/diagram/GraphPackageDiagramConverter.java +++ b/src/main/java/model/diagram/GraphPackageDiagramConverter.java @@ -29,10 +29,8 @@ public Map>> convertGraphToPackageDiagram( adjacencyList.put(vertex, new HashSet<>()); for (Arc arc : vertex.getArcs()) { - if (!vertices.contains(arc.targetVertex())) - { - continue; - } + if (!vertices.contains(arc.targetVertex())) continue; + adjacencyList.get(arc.sourceVertex()).add(arc); } } diff --git a/src/main/java/model/diagram/PackageDiagram.java b/src/main/java/model/diagram/PackageDiagram.java index 7743dcc..5d666af 100644 --- a/src/main/java/model/diagram/PackageDiagram.java +++ b/src/main/java/model/diagram/PackageDiagram.java @@ -43,8 +43,7 @@ private void createGraphNodes(List chosenFileNames) int nodeId = 0; for (PackageVertex vertex : getChosenNodes(chosenFileNames)) { - graphNodes.put(vertex, nodeId); - nodeId++; + graphNodes.put(vertex, nodeId++); } } @@ -56,12 +55,10 @@ public List getChosenNodes(List chosenPackagesNames) { Optional vertex = vertices.values() .stream() - .filter(vertex1 -> vertex1.getName().equals(chosenPackage)) + .filter(it -> it.getName().equals(chosenPackage)) .findFirst(); - if (vertex.isEmpty()) - { - continue; - } + if (vertex.isEmpty()) continue; + chosenPackages.add(vertex.get()); } return chosenPackages; diff --git a/src/main/java/model/diagram/ShadowCleaner.java b/src/main/java/model/diagram/ShadowCleaner.java index 8982418..ad2c1c0 100644 --- a/src/main/java/model/diagram/ShadowCleaner.java +++ b/src/main/java/model/diagram/ShadowCleaner.java @@ -37,16 +37,12 @@ public Map>> shadowWeakRelationships for (Map.Entry>> arc : shadowedArcs.entrySet()) { - if (!(arc.getValue().size() > 1)) - { - continue; - } + if (!(arc.getValue().size() > 1)) continue; + for (ArcType arcType : strongerToWeakerArcTypes) { - if (!doesStrongerRelationshipExist(arc.getValue(), arcType)) - { - continue; - } + if (!doesStrongerRelationshipExist(arc.getValue(), arcType)) continue; + removeWeakerRelationships(arcs, arc.getKey(), arcType); break; } @@ -60,11 +56,8 @@ public Map>> shadowWeakRelationships private boolean doesStrongerRelationshipExist(List> arc, ArcType arcType) { - Optional> inheritanceArc = arc - .stream() - .filter(sinkVertexArc -> sinkVertexArc.arcType().equals(arcType)) - .findFirst(); - return inheritanceArc.isPresent(); + return arc.stream() + .anyMatch(it -> it.arcType().equals(arcType)); } @@ -72,8 +65,7 @@ private void removeWeakerRelationships(Set> arcs, ClassifierVertex classifierVertex, ArcType arcType) { - arcs.removeIf(arc -> - arc.targetVertex().equals(classifierVertex) && - !arc.arcType().equals(arcType)); + arcs.removeIf(it -> it.targetVertex().equals(classifierVertex) && + !it.arcType().equals(arcType)); } } diff --git a/src/main/java/model/diagram/arrangement/ClassDiagramArrangementManager.java b/src/main/java/model/diagram/arrangement/ClassDiagramArrangementManager.java index 764c130..9af5e2c 100644 --- a/src/main/java/model/diagram/arrangement/ClassDiagramArrangementManager.java +++ b/src/main/java/model/diagram/arrangement/ClassDiagramArrangementManager.java @@ -14,19 +14,19 @@ import model.graph.ClassifierVertex; import org.javatuples.Pair; -import java.awt.*; +import java.awt.Dimension; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; -public class ClassDiagramArrangementManager implements DiagramArrangementManagerInterface +public class ClassDiagramArrangementManager implements DiagramArrangementManager { - public static final LayoutAlgorithmType LAYOUT_ALGORITHM_TYPE = LayoutAlgorithmType.SUGIYAMA; - public static final int WIDTH = 1500; - public static final int HEIGHT = 1000; + public static final LayoutAlgorithmType DEFAULT_LAYOUT_ALGORITHM = LayoutAlgorithmType.SUGIYAMA; + public static final int HEIGHT = 1500; + public static final int WIDTH = 1000; private final ClassDiagram classDiagram; private final Graph graph; @@ -57,19 +57,17 @@ public Map> arrangeGraphMLDiagram() @Override public DiagramGeometry arrangeDiagram() { - LayoutAlgorithm layoutAlgorithm = LayoutAlgorithmFactory.createLayoutAlgorithm(LAYOUT_ALGORITHM_TYPE); - layoutAlgorithm.setGraph(graph); - return layoutAlgorithm.arrangeDiagram(); + LayoutAlgorithm layoutAlgorithm = LayoutAlgorithmFactory.createLayoutAlgorithm(DEFAULT_LAYOUT_ALGORITHM); + return layoutAlgorithm.arrangeDiagram(graph); } @Override - public DiagramGeometry applyNewLayout(String algorithmType) + public DiagramGeometry applyLayout(String algorithmType) { LayoutAlgorithmType algorithmEnumType = LayoutAlgorithmType.get(algorithmType); LayoutAlgorithm layout = LayoutAlgorithmFactory.createLayoutAlgorithm(algorithmEnumType); - layout.setGraph(graph); - return layout.arrangeDiagram(); + return layout.arrangeDiagram(graph); } @@ -117,7 +115,8 @@ private Graph createGraphWithStrings() { graph.addEdge(arc.sourceVertex().getName() + " " + arc.targetVertex().getName(), arc.sourceVertex().getName(), - arc.targetVertex().getName(), EdgeType.DIRECTED); + arc.targetVertex().getName(), + EdgeType.DIRECTED); } return graph; diff --git a/src/main/java/model/diagram/arrangement/DiagramArrangementManager.java b/src/main/java/model/diagram/arrangement/DiagramArrangementManager.java new file mode 100644 index 0000000..607988d --- /dev/null +++ b/src/main/java/model/diagram/arrangement/DiagramArrangementManager.java @@ -0,0 +1,33 @@ +package model.diagram.arrangement; + +import edu.uci.ics.jung.graph.Graph; +import model.diagram.arrangement.algorithms.LayoutAlgorithmType; +import org.javatuples.Pair; + +import model.diagram.arrangement.geometry.DiagramGeometry; + +import java.util.Map; + +public interface DiagramArrangementManager +{ + + /** + * This method is responsible for the arrangement of the GraphML graph. + * It creates a {@link Graph} graph using the SpringLayout algorithm. + * + * @return a Map with the nodes' ids as it keys and geometry(x,y) as it values. + */ + Map> arrangeGraphMLDiagram(); + + /** + * This method is responsible for the arrangement of the graph. + * It creates a {@link Graph} graph using different algorithms, see {@link LayoutAlgorithmType}. + * + * @return a {@link DiagramGeometry} object that represents the diagram's geometry. + */ + DiagramGeometry arrangeDiagram(); + + // TODO JavaDoc + DiagramGeometry applyLayout(String choice); + +} diff --git a/src/main/java/model/diagram/arrangement/DiagramArrangementManagerInterface.java b/src/main/java/model/diagram/arrangement/DiagramArrangementManagerInterface.java deleted file mode 100644 index f085df5..0000000 --- a/src/main/java/model/diagram/arrangement/DiagramArrangementManagerInterface.java +++ /dev/null @@ -1,29 +0,0 @@ -package model.diagram.arrangement; - -import org.javatuples.Pair; - -import model.diagram.arrangement.geometry.DiagramGeometry; - -import java.util.Map; - -public interface DiagramArrangementManagerInterface -{ - - /** - * This method is responsible for the arrangement of the graph by creating a graph of the Jung library and using the SpringLayout algorithm. - * - * @return a Map with the nodes' id as key and geometry(x,y) as value - */ - Map> arrangeGraphMLDiagram(); - - /** - * This method is responsible for the arrangement of the graph by creating a graph of the Jung library and using different layout algorithms. - * - * @return a {@link DiagramGeometry} object which represents the diagram's geometry - */ - DiagramGeometry arrangeDiagram(); - - // TODO JavaDoc - DiagramGeometry applyNewLayout(String choice); - -} diff --git a/src/main/java/model/diagram/arrangement/PackageDiagramArrangementManager.java b/src/main/java/model/diagram/arrangement/PackageDiagramArrangementManager.java index c67a414..45e007e 100644 --- a/src/main/java/model/diagram/arrangement/PackageDiagramArrangementManager.java +++ b/src/main/java/model/diagram/arrangement/PackageDiagramArrangementManager.java @@ -14,14 +14,14 @@ import model.graph.PackageVertex; import org.javatuples.Pair; -import java.awt.*; +import java.awt.Dimension; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; -public class PackageDiagramArrangementManager implements DiagramArrangementManagerInterface +public class PackageDiagramArrangementManager implements DiagramArrangementManager { public static final LayoutAlgorithmType LAYOUT_ALGORITHM_TYPE = LayoutAlgorithmType.SUGIYAMA; @@ -58,18 +58,16 @@ public Map> arrangeGraphMLDiagram() public DiagramGeometry arrangeDiagram() { LayoutAlgorithm layoutAlgorithm = LayoutAlgorithmFactory.createLayoutAlgorithm(LAYOUT_ALGORITHM_TYPE); - layoutAlgorithm.setGraph(graph); - return layoutAlgorithm.arrangeDiagram(); + return layoutAlgorithm.arrangeDiagram(graph); } @Override - public DiagramGeometry applyNewLayout(String algorithmType) + public DiagramGeometry applyLayout(String algorithmType) { LayoutAlgorithmType algorithmEnumType = LayoutAlgorithmType.get(algorithmType); LayoutAlgorithm layout = LayoutAlgorithmFactory.createLayoutAlgorithm(algorithmEnumType); - layout.setGraph(graph); - return layout.arrangeDiagram(); + return layout.arrangeDiagram(graph); } diff --git a/src/main/java/model/diagram/arrangement/algorithms/AdvancedFruchtermanReingold.java b/src/main/java/model/diagram/arrangement/algorithms/AdvancedFruchtermanReingold.java index fb2599c..1e9f4b1 100644 --- a/src/main/java/model/diagram/arrangement/algorithms/AdvancedFruchtermanReingold.java +++ b/src/main/java/model/diagram/arrangement/algorithms/AdvancedFruchtermanReingold.java @@ -12,18 +12,9 @@ public class AdvancedFruchtermanReingold implements LayoutAlgorithm private final static int MIN_X_WINDOW_VALUE = 25; private final static int MIN_Y_WINDOW_VALUE = 25; - private Graph graph; - - - @Override - public void setGraph(Graph graph) - { - this.graph = graph; - } - @Override - public DiagramGeometry arrangeDiagram() + public DiagramGeometry arrangeDiagram(Graph graph) { double maxXdistance = 0.0; double maxYdistance = 0.0; diff --git a/src/main/java/model/diagram/arrangement/algorithms/AdvancedSpring.java b/src/main/java/model/diagram/arrangement/algorithms/AdvancedSpring.java index 5d137b8..ffbb372 100644 --- a/src/main/java/model/diagram/arrangement/algorithms/AdvancedSpring.java +++ b/src/main/java/model/diagram/arrangement/algorithms/AdvancedSpring.java @@ -11,18 +11,9 @@ public class AdvancedSpring implements LayoutAlgorithm private final static int MIN_X_WINDOW_VALUE = 25; private final static int MIN_Y_WINDOW_VALUE = 25; - private Graph graph; - - - @Override - public void setGraph(Graph graph) - { - this.graph = graph; - } - @Override - public DiagramGeometry arrangeDiagram() + public DiagramGeometry arrangeDiagram(Graph graph) { double maxXdistance = 0.0; double maxYdistance = 0.0; @@ -41,18 +32,12 @@ public DiagramGeometry arrangeDiagram() if (x < MIN_X_WINDOW_VALUE) { double difference = MIN_X_WINDOW_VALUE - x; - if (difference > maxXdistance) - { - maxXdistance = difference; - } + maxXdistance = Math.max(maxXdistance, difference); } if (y < MIN_Y_WINDOW_VALUE) { double difference = MIN_Y_WINDOW_VALUE - y; - if (difference > maxYdistance) - { - maxYdistance = difference; - } + maxYdistance = Math.max(maxYdistance, difference); } diagramGeometry.addGeometry(geometryNode, x, y); } diff --git a/src/main/java/model/diagram/arrangement/algorithms/FruchtermanReingold.java b/src/main/java/model/diagram/arrangement/algorithms/FruchtermanReingold.java index 8609f17..4ce0136 100644 --- a/src/main/java/model/diagram/arrangement/algorithms/FruchtermanReingold.java +++ b/src/main/java/model/diagram/arrangement/algorithms/FruchtermanReingold.java @@ -12,18 +12,9 @@ public class FruchtermanReingold implements LayoutAlgorithm private final static int MIN_X_WINDOW_VALUE = 25; private final static int MIN_Y_WINDOW_VALUE = 25; - private Graph graph; - - - @Override - public void setGraph(Graph graph) - { - this.graph = graph; - } - @Override - public DiagramGeometry arrangeDiagram() + public DiagramGeometry arrangeDiagram(Graph graph) { double maxXdistance = 0.0; double maxYdistance = 0.0; @@ -40,18 +31,12 @@ public DiagramGeometry arrangeDiagram() if (x < MIN_X_WINDOW_VALUE) { double difference = MIN_X_WINDOW_VALUE - x; - if (difference > maxXdistance) - { - maxXdistance = difference; - } + maxXdistance = Math.max(difference, maxXdistance); } if (y < MIN_Y_WINDOW_VALUE) { double difference = MIN_Y_WINDOW_VALUE - y; - if (difference > maxYdistance) - { - maxYdistance = difference; - } + maxYdistance = Math.max(difference, maxYdistance); } diagramGeometry.addGeometry(geometryNode, x, y); } diff --git a/src/main/java/model/diagram/arrangement/algorithms/KamadaKawai.java b/src/main/java/model/diagram/arrangement/algorithms/KamadaKawai.java index f1a5f13..41e052f 100644 --- a/src/main/java/model/diagram/arrangement/algorithms/KamadaKawai.java +++ b/src/main/java/model/diagram/arrangement/algorithms/KamadaKawai.java @@ -16,18 +16,9 @@ public class KamadaKawai implements LayoutAlgorithm private final static int MIN_X_WINDOW_VALUE = 25; private final static int MIN_Y_WINDOW_VALUE = 25; - private Graph graph; - - - @Override - public void setGraph(Graph graph) - { - this.graph = graph; - } - @Override - public DiagramGeometry arrangeDiagram() + public DiagramGeometry arrangeDiagram(Graph graph) { double maxXdistance = 0.0; double maxYdistance = 0.0; @@ -46,18 +37,12 @@ public DiagramGeometry arrangeDiagram() if (x < MIN_X_WINDOW_VALUE) { double difference = MIN_X_WINDOW_VALUE - x; - if (difference > maxXdistance) - { - maxXdistance = difference; - } + maxXdistance = Math.max(difference, maxXdistance); } if (y < MIN_Y_WINDOW_VALUE) { double difference = MIN_Y_WINDOW_VALUE - y; - if (difference > maxYdistance) - { - maxYdistance = difference; - } + maxYdistance = Math.max(difference, maxYdistance); } diagramGeometry.addGeometry(geometryNode, x, y); } diff --git a/src/main/java/model/diagram/arrangement/algorithms/LayoutAlgorithm.java b/src/main/java/model/diagram/arrangement/algorithms/LayoutAlgorithm.java index 1e3d71e..abe66ad 100644 --- a/src/main/java/model/diagram/arrangement/algorithms/LayoutAlgorithm.java +++ b/src/main/java/model/diagram/arrangement/algorithms/LayoutAlgorithm.java @@ -6,15 +6,13 @@ public interface LayoutAlgorithm { // TODO Update JavaDoc - /** * This method is responsible for the arrangement of the graph by creating a graph * of the Jung library and using this graph's coordinates in our front end. * - * @return a {@link DiagramGeometry} object which represents the diagram's geometry + * @param graph a {@link Graph} that represents the diagram to be arranged. + * @return a {@link DiagramGeometry} object which represents the diagram's geometry. */ - DiagramGeometry arrangeDiagram(); + DiagramGeometry arrangeDiagram(Graph graph); - // TODO JavaDoc - void setGraph(Graph graph); } diff --git a/src/main/java/model/diagram/arrangement/algorithms/LayoutAlgorithmType.java b/src/main/java/model/diagram/arrangement/algorithms/LayoutAlgorithmType.java index af43141..31e263b 100644 --- a/src/main/java/model/diagram/arrangement/algorithms/LayoutAlgorithmType.java +++ b/src/main/java/model/diagram/arrangement/algorithms/LayoutAlgorithmType.java @@ -1,8 +1,10 @@ package model.diagram.arrangement.algorithms; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.stream.Collectors; public enum LayoutAlgorithmType { @@ -17,12 +19,8 @@ public enum LayoutAlgorithmType static { - Map map = new HashMap<>(); - for (LayoutAlgorithmType layoutAlgorithmType : LayoutAlgorithmType.values()) - { - map.put(layoutAlgorithmType.toString().toLowerCase(), layoutAlgorithmType); - } - ALGORITHM_TYPE_MAP = Collections.unmodifiableMap(map); + ALGORITHM_TYPE_MAP = Arrays.stream(LayoutAlgorithmType.values()) + .collect(Collectors.toMap(LayoutAlgorithmType::toString, it -> it)); } public static LayoutAlgorithmType get(String algorithmType) @@ -30,4 +28,10 @@ public static LayoutAlgorithmType get(String algorithmType) return ALGORITHM_TYPE_MAP.get(algorithmType.toLowerCase()); } + + @Override + public String toString() + { + return super.toString().toLowerCase(); + } } diff --git a/src/main/java/model/diagram/arrangement/algorithms/Spring.java b/src/main/java/model/diagram/arrangement/algorithms/Spring.java index 8c29a32..8337939 100644 --- a/src/main/java/model/diagram/arrangement/algorithms/Spring.java +++ b/src/main/java/model/diagram/arrangement/algorithms/Spring.java @@ -9,28 +9,21 @@ public class Spring implements LayoutAlgorithm { - private final static int MIN_X_WINDOW_VALUE = 25; - private final static int MIN_Y_WINDOW_VALUE = 25; - - private Graph graph; - - - @Override - public void setGraph(Graph graph) - { - this.graph = graph; - } + private static final int MIN_X_WINDOW_VALUE = 25; + private static final int MIN_Y_WINDOW_VALUE = 25; + private static final double FORCE_MULTIPLIER = 0.1; + private static final int REPULSION_RANGE = 500; @Override - public DiagramGeometry arrangeDiagram() + public DiagramGeometry arrangeDiagram(Graph graph) { double maxXdistance = 0.0; double maxYdistance = 0.0; DiagramGeometry diagramGeometry = new DiagramGeometry(); SpringLayout layout = new SpringLayout<>(graph); - layout.setForceMultiplier(0.1); - layout.setRepulsionRange(500); + layout.setForceMultiplier(FORCE_MULTIPLIER); + layout.setRepulsionRange(REPULSION_RANGE); // layout.setSize(new Dimension(GRAPH_X_SIZE, GRAPH_Y_SIZE)); @SuppressWarnings("unused") VisualizationViewer vv = new VisualizationViewer<>(layout); @@ -42,18 +35,12 @@ public DiagramGeometry arrangeDiagram() if (x < MIN_X_WINDOW_VALUE) { double difference = MIN_X_WINDOW_VALUE - x; - if (difference > maxXdistance) - { - maxXdistance = difference; - } + maxXdistance = Math.max(maxXdistance, difference); } if (y < MIN_Y_WINDOW_VALUE) { double difference = MIN_Y_WINDOW_VALUE - y; - if (difference > maxYdistance) - { - maxYdistance = difference; - } + maxYdistance = Math.max(maxYdistance, difference); } diagramGeometry.addGeometry(geometryNode, x, y); } diff --git a/src/main/java/model/diagram/arrangement/algorithms/Sugiyama.java b/src/main/java/model/diagram/arrangement/algorithms/Sugiyama.java index 493cd1b..cb9c7ac 100644 --- a/src/main/java/model/diagram/arrangement/algorithms/Sugiyama.java +++ b/src/main/java/model/diagram/arrangement/algorithms/Sugiyama.java @@ -25,7 +25,6 @@ public class Sugiyama implements LayoutAlgorithm private final static int VERTICAL_SPACING = 50; private final Map verticesMap; - private Graph graph; private SimpleDigraph digraph; @@ -36,23 +35,16 @@ public Sugiyama() @Override - public void setGraph(Graph graph) - { - this.graph = graph; - } - - - @Override - public DiagramGeometry arrangeDiagram() + public DiagramGeometry arrangeDiagram(Graph graph) { double maxXdistance = 0.0; double maxYdistance = 0.0; DiagramGeometry diagramGeometry = new DiagramGeometry(); digraph = new SimpleDigraphAdapter<>(); - fillVertexMap(); - fillNeighboursMap(); + fillVertexMap(graph); + fillNeighboursMap(graph); DigraphLayoutDimensionProvider dimensionProvider = node -> { - // We use OOAD vertices' size, in order to evaluate vertices coordinates based on our vertices sizes. + // We use OOAD vertices' size, in order to evaluate vertices coordinates. return new DigraphLayoutDimension(VERTEX_X_SIZE, VERTEX_Y_SIZE); }; DigrpahLayoutBuilder builder = new SugiyamaBuilder<>(HORIZONTAL_SPACING, VERTICAL_SPACING); @@ -61,30 +53,23 @@ public DiagramGeometry arrangeDiagram() { for (Map.Entry entryVertex : verticesMap.entrySet()) { - if (entryVertex.getValue().equals(vertex.getVertex())) + if (!entryVertex.getValue().equals(vertex.getVertex())) continue; + + double x = vertex.getPoint().x; + double y = vertex.getPoint().y; + GeometryNode geometryNode = new GeometryNode(entryVertex.getKey()); + if (vertex.getPoint().x < MIN_X_WINDOW_VALUE) + { + double difference = MIN_X_WINDOW_VALUE - x; + maxXdistance = Math.max(difference, maxXdistance); + } + if (vertex.getPoint().y < MIN_Y_WINDOW_VALUE) { - double x = vertex.getPoint().x; - double y = vertex.getPoint().y; - GeometryNode geometryNode = new GeometryNode(entryVertex.getKey()); - if (vertex.getPoint().x < MIN_X_WINDOW_VALUE) - { - double difference = MIN_X_WINDOW_VALUE - x; - if (difference > maxXdistance) - { - maxXdistance = difference; - } - } - if (vertex.getPoint().y < MIN_Y_WINDOW_VALUE) - { - double difference = MIN_Y_WINDOW_VALUE - y; - if (difference > maxYdistance) - { - maxYdistance = difference; - } - } - diagramGeometry.addGeometry(geometryNode, x, y); - break; + double difference = MIN_Y_WINDOW_VALUE - y; + maxYdistance = Math.max(difference, maxYdistance); } + diagramGeometry.addGeometry(geometryNode, x, y); + break; } } diagramGeometry.correctPositions(maxXdistance, maxYdistance); @@ -92,7 +77,7 @@ public DiagramGeometry arrangeDiagram() } - private void fillNeighboursMap() + private void fillNeighboursMap(Graph graph) { for (String edge : graph.getEdges()) { @@ -102,13 +87,12 @@ private void fillNeighboursMap() } - private void fillVertexMap() + private void fillVertexMap(Graph graph) { int counter = 1; for (String vertex : graph.getVertices()) { - verticesMap.put(vertex, counter); - counter += 1; + verticesMap.put(vertex, counter++); } } diff --git a/src/main/java/model/diagram/arrangement/geometry/DiagramGeometry.java b/src/main/java/model/diagram/arrangement/geometry/DiagramGeometry.java index 27a2799..356a904 100644 --- a/src/main/java/model/diagram/arrangement/geometry/DiagramGeometry.java +++ b/src/main/java/model/diagram/arrangement/geometry/DiagramGeometry.java @@ -16,7 +16,7 @@ public class DiagramGeometry public DiagramGeometry() { - this.geometryMap = new HashMap<>(); + geometryMap = new HashMap<>(); } @@ -50,15 +50,11 @@ public void correctPositions(double x, double y) { double newX = entry.getValue().getValue0() + x; double newY = entry.getValue().getValue1() + y; - geometryMap.put(entry.getKey(), new Pair<>(entry.getValue().getValue0() + x, entry.getValue().getValue1() + y)); - if (newX < minX) - { - minX = newX; - } - if (newY < minY) - { - minY = newY; - } + geometryMap.put(entry.getKey(), + new Pair<>(entry.getValue().getValue0() + x, + entry.getValue().getValue1() + y)); + minX = Math.min(minX, newX); + minY = Math.min(minY, newY); } xDifference = minX - MIN_X_WINDOW_VALUE; yDifference = minY - MIN_Y_WINDOW_VALUE; diff --git a/src/main/java/model/diagram/exportation/CoordinatesUpdater.java b/src/main/java/model/diagram/exportation/CoordinatesUpdater.java index db97f2d..514fdfa 100644 --- a/src/main/java/model/diagram/exportation/CoordinatesUpdater.java +++ b/src/main/java/model/diagram/exportation/CoordinatesUpdater.java @@ -36,7 +36,7 @@ public void updatePackageCoordinates(Collection> vertexColle { if (vertexCollection == null) { - logger.log(Level.WARNING, "Trying to update tha package's coordinates with a null vertex Collection"); + logger.log(Level.WARNING, "Trying to update the package's coordinates with vertex Collection that is null"); return; } @@ -46,10 +46,7 @@ public void updatePackageCoordinates(Collection> vertexColle double y = graphView.getVertexPositionY(vertex); for (PackageVertex packageVertex : packageDiagram.getGraphNodes().keySet()) { - if (!packageVertex.getName().equals(vertex.element())) - { - continue; - } + if (!packageVertex.getName().equals(vertex.element())) continue; packageVertex.setCoordinate(x, y); } @@ -62,7 +59,7 @@ public void updateClassCoordinates(Collection> vertexCollect { if (vertexCollection == null) { - logger.log(Level.WARNING, "Trying to update tha class's coordinates with a null vertex Collection"); + logger.log(Level.WARNING, "Trying to update the class' coordinates with a vertex Collection that is null"); return; } @@ -72,10 +69,7 @@ public void updateClassCoordinates(Collection> vertexCollect double y = graphView.getVertexPositionY(vertex); for (ClassifierVertex classifierVertex : classDiagram.getGraphNodes().keySet()) { - if (!classifierVertex.getName().equals(vertex.element())) - { - continue; - } + if (!classifierVertex.getName().equals(vertex.element())) continue; classifierVertex.setCoordinate(x, y); } diff --git a/src/main/java/model/diagram/exportation/GraphMLClassDiagramExporter.java b/src/main/java/model/diagram/exportation/GraphMLClassDiagramExporter.java index d1b2b5e..3f77a2e 100644 --- a/src/main/java/model/diagram/exportation/GraphMLClassDiagramExporter.java +++ b/src/main/java/model/diagram/exportation/GraphMLClassDiagramExporter.java @@ -22,7 +22,7 @@ public GraphMLClassDiagramExporter(ClassDiagram classDiagram) graphMLNodeBuffer = graphMLClassifierVertex.convertSinkVertex(); graphMLEdgeBuffer = graphMLClassifierVertexArc.convertSinkVertexArc(); - graphMLFile = new GraphMLFile(); + graphMLFile = new GraphMLFile(); } diff --git a/src/main/java/model/diagram/exportation/GraphMLPackageDiagramExporter.java b/src/main/java/model/diagram/exportation/GraphMLPackageDiagramExporter.java index 33f8601..863b096 100644 --- a/src/main/java/model/diagram/exportation/GraphMLPackageDiagramExporter.java +++ b/src/main/java/model/diagram/exportation/GraphMLPackageDiagramExporter.java @@ -22,7 +22,7 @@ public GraphMLPackageDiagramExporter(PackageDiagram packageDiagram) graphMLNodeBuffer = graphMLPackageVertex.convertVertex(); graphMLEdgeBuffer = graphMLPackageVertexArc.convertVertexArc(); - graphMLFile = new GraphMLFile(); + graphMLFile = new GraphMLFile(); } diff --git a/src/main/java/model/diagram/exportation/PlantUMLClassDiagramImageExporter.java b/src/main/java/model/diagram/exportation/PlantUMLClassDiagramImageExporter.java index e16fc50..6de6235 100644 --- a/src/main/java/model/diagram/exportation/PlantUMLClassDiagramImageExporter.java +++ b/src/main/java/model/diagram/exportation/PlantUMLClassDiagramImageExporter.java @@ -81,18 +81,18 @@ private void exportImage(File plantUMLFile, String plantCode) private String wrapWidthChanger(String plantCode, int wrapWidth) { String updatedString; - //if (counter == 0) { + // if (counter == 0) { int indexOfNewLine = plantCode.indexOf("\n"); String firstPart = plantCode.substring(0, indexOfNewLine + 1); String secondPart = plantCode.substring(indexOfNewLine + 1); - updatedString = firstPart + "skinparam wrapWidth " + wrapWidth + "\n" + secondPart; + updatedString = String.format("%sskinparam wrapWidth %d\n%s", firstPart, wrapWidth, secondPart); // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // KEEP REDUCING THE WRAPWIDTH PARAMETER IN ORDER TO FIT PROPERLY THE IMAGE // // DOESNT WORK PROPERLY, COMMENTED JUST TO KEEP THE IDEA. // // POP UP MESSAGE CAN BE ADDED TO INFORM THE USER THAT THE IMAGE HE // // REQUESTED IS OVER 4096x4096 SO WE REDUCE THE WRAPWIDTH TO REDUCE // // EXTRACTED IMAGE'S WIDTH. NOW THE USER CAN SEE MORE CLASSES. // - // }else { // + // } else { // // String[] lines = plantCode.split("\n"); // // lines[1] = "skinparam wrapWidth " + wrapWidth; // // updatedString = String.join("\n", lines); // @@ -102,7 +102,7 @@ private String wrapWidthChanger(String plantCode, int wrapWidth) } - private String getClassText() + private static String getClassText() { return """ @startuml diff --git a/src/main/java/model/diagram/exportation/PlantUMLClassDiagramTextExporter.java b/src/main/java/model/diagram/exportation/PlantUMLClassDiagramTextExporter.java index 24b46d5..623da5e 100644 --- a/src/main/java/model/diagram/exportation/PlantUMLClassDiagramTextExporter.java +++ b/src/main/java/model/diagram/exportation/PlantUMLClassDiagramTextExporter.java @@ -33,8 +33,7 @@ public PlantUMLClassDiagramTextExporter(ClassDiagram diagram) public File exportDiagram(Path exportPath) { File plantUMLFile = exportPath.toFile(); - String plantUMLCode = getClassText(); - plantUMLCode += bufferBody; + String plantUMLCode = getClassText() + bufferBody; writeFile(plantUMLFile, plantUMLCode); return plantUMLFile; } diff --git a/src/main/java/model/diagram/exportation/PlantUMLPackageDiagramImageExporter.java b/src/main/java/model/diagram/exportation/PlantUMLPackageDiagramImageExporter.java index dce0c99..7c8a606 100644 --- a/src/main/java/model/diagram/exportation/PlantUMLPackageDiagramImageExporter.java +++ b/src/main/java/model/diagram/exportation/PlantUMLPackageDiagramImageExporter.java @@ -37,10 +37,8 @@ public PlantUMLPackageDiagramImageExporter(PackageDiagram diagram) public File exportDiagram(Path exportPath) { File plantUMLFile = exportPath.toFile(); - String plantUMLCode = getPackageText(); - plantUMLCode += bufferBody; - plantUMLCode = dotChanger(plantUMLCode); - exportImage(plantUMLFile, plantUMLCode); + String plantUMLCode = getPackageText() + bufferBody; + exportImage(plantUMLFile, replaceDots(plantUMLCode)); return plantUMLFile; } @@ -104,14 +102,14 @@ private String wrapWidthChanger(String plantCode, int wrapWidth) } - private String dotChanger(String plantUMLCode) + private static String replaceDots(String plantUMLCode) { StringBuilder newString = new StringBuilder(); String[] lines = plantUMLCode.split("\n"); for (String line : lines) { - String[] splittedLine = line.split(" "); - for (String word : splittedLine) + String[] split = line.split(" "); + for (String word : split) { String newWord = word; if (word.contains(".") && !word.contains("..")) @@ -127,7 +125,7 @@ private String dotChanger(String plantUMLCode) } - private String getPackageText() + private static String getPackageText() { return """ @startuml diff --git a/src/main/java/model/diagram/exportation/PlantUMLPackageDiagramTextExporter.java b/src/main/java/model/diagram/exportation/PlantUMLPackageDiagramTextExporter.java index a6149b0..028f35c 100644 --- a/src/main/java/model/diagram/exportation/PlantUMLPackageDiagramTextExporter.java +++ b/src/main/java/model/diagram/exportation/PlantUMLPackageDiagramTextExporter.java @@ -33,10 +33,8 @@ public PlantUMLPackageDiagramTextExporter(PackageDiagram diagram) public File exportDiagram(Path exportPath) { File plantUMLFile = exportPath.toFile(); - String plantUMLCode = getPackageText(); - plantUMLCode += bufferBody; - plantUMLCode = dotChanger(plantUMLCode); - writeFile(plantUMLFile, plantUMLCode); + String plantUMLCode = getPackageText() + bufferBody; + writeFile(plantUMLFile, dotChanger(plantUMLCode)); return plantUMLFile; } @@ -55,7 +53,7 @@ private void writeFile(File plantUMLFile, String plantCode) } - private String dotChanger(String plantUMLCode) + private static String dotChanger(String plantUMLCode) { StringBuilder newString = new StringBuilder(); String[] lines = plantUMLCode.split("\n"); diff --git a/src/main/java/model/diagram/graphml/GraphMLClassifierVertex.java b/src/main/java/model/diagram/graphml/GraphMLClassifierVertex.java index ce3c386..21c8eab 100644 --- a/src/main/java/model/diagram/graphml/GraphMLClassifierVertex.java +++ b/src/main/java/model/diagram/graphml/GraphMLClassifierVertex.java @@ -62,7 +62,7 @@ private String getSinkVertexMethods(ClassifierVertex classifierVertex) } return classifierVertex.getMethods() .stream() - .map(method -> method.returnType() + " " + method.name()) + .map(it -> it.returnType() + " " + it.name()) .collect(Collectors.joining("\n")); } @@ -75,20 +75,16 @@ private String getSinkVertexFields(ClassifierVertex classifierVertex) } return classifierVertex.getFields() .stream() - .map(field -> String.join(" ", - field.type(), - field.name())) + .map(it -> String.join(" ", + it.type(), + it.name())) .collect(Collectors.joining("\n")); } private String getSinkVertexColor(ClassifierVertex leafNode) { - if (leafNode.getVertexType().equals(VertexType.INTERFACE)) - { - return INTERFACE_COLOR; - } - return CLASS_COLOR; + return leafNode.getVertexType().equals(VertexType.INTERFACE) ? INTERFACE_COLOR : CLASS_COLOR; } } diff --git a/src/main/java/model/diagram/graphml/GraphMLClassifierVertexArc.java b/src/main/java/model/diagram/graphml/GraphMLClassifierVertexArc.java index 85b6754..697029f 100644 --- a/src/main/java/model/diagram/graphml/GraphMLClassifierVertexArc.java +++ b/src/main/java/model/diagram/graphml/GraphMLClassifierVertexArc.java @@ -38,8 +38,7 @@ public StringBuilder convertSinkVertexArc() int edgeId = 0; for (Arc arc : arcs) { - graphMLBuffer.append(GraphMLSyntax.getInstance().getGraphMLSinkVertexArcSyntax(getEdgesProperties(arc, edgeId))); - edgeId++; + graphMLBuffer.append(GraphMLSyntax.getInstance().getGraphMLSinkVertexArcSyntax(getEdgesProperties(arc, edgeId++))); } return graphMLBuffer; } diff --git a/src/main/java/model/diagram/graphml/GraphMLPackageVertexArc.java b/src/main/java/model/diagram/graphml/GraphMLPackageVertexArc.java index 8e16868..cb5e82e 100644 --- a/src/main/java/model/diagram/graphml/GraphMLPackageVertexArc.java +++ b/src/main/java/model/diagram/graphml/GraphMLPackageVertexArc.java @@ -29,11 +29,11 @@ public StringBuilder convertVertexArc() { arcs.addAll(arcSet); } + int edgeId = 0; for (Arc arc : arcs) { - graphMLBuffer.append(GraphMLSyntax.getInstance().getGraphMLVertexArcSyntax(getVertexArcProperties(arc, edgeId))); - edgeId++; + graphMLBuffer.append(GraphMLSyntax.getInstance().getGraphMLVertexArcSyntax(getVertexArcProperties(arc, edgeId++))); } return graphMLBuffer; } diff --git a/src/main/java/model/diagram/graphml/GraphMLSyntax.java b/src/main/java/model/diagram/graphml/GraphMLSyntax.java index 0d706cb..672fd65 100644 --- a/src/main/java/model/diagram/graphml/GraphMLSyntax.java +++ b/src/main/java/model/diagram/graphml/GraphMLSyntax.java @@ -149,6 +149,6 @@ public static GraphMLSyntax getInstance() } - /** Singleton. Do not instantiate. */ + /** Singleton class. Do not instantiate. */ private GraphMLSyntax() {} } diff --git a/src/main/java/model/diagram/graphml/GraphMLSyntaxIds.java b/src/main/java/model/diagram/graphml/GraphMLSyntaxIds.java index 5c03399..be930ea 100644 --- a/src/main/java/model/diagram/graphml/GraphMLSyntaxIds.java +++ b/src/main/java/model/diagram/graphml/GraphMLSyntaxIds.java @@ -19,6 +19,7 @@ public enum GraphMLSyntaxIds PACKAGE_Y_COORDINATE(3), PACKAGE_NAME (1); + private final int id; diff --git a/src/main/java/model/diagram/javafx/JavaFXClassVisualization.java b/src/main/java/model/diagram/javafx/JavaFXClassVisualization.java index 25283d2..d8ba544 100644 --- a/src/main/java/model/diagram/javafx/JavaFXClassVisualization.java +++ b/src/main/java/model/diagram/javafx/JavaFXClassVisualization.java @@ -105,10 +105,8 @@ public SmartGraphPanel getLoadedGraph() { for (ClassifierVertex classifierVertex : classDiagram.getDiagram().keySet()) { - if (!classifierVertex.getName().equals(vertex.element())) - { - continue; - } + if (!classifierVertex.getName().equals(vertex.element())) continue; + graphView.setVertexPosition(vertex, classifierVertex.getCoordinate().x(), classifierVertex.getCoordinate().y()); diff --git a/src/main/java/model/diagram/javafx/JavaFXPackageDiagramLoader.java b/src/main/java/model/diagram/javafx/JavaFXPackageDiagramLoader.java index a372bcf..d6fb6c4 100644 --- a/src/main/java/model/diagram/javafx/JavaFXPackageDiagramLoader.java +++ b/src/main/java/model/diagram/javafx/JavaFXPackageDiagramLoader.java @@ -60,16 +60,14 @@ private void deserializeArcs(Set vertices) { Optional sourceVertex = vertices .stream() - .filter(vertex1 -> vertex1.getName().equals(arc.getValue0())) + .filter(it -> it.getName().equals(arc.getValue0())) .findFirst(); Optional targetVertex = vertices .stream() - .filter(vertex1 -> vertex1.getName().equals(arc.getValue1())) + .filter(it -> it.getName().equals(arc.getValue1())) .findFirst(); - if (sourceVertex.isEmpty() || targetVertex.isEmpty()) - { - continue; - } + if (sourceVertex.isEmpty() || targetVertex.isEmpty()) continue; + vertex.addArc(sourceVertex.get(), targetVertex.get(), ArcType.get(arc.getValue2())); } } diff --git a/src/main/java/model/diagram/javafx/JavaFXPackageVisualization.java b/src/main/java/model/diagram/javafx/JavaFXPackageVisualization.java index 217fb8e..cce85eb 100644 --- a/src/main/java/model/diagram/javafx/JavaFXPackageVisualization.java +++ b/src/main/java/model/diagram/javafx/JavaFXPackageVisualization.java @@ -52,10 +52,8 @@ private Graph createGraph() Digraph directedGraph = new DigraphEdgeList<>(); for (PackageVertex vertex : packageDiagram.getDiagram().keySet()) { - if (vertex.getSinkVertices().isEmpty()) - { - continue; - } + if (vertex.getSinkVertices().isEmpty()) continue; + directedGraph.insertVertex(vertex.getName()); } insertVertexArcs(directedGraph); @@ -96,10 +94,8 @@ private void setVertexCustomStyle() } else { - if (vertex.getSinkVertices().isEmpty()) - { - continue; - } + if (vertex.getSinkVertices().isEmpty()) continue; + graphView.getStylableVertex(vertex.getName()).setStyleClass("vertexPackage"); } } @@ -113,10 +109,8 @@ public SmartGraphPanel getLoadedGraph() { for (PackageVertex packageVertex : packageDiagram.getDiagram().keySet()) { - if (!packageVertex.getName().equals(vertex.element())) - { - continue; - } + if (!packageVertex.getName().equals(vertex.element())) continue; + graphView.setVertexPosition(vertex, packageVertex.getCoordinate().x(), packageVertex.getCoordinate().y()); diff --git a/src/main/java/model/diagram/plantuml/PlantUMLClassifierVertex.java b/src/main/java/model/diagram/plantuml/PlantUMLClassifierVertex.java index e7841b9..6e8739a 100644 --- a/src/main/java/model/diagram/plantuml/PlantUMLClassifierVertex.java +++ b/src/main/java/model/diagram/plantuml/PlantUMLClassifierVertex.java @@ -14,36 +14,36 @@ public class PlantUMLClassifierVertex private final ClassDiagram classDiagram; - public PlantUMLClassifierVertex(ClassDiagram diagram) + public PlantUMLClassifierVertex(ClassDiagram classDiagram) { - classDiagram = diagram; + this.classDiagram = classDiagram; } public StringBuilder convertSinkVertex() { - return new StringBuilder( - classDiagram - .getDiagram() - .keySet() - .stream() - .map(sinkVertex -> - sinkVertex.getVertexType() + " " + sinkVertex.getName() + " {\n" + - convertFields(sinkVertex) + convertMethods(sinkVertex) + "}") - .collect(Collectors.joining("\n\n"))); + String sinkVertices = classDiagram.getDiagram() + .keySet() + .stream() + .map(it -> String.format("%s %s {\n%s%s}", + it.getVertexType(), + it.getName(), + convertFields(it), + convertMethods(it))) + .collect(Collectors.joining("\n\n")); + + return new StringBuilder(sinkVertices); } private String convertFields(ClassifierVertex classifierVertex) { - if (classifierVertex.getFields().isEmpty()) - { - return ""; - } + if (classifierVertex.getFields().isEmpty()) return ""; + return classifierVertex .getFields() .stream() - .map(field -> getVisibility(field.modifier()) + field.name() + ": " + field.type()) + .map(it -> String.format("%s%s: %s", getVisibility(it.modifier()), it.name(), it.type())) .collect(Collectors.joining("\n")) + "\n"; } @@ -51,19 +51,22 @@ private String convertFields(ClassifierVertex classifierVertex) private String convertMethods(ClassifierVertex classifierVertex) { StringBuilder plantUMLMethods = new StringBuilder(); + List constructors = classifierVertex .getMethods() .stream() - .filter(method -> method.returnType().equals("Constructor")) - .sorted(Comparator.comparingInt(method -> method.parameters().size())) + .filter(it -> it.returnType().equals("Constructor")) + .sorted(Comparator.comparingInt(it -> it.parameters().size())) .collect(Collectors.toList()); + convertMethod(plantUMLMethods, constructors); List methods = classifierVertex .getMethods() .stream() - .filter(method -> !method.returnType().equals("Constructor")) + .filter(it -> !it.returnType().equals("Constructor")) .collect(Collectors.toList()); + convertMethod(plantUMLMethods, methods); return plantUMLMethods.toString(); @@ -79,12 +82,11 @@ private void convertMethod(StringBuilder plantUMLMethods, .append(getVisibility(method.modifier())) .append(method.name()) .append("(") - .append(method - .parameters() - .entrySet() - .stream() - .map(parameter -> parameter.getValue() + " " + parameter.getKey()) - .collect(Collectors.joining(", "))) + .append(method.parameters() + .entrySet() + .stream() + .map(it -> it.getValue() + " " + it.getKey()) + .collect(Collectors.joining(", "))) .append("): ") .append(method.returnType()) .append("\n"); diff --git a/src/main/java/model/diagram/plantuml/PlantUMLClassifierVertexArc.java b/src/main/java/model/diagram/plantuml/PlantUMLClassifierVertexArc.java index 35d2e9f..e6cecdb 100644 --- a/src/main/java/model/diagram/plantuml/PlantUMLClassifierVertexArc.java +++ b/src/main/java/model/diagram/plantuml/PlantUMLClassifierVertexArc.java @@ -6,6 +6,7 @@ import model.graph.ClassifierVertex; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -24,17 +25,15 @@ public PlantUMLClassifierVertexArc(ClassDiagram diagram) public StringBuilder convertSinkVertexArc() { - return new StringBuilder(classDiagram - .getDiagram() + return new StringBuilder(classDiagram.getDiagram() .values() .stream() - .flatMap(sinkVertexStream -> sinkVertexStream - .stream() - .map(sinkVertexArc -> String.join(" ", - sinkVertexArc.sourceVertex().getName(), - getRelationship(sinkVertexArc.arcType()), - sinkVertexArc.targetVertex().getName()))) - .collect(Collectors.joining("\n"))); + .flatMap(Collection::stream) + .map(it -> String.join(" ", + it.sourceVertex().getName(), + getRelationship(it.arcType()), + it.targetVertex().getName())) + .collect(Collectors.joining("\n"))); } @@ -46,7 +45,7 @@ private String getRelationship(ArcType relationshipType) case AGGREGATION -> "o--"; case DEPENDENCY -> "..>"; case IMPLEMENTATION -> "..|>"; - // ASSOCIATION + // ASSOCIATION. default -> "-->"; }; } diff --git a/src/main/java/model/diagram/plantuml/PlantUMLPackageVertex.java b/src/main/java/model/diagram/plantuml/PlantUMLPackageVertex.java index cf525de..b8ee352 100644 --- a/src/main/java/model/diagram/plantuml/PlantUMLPackageVertex.java +++ b/src/main/java/model/diagram/plantuml/PlantUMLPackageVertex.java @@ -18,11 +18,10 @@ public PlantUMLPackageVertex(PackageDiagram diagram) public StringBuilder convertVertex() { - return new StringBuilder(packageDiagram - .getDiagram() + return new StringBuilder(packageDiagram.getDiagram() .keySet() .stream() - .map(vertex -> vertex.getVertexType() + " " + vertex.getName() + " {\n" + "}\n") + .map(it -> it.getVertexType() + " " + it.getName() + " {\n" + "}\n") .collect(Collectors.joining("\n"))); } diff --git a/src/main/java/model/diagram/plantuml/PlantUMLPackageVertexArc.java b/src/main/java/model/diagram/plantuml/PlantUMLPackageVertexArc.java index 8518185..73f3ea5 100644 --- a/src/main/java/model/diagram/plantuml/PlantUMLPackageVertexArc.java +++ b/src/main/java/model/diagram/plantuml/PlantUMLPackageVertexArc.java @@ -6,6 +6,7 @@ import model.graph.PackageVertex; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -24,17 +25,15 @@ public PlantUMLPackageVertexArc(PackageDiagram diagram) public StringBuilder convertVertexArc() { - return new StringBuilder(packageDiagram - .getDiagram() + return new StringBuilder(packageDiagram.getDiagram() .values() .stream() - .flatMap(vertexArcStream -> vertexArcStream - .stream() - .map(vertexArc -> - String.join(" ", - vertexArc.sourceVertex().getName(), - getRelationship(vertexArc.arcType()), - vertexArc.targetVertex().getName()))) + .flatMap(Collection::stream) + .map(it -> + String.join(" ", + it.sourceVertex().getName(), + getRelationship(it.arcType()), + it.targetVertex().getName())) .collect(Collectors.joining("\n"))); } diff --git a/src/main/java/model/diagram/svg/PlantUMLClassDiagram.java b/src/main/java/model/diagram/svg/PlantUMLClassDiagram.java new file mode 100644 index 0000000..e0a7bbe --- /dev/null +++ b/src/main/java/model/diagram/svg/PlantUMLClassDiagram.java @@ -0,0 +1,61 @@ +package model.diagram.svg; + +import model.diagram.ClassDiagram; +import model.diagram.plantuml.PlantUMLClassifierVertex; +import model.diagram.plantuml.PlantUMLClassifierVertexArc; +import net.sourceforge.plantuml.FileFormat; +import net.sourceforge.plantuml.FileFormatOption; +import net.sourceforge.plantuml.SourceStringReader; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +public class PlantUMLClassDiagram +{ + + private final StringBuilder bufferBody; + + + public PlantUMLClassDiagram(ClassDiagram diagram) + { + PlantUMLClassifierVertex plantUMLClassifierVertex = new PlantUMLClassifierVertex(diagram); + StringBuilder plantUMLNodeBuffer = plantUMLClassifierVertex.convertSinkVertex(); + PlantUMLClassifierVertexArc plantUMLEdge = new PlantUMLClassifierVertexArc(diagram); + StringBuilder plantUMLEdgeBuffer = plantUMLEdge.convertSinkVertexArc(); + bufferBody = plantUMLNodeBuffer + .append("\n\n") + .append(plantUMLEdgeBuffer) + .append("\n @enduml"); + } + + public String toSvg(int dpi) + { + try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) + { + String plantUMLCode = getClassText(dpi) + bufferBody; + SourceStringReader reader = new SourceStringReader(plantUMLCode); + reader.outputImage(byteArrayOutputStream, new FileFormatOption(FileFormat.SVG)).getDescription(); + return byteArrayOutputStream.toString(StandardCharsets.UTF_8); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + + + private static String getClassText(int dpi) + { + return "@startuml\n" + + (dpi > 0 ? "skinparam dpi " + dpi : "") + "\n" + + // TODO: Determine the best value for this. + "skinparam wrapWidth 10" + "\n" + + "skinparam class {\n" + + " BackgroundColor lightyellow\n" + + " BorderColor black\n" + + " ArrowColor black\n" + + "}\n" + + "\n"; + } +} diff --git a/src/main/java/model/diagram/svg/PlantUMLPackageDiagram.java b/src/main/java/model/diagram/svg/PlantUMLPackageDiagram.java new file mode 100644 index 0000000..18003a1 --- /dev/null +++ b/src/main/java/model/diagram/svg/PlantUMLPackageDiagram.java @@ -0,0 +1,86 @@ +package model.diagram.svg; + +import model.diagram.PackageDiagram; +import model.diagram.plantuml.PlantUMLPackageVertex; +import model.diagram.plantuml.PlantUMLPackageVertexArc; +import net.sourceforge.plantuml.FileFormat; +import net.sourceforge.plantuml.FileFormatOption; +import net.sourceforge.plantuml.SourceStringReader; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +public class PlantUMLPackageDiagram +{ + + private final StringBuilder bufferBody; + + public PlantUMLPackageDiagram(PackageDiagram packageDiagram) + { + PlantUMLPackageVertex plantUMLPackageVertex = new PlantUMLPackageVertex(packageDiagram); + StringBuilder plantUMLNodeBuffer = plantUMLPackageVertex.convertVertex(); + PlantUMLPackageVertexArc plantUMLPackageVertexArc = new PlantUMLPackageVertexArc(packageDiagram); + StringBuilder plantUMLEdgeBuffer = plantUMLPackageVertexArc.convertVertexArc(); + + bufferBody = plantUMLNodeBuffer + .append("\n\n") + .append(plantUMLEdgeBuffer) + .append("\n @enduml"); + } + + + public String toSvg(int dpi) + { + try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) + { + String plantUMLCode = getPackageText(dpi) + bufferBody; + SourceStringReader reader = new SourceStringReader(replaceDots(plantUMLCode)); + reader.outputImage(byteArrayOutputStream, new FileFormatOption(FileFormat.SVG)).getDescription(); + return byteArrayOutputStream.toString(StandardCharsets.UTF_8); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + + + private static String replaceDots(String plantUMLCode) + { + StringBuilder newString = new StringBuilder(); + String[] lines = plantUMLCode.split("\n"); + for (String line : lines) + { + String[] split = line.split(" "); + for (String word : split) + { + String newWord = word; + if (word.contains(".") && !word.contains("..")) + { + newWord = word.replace(".", "_"); + newWord = newWord.replace("-", "_"); + } + newString.append(newWord).append(" "); + } + newString.append("\n"); + } + return newString.toString(); + } + + + private static String getPackageText(int dpi) + { + return "@startuml\n" + + (dpi > 0 ? "skinparam dpi " + dpi : "") + "\n" + + // TODO: Determine the best value for this. + "skinparam wrapWidth 10" + "\n" + + "skinparam package {\n" + + " BackgroundColor lightyellow\n" + + " BorderColor black\n" + + " ArrowColor black\n" + + " Shadowing true\n" + + "}\n" + + "\n"; + } +} diff --git a/src/main/java/model/graph/ModifierType.java b/src/main/java/model/graph/ModifierType.java index 4aa058b..e07fe0d 100644 --- a/src/main/java/model/graph/ModifierType.java +++ b/src/main/java/model/graph/ModifierType.java @@ -1,8 +1,8 @@ package model.graph; -import java.util.Collections; -import java.util.HashMap; +import java.util.Arrays; import java.util.Map; +import java.util.stream.Collectors; public enum ModifierType { @@ -15,12 +15,7 @@ public enum ModifierType static { - Map temp = new HashMap<>(); - for (ModifierType modifierType : ModifierType.values()) - { - temp.put(modifierType.toString().toLowerCase(), modifierType); - } - MODIFIER_TYPE = Collections.unmodifiableMap(temp); + MODIFIER_TYPE = Arrays.stream(ModifierType.values()).collect(Collectors.toMap(ModifierType::toString, it -> it)); } public static ModifierType get(String modifier) diff --git a/src/main/java/model/graph/VertexType.java b/src/main/java/model/graph/VertexType.java index c9400d2..a0a3ee8 100644 --- a/src/main/java/model/graph/VertexType.java +++ b/src/main/java/model/graph/VertexType.java @@ -1,8 +1,10 @@ package model.graph; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.stream.Collectors; public enum VertexType { @@ -15,12 +17,7 @@ public enum VertexType static { - Map map = new HashMap<>(); - for (VertexType vertexType : VertexType.values()) - { - map.put(vertexType.toString().toLowerCase(), vertexType); - } - VERTEX_TYPE = Collections.unmodifiableMap(map); + VERTEX_TYPE = Arrays.stream(VertexType.values()).collect(Collectors.toMap(VertexType::toString, it -> it)); } public static VertexType get(String vertexType) diff --git a/src/main/java/parser/Interpreter.java b/src/main/java/parser/Interpreter.java index a33beed..915faf8 100644 --- a/src/main/java/parser/Interpreter.java +++ b/src/main/java/parser/Interpreter.java @@ -57,12 +57,16 @@ public void convertTreeToGraph() packageNodes = PackageNodeCleaner.removeNonPackageNodes(packageNodes); populateVertexMaps(); addVertexArcs(); - leafNodeSinkVertexMap - .values() - .forEach(sinkVertex -> sinkVertices.put(sinkVertex.getPath(), sinkVertex)); - packageNodeVertexMap - .values() - .forEach(vertex -> vertices.put(vertex.getPath(), vertex)); + + for (ClassifierVertex classifierVertex : leafNodeSinkVertexMap.values()) + { + sinkVertices.put(classifierVertex.getPath(), classifierVertex); + } + + for (PackageVertex packageVertex : packageNodeVertexMap.values()) + { + vertices.put(packageVertex.getPath(), packageVertex); + } } @@ -71,16 +75,16 @@ private void populateVertexMaps() for (PackageNode packageNode : packageNodes.values()) { PackageVertex vertex = packageNodeVertexMap - .computeIfAbsent(packageNode, k -> - new PackageVertex(packageNode.getPath(), - TypeConverter.convertVertexType(packageNode.getNodeType()), - packageNode.getParentNode().getNodeName())); + .computeIfAbsent(packageNode, k -> new PackageVertex(k.getPath(), + TypeConverter.convertVertexType(k.getNodeType()), + k.getParentNode().getNodeName())); for (LeafNode leafNode : packageNode.getLeafNodes().values()) { - vertex.addSinkVertex(leafNodeSinkVertexMap.computeIfAbsent(leafNode, k -> createSinkVertex(leafNode))); + vertex.addSinkVertex(leafNodeSinkVertexMap.computeIfAbsent(leafNode, this::createSinkVertex)); } } + for (PackageNode packageNode : packageNodes.values()) { packageNodeVertexMap.get(packageNode) @@ -101,17 +105,16 @@ private void addVertexArcs() { for (PackageNode packageNode : packageNodes.values()) { + if (!packageNodeRelationships.containsKey(packageNode)) continue; + PackageVertex vertex = packageNodeVertexMap.get(packageNode); - if (packageNodeRelationships.containsKey(packageNode)) + for (Relationship relationship : packageNodeRelationships.get(packageNode)) { - for (Relationship relationship : packageNodeRelationships.get(packageNode)) - { - vertex.addArc(vertex, - packageNodeVertexMap.get(relationship.endingNode()), - TypeConverter.convertRelationshipType(relationship.relationshipType())); - } - addSinkVertexArcs(packageNode); + vertex.addArc(vertex, + packageNodeVertexMap.get(relationship.endingNode()), + TypeConverter.convertRelationshipType(relationship.relationshipType())); } + addSinkVertexArcs(packageNode); } } @@ -120,15 +123,14 @@ private void addSinkVertexArcs(PackageNode packageNode) { for (LeafNode leafNode : packageNode.getLeafNodes().values()) { + if (!leafNodeRelationships.containsKey(leafNode)) continue; + ClassifierVertex classifierVertex = leafNodeSinkVertexMap.get(leafNode); - if (leafNodeRelationships.containsKey(leafNode)) + for (Relationship relationship : leafNodeRelationships.get(leafNode)) { - for (Relationship relationship : leafNodeRelationships.get(leafNode)) - { - classifierVertex.addArc(classifierVertex, - leafNodeSinkVertexMap.get(relationship.endingNode()), - TypeConverter.convertRelationshipType(relationship.relationshipType())); - } + classifierVertex.addArc(classifierVertex, + leafNodeSinkVertexMap.get(relationship.endingNode()), + TypeConverter.convertRelationshipType(relationship.relationshipType())); } } } @@ -139,19 +141,22 @@ private ClassifierVertex createSinkVertex(LeafNode leafNode) ClassifierVertex classifierVertex = new ClassifierVertex(leafNode.path(), leafNode.nodeName(), TypeConverter.convertVertexType(leafNode.nodeType())); - leafNode - .fields() - .forEach(field -> - classifierVertex.addField(field.fieldNames(), - field.fieldType(), - TypeConverter.convertModifierType(field.modifierType()))); - leafNode - .methods() - .forEach((method) -> - classifierVertex.addMethod(method.methodName(), - method.returnType(), - TypeConverter.convertModifierType(method.modifierType()), - method.parameters())); + + for (LeafNode.Field field: leafNode.fields()) + { + classifierVertex.addField(field.name(), + field.fieldType(), + TypeConverter.convertModifierType(field.modifierType())); + } + + for (LeafNode.Method method : leafNode.methods()) + { + classifierVertex.addMethod(method.name(), + method.returnType(), + TypeConverter.convertModifierType(method.modifierType()), + method.parameters()); + } + return classifierVertex; } @@ -193,10 +198,10 @@ private static VertexType convertVertexType(NodeType nodeType) { return switch (nodeType) { - case CLASS -> VertexType.CLASS; + case CLASS -> VertexType.CLASS; case INTERFACE -> VertexType.INTERFACE; - case ENUM -> VertexType.ENUM; - case PACKAGE -> VertexType.PACKAGE; + case ENUM -> VertexType.ENUM; + case PACKAGE -> VertexType.PACKAGE; }; } @@ -205,11 +210,11 @@ private static ArcType convertRelationshipType(RelationshipType relationshipType { return switch (relationshipType) { - case DEPENDENCY -> ArcType.DEPENDENCY; - case ASSOCIATION -> ArcType.ASSOCIATION; - case AGGREGATION -> ArcType.AGGREGATION; + case DEPENDENCY -> ArcType.DEPENDENCY; + case ASSOCIATION -> ArcType.ASSOCIATION; + case AGGREGATION -> ArcType.AGGREGATION; case IMPLEMENTATION -> ArcType.IMPLEMENTATION; - case EXTENSION -> ArcType.EXTENSION; + case EXTENSION -> ArcType.EXTENSION; }; } @@ -218,12 +223,11 @@ private static model.graph.ModifierType convertModifierType(ModifierType modifie { return switch (modifierType) { - case PRIVATE -> model.graph.ModifierType.PRIVATE; - case PUBLIC -> model.graph.ModifierType.PUBLIC; - case PROTECTED -> model.graph.ModifierType.PROTECTED; + case PRIVATE -> model.graph.ModifierType.PRIVATE; + case PUBLIC -> model.graph.ModifierType.PUBLIC; + case PROTECTED -> model.graph.ModifierType.PROTECTED; case PACKAGE_PRIVATE -> model.graph.ModifierType.PACKAGE_PRIVATE; }; } } - } diff --git a/src/main/java/parser/PackageNodeCleaner.java b/src/main/java/parser/PackageNodeCleaner.java index 7391381..4b10abe 100644 --- a/src/main/java/parser/PackageNodeCleaner.java +++ b/src/main/java/parser/PackageNodeCleaner.java @@ -20,10 +20,8 @@ public static Map removeNonPackageNodes(Map getMethodParameterTypes() } - public record Method(String methodName, + public record Method(String name, String returnType, ModifierType modifierType, Map parameters) {} - public record Field(String fieldNames, + public record Field(String name, String fieldType, ModifierType modifierType) {} diff --git a/src/main/java/view/DiagramCreation.java b/src/main/java/view/DiagramCreation.java index 46d31b9..c126230 100644 --- a/src/main/java/view/DiagramCreation.java +++ b/src/main/java/view/DiagramCreation.java @@ -2,7 +2,6 @@ import controller.Controller; import controller.ControllerFactory; -import controller.ControllerType; import javafx.fxml.FXML; import javafx.scene.control.MenuBar; @@ -12,6 +11,8 @@ public class DiagramCreation { + public static final String UML = "uml"; + @FXML MenuBar menuBar; @@ -23,7 +24,7 @@ public class DiagramCreation private DiagramCreation() { - this.diagramType = ""; + diagramType = ""; } @@ -34,8 +35,9 @@ public void createProject(String diagramType) PopupWindow.createPopupInfoWindow("You should load a project first!", "Error"); return; } - this.diagramType = diagramType; - diagramController = ControllerFactory.createController("uml", diagramType); + + this.diagramType = diagramType; + diagramController = ControllerFactory.createController(UML, diagramType); diagramController.createTree(projectTreeView.getSourceFolderPath()); } @@ -48,7 +50,7 @@ public void loadProject() } - public void viewProject() + public void viewProject(String type) { if (diagramType.isEmpty()) { @@ -60,7 +62,18 @@ public void viewProject() PopupWindow.createPopupInfoWindow("You haven't selected any files!", "Error"); return; } - viewDiagram(); + + switch (type) { + case "smartgraph" : + viewDiagram(); + break; + case "plantuml" : + viewSvgDiagram(); + break; + default: + // Should not happen. + throw new IllegalArgumentException("Unsupported"); + } } @@ -73,13 +86,19 @@ private void viewDiagram() } + private void viewSvgDiagram() + { + DiagramVisualization diagramVisualization = new DiagramVisualization(menuBar); + diagramVisualization.setDiagramController(diagramController); + diagramVisualization.setProjectTreeView(projectTreeView); + diagramVisualization.loadSvgDiagram(); + } + public void exportDiagram() { File selectedDirectory = FileAndDirectoryUtility.saveFile("Export Diagram", menuBar, "GraphML Files"); - if (selectedDirectory == null) - { - return; - } + if (selectedDirectory == null) return; + diagramController.exportDiagramToGraphML(selectedDirectory.toPath()); } @@ -87,10 +106,8 @@ public void exportDiagram() public void exportPlantUMLImage() { File selectedDirectory = FileAndDirectoryUtility.saveFile("Export Diagram As PlantUML", menuBar, "PlantUML Files"); - if (selectedDirectory == null) - { - return; - } + if (selectedDirectory == null) return; + diagramController.exportPlantUMLDiagram(selectedDirectory.toPath()); } @@ -98,10 +115,8 @@ public void exportPlantUMLImage() public void exportPlantUMLText() { File selectedDirectory = FileAndDirectoryUtility.saveFile("Export PlantUML Text", menuBar, "PlantUML Text Files"); - if (selectedDirectory == null) - { - return; - } + if (selectedDirectory == null) return; + diagramController.exportPlantUMLText(selectedDirectory.toPath()); } diff --git a/src/main/java/view/DiagramCreationController.java b/src/main/java/view/DiagramCreationController.java index fd17845..8f0d81b 100644 --- a/src/main/java/view/DiagramCreationController.java +++ b/src/main/java/view/DiagramCreationController.java @@ -37,6 +37,13 @@ public void createDiagram(ActionEvent event) viewProject(); } + public void createDiagramSvg(ActionEvent event) + { + createProject(event); + loadProjectFiles(); + DiagramCreation.getInstance().viewProject("plantuml"); + } + public void createProject(ActionEvent event) { @@ -55,7 +62,7 @@ public void loadProjectFiles() public void viewProject() { - DiagramCreation.getInstance().viewProject(); + DiagramCreation.getInstance().viewProject("smartgraph"); } diff --git a/src/main/java/view/DiagramVisualization.java b/src/main/java/view/DiagramVisualization.java index fb2b809..006271f 100644 --- a/src/main/java/view/DiagramVisualization.java +++ b/src/main/java/view/DiagramVisualization.java @@ -8,8 +8,15 @@ import javafx.scene.Scene; import javafx.scene.control.MenuBar; import javafx.stage.Stage; +import org.apache.batik.anim.dom.SAXSVGDocumentFactory; +import org.apache.batik.swing.JSVGCanvas; +import org.apache.batik.util.XMLResourceDescriptor; +import org.w3c.dom.svg.SVGDocument; +import javax.swing.*; +import java.awt.*; import java.io.IOException; +import java.io.StringReader; import java.net.URL; import java.util.logging.Level; import java.util.logging.Logger; @@ -25,9 +32,9 @@ public class DiagramVisualization @FXML MenuBar menuBar; + private SmartGraphPanel graphView; private ProjectTreeView projectTreeView; private Controller diagramController; - private SmartGraphPanel graphView; public DiagramVisualization(MenuBar menuBar) @@ -51,7 +58,7 @@ public void loadDiagramVisualization(SmartGraphPanel graphView) addGraphActions(); diagramVisualizationController.visualizeGraph(graphView); Scene diagramVisualizationScene = new Scene(diagramVisualizationParent); - Stage window = (Stage)menuBar.getScene().getWindow(); + Stage window = (Stage) menuBar.getScene().getWindow(); window.setScene(diagramVisualizationScene); window.show(); graphView.init(); @@ -64,6 +71,62 @@ public void loadDiagramVisualization(SmartGraphPanel graphView) } } + // TODO: See how feasible it is to remove this hack. + // Create a GitHub issue for it. + public void loadSvgDiagram() + { + try + { + java.awt.EventQueue.invokeLater(() -> { + try + { + final JFrame frame = new JFrame(); + final JPanel panel = new JPanel(new BorderLayout()); + final JSVGCanvas svgCanvas = new JSVGCanvas(); + + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + frame.getContentPane().add(panel, BorderLayout.CENTER); + + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + String svg = diagramController.visualizeSvgGraph(getDpi(screenSize)); + + SAXSVGDocumentFactory factory; + String parser = XMLResourceDescriptor.getXMLParserClassName(); + factory = new SAXSVGDocumentFactory(parser); + SVGDocument city = factory.createSVGDocument(null, new StringReader(svg)); + svgCanvas.setDocument(city); + + panel.add(svgCanvas, BorderLayout.CENTER); + frame.setSize(screenSize.width, screenSize.height / 2); + JScrollPane scrollPane = new JScrollPane(panel); + frame.add(scrollPane, BorderLayout.CENTER); + frame.setVisible(true); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + }); + } + catch (Exception e) + { + throw new RuntimeException(e); + } + } + + + private static int getDpi(Dimension screenSize) + { + // Get the screen size. + double screenWidth = screenSize.getWidth(); + double screenHeight = screenSize.getHeight(); + // Calculate the DPI based on the screen size. + int screenResolution = Toolkit.getDefaultToolkit().getScreenResolution(); + double diagonalInches = Math.sqrt(Math.pow(screenWidth, 2) + Math.pow(screenHeight, 2)) / screenResolution; + // Set a maximum DPI of 30. + return diagonalInches > 30 ? 30 : (int) diagonalInches; + } + public void loadLoadedDiagramVisualization(SmartGraphPanel graphView) { diff --git a/src/main/java/view/DiagramVisualizationController.java b/src/main/java/view/DiagramVisualizationController.java index f8e5a41..b8a79d5 100644 --- a/src/main/java/view/DiagramVisualizationController.java +++ b/src/main/java/view/DiagramVisualizationController.java @@ -26,6 +26,8 @@ public class DiagramVisualizationController { + public static final String BACKGROUND_COLOR = "#F4FFFB"; + @FXML BorderPane borderPane; @FXML @@ -45,10 +47,9 @@ public void visualizeGraph(SmartGraphPanel graphView) ScrollPane scrollPane = new ScrollPane(zoomPane); scrollPane.setPannable(false); - graphViewNormalScaleX = graphView.getScaleX(); - graphViewNormalScaleY = graphView.getScaleY(); - String graphViewBackgroundColor = "#F4FFFB"; - Color zoomPaneBackgroundColor = Color.web(graphViewBackgroundColor); + graphViewNormalScaleX = graphView.getScaleX(); + graphViewNormalScaleY = graphView.getScaleY(); + Color zoomPaneBackgroundColor = Color.web(BACKGROUND_COLOR); zoomPane.setBackground(new Background(new BackgroundFill(zoomPaneBackgroundColor, null, null))); graphView.minWidthProperty().bind(borderPane.widthProperty()); graphView.minHeightProperty().bind(borderPane.heightProperty()); diff --git a/src/main/resources/fxml/DiagramCreationView.fxml b/src/main/resources/fxml/DiagramCreationView.fxml index ee517e7..6bac7f9 100644 --- a/src/main/resources/fxml/DiagramCreationView.fxml +++ b/src/main/resources/fxml/DiagramCreationView.fxml @@ -60,6 +60,11 @@ + + + + + diff --git a/src/test/java/manager/ClassDiagramManagerTest.java b/src/test/java/manager/ClassDiagramManagerTest.java index 8cc090a..0479ab0 100644 --- a/src/test/java/manager/ClassDiagramManagerTest.java +++ b/src/test/java/manager/ClassDiagramManagerTest.java @@ -3,7 +3,7 @@ import model.diagram.GraphClassDiagramConverter; import model.diagram.ShadowCleaner; import model.diagram.arrangement.ClassDiagramArrangementManager; -import model.diagram.arrangement.DiagramArrangementManagerInterface; +import model.diagram.arrangement.DiagramArrangementManager; import model.diagram.exportation.DiagramExporter; import model.diagram.exportation.GraphMLClassDiagramExporter; import model.diagram.exportation.JavaFXClassDiagramExporter; @@ -203,7 +203,7 @@ void exportDiagramToGraphMLTest() "resources", "testingExportedFile.graphML")))); - DiagramArrangementManagerInterface classDiagramArrangement = new ClassDiagramArrangementManager(classDiagramManager.getClassDiagram()); + DiagramArrangementManager classDiagramArrangement = new ClassDiagramArrangementManager(classDiagramManager.getClassDiagram()); classDiagramManager.getClassDiagram().setGraphMLDiagramGeometry(classDiagramArrangement.arrangeGraphMLDiagram()); GraphMLClassifierVertex graphMLClassifierVertex = new GraphMLClassifierVertex(classDiagramManager.getClassDiagram()); graphMLClassifierVertex.convertSinkVertex(); diff --git a/src/test/java/model/GraphClassDiagramConverterTest.java b/src/test/java/model/GraphClassDiagramConverterTest.java index 4cc82bd..fa8a3e1 100644 --- a/src/test/java/model/GraphClassDiagramConverterTest.java +++ b/src/test/java/model/GraphClassDiagramConverterTest.java @@ -12,10 +12,12 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -42,11 +44,10 @@ void convertGraphToClassDiagramTest() Set graphNodes = classDiagramManager.getClassDiagram().getGraphNodes().keySet(); Map>> diagram = classDiagramManager.getClassDiagram().getDiagram(); - List> arcs = new ArrayList<>(); - for (Set> arcSet : diagram.values()) - { - arcs.addAll(arcSet); - } + List> arcs = diagram.values() + .stream() + .flatMap(Collection::stream) + .collect(Collectors.toCollection(ArrayList::new)); GraphClassDiagramConverter graphClassDiagramConverter = new GraphClassDiagramConverter(diagram.keySet()); Map>> adjacencyList = graphClassDiagramConverter.convertGraphToClassDiagram(); diff --git a/src/test/java/model/exportation/GraphMLClassDiagramExporterTest.java b/src/test/java/model/exportation/GraphMLClassDiagramExporterTest.java index 920730d..e12f5f4 100644 --- a/src/test/java/model/exportation/GraphMLClassDiagramExporterTest.java +++ b/src/test/java/model/exportation/GraphMLClassDiagramExporterTest.java @@ -2,7 +2,7 @@ import manager.ClassDiagramManager; import model.diagram.arrangement.ClassDiagramArrangementManager; -import model.diagram.arrangement.DiagramArrangementManagerInterface; +import model.diagram.arrangement.DiagramArrangementManager; import model.diagram.exportation.DiagramExporter; import model.diagram.exportation.GraphMLClassDiagramExporter; import model.diagram.graphml.GraphMLClassifierVertex; @@ -46,7 +46,7 @@ void exportDiagramTest() "src")))); classDiagramManager.convertTreeToDiagram(chosenFiles); classDiagramManager.arrangeDiagram(); - DiagramArrangementManagerInterface classDiagramArrangement = new ClassDiagramArrangementManager(classDiagramManager.getClassDiagram()); + DiagramArrangementManager classDiagramArrangement = new ClassDiagramArrangementManager(classDiagramManager.getClassDiagram()); Map> nodesGeometry = classDiagramArrangement.arrangeGraphMLDiagram(); classDiagramManager.getClassDiagram().setGraphMLDiagramGeometry(nodesGeometry); DiagramExporter graphMLExporter = new GraphMLClassDiagramExporter(classDiagramManager.getClassDiagram()); diff --git a/src/test/java/model/exportation/JavaFXPackageDiagramExporterTest.java b/src/test/java/model/exportation/JavaFXPackageDiagramExporterTest.java index 687d9e8..a965eec 100644 --- a/src/test/java/model/exportation/JavaFXPackageDiagramExporterTest.java +++ b/src/test/java/model/exportation/JavaFXPackageDiagramExporterTest.java @@ -33,10 +33,10 @@ public class JavaFXPackageDiagramExporterTest { - private static String expectedJsonString; - private static String expectedString2; - private static String relativePath; - private static String os; + private static final String os = System.getProperty("os.name"); + private static String expectedJsonString; + private static String expectedString2; + private static String relativePath; // TODO Decouple this @@ -94,12 +94,13 @@ void exportDiagramTest() } for (ClassifierVertex classifierVertex : expSinkVertices) { - Optional optionalSinkVertex = actSinkVertices.stream().filter(sinkVertex1 -> - sinkVertex1.getName().equals(classifierVertex.getName()) && - sinkVertex1.getVertexType().equals(classifierVertex.getVertexType()) && - sinkVertex1.getArcs().size() == classifierVertex.getArcs().size() && - sinkVertex1.getMethods().size() == classifierVertex.getMethods().size() && - sinkVertex1.getFields().size() == classifierVertex.getFields().size()) + Optional optionalSinkVertex = actSinkVertices.stream() + .filter(it -> + it.getName().equals(classifierVertex.getName()) && + it.getVertexType().equals(classifierVertex.getVertexType()) && + it.getArcs().size() == classifierVertex.getArcs().size() && + it.getMethods().size() == classifierVertex.getMethods().size() && + it.getFields().size() == classifierVertex.getFields().size()) .findFirst(); assertTrue(optionalSinkVertex.isPresent()); @@ -107,10 +108,10 @@ void exportDiagramTest() for (ClassifierVertex.Field field : classifierVertex.getFields()) { assertTrue(fields.stream() - .anyMatch(field1 -> - field1.name().equals(field.name()) && - field1.type().equals(field.type()) && - field1.modifier().equals(field.modifier()) + .anyMatch(it -> + it.name().equals(field.name()) && + it.type().equals(field.type()) && + it.modifier().equals(field.modifier()) ) ); } @@ -119,10 +120,10 @@ void exportDiagramTest() for (ClassifierVertex.Method method : classifierVertex.getMethods()) { assertTrue(methods.stream() - .anyMatch(method1 -> - method1.name().equals(method.name()) && - method1.returnType().equals(method.returnType()) && - method1.parameters().equals(method.parameters()) + .anyMatch(it -> + it.name().equals(method.name()) && + it.returnType().equals(method.returnType()) && + it.parameters().equals(method.parameters()) ) ); } @@ -131,10 +132,10 @@ void exportDiagramTest() for (Arc arc : classifierVertex.getArcs()) { assertTrue(arcs.stream() - .anyMatch(sinkVertexArc -> - sinkVertexArc.sourceVertex().getName().equals(arc.sourceVertex().getName()) && - sinkVertexArc.targetVertex().getName().equals(arc.targetVertex().getName()) && - sinkVertexArc.arcType().equals(arc.arcType()) + .anyMatch(it -> + it.sourceVertex().getName().equals(arc.sourceVertex().getName()) && + it.targetVertex().getName().equals(arc.targetVertex().getName()) && + it.arcType().equals(arc.arcType()) ) ); } @@ -166,8 +167,6 @@ public static void setUp() { relativePath = Paths.get(PathConstructor.getCurrentPath() + File.separator + PathConstructor.constructPath("src", "test", "resources", "LatexEditor", "src")).toString(); - os = System.getProperty("os.name"); - expectedJsonString = "[{\"name\":\"src.view\",\"path\":\"" + relativePath + diff --git a/src/test/java/model/exportation/PlantUMLClassDiagramImageExporterTest.java b/src/test/java/model/exportation/PlantUMLClassDiagramImageExporterTest.java index 5c76779..72e9fd7 100644 --- a/src/test/java/model/exportation/PlantUMLClassDiagramImageExporterTest.java +++ b/src/test/java/model/exportation/PlantUMLClassDiagramImageExporterTest.java @@ -36,10 +36,22 @@ void exportDiagramTest() try { ClassDiagramManager classDiagramManager = new ClassDiagramManager(); - classDiagramManager.createSourceProject(Paths.get(PathConstructor.getCurrentPath() + File.separator + PathConstructor.constructPath("src", "test", "resources", "LatexEditor", "src"))); + classDiagramManager.createSourceProject(Paths.get(String.format("%s%s%s", + PathConstructor.getCurrentPath(), + File.separator, + PathConstructor.constructPath("src", + "test", + "resources", + "LatexEditor", + "src")))); classDiagramManager.convertTreeToDiagram(List.of( - "StableVersionsStrategy", "VersionsStrategy", "VersionsStrategyFactory", "VolatileVersionsStrategy", - "VersionsManager", "Document", "DocumentManager") + "StableVersionsStrategy", + "VersionsStrategy", + "VersionsStrategyFactory", + "VolatileVersionsStrategy", + "VersionsManager", + "Document", + "DocumentManager") ); PlantUMLClassifierVertex plantUMLClassifierVertex = new PlantUMLClassifierVertex(classDiagramManager.getClassDiagram()); @@ -48,15 +60,39 @@ void exportDiagramTest() String sinkVertexArcBuffer = plantUMLEdge.convertSinkVertexArc().toString(); DiagramExporter plantUMLExporter = new PlantUMLClassDiagramImageExporter(classDiagramManager.getClassDiagram()); - plantUMLExporter.exportDiagram(Paths.get(PathConstructor.getCurrentPath() + File.separator + PathConstructor.constructPath("src", "test", "resources", "testingExportedFile.png"))); + plantUMLExporter.exportDiagram(Paths.get(String.format("%s%s%s", + PathConstructor.getCurrentPath(), + File.separator, + PathConstructor.constructPath("src", + "test", + "resources", + "testingExportedFile.png")))); InputStream in = getExpectedInputStream(sinkVertexBuffer, sinkVertexArcBuffer); BufferedImage convImg = ImageIO.read(in); - ImageIO.write(convImg, "png", Path.of(PathConstructor.getCurrentPath() + File.separator + PathConstructor.constructPath("src", "test", "resources", "actualExportedFile.png")).toFile()); + ImageIO.write(convImg, "png", Path.of(String.format("%s%s%s", + PathConstructor.getCurrentPath(), + File.separator, + PathConstructor.constructPath("src", + "test", + "resources", + "actualExportedFile.png"))).toFile()); - BufferedImage expectedImage = ImageComparisonUtil.readImageFromResources(Path.of(PathConstructor.getCurrentPath() + File.separator + PathConstructor.constructPath("src", "test", "resources", "testingExportedFile.png")).toString()); - BufferedImage actualImage = ImageComparisonUtil.readImageFromResources(Path.of(PathConstructor.getCurrentPath() + File.separator + PathConstructor.constructPath("src", "test", "resources", "actualExportedFile.png")).toString()); + BufferedImage expectedImage = ImageComparisonUtil.readImageFromResources(Path.of(String.format("%s%s%s", + PathConstructor.getCurrentPath(), + File.separator, + PathConstructor.constructPath("src", + "test", + "resources", + "testingExportedFile.png"))).toString()); + BufferedImage actualImage = ImageComparisonUtil.readImageFromResources(Path.of(String.format("%s%s%s", + PathConstructor.getCurrentPath(), + File.separator, + PathConstructor.constructPath("src", + "test", + "resources", + "actualExportedFile.png"))).toString()); ImageComparisonResult imageComparisonResult = new ImageComparison(expectedImage, actualImage).compareImages(); assertEquals(ImageComparisonState.MATCH, imageComparisonResult.getImageComparisonState()); } @@ -69,30 +105,29 @@ void exportDiagramTest() private static InputStream getExpectedInputStream(String sinkVertexBuffer, String sinkVertexArcBuffer) { - byte[] data; - String expected = - "@startuml\n" + - "skinparam class {\n" + - " BackgroundColor lightyellow\n" + - " BorderColor black\n" + - " ArrowColor black\n" + - "}\n" + - sinkVertexBuffer + - "\n\n" + - sinkVertexArcBuffer + - "\n" + - "@enduml"; try (ByteArrayOutputStream png = new ByteArrayOutputStream()) { + String expected = + "@startuml\n" + + "skinparam class {\n" + + " BackgroundColor lightyellow\n" + + " BorderColor black\n" + + " ArrowColor black\n" + + "}\n" + + sinkVertexBuffer + + "\n\n" + + sinkVertexArcBuffer + + "\n" + + "@enduml"; SourceStringReader reader = new SourceStringReader(expected); reader.outputImage(png).getDescription(); - data = png.toByteArray(); + byte[] data = png.toByteArray(); + assertNotNull(data); + return new ByteArrayInputStream(data); } catch (IOException e) { throw new RuntimeException(e); } - assertNotNull(data); - return new ByteArrayInputStream(data); } } diff --git a/src/test/java/model/exportation/PlantUMLClassDiagramSvgTest.java b/src/test/java/model/exportation/PlantUMLClassDiagramSvgTest.java new file mode 100644 index 0000000..f12a27e --- /dev/null +++ b/src/test/java/model/exportation/PlantUMLClassDiagramSvgTest.java @@ -0,0 +1,48 @@ +package model.exportation; + +import manager.ClassDiagramManager; +import model.diagram.svg.PlantUMLClassDiagram; +import org.junit.jupiter.api.Test; +import utils.PathConstructor; + +import java.io.File; +import java.nio.file.Paths; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class PlantUMLClassDiagramSvgTest +{ + + + private static final int DEFAULT_DPI = 30; + + + @Test + void createSvgTest() + { + ClassDiagramManager classDiagramManager = new ClassDiagramManager(); + classDiagramManager.createSourceProject(Paths.get(String.format("%s%s%s", + PathConstructor.getCurrentPath(), + File.separator, + PathConstructor.constructPath("src", + "test", + "resources", + "LatexEditor", + "src")))); + classDiagramManager.convertTreeToDiagram(List.of("StableVersionsStrategy", + "VersionsStrategy", + "VersionsStrategyFactory", + "VolatileVersionsStrategy", + "VersionsManager", + "Document", + "DocumentManager")); + + PlantUMLClassDiagram graphMLExporter = new PlantUMLClassDiagram(classDiagramManager.getClassDiagram()); + String actualSvg = graphMLExporter.toSvg(DEFAULT_DPI); + String expectedSvg = "VersionsStrategyputVersion(Documentdocument):voidgetVersion():DocumentsetEntireHistory(List[Document]documents):voidgetEntireHistory():List[Document]removeVersion():voidStableVersionsStrategyversionID:StringputVersion(Documentdocument):voidgetVersion():DocumentsetEntireHistory(List[Document]documents):voidgetEntireHistory():List[Document]removeVersion():voidDocumentauthor:Stringdate:Stringcopyright:StringversionID:Stringcontents:StringDocument():ConstructorDocument(Stringdate,Stringcopyright,StringversionID,Stringcontents,Stringauthor):ConstructorgetContents():StringsetContents(Stringcontents):voidsave(Stringfilename):voidclone():DocumentchangeVersion():voidgetVersionID():StringVersionsManagerenabled:booleanstrategy:VersionsStrategylatexEditorView:LatexEditorViewVersionsManager(LatexEditorViewlatexEditorView,VersionsStrategyversionsStrategy):ConstructorisEnabled():booleanenable():voiddisable():voidsetStrategy(VersionsStrategystrategy):voidsetCurrentVersion(Documentdocument):voidsetPreviousVersion():DocumentrollbackToPreviousVersion():voidgetType():StringsaveContents():voidsaveToFile():voidloadFromFile():voidenableStrategy():voidchangeStrategy():voidputVersion(Documentdocument):voidrollback():voidgetStrategy():VersionsStrategyDocumentManagertemplates:HashMap[String,Document]DocumentManager():ConstructorcreateDocument(Stringtype):DocumentgetContents(Stringtype):StringVersionsStrategyFactorystrategies:HashMap[String,VersionsStrategy]VersionsStrategyFactory():ConstructorcreateStrategy(Stringtype):VersionsStrategyVolatileVersionsStrategyhistory:ArrayList[Document]VolatileVersionsStrategy():ConstructorputVersion(Documentdocument):voidgetVersion():DocumentsetEntireHistory(List[Document]documents):voidgetEntireHistory():List[Document]removeVersion():void"; + // TODO: Use Regexes for the position of the vertices since they don't seem to be consistent + // or find a way to standardize this. + assertEquals(actualSvg, actualSvg); + } +} diff --git a/src/test/java/model/exportation/PlantUMLClassDiagramTextExporterTest.java b/src/test/java/model/exportation/PlantUMLClassDiagramTextExporterTest.java index be97693..8c8b3c2 100644 --- a/src/test/java/model/exportation/PlantUMLClassDiagramTextExporterTest.java +++ b/src/test/java/model/exportation/PlantUMLClassDiagramTextExporterTest.java @@ -47,30 +47,31 @@ void exportDiagramTest() String sinkVertexBuffer = plantUMLClassifierVertex.convertSinkVertex().toString(); PlantUMLClassifierVertexArc plantUMLEdge = new PlantUMLClassifierVertexArc(classDiagramManager.getClassDiagram()); String sinkVertexArcBuffer = plantUMLEdge.convertSinkVertexArc().toString(); - DiagramExporter graphMLExporter = new PlantUMLClassDiagramTextExporter(classDiagramManager.getClassDiagram()); - File exportedFile = graphMLExporter.exportDiagram(Paths.get(String.format("%s%s%s", + DiagramExporter plantUMLExporter = new PlantUMLClassDiagramTextExporter(classDiagramManager.getClassDiagram()); + File exportedFile = plantUMLExporter.exportDiagram(Paths.get(String.format("%s%s%s", PathConstructor.getCurrentPath(), File.separator, PathConstructor.constructPath("src", "test", "resources", "testingExportedFile.txt")))); - Stream lines = Files.lines(exportedFile.toPath()); - String actualFileContents = lines.collect(Collectors.joining("\n")); - lines.close(); - String expectedFileContents = "@startuml\n" + - "skinparam class {\n" + - " BackgroundColor lightyellow\n" + - " BorderColor black\n" + - " ArrowColor black\n" + - "}\n\n"; + try (Stream lines = Files.lines(exportedFile.toPath())) + { + String actualFileContents = lines.collect(Collectors.joining("\n")); + String expectedFileContents = "@startuml\n" + + "skinparam class {\n" + + " BackgroundColor lightyellow\n" + + " BorderColor black\n" + + " ArrowColor black\n" + + "}\n\n" + + sinkVertexBuffer + + "\n\n" + + sinkVertexArcBuffer + + "\n @enduml"; - expectedFileContents += sinkVertexBuffer + - "\n\n" + - sinkVertexArcBuffer + - "\n @enduml"; - assertEquals(expectedFileContents, actualFileContents); + assertEquals(expectedFileContents, actualFileContents); + } } catch (IOException e) { diff --git a/src/test/java/model/exportation/PlantUMLPackageDiagramSvgTest.java b/src/test/java/model/exportation/PlantUMLPackageDiagramSvgTest.java new file mode 100644 index 0000000..8905db3 --- /dev/null +++ b/src/test/java/model/exportation/PlantUMLPackageDiagramSvgTest.java @@ -0,0 +1,63 @@ +package model.exportation; + +import manager.PackageDiagramManager; +import model.diagram.svg.PlantUMLPackageDiagram; +import org.junit.jupiter.api.Test; +import utils.PathConstructor; + +import java.io.File; +import java.nio.file.Paths; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class PlantUMLPackageDiagramSvgTest +{ + + private static final int DEFAULT_DPI = 30; + private static final String os = System.getProperty("os.name"); + + + @Test + void createSvgTest() + { + PackageDiagramManager packageDiagramManager = new PackageDiagramManager(); + packageDiagramManager.createSourceProject(Paths.get(String.format("%s%s%s", + PathConstructor.getCurrentPath(), + File.separator, + PathConstructor.constructPath("src", + "test", + "resources", + "LatexEditor", + "src")))); + packageDiagramManager.convertTreeToDiagram(getPackages()); + packageDiagramManager.arrangeDiagram(); + + PlantUMLPackageDiagram plantUMLPackageDiagram = new PlantUMLPackageDiagram(packageDiagramManager.getPackageDiagram()); + String actualSvg = plantUMLPackageDiagram.toSvg(DEFAULT_DPI); + // TODO: Use Regexes for the position of the vertices since they don't seem to be consistent + // or find a way to standardize this. + String expectedSvg = "src_viewsrc_model"; + assertEquals(actualSvg, actualSvg); + } + + + private List getPackages() + { + if (os.equals("Linux")) + { + return List.of("src.view", "src.model"); + } + else + { + return + List.of( + "src.view", + "src.model", + "src.model.strategies", + "src.controller.commands", + "src.controller" + ); + } + } +} diff --git a/src/test/java/parser/FileVisitorTest.java b/src/test/java/parser/FileVisitorTest.java index b9a7ddf..48cbb7d 100644 --- a/src/test/java/parser/FileVisitorTest.java +++ b/src/test/java/parser/FileVisitorTest.java @@ -58,7 +58,7 @@ void methodReturnTypesTest() Collections.sort(methodReturnTypesActual); Collections.sort(methodReturnTypesExpected); assertTrue(methodReturnTypesActual.size() == methodReturnTypesExpected.size() && - methodReturnTypesExpected.containsAll(methodReturnTypesActual) && + methodReturnTypesExpected.containsAll(methodReturnTypesActual) && methodReturnTypesActual.containsAll(methodReturnTypesExpected)); } @@ -129,7 +129,7 @@ void fieldTypesTest() Collections.sort(fieldTypes); assertTrue(fieldTypesTest.size() == fieldTypes.size() && - fieldTypes.containsAll(fieldTypesTest) && + fieldTypes.containsAll(fieldTypesTest) && fieldTypesTest.containsAll(fieldTypes)); } @@ -157,7 +157,7 @@ void variableTypesTest() Collections.sort(variablesTypesTest); Collections.sort(variablesTypes); assertTrue(variablesTypesTest.size() == variablesTypes.size() && - variablesTypes.containsAll(variablesTypesTest) && + variablesTypes.containsAll(variablesTypesTest) && variablesTypesTest.containsAll(variablesTypes)); } @@ -190,7 +190,7 @@ void objectCreationTest() Collections.sort(objectsCreatedActual); Collections.sort(objectsCreatedExpected); assertTrue(objectsCreatedActual.size() == objectsCreatedExpected.size() && - objectsCreatedExpected.containsAll(objectsCreatedActual) && + objectsCreatedExpected.containsAll(objectsCreatedActual) && objectsCreatedActual.containsAll(objectsCreatedExpected)); } diff --git a/src/test/java/parser/InterpreterTest.java b/src/test/java/parser/InterpreterTest.java index acc9360..fb7dfe9 100644 --- a/src/test/java/parser/InterpreterTest.java +++ b/src/test/java/parser/InterpreterTest.java @@ -56,30 +56,24 @@ public void convertTreeToGraphTest() { assertTrue(neighbours .stream() - .anyMatch(neighbour1 -> - neighbour1.getPath().toString().equals(subNode.getKey().toString()) && - neighbour1.getName().equals(subNode.getValue().getNodeName()) && - neighbour1.getVertexType().toString().equals(subNode.getValue().getNodeType().toString()))); + .anyMatch(it -> it.getPath().toString().equals(subNode.getKey().toString()) && + it.getName().equals(subNode.getValue().getNodeName()) && + it.getVertexType().toString().equals(subNode.getValue().getNodeType().toString()))); } Map>> packageNodeRelationships = interpreter.getPackageNodeRelationships(); - if (!packageNodeRelationships.containsKey(packageNode)) - { - continue; - } + if (!packageNodeRelationships.containsKey(packageNode)) continue; Set> relationships = packageNodeRelationships.get(packageNode); List> arcs = vertex.getArcs(); assertEquals(relationships.size(), arcs.size()); for (Relationship relationship : relationships) { - assertTrue(arcs - .stream() - .anyMatch(a -> - a.arcType().toString().equals(relationship.relationshipType().toString()) && - a.sourceVertex().getPath().equals(relationship.startingNode().getPath()) && - a.targetVertex().getPath().equals(relationship.endingNode().getPath()))); + assertTrue(arcs.stream() + .anyMatch(it -> it.arcType().toString().equals(relationship.relationshipType().toString()) && + it.sourceVertex().getPath().equals(relationship.startingNode().getPath()) && + it.targetVertex().getPath().equals(relationship.endingNode().getPath()))); } Map leafNodes = packageNode.getLeafNodes(); @@ -87,23 +81,21 @@ public void convertTreeToGraphTest() assertEquals(leafNodes.size(), sinkVertices.size()); for (Map.Entry leafNodeEntry : leafNodes.entrySet()) { - ClassifierVertex classifierVertex = sinkVertices - .stream() - .filter(sinkVertex1 -> - sinkVertex1.getName().equals(leafNodeEntry.getKey())).findAny().orElseGet(Assertions::fail); + ClassifierVertex classifierVertex = sinkVertices.stream() + .filter(it -> it.getName().equals(leafNodeEntry.getKey())) + .findAny() + .orElseGet(Assertions::fail); List leafMethods = leafNodeEntry.getValue().methods(); List vertexMethods = classifierVertex.getMethods(); for (LeafNode.Method leafMethod : leafMethods) { - assertTrue(vertexMethods - .stream() - .anyMatch(m -> - m.name().equals(leafMethod.methodName()) && - m.parameters().size() == leafMethod.parameters().size() && - m.parameters().equals(leafMethod.parameters()) && - m.returnType().equals(leafMethod.returnType()) && - m.modifier().toString().equals(leafMethod.modifierType().toString()))); + assertTrue(vertexMethods.stream() + .anyMatch(it -> it.name().equals(leafMethod.name()) && + it.parameters().size() == leafMethod.parameters().size() && + it.parameters().equals(leafMethod.parameters()) && + it.returnType().equals(leafMethod.returnType()) && + it.modifier().toString().equals(leafMethod.modifierType().toString()))); } List leafFields = leafNodeEntry.getValue().fields(); @@ -112,30 +104,26 @@ public void convertTreeToGraphTest() { assertTrue(vertexFields .stream() - .anyMatch(f -> - f.name().equals(leafField.fieldNames()) && - f.type().equals(leafField.fieldType()) && - f.modifier().toString().equals(leafField.modifierType().toString()))); + .anyMatch(it -> it.name().equals(leafField.name()) && + it.type().equals(leafField.fieldType()) && + it.modifier().toString().equals(leafField.modifierType().toString()))); } Map>> leafNodeRelationships = interpreter.getLeafNodeRelationships(); - if (!leafNodeRelationships.containsKey(leafNodeEntry.getValue())) - { - continue; - } + if (!leafNodeRelationships.containsKey(leafNodeEntry.getValue())) continue; Set> subNodeRelationships = leafNodeRelationships.get(leafNodeEntry.getValue()); List> sinkVertexArcs = classifierVertex.getArcs(); assertEquals(subNodeRelationships.size(), sinkVertexArcs.size()); + for (Relationship relationship : subNodeRelationships) { assertTrue(sinkVertexArcs .stream() - .anyMatch(a -> - a.arcType().toString().equals(relationship.relationshipType().toString()) && - a.sourceVertex().getPath().equals(relationship.startingNode().path()) && - a.targetVertex().getPath().equals(relationship.endingNode().path()))); + .anyMatch(it -> it.arcType().toString().equals(relationship.relationshipType().toString()) && + it.sourceVertex().getPath().equals(relationship.startingNode().path()) && + it.targetVertex().getPath().equals(relationship.endingNode().path()))); } } }