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