package org.jboss.windup.reporting.freemarker;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapperBuilder;
import org.jboss.forge.furnace.Furnace;
import org.jboss.forge.furnace.services.Imported;
import org.jboss.windup.config.GraphRewrite;
import org.jboss.windup.config.Variables;
import org.jboss.windup.config.operation.Iteration;
import org.jboss.windup.graph.model.WindupVertexFrame;
import org.jboss.windup.util.exception.WindupException;
import freemarker.template.SimpleScalar;
import freemarker.template.SimpleSequence;
/**
* This class contains several useful utility functions that can be used for rendering a freemarker template within Windup.
*
*/
public class FreeMarkerUtil
{
/**
* Gets the default configuration for Freemarker within Windup.
*/
public static Configuration getDefaultFreemarkerConfiguration()
{
freemarker.template.Configuration configuration = new freemarker.template.Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
DefaultObjectWrapperBuilder objectWrapperBuilder = new DefaultObjectWrapperBuilder(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
objectWrapperBuilder.setUseAdaptersForContainers(true);
configuration.setObjectWrapper(objectWrapperBuilder.build());
configuration.setAPIBuiltinEnabled(true);
configuration.setTemplateLoader(new FurnaceFreeMarkerTemplateLoader());
configuration.setTemplateUpdateDelayMilliseconds(3600);
return configuration;
}
/**
* Converts a FreeMarker {@link SimpleSequence} to a {@link Set}.
*
*/
public static Set<String> simpleSequenceToSet(SimpleSequence simpleSequence)
{
if (simpleSequence == null)
return Collections.emptySet();
Set<String> result = new HashSet<>();
for (int i = 0; i < simpleSequence.size(); i++)
{
try
{
Object sequenceEntry = simpleSequence.get(i);
if (sequenceEntry instanceof SimpleScalar)
{
result.add(((SimpleScalar) sequenceEntry).getAsString());
}
else
{
result.add(simpleSequence.get(i).toString());
}
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
return result;
}
/**
* Gets freemarker extensions (eg, custom functions) provided by furnace addons
*/
public static Map<String, Object> findFreeMarkerExtensions(Furnace furnace, GraphRewrite event)
{
Imported<WindupFreeMarkerMethod> freeMarkerMethods = furnace.getAddonRegistry().getServices(
WindupFreeMarkerMethod.class);
Map<String, Object> results = new HashMap<>();
for (WindupFreeMarkerMethod freeMarkerMethod : freeMarkerMethods)
{
freeMarkerMethod.setContext(event);
if (results.containsKey(freeMarkerMethod.getMethodName()))
{
throw new WindupException("Windup contains two freemarker extension providing the same name: "
+ freeMarkerMethod.getMethodName());
}
results.put(freeMarkerMethod.getMethodName(), freeMarkerMethod);
}
Imported<WindupFreeMarkerTemplateDirective> freeMarkerDirectives = furnace.getAddonRegistry().getServices(
WindupFreeMarkerTemplateDirective.class);
for (WindupFreeMarkerTemplateDirective freeMarkerDirective : freeMarkerDirectives)
{
freeMarkerDirective.setContext(event);
if (results.containsKey(freeMarkerDirective.getDirectiveName()))
{
throw new WindupException("Windup contains two freemarker extension providing the same name: "
+ freeMarkerDirective.getDirectiveName());
}
results.put(freeMarkerDirective.getDirectiveName(), freeMarkerDirective);
}
return results;
}
/**
* Finds all variables in the context with the given names, and also attaches all WindupFreeMarkerMethods from all addons into the map.
*
* This allows external addons to extend the capabilities in the freemarker reporting system.
*/
public static Map<String, Object> findFreeMarkerContextVariables(Variables variables, String... varNames)
{
Map<String, Object> results = new HashMap<>();
for (String varName : varNames)
{
WindupVertexFrame payload = null;
try
{
payload = Iteration.getCurrentPayload(variables, null, varName);
}
catch (IllegalStateException | IllegalArgumentException e)
{
// oh well
}
if (payload != null)
{
results.put(varName, payload);
}
else
{
Iterable<? extends WindupVertexFrame> var = variables.findVariable(varName);
if (var != null)
{
results.put(varName, var);
}
}
}
return results;
}
}