001 package net.sourceforge.pmd.util.filter;
002
003 import java.io.File;
004 import java.io.FilenameFilter;
005 import java.util.ArrayList;
006 import java.util.Collection;
007 import java.util.List;
008
009 /**
010 * Utility class for working with Filters. Contains builder style methods,
011 * apply methods, as well as mechanisms for adapting Filters and FilenameFilters.
012 */
013 public class Filters {
014
015 /**
016 * Filter a given Collection.
017 * @param <T> Type of the Collection.
018 * @param filter A Filter upon the Type of objects in the Collection.
019 * @param collection The Collection to filter.
020 * @return A List containing only those objects for which the Filter returned <code>true</code>.
021 */
022 public static <T> List<T> filter(Filter<T> filter, Collection<T> collection) {
023 List<T> list = new ArrayList<T>();
024 for (T obj : collection) {
025 if (filter.filter(obj)) {
026 list.add(obj);
027 }
028 }
029 return list;
030 }
031
032 /**
033 * Get a File Filter for files with the given extensions, ignoring case.
034 * @param extensions The extensions to filter.
035 * @return A File Filter.
036 */
037 public static Filter<File> getFileExtensionFilter(String... extensions) {
038 return new FileExtensionFilter(extensions);
039 }
040
041 /**
042 * Get a File Filter for directories.
043 * @return A File Filter.
044 */
045 public static Filter<File> getDirectoryFilter() {
046 return DirectoryFilter.INSTANCE;
047 }
048
049 /**
050 * Get a File Filter for directories or for files with the given extensions, ignoring case.
051 * @param extensions The extensions to filter.
052 * @return A File Filter.
053 */
054 public static Filter<File> getFileExtensionOrDirectoryFilter(String... extensions) {
055 return new OrFilter<File>(getFileExtensionFilter(extensions), getDirectoryFilter());
056 }
057
058 /**
059 * Given a String Filter, expose as a File Filter. The File paths are
060 * normalized to a standard pattern using <code>/</code> as a path separator
061 * which can be used cross platform easily in a regular expression based
062 * String Filter.
063 *
064 * @param filter A String Filter.
065 * @return A File Filter.
066 */
067 public static Filter<File> toNormalizedFileFilter(final Filter<String> filter) {
068 return new Filter<File>() {
069 public boolean filter(File file) {
070 String path = file.getPath();
071 path = path.replace('\\', '/');
072 return filter.filter(path);
073 }
074
075 public String toString() {
076 return filter.toString();
077 }
078 };
079 }
080
081 /**
082 * Given a String Filter, expose as a Filter on another type. The
083 * <code>toString()</code> method is called on the objects of the other
084 * type and delegated to the String Filter.
085 * @param <T> The desired type.
086 * @param filter The existing String Filter.
087 * @return A Filter on the desired type.
088 */
089 public static <T> Filter<T> fromStringFilter(final Filter<String> filter) {
090 return new Filter<T>() {
091 public boolean filter(T obj) {
092 return filter.filter(obj.toString());
093 }
094
095 public String toString() {
096 return filter.toString();
097 }
098 };
099 }
100
101 /**
102 * Given a File Filter, expose as a FilenameFilter.
103 * @param filter The File Filter.
104 * @return A FilenameFilter.
105 */
106 public static FilenameFilter toFilenameFilter(final Filter<File> filter) {
107 return new FilenameFilter() {
108 public boolean accept(File dir, String name) {
109 return filter.filter(new File(dir, name));
110 }
111
112 public String toString() {
113 return filter.toString();
114 }
115 };
116 }
117
118 /**
119 * Given a FilenameFilter, expose as a File Filter.
120 * @param filter The FilenameFilter.
121 * @return A File Filter.
122 */
123 public static Filter<File> toFileFilter(final FilenameFilter filter) {
124 return new Filter<File>() {
125 public boolean filter(File file) {
126 return filter.accept(file.getParentFile(), file.getName());
127 }
128
129 public String toString() {
130 return filter.toString();
131 }
132 };
133 }
134
135 /**
136 * Construct a String Filter using set of include and exclude regular
137 * expressions. If there are no include regular expressions provide, then
138 * a regular expression is added which matches every String by default.
139 * A String is included as long as it matches an include regular expression
140 * and does not match an exclude regular expression.
141 * <p>
142 * In other words, exclude patterns override include patterns.
143 *
144 * @param includeRegexes The include regular expressions. May be <code>null</code>.
145 * @param excludeRegexes The exclude regular expressions. May be <code>null</code>.
146 * @return A String Filter.
147 */
148 public static Filter<String> buildRegexFilterExcludeOverInclude(List<String> includeRegexes,
149 List<String> excludeRegexes) {
150 OrFilter<String> includeFilter = new OrFilter<String>();
151 if (includeRegexes == null || includeRegexes.isEmpty()) {
152 includeFilter.addFilter(new RegexStringFilter(".*"));
153 } else {
154 for (String includeRegex : includeRegexes) {
155 includeFilter.addFilter(new RegexStringFilter(includeRegex));
156 }
157 }
158
159 OrFilter<String> excludeFilter = new OrFilter<String>();
160 if (excludeRegexes != null) {
161 for (String excludeRegex : excludeRegexes) {
162 excludeFilter.addFilter(new RegexStringFilter(excludeRegex));
163 }
164 }
165
166 return new AndFilter<String>(includeFilter, new NotFilter<String>(excludeFilter));
167 }
168
169 /**
170 * Construct a String Filter using set of include and exclude regular
171 * expressions. If there are no include regular expressions provide, then
172 * a regular expression is added which matches every String by default.
173 * A String is included as long as the case that there is an include which
174 * matches or there is not an exclude which matches.
175 * <p>
176 * In other words, include patterns override exclude patterns.
177 *
178 * @param includeRegexes The include regular expressions. May be <code>null</code>.
179 * @param excludeRegexes The exclude regular expressions. May be <code>null</code>.
180 * @return A String Filter.
181 */
182 public static Filter<String> buildRegexFilterIncludeOverExclude(List<String> includeRegexes,
183 List<String> excludeRegexes) {
184 OrFilter<String> includeFilter = new OrFilter<String>();
185 if (includeRegexes != null) {
186 for (String includeRegex : includeRegexes) {
187 includeFilter.addFilter(new RegexStringFilter(includeRegex));
188 }
189 }
190
191 OrFilter<String> excludeFilter = new OrFilter<String>();
192 if (excludeRegexes != null) {
193 for (String excludeRegex : excludeRegexes) {
194 excludeFilter.addFilter(new RegexStringFilter(excludeRegex));
195 }
196 }
197
198 return new OrFilter<String>(includeFilter, new NotFilter<String>(excludeFilter));
199 }
200 }
|