package org.jboss.windup.reporting.freemarker;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jboss.windup.config.GraphRewrite;
import org.jboss.windup.graph.model.ProjectModel;
import org.jboss.windup.graph.traversal.ProjectModelTraversal;
import org.jboss.windup.reporting.service.ClassificationService;
import org.jboss.windup.reporting.service.InlineHintService;
import org.jboss.windup.util.ExecutionStatistics;
import freemarker.ext.beans.StringModel;
import freemarker.template.SimpleSequence;
import freemarker.template.TemplateBooleanModel;
import freemarker.template.TemplateModelException;
import java.util.logging.Logger;
/**
* Gets the number of effort points involved in migrating this application.
*
* <p> Called from a freemarker template as follows:
*
* <pre>getMigrationEffortPoints(
* projectModel: ProjectModel,
* recursive: Boolean,
* [includeTags: Set<String>],
* [excludeTags: Set<String>]
* ) : int
* </pre>
*
* <p> If recursive is true, the effort total includes child projects.
*
* @author <a href="mailto:jesse.sightler@gmail.com">Jesse Sightler</a>
* @author <a href="http://ondra.zizka.cz/">Ondrej Zizka, zizka@seznam.cz</a>
*/
public class GetEffortDetailsForProjectTraversalMethod implements WindupFreeMarkerMethod
{
public static final Logger LOG = Logger.getLogger(GetEffortDetailsForProjectTraversalMethod.class.getName());
private static final String NAME = "getEffortDetailsForProjectTraversal";
private ClassificationService classificationService;
private InlineHintService inlineHintService;
@Override
public void setContext(GraphRewrite event)
{
this.classificationService = new ClassificationService(event.getGraphContext());
this.inlineHintService = new InlineHintService(event.getGraphContext());
}
@Override
public String getMethodName()
{
return NAME;
}
@Override
public String getDescription()
{
return "Takes a " + ProjectModel.class.getSimpleName()
+ " as a parameter and returns Map<Integer, Integer> where the key is the effort level and the value is the number of incidents at that particular level of effort.";
}
@Override
public Object exec(@SuppressWarnings("rawtypes") List arguments) throws TemplateModelException
{
// Process arguments
ExecutionStatistics.get().begin(NAME);
if (arguments.size() < 2)
{
throw new TemplateModelException(
"Error, method expects at least three arguments"
+ " (projectModel: ProjectModel, recursive: Boolean, [includeTags: Set<String>], [excludeTags: Set<String>])");
}
StringModel projectModelTraversalArg = (StringModel) arguments.get(0);
ProjectModelTraversal projectModelTraversal = (ProjectModelTraversal) projectModelTraversalArg.getWrappedObject();
TemplateBooleanModel recursiveBooleanModel = (TemplateBooleanModel) arguments.get(1);
boolean recursive = recursiveBooleanModel.getAsBoolean();
Set<String> includeTags = Collections.emptySet();
if (arguments.size() >= 3)
{
includeTags = FreeMarkerUtil.simpleSequenceToSet((SimpleSequence) arguments.get(2));
}
Set<String> excludeTags = Collections.emptySet();
if (arguments.size() >= 4)
{
excludeTags = FreeMarkerUtil.simpleSequenceToSet((SimpleSequence) arguments.get(3));
}
// Get values for classification and hints.
Map<Integer, Integer> classificationEffortDetails =
classificationService.getMigrationEffortByPoints(projectModelTraversal, includeTags, excludeTags, recursive, false);
Map<Integer, Integer> hintEffortDetails =
inlineHintService.getMigrationEffortByPoints(projectModelTraversal, includeTags, excludeTags, recursive, false);
Map<Integer, Integer> results = sumMaps(classificationEffortDetails, hintEffortDetails);
ExecutionStatistics.get().end(NAME);
int points = sumPoints(results);
LOG.info(String.format("%s() FM function called:\n\t\t\tEFFORT: %3d = %s = C%s + H%s; %s, %srecur, tags: %s, excl: %s",
NAME, points, results, classificationEffortDetails, hintEffortDetails,
projectModelTraversal, recursive ? "" : "!", includeTags, excludeTags));
return results;
}
private Map<Integer, Integer> sumMaps(Map<Integer, Integer> classificationEffortDetails, Map<Integer, Integer> hintEffortDetails)
{
Map<Integer, Integer> results = new HashMap<>(classificationEffortDetails.size() + hintEffortDetails.size());
results.putAll(classificationEffortDetails);
for (Map.Entry<Integer, Integer> entry : hintEffortDetails.entrySet())
{
if (!results.containsKey(entry.getKey()))
results.put(entry.getKey(), entry.getValue());
else
results.put(entry.getKey(), results.get(entry.getKey()) + entry.getValue());
}
return results;
}
private int sumPoints(Map<Integer, Integer> results)
{
int sum = 0;
for (Map.Entry<Integer, Integer> entry : results.entrySet())
{
sum += entry.getKey() * entry.getValue();
}
return sum;
}
}