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.internal;
014
015import static org.apache.juneau.internal.ClassFlags.*;
016import static org.apache.juneau.internal.CollectionUtils.*;
017
018import java.io.*;
019import java.lang.annotation.*;
020import java.lang.reflect.*;
021import java.util.*;
022import java.util.concurrent.*;
023
024import org.apache.juneau.*;
025import org.apache.juneau.utils.*;
026
027/**
028 * Class-related utility methods.
029 */
030public final class ClassUtils {
031
032   private static final Map<Class<?>,ConstructorCacheEntry> CONSTRUCTOR_CACHE = new ConcurrentHashMap<>();
033
034   /**
035    * Given the specified list of objects, return readable names for the class types of the objects.
036    *
037    * @param o The objects.
038    * @return An array of readable class type strings.
039    */
040   public static ObjectList getReadableClassNames(Object[] o) {
041      ObjectList l = new ObjectList();
042      for (int i = 0; i < o.length; i++)
043         l.add(o[i] == null ? "null" : getReadableClassName(o[i].getClass()));
044      return l;
045   }
046
047   /**
048    * Shortcut for calling <code><jsm>getReadableClassName</jsm>(c.getName())</code>
049    *
050    * @param c The class.
051    * @return A readable class type name, or <jk>null</jk> if parameter is <jk>null</jk>.
052    */
053   public static String getReadableClassName(Class<?> c) {
054      if (c == null)
055         return null;
056      return getReadableClassName(c.getName());
057   }
058
059   /**
060    * Shortcut for calling <code><jsm>getReadableClassName</jsm>(c.getClass().getName())</code>
061    *
062    * @param o The object whose class we want to render.
063    * @return A readable class type name, or <jk>null</jk> if parameter is <jk>null</jk>.
064    */
065   public static String getReadableClassNameForObject(Object o) {
066      if (o == null)
067         return null;
068      return getReadableClassName(o.getClass().getName());
069   }
070
071   /**
072    * Converts the specified class name to a readable form when class name is a special construct like <js>"[[Z"</js>.
073    *
074    * <h5 class='section'>Example:</h5>
075    * <p class='bcode w800'>
076    *    <jsm>getReadableClassName</jsm>(<js>"java.lang.Object"</js>);  <jc>// Returns "java.lang.Object"</jc>
077    *    <jsm>getReadableClassName</jsm>(<js>"boolean"</js>);  <jc>// Returns "boolean"</jc>
078    *    <jsm>getReadableClassName</jsm>(<js>"[Z"</js>);  <jc>// Returns "boolean[]"</jc>
079    *    <jsm>getReadableClassName</jsm>(<js>"[[Z"</js>);  <jc>// Returns "boolean[][]"</jc>
080    *    <jsm>getReadableClassName</jsm>(<js>"[Ljava.lang.Object;"</js>);  <jc>// Returns "java.lang.Object[]"</jc>
081    *    <jsm>getReadableClassName</jsm>(<jk>null</jk>);  <jc>// Returns null</jc>
082    * </p>
083    *
084    * @param className The class name.
085    * @return A readable class type name, or <jk>null</jk> if parameter is <jk>null</jk>.
086    */
087   public static String getReadableClassName(String className) {
088      if (className == null)
089         return null;
090      if (! StringUtils.startsWith(className, '['))
091         return className;
092      int depth = 0;
093      for (int i = 0; i < className.length(); i++) {
094         if (className.charAt(i) == '[')
095            depth++;
096         else
097            break;
098      }
099      char type = className.charAt(depth);
100      String c;
101      switch (type) {
102         case 'Z': c = "boolean"; break;
103         case 'B': c = "byte"; break;
104         case 'C': c = "char"; break;
105         case 'D': c = "double"; break;
106         case 'F': c = "float"; break;
107         case 'I': c = "int"; break;
108         case 'J': c = "long"; break;
109         case 'S': c = "short"; break;
110         default: c = className.substring(depth+1, className.length()-1);
111      }
112      StringBuilder sb = new StringBuilder(c.length() + 2*depth).append(c);
113      for (int i = 0; i < depth; i++)
114         sb.append("[]");
115      return sb.toString();
116   }
117
118   /**
119    * Converts the string generated by {@link #getReadableClassName(Class)} back into a {@link Class}.
120    *
121    * <p>
122    * Generics are stripped from the string since they cannot be converted to a class.
123    *
124    * @param cl The classloader to use to load the class.
125    * @param name The readable class name.
126    * @return The class object.
127    * @throws ClassNotFoundException
128    */
129   public static Class<?> getClassFromReadableName(ClassLoader cl, String name) throws ClassNotFoundException {
130      return cl.loadClass(name);
131   }
132
133   /**
134    * Returns <jk>true</jk> if <code>parent</code> is a parent class of <code>child</code>.
135    *
136    * @param parent The parent class.
137    * @param child The child class.
138    * @param strict If <jk>true</jk> returns <jk>false</jk> if the classes are the same.
139    * @return <jk>true</jk> if <code>parent</code> is a parent class of <code>child</code>.
140    */
141   public static boolean isParentClass(Class<?> parent, Class<?> child, boolean strict) {
142      return parent.isAssignableFrom(child) && ((!strict) || ! parent.equals(child));
143   }
144
145   /**
146    * Returns <jk>true</jk> if <code>parent</code> is a parent class or the same as <code>child</code>.
147    *
148    * @param parent The parent class.
149    * @param child The child class.
150    * @return <jk>true</jk> if <code>parent</code> is a parent class or the same as <code>child</code>.
151    */
152   public static boolean isParentClass(Class<?> parent, Class<?> child) {
153      return isParentClass(parent, child, false);
154   }
155
156   /**
157    * Returns <jk>true</jk> if <code>parent</code> is a parent class or the same as <code>child</code>.
158    *
159    * @param parent The parent class.
160    * @param child The child class.
161    * @return <jk>true</jk> if <code>parent</code> is a parent class or the same as <code>child</code>.
162    */
163   public static boolean isParentClass(Class<?> parent, Type child) {
164      if (child instanceof Class)
165         return isParentClass(parent, (Class<?>)child);
166      return false;
167   }
168
169   /**
170    * Returns the signature of the specified method.
171    *
172    * <p>
173    * For no-arg methods, the signature will be a simple string such as <js>"toString"</js>.
174    * For methods with one or more args, the arguments will be fully-qualified class names (e.g.
175    * <js>"append(java.util.StringBuilder,boolean)"</js>)
176    *
177    * @param m The methods to get the signature on.
178    * @return The methods signature.
179    */
180   public static String getMethodSignature(Method m) {
181      StringBuilder sb = new StringBuilder(m.getName());
182      Class<?>[] pt = m.getParameterTypes();
183      if (pt.length > 0) {
184         sb.append('(');
185         for (int i = 0; i < pt.length; i++) {
186            if (i > 0)
187               sb.append(',');
188            sb.append(getReadableClassName(pt[i]));
189         }
190         sb.append(')');
191      }
192      return sb.toString();
193   }
194
195   private static final Map<Class<?>, Class<?>>
196      pmap1 = new HashMap<>(),
197      pmap2 = new HashMap<>();
198   static {
199      pmap1.put(boolean.class, Boolean.class);
200      pmap1.put(byte.class, Byte.class);
201      pmap1.put(short.class, Short.class);
202      pmap1.put(char.class, Character.class);
203      pmap1.put(int.class, Integer.class);
204      pmap1.put(long.class, Long.class);
205      pmap1.put(float.class, Float.class);
206      pmap1.put(double.class, Double.class);
207      pmap2.put(Boolean.class, boolean.class);
208      pmap2.put(Byte.class, byte.class);
209      pmap2.put(Short.class, short.class);
210      pmap2.put(Character.class, char.class);
211      pmap2.put(Integer.class, int.class);
212      pmap2.put(Long.class, long.class);
213      pmap2.put(Float.class, float.class);
214      pmap2.put(Double.class, double.class);
215   }
216
217   /**
218    * Returns <jk>true</jk> if the {@link #getPrimitiveWrapper(Class)} class returns a value for the specified class.
219    *
220    * @param c The class.
221    * @return <jk>true</jk> if the {@link #getPrimitiveWrapper(Class)} class returns a value for the specified class.
222    */
223   public static boolean hasPrimitiveWrapper(Class<?> c) {
224      return pmap1.containsKey(c);
225   }
226
227   /**
228    * If the specified class is a primitive (e.g. <code><jk>int</jk>.<jk>class</jk></code>) returns it's wrapper class
229    * (e.g. <code>Integer.<jk>class</jk></code>).
230    *
231    * @param c The class.
232    * @return The wrapper class, or <jk>null</jk> if class is not a primitive.
233    */
234   public static Class<?> getPrimitiveWrapper(Class<?> c) {
235      return pmap1.get(c);
236   }
237
238   /**
239    * If the specified class is a primitive wrapper (e.g. <code><jk>Integer</jk>.<jk>class</jk></code>) returns it's
240    * primitive class (e.g. <code>int.<jk>class</jk></code>).
241    *
242    * @param c The class.
243    * @return The primitive class, or <jk>null</jk> if class is not a primitive wrapper.
244    */
245   public static Class<?> getPrimitiveForWrapper(Class<?> c) {
246      return pmap2.get(c);
247   }
248
249   /**
250    * If the specified class is a primitive (e.g. <code><jk>int</jk>.<jk>class</jk></code>) returns it's wrapper class
251    * (e.g. <code>Integer.<jk>class</jk></code>).
252    *
253    * @param c The class.
254    * @return The wrapper class if it's primitive, or the same class if class is not a primitive.
255    */
256   public static Class<?> getWrapperIfPrimitive(Class<?> c) {
257      if (! c.isPrimitive())
258         return c;
259      return pmap1.get(c);
260   }
261
262   /**
263    * Returns <jk>true</jk> if all specified flags are applicable to the specified class.
264    *
265    * @param x The class to test.
266    * @param flags The flags to test for.
267    * @return <jk>true</jk> if all specified flags are applicable to the specified class.
268    */
269   public static boolean isAll(Class<?> x, ClassFlags...flags) {
270      for (ClassFlags f : flags) {
271         switch (f) {
272            case DEPRECATED:
273               if (isNotDeprecated(x))
274                  return false;
275               break;
276            case NOT_DEPRECATED:
277               if (isDeprecated(x))
278                  return false;
279               break;
280            case PUBLIC:
281               if (isNotPublic(x))
282                  return false;
283               break;
284            case NOT_PUBLIC:
285               if (isPublic(x))
286                  return false;
287               break;
288            case STATIC:
289               if (isNotStatic(x))
290                  return false;
291               break;
292            case NOT_STATIC:
293               if (isStatic(x))
294                  return false;
295               break;
296            case ABSTRACT:
297               if (isNotAbstract(x))
298                  return false;
299               break;
300            case NOT_ABSTRACT:
301               if (isAbstract(x))
302                  return false;
303               break;
304            case HAS_ARGS:
305            case HAS_NO_ARGS:
306            case TRANSIENT:
307            case NOT_TRANSIENT:
308            default:
309               break;
310
311         }
312      }
313      return true;
314   }
315
316   /**
317    * Returns <jk>true</jk> if all specified flags are applicable to the specified method.
318    *
319    * @param x The method to test.
320    * @param flags The flags to test for.
321    * @return <jk>true</jk> if all specified flags are applicable to the specified method.
322    */
323   public static boolean isAll(Method x, ClassFlags...flags) {
324      for (ClassFlags f : flags) {
325         switch (f) {
326            case DEPRECATED:
327               if (isNotDeprecated(x))
328                  return false;
329               break;
330            case NOT_DEPRECATED:
331               if (isDeprecated(x))
332                  return false;
333               break;
334            case HAS_ARGS:
335               if (hasNoArgs(x))
336                  return false;
337               break;
338            case HAS_NO_ARGS:
339               if (hasArgs(x))
340                  return false;
341               break;
342            case PUBLIC:
343               if (isNotPublic(x))
344                  return false;
345               break;
346            case NOT_PUBLIC:
347               if (isPublic(x))
348                  return false;
349               break;
350            case STATIC:
351               if (isNotStatic(x))
352                  return false;
353               break;
354            case NOT_STATIC:
355               if (isStatic(x))
356                  return false;
357               break;
358            case ABSTRACT:
359               if (isNotAbstract(x))
360                  return false;
361               break;
362            case NOT_ABSTRACT:
363               if (isAbstract(x))
364                  return false;
365               break;
366            case TRANSIENT:
367            case NOT_TRANSIENT:
368            default:
369               break;
370
371         }
372      }
373      return true;
374   }
375
376   /**
377    * Returns <jk>true</jk> if all specified flags are applicable to the specified constructor.
378    *
379    * @param x The constructor to test.
380    * @param flags The flags to test for.
381    * @return <jk>true</jk> if all specified flags are applicable to the specified constructor.
382    */
383   public static boolean isAll(Constructor<?> x, ClassFlags...flags) {
384      for (ClassFlags f : flags) {
385         switch (f) {
386            case DEPRECATED:
387               if (isNotDeprecated(x))
388                  return false;
389               break;
390            case NOT_DEPRECATED:
391               if (isDeprecated(x))
392                  return false;
393               break;
394            case HAS_ARGS:
395               if (hasNoArgs(x))
396                  return false;
397               break;
398            case HAS_NO_ARGS:
399               if (hasArgs(x))
400                  return false;
401               break;
402            case PUBLIC:
403               if (isNotPublic(x))
404                  return false;
405               break;
406            case NOT_PUBLIC:
407               if (isPublic(x))
408                  return false;
409               break;
410            case STATIC:
411            case NOT_STATIC:
412            case ABSTRACT:
413            case NOT_ABSTRACT:
414            case TRANSIENT:
415            case NOT_TRANSIENT:
416            default:
417               break;
418
419         }
420      }
421      return true;
422   }
423
424   /**
425    * Returns <jk>true</jk> if all specified flags are applicable to the specified field.
426    *
427    * @param x The field to test.
428    * @param flags The flags to test for.
429    * @return <jk>true</jk> if all specified flags are applicable to the specified field.
430    */
431   public static boolean isAll(Field x, ClassFlags...flags) {
432      for (ClassFlags f : flags) {
433         switch (f) {
434            case DEPRECATED:
435               if (isNotDeprecated(x))
436                  return false;
437               break;
438            case NOT_DEPRECATED:
439               if (isDeprecated(x))
440                  return false;
441               break;
442            case HAS_ARGS:
443               break;
444            case HAS_NO_ARGS:
445               break;
446            case PUBLIC:
447               if (isNotPublic(x))
448                  return false;
449               break;
450            case NOT_PUBLIC:
451               if (isPublic(x))
452                  return false;
453               break;
454            case STATIC:
455               if (isNotStatic(x))
456                  return false;
457               break;
458            case NOT_STATIC:
459               if (isStatic(x))
460                  return false;
461               break;
462            case TRANSIENT:
463               if (isNotTransient(x))
464                  return false;
465               break;
466            case NOT_TRANSIENT:
467               if (isTransient(x))
468                  return false;
469               break;
470            case ABSTRACT:
471            case NOT_ABSTRACT:
472            default:
473               break;
474
475         }
476      }
477      return true;
478   }
479
480   /**
481    * Returns <jk>true</jk> if all specified flags are applicable to the specified class.
482    *
483    * @param x The class to test.
484    * @param flags The flags to test for.
485    * @return <jk>true</jk> if all specified flags are applicable to the specified class.
486    */
487   public static boolean isAny(Class<?> x, ClassFlags...flags) {
488      for (ClassFlags f : flags) {
489         switch (f) {
490            case DEPRECATED:
491               if (isDeprecated(x))
492                  return true;
493               break;
494            case NOT_DEPRECATED:
495               if (isNotDeprecated(x))
496                  return true;
497               break;
498            case PUBLIC:
499               if (isPublic(x))
500                  return true;
501               break;
502            case NOT_PUBLIC:
503               if (isNotPublic(x))
504                  return true;
505               break;
506            case STATIC:
507               if (isStatic(x))
508                  return true;
509               break;
510            case NOT_STATIC:
511               if (isNotStatic(x))
512                  return true;
513               break;
514            case ABSTRACT:
515               if (isAbstract(x))
516                  return true;
517               break;
518            case NOT_ABSTRACT:
519               if (isNotAbstract(x))
520                  return true;
521               break;
522            case TRANSIENT:
523            case NOT_TRANSIENT:
524            case HAS_ARGS:
525            case HAS_NO_ARGS:
526            default:
527               break;
528
529         }
530      }
531      return false;
532   }
533
534   /**
535    * Returns <jk>true</jk> if all specified flags are applicable to the specified method.
536    *
537    * @param x The method to test.
538    * @param flags The flags to test for.
539    * @return <jk>true</jk> if all specified flags are applicable to the specified method.
540    */
541   public static boolean isAny(Method x, ClassFlags...flags) {
542      for (ClassFlags f : flags) {
543         switch (f) {
544            case DEPRECATED:
545               if (isDeprecated(x))
546                  return true;
547               break;
548            case NOT_DEPRECATED:
549               if (isNotDeprecated(x))
550                  return true;
551               break;
552            case HAS_ARGS:
553               if (hasArgs(x))
554                  return true;
555               break;
556            case HAS_NO_ARGS:
557               if (hasNoArgs(x))
558                  return true;
559               break;
560            case PUBLIC:
561               if (isPublic(x))
562                  return true;
563               break;
564            case NOT_PUBLIC:
565               if (isNotPublic(x))
566                  return true;
567               break;
568            case STATIC:
569               if (isStatic(x))
570                  return true;
571               break;
572            case NOT_STATIC:
573               if (isNotStatic(x))
574                  return true;
575               break;
576            case ABSTRACT:
577               if (isAbstract(x))
578                  return true;
579               break;
580            case NOT_ABSTRACT:
581               if (isNotAbstract(x))
582                  return true;
583               break;
584            case TRANSIENT:
585            case NOT_TRANSIENT:
586            default:
587               break;
588
589         }
590      }
591      return false;
592   }
593
594   /**
595    * Returns <jk>true</jk> if all specified flags are applicable to the specified constructor.
596    *
597    * @param x The constructor to test.
598    * @param flags The flags to test for.
599    * @return <jk>true</jk> if all specified flags are applicable to the specified constructor.
600    */
601   public static boolean isAny(Constructor<?> x, ClassFlags...flags) {
602      for (ClassFlags f : flags) {
603         switch (f) {
604            case DEPRECATED:
605               if (isDeprecated(x))
606                  return true;
607               break;
608            case NOT_DEPRECATED:
609               if (isNotDeprecated(x))
610                  return true;
611               break;
612            case HAS_ARGS:
613               if (hasArgs(x))
614                  return true;
615               break;
616            case HAS_NO_ARGS:
617               if (hasNoArgs(x))
618                  return true;
619               break;
620            case PUBLIC:
621               if (isPublic(x))
622                  return true;
623               break;
624            case NOT_PUBLIC:
625               if (isNotPublic(x))
626                  return true;
627               break;
628            case STATIC:
629            case NOT_STATIC:
630            case ABSTRACT:
631            case NOT_ABSTRACT:
632            case TRANSIENT:
633            case NOT_TRANSIENT:
634            default:
635               break;
636
637         }
638      }
639      return false;
640   }
641
642   /**
643    * Returns <jk>true</jk> if all specified flags are applicable to the specified field.
644    *
645    * @param x The field to test.
646    * @param flags The flags to test for.
647    * @return <jk>true</jk> if all specified flags are applicable to the specified field.
648    */
649   public static boolean isAny(Field x, ClassFlags...flags) {
650      for (ClassFlags f : flags) {
651         switch (f) {
652            case DEPRECATED:
653               if (isDeprecated(x))
654                  return true;
655               break;
656            case NOT_DEPRECATED:
657               if (isNotDeprecated(x))
658                  return true;
659               break;
660            case PUBLIC:
661               if (isPublic(x))
662                  return true;
663               break;
664            case NOT_PUBLIC:
665               if (isNotPublic(x))
666                  return true;
667               break;
668            case STATIC:
669               if (isStatic(x))
670                  return true;
671               break;
672            case NOT_STATIC:
673               if (isNotStatic(x))
674                  return true;
675               break;
676            case TRANSIENT:
677               if (isTransient(x))
678                  return true;
679               break;
680            case NOT_TRANSIENT:
681               if (isNotTransient(x))
682                  return true;
683               break;
684            case HAS_ARGS:
685            case HAS_NO_ARGS:
686            case ABSTRACT:
687            case NOT_ABSTRACT:
688            default:
689               break;
690
691         }
692      }
693      return false;
694   }
695
696   /**
697    * Returns <jk>true</jk> if the specified method has the specified arguments.
698    *
699    * @param x The method to test.
700    * @param args The arguments to test for.
701    * @return <jk>true</jk> if the specified method has the specified arguments in the exact order.
702    */
703   public static boolean hasArgs(Method x, Class<?>...args) {
704      Class<?>[] pt = x.getParameterTypes();
705      if (pt.length == args.length) {
706         for (int i = 0; i < pt.length; i++)
707            if (! pt[i].equals(args[i]))
708               return false;
709         return true;
710      }
711      return false;
712   }
713
714   /**
715    * Returns <jk>true</jk> if the specified constructor has the specified arguments.
716    *
717    * @param x The constructor to test.
718    * @param args The arguments to test for.
719    * @return <jk>true</jk> if the specified constructor has the specified arguments in the exact order.
720    */
721   public static boolean hasArgs(Constructor<?> x, Class<?>...args) {
722      Class<?>[] pt = x.getParameterTypes();
723      if (pt.length == args.length) {
724         for (int i = 0; i < pt.length; i++)
725            if (! pt[i].equals(args[i]))
726               return false;
727         return true;
728      }
729      return false;
730   }
731
732   /**
733    * Returns <jk>true</jk> if the specified constructor has one or more arguments.
734    *
735    * @param x The method to test.
736    * @return <jk>true</jk> if the specified constructor has one or more arguments.
737    */
738   public static boolean hasArgs(Constructor<?> x) {
739      return x.getParameterTypes().length > 0;
740   }
741
742   /**
743    * Returns <jk>true</jk> if the specified constructor has zero arguments.
744    *
745    * @param x The method to test.
746    * @return <jk>true</jk> if the specified constructor has zero arguments.
747    */
748   public static boolean hasNoArgs(Constructor<?> x) {
749      return x.getParameterTypes().length == 0;
750   }
751
752   /**
753    * Returns <jk>true</jk> if the specified constructor has the specified number of arguments.
754    *
755    * @param x The method to test.
756    * @param number The number of expected arguments.
757    * @return <jk>true</jk> if the specified method has the specified number of arguments.
758    */
759   public static boolean hasNumArgs(Method x, int number) {
760      return x.getParameterTypes().length == number;
761   }
762
763   /**
764    * Returns <jk>true</jk> if the specified constructor has the specified number of arguments.
765    *
766    * @param x The constructor to test.
767    * @param number The number of expected arguments.
768    * @return <jk>true</jk> if the specified constructor has the specified number of arguments.
769    */
770   public static boolean hasNumArgs(Constructor<?> x, int number) {
771      return x.getParameterTypes().length == number;
772   }
773
774   /**
775    * Returns <jk>true</jk> if the specified method has at most only the specified arguments in any order.
776    *
777    * @param x The method to test.
778    * @param args The arguments to test for.
779    * @return <jk>true</jk> if the specified method has at most only the specified arguments in any order.
780    */
781   public static boolean hasFuzzyArgs(Method x, Class<?>...args) {
782      return fuzzyArgsMatch(x.getParameterTypes(), args) != -1;
783   }
784
785   /**
786    * Returns <jk>true</jk> if the specified constructor has at most only the specified arguments in any order.
787    *
788    * @param x The constructor to test.
789    * @param args The arguments to test for.
790    * @return <jk>true</jk> if the specified constructor has at most only the specified arguments in any order.
791    */
792   public static boolean hasFuzzyArgs(Constructor<?> x, Class<?>...args) {
793      return fuzzyArgsMatch(x.getParameterTypes(), args) != -1;
794   }
795
796   /**
797    * Returns <jk>true</jk> if the specified class has the {@link Deprecated @Deprecated} annotation on it.
798    *
799    * @param c The class.
800    * @return <jk>true</jk> if the specified class has the {@link Deprecated @Deprecated} annotation on it.
801    */
802   public static boolean isDeprecated(Class<?> c) {
803      return c.isAnnotationPresent(Deprecated.class);
804   }
805
806   /**
807    * Returns <jk>true</jk> if the specified method has the {@link Deprecated @Deprecated} annotation on it.
808    *
809    * @param m The method.
810    * @return <jk>true</jk> if the specified method has the {@link Deprecated @Deprecated} annotation on it.
811    */
812   public static boolean isDeprecated(Method m) {
813      return m.isAnnotationPresent(Deprecated.class);
814
815   }
816
817   /**
818    * Returns <jk>true</jk> if the specified constructor has the {@link Deprecated @Deprecated} annotation on it.
819    *
820    * @param c The constructor.
821    * @return <jk>true</jk> if the specified constructor has the {@link Deprecated @Deprecated} annotation on it.
822    */
823   public static boolean isDeprecated(Constructor<?> c) {
824      return c.isAnnotationPresent(Deprecated.class);
825   }
826
827   /**
828    * Returns <jk>true</jk> if the specified field has the {@link Deprecated @Deprecated} annotation on it.
829    *
830    * @param f The field.
831    * @return <jk>true</jk> if the specified field has the {@link Deprecated @Deprecated} annotation on it.
832    */
833   public static boolean isDeprecated(Field f) {
834      return f.isAnnotationPresent(Deprecated.class);
835   }
836
837   /**
838    * Returns <jk>true</jk> if the specified class doesn't have the {@link Deprecated @Deprecated} annotation on it.
839    *
840    * @param c The class.
841    * @return <jk>true</jk> if the specified class doesn't have the {@link Deprecated @Deprecated} annotation on it.
842    */
843   public static boolean isNotDeprecated(Class<?> c) {
844      return ! c.isAnnotationPresent(Deprecated.class);
845   }
846
847   /**
848    * Returns <jk>true</jk> if the specified method doesn't have the {@link Deprecated @Deprecated} annotation on it.
849    *
850    * @param m The method.
851    * @return <jk>true</jk> if the specified method doesn't have the {@link Deprecated @Deprecated} annotation on it.
852    */
853   public static boolean isNotDeprecated(Method m) {
854      return ! m.isAnnotationPresent(Deprecated.class);
855
856   }
857
858   /**
859    * Returns <jk>true</jk> if the specified constructor doesn't have the {@link Deprecated @Deprecated} annotation on it.
860    *
861    * @param c The constructor.
862    * @return <jk>true</jk> if the specified constructor doesn't have the {@link Deprecated @Deprecated} annotation on it.
863    */
864   public static boolean isNotDeprecated(Constructor<?> c) {
865      return ! c.isAnnotationPresent(Deprecated.class);
866   }
867
868   /**
869    * Returns <jk>true</jk> if the specified field doesn't have the {@link Deprecated @Deprecated} annotation on it.
870    *
871    * @param f The field.
872    * @return <jk>true</jk> if the specified field doesn't have the {@link Deprecated @Deprecated} annotation on it.
873    */
874   public static boolean isNotDeprecated(Field f) {
875      return ! f.isAnnotationPresent(Deprecated.class);
876   }
877
878   /**
879    * Returns <jk>true</jk> if the specified class is public.
880    *
881    * @param c The class.
882    * @return <jk>true</jk> if the specified class is public.
883    */
884   public static boolean isPublic(Class<?> c) {
885      return Modifier.isPublic(c.getModifiers());
886   }
887
888   /**
889    * Returns <jk>true</jk> if the specified class is not public.
890    *
891    * @param c The class.
892    * @return <jk>true</jk> if the specified class is not public.
893    */
894   public static boolean isNotPublic(Class<?> c) {
895      return ! Modifier.isPublic(c.getModifiers());
896   }
897
898   /**
899    * Returns <jk>true</jk> if the specified class is public.
900    *
901    * @param c The class.
902    * @return <jk>true</jk> if the specified class is public.
903    */
904   public static boolean isStatic(Class<?> c) {
905      return Modifier.isStatic(c.getModifiers());
906   }
907
908   /**
909    * Returns <jk>true</jk> if the specified class is not static.
910    *
911    * @param c The class.
912    * @return <jk>true</jk> if the specified class is not static.
913    */
914   public static boolean isNotStatic(Class<?> c) {
915      return ! Modifier.isStatic(c.getModifiers());
916   }
917
918   /**
919    * Returns <jk>true</jk> if the specified class is abstract.
920    *
921    * @param c The class.
922    * @return <jk>true</jk> if the specified class is abstract.
923    */
924   public static boolean isAbstract(Class<?> c) {
925      return Modifier.isAbstract(c.getModifiers());
926   }
927
928   /**
929    * Returns <jk>true</jk> if the specified class is not abstract.
930    *
931    * @param c The class.
932    * @return <jk>true</jk> if the specified class is not abstract.
933    */
934   public static boolean isNotAbstract(Class<?> c) {
935      return ! Modifier.isAbstract(c.getModifiers());
936   }
937
938   /**
939    * Returns <jk>true</jk> if the specified method is abstract.
940    *
941    * @param m The method.
942    * @return <jk>true</jk> if the specified method is abstract.
943    */
944   public static boolean isAbstract(Method m) {
945      return Modifier.isAbstract(m.getModifiers());
946   }
947
948   /**
949    * Returns <jk>true</jk> if the specified method is not abstract.
950    *
951    * @param m The method.
952    * @return <jk>true</jk> if the specified method is not abstract.
953    */
954   public static boolean isNotAbstract(Method m) {
955      return ! Modifier.isAbstract(m.getModifiers());
956   }
957
958   /**
959    * Returns <jk>true</jk> if the specified method is public.
960    *
961    * @param m The method.
962    * @return <jk>true</jk> if the specified method is public.
963    */
964   public static boolean isPublic(Method m) {
965      return Modifier.isPublic(m.getModifiers());
966   }
967
968   /**
969    * Returns <jk>true</jk> if the specified method is not public.
970    *
971    * @param m The method.
972    * @return <jk>true</jk> if the specified method is not public.
973    */
974   public static boolean isNotPublic(Method m) {
975      return ! Modifier.isPublic(m.getModifiers());
976   }
977
978   /**
979    * Returns <jk>true</jk> if the specified field is public.
980    *
981    * @param f The field.
982    * @return <jk>true</jk> if the specified field is public.
983    */
984   public static boolean isPublic(Field f) {
985      return Modifier.isPublic(f.getModifiers());
986   }
987
988   /**
989    * Returns <jk>true</jk> if the specified field is not public.
990    *
991    * @param f The field.
992    * @return <jk>true</jk> if the specified field is not public.
993    */
994   public static boolean isNotPublic(Field f) {
995      return ! Modifier.isPublic(f.getModifiers());
996   }
997
998   /**
999    * Returns <jk>true</jk> if the specified method is static.
1000    *
1001    * @param m The method.
1002    * @return <jk>true</jk> if the specified method is static.
1003    */
1004   public static boolean isStatic(Method m) {
1005      return Modifier.isStatic(m.getModifiers());
1006   }
1007
1008   /**
1009    * Returns <jk>true</jk> if the specified method is not static.
1010    *
1011    * @param m The method.
1012    * @return <jk>true</jk> if the specified method is not static.
1013    */
1014   public static boolean isNotStatic(Method m) {
1015      return !  Modifier.isStatic(m.getModifiers());
1016   }
1017
1018   /**
1019    * Returns <jk>true</jk> if the specified field is static.
1020    *
1021    * @param f The field.
1022    * @return <jk>true</jk> if the specified field is static.
1023    */
1024   public static boolean isStatic(Field f) {
1025      return Modifier.isStatic(f.getModifiers());
1026   }
1027
1028   /**
1029    * Returns <jk>true</jk> if the specified field is not static.
1030    *
1031    * @param f The field.
1032    * @return <jk>true</jk> if the specified field is not static.
1033    */
1034   public static boolean isNotStatic(Field f) {
1035      return ! Modifier.isStatic(f.getModifiers());
1036   }
1037
1038   /**
1039    * Returns <jk>true</jk> if the specified constructor is public.
1040    *
1041    * @param c The constructor.
1042    * @return <jk>true</jk> if the specified constructor is public.
1043    */
1044   public static boolean isPublic(Constructor<?> c) {
1045      return Modifier.isPublic(c.getModifiers());
1046   }
1047
1048   /**
1049    * Returns <jk>true</jk> if the specified constructor is not public.
1050    *
1051    * @param c The constructor.
1052    * @return <jk>true</jk> if the specified constructor is not public.
1053    */
1054   public static boolean isNotPublic(Constructor<?> c) {
1055      return ! Modifier.isPublic(c.getModifiers());
1056   }
1057
1058   /**
1059    * Returns <jk>true</jk> if the specified field is transient.
1060    *
1061    * @param f The field.
1062    * @return <jk>true</jk> if the specified field is transient.
1063    */
1064   public static boolean isTransient(Field f) {
1065      return Modifier.isTransient(f.getModifiers());
1066   }
1067
1068   /**
1069    * Returns <jk>true</jk> if the specified field is not transient.
1070    *
1071    * @param f The field.
1072    * @return <jk>true</jk> if the specified field is not transient.
1073    */
1074   public static boolean isNotTransient(Field f) {
1075      return ! Modifier.isTransient(f.getModifiers());
1076   }
1077
1078   /**
1079    * Returns <jk>true</jk> if the specified method has one or more arguments.
1080    *
1081    * @param x The method to test.
1082    * @return <jk>true</jk> if the specified method has one or more arguments.
1083    */
1084   public static boolean hasArgs(Method x) {
1085      return x.getParameterTypes().length > 0;
1086   }
1087
1088   /**
1089    * Returns <jk>true</jk> if the specified method has zero arguments.
1090    *
1091    * @param x The method to test.
1092    * @return <jk>true</jk> if the specified method has zero arguments.
1093    */
1094   public static boolean hasNoArgs(Method x) {
1095      return x.getParameterTypes().length == 0;
1096   }
1097
1098   /**
1099    * Returns <jk>true</jk> if the specified method has the specified name.
1100    *
1101    * @param m The method to test.
1102    * @param name The name to test for.
1103    * @return <jk>true</jk> if the specified method has the specified name.
1104    */
1105   public static boolean hasName(Method m, String name) {
1106      return m.getName().equals(name);
1107   }
1108
1109   /**
1110    * Returns <jk>true</jk> if the specified method has the specified return type.
1111    *
1112    * @param m The method to test.
1113    * @param c The return type to test for.
1114    * @return <jk>true</jk> if the specified method has the specified return type.
1115    */
1116   public static boolean hasReturnType(Method m, Class<?> c) {
1117      return m.getReturnType() == c;
1118   }
1119
1120   /**
1121    * Returns <jk>true</jk> if the specified method has the specified parent return type.
1122    *
1123    * @param m The method to test.
1124    * @param c The return type to test for.
1125    * @return <jk>true</jk> if the specified method has the specified parent return type.
1126    */
1127   public static boolean hasReturnTypeParent(Method m, Class<?> c) {
1128      return isParentClass(c, m.getReturnType());
1129   }
1130
1131   /**
1132    * Returns the specified annotation on the specified method.
1133    *
1134    * <p>
1135    * Similar to {@link Method#getAnnotation(Class)}, but searches up the parent hierarchy for the annotation
1136    * defined on parent classes and interfaces.
1137    *
1138    * <p>
1139    * Normally, annotations defined on methods of parent classes and interfaces are not inherited by the child methods.
1140    * This utility method gets around that limitation by searching the class hierarchy for the "same" method
1141    * (i.e. the same name and arguments).
1142    *
1143    * @param a The annotation to search for.
1144    * @param m The method to search.
1145    * @return The annotation, or <jk>null</jk> if it wasn't found.
1146    */
1147   public static <T extends Annotation> T getMethodAnnotation(Class<T> a, Method m) {
1148      return getMethodAnnotation(a, m.getDeclaringClass(), m);
1149   }
1150
1151   /**
1152    * Returns the specified annotation on the specified method.
1153    *
1154    * <p>
1155    * Similar to {@link Method#getAnnotation(Class)}, but searches up the parent hierarchy for the annotation defined
1156    * on parent classes and interfaces.
1157    *
1158    * <p>
1159    * Normally, annotations defined on methods of parent classes and interfaces are not inherited by the child methods.
1160    * This utility method gets around that limitation by searching the class hierarchy for the "same" method
1161    * (i.e. the same name and arguments).
1162    *
1163    * @param a The annotation to search for.
1164    * @param c
1165    *    The child class to start searching from.
1166    *    Note that it can be a descendant class of the actual declaring class of the method passed in.
1167    *    This allows you to find annotations on methods overridden by the method passed in.
1168    * @param method The method to search.
1169    * @return The annotation, or <jk>null</jk> if it wasn't found.
1170    */
1171   public static <T extends Annotation> T getMethodAnnotation(Class<T> a, Class<?> c, Method method) {
1172      for (Method m : c.getDeclaredMethods()) {
1173         if (isSameMethod(method, m)) {
1174            T t = m.getAnnotation(a);
1175            if (t != null)
1176               return t;
1177         }
1178      }
1179      Class<?> pc = c.getSuperclass();
1180      if (pc != null) {
1181         T t = getMethodAnnotation(a, pc, method);
1182         if (t != null)
1183            return t;
1184      }
1185      for (Class<?> ic : c.getInterfaces()) {
1186         T t = getMethodAnnotation(a, ic, method);
1187         if (t != null)
1188            return t;
1189      }
1190      return null;
1191   }
1192
1193   /**
1194    * Given a specific method, finds all declared methods with the same name and arguments on all
1195    * superclasses and interfaces.
1196    *
1197    * @param m The method to find matches against.
1198    * @return All matching methods including the input method itself.
1199    */
1200   public static List<Method> findMatchingMethods(Method m) {
1201      return findMatchingMethods(new ArrayList<Method>(), m);
1202   }
1203
1204   private static List<Method> findMatchingMethods(List<Method> l, Method m) {
1205      l.add(m);
1206      Class<?> c = m.getDeclaringClass();
1207      Class<?> pc = c.getSuperclass();
1208      if (pc != null)
1209         for (Method m2 : pc.getDeclaredMethods())
1210            if (isSameMethod(m, m2))
1211               findMatchingMethods(l, m2);
1212      for (Class<?> ic : c.getInterfaces())
1213         for (Method m2 : ic.getDeclaredMethods())
1214            if (isSameMethod(m, m2))
1215               findMatchingMethods(l, m2);
1216      return l;
1217   }
1218
1219   private static boolean isSameMethod(Method m1, Method m2) {
1220      return m1.getName().equals(m2.getName()) && Arrays.equals(m1.getParameterTypes(), m2.getParameterTypes());
1221   }
1222
1223   /**
1224    * Locates the no-arg constructor for the specified class.
1225    *
1226    * <p>
1227    * Constructor must match the visibility requirements specified by parameter 'v'.
1228    * If class is abstract, always returns <jk>null</jk>.
1229    * Note that this also returns the 1-arg constructor for non-static member classes.
1230    *
1231    * @param c The class from which to locate the no-arg constructor.
1232    * @param v The minimum visibility.
1233    * @return The constructor, or <jk>null</jk> if no no-arg constructor exists with the required visibility.
1234    */
1235   @SuppressWarnings({"rawtypes","unchecked"})
1236   public static final <T> Constructor<T> findNoArgConstructor(Class<T> c, Visibility v) {
1237      int mod = c.getModifiers();
1238      if (Modifier.isAbstract(mod))
1239         return null;
1240      boolean isMemberClass = c.isMemberClass() && ! isStatic(c);
1241      for (Constructor cc : c.getConstructors()) {
1242         mod = cc.getModifiers();
1243         if (hasNumArgs(cc, isMemberClass ? 1 : 0) && v.isVisible(mod) && isNotDeprecated(cc))
1244            return v.transform(cc);
1245      }
1246      return null;
1247   }
1248
1249   /**
1250    * Finds the real parameter type of the specified class.
1251    *
1252    * @param c The class containing the parameters (e.g. PojoSwap&lt;T,S&gt;)
1253    * @param index The zero-based index of the parameter to resolve.
1254    * @param oc The class we're trying to resolve the parameter type for.
1255    * @return The resolved real class.
1256    */
1257   public static Class<?> resolveParameterType(Class<?> c, int index, Class<?> oc) {
1258
1259      // We need to make up a mapping of type names.
1260      Map<Type,Type> typeMap = new HashMap<>();
1261      while (c != oc.getSuperclass()) {
1262         extractTypes(typeMap, oc);
1263         oc = oc.getSuperclass();
1264      }
1265
1266      Type gsc = oc.getGenericSuperclass();
1267
1268      // Not actually a parameterized type.
1269      if (! (gsc instanceof ParameterizedType))
1270         return Object.class;
1271
1272      ParameterizedType opt = (ParameterizedType)gsc;
1273      Type actualType = opt.getActualTypeArguments()[index];
1274
1275      if (typeMap.containsKey(actualType))
1276         actualType = typeMap.get(actualType);
1277
1278      if (actualType instanceof Class) {
1279         return (Class<?>)actualType;
1280
1281      } else if (actualType instanceof GenericArrayType) {
1282         Class<?> cmpntType = (Class<?>)((GenericArrayType)actualType).getGenericComponentType();
1283         return Array.newInstance(cmpntType, 0).getClass();
1284
1285      } else if (actualType instanceof TypeVariable) {
1286         TypeVariable<?> typeVariable = (TypeVariable<?>)actualType;
1287         List<Class<?>> nestedOuterTypes = new LinkedList<>();
1288         for (Class<?> ec = oc.getEnclosingClass(); ec != null; ec = ec.getEnclosingClass()) {
1289            try {
1290               Class<?> outerClass = oc.getClass();
1291               nestedOuterTypes.add(outerClass);
1292               Map<Type,Type> outerTypeMap = new HashMap<>();
1293               extractTypes(outerTypeMap, outerClass);
1294               for (Map.Entry<Type,Type> entry : outerTypeMap.entrySet()) {
1295                  Type key = entry.getKey(), value = entry.getValue();
1296                  if (key instanceof TypeVariable) {
1297                     TypeVariable<?> keyType = (TypeVariable<?>)key;
1298                     if (keyType.getName().equals(typeVariable.getName()) && isInnerClass(keyType.getGenericDeclaration(), typeVariable.getGenericDeclaration())) {
1299                        if (value instanceof Class)
1300                           return (Class<?>)value;
1301                        typeVariable = (TypeVariable<?>)entry.getValue();
1302                     }
1303                  }
1304               }
1305            } catch (Exception e) {
1306               throw new RuntimeException(e);
1307            }
1308         }
1309         throw new FormattedRuntimeException("Could not resolve type: {0}", actualType);
1310      } else {
1311         throw new FormattedRuntimeException("Invalid type found in resolveParameterType: {0}", actualType);
1312      }
1313   }
1314
1315   /**
1316    * Invokes the specified method using fuzzy-arg matching.
1317    *
1318    * <p>
1319    * Arguments will be matched to the parameters based on the parameter types.
1320    * <br>Arguments can be in any order.
1321    * <br>Extra arguments will be ignored.
1322    * <br>Missing arguments will be left <jk>null</jk>.
1323    *
1324    * <p>
1325    * Note that this only works for methods that have distinguishable argument types.
1326    * <br>It's not going to work on methods with generic argument types like <code>Object</code>
1327    *
1328    * @param m The method being called.
1329    * @param pojo
1330    *    The POJO the method is being called on.
1331    *    <br>Can be <jk>null</jk> for static methods.
1332    * @param args
1333    *    The arguments to pass to the method.
1334    * @return
1335    *    The results of the method invocation.
1336    * @throws Exception
1337    */
1338   public static Object invokeMethodFuzzy(Method m, Object pojo, Object...args) throws Exception {
1339      return m.invoke(pojo, getMatchingArgs(m.getParameterTypes(), args));
1340   }
1341
1342   /**
1343    * Invokes the specified constructor using fuzzy-arg matching.
1344    *
1345    * <p>
1346    * Arguments will be matched to the parameters based on the parameter types.
1347    * <br>Arguments can be in any order.
1348    * <br>Extra arguments will be ignored.
1349    * <br>Missing arguments will be left <jk>null</jk>.
1350    *
1351    * <p>
1352    * Note that this only works for constructors that have distinguishable argument types.
1353    * <br>It's not going to work on constructors with generic argument types like <code>Object</code>
1354    *
1355    * @param c The constructor being called.
1356    * @param args
1357    *    The arguments to pass to the constructor.
1358    * @return
1359    *    The results of the method invocation.
1360    * @throws Exception
1361    */
1362   public static <T> T invokeConstructorFuzzy(Constructor<T> c, Object...args) throws Exception {
1363      return c.newInstance(getMatchingArgs(c.getParameterTypes(), args));
1364   }
1365
1366   private static boolean isInnerClass(GenericDeclaration od, GenericDeclaration id) {
1367      if (od instanceof Class && id instanceof Class) {
1368         Class<?> oc = (Class<?>)od;
1369         Class<?> ic = (Class<?>)id;
1370         while ((ic = ic.getEnclosingClass()) != null)
1371            if (ic == oc)
1372               return true;
1373      }
1374      return false;
1375   }
1376
1377   private static void extractTypes(Map<Type,Type> typeMap, Class<?> c) {
1378      Type gs = c.getGenericSuperclass();
1379      if (gs instanceof ParameterizedType) {
1380         ParameterizedType pt = (ParameterizedType)gs;
1381         Type[] typeParameters = ((Class<?>)pt.getRawType()).getTypeParameters();
1382         Type[] actualTypeArguments = pt.getActualTypeArguments();
1383         for (int i = 0; i < typeParameters.length; i++) {
1384            if (typeMap.containsKey(actualTypeArguments[i]))
1385               actualTypeArguments[i] = typeMap.get(actualTypeArguments[i]);
1386            typeMap.put(typeParameters[i], actualTypeArguments[i]);
1387         }
1388      }
1389   }
1390
1391   /**
1392    * Finds a public method with the specified parameters.
1393    *
1394    * @param c The class to look for the method.
1395    * @param name The method name.
1396    * @param returnType
1397    *    The return type of the method.
1398    *    Can be a super type of the actual return type.
1399    *    For example, if the actual return type is <code>CharSequence</code>, then <code>Object</code> will match but
1400    *    <code>String</code> will not.
1401    * @param argTypes
1402    *    The argument types of the method.
1403    *    Can be subtypes of the actual parameter types.
1404    *    For example, if the parameter type is <code>CharSequence</code>, then <code>String</code> will match but
1405    *    <code>Object</code> will not.
1406    * @return The matched method, or <jk>null</jk> if no match was found.
1407    */
1408   public static Method findPublicMethod(Class<?> c, String name, Class<?> returnType, Class<?>...argTypes) {
1409      for (Method m : c.getMethods()) {
1410         if (isPublic(m) && hasName(m, name) && hasReturnTypeParent(m, returnType) && argsMatch(m.getParameterTypes(), argTypes))
1411            return m;
1412      }
1413      return null;
1414   }
1415
1416   /**
1417    * Finds a public constructor with the specified parameters without throwing an exception.
1418    *
1419    * @param c The class to search for a constructor.
1420    * @param fuzzyArgs
1421    *    Use fuzzy-arg matching.
1422    *    Find a constructor that best matches the specified args.
1423    * @param argTypes
1424    *    The argument types in the constructor.
1425    *    Can be subtypes of the actual constructor argument types.
1426    * @return The matching constructor, or <jk>null</jk> if constructor could not be found.
1427    */
1428   public static <T> Constructor<T> findPublicConstructor(Class<T> c, boolean fuzzyArgs, Class<?>...argTypes) {
1429      return findConstructor(c, Visibility.PUBLIC, fuzzyArgs, argTypes);
1430   }
1431
1432   /**
1433    * Finds a constructor with the specified parameters without throwing an exception.
1434    *
1435    * @param c The class to search for a constructor.
1436    * @param vis The minimum visibility.
1437    * @param fuzzyArgs
1438    *    Use fuzzy-arg matching.
1439    *    Find a constructor that best matches the specified args.
1440    * @param argTypes
1441    *    The argument types in the constructor.
1442    *    Can be subtypes of the actual constructor argument types.
1443    * @return The matching constructor, or <jk>null</jk> if constructor could not be found.
1444    */
1445   @SuppressWarnings("unchecked")
1446   public static <T> Constructor<T> findConstructor(Class<T> c, Visibility vis, boolean fuzzyArgs, Class<?>...argTypes) {
1447      ConstructorCacheEntry cce = CONSTRUCTOR_CACHE.get(c);
1448      if (cce != null && argsMatch(cce.paramTypes, argTypes) && cce.isVisible(vis))
1449         return (Constructor<T>)cce.constructor;
1450
1451      if (fuzzyArgs) {
1452         int bestCount = -1;
1453         Constructor<?> bestMatch = null;
1454         for (Constructor<?> n : c.getDeclaredConstructors()) {
1455            if (vis.isVisible(n)) {
1456               int m = fuzzyArgsMatch(n.getParameterTypes(), argTypes);
1457               if (m > bestCount) {
1458                  bestCount = m;
1459                  bestMatch = n;
1460               }
1461            }
1462         }
1463         if (bestCount >= 0)
1464            CONSTRUCTOR_CACHE.put(c, new ConstructorCacheEntry(c, bestMatch));
1465         return (Constructor<T>)bestMatch;
1466      }
1467
1468      final boolean isMemberClass = c.isMemberClass() && ! isStatic(c);
1469      for (Constructor<?> n : c.getConstructors()) {
1470         Class<?>[] paramTypes = n.getParameterTypes();
1471         if (isMemberClass)
1472            paramTypes = Arrays.copyOfRange(paramTypes, 1, paramTypes.length);
1473         if (argsMatch(paramTypes, argTypes) && vis.isVisible(n)) {
1474            CONSTRUCTOR_CACHE.put(c, new ConstructorCacheEntry(c, n));
1475            return (Constructor<T>)n;
1476         }
1477      }
1478
1479      return null;
1480   }
1481
1482
1483
1484   private static final class ConstructorCacheEntry {
1485      final Constructor<?> constructor;
1486      final Class<?>[] paramTypes;
1487
1488      ConstructorCacheEntry(Class<?> forClass, Constructor<?> constructor) {
1489         this.constructor = constructor;
1490         this.paramTypes = constructor.getParameterTypes();
1491      }
1492
1493      boolean isVisible(Visibility vis) {
1494         return vis.isVisible(constructor);
1495      }
1496   }
1497
1498   /**
1499    * Returns <jk>true</jk> if the specified argument types are valid for the specified parameter types.
1500    *
1501    * @param paramTypes The parameters types specified on a method.
1502    * @param argTypes The class types of the arguments being passed to the method.
1503    * @return <jk>true</jk> if the arguments match the parameters.
1504    */
1505   public static boolean argsMatch(Class<?>[] paramTypes, Class<?>[] argTypes) {
1506      if (paramTypes.length == argTypes.length) {
1507         for (int i = 0; i < paramTypes.length; i++)
1508            if (! isParentClass(paramTypes[i], argTypes[i]))
1509               return false;
1510         return true;
1511      }
1512      return false;
1513   }
1514
1515   /**
1516    * Returns a number representing the number of arguments that match the specified parameters.
1517    *
1518    * @param paramTypes The parameters types specified on a method.
1519    * @param argTypes The class types of the arguments being passed to the method.
1520    * @return The number of matching arguments, or <code>-1</code> a parameter was found that isn't in the list of args.
1521    */
1522   public static int fuzzyArgsMatch(Class<?>[] paramTypes, Class<?>... argTypes) {
1523      int matches = 0;
1524      outer: for (Class<?> p : paramTypes) {
1525         p = getWrapperIfPrimitive(p);
1526         for (Class<?> a : argTypes) {
1527            if (isParentClass(p, a)) {
1528               matches++;
1529               continue outer;
1530            }
1531         }
1532         return -1;
1533      }
1534      return matches;
1535   }
1536
1537   /**
1538    * Finds the public constructor that can take in the specified arguments.
1539    *
1540    * @param c The class we're trying to construct.
1541    * @param args The arguments we want to pass into the constructor.
1542    * @return
1543    *    The constructor, or <jk>null</jk> if a public constructor could not be found that takes in the specified
1544    *    arguments.
1545    */
1546   public static <T> Constructor<T> findPublicConstructor(Class<T> c, Object...args) {
1547      return findPublicConstructor(c, false, getClasses(args));
1548   }
1549
1550   /**
1551    * Finds the public constructor that can take in the specified arguments.
1552    *
1553    * @param c The class we're trying to construct.
1554    * @param args The argument types we want to pass into the constructor.
1555    * @return
1556    *    The constructor, or <jk>null</jk> if a public constructor could not be found that takes in the specified
1557    *    arguments.
1558    */
1559   public static <T> Constructor<T> findPublicConstructor(Class<T> c, Class<?>...args) {
1560      return findPublicConstructor(c, false, args);
1561   }
1562
1563   /**
1564    * Finds the public constructor that can take in the specified arguments.
1565    *
1566    * @param c The class we're trying to construct.
1567    * @param fuzzyArgs
1568    *    Use fuzzy-arg matching.
1569    *    Find a constructor that best matches the specified args.
1570    * @param args The arguments we want to pass into the constructor.
1571    * @return
1572    *    The constructor, or <jk>null</jk> if a public constructor could not be found that takes in the specified
1573    *    arguments.
1574    */
1575   public static <T> Constructor<T> findPublicConstructor(Class<T> c, boolean fuzzyArgs, Object...args) {
1576      return findPublicConstructor(c, fuzzyArgs, getClasses(args));
1577   }
1578
1579   /**
1580    * Returns the class types for the specified arguments.
1581    *
1582    * @param args The objects we're getting the classes of.
1583    * @return The classes of the arguments.
1584    */
1585   public static Class<?>[] getClasses(Object...args) {
1586      Class<?>[] pt = new Class<?>[args.length];
1587      for (int i = 0; i < args.length; i++)
1588         pt[i] = args[i] == null ? null : args[i].getClass();
1589      return pt;
1590   }
1591
1592   /**
1593    * Returns a {@link MethodInfo} bean that describes the specified method.
1594    *
1595    * @param m The method to describe.
1596    * @return The bean with information about the method.
1597    */
1598   public static MethodInfo getMethodInfo(Method m) {
1599      return new MethodInfo(m);
1600   }
1601
1602   /**
1603    * Returns {@link MethodInfo} beans that describe the specified methods.
1604    *
1605    * @param m The methods to describe.
1606    * @return The beans with information about the methods.
1607    */
1608   public static MethodInfo[] getMethodInfo(Collection<Method> m) {
1609      MethodInfo[] mi = new MethodInfo[m.size()];
1610      int i = 0;
1611      for (Method mm : m)
1612         mi[i++] = getMethodInfo(mm);
1613      return mi;
1614   }
1615
1616   /**
1617    * Simple bean that shows the name, parameter types, and return type of a method.
1618    */
1619   @SuppressWarnings("javadoc")
1620   public static class MethodInfo {
1621      public final String methodName;
1622      public final String[] parameterTypes;
1623      public final String returnType;
1624
1625      MethodInfo(Method m) {
1626         methodName = m.getName();
1627         Type[] pt = m.getGenericParameterTypes();
1628         parameterTypes = new String[pt.length];
1629         for (int i  = 0; i < pt.length; i++)
1630            parameterTypes[i] = BeanContext.DEFAULT.getClassMeta(pt[i]).toString();
1631         returnType = BeanContext.DEFAULT.getClassMeta(m.getGenericReturnType()).toString();
1632      }
1633   }
1634
1635   /**
1636    * Creates an instance of the specified class.
1637    *
1638    * @param c
1639    *    The class to cast to.
1640    * @param c2
1641    *    The class to instantiate.
1642    *    Can also be an instance of the class.
1643    * @return
1644    *    The new class instance, or <jk>null</jk> if the class was <jk>null</jk> or is abstract or an interface.
1645    * @throws
1646    *    RuntimeException if constructor could not be found or called.
1647    */
1648   public static <T> T newInstance(Class<T> c, Object c2) {
1649      return newInstanceFromOuter(null, c, c2, false);
1650   }
1651
1652   /**
1653    * Creates an instance of the specified class.
1654    *
1655    * @param c
1656    *    The class to cast to.
1657    * @param c2
1658    *    The class to instantiate.
1659    *    Can also be an instance of the class.
1660    * @param fuzzyArgs
1661    *    Use fuzzy constructor arg matching.
1662    *    <br>When <jk>true</jk>, constructor args can be in any order and extra args are ignored.
1663    *    <br>No-arg constructors are also used if no other constructors are found.
1664    * @param args
1665    *    The arguments to pass to the constructor.
1666    * @return
1667    *    The new class instance, or <jk>null</jk> if the class was <jk>null</jk> or is abstract or an interface.
1668    * @throws
1669    *    RuntimeException if constructor could not be found or called.
1670    */
1671   public static <T> T newInstance(Class<T> c, Object c2, boolean fuzzyArgs, Object...args) {
1672      return newInstanceFromOuter(null, c, c2, fuzzyArgs, args);
1673   }
1674
1675   /**
1676    * Creates an instance of the specified class from within the context of another object.
1677    *
1678    * @param outer
1679    *    The outer object.
1680    *    Can be <jk>null</jk>.
1681    * @param c
1682    *    The class to cast to.
1683    * @param c2
1684    *    The class to instantiate.
1685    *    Can also be an instance of the class.
1686    * @param fuzzyArgs
1687    *    Use fuzzy constructor arg matching.
1688    *    <br>When <jk>true</jk>, constructor args can be in any order and extra args are ignored.
1689    *    <br>No-arg constructors are also used if no other constructors are found.
1690    * @param args
1691    *    The arguments to pass to the constructor.
1692    * @return
1693    *    The new class instance, or <jk>null</jk> if the class was <jk>null</jk> or is abstract or an interface.
1694    * @throws
1695    *    RuntimeException if constructor could not be found or called.
1696    */
1697   @SuppressWarnings("unchecked")
1698   public static <T> T newInstanceFromOuter(Object outer, Class<T> c, Object c2, boolean fuzzyArgs, Object...args) {
1699      if (c2 == null)
1700         return null;
1701      if (c2 instanceof Class) {
1702         try {
1703            Class<?> c3 = (Class<?>)c2;
1704            if (c3.isInterface() || isAbstract(c3))
1705               return null;
1706
1707            // First look for an exact match.
1708            Constructor<?> con = findPublicConstructor(c3, false, args);
1709            if (con != null)
1710               return (T)con.newInstance(args);
1711
1712            // Next look for an exact match including the outer.
1713            if (outer != null) {
1714               args = new AList<>().append(outer).appendAll(args).toArray();
1715               con = findPublicConstructor(c3, false, args);
1716               if (con != null)
1717                  return (T)con.newInstance(args);
1718            }
1719
1720            // Finally use fuzzy matching.
1721            if (fuzzyArgs) {
1722               con = findPublicConstructor(c3, true, args);
1723               if (con != null)
1724                  return (T)con.newInstance(getMatchingArgs(con.getParameterTypes(), args));
1725            }
1726
1727            throw new FormattedRuntimeException("Could not instantiate class {0}/{1}.  Constructor not found.", c.getName(), c2);
1728         } catch (Exception e) {
1729            throw new FormattedRuntimeException(e, "Could not instantiate class {0}", c.getName());
1730         }
1731      } else if (isParentClass(c, c2.getClass())) {
1732         return (T)c2;
1733      } else {
1734         throw new FormattedRuntimeException("Object of type {0} found but was expecting {1}.", c2.getClass(), c.getClass());
1735      }
1736   }
1737
1738   /**
1739    * Matches arguments to a list of parameter types.
1740    *
1741    * <p>
1742    * Extra parameters are ignored.
1743    * <br>Missing parameters are left null.
1744    *
1745    * @param paramTypes The parameter types.
1746    * @param args The arguments to match to the parameter types.
1747    * @return
1748    *    An array of parameters.
1749    */
1750   public static Object[] getMatchingArgs(Class<?>[] paramTypes, Object... args) {
1751      Object[] params = new Object[paramTypes.length];
1752      for (int i = 0; i < paramTypes.length; i++) {
1753         Class<?> pt = getWrapperIfPrimitive(paramTypes[i]);
1754         for (int j = 0; j < args.length; j++) {
1755            if (isParentClass(pt, args[j].getClass())) {
1756               params[i] = args[j];
1757               break;
1758            }
1759         }
1760      }
1761      return params;
1762   }
1763
1764   /**
1765    * Returns all the fields in the specified class and all parent classes.
1766    *
1767    * <p>
1768    * Fields are ordered in either parent-to-child, or child-to-parent order, then alphabetically.
1769    *
1770    * @param c The class to get all fields on.
1771    * @param parentFirst Order them in parent-class-to-child-class order, otherwise child-class-to-parent-class order.
1772    * @return An iterable of all fields in the specified class.
1773    */
1774   @SuppressWarnings("rawtypes")
1775   public static Iterable<Field> getAllFields(final Class c, final boolean parentFirst) {
1776      return new Iterable<Field>() {
1777         @Override
1778         public Iterator<Field> iterator() {
1779            return new Iterator<Field>(){
1780               final Iterator<Class<?>> classIterator = getParentClasses(c, parentFirst, false);
1781               Field[] fields = classIterator.hasNext() ? sort(classIterator.next().getDeclaredFields()) : new Field[0];
1782               int fIndex = 0;
1783               Field next;
1784
1785               @Override
1786               public boolean hasNext() {
1787                  prime();
1788                  return next != null;
1789               }
1790
1791               private void prime() {
1792                  if (next == null) {
1793                     while (fIndex >= fields.length) {
1794                        if (classIterator.hasNext()) {
1795                           fields = sort(classIterator.next().getDeclaredFields());
1796                           fIndex = 0;
1797                        } else {
1798                           fIndex = -1;
1799                        }
1800                     }
1801                     if (fIndex != -1)
1802                        next = fields[fIndex++];
1803                  }
1804               }
1805
1806               @Override
1807               public Field next() {
1808                  prime();
1809                  Field f = next;
1810                  next = null;
1811                  return f;
1812               }
1813
1814               @Override
1815               public void remove() {
1816               }
1817            };
1818         }
1819      };
1820   }
1821
1822   /**
1823    * Returns all the methods in the specified class and all parent classes.
1824    *
1825    * <p>
1826    * Methods are ordered in either parent-to-child, or child-to-parent order, then alphabetically.
1827    *
1828    * @param c The class to get all methods on.
1829    * @param parentFirst Order them in parent-class-to-child-class order, otherwise child-class-to-parent-class order.
1830    * @return An iterable of all methods in the specified class.
1831    */
1832   @SuppressWarnings("rawtypes")
1833   public static Iterable<Method> getAllMethods(final Class c, final boolean parentFirst) {
1834      return new Iterable<Method>() {
1835         @Override
1836         public Iterator<Method> iterator() {
1837            return new Iterator<Method>(){
1838               final Iterator<Class<?>> classIterator = getParentClasses(c, parentFirst, true);
1839               Method[] methods = classIterator.hasNext() ? sort(classIterator.next().getDeclaredMethods()) : new Method[0];
1840               int mIndex = 0;
1841               Method next;
1842
1843               @Override
1844               public boolean hasNext() {
1845                  prime();
1846                  return next != null;
1847               }
1848
1849               private void prime() {
1850                  if (next == null) {
1851                     while (mIndex >= methods.length) {
1852                        if (classIterator.hasNext()) {
1853                           methods = sort(classIterator.next().getDeclaredMethods());
1854                           mIndex = 0;
1855                        } else {
1856                           mIndex = -1;
1857                        }
1858                     }
1859                     if (mIndex != -1)
1860                        next = methods[mIndex++];
1861                  }
1862               }
1863
1864               @Override
1865               public Method next() {
1866                  prime();
1867                  Method m = next;
1868                  next = null;
1869                  return m;
1870               }
1871
1872               @Override
1873               public void remove() {
1874               }
1875            };
1876         }
1877      };
1878   }
1879
1880   private static Comparator<Method> METHOD_COMPARATOR = new Comparator<Method>() {
1881
1882      @Override
1883      public int compare(Method o1, Method o2) {
1884         int i = o1.getName().compareTo(o2.getName());
1885         if (i == 0) {
1886            i = o1.getParameterTypes().length - o2.getParameterTypes().length;
1887            if (i == 0) {
1888               for (int j = 0; j < o1.getParameterTypes().length && i == 0; j++) {
1889                  i = o1.getParameterTypes()[j].getName().compareTo(o2.getParameterTypes()[j].getName());
1890               }
1891            }
1892         }
1893         return i;
1894      }
1895   };
1896
1897   /**
1898    * Sorts methods in alphabetical order.
1899    *
1900    * @param m The methods to sort.
1901    * @return The same array, but with elements sorted.
1902    */
1903   public static Method[] sort(Method[] m) {
1904      Arrays.sort(m, METHOD_COMPARATOR);
1905      return m;
1906   }
1907
1908   private static Comparator<Field> FIELD_COMPARATOR = new Comparator<Field>() {
1909
1910      @Override
1911      public int compare(Field o1, Field o2) {
1912         return o1.getName().compareTo(o2.getName());
1913      }
1914   };
1915
1916   /**
1917    * Sorts methods in alphabetical order.
1918    *
1919    * @param m The methods to sort.
1920    * @return The same array, but with elements sorted.
1921    */
1922   public static Field[] sort(Field[] m) {
1923      Arrays.sort(m, FIELD_COMPARATOR);
1924      return m;
1925   }
1926
1927   /**
1928    * Returns a list of all the parent classes of the specified class including the class itself.
1929    *
1930    * @param c The class to retrieve the parent classes.
1931    * @param parentFirst In parent-to-child order, otherwise child-to-parent.
1932    * @param includeInterfaces Include interfaces.
1933    * @return An iterator of parent classes in the class hierarchy.
1934    */
1935   public static Iterator<Class<?>> getParentClasses(final Class<?> c, boolean parentFirst, boolean includeInterfaces) {
1936      List<Class<?>> l = getParentClasses(new ArrayList<Class<?>>(), c, parentFirst, includeInterfaces);
1937      return l.iterator();
1938   }
1939
1940   private static List<Class<?>> getParentClasses(List<Class<?>> l, Class<?> c, boolean parentFirst, boolean includeInterfaces) {
1941      if (parentFirst) {
1942         if (includeInterfaces)
1943            for (Class<?> i : c.getInterfaces())
1944               l.add(i);
1945         if (c.getSuperclass() != Object.class && c.getSuperclass() != null)
1946            getParentClasses(l, c.getSuperclass(), parentFirst, includeInterfaces);
1947         l.add(c);
1948      } else {
1949         l.add(c);
1950         if (c.getSuperclass() != Object.class && c.getSuperclass() != null)
1951            getParentClasses(l, c.getSuperclass(), parentFirst, includeInterfaces);
1952         if (includeInterfaces)
1953            for (Class<?> i : c.getInterfaces())
1954               l.add(i);
1955      }
1956      return l;
1957   }
1958
1959   /**
1960    * Returns the default value for the specified primitive class.
1961    *
1962    * @param primitiveClass The primitive class to get the default value for.
1963    * @return The default value, or <jk>null</jk> if the specified class is not a primitive class.
1964    */
1965   public static Object getPrimitiveDefault(Class<?> primitiveClass) {
1966      return primitiveDefaultMap.get(primitiveClass);
1967   }
1968
1969   private static final Map<Class<?>,Object> primitiveDefaultMap = Collections.unmodifiableMap(
1970      new AMap<Class<?>,Object>()
1971         .append(Boolean.TYPE, false)
1972         .append(Character.TYPE, (char)0)
1973         .append(Short.TYPE, (short)0)
1974         .append(Integer.TYPE, 0)
1975         .append(Long.TYPE, 0l)
1976         .append(Float.TYPE, 0f)
1977         .append(Double.TYPE, 0d)
1978         .append(Byte.TYPE, (byte)0)
1979         .append(Boolean.class, false)
1980         .append(Character.class, (char)0)
1981         .append(Short.class, (short)0)
1982         .append(Integer.class, 0)
1983         .append(Long.class, 0l)
1984         .append(Float.class, 0f)
1985         .append(Double.class, 0d)
1986         .append(Byte.class, (byte)0)
1987   );
1988
1989   /**
1990    * Returns a readable representation of the specified method.
1991    *
1992    * <p>
1993    * The format of the string is <js>"full-qualified-class.method-name(parameter-simple-class-names)"</js>.
1994    *
1995    * @param m The method to stringify.
1996    * @return The stringified method.
1997    */
1998   public static String toString(Method m) {
1999      StringBuilder sb = new StringBuilder(m.getDeclaringClass().getName() + "." + m.getName() + "(");
2000      for (int i = 0; i < m.getParameterTypes().length; i++) {
2001         if (i > 0)
2002            sb.append(",");
2003         sb.append(m.getParameterTypes()[i].getSimpleName());
2004      }
2005      sb.append(")");
2006      return sb.toString();
2007   }
2008
2009   /**
2010    * Returns a readable representation of the specified field.
2011    *
2012    * <p>
2013    * The format of the string is <js>"full-qualified-class.field-name"</js>.
2014    *
2015    * @param f The field to stringify.
2016    * @return The stringified field.
2017    */
2018   public static String toString(Field f) {
2019      return f.getDeclaringClass().getName() + "." + f.getName();
2020   }
2021
2022   /**
2023    * Throws an {@link IllegalArgumentException} if the parameters on the method are not in the specified list provided.
2024    *
2025    * @param m The method to test.
2026    * @param args The valid class types (exact) for the arguments.
2027    * @throws FormattedIllegalArgumentException If any of the parameters on the method weren't in the list.
2028    */
2029   public static void assertArgsOfType(Method m, Class<?>...args) throws FormattedIllegalArgumentException {
2030      for (Class<?> c1 : m.getParameterTypes()) {
2031         boolean foundMatch = false;
2032         for (Class<?> c2 : args)
2033            if (c1 == c2)
2034               foundMatch = true;
2035         if (! foundMatch)
2036            throw new FormattedIllegalArgumentException("Invalid argument of type {0} passed in method {1}.  Only arguments of type {2} are allowed.", c1, m, args);
2037      }
2038   }
2039
2040   /**
2041    * Finds the public static "fromString" method on the specified class.
2042    *
2043    * <p>
2044    * Looks for the following method names:
2045    * <ul>
2046    *    <li><code>fromString</code>
2047    *    <li><code>fromValue</code>
2048    *    <li><code>valueOf</code>
2049    *    <li><code>parse</code>
2050    *    <li><code>parseString</code>
2051    *    <li><code>forName</code>
2052    *    <li><code>forString</code>
2053    * </ul>
2054    *
2055    * @param c The class to find the method on.
2056    * @return The static method, or <jk>null</jk> if it couldn't be found.
2057    */
2058   public static Method findPublicFromStringMethod(Class<?> c) {
2059      for (String methodName : new String[]{"create","fromString","fromValue","valueOf","parse","parseString","forName","forString"})
2060         for (Method m : c.getMethods())
2061            if (isAll(m, STATIC, PUBLIC, NOT_DEPRECATED) && hasName(m, methodName) && hasReturnType(m, c) && hasArgs(m, String.class))
2062               return m;
2063      return null;
2064   }
2065
2066   /**
2067    * Find the public static creator method on the specified class.
2068    *
2069    * @param oc The created type.
2070    * @param ic The argument type.
2071    * @param name The method name.
2072    * @return The static method, or <jk>null</jk> if it couldn't be found.
2073    */
2074   public static Method findPublicStaticCreateMethod(Class<?> oc, Class<?> ic, String name) {
2075      for (Method m : oc.getMethods())
2076         if (isAll(m, STATIC, PUBLIC, NOT_DEPRECATED) && hasName(m, name) && hasReturnType(m, oc) && hasArgs(m, ic))
2077            return m;
2078      return null;
2079   }
2080
2081   /**
2082    * Constructs a new instance of the specified class from the specified string.
2083    *
2084    * <p>
2085    * Class must be one of the following:
2086    * <ul>
2087    *    <li>Have a public constructor that takes in a single <code>String</code> argument.
2088    *    <li>Have a static <code>fromString(String)</code> (or related) method.
2089    *       <br>See {@link #findPublicFromStringMethod(Class)} for the list of possible static method names.
2090    *    <li>Be an <code>enum</code>.
2091    * </ul>
2092    *
2093    * @param c The class.
2094    * @param s The string to create the instance from.
2095    * @return A new object instance, or <jk>null</jk> if a method for converting the string to an object could not be found.
2096    */
2097   public static <T> T fromString(Class<T> c, String s) {
2098      Transform<String,T> t = TransformCache.get(String.class, c);
2099      return t == null ? null : t.transform(s);
2100   }
2101
2102   /**
2103    * Converts an object to a string.
2104    *
2105    * <p>
2106    * Normally, this is just going to call <code>toString()</code> on the object.
2107    * However, the {@link Locale} and {@link TimeZone} objects are treated special so that the returned value
2108    * works with the {@link #fromString(Class, String)} method.
2109    *
2110    * @param o The object to convert to a string.
2111    * @return The stringified object, or <jk>null</jk> if the object was <jk>null</jk>.
2112    */
2113   @SuppressWarnings({ "unchecked" })
2114   public static String toString(Object o) {
2115      if (o == null)
2116         return null;
2117      Transform<Object,String> t = (Transform<Object,String>)TransformCache.get(o.getClass(), String.class);
2118      return t == null ? o.toString() : t.transform(o);
2119   }
2120
2121   /**
2122    * Attempts to call <code>x.setAccessible(<jk>true</jk>)</code> and quietly ignores security exceptions.
2123    *
2124    * @param x The constructor.
2125    * @param ignoreExceptions Ignore {@link SecurityException SecurityExceptions} and just return <jk>false</jk> if thrown.
2126    * @return <jk>true</jk> if call was successful.
2127    */
2128   public static boolean setAccessible(Constructor<?> x, boolean ignoreExceptions) {
2129      try {
2130         if (! (x == null || x.isAccessible()))
2131            x.setAccessible(true);
2132         return true;
2133      } catch (SecurityException e) {
2134         if (ignoreExceptions)
2135            return false;
2136         throw new ClassMetaRuntimeException("Could not set accessibility to true on constructor ''{0}''", x);
2137      }
2138   }
2139
2140   /**
2141    * Attempts to call <code>x.setAccessible(<jk>true</jk>)</code> and quietly ignores security exceptions.
2142    *
2143    * @param x The method.
2144    * @param ignoreExceptions Ignore {@link SecurityException SecurityExceptions} and just return <jk>false</jk> if thrown.
2145    * @return <jk>true</jk> if call was successful.
2146    */
2147   public static boolean setAccessible(Method x, boolean ignoreExceptions) {
2148      try {
2149         if (! (x == null || x.isAccessible()))
2150            x.setAccessible(true);
2151         return true;
2152      } catch (SecurityException e) {
2153         if (ignoreExceptions)
2154            return false;
2155         throw new ClassMetaRuntimeException("Could not set accessibility to true on method ''{0}''", x);
2156      }
2157   }
2158
2159   /**
2160    * Attempts to call <code>x.setAccessible(<jk>true</jk>)</code> and quietly ignores security exceptions.
2161    *
2162    * @param x The field.
2163    * @param ignoreExceptions Ignore {@link SecurityException SecurityExceptions} and just return <jk>false</jk> if thrown.
2164    * @return <jk>true</jk> if call was successful.
2165    */
2166   public static boolean setAccessible(Field x, boolean ignoreExceptions) {
2167      try {
2168         if (! (x == null || x.isAccessible()))
2169            x.setAccessible(true);
2170         return true;
2171      } catch (SecurityException e) {
2172         if (ignoreExceptions)
2173            return false;
2174         throw new ClassMetaRuntimeException("Could not set accessibility to true on field ''{0}''", x);
2175      }
2176   }
2177
2178   /**
2179    * Returns the simple name of a class.
2180    *
2181    * <p>
2182    * Similar to {@link Class#getSimpleName()}, but includes the simple name of an enclosing or declaring class.
2183    *
2184    * @param c The class to get the simple name on.
2185    * @return The simple name of a class.
2186    */
2187   public static String getSimpleName(Class<?> c) {
2188      if (c.isLocalClass())
2189         return getSimpleName(c.getEnclosingClass()) + '.' + c.getSimpleName();
2190      if (c.isMemberClass())
2191         return getSimpleName(c.getDeclaringClass()) + '.' + c.getSimpleName();
2192      return c.getSimpleName();
2193   }
2194
2195   /**
2196    * Returns the simple name of a class.
2197    *
2198    * <p>
2199    * Similar to {@link Class#getSimpleName()}, but includes the simple name of an enclosing or declaring class.
2200    *
2201    * @param t The class to get the simple name on.
2202    * @return The simple name of a class.
2203    */
2204   public static String getSimpleName(Type t) {
2205      if (t instanceof Class)
2206         return getSimpleName((Class<?>)t);
2207      if (t instanceof ParameterizedType) {
2208         StringBuilder sb = new StringBuilder();
2209         ParameterizedType pt = (ParameterizedType)t;
2210         sb.append(getSimpleName(pt.getRawType()));
2211         sb.append("<");
2212         boolean first = true;
2213         for (Type t2 : pt.getActualTypeArguments()) {
2214            if (! first)
2215               sb.append(',');
2216            first = false;
2217            sb.append(getSimpleName(t2));
2218         }
2219         sb.append(">");
2220         return sb.toString();
2221      }
2222      return null;
2223   }
2224
2225   /**
2226    * Returns <jk>true</jk> if the {@link #getAnnotation(Class, Method, int)} returns a value.
2227    *
2228    * @param a The annotation to check for.
2229    * @param m The method containing the parameter to check.
2230    * @param index The parameter index.
2231    * @return <jk>true</jk> if the {@link #getAnnotation(Class, Method, int)} returns a value.
2232    */
2233   public static boolean hasAnnotation(Class<? extends Annotation> a, Method m, int index) {
2234      return getAnnotation(a, m, index) != null;
2235   }
2236
2237   /**
2238    * Returns <jk>true</jk> if the {@link #getAnnotation(Class, Method)} returns a value.
2239    *
2240    * @param a The annotation to check for.
2241    * @param m The method to check.
2242    * @return <jk>true</jk> if the {@link #getAnnotation(Class, Method)} returns a value.
2243    */
2244   public static boolean hasAnnotation(Class<? extends Annotation> a, Method m) {
2245      return getAnnotation(a, m) != null;
2246   }
2247
2248   /**
2249    * Returns <jk>true</jk> if the {@link #getAnnotation(Class, Type)} returns a value.
2250    *
2251    * @param a The annotation to check for.
2252    * @param t The class to check.
2253    * @return <jk>true</jk> if the {@link #getAnnotation(Class, Type)} returns a value.
2254    */
2255   public static boolean hasAnnotation(Class<? extends Annotation> a, Type t) {
2256      return getAnnotation(a, t) != null;
2257   }
2258
2259   /**
2260    * Returns the specified annotation if it exists on the specified parameter or parameter type class.
2261    *
2262    * @param a The annotation to check for.
2263    * @param m The method containing the parameter to check.
2264    * @param index The parameter index.
2265    * @return <jk>true</jk> if the {@link #getAnnotation(Class, Method, int)} returns a value.
2266    */
2267   @SuppressWarnings("unchecked")
2268   public static <T extends Annotation> T getAnnotation(Class<T> a, Method m, int index) {
2269      for (Annotation a2 :  m.getParameterAnnotations()[index])
2270         if (a.isInstance(a2))
2271            return (T)a2;
2272      Type t = m.getGenericParameterTypes()[index];
2273      if (Value.isType(t))
2274         return getAnnotation(a, Value.getParameterType(t));
2275      return getAnnotation(a, t);
2276   }
2277
2278   /**
2279    * Returns all annotations defined on the specified parameter and parameter type.
2280    *
2281    * <p>
2282    * Annotations are ordered parameter first, then class, then superclasses.
2283    *
2284    * @param a The annotation to look for.
2285    * @param m The method containing the parameter.
2286    * @param index The parameter index.
2287    * @return All instances of the annotation with the
2288    */
2289   @SuppressWarnings("unchecked")
2290   public static <T extends Annotation> List<T> getAnnotations(Class<T> a, Method m, int index) {
2291      List<T> l = new ArrayList<>();
2292      for (Annotation a2 :  m.getParameterAnnotations()[index])
2293         if (a.isInstance(a2))
2294            l.add((T)a2);
2295      Type t = m.getGenericParameterTypes()[index];
2296      if (Value.isType(t))
2297         appendAnnotations(a, Value.getParameterType(t), l);
2298      else
2299         appendAnnotations(a, t, l);
2300      return l;
2301   }
2302
2303   /**
2304    * Returns all annotations defined on the specified parameter and parameter type.
2305    *
2306    * <p>
2307    * Annotations are ordered parameter superclasses first, then class, then parameter.
2308    *
2309    * @param a The annotation to look for.
2310    * @param m The method containing the parameter.
2311    * @param index The parameter index.
2312    * @return All instances of the annotation with the
2313    */
2314   public static <T extends Annotation> List<T> getAnnotationsParentFirst(Class<T> a, Method m, int index) {
2315      List<T> l = getAnnotations(a, m, index);
2316      Collections.reverse(l);
2317      return l;
2318   }
2319
2320   /**
2321    * Returns all annotations defined on the specified method and return type.
2322    *
2323    * <p>
2324    * Annotations are ordered method first, then return class, then return superclasses.
2325    *
2326    * @param a The annotation to look for.
2327    * @param m The method being inspected.
2328    * @return All instances of the annotation with the
2329    */
2330   @SuppressWarnings("unchecked")
2331   public static <T extends Annotation> List<T> getAnnotations(Class<T> a, Method m) {
2332      List<T> l = new ArrayList<>();
2333      for (Method m2 : findMatchingMethods(m))
2334         for (Annotation a2 :  m2.getAnnotations())
2335            if (a.isInstance(a2))
2336               l.add((T)a2);
2337      Type t = m.getGenericReturnType();
2338      if (Value.isType(t))
2339         appendAnnotations(a, Value.getParameterType(t), l);
2340      else
2341         appendAnnotations(a, t, l);
2342      return l;
2343   }
2344
2345   /**
2346    * Returns all annotations defined on the specified method and return type.
2347    *
2348    * <p>
2349    * Annotations are ordered return superclass first, then return class, then method.
2350    *
2351    * @param a The annotation to look for.
2352    * @param m The method being inspected.
2353    * @return All instances of the annotation with the
2354    */
2355   public static <T extends Annotation> List<T> getAnnotationsParentFirst(Class<T> a, Method m) {
2356      List<T> l = getAnnotations(a, m);
2357      Collections.reverse(l);
2358      return l;
2359   }
2360
2361   /**
2362    * Returns the specified annotation if it exists on the specified method or return type class.
2363    *
2364    * @param a The annotation to check for.
2365    * @param m The method to check.
2366    * @return <jk>true</jk> if the {@link #getAnnotation(Class, Method, int)} returns a value.
2367    */
2368   @SuppressWarnings("unchecked")
2369   public static <T extends Annotation> T getAnnotation(Class<T> a, Method m) {
2370      for (Annotation a2 :  m.getAnnotations())
2371         if (a.isInstance(a2))
2372            return (T)a2;
2373      return getAnnotation(a, m.getGenericReturnType());
2374   }
2375
2376   /**
2377    * Similar to {@link Class#getAnnotation(Class)} except also searches annotations on interfaces.
2378    *
2379    * @param <T> The annotation class type.
2380    * @param a The annotation class.
2381    * @param t The annotated class.
2382    * @return The annotation, or <jk>null</jk> if not found.
2383    */
2384   public static <T extends Annotation> T getAnnotation(Class<T> a, Type t) {
2385      Class<?> c = toClass(t);
2386      if (c != null) {
2387         T t2 = getDeclaredAnnotation(a, c);
2388         if (t2 != null)
2389            return t2;
2390
2391         t2 = getAnnotation(a, c.getSuperclass());
2392         if (t2 != null)
2393            return t2;
2394
2395         for (Class<?> c2 : c.getInterfaces()) {
2396            t2 = getAnnotation(a, c2);
2397            if (t2 != null)
2398               return t2;
2399         }
2400      }
2401      return null;
2402   }
2403
2404   /**
2405    * Returns the specified annotation only if it's been declared on the specified class.
2406    *
2407    * <p>
2408    * More efficient than calling {@link Class#getAnnotation(Class)} since it doesn't recursively look for the class
2409    * up the parent chain.
2410    *
2411    * @param <T> The annotation class type.
2412    * @param a The annotation class.
2413    * @param t The annotated class.
2414    * @return The annotation, or <jk>null</jk> if not found.
2415    */
2416   @SuppressWarnings("unchecked")
2417   public static <T extends Annotation> T getDeclaredAnnotation(Class<T> a, Type t) {
2418      Class<?> c = toClass(t);
2419      if (c != null)
2420         for (Annotation a2 : c.getDeclaredAnnotations())
2421            if (a2.annotationType() == a)
2422               return (T)a2;
2423      return null;
2424   }
2425
2426   /**
2427    * Returns all instances of the specified annotation on the specified class.
2428    *
2429    * <p>
2430    * Searches all superclasses and superinterfaces.
2431    * Results are ordered child-to-parent.
2432    *
2433    * @param <T> The annotation class type.
2434    * @param a The annotation class type.
2435    * @param t The class being searched.
2436    * @return The found matches, or an empty array if annotation was not found.
2437    */
2438   public static <T extends Annotation> List<T> getAnnotations(Class<T> a, Type t) {
2439      List<T> l = new LinkedList<>();
2440      appendAnnotations(a, t, l);
2441      return l;
2442   }
2443
2444   /**
2445    * Same as {@link #getAnnotations(Class, Type)} but returns the list in parent-to-child order.
2446    *
2447    * @param a The annotation class type.
2448    * @param t The class being searched.
2449    * @return The found matches, or an empty array if annotation was not found.
2450    */
2451   public static <T extends Annotation> List<T> getAnnotationsParentFirst(Class<T> a, Type t) {
2452      List<T> l = getAnnotations(a, t);
2453      Collections.reverse(l);
2454      return l;
2455   }
2456
2457   /**
2458    * Same as {@link #getAnnotations(Class, Type)} except returns the annotations as a map with the keys being the
2459    * class on which the annotation was found.
2460    *
2461    * <p>
2462    * Results are ordered child-to-parent.
2463    *
2464    * @param <T> The annotation class type.
2465    * @param a The annotation class type.
2466    * @param t The class being searched.
2467    * @return The found matches, or an empty map if annotation was not found.
2468    */
2469   public static <T extends Annotation> LinkedHashMap<Class<?>,T> getAnnotationsMap(Class<T> a, Type t) {
2470      LinkedHashMap<Class<?>,T> m = new LinkedHashMap<>();
2471      findAnnotationsMap(a, t, m);
2472      return m;
2473   }
2474
2475   /**
2476    * Same as {@link #getAnnotationsMap(Class, Type)} except returns results in parent-to-child order.
2477    *
2478    * @param <T> The annotation class type.
2479    * @param a The annotation class type.
2480    * @param t The class being searched.
2481    * @return The found matches, or an empty map if annotation was not found.
2482    */
2483   public static <T extends Annotation> LinkedHashMap<Class<?>,T> getAnnotationsMapParentFirst(Class<T> a, Type t) {
2484      return CollectionUtils.reverse(getAnnotationsMap(a, t));
2485   }
2486
2487   private static <T extends Annotation> void findAnnotationsMap(Class<T> a, Type t, Map<Class<?>,T> m) {
2488      Class<?> c = toClass(t);
2489      if (c != null) {
2490
2491         T t2 = getDeclaredAnnotation(a, c);
2492         if (t2 != null)
2493            m.put(c, t2);
2494
2495         findAnnotationsMap(a, c.getSuperclass(), m);
2496
2497         for (Class<?> c2 : c.getInterfaces())
2498            findAnnotationsMap(a, c2, m);
2499      }
2500   }
2501
2502   /**
2503    * Finds and appends the specified annotation on the specified class and superclasses/interfaces to the specified
2504    * list.
2505    *
2506    * @param a The annotation.
2507    * @param t The class.
2508    * @param l The list of annotations.
2509    */
2510   public static <T extends Annotation> void appendAnnotations(Class<T> a, Type t, List<T> l) {
2511      Class<?> c = toClass(t);
2512      if (c != null) {
2513         addIfNotNull(l, getDeclaredAnnotation(a, c));
2514
2515         if (c.getPackage() != null)
2516            addIfNotNull(l, c.getPackage().getAnnotation(a));
2517
2518         appendAnnotations(a, c.getSuperclass(), l);
2519
2520         for (Class<?> c2 : c.getInterfaces())
2521            appendAnnotations(a, c2, l);
2522      }
2523   }
2524
2525   /**
2526    * Returns the specified type as a <code>Class</code>.
2527    *
2528    * <p>
2529    * If it's already a <code>Class</code>, it just does a cast.
2530    * <br>If it's a <code>ParameterizedType</code>, it returns the raw type.
2531    *
2532    * @param t The type to convert.
2533    * @return The type converted to a <code>Class</code>, or <jk>null</jk> if it could not be converted.
2534    */
2535   public static Class<?> toClass(Type t) {
2536      if (t instanceof Class)
2537         return (Class<?>)t;
2538      if (t instanceof ParameterizedType) {
2539         ParameterizedType pt = (ParameterizedType)t;
2540         // The raw type should always be a class (right?)
2541         return (Class<?>)pt.getRawType();
2542      }
2543      return null;
2544   }
2545
2546   /**
2547    * Similar to {@link Class#getResourceAsStream(String)} except looks up the parent hierarchy for the existence of
2548    * the specified resource.
2549    *
2550    * @param c The class to return the resource on.
2551    * @param name The resource name.
2552    * @return An input stream on the specified resource, or <jk>null</jk> if the resource could not be found.
2553    */
2554   public static InputStream getResource(Class<?> c, String name) {
2555      if (name == null)
2556         return null;
2557      while (c != null) {
2558         InputStream is = c.getResourceAsStream(name);
2559         if (is != null)
2560            return is;
2561         c = c.getSuperclass();
2562      }
2563      return null;
2564   }
2565}