001package ball.annotation.processing; 002/*- 003 * ########################################################################## 004 * Utilities 005 * $Id: JavaxLangModelUtilities.java 7350 2021-01-15 22:58:26Z ball $ 006 * $HeadURL: svn+ssh://svn.hcf.dev/var/spool/scm/repository.svn/ball-util/trunk/src/main/java/ball/annotation/processing/JavaxLangModelUtilities.java $ 007 * %% 008 * Copyright (C) 2008 - 2021 Allen D. Ball 009 * %% 010 * Licensed under the Apache License, Version 2.0 (the "License"); 011 * you may not use this file except in compliance with the License. 012 * You may obtain a copy of the License at 013 * 014 * http://www.apache.org/licenses/LICENSE-2.0 015 * 016 * Unless required by applicable law or agreed to in writing, software 017 * distributed under the License is distributed on an "AS IS" BASIS, 018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 019 * See the License for the specific language governing permissions and 020 * limitations under the License. 021 * ########################################################################## 022 */ 023import ball.beans.PropertyMethodEnum; 024import java.lang.annotation.Annotation; 025import java.lang.reflect.Constructor; 026import java.lang.reflect.Executable; 027import java.lang.reflect.Field; 028import java.lang.reflect.Method; 029/* import java.lang.reflect.Modifier; */ 030import java.net.URLClassLoader; 031import java.util.Arrays; 032import java.util.Collection; 033import java.util.EnumMap; 034import java.util.EnumSet; 035import java.util.List; 036import java.util.Objects; 037import java.util.Optional; 038import java.util.Set; 039import java.util.TreeSet; 040import java.util.function.Function; 041import java.util.function.Predicate; 042import java.util.stream.IntStream; 043import java.util.stream.Stream; 044import javax.lang.model.element.AnnotationMirror; 045import javax.lang.model.element.AnnotationValue; 046import javax.lang.model.element.Element; 047import javax.lang.model.element.ExecutableElement; 048import javax.lang.model.element.Modifier; 049import javax.lang.model.element.Name; 050import javax.lang.model.element.PackageElement; 051import javax.lang.model.element.TypeElement; 052import javax.lang.model.element.VariableElement; 053import javax.lang.model.type.TypeKind; 054import javax.lang.model.type.TypeMirror; 055import javax.lang.model.util.Elements; 056import javax.lang.model.util.Types; 057import javax.tools.JavaFileManager; 058import lombok.NoArgsConstructor; 059import lombok.ToString; 060 061import static java.util.Collections.disjoint; 062import static java.util.stream.Collectors.joining; 063import static java.util.stream.Collectors.toList; 064import static javax.lang.model.element.ElementKind.CONSTRUCTOR; 065import static javax.lang.model.element.ElementKind.METHOD; 066import static javax.lang.model.element.Modifier.PRIVATE; 067import static javax.lang.model.element.Modifier.STATIC; 068import static javax.lang.model.util.ElementFilter.constructorsIn; 069import static javax.lang.model.util.ElementFilter.fieldsIn; 070import static javax.lang.model.util.ElementFilter.methodsIn; 071import static javax.tools.StandardLocation.CLASS_PATH; 072import static lombok.AccessLevel.PROTECTED; 073 074/** 075 * Utility methods for {@link javax.annotation.processing.Processor} and 076 * {@code Taglet} implementations. 077 * 078 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball} 079 * @version $Revision: 7350 $ 080 */ 081@NoArgsConstructor(access = PROTECTED) @ToString 082public abstract class JavaxLangModelUtilities { 083 public static final ModifierMap MODIFIERS = new ModifierMap(); 084 085 /** See {@link javax.annotation.processing.ProcessingEnvironment#getElementUtils()}. */ 086 protected Elements elements = null; 087 /** See {@link javax.annotation.processing.ProcessingEnvironment#getTypeUtils()}. */ 088 protected Types types = null; 089 /** {@link com.sun.source.util.JavacTask} {@link JavaFileManager} instance. */ 090 protected JavaFileManager fm = null; 091 private transient ClassLoader loader = null; 092 093 /** 094 * Method to get the {@link ClassLoader} for loading dependencies. 095 * 096 * @return The {@link ClassLoader}. 097 */ 098 protected ClassLoader getClassLoader() { 099 if (loader == null) { 100 loader = getClassPathClassLoader(fm, getClass().getClassLoader()); 101 } 102 103 return loader; 104 } 105 106 /** 107 * Method to get the {@link Class} corresponding to a 108 * {@link TypeElement}. 109 * 110 * @param element The {@link TypeElement}. 111 * 112 * @return The {@link Class} for the {@link TypeElement}. 113 */ 114 protected Class<?> asClass(TypeElement element) { 115 Class<?> type = null; 116 Name name = elements.getBinaryName(element); 117 118 if (name == null) { 119 name = element.getQualifiedName(); 120 } 121 122 try { 123 type = getClassLoader().loadClass(name.toString()); 124 } catch (Exception exception) { 125 throw new IllegalArgumentException("type=" + name, exception); 126 } 127 128 return type; 129 } 130 131 /** 132 * Method to get the {@code package-info.class} ({@link Class}) 133 * corresponding to a {@link PackageElement}. 134 * 135 * @param element The {@link PackageElement}. 136 * 137 * @return The {@link Class} for the {@link PackageElement} 138 * {@code package-info.class}. 139 */ 140 protected Class<?> asPackageInfoClass(PackageElement element) { 141 Class<?> type = null; 142 String name = 143 element.getQualifiedName().toString() + ".package-info"; 144 145 try { 146 type = getClassLoader().loadClass(name); 147 } catch (Exception exception) { 148 throw new IllegalArgumentException("type=" + name, exception); 149 } 150 151 return type; 152 } 153 154 /** 155 * Method to get a {@link TypeElement} for a {@link Class}. 156 * 157 * @param type The {@link Class}. 158 * 159 * @return The {@link TypeElement} for the {@link Class}. 160 */ 161 protected TypeElement asTypeElement(Class<?> type) { 162 TypeElement element = null; 163 164 try { 165 element = elements.getTypeElement(type.getCanonicalName()); 166 } catch (Exception exception) { 167 throw new IllegalArgumentException("type=" + type, exception); 168 } 169 170 return element; 171 } 172 173 /** 174 * Method to get a {@link ExecutableElement} for a {@link Constructor}. 175 * 176 * @param constructor The {@link Constructor}. 177 * 178 * @return The {@link ExecutableElement} for the {@link Constructor}. 179 */ 180 protected ExecutableElement asExecutableElement(Constructor<?> constructor) { 181 TypeElement type = asTypeElement(constructor.getDeclaringClass()); 182 Element element = 183 constructorsIn(type.getEnclosedElements()).stream() 184 .filter(hasSameSignatureAs(constructor)) 185 .findFirst().orElse(null); 186 187 return (ExecutableElement) element; 188 } 189 190 /** 191 * Method to get a {@link ExecutableElement} for a {@link Method}. 192 * 193 * @param method The {@link Method}. 194 * 195 * @return The {@link ExecutableElement} for the {@link Method}. 196 */ 197 protected ExecutableElement asExecutableElement(Method method) { 198 return getMethod(asTypeElement(method.getDeclaringClass()), method); 199 } 200 201 @Deprecated 202 protected ExecutableElement getMethod(Method method) { 203 return asExecutableElement(method); 204 } 205 206 /** 207 * Method to get a {@link VariableElement} for a {@link Field}. 208 * 209 * @param field The {@link Field}. 210 * 211 * @return The {@link VariableElement} for the {@link Field}. 212 */ 213 protected VariableElement asVariableElement(Field field) { 214 TypeElement type = asTypeElement(field.getDeclaringClass()); 215 Element element = 216 fieldsIn(type.getEnclosedElements()) 217 .stream() 218 .filter(t -> t.getSimpleName().contentEquals(field.getName())) 219 .findFirst().orElse(null); 220 221 return (VariableElement) element; 222 } 223 224 /** 225 * Method to get a {@link TypeMirror} for a {@link Class}. 226 * 227 * @param type The {@link Class}. 228 * 229 * @return The {@link TypeMirror} for the {@link Class}. 230 */ 231 protected TypeMirror asTypeMirror(Class<?> type) { 232 TypeMirror mirror = null; 233 234 if (type.isArray()) { 235 mirror = types.getArrayType(asTypeMirror(type.getComponentType())); 236 } else if (type.isPrimitive()) { 237 mirror = asTypeMirror(TypeKind.valueOf(type.getName().toUpperCase())); 238 } else { 239 mirror = asTypeElement(type).asType(); 240 } 241 242 return mirror; 243 } 244 245 private TypeMirror asTypeMirror(TypeKind type) { 246 return type.isPrimitive() ? types.getPrimitiveType(type) : types.getNoType(type); 247 } 248 249 /** 250 * Method to get a {@link List} of {@link TypeMirror}s for an array of 251 * {@link Class}es. 252 * 253 * @param types The array of {@link Class}es. 254 * 255 * @return The {@link List} of {@link TypeMirror}s. 256 */ 257 protected List<TypeMirror> asTypeMirrorList(Class<?>... types) { 258 return Stream.of(types).map(t -> asTypeMirror(t)).collect(toList()); 259 } 260 261 /** 262 * Method to get the enclosing {@link TypeElement} for an 263 * {@link Element}. 264 * 265 * @param element The {@link Element}. 266 * 267 * @return The enclosing {@link TypeElement}. 268 */ 269 protected TypeElement getEnclosingTypeElement(Element element) { 270 while (element != null) { 271 if (element instanceof TypeElement) { 272 break; 273 } 274 275 element = element.getEnclosingElement(); 276 } 277 278 return (TypeElement) element; 279 } 280 281 /** 282 * Method to get the {@link TypeElement} for a context {@link Element}. 283 * 284 * @param context The context {@link Element}. 285 * @param name The name of the {@link Element} 286 * ({@link Class}). 287 * 288 * @return The context's {@link TypeElement}. 289 */ 290 protected TypeElement getTypeElementFor(Element context, String name) { 291 if (! name.contains(".")) { 292 name = 293 elements.getPackageOf(context).getQualifiedName() + "." + name; 294 } 295 296 return elements.getTypeElement(name); 297 } 298 299 /** 300 * Constructor to get an {@link ExecutableElement} for a {@link Class} 301 * {@link Constructor} by parameter list. 302 * 303 * @param type The {@link TypeElement}. 304 * @param parameters The constructor parameter types. 305 * 306 * @return The {@link ExecutableElement} for the constructor. 307 */ 308 protected ExecutableElement getConstructor(TypeElement type, 309 List<TypeMirror> parameters) { 310 Element element = 311 constructorsIn(type.getEnclosedElements()) 312 .stream() 313 .filter(hasSameSignatureAs(parameters)) 314 .findFirst().orElse(null); 315 316 return (ExecutableElement) element; 317 } 318 319 /** 320 * Method to get an {@link ExecutableElement} for a {@link Method} 321 * prototype. 322 * 323 * @param type The {@link TypeElement}. 324 * @param method The prototype {@link Method}. 325 * 326 * @return The {@link ExecutableElement} for the method. 327 */ 328 protected ExecutableElement getMethod(TypeElement type, Method method) { 329 Element element = 330 methodsIn(type.getEnclosedElements()) 331 .stream() 332 .filter(hasSameSignatureAs(method)) 333 .findFirst().orElse(null); 334 335 return (ExecutableElement) element; 336 } 337 338 /** 339 * Method to return the {@link ExecutableElement} 340 * ({@link java.lang.reflect.Method}) the argument 341 * {@link ExecutableElement} overrides (if any). 342 * 343 * @param overrider The {@link ExecutableElement}. 344 * 345 * @return The overridden {@link ExecutableElement} if any; 346 * {@code null} otherwise. 347 * 348 * @see Elements#overrides(ExecutableElement,ExecutableElement,TypeElement) 349 */ 350 protected ExecutableElement overrides(ExecutableElement overrider) { 351 TypeElement type = (TypeElement) overrider.getEnclosingElement(); 352 ExecutableElement element = 353 types.directSupertypes(type.asType()) 354 .stream() 355 .map(t -> overrides(overrider, types.asElement(t))) 356 .filter(Objects::nonNull) 357 .findFirst().orElse(null); 358 359 return element; 360 } 361 362 private ExecutableElement overrides(ExecutableElement overrider, 363 Element type) { 364 ExecutableElement overridden = null; 365 366 if (type != null) { 367 switch (type.getKind()) { 368 case CLASS: 369 case INTERFACE: 370 overridden = overridden(overrider, (TypeElement) type); 371 break; 372 373 default: 374 break; 375 } 376 } 377 378 return overridden; 379 } 380 381 private ExecutableElement overridden(ExecutableElement overrider, 382 TypeElement type) { 383 ExecutableElement element = 384 methodsIn(type.getEnclosedElements()) 385 .stream() 386 .filter(withoutModifiers(PRIVATE, STATIC)) 387 .filter(t -> elements.overrides(overrider, t, type)) 388 .findFirst().orElse(null); 389 390 if (element == null) { 391 element = 392 overrides(overrider, types.asElement(type.getSuperclass())); 393 } 394 395 return element; 396 } 397 398 /** 399 * Method to determine if a {@link ExecutableElement} 400 * ({@link java.lang.reflect.Method}) overrides another 401 * {@link ExecutableElement}. 402 * 403 * @param overrider The (possibly) overriding 404 * {@link ExecutableElement}. 405 * @param overridden The overridden {@link ExecutableElement}. 406 * 407 * @return {@code true} if {@code overrider} overrides 408 * {@code overridden}; {@code false} otherwise. 409 * 410 * @see Elements#overrides(ExecutableElement,ExecutableElement,TypeElement) 411 */ 412 protected boolean overrides(ExecutableElement overrider, 413 ExecutableElement overridden) { 414 TypeElement type = (TypeElement) overridden.getEnclosingElement(); 415 416 return elements.overrides(overrider, overridden, type); 417 } 418 419 /** 420 * Method to return the {@link ExecutableElement} 421 * ({@link java.lang.reflect.Method}) the argument 422 * {@link ExecutableElement} is overriden by (if any). 423 * 424 * @param overridden The {@link ExecutableElement}. 425 * @param type The {@link TypeElement}. 426 * 427 * @return The overriding {@link ExecutableElement} if any; 428 * {@code null} otherwise. 429 * 430 * @see #overrides(ExecutableElement) 431 */ 432 protected ExecutableElement implementationOf(ExecutableElement overridden, 433 TypeElement type) { 434 ExecutableElement element = null; 435 436 if (type != null) { 437 element = 438 methodsIn(type.getEnclosedElements()) 439 .stream() 440 .filter(t -> overrides(t, overridden)) 441 .findFirst().orElse(null); 442 443 if (element == null) { 444 element = 445 Optional.ofNullable(type.getSuperclass()) 446 .map(t -> (TypeElement) types.asElement(t)) 447 .filter(Objects::nonNull) 448 .map(t -> implementationOf(overridden, t)) 449 .orElse(null); 450 } 451 } 452 453 return element; 454 } 455 456 /** 457 * Method to return the {@link ExecutableElement} 458 * ({@link java.lang.reflect.Method}) the argument 459 * {@link ExecutableElement} is specified by (if any). 460 * 461 * @param method The {@link ExecutableElement}. 462 * 463 * @return The specification {@link ExecutableElement} if any; 464 * {@code null} otherwise. 465 * 466 * @see #overrides(ExecutableElement) 467 */ 468 protected ExecutableElement specifiedBy(ExecutableElement method) { 469 ExecutableElement specification = overrides(method); 470 471 if (specification != null) { 472 for (;;) { 473 ExecutableElement overridden = overrides(specification); 474 475 if (overridden != null) { 476 specification = overridden; 477 } else { 478 break; 479 } 480 } 481 } 482 483 return specification; 484 } 485 486 /** 487 * Method to generate the application signature of an 488 * {@link Executable}. 489 * 490 * @param executable The {@link Executable}. 491 * 492 * @return The signature {@link String}. 493 */ 494 protected String signature(Executable executable) { 495 String signature = 496 Stream.of(executable.getParameterTypes()) 497 .map(Class::getCanonicalName) 498 .collect(joining(",", "(", ")")); 499 500 return signature; 501 } 502 503 /** 504 * Method to generate the application signature of an 505 * {@link ExecutableElement}. 506 * 507 * @param element The {@link ExecutableElement}. 508 * 509 * @return The signature {@link String}. 510 */ 511 protected String signature(ExecutableElement element) { 512 String signature = 513 element.getParameters().stream() 514 .map(VariableElement::asType) 515 .map(Object::toString) 516 .collect(joining(",", "(", ")")); 517 518 return signature; 519 } 520 521 /** 522 * Method to get an {@link Element}'s {@link AnnotationMirror}. 523 * 524 * @param element The annotated {@link Element}. 525 * @param type The {@link Annotation} type ({@link Class}). 526 * 527 * @return The {@link AnnotationMirror} if the {@link Element} is 528 * annotated with the argument annotation; {@code null} 529 * otherwise. 530 * 531 * @see Element#getAnnotationMirrors() 532 */ 533 protected AnnotationMirror getAnnotationMirror(Element element, 534 Class<? extends Annotation> type) { 535 return getAnnotationMirror(element, type.getName()); 536 } 537 538 /** 539 * Method to get an {@link Element}'s {@link AnnotationMirror}. 540 * 541 * @param element The annotated {@link Element}. 542 * @param type The {@link Annotation} type 543 * ({@link TypeElement}). 544 * 545 * @return The {@link AnnotationMirror} if the {@link Element} is 546 * annotated with the argument annotation; {@code null} 547 * otherwise. 548 * 549 * @see Element#getAnnotationMirrors() 550 */ 551 protected AnnotationMirror getAnnotationMirror(Element element, 552 TypeElement type) { 553 return getAnnotationMirror(element, 554 type.getQualifiedName().toString()); 555 } 556 557 private AnnotationMirror getAnnotationMirror(Element element, 558 String name) { 559 AnnotationMirror mirror = 560 element.getAnnotationMirrors() 561 .stream() 562 .filter(t -> t.getAnnotationType().toString().equals(name)) 563 .map(t -> (AnnotationMirror) t) 564 .findFirst().orElse(null); 565 566 return mirror; 567 } 568 569 /** 570 * Method to get an {@link AnnotationMirror} element's 571 * {@link AnnotationValue}. 572 * 573 * @param annotation The {@link AnnotationMirror}. 574 * @param name The simple name of the element. 575 * 576 * @return The {@link AnnotationValue} if it is defined; {@code null} 577 * otherwise. 578 * 579 * @see Elements#getElementValuesWithDefaults(AnnotationMirror) 580 */ 581 protected AnnotationValue getAnnotationValue(AnnotationMirror annotation, String name) { 582 AnnotationValue value = 583 elements.getElementValuesWithDefaults(annotation).entrySet() 584 .stream() 585 .filter(t -> named(name).test(t.getKey())) 586 .map(t -> t.getValue()) 587 .findFirst().orElse(null); 588 589 return value; 590 } 591 592 /** 593 * Method to determine if an {@link AnnotationValue} is "empty": 594 * {@code null} or an empty array. 595 * 596 * @param value The {@link AnnotationValue}. 597 * 598 * @return {@code true} if empty; {code false} otherwise. 599 */ 600 protected boolean isEmptyArray(AnnotationValue value) { 601 List<?> list = (List<?>) ((value != null) ? value.getValue() : null); 602 603 return (list == null || list.isEmpty()); 604 } 605 606 /** 607 * Method to get bean property name from an {@link ExecutableElement}. 608 * 609 * @param element The {@link ExecutableElement}. 610 * 611 * @return the name {@link String} if the {@link ExecutableElement} 612 * is a getter or setter method; {@code null} otherwise. 613 */ 614 protected String getPropertyName(ExecutableElement element) { 615 String string = 616 Stream.of(PropertyMethodEnum.values()) 617 .filter(t -> t.getPropertyName(element.getSimpleName().toString()) != null) 618 .filter(t -> isAssignableTo(t.getReturnType(), 619 e -> ((ExecutableElement) e).getReturnType()).test(element)) 620 .filter(t -> withParameters(t.getParameterTypes()).test(element)) 621 .map(t -> t.getPropertyName(element.getSimpleName().toString())) 622 .findFirst().orElse(null); 623 624 return string; 625 } 626 627 /** 628 * Method to determine if an {@link ExecutableElement} is a bean getter. 629 * 630 * @param element The {@link ExecutableElement}. 631 * 632 * @return {@code true} if the {@link Element} has a non-private getter 633 * method; {@code false} otherwise. 634 */ 635 protected boolean isGetterMethod(ExecutableElement element) { 636 Optional <PropertyMethodEnum> optional = 637 Stream.of(PropertyMethodEnum.GET, PropertyMethodEnum.IS) 638 .filter(t -> t.getPropertyName(element.getSimpleName().toString()) != null) 639 .filter(t -> withoutModifiers(PRIVATE).test(element)) 640 .filter(t -> isAssignableTo(t.getReturnType(), 641 e -> ((ExecutableElement) e).getReturnType()).test(element)) 642 .filter(t -> withParameters(t.getParameterTypes()).test(element)) 643 .findFirst(); 644 645 return optional.isPresent(); 646 } 647 648 /** 649 * Method to get the {@link Set} of bean property names for the 650 * specified {@link TypeElement}. 651 * 652 * @param type The {@link TypeElement} to analyze. 653 * 654 * @return The {@link Set} of bean property names. 655 */ 656 protected Set<String> getPropertyNames(TypeElement type) { 657 return getPropertyNames(new TreeSet<>(), type); 658 } 659 660 private Set<String> getPropertyNames(Set<String> set, TypeElement type) { 661 for (ExecutableElement element : 662 methodsIn(type.getEnclosedElements())) { 663 if (withoutModifiers(PRIVATE).test(element)) { 664 Stream.of(PropertyMethodEnum.values()) 665 .filter(t -> t.getPropertyName(element.getSimpleName().toString()) != null) 666 .filter(t -> isAssignableTo(t.getReturnType(), 667 e -> ((ExecutableElement) e).getReturnType()).test(element)) 668 .filter(t -> withParameters(t.getParameterTypes()).test(element)) 669 .map(t -> t.getPropertyName(element.getSimpleName().toString())) 670 .forEach(t -> set.add(t)); 671 } 672 } 673 674 Element superclass = types.asElement(type.getSuperclass()); 675 676 if (superclass != null) 677 switch (superclass.getKind()) { 678 case CLASS: 679 getPropertyNames(set, (TypeElement) superclass); 680 break; 681 682 default: 683 break; 684 } 685 686 return set; 687 } 688 /* 689 * Element Predicate Calculus 690 */ 691 protected <E extends Enum<E>> EnumSet<E> toEnumSet(E[] array) { 692 return EnumSet.copyOf(Arrays.asList(array)); 693 } 694 695 private <E extends Enum<E>> Predicate<Element> is(E e, Function<? super Element,E> extractor) { 696 return t -> e.equals(extractor.apply(t)); 697 } 698 699 protected Predicate<Element> hasSameSignatureAs(List<TypeMirror> parameters) { 700 return is(CONSTRUCTOR, Element::getKind).and(withParameters(parameters)); 701 } 702 703 protected Predicate<Element> hasSameSignatureAs(Executable executable) { 704 return hasSameSignatureAs(executable.getName(), 705 executable.getParameterTypes()); 706 } 707 708 protected Predicate<Element> hasSameSignatureAs(CharSequence name, 709 Class<?>[] parameters) { 710 return is(METHOD, Element::getKind).and(named(name).and(withParameters(parameters))); 711 } 712 713 protected Predicate<Element> isAssignableTo(Class<?> type) { 714 return isAssignableTo(type, t -> t.asType()); 715 } 716 717 protected Predicate<Element> isAssignableTo(TypeMirror type) { 718 return isAssignableTo(type, t -> t.asType()); 719 } 720 721 protected Predicate<Element> isAssignableTo(Class<?> type, 722 Function<? super Element,TypeMirror> extractor) { 723 return isAssignableTo(asTypeMirror(type), extractor); 724 } 725 726 protected Predicate<Element> isAssignableTo(TypeMirror type, 727 Function<? super Element,TypeMirror> extractor) { 728 return t -> types.isAssignable(extractor.apply(t), type); 729 } 730 731 protected Predicate<Element> named(CharSequence name) { 732 return t -> t.getSimpleName().contentEquals(name); 733 } 734 735 protected Predicate<Element> withParameters(Class<?>[] parameters) { 736 return withParameters(asTypeMirrorList(parameters)); 737 } 738 739 protected Predicate<Element> withParameters(List<TypeMirror> parameters) { 740 return new Predicate<Element>() { 741 @Override 742 public boolean test(Element element) { 743 boolean match = 744 parameters.size() == ((ExecutableElement) element).getParameters().size(); 745 746 if (match) { 747 match &= 748 IntStream.range(0, parameters.size()) 749 .allMatch(i -> isAssignableTo(parameters.get(i), 750 t -> types.erasure(((ExecutableElement) t) 751 .getParameters().get(i).asType())) 752 .test(element)); 753 } 754 755 return match; 756 } 757 }; 758 } 759 760 protected Predicate<Element> withModifiers(Modifier... modifiers) { 761 return withModifiers(toEnumSet(modifiers)); 762 } 763 764 protected Predicate<Element> withModifiers(Set<Modifier> modifiers) { 765 return with(modifiers, t -> t.getModifiers()); 766 } 767 768 protected Predicate<Element> withoutModifiers(Modifier... modifiers) { 769 return withoutModifiers(toEnumSet(modifiers)); 770 } 771 772 protected Predicate<Element> withoutModifiers(Set<Modifier> modifiers) { 773 return without(modifiers, t -> t.getModifiers()); 774 } 775 776 protected <E> Predicate<Element> with(Set<E> set, 777 Function<Element,Collection<E>> extractor) { 778 return t -> extractor.apply(t).containsAll(set); 779 } 780 781 protected <E> Predicate<Element> without(Set<E> set, 782 Function<Element,Collection<E>> extractor) { 783 return t -> disjoint(set, extractor.apply(t)); 784 } 785 786 /** 787 * See {@link JavaFileManager#getClassLoader(javax.tools.JavaFileManager.Location) JavaFileManager.getClassLoader(CLASS_PATH)}. 788 * 789 * @param fm The {@link JavaFileManager}. 790 * @param parent The parent {@link ClassLoader}. 791 * 792 * @return The {@link ClassLoader}. 793 */ 794 protected ClassLoader getClassPathClassLoader(JavaFileManager fm, 795 ClassLoader parent) { 796 ClassLoader loader = parent; 797 798 if (fm != null) { 799 loader = fm.getClassLoader(CLASS_PATH); 800 801 if (loader instanceof URLClassLoader) { 802 loader = 803 URLClassLoader 804 .newInstance(((URLClassLoader) loader).getURLs(), parent); 805 } 806 } 807 808 return loader; 809 } 810 811 /** 812 * See {@link JavaFileManager#getClassLoader(javax.tools.JavaFileManager.Location) JavaFileManager.getClassLoader(CLASS_PATH)}. 813 * 814 * @param fm The {@link JavaFileManager}. 815 * 816 * @return The {@link ClassLoader}. 817 */ 818 protected ClassLoader getClassPathClassLoader(JavaFileManager fm) { 819 return getClassPathClassLoader(fm, getClass().getClassLoader()); 820 } 821 822 /** 823 * Method to get the 824 * {@link java.lang.reflect.Modifier java.lang.reflect.Modifier} flags 825 * for a {@link Set} of {@link Modifier}s. 826 * 827 * @param set The {@link Modifier}s. 828 * 829 * @return The flags. 830 */ 831 public static int toModifiers(Set<Modifier> set) { 832 return MODIFIERS.toModifiers(set); 833 } 834 835 private static class ModifierMap extends EnumMap<Modifier,Integer> { 836 private static final long serialVersionUID = 1665841849117866554L; 837 838 public ModifierMap() { 839 super(Modifier.class); 840 841 for (Modifier key : Modifier.values()) { 842 try { 843 Object value = 844 java.lang.reflect.Modifier.class 845 .getField(key.name()).get(null); 846 847 put(key, (Integer) value); 848 } catch (Exception exception) { 849 } 850 } 851 } 852 853 public int toModifiers(Set<Modifier> set) { 854 return set.stream().map(this::get).mapToInt(Integer::intValue).sum(); 855 } 856 } 857}