001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2008-2011 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020 021 package net.sourceforge.pmd.util.filter; 022 023 import java.io.File; 024 import java.io.FilenameFilter; 025 import java.util.ArrayList; 026 import java.util.Collection; 027 import java.util.List; 028 029 /** 030 * Utility class for working with Filters. Contains builder style methods, 031 * apply methods, as well as mechanisms for adapting Filters and FilenameFilters. 032 */ 033 public class Filters { 034 035 /** 036 * Filter a given Collection. 037 * @param <T> Type of the Collection. 038 * @param filter A Filter upon the Type of objects in the Collection. 039 * @param collection The Collection to filter. 040 * @return A List containing only those objects for which the Filter returned <code>true</code>. 041 */ 042 public static <T> List<T> filter(Filter<T> filter, Collection<T> collection) { 043 List<T> list = new ArrayList<T>(); 044 for (T obj : collection) { 045 if (filter.filter(obj)) { 046 list.add(obj); 047 } 048 } 049 return list; 050 } 051 052 /** 053 * Get a File Filter for files with the given extensions, ignoring case. 054 * @param extensions The extensions to filter. 055 * @return A File Filter. 056 */ 057 public static Filter<File> getFileExtensionFilter(String... extensions) { 058 return new FileExtensionFilter(extensions); 059 } 060 061 /** 062 * Get a File Filter for directories. 063 * @return A File Filter. 064 */ 065 public static Filter<File> getDirectoryFilter() { 066 return DirectoryFilter.INSTANCE; 067 } 068 069 /** 070 * Get a File Filter for directories or for files with the given extensions, ignoring case. 071 * @param extensions The extensions to filter. 072 * @return A File Filter. 073 */ 074 public static Filter<File> getFileExtensionOrDirectoryFilter(String... extensions) { 075 return new OrFilter<File>(getFileExtensionFilter(extensions), getDirectoryFilter()); 076 } 077 078 /** 079 * Given a String Filter, expose as a File Filter. The File paths are 080 * normalized to a standard pattern using <code>/</code> as a path separator 081 * which can be used cross platform easily in a regular expression based 082 * String Filter. 083 * 084 * @param filter A String Filter. 085 * @return A File Filter. 086 */ 087 public static Filter<File> toNormalizedFileFilter(final Filter<String> filter) { 088 return new Filter<File>() { 089 public boolean filter(File file) { 090 String path = file.getPath(); 091 path = path.replace('\\', '/'); 092 return filter.filter(path); 093 } 094 095 public String toString() { 096 return filter.toString(); 097 } 098 }; 099 } 100 101 /** 102 * Given a String Filter, expose as a Filter on another type. The 103 * <code>toString()</code> method is called on the objects of the other 104 * type and delegated to the String Filter. 105 * @param <T> The desired type. 106 * @param filter The existing String Filter. 107 * @return A Filter on the desired type. 108 */ 109 public static <T> Filter<T> fromStringFilter(final Filter<String> filter) { 110 return new Filter<T>() { 111 public boolean filter(T obj) { 112 return filter.filter(obj.toString()); 113 } 114 115 public String toString() { 116 return filter.toString(); 117 } 118 }; 119 } 120 121 /** 122 * Given a File Filter, expose as a FilenameFilter. 123 * @param filter The File Filter. 124 * @return A FilenameFilter. 125 */ 126 public static FilenameFilter toFilenameFilter(final Filter<File> filter) { 127 return new FilenameFilter() { 128 public boolean accept(File dir, String name) { 129 return filter.filter(new File(dir, name)); 130 } 131 132 public String toString() { 133 return filter.toString(); 134 } 135 }; 136 } 137 138 /** 139 * Given a FilenameFilter, expose as a File Filter. 140 * @param filter The FilenameFilter. 141 * @return A File Filter. 142 */ 143 public static Filter<File> toFileFilter(final FilenameFilter filter) { 144 return new Filter<File>() { 145 public boolean filter(File file) { 146 return filter.accept(file.getParentFile(), file.getName()); 147 } 148 149 public String toString() { 150 return filter.toString(); 151 } 152 }; 153 } 154 155 /** 156 * Construct a String Filter using set of include and exclude regular 157 * expressions. If there are no include regular expressions provide, then 158 * a regular expression is added which matches every String by default. 159 * A String is included as long as it matches an include regular expression 160 * and does not match an exclude regular expression. 161 * <p> 162 * In other words, exclude patterns override include patterns. 163 * 164 * @param includeRegexes The include regular expressions. May be <code>null</code>. 165 * @param excludeRegexes The exclude regular expressions. May be <code>null</code>. 166 * @return A String Filter. 167 */ 168 public static Filter<String> buildRegexFilterExcludeOverInclude(List<String> includeRegexes, 169 List<String> excludeRegexes) { 170 OrFilter<String> includeFilter = new OrFilter<String>(); 171 if (includeRegexes == null || includeRegexes.size() == 0) { 172 includeFilter.addFilter(new RegexStringFilter(".*")); 173 } else { 174 for (String includeRegex : includeRegexes) { 175 includeFilter.addFilter(new RegexStringFilter(includeRegex)); 176 } 177 } 178 179 OrFilter<String> excludeFilter = new OrFilter<String>(); 180 if (excludeRegexes != null) { 181 for (String excludeRegex : excludeRegexes) { 182 excludeFilter.addFilter(new RegexStringFilter(excludeRegex)); 183 } 184 } 185 186 return new AndFilter<String>(includeFilter, new NotFilter<String>(excludeFilter)); 187 } 188 189 /** 190 * Construct a String Filter using set of include and exclude regular 191 * expressions. If there are no include regular expressions provide, then 192 * a regular expression is added which matches every String by default. 193 * A String is included as long as the case that there is an include which 194 * matches or there is not an exclude which matches. 195 * <p> 196 * In other words, include patterns override exclude patterns. 197 * 198 * @param includeRegexes The include regular expressions. May be <code>null</code>. 199 * @param excludeRegexes The exclude regular expressions. May be <code>null</code>. 200 * @return A String Filter. 201 */ 202 public static Filter<String> buildRegexFilterIncludeOverExclude(List<String> includeRegexes, 203 List<String> excludeRegexes) { 204 OrFilter<String> includeFilter = new OrFilter<String>(); 205 if (includeRegexes != null) { 206 for (String includeRegex : includeRegexes) { 207 includeFilter.addFilter(new RegexStringFilter(includeRegex)); 208 } 209 } 210 211 OrFilter<String> excludeFilter = new OrFilter<String>(); 212 if (excludeRegexes != null) { 213 for (String excludeRegex : excludeRegexes) { 214 excludeFilter.addFilter(new RegexStringFilter(excludeRegex)); 215 } 216 } 217 218 return new OrFilter<String>(includeFilter, new NotFilter<String>(excludeFilter)); 219 } 220 }