package org.jboss.windup.reporting.freemarker;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.forge.furnace.Furnace;
import org.jboss.forge.furnace.lock.LockMode;
import org.jboss.windup.config.GraphRewrite;
import org.jboss.windup.config.Variables;
import org.jboss.windup.config.operation.Iteration;
import org.jboss.windup.config.operation.iteration.AbstractIterationOperation;
import org.jboss.windup.reporting.model.ReportModel;
import org.jboss.windup.reporting.service.ReportService;
import org.jboss.windup.util.ExecutionStatistics;
import org.ocpsoft.rewrite.context.EvaluationContext;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
/**
* This class is used to produce a freemarker report from inside of a Windup {@link Iteration}.
*
* @author <a href="mailto:jesse.sightler@gmail.com">Jesse Sightler</a> <jesse.sightler@gmail.com)
*
*/
public class FreeMarkerIterationOperation extends AbstractIterationOperation<ReportModel>
{
private static final String DEFAULT_ITERATION_PAYLOAD_NAME = "reportModel";
private static final Logger LOG = Logger.getLogger(FreeMarkerIterationOperation.class.getName());
private final Furnace furnace;
private final Set<String> variableNames = new HashSet<>();
private final boolean useDefaultPayloadVariableName;
protected FreeMarkerIterationOperation(Furnace furnace, String... varNames)
{
super();
this.furnace = furnace;
useDefaultPayloadVariableName = true;
if (varNames != null)
{
variableNames.addAll(Arrays.asList(varNames));
}
}
protected FreeMarkerIterationOperation(Furnace furnace, String iterationVarName, String... varNames)
{
super(iterationVarName);
this.furnace = furnace;
useDefaultPayloadVariableName = false;
variableNames.add(iterationVarName);
if (varNames != null)
{
variableNames.addAll(Arrays.asList(varNames));
}
}
/**
* Create a FreeMarkerIterationOperation with the provided furnace instance, the provided iteration var, as well as any other associated variables
* (based upon variables in the Variables object).
*/
public static FreeMarkerIterationOperation create(Furnace furnace, String... varNames)
{
return new FreeMarkerIterationOperation(furnace, varNames);
}
@Override
public void perform(final GraphRewrite event, final EvaluationContext context, final ReportModel payload)
{
String templatePath = payload.getTemplatePath().replace('\\', '/');
String outputFilename = payload.getReportFilename();
ExecutionStatistics.get().begin("FreeMarkerIterationOperation.render(" + templatePath + ", " + outputFilename + ")");
try
{
ReportService reportService = new ReportService(event.getGraphContext());
Path outputDir = reportService.getReportDirectory();
if (!Files.isDirectory(outputDir))
{
Files.createDirectories(outputDir);
}
Path outputPath = outputDir.resolve(outputFilename);
LOG.info("Reporting: Writing template \"" + templatePath + "\" to output file \"" + outputPath.toAbsolutePath().toString() + "\"");
Configuration freemarkerConfig = FreeMarkerUtil.getDefaultFreemarkerConfiguration();
Template template = freemarkerConfig.getTemplate(templatePath);
Variables variables = Variables.instance(event);
// just the variables
Map<String, Object> vars = FreeMarkerUtil.findFreeMarkerContextVariables(variables,
variableNames.toArray(new String[variableNames
.size()]));
if (useDefaultPayloadVariableName)
{
vars.put(DEFAULT_ITERATION_PAYLOAD_NAME, payload);
}
vars.put("event", event);
// also, extension functions (these are kept separate from vars in order to prevent them
// from being stored in the associated data with the reportmodel)
final Map<String, Object> freeMarkerExtensions;
freeMarkerExtensions = furnace.getLockManager().performLocked(LockMode.WRITE, new Callable<Map<String, Object>>()
{
@Override
public Map<String, Object> call() throws Exception
{
return FreeMarkerUtil.findFreeMarkerExtensions(furnace, event);
}
});
Map<String, Object> objects = new HashMap<>(vars);
objects.putAll(freeMarkerExtensions);
try (FileWriter fw = new FileWriter(outputPath.toFile()))
{
template.process(objects, fw);
}
}
catch (IOException | TemplateException e)
{
LOG.log(Level.WARNING,
"\n Failed to write template: " + templatePath
+ "\n To: " + outputFilename
+ "\n Due to: " + e.getMessage(), e);
}
finally
{
ExecutionStatistics.get().end("FreeMarkerIterationOperation.render(" + templatePath + ", " + outputFilename + ")");
}
}
@Override
public String toString()
{
return "RenderFreeMarkerTemplate";
}
}