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 * @spec JPMS 202 */ 203 public static List<ModuleElement> 204 modulesIn(Iterable<? extends Element> elements) { 205 return listFilter(elements, MODULE_KIND, ModuleElement.class); 206 } 207 208 /** 209 * Returns a set of modules in {@code elements}. 210 * @return a set of modules in {@code elements} 211 * @param elements the elements to filter 212 * @since 9 213 * @spec JPMS 214 */ 215 public static Set<ModuleElement> 216 modulesIn(Set<? extends Element> elements) { 217 return setFilter(elements, MODULE_KIND, ModuleElement.class); 218 } 219 220 // Assumes targetKinds and E are sensible. 221 private static <E extends Element> List<E> listFilter(Iterable<? extends Element> elements, 222 Set<ElementKind> targetKinds, 223 Class<E> clazz) { 224 List<E> list = new ArrayList<>(); 225 for (Element e : elements) { 226 if (targetKinds.contains(e.getKind())) 227 list.add(clazz.cast(e)); 228 } 229 return list; 230 } 231 232 // Assumes targetKinds and E are sensible. 233 private static <E extends Element> Set<E> setFilter(Set<? extends Element> elements, 234 Set<ElementKind> targetKinds, 235 Class<E> clazz) { 236 // Return set preserving iteration order of input set. 237 Set<E> set = new LinkedHashSet<>(); 238 for (Element e : elements) { 239 if (targetKinds.contains(e.getKind())) 240 set.add(clazz.cast(e)); 241 } 242 return set; 243 } 244 245 /** 246 * Returns a list of {@code exports} directives in {@code directives}. 247 * @return a list of {@code exports} directives in {@code directives} 248 * @param directives the directives to filter 249 * @since 9 250 * @spec JPMS 251 */ 252 public static List<ExportsDirective> 253 exportsIn(Iterable<? extends Directive> directives) { 254 return listFilter(directives, DirectiveKind.EXPORTS, ExportsDirective.class); 255 } 256 257 /** 258 * Returns a list of {@code opens} directives in {@code directives}. 259 * @return a list of {@code opens} directives in {@code directives} 260 * @param directives the directives to filter 261 * @since 9 262 */ 263 public static List<OpensDirective> 264 opensIn(Iterable<? extends Directive> directives) { 265 return listFilter(directives, DirectiveKind.OPENS, OpensDirective.class); 266 } 267 268 /** 269 * Returns a list of {@code provides} directives in {@code directives}. 270 * @return a list of {@code provides} directives in {@code directives} 271 * @param directives the directives to filter 272 * @since 9 273 * @spec JPMS 274 */ 275 public static List<ProvidesDirective> 276 providesIn(Iterable<? extends Directive> directives) { 277 return listFilter(directives, DirectiveKind.PROVIDES, ProvidesDirective.class); 278 } 279 280 /** 281 * Returns a list of {@code requires} directives in {@code directives}. 282 * @return a list of {@code requires} directives in {@code directives} 283 * @param directives the directives to filter 284 * @since 9 285 * @spec JPMS 286 */ 287 public static List<RequiresDirective> 288 requiresIn(Iterable<? extends Directive> directives) { 289 return listFilter(directives, DirectiveKind.REQUIRES, RequiresDirective.class); 290 } 291 292 /** 293 * Returns a list of {@code uses} directives in {@code directives}. 294 * @return a list of {@code uses} directives in {@code directives} 295 * @param directives the directives to filter 296 * @since 9 297 * @spec JPMS 298 */ 299 public static List<UsesDirective> 300 usesIn(Iterable<? extends Directive> directives) { 301 return listFilter(directives, DirectiveKind.USES, UsesDirective.class); 302 } 303 304 // Assumes directiveKind and D are sensible. 305 private static <D extends Directive> List<D> listFilter(Iterable<? extends Directive> directives, 306 DirectiveKind directiveKind, 307 Class<D> clazz) { 308 List<D> list = new ArrayList<>(); 309 for (Directive d : directives) { 310 if (d.getKind() == directiveKind) 311 list.add(clazz.cast(d)); 312 } 313 return list; 314 } 315 }