KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > mirror > util > DeclarationFilter


1 /*
2  * @(#)DeclarationFilter.java 1.2 04/07/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package com.sun.mirror.util;
9
10
11 import java.util.ArrayList JavaDoc;
12 import java.util.Collection JavaDoc;
13
14 import com.sun.mirror.declaration.Declaration;
15 import com.sun.mirror.declaration.Modifier;
16
17 import static com.sun.mirror.declaration.Modifier.*;
18
19
20 /**
21  * A filter for selecting just the items of interest
22  * from a collection of declarations.
23  * The filter is said to <i>select</i> or to <i>match</i> those declarations.
24  * Filters can be created in several ways:
25  * by the static methods described below,
26  * by negating or composing existing filters,
27  * or by subclasses that implement arbitrary matching rules.
28  *
29  * <p> A subclass can create an arbitrary filter simply by implementing
30  * the {@link #matches(Declaration)} method.
31  *
32  * <p> Examples.
33  * <p> Selecting the <tt>public</tt> declarations from a collection:
34  * <blockquote><pre>
35  * result = FILTER_PUBLIC.filter(decls); </pre></blockquote>
36  * Selecting class declarations (including enums):
37  * <blockquote><pre>
38  * classFilter = DeclarationFilter.getFilter(ClassDeclaration.class);
39  * result = classFilter.filter(decls); </pre></blockquote>
40  * Selecting class declarations but excluding enums:
41  * <blockquote><pre>
42  * enumFilter = DeclarationFilter.getFilter(EnumDeclaration.class);
43  * compoundFilter = classFilter.and(enumFilter.not());
44  * result = compoundFilter.filter(decls); </pre></blockquote>
45  * Selecting declarations named "Bob":
46  * <blockquote><pre>
47  * nameFilter = new DeclarationFilter() {
48  * public boolean matches(Declaration d) {
49  * return d.getSimpleName().equals("Bob");
50  * }
51  * };
52  * result = nameFilter.filter(decls); </pre></blockquote>
53  *
54  * @author Joseph D. Darcy
55  * @author Scott Seligman
56  * @version 1.2 04/07/19
57  * @since 1.5
58  */

59
60 public class DeclarationFilter {
61
62     // Predefined filters for convenience.
63

64     /**
65      * A filter that selects only <tt>public</tt> declarations.
66      */

67     public static final DeclarationFilter FILTER_PUBLIC =
68         new AccessFilter(PUBLIC);
69
70     /**
71      * A filter that selects only <tt>protected</tt> declarations.
72      */

73     public static final DeclarationFilter FILTER_PROTECTED =
74         new AccessFilter(PROTECTED);
75
76     /**
77      * A filter that selects only <tt>public</tt> or <tt>protected</tt>
78      * declarations.
79      */

80     public static final DeclarationFilter FILTER_PUBLIC_OR_PROTECTED =
81         new AccessFilter(PUBLIC, PROTECTED);
82
83     /**
84      * A filter that selects only package-private (<i>default</i>)
85      * declarations.
86      */

87     public static final DeclarationFilter FILTER_PACKAGE =
88         new AccessFilter();
89
90     /**
91      * A filter that selects only <tt>private</tt> declarations.
92      */

93     public static final DeclarationFilter FILTER_PRIVATE =
94         new AccessFilter(PRIVATE);
95
96
97     /**
98      * Constructs an identity filter: one that selects all declarations.
99      */

100     public DeclarationFilter() {
101     }
102
103
104
105     // Methods to create a filter.
106

107     /**
108      * Returns a filter that selects declarations containing all of a
109      * collection of modifiers.
110      *
111      * @param mods the modifiers to match (non-null)
112      * @return a filter that matches declarations containing <tt>mods</tt>
113      */

114     public static DeclarationFilter getFilter(
115                          final Collection JavaDoc<Modifier> mods) {
116     return new DeclarationFilter() {
117         public boolean matches(Declaration d) {
118         return d.getModifiers().containsAll(mods);
119         }
120     };
121     }
122
123     /**
124      * Returns a filter that selects declarations of a particular kind.
125      * For example, there may be a filter that selects only class
126      * declarations, or only fields.
127      * The filter will select declarations of the specified kind,
128      * and also any subtypes of that kind; for example, a field filter
129      * will also select enum constants.
130      *
131      * @param kind the kind of declarations to select
132      * @return a filter that selects declarations of a particular kind
133      */

134     public static DeclarationFilter getFilter(
135                      final Class JavaDoc<? extends Declaration> kind) {
136     return new DeclarationFilter() {
137         public boolean matches(Declaration d) {
138         return kind.isInstance(d);
139         }
140     };
141     }
142
143     /**
144      * Returns a filter that selects those declarations selected
145      * by both this filter and another.
146      *
147      * @param f filter to be composed with this one
148      * @return a filter that selects those declarations selected by
149      * both this filter and another
150      */

151     public DeclarationFilter and(DeclarationFilter f) {
152     final DeclarationFilter f1 = this;
153     final DeclarationFilter f2 = f;
154     return new DeclarationFilter() {
155         public boolean matches(Declaration d) {
156         return f1.matches(d) && f2.matches(d);
157         }
158     };
159     }
160
161     /**
162      * Returns a filter that selects those declarations selected
163      * by either this filter or another.
164      *
165      * @param f filter to be composed with this one
166      * @return a filter that selects those declarations selected by
167      * either this filter or another
168      */

169     public DeclarationFilter or(DeclarationFilter f) {
170     final DeclarationFilter f1 = this;
171     final DeclarationFilter f2 = f;
172     return new DeclarationFilter() {
173         public boolean matches(Declaration d) {
174         return f1.matches(d) || f2.matches(d);
175         }
176     };
177     }
178
179     /**
180      * Returns a filter that selects those declarations not selected
181      * by this filter.
182      *
183      * @return a filter that selects those declarations not selected
184      * by this filter
185      */

186     public DeclarationFilter not() {
187     return new DeclarationFilter() {
188         public boolean matches(Declaration d) {
189         return !DeclarationFilter.this.matches(d);
190         }
191     };
192     }
193
194
195
196     // Methods to apply a filter.
197

198     /**
199      * Tests whether this filter matches a given declaration.
200      * The default implementation always returns <tt>true</tt>;
201      * subclasses should override this.
202      *
203      * @param decl the declaration to match
204      * @return <tt>true</tt> if this filter matches the given declaration
205      */

206     public boolean matches(Declaration decl) {
207     return true;
208     }
209
210     /**
211      * Returns the declarations matched by this filter.
212      * The result is a collection of the same type as the argument;
213      * the {@linkplain #filter(Collection, Class) two-parameter version}
214      * of <tt>filter</tt> offers control over the result type.
215      *
216      * @param <D> type of the declarations being filtered
217      * @param decls declarations being filtered
218      * @return the declarations matched by this filter
219      */

220     public <D extends Declaration> Collection JavaDoc<D> filter(Collection JavaDoc<D> decls) {
221     ArrayList JavaDoc<D> res = new ArrayList JavaDoc<D>(decls.size());
222     for (D d : decls) {
223         if (matches(d)) {
224         res.add(d);
225         }
226     }
227     return res;
228     }
229
230     /**
231      * Returns the declarations matched by this filter, with the result
232      * being restricted to declarations of a given kind.
233      * Similar to the simpler
234      * {@linkplain #filter(Collection) single-parameter version}
235      * of <tt>filter</tt>, but the result type is specified explicitly.
236      *
237      * @param <D> type of the declarations being returned
238      * @param decls declarations being filtered
239      * @param resType type of the declarations being returned --
240      * the reflective view of <tt>D</tt>
241      * @return the declarations matched by this filter, restricted to those
242      * of the specified type
243      */

244     public <D extends Declaration> Collection JavaDoc<D>
245         filter(Collection JavaDoc<? extends Declaration> decls, Class JavaDoc<D> resType) {
246     ArrayList JavaDoc<D> res = new ArrayList JavaDoc<D>(decls.size());
247     for (Declaration d : decls) {
248         if (resType.isInstance(d) && matches(d)) {
249         res.add(resType.cast(d));
250         }
251     }
252     return res;
253     }
254
255
256
257     /*
258      * A filter based on access modifiers.
259      */

260     private static class AccessFilter extends DeclarationFilter {
261
262     // The first access modifier to filter on, or null if we're looking
263
// for declarations with no access modifiers.
264
private Modifier mod1 = null;
265
266     // The second access modifier to filter on, or null if none.
267
private Modifier mod2 = null;
268
269     // Returns a filter that matches declarations with no access
270
// modifiers.
271
AccessFilter() {
272     }
273
274     // Returns a filter that matches m.
275
AccessFilter(Modifier m) {
276         mod1 = m;
277     }
278
279     // Returns a filter that matches either m1 or m2.
280
AccessFilter(Modifier m1, Modifier m2) {
281         mod1 = m1;
282         mod2 = m2;
283     }
284
285     public boolean matches(Declaration d) {
286         Collection JavaDoc<Modifier> mods = d.getModifiers();
287         if (mod1 == null) { // looking for package private
288
return !(mods.contains(PUBLIC) ||
289              mods.contains(PROTECTED) ||
290              mods.contains(PRIVATE));
291         }
292         return mods.contains(mod1) &&
293            (mod2 == null || mods.contains(mod2));
294     }
295     }
296 }
297
Popular Tags