summaryrefslogtreecommitdiff
path: root/support/latex-dependency-grapher/source/main/java/ch/bfh/lpdg/LatexHelper.java
blob: a77a0e61839b4925016c6a6882c4ffade824cc20 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package ch.bfh.lpdg;

import ch.bfh.lpdg.datastructure.Dependency;
import ch.bfh.lpdg.datastructure.DependencyType;
import lombok.NoArgsConstructor;
import org.springframework.util.FileSystemUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@NoArgsConstructor
public class LatexHelper {

    private final InteractionHandler interactionHandler = InteractionHandler.getInstance();
    private Path tempFile;
    private Path sourceFile;
    private Path tempFolder;
    private Dependency dependencies;

    public LatexHelper(File file, Dependency dependencies) throws IOException {
        this.dependencies = dependencies;
        this.tempFile = createTempFile(file, ".temp");
        this.sourceFile = file.toPath();
        this.tempFolder = createTempFolder(Paths.get(file.getParent()));
        interactionHandler.printDebugMessage("Temp-File has been created. " + tempFile);
    }

    private static String getFileExtension(String fileName) {
        int lastDotIndex = fileName.lastIndexOf(".");
        return (lastDotIndex != -1) ? fileName.substring(lastDotIndex) : "";
    }

    public void findUnnecessaryDependencies(Boolean overwrite, Boolean minimize) throws IOException {
        this.interactionHandler.printDebugMessage("Finding unnecessary Dependencies.");
        List<Dependency> unnecessaryDependencies = new ArrayList<>();
        for (var dep : dependencies.getDependencyList()) {
            if(dep.getType() != DependencyType.REQUIRE_PACKAGE && dep.getType() != DependencyType.USE_PACKAGE)
                continue;
            this.interactionHandler.printDebugMessage("Trying without " + dep.toString());
            this.replaceDependency(tempFile, dep.getSource(), "%" + dep.getSource());
            if (this.compileTempDocument(tempFolder.toAbsolutePath().toString(), tempFile.toAbsolutePath().toString())) {
                unnecessaryDependencies.add(dep);
                dep.IsUnused = true;
            }
            this.replaceDependency(tempFile, "%" + dep.getSource(), dep.getSource());
        }
        this.deleteTempFiles();

        if(unnecessaryDependencies.size() > 0) {
            System.out.println("\nThe following Packages are not needed:");
            for (var dep : unnecessaryDependencies)
                System.out.println("\t" + dep.getName());
        }

        if (minimize || overwrite) {
            Path fileToMinimize = overwrite ? this.sourceFile : createTempFile(sourceFile.toFile(), ".minimized");
            this.writeMinimizedFile(fileToMinimize);
        }
    }

    public boolean compileTempDocument(final String outputDirectory, final String documentToCompile) {
        try {
            List<String> cmd = Arrays.asList(
                    "pdflatex", //We use pdflatex to compile the documents.
                    "-output-directory", outputDirectory, //Set the output directory to the created tempFolder directory of the input
                    "-interaction", "nonstopmode",
                    "-halt-on-error",
                    "-file-line-error",
                    documentToCompile);
            this.interactionHandler.printDebugMessage("Running: " + cmd);
            ProcessBuilder processBuilder = new ProcessBuilder(cmd);

            // Redirect the error stream to the output stream
            processBuilder.redirectErrorStream(true);

            Process process = processBuilder.start();
            InputStream is = process.getInputStream();
            int readBytes;
            byte[] buffer = new byte[1024];
            StringBuilder outputBuilder = new StringBuilder();

            while ((readBytes = is.read(buffer)) != -1) {
                String chunk = new String(buffer, 0, readBytes, StandardCharsets.UTF_8);
                outputBuilder.append(chunk);
            }
            this.interactionHandler.printDebugMessage(outputBuilder.toString());

            var res = process.waitFor();
            this.interactionHandler.printDebugMessage("ReturnCode: " + res);
            return res == 0;
        } catch (Exception e) {
            System.err.println("Error while compiling the temporary file: " + e);
            return false;
        }
    }

    private void writeMinimizedFile(Path minimizedFile) {
        for (var dep : dependencies.getDependencyList()) {
            if (!dep.IsUnused)
                continue;
            replaceDependency(minimizedFile, dep.getSource(), "%" + dep.getSource());
        }
    }

    private void replaceDependency(Path file, String dependency, String replaceWith) {
        this.interactionHandler.printDebugMessage("Replacing " + dependency + " with " + replaceWith);
        try {
            BufferedReader reader = Files.newBufferedReader(file);
            StringBuilder content = new StringBuilder();

            String row;
            while ((row = reader.readLine()) != null) {
                content.append(row).append(System.lineSeparator());
            }

            String newContent = content.toString().replace(dependency, replaceWith);

            BufferedWriter writer = Files.newBufferedWriter(file);
            writer.write(newContent);

            reader.close();
            writer.close();
        } catch (IOException e) {
            System.err.println("Error in the temporary file: " + e);
        }
    }

    private Path createTempFile(File file, String identifier) throws IOException {
        var extension = getFileExtension(file.getName());
        return Files.copy(Paths.get(file.getAbsolutePath()), Paths.get(file.getPath().replace(extension, identifier + extension)), StandardCopyOption.REPLACE_EXISTING);
    }

    private Path createTempFolder(Path parentDirectory) throws IOException {
        return Files.createTempDirectory(parentDirectory, "LatexDependencyTemp");
    }

    private void deleteTempFiles() throws IOException {
        FileSystemUtils.deleteRecursively(tempFolder.toFile());
        Files.delete(tempFile);
    }
}