/** * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.util.filter; import java.io.File; import java.io.FilenameFilter; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * Utility class for working with Filters. Contains builder style methods, apply * methods, as well as mechanisms for adapting Filters and FilenameFilters. */ public class Filters { private Filters() { } /** * Filter a given Collection. * * @param <T> * Type of the Collection. * @param filter * A Filter upon the Type of objects in the Collection. * @param collection * The Collection to filter. * @return A List containing only those objects for which the Filter * returned <code>true</code>. */ public static <T> List<T> filter(Filter<T> filter, Collection<T> collection) { List<T> list = new ArrayList<>(); for (T obj : collection) { if (filter.filter(obj)) { list.add(obj); } } return list; } /** * Get a File Filter for files with the given extensions, ignoring case. * * @param extensions * The extensions to filter. * @return A File Filter. */ public static Filter<File> getFileExtensionFilter(String... extensions) { return new FileExtensionFilter(extensions); } /** * Get a File Filter for directories. * * @return A File Filter. */ public static Filter<File> getDirectoryFilter() { return DirectoryFilter.INSTANCE; } /** * Get a File Filter for directories or for files with the given extensions, * ignoring case. * * @param extensions * The extensions to filter. * @return A File Filter. */ public static Filter<File> getFileExtensionOrDirectoryFilter(String... extensions) { return new OrFilter<>(getFileExtensionFilter(extensions), getDirectoryFilter()); } /** * Given a String Filter, expose as a File Filter. The File paths are * normalized to a standard pattern using <code>/</code> as a path separator * which can be used cross platform easily in a regular expression based * String Filter. * * @param filter * A String Filter. * @return A File Filter. */ public static Filter<File> toNormalizedFileFilter(final Filter<String> filter) { return new Filter<File>() { @Override public boolean filter(File file) { String path = file.getPath(); path = path.replace('\\', '/'); return filter.filter(path); } @Override public String toString() { return filter.toString(); } }; } /** * Given a String Filter, expose as a Filter on another type. The * <code>toString()</code> method is called on the objects of the other type * and delegated to the String Filter. * * @param <T> * The desired type. * @param filter * The existing String Filter. * @return A Filter on the desired type. */ public static <T> Filter<T> fromStringFilter(final Filter<String> filter) { return new Filter<T>() { @Override public boolean filter(T obj) { return filter.filter(obj.toString()); } @Override public String toString() { return filter.toString(); } }; } /** * Given a File Filter, expose as a FilenameFilter. * * @param filter * The File Filter. * @return A FilenameFilter. */ public static FilenameFilter toFilenameFilter(final Filter<File> filter) { return new FilenameFilter() { @Override public boolean accept(File dir, String name) { return filter.filter(new File(dir, name)); } @Override public String toString() { return filter.toString(); } }; } /** * Given a FilenameFilter, expose as a File Filter. * * @param filter * The FilenameFilter. * @return A File Filter. */ public static Filter<File> toFileFilter(final FilenameFilter filter) { return new Filter<File>() { @Override public boolean filter(File file) { return filter.accept(file.getParentFile(), file.getName()); } @Override public String toString() { return filter.toString(); } }; } /** * Construct a String Filter using set of include and exclude regular * expressions. If there are no include regular expressions provide, then a * regular expression is added which matches every String by default. A * String is included as long as it matches an include regular expression * and does not match an exclude regular expression. * <p> * In other words, exclude patterns override include patterns. * * @param includeRegexes * The include regular expressions. May be <code>null</code>. * @param excludeRegexes * The exclude regular expressions. May be <code>null</code>. * @return A String Filter. */ public static Filter<String> buildRegexFilterExcludeOverInclude(List<String> includeRegexes, List<String> excludeRegexes) { OrFilter<String> includeFilter = new OrFilter<>(); if (includeRegexes == null || includeRegexes.isEmpty()) { includeFilter.addFilter(new RegexStringFilter(".*")); } else { for (String includeRegex : includeRegexes) { includeFilter.addFilter(new RegexStringFilter(includeRegex)); } } OrFilter<String> excludeFilter = new OrFilter<>(); if (excludeRegexes != null) { for (String excludeRegex : excludeRegexes) { excludeFilter.addFilter(new RegexStringFilter(excludeRegex)); } } return new AndFilter<>(includeFilter, new NotFilter<>(excludeFilter)); } /** * Construct a String Filter using set of include and exclude regular * expressions. If there are no include regular expressions provide, then a * regular expression is added which matches every String by default. A * String is included as long as the case that there is an include which * matches or there is not an exclude which matches. * <p> * In other words, include patterns override exclude patterns. * * @param includeRegexes * The include regular expressions. May be <code>null</code>. * @param excludeRegexes * The exclude regular expressions. May be <code>null</code>. * @return A String Filter. */ public static Filter<String> buildRegexFilterIncludeOverExclude(List<String> includeRegexes, List<String> excludeRegexes) { OrFilter<String> includeFilter = new OrFilter<>(); if (includeRegexes != null) { for (String includeRegex : includeRegexes) { includeFilter.addFilter(new RegexStringFilter(includeRegex)); } } OrFilter<String> excludeFilter = new OrFilter<>(); if (excludeRegexes != null) { for (String excludeRegex : excludeRegexes) { excludeFilter.addFilter(new RegexStringFilter(excludeRegex)); } } return new OrFilter<>(includeFilter, new NotFilter<>(excludeFilter)); } }