1 /* 2 * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.mirror.util; 27 28 29 import java.util.ArrayList; 30 import java.util.Collection; 31 32 import com.sun.mirror.declaration.Declaration; 33 import com.sun.mirror.declaration.Modifier; 34 35 import static com.sun.mirror.declaration.Modifier.*; 36 37 38 /** 39 * A filter for selecting just the items of interest 40 * from a collection of declarations. 41 * The filter is said to <i>select</i> or to <i>match</i> those declarations. 42 * Filters can be created in several ways: 43 * by the static methods described below, 44 * by negating or composing existing filters, 45 * or by subclasses that implement arbitrary matching rules. 46 * 47 * <p> A subclass can create an arbitrary filter simply by implementing 48 * the {@link #matches(Declaration)} method. 49 * 50 * <p> Examples. 51 * <p> Selecting the <tt>public</tt> declarations from a collection: 52 * <blockquote><pre> 53 * result = FILTER_PUBLIC.filter(decls); </pre></blockquote> 54 * Selecting class declarations (including enums): 55 * <blockquote><pre> 56 * classFilter = DeclarationFilter.getFilter(ClassDeclaration.class); 57 * result = classFilter.filter(decls); </pre></blockquote> 58 * Selecting class declarations but excluding enums: 59 * <blockquote><pre> 60 * enumFilter = DeclarationFilter.getFilter(EnumDeclaration.class); 61 * compoundFilter = classFilter.and(enumFilter.not()); 62 * result = compoundFilter.filter(decls); </pre></blockquote> 63 * Selecting declarations named "Bob": 64 * <blockquote><pre> 65 * nameFilter = new DeclarationFilter() { 66 * public boolean matches(Declaration d) { 67 * return d.getSimpleName().equals("Bob"); 68 * } 69 * }; 70 * result = nameFilter.filter(decls); </pre></blockquote> 71 * 72 * @deprecated All components of this API have been superseded by the 73 * standardized annotation processing API. The replacement for the 74 * functionality of this class is {@link 75 * javax.lang.model.util.ElementFilter}. 76 * 77 * @author Joseph D. Darcy 78 * @author Scott Seligman 79 * @since 1.5 80 */ 81 @Deprecated 82 @SuppressWarnings("deprecation") 83 public class DeclarationFilter { 84 85 // Predefined filters for convenience. 86 87 /** 88 * A filter that selects only <tt>public</tt> declarations. 89 */ 90 public static final DeclarationFilter FILTER_PUBLIC = 91 new AccessFilter(PUBLIC); 92 93 /** 94 * A filter that selects only <tt>protected</tt> declarations. 95 */ 96 public static final DeclarationFilter FILTER_PROTECTED = 97 new AccessFilter(PROTECTED); 98 99 /** 100 * A filter that selects only <tt>public</tt> or <tt>protected</tt> 101 * declarations. 102 */ 103 public static final DeclarationFilter FILTER_PUBLIC_OR_PROTECTED = 104 new AccessFilter(PUBLIC, PROTECTED); 105 106 /** 107 * A filter that selects only package-private (<i>default</i>) 108 * declarations. 109 */ 110 public static final DeclarationFilter FILTER_PACKAGE = 111 new AccessFilter(); 112 113 /** 114 * A filter that selects only <tt>private</tt> declarations. 115 */ 116 public static final DeclarationFilter FILTER_PRIVATE = 117 new AccessFilter(PRIVATE); 118 119 120 /** 121 * Constructs an identity filter: one that selects all declarations. 122 */ 123 public DeclarationFilter() { 124 } 125 126 127 128 // Methods to create a filter. 129 130 /** 131 * Returns a filter that selects declarations containing all of a 132 * collection of modifiers. 133 * 134 * @param mods the modifiers to match (non-null) 135 * @return a filter that matches declarations containing <tt>mods</tt> 136 */ 137 public static DeclarationFilter getFilter( 138 final Collection<Modifier> mods) { 139 return new DeclarationFilter() { 140 public boolean matches(Declaration d) { 141 return d.getModifiers().containsAll(mods); 142 } 143 }; 144 } 145 146 /** 147 * Returns a filter that selects declarations of a particular kind. 148 * For example, there may be a filter that selects only class 149 * declarations, or only fields. 150 * The filter will select declarations of the specified kind, 151 * and also any subtypes of that kind; for example, a field filter 152 * will also select enum constants. 153 * 154 * @param kind the kind of declarations to select 155 * @return a filter that selects declarations of a particular kind 156 */ 157 public static DeclarationFilter getFilter( 158 final Class<? extends Declaration> kind) { 159 return new DeclarationFilter() { 160 public boolean matches(Declaration d) { 161 return kind.isInstance(d); 162 } 163 }; 164 } 165 166 /** 167 * Returns a filter that selects those declarations selected 168 * by both this filter and another. 169 * 170 * @param f filter to be composed with this one 171 * @return a filter that selects those declarations selected by 172 * both this filter and another 173 */ 174 public DeclarationFilter and(DeclarationFilter f) { 175 final DeclarationFilter f1 = this; 176 final DeclarationFilter f2 = f; 177 return new DeclarationFilter() { 178 public boolean matches(Declaration d) { 179 return f1.matches(d) && f2.matches(d); 180 } 181 }; 182 } 183 184 /** 185 * Returns a filter that selects those declarations selected 186 * by either this filter or another. 187 * 188 * @param f filter to be composed with this one 189 * @return a filter that selects those declarations selected by 190 * either this filter or another 191 */ 192 public DeclarationFilter or(DeclarationFilter f) { 193 final DeclarationFilter f1 = this; 194 final DeclarationFilter f2 = f; 195 return new DeclarationFilter() { 196 public boolean matches(Declaration d) { 197 return f1.matches(d) || f2.matches(d); 198 } 199 }; 200 } 201 202 /** 203 * Returns a filter that selects those declarations not selected 204 * by this filter. 205 * 206 * @return a filter that selects those declarations not selected 207 * by this filter 208 */ 209 public DeclarationFilter not() { 210 return new DeclarationFilter() { 211 public boolean matches(Declaration d) { 212 return !DeclarationFilter.this.matches(d); 213 } 214 }; 215 } 216 217 218 219 // Methods to apply a filter. 220 221 /** 222 * Tests whether this filter matches a given declaration. 223 * The default implementation always returns <tt>true</tt>; 224 * subclasses should override this. 225 * 226 * @param decl the declaration to match 227 * @return <tt>true</tt> if this filter matches the given declaration 228 */ 229 public boolean matches(Declaration decl) { 230 return true; 231 } 232 233 /** 234 * Returns the declarations matched by this filter. 235 * The result is a collection of the same type as the argument; 236 * the {@linkplain #filter(Collection, Class) two-parameter version} 237 * of <tt>filter</tt> offers control over the result type. 238 * 239 * @param <D> type of the declarations being filtered 240 * @param decls declarations being filtered 241 * @return the declarations matched by this filter 242 */ 243 public <D extends Declaration> Collection<D> filter(Collection<D> decls) { 244 ArrayList<D> res = new ArrayList<D>(decls.size()); 245 for (D d : decls) { 246 if (matches(d)) { 247 res.add(d); 248 } 249 } 250 return res; 251 } 252 253 /** 254 * Returns the declarations matched by this filter, with the result 255 * being restricted to declarations of a given kind. 256 * Similar to the simpler 257 * {@linkplain #filter(Collection) single-parameter version} 258 * of <tt>filter</tt>, but the result type is specified explicitly. 259 * 260 * @param <D> type of the declarations being returned 261 * @param decls declarations being filtered 262 * @param resType type of the declarations being returned -- 263 * the reflective view of <tt>D</tt> 264 * @return the declarations matched by this filter, restricted to those 265 * of the specified type 266 */ 267 public <D extends Declaration> Collection<D> 268 filter(Collection<? extends Declaration> decls, Class<D> resType) { 269 ArrayList<D> res = new ArrayList<D>(decls.size()); 270 for (Declaration d : decls) { 271 if (resType.isInstance(d) && matches(d)) { 272 res.add(resType.cast(d)); 273 } 274 } 275 return res; 276 } 277 278 279 280 /* 281 * A filter based on access modifiers. 282 */ 283 private static class AccessFilter extends DeclarationFilter { 284 285 // The first access modifier to filter on, or null if we're looking 286 // for declarations with no access modifiers. 287 private Modifier mod1 = null; 288 289 // The second access modifier to filter on, or null if none. 290 private Modifier mod2 = null; 291 292 // Returns a filter that matches declarations with no access 293 // modifiers. 294 AccessFilter() { 295 } 296 297 // Returns a filter that matches m. 298 AccessFilter(Modifier m) { 299 mod1 = m; 300 } 301 302 // Returns a filter that matches either m1 or m2. 303 AccessFilter(Modifier m1, Modifier m2) { 304 mod1 = m1; 305 mod2 = m2; 306 } 307 308 public boolean matches(Declaration d) { 309 Collection<Modifier> mods = d.getModifiers(); 310 if (mod1 == null) { // looking for package private 311 return !(mods.contains(PUBLIC) || 312 mods.contains(PROTECTED) || 313 mods.contains(PRIVATE)); 314 } 315 return mods.contains(mod1) && 316 (mod2 == null || mods.contains(mod2)); 317 } 318 } 319 }