output.TikzTex.java Source code

Java tutorial

Introduction

Here is the source code for output.TikzTex.java

Source

/*
 * Copyright 2016 Sven Wiemann
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 
 * this file except in compliance with the License. You may obtain a copy of the 
 * License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed 
 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES 
 * OR CONDITIONS OF ANY KIND, either express or implied. See the License for 
 * the specific language governing permissions and limitations under the License.
 */
package output;

import java.awt.Image;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.text.StrSubstitutor;

/**
 * Create a Tikz/PGF Graph based upon the test data.
 * @author Sven Wiemann
 *
 */
public class TikzTex {
    // The Folder the output should be written to
    private String outputDir = "src/main/resources/output/";

    public TikzTex(String outputDir) {
        this.outputDir = outputDir;
    }

    /**
     * Use PDF-Latex to parse the .tex file
     * @param file the source File containing the Data
     * @throws IOException
     */
    public void genPdf(File file) throws IOException {
        ProcessBuilder pb = new ProcessBuilder("pdflatex", "-shell-escape", file.getAbsolutePath());
        File directory = new File(outputDir);
        pb.directory(directory);

        Process p;
        try {
            p = pb.start();
            // We need to parse the Error and the Output generated by pdflatex
            StreamGobbler errorGobbler = new StreamGobbler(p.getErrorStream(), "ERROR");
            StreamGobbler outputGobbler = new StreamGobbler(p.getInputStream(), "OUTPUT");
            errorGobbler.start();
            outputGobbler.start();
            // Wait until its done
            int exitVal = p.waitFor();

            // Spawn a Frame with the Image
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            String imgPath = file.getAbsolutePath().substring(0, file.getAbsolutePath().length() - 4) + ".png";
            ImageIcon icon = new ImageIcon(imgPath);
            // resize
            Image img = icon.getImage();
            double ratio = (double) icon.getIconWidth() / icon.getIconHeight();
            Image newimg = img.getScaledInstance((int) (Math.round(600 * ratio)), 600, java.awt.Image.SCALE_SMOOTH);
            icon = new ImageIcon(newimg);
            JLabel imgLabel = new JLabel(icon);
            JScrollPane scrollPanel = new JScrollPane(imgLabel);

            frame.getContentPane().add(scrollPanel);
            frame.setSize(1280, 720);
            frame.setVisible(true);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * Replace the Patterns in the Template.tex File with the actual Data.
     * The y-axis contains the runtimes
     * @param texFile template File
     * @param dataFile File with the Test results
     * @param xDef which column of the Test results should be used on the x-axis
     * @param title Title of the Graph
     * @param xDesc Description of the x-Axis
     * @return
     * @throws IOException
     */
    public File insertAlgorithmResults(File texFile, File dataFile, String xDef, String title, String xDesc)
            throws IOException {
        Map<String, String> valuesMap = new HashMap<>();
        String dataString = readDataFile(dataFile);
        // Put the Patterns and the replacements into a map
        valuesMap.put("ALGORITHM_RESULTS", dataString);
        valuesMap.putAll(getAlgorithms(dataFile));
        valuesMap.put("Cat", xDef);
        valuesMap.put("Title", title);
        valuesMap.put("xDesc", xDesc);
        valuesMap.put("yDef", "CalcTime");
        valuesMap.put("yDesc", "Laufzeit in Sek.");

        // Write the complete file
        Path path = Paths.get(texFile.getAbsolutePath());
        String content = new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
        StrSubstitutor sub = new StrSubstitutor(valuesMap);
        content = sub.replace(content);
        File output = new File(outputDir + System.currentTimeMillis() + ".tex");
        FileUtils.writeStringToFile(output, content, StandardCharsets.UTF_8);
        return output;
    }

    /**
     * Replace the Patterns in the Template.tex File with the actual Data
     * The content of the y-Axis could be replaced by this method.
     * @param texFile template File
     * @param dataFile File with the Test results
     * @param xDef which column of the Test results should be used on the x-axis
     * @param title Title of the Graph
     * @param xDesc Description of the x-Axis
     * @param yDef which column of the Test results should be used on the y-axis
     * @param yDesc Description of the y-Axis
     * @return
     * @throws IOException
     */
    public File insertAlgorithmResults(File texFile, File dataFile, String xDef, String title, String xDesc,
            String yDef, String yDesc) throws IOException {
        Map<String, String> valuesMap = new HashMap<>();
        String dataString = readDataFile(dataFile);
        // Put the Patterns and the replacements into a map
        valuesMap.put("ALGORITHM_RESULTS", dataString);
        valuesMap.putAll(getAlgorithms(dataFile));
        valuesMap.put("Cat", xDef);
        valuesMap.put("Title", title);
        valuesMap.put("xDesc", xDesc);
        valuesMap.put("yDef", yDef);
        valuesMap.put("yDesc", yDesc);

        // Write the complete file
        Path path = Paths.get(texFile.getAbsolutePath());
        String content = new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
        StrSubstitutor sub = new StrSubstitutor(valuesMap);
        content = sub.replace(content);
        File output = new File(outputDir + System.currentTimeMillis() + ".tex");
        FileUtils.writeStringToFile(output, content, StandardCharsets.UTF_8);
        return output;
    }

    /**
     * Which Algorithms are used in the Test?
     * @param dataFile
     * @return
     * @throws IOException
     */
    public Map<String, String> getAlgorithms(File dataFile) throws IOException {
        Map<String, String> valuesMap = new HashMap<>();
        BufferedReader br = new BufferedReader(new FileReader(dataFile));
        String line = br.readLine(); // reject first line
        line = br.readLine();
        int i = 1;

        // Read every data file, new Algorithm found? Put it into the Map!
        while (line != null) {
            String[] values = line.split("\t");
            if (!valuesMap.containsValue(values[values.length - 1])) {
                valuesMap.put("Algo" + i, values[values.length - 1]);
                i++;
            }
            line = br.readLine();
        }
        br.close();

        return valuesMap;
    }

    public String readDataFile(File dataFile) throws IOException {
        return new String(Files.readAllBytes(Paths.get(dataFile.getAbsolutePath())), StandardCharsets.UTF_8);
    }
}

/**
 * Based upon http://www.javaworld.com/article/2071275/core-java/when-runtime-exec---won-t.html by Michael C. Daconta
 *
 */
class StreamGobbler extends Thread {
    InputStream inputStream;
    String type;

    StreamGobbler(InputStream inputStream, String type) {
        this.inputStream = inputStream;
        this.type = type;
    }

    public void run() {
        try {
            InputStreamReader inputReader = new InputStreamReader(inputStream);
            BufferedReader br = new BufferedReader(inputReader);
            String line = br.readLine();
            while (line != null) {
                line = br.readLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}