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