1 /*
2  * Copyright (c) 2005, 2012, 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 javax.lang.model.util;
27 
28 import java.util.Collections;
29 import java.util.List;
30 import java.util.Set;
31 import java.util.EnumSet;
32 import java.util.ArrayList;
33 import java.util.LinkedHashSet;
34 
35 import javax.lang.model.element.*;
36 
37 
38 /**
39  * Filters for selecting just the elements of interest from a
40  * collection of elements.  The returned sets and lists are new
41  * collections and do use the argument as a backing store.  The
42  * methods in this class do not make any attempts to guard against
43  * concurrent modifications of the arguments.  The returned sets and
44  * lists are mutable but unsafe for concurrent access.  A returned set
45  * has the same iteration order as the argument set to a method.
46  *
47  * <p>If iterables and sets containing {@code null} are passed as
48  * arguments to methods in this class, a {@code NullPointerException}
49  * will be thrown.
50  *
51  * <p>Note that a <i>static import</i> statement can make the text of
52  * calls to the methods in this class more concise; for example:
53  *
54  * <blockquote><pre>
55  *     import static javax.lang.model.util.ElementFilter.*;
56  *     ...
57  *         {@code List<VariableElement>} fs = fieldsIn(someClass.getEnclosedElements());
58  * </pre></blockquote>
59  *
60  * @author Joseph D. Darcy
61  * @author Scott Seligman
62  * @author Peter von der Ah&eacute;
63  * @author Martin Buchholz
64  * @since 1.6
65  */
66 public class ElementFilter {
ElementFilter()67     private ElementFilter() {} // Do not instantiate.
68 
69     private static final Set<ElementKind> CONSTRUCTOR_KIND =
70         Collections.unmodifiableSet(EnumSet.of(ElementKind.CONSTRUCTOR));
71 
72     private static final Set<ElementKind> FIELD_KINDS =
73         Collections.unmodifiableSet(EnumSet.of(ElementKind.FIELD,
74                                                ElementKind.ENUM_CONSTANT));
75     private static final Set<ElementKind> METHOD_KIND =
76         Collections.unmodifiableSet(EnumSet.of(ElementKind.METHOD));
77 
78     private static final Set<ElementKind> PACKAGE_KIND =
79         Collections.unmodifiableSet(EnumSet.of(ElementKind.PACKAGE));
80 
81     private static final Set<ElementKind> TYPE_KINDS =
82         Collections.unmodifiableSet(EnumSet.of(ElementKind.CLASS,
83                                                ElementKind.ENUM,
84                                                ElementKind.INTERFACE,
85                                                ElementKind.ANNOTATION_TYPE));
86     /**
87      * Returns a list of fields in {@code elements}.
88      * @return a list of fields in {@code elements}
89      * @param elements the elements to filter
90      */
91     public static List<VariableElement>
fieldsIn(Iterable<? extends Element> elements)92             fieldsIn(Iterable<? extends Element> elements) {
93         return listFilter(elements, FIELD_KINDS, VariableElement.class);
94     }
95 
96     /**
97      * Returns a set of fields in {@code elements}.
98      * @return a set of fields in {@code elements}
99      * @param elements the elements to filter
100      */
101     public static Set<VariableElement>
fieldsIn(Set<? extends Element> elements)102             fieldsIn(Set<? extends Element> elements) {
103         return setFilter(elements, FIELD_KINDS, VariableElement.class);
104     }
105 
106     /**
107      * Returns a list of constructors in {@code elements}.
108      * @return a list of constructors in {@code elements}
109      * @param elements the elements to filter
110      */
111     public static List<ExecutableElement>
constructorsIn(Iterable<? extends Element> elements)112             constructorsIn(Iterable<? extends Element> elements) {
113         return listFilter(elements, CONSTRUCTOR_KIND, ExecutableElement.class);
114     }
115 
116     /**
117      * Returns a set of constructors in {@code elements}.
118      * @return a set of constructors in {@code elements}
119      * @param elements the elements to filter
120      */
121     public static Set<ExecutableElement>
constructorsIn(Set<? extends Element> elements)122             constructorsIn(Set<? extends Element> elements) {
123         return setFilter(elements, CONSTRUCTOR_KIND, ExecutableElement.class);
124     }
125 
126     /**
127      * Returns a list of methods in {@code elements}.
128      * @return a list of methods in {@code elements}
129      * @param elements the elements to filter
130      */
131     public static List<ExecutableElement>
methodsIn(Iterable<? extends Element> elements)132             methodsIn(Iterable<? extends Element> elements) {
133         return listFilter(elements, METHOD_KIND, ExecutableElement.class);
134     }
135 
136     /**
137      * Returns a set of methods in {@code elements}.
138      * @return a set of methods in {@code elements}
139      * @param elements the elements to filter
140      */
141     public static Set<ExecutableElement>
methodsIn(Set<? extends Element> elements)142             methodsIn(Set<? extends Element> elements) {
143         return setFilter(elements, METHOD_KIND, ExecutableElement.class);
144     }
145 
146     /**
147      * Returns a list of types in {@code elements}.
148      * @return a list of types in {@code elements}
149      * @param elements the elements to filter
150      */
151     public static List<TypeElement>
typesIn(Iterable<? extends Element> elements)152             typesIn(Iterable<? extends Element> elements) {
153         return listFilter(elements, TYPE_KINDS, TypeElement.class);
154     }
155 
156     /**
157      * Returns a set of types in {@code elements}.
158      * @return a set of types in {@code elements}
159      * @param elements the elements to filter
160      */
161     public static Set<TypeElement>
typesIn(Set<? extends Element> elements)162             typesIn(Set<? extends Element> elements) {
163         return setFilter(elements, TYPE_KINDS, TypeElement.class);
164     }
165 
166     /**
167      * Returns a list of packages in {@code elements}.
168      * @return a list of packages in {@code elements}
169      * @param elements the elements to filter
170      */
171     public static List<PackageElement>
packagesIn(Iterable<? extends Element> elements)172             packagesIn(Iterable<? extends Element> elements) {
173         return listFilter(elements, PACKAGE_KIND, PackageElement.class);
174     }
175 
176     /**
177      * Returns a set of packages in {@code elements}.
178      * @return a set of packages in {@code elements}
179      * @param elements the elements to filter
180      */
181     public static Set<PackageElement>
packagesIn(Set<? extends Element> elements)182             packagesIn(Set<? extends Element> elements) {
183         return setFilter(elements, PACKAGE_KIND, PackageElement.class);
184     }
185 
186     // Assumes targetKinds and E are sensible.
listFilter(Iterable<? extends Element> elements, Set<ElementKind> targetKinds, Class<E> clazz)187     private static <E extends Element> List<E> listFilter(Iterable<? extends Element> elements,
188                                                           Set<ElementKind> targetKinds,
189                                                           Class<E> clazz) {
190         List<E> list = new ArrayList<E>();
191         for (Element e : elements) {
192             if (targetKinds.contains(e.getKind()))
193                 list.add(clazz.cast(e));
194         }
195         return list;
196     }
197 
198     // Assumes targetKinds and E are sensible.
setFilter(Set<? extends Element> elements, Set<ElementKind> targetKinds, Class<E> clazz)199     private static <E extends Element> Set<E> setFilter(Set<? extends Element> elements,
200                                                         Set<ElementKind> targetKinds,
201                                                         Class<E> clazz) {
202         // Return set preserving iteration order of input set.
203         Set<E> set = new LinkedHashSet<E>();
204         for (Element e : elements) {
205             if (targetKinds.contains(e.getKind()))
206                 set.add(clazz.cast(e));
207         }
208         return set;
209     }
210 }
211