package com.github.shell88.bddvideoannotator.annotationfile.exporter; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.github.shell88.bddvideoannotator.annotationfile.converter.GsonEscapeStringSerializer; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URISyntaxException; import java.net.URL; import java.net.URLDecoder; import java.util.Enumeration; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; /** * Exports Annotations to a HTML-Report. The Codec of the video file must be * supported by the browser that you want to view with it, see also * {@link com.github.shell88.bddvideoannotator.annotationfile.converter.HtmlConverter} * Can be used to export multiple Scenarios to a single index.html. * @author Hell * */ public class HtmlAnnotationExporter extends AnnotationExporter { private Gson gson; private final String htmlResourcesFolder = "htmlconverter"; private final String fileNameTargetHtml = "index.html"; private boolean assetsCopied = false; private JsonArray bufferedScenarios; /** * @param outputDir - Directory where to store the htmlReport. */ public HtmlAnnotationExporter(File outputDir) { super(outputDir); GsonBuilder builder = new GsonBuilder(); builder.setPrettyPrinting(); builder.registerTypeAdapter(String.class, new GsonEscapeStringSerializer()); this.gson = builder.create(); bufferedScenarios = new JsonArray(); } @Override public void write(ScenarioAnnotationsDto exportable) throws IOException { if (!assetsCopied) { copyAssetsToOutputDirectory(); } JsonObject scenario = scenarioToJsonObject(exportable.getFeatureText(), exportable.getScenarioText(), exportable.getStepAnnotations(), exportable.getNameVideoFile()); // Every Scenario for the output-Index.html is buffered here // => each write command will write all Scenarios so that // index.html is consistent at any point in time bufferedScenarios.add(scenario); writeScenarioJsonObjectsToHtmlTemplate(bufferedScenarios); } private void copyAssetsToOutputDirectory() throws IOException { URL htmlResourceFolderUrl = ClassLoader .getSystemResource(htmlResourcesFolder); if (htmlResourceFolderUrl == null) { throw new IOException("Cannot find html resource folder " + htmlResourcesFolder); } if (htmlResourceFolderUrl.getProtocol().equals("jar")) { //Needed so that converter can also used from the standalone server jar String jarPath = htmlResourceFolderUrl.getPath().substring(5, htmlResourceFolderUrl.getPath().indexOf("!")); //strip out only the JAR file JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8")); Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar JarEntry entry; while (entries.hasMoreElements()) { entry = entries.nextElement(); if (!entry.isDirectory() && entry.getName().startsWith(htmlResourcesFolder)) { InputStream in = jar.getInputStream(entry); FileUtils.copyInputStreamToFile(in, new File(getOutputDirectory(), entry.getName() .replaceFirst(htmlResourcesFolder, ""))); } } jar.close(); assetsCopied = true; } else { File htmlResource; try { htmlResource = new File(htmlResourceFolderUrl.toURI()); if (htmlResource.list().length == 0) { throw new IOException(this.htmlResourcesFolder + " is empty!"); } FileUtils.copyDirectory(htmlResource, this.getOutputDirectory()); } catch (URISyntaxException e) { throw new IOException("Cannot read htmlResourceFolder: " + e.getMessage()); } assetsCopied = true; } } private JsonObject scenarioToJsonObject(String featureText, String scenarioName, List<StepAnnotation> steps, String nameVideoFile) { JsonElement stepsAsJson = gson.toJsonTree(steps); JsonObject scenarioJson = new JsonObject(); scenarioJson.addProperty("featuretext", featureText); scenarioJson.addProperty("scenarioname", scenarioName); scenarioJson.addProperty("video", nameVideoFile); scenarioJson.add("steps", stepsAsJson); return scenarioJson; } private void writeScenarioJsonObjectsToHtmlTemplate(JsonArray arrayScenarios) throws IOException { File indexFileCopy = new File(this.getOutputDirectory(), fileNameTargetHtml); String content = FileUtils.readFileToString(indexFileCopy, "UTF-8"); content = content.replaceFirst("scenarios=[^;]*", "scenarios=" + gson.toJson(arrayScenarios)); FileUtils.writeStringToFile(indexFileCopy, content); } }