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