summaryrefslogtreecommitdiff
path: root/support/latex-dependency-grapher/source/main/java/ch/bfh/lpdg/GraphHelper.java
diff options
context:
space:
mode:
Diffstat (limited to 'support/latex-dependency-grapher/source/main/java/ch/bfh/lpdg/GraphHelper.java')
-rw-r--r--support/latex-dependency-grapher/source/main/java/ch/bfh/lpdg/GraphHelper.java181
1 files changed, 181 insertions, 0 deletions
diff --git a/support/latex-dependency-grapher/source/main/java/ch/bfh/lpdg/GraphHelper.java b/support/latex-dependency-grapher/source/main/java/ch/bfh/lpdg/GraphHelper.java
new file mode 100644
index 0000000000..fd6a754b7d
--- /dev/null
+++ b/support/latex-dependency-grapher/source/main/java/ch/bfh/lpdg/GraphHelper.java
@@ -0,0 +1,181 @@
+package ch.bfh.lpdg;
+
+import ch.bfh.lpdg.datastructure.Dependency;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.*;
+
+public class GraphHelper {
+
+ public final static GraphHelper INSTANCE = new GraphHelper();
+ private final InteractionHandler interactionHandler = InteractionHandler.getInstance();
+
+ private GraphHelper() {
+ }
+
+ public static GraphHelper getInstance() {
+ return INSTANCE;
+ }
+
+ /**
+ * This method creates a new .tex file containing a list of the found dependencies and the dependeccy graph created with Graphviz
+ *
+ * @param dependency for which the .tex file should be created
+ * @param outputPath in which the created file should be located.
+ * @return the path of the newly created .tex file.
+ */
+ public Path createFileForDependency(final Dependency dependency, final String outputPath) {
+ final String dependencyFileName = "dependencies_" + dependency.getName() + ".tex";
+ final String dependencyFilePath = outputPath + dependencyFileName;
+ var dependencyFile = new File(outputPath + dependencyFileName);
+
+ var latexHelper = new LatexHelper();
+ this.writeDependencyToFile(dependencyFile, dependency);
+
+ var result = latexHelper.compileTempDocument(outputPath, dependencyFilePath);
+ interactionHandler.printDebugMessage(String.valueOf(result));
+
+ if (!generatePdfFromDotFile(outputPath + "dependencyGraph.dot")) {
+ interactionHandler.printDebugMessage("Something went wrong trying to generate a pdf from the dot file.");
+ }
+
+ //Second compile cycle to include the generated graph in the file.
+ var result2 = latexHelper.compileTempDocument(outputPath, dependencyFilePath);
+ interactionHandler.printDebugMessage(String.valueOf(result2));
+
+ return dependencyFile.toPath();
+ }
+
+ /**
+ * This method created the .tex file containing a list of the dependencies and its graph.
+ *
+ * @param file in which should be written
+ * @param dependency the dependency for which the graph should be created
+ */
+ private void writeDependencyToFile(final File file, final Dependency dependency) {
+ try {
+ final String dependencyList = dependency.toLaTeXString();
+ final String graphString = dependency.toGraphString();
+ final String truncatedGraphString = this.truncateGraphString(graphString);
+ final String reorganizedGraphString = this.reorganizeGraphString(truncatedGraphString);
+
+ BufferedWriter writer = Files.newBufferedWriter(file.toPath());
+ writer.write("""
+ \\documentclass{article}
+ \\usepackage[pdf]{graphviz}
+ \\usepackage{pdflscape}
+ \\begin{document}
+ \\begin{verbatim}
+ """);
+ writer.write(dependencyList);
+ writer.write("\\end{verbatim}\n");
+
+ if (dependency.getDependencyList().size() != 0) {
+ writer.write("\\pagebreak\n");
+ writer.write("\\begin{landscape}\n");
+ writer.write("\\digraph{dependencyGraph}{\n");
+ writer.write("\tnewrank=true;\n\t");
+ writer.write("\trank=\"same\";\n\t");
+ writer.write("\trankdir=TB;\n\t");
+ writer.write("\tratio=\"fill\";\n\t");
+ writer.write("\tsize=\"8.3,11.7!\";\n\t");
+ writer.write("\tmargin=0;\n\t");
+ writer.write(reorganizedGraphString);
+ writer.write("}\n");
+ writer.write("\\end{landscape}\n");
+ }
+
+ writer.write("\\end{document}\n");
+ writer.close();
+ } catch (IOException e) {
+ System.err.println("Error in the temporary file: " + e);
+ }
+ }
+
+ /**
+ * Removes duplicated lines from graphString
+ *
+ * @param graphString for which duplicated lines should be removed
+ * @return a truncated string
+ */
+ private String truncateGraphString(final String graphString) {
+ StringBuilder builder = new StringBuilder();
+ for (String line : new LinkedHashSet<>(Arrays.asList(graphString.split("\n")))) {
+ builder.append(line).append("\n");
+ }
+ return builder.toString();
+ }
+
+ private String reorganizeGraphString(String graphString) {
+ StringBuilder result = new StringBuilder();
+ String[] lines = graphString.split("\n");
+
+ Map<String, Integer> lastOccurrences = new LinkedHashMap<>();
+
+ // Iterate to find the last occurrence index for each node
+ for (int i = 0; i < lines.length; i++) {
+ String line = lines[i].trim();
+ if (!line.isEmpty()) {
+ String[] parts = line.split(" -> ");
+ String rightNode = parts[1].substring(0, parts[1].indexOf(';')).trim();
+ lastOccurrences.put(rightNode, i);
+ }
+ }
+
+ // Append lines with the last occurrences
+ for (int i : lastOccurrences.values()) {
+ result.append(lines[i]).append("\n");
+ }
+
+ // Append lines with other occurrences
+ for (int i = 0; i < lines.length; i++) {
+ String line = lines[i].trim();
+ if (!line.isEmpty()) {
+ String[] parts = line.split(" -> ");
+ String rightNode = parts[1].substring(0, parts[1].indexOf(';')).trim();
+
+ // Skip if it's the last occurrence
+ if (i != lastOccurrences.get(rightNode)) {
+ result.append(lines[i]).append("\n");
+ }
+ }
+ }
+
+ return result.toString();
+ }
+
+ /**
+ * This method generated a pdf document for the .dot document.
+ * This is required to include it to the .tex document given to the user.
+ *
+ * @param dependencyGraphPath of the generated .dot file
+ * @return if the generation was successful or not
+ */
+ private boolean generatePdfFromDotFile(final String dependencyGraphPath) {
+ try {
+ List<String> cmd = Arrays.asList(
+ "dot",
+ "-Tpdf",
+ "-o", dependencyGraphPath.replace("dot", "pdf"),
+ dependencyGraphPath);
+
+ ProcessBuilder processBuilder = new ProcessBuilder(cmd);
+
+ // Redirect the error stream to the output stream
+ processBuilder.redirectErrorStream(true);
+
+ Process process = processBuilder.start();
+
+ var res = process.waitFor();
+
+ return res == 0;
+ } catch (Exception e) {
+ System.err.println("Error while compiling the dot file to pdf: " + e);
+ return false;
+ }
+ }
+} \ No newline at end of file