View Javadoc

1   package net.sourceforge.pmd.util.filter;
2   
3   import java.io.File;
4   import java.io.FilenameFilter;
5   import java.util.ArrayList;
6   import java.util.Collection;
7   import java.util.List;
8   
9   /**
10   * Utility class for working with Filters.  Contains builder style methods,
11   * apply methods, as well as mechanisms for adapting Filters and FilenameFilters.
12   */
13  public class Filters {
14  
15  	/**
16  	 * Filter a given Collection.
17  	 * @param <T> Type of the Collection.
18  	 * @param filter A Filter upon the Type of objects in the Collection.
19  	 * @param collection The Collection to filter.
20  	 * @return A List containing only those objects for which the Filter returned <code>true</code>.
21  	 */
22  	public static <T> List<T> filter(Filter<T> filter, Collection<T> collection) {
23  		List<T> list = new ArrayList<T>();
24  		for (T obj : collection) {
25  			if (filter.filter(obj)) {
26  				list.add(obj);
27  			}
28  		}
29  		return list;
30  	}
31  
32  	/**
33  	 * Get a File Filter for files with the given extensions, ignoring case.
34  	 * @param extensions The extensions to filter.
35  	 * @return A File Filter.
36  	 */
37  	public static Filter<File> getFileExtensionFilter(String... extensions) {
38  		return new FileExtensionFilter(extensions);
39  	}
40  
41  	/**
42  	 * Get a File Filter for directories.
43  	 * @return A File Filter.
44  	 */
45  	public static Filter<File> getDirectoryFilter() {
46  		return DirectoryFilter.INSTANCE;
47  	}
48  
49  	/**
50  	 * Get a File Filter for directories or for files with the given extensions, ignoring case.
51  	 * @param extensions The extensions to filter.
52  	 * @return A File Filter.
53  	 */
54  	public static Filter<File> getFileExtensionOrDirectoryFilter(String... extensions) {
55  		return new OrFilter<File>(getFileExtensionFilter(extensions), getDirectoryFilter());
56  	}
57  
58  	/**
59  	 * Given a String Filter, expose as a File Filter.  The File paths are
60  	 * normalized to a standard pattern using <code>/</code> as a path separator
61  	 * which can be used cross platform easily in a regular expression based
62  	 * String Filter.
63  	 * 
64  	 * @param filter A String Filter.
65  	 * @return A File Filter.
66  	 */
67  	public static Filter<File> toNormalizedFileFilter(final Filter<String> filter) {
68  		return new Filter<File>() {
69  			public boolean filter(File file) {
70  				String path = file.getPath();
71  				path = path.replace('\\', '/');
72  				return filter.filter(path);
73  			}
74  
75  			public String toString() {
76  				return filter.toString();
77  			}
78  		};
79  	}
80  
81  	/**
82  	 * Given a String Filter, expose as a Filter on another type.  The
83  	 * <code>toString()</code> method is called on the objects of the other
84  	 * type and delegated to the String Filter.
85  	 * @param <T> The desired type.
86  	 * @param filter The existing String Filter.
87  	 * @return A Filter on the desired type.
88  	 */
89  	public static <T> Filter<T> fromStringFilter(final Filter<String> filter) {
90  		return new Filter<T>() {
91  			public boolean filter(T obj) {
92  				return filter.filter(obj.toString());
93  			}
94  
95  			public String toString() {
96  				return filter.toString();
97  			}
98  		};
99  	}
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.size() == 0) {
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 }