ElementFilter.java revision 3294:9adfb22ff08f
1/*
2 * Copyright (c) 2005, 2015, 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
26package javax.lang.model.util;
27
28import java.util.Collections;
29import java.util.List;
30import java.util.Set;
31import java.util.EnumSet;
32import java.util.ArrayList;
33import java.util.LinkedHashSet;
34
35import javax.lang.model.element.*;
36import javax.lang.model.element.ModuleElement.Directive;
37import javax.lang.model.element.ModuleElement.DirectiveKind;
38import javax.lang.model.element.ModuleElement.ExportsDirective;
39import javax.lang.model.element.ModuleElement.ProvidesDirective;
40import javax.lang.model.element.ModuleElement.RequiresDirective;
41import javax.lang.model.element.ModuleElement.UsesDirective;
42
43
44/**
45 * Filters for selecting just the elements of interest from a
46 * collection of elements.  The returned sets and lists are new
47 * collections and do use the argument as a backing store.  The
48 * methods in this class do not make any attempts to guard against
49 * concurrent modifications of the arguments.  The returned sets and
50 * lists are mutable but unsafe for concurrent access.  A returned set
51 * has the same iteration order as the argument set to a method.
52 *
53 * <p>If iterables and sets containing {@code null} are passed as
54 * arguments to methods in this class, a {@code NullPointerException}
55 * will be thrown.
56 *
57 * <p>Note that a <i>static import</i> statement can make the text of
58 * calls to the methods in this class more concise; for example:
59 *
60 * <blockquote><pre>
61 *     import static javax.lang.model.util.ElementFilter.*;
62 *     ...
63 *         {@code List<VariableElement>} fs = fieldsIn(someClass.getEnclosedElements());
64 * </pre></blockquote>
65 *
66 * @author Joseph D. Darcy
67 * @author Scott Seligman
68 * @author Peter von der Ah&eacute;
69 * @author Martin Buchholz
70 * @since 1.6
71 */
72public class ElementFilter {
73    private ElementFilter() {} // Do not instantiate.
74
75    private static final Set<ElementKind> CONSTRUCTOR_KIND =
76        Collections.unmodifiableSet(EnumSet.of(ElementKind.CONSTRUCTOR));
77
78    private static final Set<ElementKind> FIELD_KINDS =
79        Collections.unmodifiableSet(EnumSet.of(ElementKind.FIELD,
80                                               ElementKind.ENUM_CONSTANT));
81    private static final Set<ElementKind> METHOD_KIND =
82        Collections.unmodifiableSet(EnumSet.of(ElementKind.METHOD));
83
84    private static final Set<ElementKind> PACKAGE_KIND =
85        Collections.unmodifiableSet(EnumSet.of(ElementKind.PACKAGE));
86
87    private static final Set<ElementKind> MODULE_KIND =
88        Collections.unmodifiableSet(EnumSet.of(ElementKind.MODULE));
89
90    private static final Set<ElementKind> TYPE_KINDS =
91        Collections.unmodifiableSet(EnumSet.of(ElementKind.CLASS,
92                                               ElementKind.ENUM,
93                                               ElementKind.INTERFACE,
94                                               ElementKind.ANNOTATION_TYPE));
95    /**
96     * Returns a list of fields in {@code elements}.
97     * @return a list of fields in {@code elements}
98     * @param elements the elements to filter
99     */
100    public static List<VariableElement>
101            fieldsIn(Iterable<? extends Element> elements) {
102        return listFilter(elements, FIELD_KINDS, VariableElement.class);
103    }
104
105    /**
106     * Returns a set of fields in {@code elements}.
107     * @return a set of fields in {@code elements}
108     * @param elements the elements to filter
109     */
110    public static Set<VariableElement>
111            fieldsIn(Set<? extends Element> elements) {
112        return setFilter(elements, FIELD_KINDS, VariableElement.class);
113    }
114
115    /**
116     * Returns a list of constructors in {@code elements}.
117     * @return a list of constructors in {@code elements}
118     * @param elements the elements to filter
119     */
120    public static List<ExecutableElement>
121            constructorsIn(Iterable<? extends Element> elements) {
122        return listFilter(elements, CONSTRUCTOR_KIND, ExecutableElement.class);
123    }
124
125    /**
126     * Returns a set of constructors in {@code elements}.
127     * @return a set of constructors in {@code elements}
128     * @param elements the elements to filter
129     */
130    public static Set<ExecutableElement>
131            constructorsIn(Set<? extends Element> elements) {
132        return setFilter(elements, CONSTRUCTOR_KIND, ExecutableElement.class);
133    }
134
135    /**
136     * Returns a list of methods in {@code elements}.
137     * @return a list of methods in {@code elements}
138     * @param elements the elements to filter
139     */
140    public static List<ExecutableElement>
141            methodsIn(Iterable<? extends Element> elements) {
142        return listFilter(elements, METHOD_KIND, ExecutableElement.class);
143    }
144
145    /**
146     * Returns a set of methods in {@code elements}.
147     * @return a set of methods in {@code elements}
148     * @param elements the elements to filter
149     */
150    public static Set<ExecutableElement>
151            methodsIn(Set<? extends Element> elements) {
152        return setFilter(elements, METHOD_KIND, ExecutableElement.class);
153    }
154
155    /**
156     * Returns a list of types in {@code elements}.
157     * @return a list of types in {@code elements}
158     * @param elements the elements to filter
159     */
160    public static List<TypeElement>
161            typesIn(Iterable<? extends Element> elements) {
162        return listFilter(elements, TYPE_KINDS, TypeElement.class);
163    }
164
165    /**
166     * Returns a set of types in {@code elements}.
167     * @return a set of types in {@code elements}
168     * @param elements the elements to filter
169     */
170    public static Set<TypeElement>
171            typesIn(Set<? extends Element> elements) {
172        return setFilter(elements, TYPE_KINDS, TypeElement.class);
173    }
174
175    /**
176     * Returns a list of packages in {@code elements}.
177     * @return a list of packages in {@code elements}
178     * @param elements the elements to filter
179     */
180    public static List<PackageElement>
181            packagesIn(Iterable<? extends Element> elements) {
182        return listFilter(elements, PACKAGE_KIND, PackageElement.class);
183    }
184
185    /**
186     * Returns a set of packages in {@code elements}.
187     * @return a set of packages in {@code elements}
188     * @param elements the elements to filter
189     */
190    public static Set<PackageElement>
191            packagesIn(Set<? extends Element> elements) {
192        return setFilter(elements, PACKAGE_KIND, PackageElement.class);
193    }
194
195    /**
196     * Returns a list of modules in {@code elements}.
197     * @return a list of modules in {@code elements}
198     * @param elements the elements to filter
199     * @since 9
200     */
201    public static List<ModuleElement>
202            modulesIn(Iterable<? extends Element> elements) {
203        return listFilter(elements, MODULE_KIND, ModuleElement.class);
204    }
205
206    /**
207     * Returns a set of modules in {@code elements}.
208     * @return a set of modules in {@code elements}
209     * @param elements the elements to filter
210     * @since 9
211     */
212    public static Set<ModuleElement>
213            modulesIn(Set<? extends Element> elements) {
214        return setFilter(elements, MODULE_KIND, ModuleElement.class);
215    }
216
217    // Assumes targetKinds and E are sensible.
218    private static <E extends Element> List<E> listFilter(Iterable<? extends Element> elements,
219                                                          Set<ElementKind> targetKinds,
220                                                          Class<E> clazz) {
221        List<E> list = new ArrayList<>();
222        for (Element e : elements) {
223            if (targetKinds.contains(e.getKind()))
224                list.add(clazz.cast(e));
225        }
226        return list;
227    }
228
229    // Assumes targetKinds and E are sensible.
230    private static <E extends Element> Set<E> setFilter(Set<? extends Element> elements,
231                                                        Set<ElementKind> targetKinds,
232                                                        Class<E> clazz) {
233        // Return set preserving iteration order of input set.
234        Set<E> set = new LinkedHashSet<>();
235        for (Element e : elements) {
236            if (targetKinds.contains(e.getKind()))
237                set.add(clazz.cast(e));
238        }
239        return set;
240    }
241
242
243
244    /**
245     * Returns a list of export directives in {@code directives}.
246     * @return a list of export directives in {@code directives}
247     * @param directives the directives to filter
248     * @since 9
249     */
250    public static List<ExportsDirective>
251            exportsIn(Iterable<? extends Directive> directives) {
252        return listFilter(directives, DirectiveKind.EXPORTS, ExportsDirective.class);
253    }
254
255    /**
256     * Returns a list of provides directives in {@code directives}.
257     * @return a list of provides directives in {@code directives}
258     * @param directives the directives to filter
259     * @since 9
260     */
261    public static List<ProvidesDirective>
262            providesIn(Iterable<? extends Directive> directives) {
263        return listFilter(directives, DirectiveKind.PROVIDES, ProvidesDirective.class);
264    }
265
266    /**
267     * Returns a list of requires directives in {@code directives}.
268     * @return a list of requires directives in {@code directives}
269     * @param directives the directives to filter
270     * @since 9
271     */
272    public static List<RequiresDirective>
273            requiresIn(Iterable<? extends Directive> directives) {
274        return listFilter(directives, DirectiveKind.REQUIRES, RequiresDirective.class);
275    }
276
277    /**
278     * Returns a list of uses directives in {@code directives}.
279     * @return a list of uses directives in {@code directives}
280     * @param directives the directives to filter
281     * @since 9
282     */
283    public static List<UsesDirective>
284            usesIn(Iterable<? extends Directive> directives) {
285        return listFilter(directives, DirectiveKind.USES, UsesDirective.class);
286    }
287
288    // Assumes directiveKind and D are sensible.
289    private static <D extends Directive> List<D> listFilter(Iterable<? extends Directive> directives,
290                                                          DirectiveKind directiveKind,
291                                                          Class<D> clazz) {
292        List<D> list = new ArrayList<>();
293        for (Directive d : directives) {
294            if (d.getKind() == directiveKind)
295                list.add(clazz.cast(d));
296        }
297        return list;
298    }
299}
300