001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.reflect; 014 015import static org.apache.juneau.common.internal.StringUtils.*; 016import static org.apache.juneau.internal.CollectionUtils.*; 017import static org.apache.juneau.internal.ConsumerUtils.*; 018 019import java.lang.annotation.*; 020import java.lang.reflect.*; 021import java.util.*; 022import java.util.function.*; 023 024import org.apache.juneau.*; 025import org.apache.juneau.internal.*; 026 027/** 028 * Contains common methods between {@link ConstructorInfo} and {@link MethodInfo}. 029 * 030 * <h5 class='section'>See Also:</h5><ul> 031 * </ul> 032 */ 033@FluentSetters 034public abstract class ExecutableInfo { 035 036 final ClassInfo declaringClass; 037 final Executable e; 038 final boolean isConstructor; 039 040 private volatile ParamInfo[] params; 041 private volatile ClassInfo[] paramTypes, exceptionInfos; 042 private volatile Class<?>[] rawParamTypes; 043 private volatile Type[] rawGenericParamTypes; 044 private volatile Parameter[] rawParameters; 045 private volatile Annotation[][] parameterAnnotations; 046 private volatile Annotation[] declaredAnnotations; 047 048 /** 049 * Constructor. 050 * 051 * @param declaringClass The class that declares this method or constructor. 052 * @param e The constructor or method that this info represents. 053 */ 054 protected ExecutableInfo(ClassInfo declaringClass, Executable e) { 055 this.declaringClass = declaringClass; 056 this.e = e; 057 this.isConstructor = e instanceof Constructor; 058 } 059 060 /** 061 * Returns metadata about the class that declared this method or constructor. 062 * 063 * @return Metadata about the class that declared this method or constructor. 064 */ 065 public final ClassInfo getDeclaringClass() { 066 return declaringClass; 067 } 068 069 /** 070 * Returns <jk>true</jk> if this executable represents a {@link Constructor}. 071 * 072 * @return 073 * <jk>true</jk> if this executable represents a {@link Constructor} and can be cast to {@link ConstructorInfo}. 074 * <jk>false</jk> if this executable represents a {@link Method} and can be cast to {@link MethodInfo}. 075 */ 076 public final boolean isConstructor() { 077 return isConstructor; 078 } 079 080 //----------------------------------------------------------------------------------------------------------------- 081 // Parameters 082 //----------------------------------------------------------------------------------------------------------------- 083 084 /** 085 * Returns the number of parameters in this executable. 086 * 087 * <p> 088 * Same as calling {@link Executable#getParameterCount()}. 089 * 090 * @return The number of parameters in this executable. 091 */ 092 public final int getParamCount() { 093 return e.getParameterCount(); 094 } 095 096 /** 097 * Returns <jk>true</jk> if this executable has at least one parameter. 098 * 099 * <p> 100 * Same as calling {@link Executable#getParameterCount()} and comparing with zero. 101 * 102 * @return <jk>true</jk> if this executable has at least one parameter. 103 */ 104 public final boolean hasParams() { 105 return getParamCount() != 0; 106 } 107 108 /** 109 * Returns <jk>true</jk> if this executable has no parameters. 110 * 111 * <p> 112 * Same as calling {@link Executable#getParameterCount()} and comparing with zero. 113 * 114 * @return <jk>true</jk> if this executable has no parameters. 115 */ 116 public final boolean hasNoParams() { 117 return getParamCount() == 0; 118 } 119 120 /** 121 * Returns <jk>true</jk> if this executable has this number of arguments. 122 * 123 * <p> 124 * Same as calling {@link Executable#getParameterCount()} and comparing the count. 125 * 126 * @param number The number of expected arguments. 127 * @return <jk>true</jk> if this executable has this number of arguments. 128 */ 129 public final boolean hasNumParams(int number) { 130 return getParamCount() == number; 131 } 132 133 /** 134 * Returns the parameters defined on this executable. 135 * 136 * <p> 137 * Same as calling {@link Executable#getParameters()} but wraps the results 138 * 139 * @return An array of parameter information, never <jk>null</jk>. 140 */ 141 public final List<ParamInfo> getParams() { 142 return ulist(_getParams()); 143 } 144 145 /** 146 * Performs an action on every parameter that matches the specified filter. 147 * 148 * @param filter The filter, can be <jk>null</jk>. 149 * @param action The action to perform. 150 * @return This object. 151 */ 152 public ExecutableInfo forEachParam(Predicate<ParamInfo> filter, Consumer<ParamInfo> action) { 153 for (ParamInfo pi : _getParams()) 154 if (test(filter, pi)) 155 action.accept(pi); 156 return this; 157 } 158 159 /** 160 * Returns parameter information at the specified index. 161 * 162 * @param index The parameter index. 163 * @return The parameter information, never <jk>null</jk>. 164 */ 165 public final ParamInfo getParam(int index) { 166 checkIndex(index); 167 return _getParams()[index]; 168 } 169 170 /** 171 * Returns the parameter types on this executable. 172 * 173 * @return The parameter types on this executable. 174 */ 175 public final List<ClassInfo> getParamTypes() { 176 return ulist(_getParameterTypes()); 177 } 178 179 /** 180 * Returns the parameter type of the parameter at the specified index. 181 * 182 * @param index The parameter index. 183 * @return The parameter type of the parameter at the specified index. 184 */ 185 public final ClassInfo getParamType(int index) { 186 checkIndex(index); 187 return _getParameterTypes()[index]; 188 } 189 190 /** 191 * Returns the raw parameter types on this executable. 192 * 193 * @return The raw parameter types on this executable. 194 */ 195 public final List<Class<?>> getRawParamTypes() { 196 return ulist(_getRawParamTypes()); 197 } 198 199 /** 200 * Returns the raw parameter type of the parameter at the specified index. 201 * 202 * @param index The parameter index. 203 * @return The raw parameter type of the parameter at the specified index. 204 */ 205 public final Class<?> getRawParamType(int index) { 206 checkIndex(index); 207 return _getRawParamTypes()[index]; 208 } 209 210 /** 211 * Returns the raw generic parameter types on this executable. 212 * 213 * @return The raw generic parameter types on this executable. 214 */ 215 public final List<Type> getRawGenericParamTypes() { 216 return ulist(_getRawGenericParamTypes()); 217 } 218 219 /** 220 * Returns the raw generic parameter type of the parameter at the specified index. 221 * 222 * @param index The parameter index. 223 * @return The raw generic parameter type of the parameter at the specified index. 224 */ 225 public final Type getRawGenericParamType(int index) { 226 checkIndex(index); 227 return _getRawGenericParamTypes()[index]; 228 } 229 230 /** 231 * Returns an array of raw {@link Parameter} objects that represent all the parameters to the underlying executable represented by this object. 232 * 233 * @return An array of raw {@link Parameter} objects, or an empty array if executable has no parameters. 234 * @see Executable#getParameters() 235 */ 236 public final List<Parameter> getRawParameters() { 237 return ulist(_getRawParameters()); 238 } 239 240 /** 241 * Returns the raw {@link Parameter} object that represents the parameter at the specified index. 242 * 243 * @param index The parameter index. 244 * @return The raw {@link Parameter} object that represents the parameter at the specified index. 245 * @see Executable#getParameters() 246 */ 247 public final Parameter getRawParameter(int index) { 248 checkIndex(index); 249 return _getRawParameters()[index]; 250 } 251 252 final ParamInfo[] _getParams() { 253 if (params == null) { 254 synchronized(this) { 255 Parameter[] rp = _getRawParameters(); 256 ParamInfo[] l = new ParamInfo[rp.length]; 257 for (int i = 0; i < rp.length; i++) 258 l[i] = new ParamInfo(this, rp[i], i); 259 params = l; 260 } 261 } 262 return params; 263 } 264 265 final ClassInfo[] _getParameterTypes() { 266 if (paramTypes == null) { 267 synchronized(this) { 268 Class<?>[] ptc = _getRawParamTypes(); 269 // Note that due to a bug involving Enum constructors, getGenericParameterTypes() may 270 // always return an empty array. This appears to be fixed in Java 8 b75. 271 Type[] ptt = _getRawGenericParamTypes(); 272 if (ptt.length != ptc.length) { 273 // Bug in javac: generic type array excludes enclosing instance parameter 274 // for inner classes with at least one generic constructor parameter. 275 if (ptt.length + 1 == ptc.length) { 276 Type[] ptt2 = new Type[ptc.length]; 277 ptt2[0] = ptc[0]; 278 for (int i = 0; i < ptt.length; i++) 279 ptt2[i+1] = ptt[i]; 280 ptt = ptt2; 281 } else { 282 ptt = ptc; 283 } 284 } 285 ClassInfo[] l = new ClassInfo[ptc.length]; 286 for (int i = 0; i < ptc.length; i++) 287 l[i] = ClassInfo.of(ptc[i], ptt[i]); 288 paramTypes = l; 289 } 290 } 291 return paramTypes; 292 } 293 294 Class<?>[] _getRawParamTypes() { 295 if (rawParamTypes == null) { 296 synchronized(this) { 297 rawParamTypes = e.getParameterTypes(); 298 } 299 } 300 return rawParamTypes; 301 } 302 303 final Type[] _getRawGenericParamTypes() { 304 if (rawGenericParamTypes == null) { 305 synchronized(this) { 306 rawGenericParamTypes = e.getGenericParameterTypes(); 307 } 308 } 309 return rawGenericParamTypes; 310 } 311 312 final Parameter[] _getRawParameters() { 313 if (rawParameters == null) { 314 synchronized(this) { 315 rawParameters = e.getParameters(); 316 } 317 } 318 return rawParameters; 319 } 320 321 private void checkIndex(int index) { 322 int pc = getParamCount(); 323 if (pc == 0) 324 throw new IndexOutOfBoundsException(format("Invalid index ''{0}''. No parameters.", index)); 325 if (index < 0 || index >= pc) 326 throw new IndexOutOfBoundsException(format("Invalid index ''{0}''. Parameter count: {1}", index, pc)); 327 } 328 329 //----------------------------------------------------------------------------------------------------------------- 330 // Annotations 331 //----------------------------------------------------------------------------------------------------------------- 332 333 /** 334 * Performs an action on all matching parameter annotations at the specified parameter index. 335 * 336 * @param <A> The annotation type. 337 * @param index The parameter index. 338 * @param type The annotation type. 339 * @param predicate The predicate. 340 * @param consumer The consumer. 341 * @return This object. 342 */ 343 public final <A extends Annotation> ExecutableInfo forEachParameterAnnotation(int index, Class<A> type, Predicate<A> predicate, Consumer<A> consumer) { 344 for (Annotation a : _getParameterAnnotations(index)) 345 if (type.isInstance(a)) 346 consume(predicate, consumer, type.cast(a)); 347 return this; 348 } 349 350 final Annotation[][] _getParameterAnnotations() { 351 if (parameterAnnotations == null) { 352 synchronized(this) { 353 parameterAnnotations = e.getParameterAnnotations(); 354 } 355 } 356 return parameterAnnotations; 357 } 358 359 final Annotation[] _getParameterAnnotations(int index) { 360 checkIndex(index); 361 Annotation[][] x = _getParameterAnnotations(); 362 int c = e.getParameterCount(); 363 if (c != x.length) { 364 // Seems to be a JVM bug where getParameterAnnotations() don't take mandated parameters into account. 365 Annotation[][] x2 = new Annotation[c][]; 366 int diff = c - x.length; 367 for (int i = 0; i < diff; i++) 368 x2[i] = new Annotation[0]; 369 for (int i = diff; i < c; i++) 370 x2[i] = x[i-diff]; 371 x = x2; 372 } 373 return x[index]; 374 } 375 376 final Annotation[] _getDeclaredAnnotations() { 377 if (declaredAnnotations == null) { 378 synchronized(this) { 379 declaredAnnotations = e.getDeclaredAnnotations(); 380 } 381 } 382 return declaredAnnotations; 383 } 384 385 //----------------------------------------------------------------------------------------------------------------- 386 // Exceptions 387 //----------------------------------------------------------------------------------------------------------------- 388 389 /** 390 * Returns the exception types on this executable. 391 * 392 * @return The exception types on this executable. 393 */ 394 public final List<ClassInfo> getExceptionTypes() { 395 return ulist(_getExceptionTypes()); 396 } 397 398 final ClassInfo[] _getExceptionTypes() { 399 if (exceptionInfos == null) { 400 synchronized(this) { 401 Class<?>[] exceptionTypes = e.getExceptionTypes(); 402 ClassInfo[] l = new ClassInfo[exceptionTypes.length]; 403 for (int i = 0; i < exceptionTypes.length; i++) 404 l[i] = ClassInfo.of(exceptionTypes[i]); 405 exceptionInfos = l; 406 } 407 } 408 return exceptionInfos; 409 } 410 411 //----------------------------------------------------------------------------------------------------------------- 412 // Characteristics 413 //----------------------------------------------------------------------------------------------------------------- 414 415 /** 416 * Returns <jk>true</jk> if all specified flags are applicable to this method. 417 * 418 * @param flags The flags to test for. 419 * @return <jk>true</jk> if all specified flags are applicable to this method. 420 */ 421 public final boolean isAll(ReflectFlags...flags) { 422 for (ReflectFlags f : flags) { 423 switch (f) { 424 case DEPRECATED: 425 if (isNotDeprecated()) 426 return false; 427 break; 428 case NOT_DEPRECATED: 429 if (isDeprecated()) 430 return false; 431 break; 432 case HAS_PARAMS: 433 if (hasNoParams()) 434 return false; 435 break; 436 case HAS_NO_PARAMS: 437 if (hasParams()) 438 return false; 439 break; 440 case PUBLIC: 441 if (isNotPublic()) 442 return false; 443 break; 444 case NOT_PUBLIC: 445 if (isPublic()) 446 return false; 447 break; 448 case PROTECTED: 449 if (isNotProtected()) 450 return false; 451 break; 452 case NOT_PROTECTED: 453 if (isProtected()) 454 return false; 455 break; 456 case STATIC: 457 if (isNotStatic()) 458 return false; 459 break; 460 case NOT_STATIC: 461 if (isStatic()) 462 return false; 463 break; 464 case ABSTRACT: 465 if (isNotAbstract()) 466 return false; 467 break; 468 case NOT_ABSTRACT: 469 if (isAbstract()) 470 return false; 471 break; 472 default: 473 throw new BasicRuntimeException("Invalid flag for executable: {0}", f); 474 } 475 } 476 return true; 477 } 478 479 /** 480 * Returns <jk>true</jk> if all specified flags are applicable to this field. 481 * 482 * @param flags The flags to test for. 483 * @return <jk>true</jk> if all specified flags are applicable to this field. 484 */ 485 public final boolean is(ReflectFlags...flags) { 486 return isAll(flags); 487 } 488 489 /** 490 * Returns <jk>true</jk> if all specified flags are applicable to this method. 491 * 492 * @param flags The flags to test for. 493 * @return <jk>true</jk> if all specified flags are applicable to this method. 494 */ 495 public final boolean isAny(ReflectFlags...flags) { 496 for (ReflectFlags f : flags) { 497 switch (f) { 498 case DEPRECATED: 499 if (isDeprecated()) 500 return true; 501 break; 502 case NOT_DEPRECATED: 503 if (isNotDeprecated()) 504 return true; 505 break; 506 case HAS_PARAMS: 507 if (hasParams()) 508 return true; 509 break; 510 case HAS_NO_PARAMS: 511 if (hasNoParams()) 512 return true; 513 break; 514 case PUBLIC: 515 if (isPublic()) 516 return true; 517 break; 518 case NOT_PUBLIC: 519 if (isNotPublic()) 520 return true; 521 break; 522 case PROTECTED: 523 if (isProtected()) 524 return true; 525 break; 526 case NOT_PROTECTED: 527 if (isNotProtected()) 528 return true; 529 break; 530 case STATIC: 531 if (isStatic()) 532 return true; 533 break; 534 case NOT_STATIC: 535 if (isNotStatic()) 536 return true; 537 break; 538 case ABSTRACT: 539 if (isAbstract()) 540 return true; 541 break; 542 case NOT_ABSTRACT: 543 if (isNotAbstract()) 544 return true; 545 break; 546 default: 547 throw new BasicRuntimeException("Invalid flag for executable: {0}", f); 548 } 549 } 550 return false; 551 } 552 553 /** 554 * Returns <jk>true</jk> if this method has the specified arguments. 555 * 556 * @param args The arguments to test for. 557 * @return <jk>true</jk> if this method has this arguments in the exact order. 558 */ 559 public final boolean hasParamTypes(Class<?>...args) { 560 Class<?>[] pt = _getRawParamTypes(); 561 if (pt.length == args.length) { 562 for (int i = 0; i < pt.length; i++) 563 if (! pt[i].equals(args[i])) 564 return false; 565 return true; 566 } 567 return false; 568 } 569 570 /** 571 * Returns <jk>true</jk> if this method has the specified arguments. 572 * 573 * @param args The arguments to test for. 574 * @return <jk>true</jk> if this method has this arguments in the exact order. 575 */ 576 public final boolean hasParamTypes(ClassInfo...args) { 577 Class<?>[] pt = _getRawParamTypes(); 578 if (pt.length == args.length) { 579 for (int i = 0; i < pt.length; i++) 580 if (! pt[i].equals(args[i].inner())) 581 return false; 582 return true; 583 } 584 return false; 585 } 586 587 /** 588 * Returns <jk>true</jk> if this method has the specified argument parent classes. 589 * 590 * @param args The arguments to test for. 591 * @return <jk>true</jk> if this method has this arguments in the exact order. 592 */ 593 public final boolean hasMatchingParamTypes(Class<?>...args) { 594 ClassInfo[] pt = _getParameterTypes(); 595 if (pt.length != args.length) 596 return false; 597 for (ClassInfo element : pt) { 598 boolean matched = false; 599 for (Class<?> arg : args) 600 if (element.isParentOfFuzzyPrimitives(arg)) 601 matched = true; 602 if (! matched) 603 return false; 604 } 605 return true; 606 } 607 608 /** 609 * Returns <jk>true</jk> if this method has the specified argument parent classes. 610 * 611 * @param args The arguments to test for. 612 * @return <jk>true</jk> if this method has this arguments in the exact order. 613 */ 614 public final boolean hasMatchingParamTypes(ClassInfo...args) { 615 ClassInfo[] pt = _getParameterTypes(); 616 if (pt.length != args.length) 617 return false; 618 for (ClassInfo element : pt) { 619 boolean matched = false; 620 for (ClassInfo arg : args) 621 if (element.isParentOfFuzzyPrimitives(arg.inner())) 622 matched = true; 623 if (! matched) 624 return false; 625 } 626 return true; 627 } 628 629 /** 630 * Returns <jk>true</jk> if this method has at most only this arguments in any order. 631 * 632 * @param args The arguments to test for. 633 * @return <jk>true</jk> if this method has at most only this arguments in any order. 634 */ 635 public final boolean hasFuzzyParamTypes(Class<?>...args) { 636 return fuzzyArgsMatch(args) != -1; 637 } 638 639 /** 640 * Returns how well this method matches the specified arg types. 641 * 642 * <p> 643 * The number returned is the number of method arguments that match the passed in arg types. 644 * <br>Returns <c>-1</c> if the method cannot take in one or more of the specified arguments. 645 * 646 * @param argTypes The arg types to check against. 647 * @return How many parameters match or <c>-1</c> if method cannot handle one or more of the arguments. 648 */ 649 public final int fuzzyArgsMatch(Class<?>... argTypes) { 650 int matches = 0; 651 outer: for (ClassInfo pi : getParamTypes()) { 652 for (Class<?> a : argTypes) { 653 if (pi.isParentOfFuzzyPrimitives(a)) { 654 matches++; 655 continue outer; 656 } 657 } 658 return -1; 659 } 660 return matches; 661 } 662 663 /** 664 * Returns how well this method matches the specified arg types. 665 * 666 * <p> 667 * The number returned is the number of method arguments that match the passed in arg types. 668 * <br>Returns <c>-1</c> if the method cannot take in one or more of the specified arguments. 669 * 670 * @param argTypes The arg types to check against. 671 * @return How many parameters match or <c>-1</c> if method cannot handle one or more of the arguments. 672 */ 673 public final int fuzzyArgsMatch(Object... argTypes) { 674 int matches = 0; 675 outer: for (ClassInfo pi : getParamTypes()) { 676 for (Object a : argTypes) { 677 if (pi.canAcceptArg(a)) { 678 matches++; 679 continue outer; 680 } 681 } 682 return -1; 683 } 684 return matches; 685 } 686 687 /** 688 * Returns <jk>true</jk> if this method has at most only this arguments in any order. 689 * 690 * @param args The arguments to test for. 691 * @return <jk>true</jk> if this method has at most only this arguments in any order. 692 */ 693 public final boolean hasFuzzyParamTypes(ClassInfo...args) { 694 return fuzzyArgsMatch(args) != -1; 695 } 696 697 /** 698 * Returns how well this method matches the specified arg types. 699 * 700 * <p> 701 * The number returned is the number of method arguments that match the passed in arg types. 702 * <br>Returns <c>-1</c> if the method cannot take in one or more of the specified arguments. 703 * 704 * @param argTypes The arg types to check against. 705 * @return How many parameters match or <c>-1</c> if method cannot handle one or more of the arguments. 706 */ 707 public final int fuzzyArgsMatch(ClassInfo... argTypes) { 708 int matches = 0; 709 outer: for (ClassInfo pi : getParamTypes()) { 710 for (ClassInfo a : argTypes) { 711 if (pi.isParentOfFuzzyPrimitives(a)) { 712 matches++; 713 continue outer; 714 } 715 } 716 return -1; 717 } 718 return matches; 719 } 720 721 /** 722 * Returns <jk>true</jk> if this method has the {@link Deprecated @Deprecated} annotation on it. 723 * 724 * @return <jk>true</jk> if this method has the {@link Deprecated @Deprecated} annotation on it. 725 */ 726 public final boolean isDeprecated() { 727 return e.isAnnotationPresent(Deprecated.class); 728 729 } 730 731 /** 732 * Returns <jk>true</jk> if this method doesn't have the {@link Deprecated @Deprecated} annotation on it. 733 * 734 * @return <jk>true</jk> if this method doesn't have the {@link Deprecated @Deprecated} annotation on it. 735 */ 736 public final boolean isNotDeprecated() { 737 return ! e.isAnnotationPresent(Deprecated.class); 738 739 } 740 741 /** 742 * Returns <jk>true</jk> if this method is abstract. 743 * 744 * @return <jk>true</jk> if this method is abstract. 745 */ 746 public final boolean isAbstract() { 747 return Modifier.isAbstract(e.getModifiers()); 748 } 749 750 /** 751 * Returns <jk>true</jk> if this method is not abstract. 752 * 753 * @return <jk>true</jk> if this method is not abstract. 754 */ 755 public final boolean isNotAbstract() { 756 return ! Modifier.isAbstract(e.getModifiers()); 757 } 758 759 /** 760 * Returns <jk>true</jk> if this method is public. 761 * 762 * @return <jk>true</jk> if this method is public. 763 */ 764 public final boolean isPublic() { 765 return Modifier.isPublic(e.getModifiers()); 766 } 767 768 /** 769 * Returns <jk>true</jk> if this method is not public. 770 * 771 * @return <jk>true</jk> if this method is not public. 772 */ 773 public final boolean isNotPublic() { 774 return ! Modifier.isPublic(e.getModifiers()); 775 } 776 777 /** 778 * Returns <jk>true</jk> if this method is protected. 779 * 780 * @return <jk>true</jk> if this method is protected. 781 */ 782 public final boolean isProtected() { 783 return Modifier.isProtected(e.getModifiers()); 784 } 785 786 /** 787 * Returns <jk>true</jk> if this method is not protected. 788 * 789 * @return <jk>true</jk> if this method is not protected. 790 */ 791 public final boolean isNotProtected() { 792 return ! Modifier.isProtected(e.getModifiers()); 793 } 794 795 /** 796 * Returns <jk>true</jk> if this method is static. 797 * 798 * @return <jk>true</jk> if this method is static. 799 */ 800 public final boolean isStatic() { 801 return Modifier.isStatic(e.getModifiers()); 802 } 803 804 /** 805 * Returns <jk>true</jk> if this method is not static. 806 * 807 * @return <jk>true</jk> if this method is not static. 808 */ 809 public final boolean isNotStatic() { 810 return ! Modifier.isStatic(e.getModifiers()); 811 } 812 813 //----------------------------------------------------------------------------------------------------------------- 814 // Visibility 815 //----------------------------------------------------------------------------------------------------------------- 816 817 /** 818 * Attempts to call <code>x.setAccessible(<jk>true</jk>)</code> and quietly ignores security exceptions. 819 * 820 * @return This object. 821 */ 822 @FluentSetter 823 public ExecutableInfo accessible() { 824 setAccessible(); 825 return this; 826 } 827 828 /** 829 * Attempts to call <code>x.setAccessible(<jk>true</jk>)</code> and quietly ignores security exceptions. 830 * 831 * @return <jk>true</jk> if call was successful. 832 */ 833 public final boolean setAccessible() { 834 try { 835 if (e != null) 836 e.setAccessible(true); 837 return true; 838 } catch (SecurityException e) { 839 return false; 840 } 841 } 842 843 /** 844 * Identifies if the specified visibility matches this method. 845 * 846 * @param v The visibility to validate against. 847 * @return <jk>true</jk> if this visibility matches the modifier attribute of this method. 848 */ 849 public final boolean isVisible(Visibility v) { 850 return v.isVisible(e); 851 } 852 853 //----------------------------------------------------------------------------------------------------------------- 854 // Labels 855 //----------------------------------------------------------------------------------------------------------------- 856 857 /** 858 * Returns <jk>true</jk> if this method has this name. 859 * 860 * @param name The name to test for. 861 * @return <jk>true</jk> if this method has this name. 862 */ 863 public final boolean hasName(String name) { 864 return getSimpleName().equals(name); 865 } 866 867 /** 868 * Returns <jk>true</jk> if this method has a name in the specified list. 869 * 870 * @param names The names to test for. 871 * @return <jk>true</jk> if this method has one of the names. 872 */ 873 public final boolean hasName(String...names) { 874 for (String n : names) 875 if (getSimpleName().equals(n)) 876 return true; 877 return false; 878 } 879 880 /** 881 * Returns <jk>true</jk> if this method has a name in the specified set. 882 * 883 * @param names The names to test for. 884 * @return <jk>true</jk> if this method has one of the names. 885 */ 886 public final boolean hasName(Set<String> names) { 887 return names.contains(getSimpleName()); 888 } 889 890 //----------------------------------------------------------------------------------------------------------------- 891 // Labels 892 //----------------------------------------------------------------------------------------------------------------- 893 894 /** 895 * Returns the full name of this executable. 896 * 897 * <h5 class='section'>Examples:</h5> 898 * <ul> 899 * <li><js>"com.foo.MyClass.get(java.util.String)"</js> - Method. 900 * <li><js>"com.foo.MyClass(java.util.String)"</js> - Constructor. 901 * </ul> 902 * 903 * @return The underlying executable name. 904 */ 905 public final String getFullName() { 906 StringBuilder sb = new StringBuilder(128); 907 ClassInfo dc = declaringClass; 908 Package p = dc.getPackage(); 909 if (p != null) 910 sb.append(p.getName()).append('.'); 911 dc.appendShortName(sb); 912 if (! isConstructor) 913 sb.append('.').append(getSimpleName()); 914 sb.append('('); 915 List<ClassInfo> pt = getParamTypes(); 916 for (int i = 0; i < pt.size(); i++) { 917 if (i > 0) 918 sb.append(','); 919 pt.get(i).appendFullName(sb); 920 } 921 sb.append(')'); 922 return sb.toString(); 923 } 924 925 /** 926 * Returns the short name of this executable. 927 * 928 * <h5 class='section'>Examples:</h5> 929 * <ul> 930 * <li><js>"MyClass.get(String)"</js> - Method. 931 * <li><js>"MyClass(String)"</js> - Constructor. 932 * </ul> 933 * 934 * @return The underlying executable name. 935 */ 936 public final String getShortName() { 937 StringBuilder sb = new StringBuilder(64); 938 sb.append(getSimpleName()).append('('); 939 Class<?>[] pt = _getRawParamTypes(); 940 for (int i = 0; i < pt.length; i++) { 941 if (i > 0) 942 sb.append(','); 943 sb.append(pt[i].getSimpleName()); 944 } 945 sb.append(')'); 946 return sb.toString(); 947 } 948 949 /** 950 * Returns the simple name of the underlying method. 951 * 952 * @return The simple name of the underlying method; 953 */ 954 public final String getSimpleName() { 955 return isConstructor ? e.getDeclaringClass().getSimpleName() : e.getName(); 956 } 957 958 @Override 959 public String toString() { 960 return getShortName(); 961 } 962 963 // <FluentSetters> 964 965 // </FluentSetters> 966}