package org.jboss.windup.reporting.freemarker; import java.util.Comparator; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; import org.jboss.windup.config.GraphRewrite; import org.jboss.windup.graph.model.comparator.FilePathComparator; import org.jboss.windup.graph.model.resource.FileModel; import org.jboss.windup.util.ExecutionStatistics; import org.jboss.windup.util.exception.WindupException; import freemarker.ext.beans.BeanModel; import freemarker.template.DefaultListAdapter; import freemarker.template.SimpleSequence; import freemarker.template.TemplateModelException; /** * Sorts file paths according to their alphabetical order. * * For example: * <ul> * <li>/foo/bar/baz.class</li> * <li>/foo/car/caz.class</li> * <li>/foo/hat.class</li> * </ul> * * Would become: * <ul> * <li>/foo/hat.class</li> * <li>/foo/bar/baz.class</li> * <li>/foo/car/caz.class</li> * </ul> * * Can be called as follows: sortFilesByPathAscending(Iterable<FileModel>) or sortFilesByPathAscending(Iterable<String>) * * @author <a href="mailto:jesse.sightler@gmail.com">Jesse Sightler</a> * */ public class SortFilesByPathMethod implements WindupFreeMarkerMethod { private static final String NAME = "sortFilesByPathAscending"; @Override public String getMethodName() { return NAME; } @Override public String getDescription() { return "Takes an Iterable<" + FileModel.class.getSimpleName() + "> or Iterable<String> and returns them, ordered alphabetically."; } @Override public Object exec(@SuppressWarnings("rawtypes") List arguments) throws TemplateModelException { ExecutionStatistics.get().begin(NAME); if (arguments.size() != 1) { throw new TemplateModelException("Error, method expects one argument (Iterable<FileModel>)"); } Iterable<Object> pathIterable = getIterable(arguments.get(0)); Comparator<Object> fileModelComparator = new Comparator<Object>() { final FilePathComparator filePathComparator = new FilePathComparator(); @Override public int compare(Object o1, Object o2) { return filePathComparator.compare(getFilePath(o1), getFilePath(o2)); } private String getFilePath(Object o) { if (o == null) return null; else if (o instanceof FileModel) return ((FileModel)o).getFilePath(); else if (o instanceof String) return (String)o; else throw new IllegalArgumentException("Unrecognized type: " + o.getClass().getName()); } }; SortedSet<Object> resultSet = new TreeSet<>(fileModelComparator); for (Object fm : pathIterable) { resultSet.add(fm); } ExecutionStatistics.get().end(NAME); return resultSet; } @SuppressWarnings("unchecked") private Iterable<Object> getIterable(Object arg) throws TemplateModelException { if (arg instanceof BeanModel) { BeanModel beanModel = (BeanModel) arg; return (Iterable<Object>) beanModel.getWrappedObject(); } else if (arg instanceof SimpleSequence) { SimpleSequence simpleSequence = (SimpleSequence) arg; return (Iterable<Object>) simpleSequence.toList(); } else if (arg instanceof DefaultListAdapter) { DefaultListAdapter defaultListAdapter = (DefaultListAdapter) arg; return (Iterable<Object>) defaultListAdapter.getWrappedObject(); } else { throw new WindupException("Unrecognized type passed to: " + getMethodName() + ": " + arg.getClass().getCanonicalName()); } } @Override public void setContext(GraphRewrite event) { // noop } }