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é 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