package com.lassekoskela.maven.timeline; import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.StringWriter; import java.io.Writer; import java.util.Map; import org.codehaus.plexus.logging.Logger; import com.github.mustachejava.DefaultMustacheFactory; import com.github.mustachejava.Mustache; import com.github.mustachejava.MustacheFactory; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableMap; import com.lassekoskela.maven.BuildTimelineExtension; import com.lassekoskela.maven.bean.Timeline; import com.lassekoskela.maven.timeline.GoalOrganizer.DisplayableGoal; public class Exporter { private static final String TEMPLATE_TIMELINE = "timeline.mustache"; private static final String TEMPLATE_BUILDITEM = "buildItem.mustache"; private static final String EXPORT_FILE = "timeline.html"; private final GoalOrganizer goalOrganizer; private final Mustache timelineMustache; private final Mustache buildItemMustache; public Exporter(Logger logger) throws FileNotFoundException { goalOrganizer = new GoalOrganizer(logger); ClassLoader classLoader = BuildTimelineExtension.class.getClassLoader(); MustacheFactory mustacheFactory = new DefaultMustacheFactory(); timelineMustache = compileTemplate(classLoader, mustacheFactory, TEMPLATE_TIMELINE); buildItemMustache = compileTemplate(classLoader, mustacheFactory, TEMPLATE_BUILDITEM); } private Mustache compileTemplate(ClassLoader ccl, MustacheFactory mf, String template) { return mf.compile(new InputStreamReader(ccl.getResourceAsStream(template)), template); } public File export(Timeline timeline) throws TimelineExportException { try { return serializeTimelineToFile(serializeBuildItems(timeline)); } catch (Exception e) { throw new TimelineExportException("Cannot export the timeline as an HTML page", e); } } private File serializeTimelineToFile(String serializedBuildItems) throws IOException { File exportFile = getExportFile(EXPORT_FILE); timelineMustache.execute(new FileWriter(exportFile), buildTimelineModel(serializedBuildItems)).flush(); return exportFile; } private String serializeBuildItems(Timeline timeline) throws IOException { Writer buildItemsWriter = new StringWriter(); for (DisplayableGoal displayableGoal : goalOrganizer.organize(timeline)) { buildItemMustache.execute(buildItemsWriter, buildItemModel(displayableGoal)); } buildItemsWriter.flush(); return buildItemsWriter.toString(); } @VisibleForTesting File getExportFile(String filePath) { File targetDir = new File("target"); targetDir.mkdirs(); File exportFile = new File(targetDir, filePath); if (exportFile.exists() && !exportFile.delete()) { throw new IllegalStateException("Cannot delete existing export file"); } return exportFile; } private Map<String, String> buildTimelineModel(String serializedBuildItems) { return ImmutableMap.of("timeline", serializedBuildItems); } @VisibleForTesting Map<String, String> buildItemModel(DisplayableGoal goal) { return ImmutableMap.of("projectId", goal.getProjectId(), "phaseId", goal.getPhaseId(), "goalId", goal.getGoalId(), "projectDeps", goal.getDependencies(), "cssStyle", cssStyle(goal)); } @VisibleForTesting String cssStyle(DisplayableGoal goal) { return String.format("height:%dpx;top:%dpx;left:%dpx;", goal.getHeightPosition(), goal.getTopPosition(), goal.getLeftPosition()); } }