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 java.lang.annotation.*;
016import java.lang.reflect.*;
017import java.util.*;
018import java.util.concurrent.*;
019
020import org.apache.juneau.*;
021import org.apache.juneau.utils.*;
022
023/**
024 * Class-related utility methods.
025 */
026public final class ClassUtils {
027
028   private static final Map<Class<?>,ConstructorCacheEntry> CONSTRUCTOR_CACHE = new ConcurrentHashMap<>();
029   private static final Map<Class<?>,Stringify<?>> STRINGIFY_CACHE = new ConcurrentHashMap<>();
030   
031   // Special cases.
032   static {
033      
034      // TimeZone doesn't follow any standard conventions.
035      STRINGIFY_CACHE.put(TimeZone.class, new Stringify<TimeZone>(TimeZone.class){
036         @Override 
037         public TimeZone fromString(String s) {
038            return TimeZone.getTimeZone(s);
039         }
040         @Override 
041         public String toString(TimeZone tz) {
042            return tz.getID();
043         }
044      });
045      
046      // Locale(String) doesn't work on strings like "ja_JP".
047      STRINGIFY_CACHE.put(Locale.class, new Stringify<Locale>(Locale.class){
048         @Override 
049         public Locale fromString(String s) {
050            return Locale.forLanguageTag(s.replace('_', '-'));
051         }
052      });
053   }
054   
055   /**
056    * Given the specified list of objects, return readable names for the class types of the objects.
057    * 
058    * @param o The objects.
059    * @return An array of readable class type strings.
060    */
061   public static ObjectList getReadableClassNames(Object[] o) {
062      ObjectList l = new ObjectList();
063      for (int i = 0; i < o.length; i++)
064         l.add(o[i] == null ? "null" : getReadableClassName(o[i].getClass()));
065      return l;
066   }
067
068   /**
069    * Shortcut for calling <code><jsm>getReadableClassName</jsm>(c.getName())</code>
070    * 
071    * @param c The class.
072    * @return A readable class type name, or <jk>null</jk> if parameter is <jk>null</jk>.
073    */
074   public static String getReadableClassName(Class<?> c) {
075      if (c == null)
076         return null;
077      return getReadableClassName(c.getName());
078   }
079
080   /**
081    * Shortcut for calling <code><jsm>getReadableClassName</jsm>(c.getClass().getName())</code>
082    * 
083    * @param o The object whose class we want to render.
084    * @return A readable class type name, or <jk>null</jk> if parameter is <jk>null</jk>.
085    */
086   public static String getReadableClassNameForObject(Object o) {
087      if (o == null)
088         return null;
089      return getReadableClassName(o.getClass().getName());
090   }
091
092   /**
093    * Converts the specified class name to a readable form when class name is a special construct like <js>"[[Z"</js>.
094    * 
095    * <h5 class='section'>Example:</h5>
096    * <p class='bcode'>
097    *    <jsm>getReadableClassName</jsm>(<js>"java.lang.Object"</js>);  <jc>// Returns "java.lang.Object"</jc>
098    *    <jsm>getReadableClassName</jsm>(<js>"boolean"</js>);  <jc>// Returns "boolean"</jc>
099    *    <jsm>getReadableClassName</jsm>(<js>"[Z"</js>);  <jc>// Returns "boolean[]"</jc>
100    *    <jsm>getReadableClassName</jsm>(<js>"[[Z"</js>);  <jc>// Returns "boolean[][]"</jc>
101    *    <jsm>getReadableClassName</jsm>(<js>"[Ljava.lang.Object;"</js>);  <jc>// Returns "java.lang.Object[]"</jc>
102    *    <jsm>getReadableClassName</jsm>(<jk>null</jk>);  <jc>// Returns null</jc>
103    * </p>
104    * 
105    * @param className The class name.
106    * @return A readable class type name, or <jk>null</jk> if parameter is <jk>null</jk>.
107    */
108   public static String getReadableClassName(String className) {
109      if (className == null)
110         return null;
111      if (! StringUtils.startsWith(className, '['))
112         return className;
113      int depth = 0;
114      for (int i = 0; i < className.length(); i++) {
115         if (className.charAt(i) == '[')
116            depth++;
117         else
118            break;
119      }
120      char type = className.charAt(depth);
121      String c;
122      switch (type) {
123         case 'Z': c = "boolean"; break;
124         case 'B': c = "byte"; break;
125         case 'C': c = "char"; break;
126         case 'D': c = "double"; break;
127         case 'F': c = "float"; break;
128         case 'I': c = "int"; break;
129         case 'J': c = "long"; break;
130         case 'S': c = "short"; break;
131         default: c = className.substring(depth+1, className.length()-1);
132      }
133      StringBuilder sb = new StringBuilder(c.length() + 2*depth).append(c);
134      for (int i = 0; i < depth; i++)
135         sb.append("[]");
136      return sb.toString();
137   }
138
139   /**
140    * Converts the string generated by {@link #getReadableClassName(Class)} back into a {@link Class}.
141    * 
142    * <p>
143    * Generics are stripped from the string since they cannot be converted to a class.
144    * 
145    * @param cl The classloader to use to load the class.
146    * @param name The readable class name.
147    * @return The class object.
148    * @throws ClassNotFoundException
149    */
150   public static Class<?> getClassFromReadableName(ClassLoader cl, String name) throws ClassNotFoundException {
151      return cl.loadClass(name);
152   }
153
154   /**
155    * Returns <jk>true</jk> if <code>parent</code> is a parent class of <code>child</code>.
156    * 
157    * @param parent The parent class.
158    * @param child The child class.
159    * @param strict If <jk>true</jk> returns <jk>false</jk> if the classes are the same.
160    * @return <jk>true</jk> if <code>parent</code> is a parent class of <code>child</code>.
161    */
162   public static boolean isParentClass(Class<?> parent, Class<?> child, boolean strict) {
163      return parent.isAssignableFrom(child) && ((!strict) || ! parent.equals(child));
164   }
165
166   /**
167    * Returns <jk>true</jk> if <code>parent</code> is a parent class or the same as <code>child</code>.
168    * 
169    * @param parent The parent class.
170    * @param child The child class.
171    * @return <jk>true</jk> if <code>parent</code> is a parent class or the same as <code>child</code>.
172    */
173   public static boolean isParentClass(Class<?> parent, Class<?> child) {
174      return isParentClass(parent, child, false);
175   }
176
177   /**
178    * Returns <jk>true</jk> if <code>parent</code> is a parent class or the same as <code>child</code>.
179    * 
180    * @param parent The parent class.
181    * @param child The child class.
182    * @return <jk>true</jk> if <code>parent</code> is a parent class or the same as <code>child</code>.
183    */
184   public static boolean isParentClass(Class<?> parent, Type child) {
185      if (child instanceof Class)
186         return isParentClass(parent, (Class<?>)child);
187      return false;
188   }
189
190   /**
191    * Returns the signature of the specified method.
192    * 
193    * <p>
194    * For no-arg methods, the signature will be a simple string such as <js>"toString"</js>.
195    * For methods with one or more args, the arguments will be fully-qualified class names (e.g.
196    * <js>"append(java.util.StringBuilder,boolean)"</js>)
197    * 
198    * @param m The methods to get the signature on.
199    * @return The methods signature.
200    */
201   public static String getMethodSignature(Method m) {
202      StringBuilder sb = new StringBuilder(m.getName());
203      Class<?>[] pt = m.getParameterTypes();
204      if (pt.length > 0) {
205         sb.append('(');
206         for (int i = 0; i < pt.length; i++) {
207            if (i > 0)
208               sb.append(',');
209            sb.append(getReadableClassName(pt[i]));
210         }
211         sb.append(')');
212      }
213      return sb.toString();
214   }
215
216   private static final Map<Class<?>, Class<?>>
217      pmap1 = new HashMap<>(),
218      pmap2 = new HashMap<>();
219   static {
220      pmap1.put(boolean.class, Boolean.class);
221      pmap1.put(byte.class, Byte.class);
222      pmap1.put(short.class, Short.class);
223      pmap1.put(char.class, Character.class);
224      pmap1.put(int.class, Integer.class);
225      pmap1.put(long.class, Long.class);
226      pmap1.put(float.class, Float.class);
227      pmap1.put(double.class, Double.class);
228      pmap2.put(Boolean.class, boolean.class);
229      pmap2.put(Byte.class, byte.class);
230      pmap2.put(Short.class, short.class);
231      pmap2.put(Character.class, char.class);
232      pmap2.put(Integer.class, int.class);
233      pmap2.put(Long.class, long.class);
234      pmap2.put(Float.class, float.class);
235      pmap2.put(Double.class, double.class);
236   }
237
238   /**
239    * If the specified class is a primitive (e.g. <code><jk>int</jk>.<jk>class</jk></code>) returns it's wrapper class
240    * (e.g. <code>Integer.<jk>class</jk></code>).
241    * 
242    * @param c The class.
243    * @return The wrapper class, or <jk>null</jk> if class is not a primitive.
244    */
245   public static Class<?> getPrimitiveWrapper(Class<?> c) {
246      return pmap1.get(c);
247   }
248
249   /**
250    * If the specified class is a primitive wrapper (e.g. <code><jk>Integer</jk>.<jk>class</jk></code>) returns it's
251    * primitive class (e.g. <code>int.<jk>class</jk></code>).
252    * 
253    * @param c The class.
254    * @return The primitive class, or <jk>null</jk> if class is not a primitive wrapper.
255    */
256   public static Class<?> getPrimitiveForWrapper(Class<?> c) {
257      return pmap2.get(c);
258   }
259
260   /**
261    * If the specified class is a primitive (e.g. <code><jk>int</jk>.<jk>class</jk></code>) returns it's wrapper class
262    * (e.g. <code>Integer.<jk>class</jk></code>).
263    * 
264    * @param c The class.
265    * @return The wrapper class if it's primitive, or the same class if class is not a primitive.
266    */
267   public static Class<?> getWrapperIfPrimitive(Class<?> c) {
268      if (! c.isPrimitive())
269         return c;
270      return pmap1.get(c);
271   }
272
273   /**
274    * Returns <jk>true</jk> if the specified class has the {@link Deprecated @Deprecated} annotation on it.
275    * 
276    * @param c The class.
277    * @return <jk>true</jk> if the specified class has the {@link Deprecated @Deprecated} annotation on it.
278    */
279   public static boolean isNotDeprecated(Class<?> c) {
280      return ! c.isAnnotationPresent(Deprecated.class);
281   }
282
283   /**
284    * Returns <jk>true</jk> if the specified method has the {@link Deprecated @Deprecated} annotation on it.
285    * 
286    * @param m The method.
287    * @return <jk>true</jk> if the specified method has the {@link Deprecated @Deprecated} annotation on it.
288    */
289   public static boolean isNotDeprecated(Method m) {
290      return ! m.isAnnotationPresent(Deprecated.class);
291
292   }
293
294   /**
295    * Returns <jk>true</jk> if the specified constructor has the {@link Deprecated @Deprecated} annotation on it.
296    * 
297    * @param c The constructor.
298    * @return <jk>true</jk> if the specified constructor has the {@link Deprecated @Deprecated} annotation on it.
299    */
300   public static boolean isNotDeprecated(Constructor<?> c) {
301      return ! c.isAnnotationPresent(Deprecated.class);
302   }
303
304   /**
305    * Returns <jk>true</jk> if the specified class is public.
306    * 
307    * @param c The class.
308    * @return <jk>true</jk> if the specified class is public.
309    */
310   public static boolean isPublic(Class<?> c) {
311      return Modifier.isPublic(c.getModifiers());
312   }
313
314   /**
315    * Returns <jk>true</jk> if the specified class is public.
316    * 
317    * @param c The class.
318    * @return <jk>true</jk> if the specified class is public.
319    */
320   public static boolean isStatic(Class<?> c) {
321      return Modifier.isStatic(c.getModifiers());
322   }
323
324   /**
325    * Returns <jk>true</jk> if the specified class is abstract.
326    * 
327    * @param c The class.
328    * @return <jk>true</jk> if the specified class is abstract.
329    */
330   public static boolean isAbstract(Class<?> c) {
331      return Modifier.isAbstract(c.getModifiers());
332   }
333
334   /**
335    * Returns <jk>true</jk> if the specified method is public.
336    * 
337    * @param m The method.
338    * @return <jk>true</jk> if the specified method is public.
339    */
340   public static boolean isPublic(Method m) {
341      return Modifier.isPublic(m.getModifiers());
342   }
343
344   /**
345    * Returns <jk>true</jk> if the specified method is static.
346    * 
347    * @param m The method.
348    * @return <jk>true</jk> if the specified method is static.
349    */
350   public static boolean isStatic(Method m) {
351      return Modifier.isStatic(m.getModifiers());
352   }
353
354   /**
355    * Returns <jk>true</jk> if the specified constructor is public.
356    * 
357    * @param c The constructor.
358    * @return <jk>true</jk> if the specified constructor is public.
359    */
360   public static boolean isPublic(Constructor<?> c) {
361      return Modifier.isPublic(c.getModifiers());
362   }
363
364   /**
365    * Returns the specified annotation on the specified method.
366    * 
367    * <p>
368    * Similar to {@link Method#getAnnotation(Class)}, but searches up the parent hierarchy for the annotation
369    * defined on parent classes and interfaces.
370    * 
371    * <p>
372    * Normally, annotations defined on methods of parent classes and interfaces are not inherited by the child methods.
373    * This utility method gets around that limitation by searching the class hierarchy for the "same" method
374    * (i.e. the same name and arguments).
375    * 
376    * @param a The annotation to search for.
377    * @param m The method to search.
378    * @return The annotation, or <jk>null</jk> if it wasn't found.
379    */
380   public static <T extends Annotation> T getMethodAnnotation(Class<T> a, Method m) {
381      return getMethodAnnotation(a, m.getDeclaringClass(), m);
382   }
383
384   /**
385    * Returns the specified annotation on the specified method.
386    * 
387    * <p>
388    * Similar to {@link Method#getAnnotation(Class)}, but searches up the parent hierarchy for the annotation defined
389    * on parent classes and interfaces.
390    * 
391    * <p>
392    * Normally, annotations defined on methods of parent classes and interfaces are not inherited by the child methods.
393    * This utility method gets around that limitation by searching the class hierarchy for the "same" method
394    * (i.e. the same name and arguments).
395    * 
396    * @param a The annotation to search for.
397    * @param c
398    *    The child class to start searching from.
399    *    Note that it can be a descendant class of the actual declaring class of the method passed in.
400    *    This allows you to find annotations on methods overridden by the method passed in.
401    * @param method The method to search.
402    * @return The annotation, or <jk>null</jk> if it wasn't found.
403    */
404   public static <T extends Annotation> T getMethodAnnotation(Class<T> a, Class<?> c, Method method) {
405      for (Method m : c.getDeclaredMethods()) {
406         if (isSameMethod(method, m)) {
407            T t = m.getAnnotation(a);
408            if (t != null)
409               return t;
410         }
411      }
412      Class<?> pc = c.getSuperclass();
413      if (pc != null) {
414         T t = getMethodAnnotation(a, pc, method);
415         if (t != null)
416            return t;
417      }
418      for (Class<?> ic : c.getInterfaces()) {
419         T t = getMethodAnnotation(a, ic, method);
420         if (t != null)
421            return t;
422      }
423      return null;
424   }
425
426   private static boolean isSameMethod(Method m1, Method m2) {
427      return m1.getName().equals(m2.getName()) && Arrays.equals(m1.getParameterTypes(), m2.getParameterTypes());
428   }
429
430   /**
431    * Locates the no-arg constructor for the specified class.
432    * 
433    * <p>
434    * Constructor must match the visibility requirements specified by parameter 'v'.
435    * If class is abstract, always returns <jk>null</jk>.
436    * Note that this also returns the 1-arg constructor for non-static member classes.
437    * 
438    * @param c The class from which to locate the no-arg constructor.
439    * @param v The minimum visibility.
440    * @return The constructor, or <jk>null</jk> if no no-arg constructor exists with the required visibility.
441    */
442   @SuppressWarnings({"rawtypes","unchecked"})
443   public static final <T> Constructor<T> findNoArgConstructor(Class<T> c, Visibility v) {
444      int mod = c.getModifiers();
445      if (Modifier.isAbstract(mod))
446         return null;
447      boolean isMemberClass = c.isMemberClass() && ! isStatic(c);
448      for (Constructor cc : c.getConstructors()) {
449         mod = cc.getModifiers();
450         if (cc.getParameterTypes().length == (isMemberClass ? 1 : 0) && v.isVisible(mod) && isNotDeprecated(cc))
451            return v.transform(cc);
452      }
453      return null;
454   }
455
456   /**
457    * Finds the real parameter type of the specified class.
458    * 
459    * @param c The class containing the parameters (e.g. PojoSwap&lt;T,S&gt;)
460    * @param index The zero-based index of the parameter to resolve.
461    * @param oc The class we're trying to resolve the parameter type for.
462    * @return The resolved real class.
463    */
464   public static Class<?> resolveParameterType(Class<?> c, int index, Class<?> oc) {
465
466      // We need to make up a mapping of type names.
467      Map<Type,Type> typeMap = new HashMap<>();
468      while (c != oc.getSuperclass()) {
469         extractTypes(typeMap, oc);
470         oc = oc.getSuperclass();
471      }
472
473      Type gsc = oc.getGenericSuperclass();
474      
475      // Not actually a parameterized type.
476      if (! (gsc instanceof ParameterizedType))
477         return Object.class;
478
479      ParameterizedType opt = (ParameterizedType)gsc;
480      Type actualType = opt.getActualTypeArguments()[index];
481
482      if (typeMap.containsKey(actualType))
483         actualType = typeMap.get(actualType);
484
485      if (actualType instanceof Class) {
486         return (Class<?>)actualType;
487
488      } else if (actualType instanceof GenericArrayType) {
489         Class<?> cmpntType = (Class<?>)((GenericArrayType)actualType).getGenericComponentType();
490         return Array.newInstance(cmpntType, 0).getClass();
491
492      } else if (actualType instanceof TypeVariable) {
493         TypeVariable<?> typeVariable = (TypeVariable<?>)actualType;
494         List<Class<?>> nestedOuterTypes = new LinkedList<>();
495         for (Class<?> ec = oc.getEnclosingClass(); ec != null; ec = ec.getEnclosingClass()) {
496            try {
497               Class<?> outerClass = oc.getClass();
498               nestedOuterTypes.add(outerClass);
499               Map<Type,Type> outerTypeMap = new HashMap<>();
500               extractTypes(outerTypeMap, outerClass);
501               for (Map.Entry<Type,Type> entry : outerTypeMap.entrySet()) {
502                  Type key = entry.getKey(), value = entry.getValue();
503                  if (key instanceof TypeVariable) {
504                     TypeVariable<?> keyType = (TypeVariable<?>)key;
505                     if (keyType.getName().equals(typeVariable.getName()) && isInnerClass(keyType.getGenericDeclaration(), typeVariable.getGenericDeclaration())) {
506                        if (value instanceof Class)
507                           return (Class<?>)value;
508                        typeVariable = (TypeVariable<?>)entry.getValue();
509                     }
510                  }
511               }
512            } catch (Exception e) {
513               throw new RuntimeException(e);
514            }
515         }
516         throw new FormattedRuntimeException("Could not resolve type: {0}", actualType);
517      } else {
518         throw new FormattedRuntimeException("Invalid type found in resolveParameterType: {0}", actualType);
519      }
520   }
521
522   private static boolean isInnerClass(GenericDeclaration od, GenericDeclaration id) {
523      if (od instanceof Class && id instanceof Class) {
524         Class<?> oc = (Class<?>)od;
525         Class<?> ic = (Class<?>)id;
526         while ((ic = ic.getEnclosingClass()) != null)
527            if (ic == oc)
528               return true;
529      }
530      return false;
531   }
532
533   private static void extractTypes(Map<Type,Type> typeMap, Class<?> c) {
534      Type gs = c.getGenericSuperclass();
535      if (gs instanceof ParameterizedType) {
536         ParameterizedType pt = (ParameterizedType)gs;
537         Type[] typeParameters = ((Class<?>)pt.getRawType()).getTypeParameters();
538         Type[] actualTypeArguments = pt.getActualTypeArguments();
539         for (int i = 0; i < typeParameters.length; i++) {
540            if (typeMap.containsKey(actualTypeArguments[i]))
541               actualTypeArguments[i] = typeMap.get(actualTypeArguments[i]);
542            typeMap.put(typeParameters[i], actualTypeArguments[i]);
543         }
544      }
545   }
546
547   /**
548    * Finds a public method with the specified parameters.
549    * 
550    * @param c The class to look for the method.
551    * @param name The method name.
552    * @param returnType
553    *    The return type of the method.
554    *    Can be a super type of the actual return type.
555    *    For example, if the actual return type is <code>CharSequence</code>, then <code>Object</code> will match but
556    *    <code>String</code> will not.
557    * @param argTypes
558    *    The argument types of the method.
559    *    Can be subtypes of the actual parameter types.
560    *    For example, if the parameter type is <code>CharSequence</code>, then <code>String</code> will match but
561    *    <code>Object</code> will not.
562    * @return The matched method, or <jk>null</jk> if no match was found.
563    */
564   public static Method findPublicMethod(Class<?> c, String name, Class<?> returnType, Class<?>...argTypes) {
565      for (Method m : c.getMethods()) {
566         if (isPublic(m) && m.getName().equals(name)) {
567            Class<?> rt = m.getReturnType();
568            if (isParentClass(returnType, rt) && argsMatch(m.getParameterTypes(), argTypes)) 
569               return m;
570         }
571      }
572      return null;
573   }
574
575   /**
576    * Finds a public constructor with the specified parameters without throwing an exception.
577    * 
578    * @param c The class to search for a constructor.
579    * @param fuzzyArgs 
580    *    Use fuzzy-arg matching.
581    *    Find a constructor that best matches the specified args.
582    * @param argTypes
583    *    The argument types in the constructor.
584    *    Can be subtypes of the actual constructor argument types.
585    * @return The matching constructor, or <jk>null</jk> if constructor could not be found.
586    */
587   public static <T> Constructor<T> findPublicConstructor(Class<T> c, boolean fuzzyArgs, Class<?>...argTypes) {
588      return findConstructor(c, Visibility.PUBLIC, fuzzyArgs, argTypes);
589   }
590   
591   /**
592    * Finds a constructor with the specified parameters without throwing an exception.
593    * 
594    * @param c The class to search for a constructor.
595    * @param vis The minimum visibility.
596    * @param fuzzyArgs 
597    *    Use fuzzy-arg matching.
598    *    Find a constructor that best matches the specified args.
599    * @param argTypes
600    *    The argument types in the constructor.
601    *    Can be subtypes of the actual constructor argument types.
602    * @return The matching constructor, or <jk>null</jk> if constructor could not be found.
603    */
604   @SuppressWarnings("unchecked")
605   public static <T> Constructor<T> findConstructor(Class<T> c, Visibility vis, boolean fuzzyArgs, Class<?>...argTypes) {
606      ConstructorCacheEntry cce = CONSTRUCTOR_CACHE.get(c);
607      if (cce != null && argsMatch(cce.paramTypes, argTypes) && cce.isVisible(vis)) 
608         return (Constructor<T>)cce.constructor;
609   
610      if (fuzzyArgs) {
611         int bestCount = -1;
612         Constructor<?> bestMatch = null;
613         for (Constructor<?> n : c.getDeclaredConstructors()) {
614            if (vis.isVisible(n)) {
615               int m = fuzzyArgsMatch(n.getParameterTypes(), argTypes);
616               if (m > bestCount) {
617                  bestCount = m;
618                  bestMatch = n;
619               }
620            }
621         }
622         if (bestCount >= 0) 
623            CONSTRUCTOR_CACHE.put(c, new ConstructorCacheEntry(c, bestMatch));
624         return (Constructor<T>)bestMatch;
625      } 
626      
627      for (Constructor<?> n : c.getConstructors()) {
628         if (argsMatch(n.getParameterTypes(), argTypes) && vis.isVisible(n)) {
629            CONSTRUCTOR_CACHE.put(c, new ConstructorCacheEntry(c, n));
630            return (Constructor<T>)n;
631         }
632      }
633
634      return null;
635   }
636   
637   
638   
639   private static final class ConstructorCacheEntry {
640      final Constructor<?> constructor;
641      final Class<?>[] paramTypes;
642      
643      ConstructorCacheEntry(Class<?> forClass, Constructor<?> constructor) {
644         this.constructor = constructor;
645         this.paramTypes = constructor.getParameterTypes();
646      }
647      
648      boolean isVisible(Visibility vis) {
649         return vis.isVisible(constructor);
650      }
651   }
652   
653   /**
654    * Returns <jk>true</jk> if the specified argument types are valid for the specified parameter types.
655    * 
656    * @param paramTypes The parameters types specified on a method.
657    * @param argTypes The class types of the arguments being passed to the method.
658    * @return <jk>true</jk> if the arguments match the parameters.
659    */
660   public static boolean argsMatch(Class<?>[] paramTypes, Class<?>[] argTypes) {
661      if (paramTypes.length == argTypes.length) {
662         for (int i = 0; i < paramTypes.length; i++) 
663            if (! isParentClass(paramTypes[i], argTypes[i])) 
664               return false;
665         return true;
666      }
667      return false;
668   }
669   
670   /**
671    * Returns a number representing the number of arguments that match the specified parameters.
672    * 
673    * @param paramTypes The parameters types specified on a method.
674    * @param argTypes The class types of the arguments being passed to the method.
675    * @return The number of matching arguments, or <code>-1</code> a parameter was found that isn't in the list of args.
676    */
677   public static int fuzzyArgsMatch(Class<?>[] paramTypes, Class<?>[] argTypes) {
678      int matches = 0;
679      outer: for (Class<?> p : paramTypes) {
680         p = getWrapperIfPrimitive(p);
681         for (Class<?> a : argTypes) {
682            if (isParentClass(p, a)) {
683               matches++;
684               continue outer;            
685            }
686         }
687         return -1;
688      }
689      return matches;
690   }
691
692   /**
693    * Finds the public constructor that can take in the specified arguments.
694    * 
695    * @param c The class we're trying to construct.
696    * @param args The arguments we want to pass into the constructor.
697    * @return
698    *    The constructor, or <jk>null</jk> if a public constructor could not be found that takes in the specified
699    *    arguments.
700    */
701   public static <T> Constructor<T> findPublicConstructor(Class<T> c, Object...args) {
702      return findPublicConstructor(c, false, getClasses(args));
703   }
704
705   /**
706    * Finds the public constructor that can take in the specified arguments.
707    * 
708    * @param c The class we're trying to construct.
709    * @param args The argument types we want to pass into the constructor.
710    * @return
711    *    The constructor, or <jk>null</jk> if a public constructor could not be found that takes in the specified
712    *    arguments.
713    */
714   public static <T> Constructor<T> findPublicConstructor(Class<T> c, Class<?>...args) {
715      return findPublicConstructor(c, false, args);
716   }
717
718   /**
719    * Finds the public constructor that can take in the specified arguments.
720    * 
721    * @param c The class we're trying to construct.
722    * @param fuzzyArgs 
723    *    Use fuzzy-arg matching.
724    *    Find a constructor that best matches the specified args.
725    * @param args The arguments we want to pass into the constructor.
726    * @return
727    *    The constructor, or <jk>null</jk> if a public constructor could not be found that takes in the specified
728    *    arguments.
729    */
730   public static <T> Constructor<T> findPublicConstructor(Class<T> c, boolean fuzzyArgs, Object...args) {
731      return findPublicConstructor(c, fuzzyArgs, getClasses(args));
732   }
733
734   /**
735    * Returns the class types for the specified arguments.
736    * 
737    * @param args The objects we're getting the classes of.
738    * @return The classes of the arguments.
739    */
740   public static Class<?>[] getClasses(Object...args) {
741      Class<?>[] pt = new Class<?>[args.length];
742      for (int i = 0; i < args.length; i++)
743         pt[i] = args[i] == null ? null : args[i].getClass();
744      return pt;
745   }
746
747   /**
748    * Returns a {@link MethodInfo} bean that describes the specified method.
749    * 
750    * @param m The method to describe.
751    * @return The bean with information about the method.
752    */
753   public static MethodInfo getMethodInfo(Method m) {
754      return new MethodInfo(m);
755   }
756
757   /**
758    * Returns {@link MethodInfo} beans that describe the specified methods.
759    * 
760    * @param m The methods to describe.
761    * @return The beans with information about the methods.
762    */
763   public static MethodInfo[] getMethodInfo(Collection<Method> m) {
764      MethodInfo[] mi = new MethodInfo[m.size()];
765      int i = 0;
766      for (Method mm : m)
767         mi[i++] = getMethodInfo(mm);
768      return mi;
769   }
770
771   /**
772    * Simple bean that shows the name, parameter types, and return type of a method.
773    */
774   @SuppressWarnings("javadoc")
775   public static class MethodInfo {
776      public final String methodName;
777      public final String[] parameterTypes;
778      public final String returnType;
779
780      MethodInfo(Method m) {
781         methodName = m.getName();
782         Type[] pt = m.getGenericParameterTypes();
783         parameterTypes = new String[pt.length];
784         for (int i  = 0; i < pt.length; i++)
785            parameterTypes[i] = BeanContext.DEFAULT.getClassMeta(pt[i]).toString();
786         returnType = BeanContext.DEFAULT.getClassMeta(m.getGenericReturnType()).toString();
787      }
788   }
789
790   /**
791    * Creates an instance of the specified class.
792    * 
793    * @param c 
794    *    The class to cast to.
795    * @param c2
796    *    The class to instantiate.
797    *    Can also be an instance of the class.
798    * @return 
799    *    The new class instance, or <jk>null</jk> if the class was <jk>null</jk> or is abstract or an interface.
800    * @throws 
801    *    RuntimeException if constructor could not be found or called.
802    */
803   public static <T> T newInstance(Class<T> c, Object c2) {
804      return newInstanceFromOuter(null, c, c2, false);
805   }
806
807   /**
808    * Creates an instance of the specified class.
809    * 
810    * @param c 
811    *    The class to cast to.
812    * @param c2
813    *    The class to instantiate.
814    *    Can also be an instance of the class.
815    * @param fuzzyArgs 
816    *    Use fuzzy constructor arg matching.  
817    *    <br>When <jk>true</jk>, constructor args can be in any order and extra args are ignored.
818    *    <br>No-arg constructors are also used if no other constructors are found.
819    * @param args 
820    *    The arguments to pass to the constructor.
821    * @return 
822    *    The new class instance, or <jk>null</jk> if the class was <jk>null</jk> or is abstract or an interface.
823    * @throws 
824    *    RuntimeException if constructor could not be found or called.
825    */
826   public static <T> T newInstance(Class<T> c, Object c2, boolean fuzzyArgs, Object...args) {
827      return newInstanceFromOuter(null, c, c2, fuzzyArgs, args);
828   }
829
830   /**
831    * Creates an instance of the specified class from within the context of another object.
832    * 
833    * @param outer
834    *    The outer object.
835    *    Can be <jk>null</jk>.
836    * @param c 
837    *    The class to cast to.
838    * @param c2
839    *    The class to instantiate.
840    *    Can also be an instance of the class.
841    * @param fuzzyArgs 
842    *    Use fuzzy constructor arg matching.  
843    *    <br>When <jk>true</jk>, constructor args can be in any order and extra args are ignored.
844    *    <br>No-arg constructors are also used if no other constructors are found.
845    * @param args 
846    *    The arguments to pass to the constructor.
847    * @return 
848    *    The new class instance, or <jk>null</jk> if the class was <jk>null</jk> or is abstract or an interface.
849    * @throws 
850    *    RuntimeException if constructor could not be found or called.
851    */
852   @SuppressWarnings("unchecked")
853   public static <T> T newInstanceFromOuter(Object outer, Class<T> c, Object c2, boolean fuzzyArgs, Object...args) {
854      if (c2 == null)
855         return null;
856      if (c2 instanceof Class) {
857         try {
858            Class<?> c3 = (Class<?>)c2;
859            if (c3.isInterface() || isAbstract(c3))
860               return null;
861
862            // First look for an exact match.
863            Constructor<?> con = findPublicConstructor(c3, false, args);
864            if (con != null)
865               return (T)con.newInstance(args);
866
867            // Next look for an exact match including the outer.
868            if (outer != null) {
869               args = new AList<>().append(outer).appendAll(args).toArray();
870               con = findPublicConstructor(c3, false, args);
871               if (con != null)
872                  return (T)con.newInstance(args);
873            }
874            
875            // Finally use fuzzy matching.
876            if (fuzzyArgs) {
877               con = findPublicConstructor(c3, true, args);
878               if (con != null)
879                  return (T)con.newInstance(getMatchingArgs(con, args));
880            }
881
882            throw new FormattedRuntimeException("Could not instantiate class {0}/{1}.  Constructor not found.", c.getName(), c2);
883         } catch (Exception e) {
884            throw new FormattedRuntimeException(e, "Could not instantiate class {0}", c.getName());
885         }
886      } else if (isParentClass(c, c2.getClass())) {
887         return (T)c2;
888      } else {
889         throw new FormattedRuntimeException("Object of type {0} found but was expecting {1}.", c2.getClass(), c.getClass());
890      }
891   }
892
893   private static Object[] getMatchingArgs(Constructor<?> con, Object[] args) {
894      Class<?>[] paramTypes = con.getParameterTypes();
895      Object[] params = new Object[paramTypes.length];
896      for (int i = 0; i < paramTypes.length; i++) {
897         Class<?> pt = getWrapperIfPrimitive(paramTypes[i]);
898         for (int j = 0; j < args.length; j++) {
899            if (isParentClass(pt, args[j].getClass())) {
900               params[i] = args[j];
901               break;
902            }
903         }
904      }
905      return params;
906   }
907
908   /**
909    * Returns all the fields in the specified class and all parent classes.
910    * 
911    * <p>
912    * Fields are ordered in either parent-to-child, or child-to-parent order, then alphabetically.
913    * 
914    * @param c The class to get all fields on.
915    * @param parentFirst Order them in parent-class-to-child-class order, otherwise child-class-to-parent-class order.
916    * @return An iterable of all fields in the specified class.
917    */
918   @SuppressWarnings("rawtypes")
919   public static Iterable<Field> getAllFields(final Class c, final boolean parentFirst) {
920      return new Iterable<Field>() {
921         @Override
922         public Iterator<Field> iterator() {
923            return new Iterator<Field>(){
924               final Iterator<Class<?>> classIterator = getParentClasses(c, parentFirst, false);
925               Field[] fields = classIterator.hasNext() ? sort(classIterator.next().getDeclaredFields()) : new Field[0];
926               int fIndex = 0;
927               Field next;
928
929               @Override
930               public boolean hasNext() {
931                  prime();
932                  return next != null;
933               }
934
935               private void prime() {
936                  if (next == null) {
937                     while (fIndex >= fields.length) {
938                        if (classIterator.hasNext()) {
939                           fields = sort(classIterator.next().getDeclaredFields());
940                           fIndex = 0;
941                        } else {
942                           fIndex = -1;
943                        }
944                     }
945                     if (fIndex != -1)
946                        next = fields[fIndex++];
947                  }
948               }
949
950               @Override
951               public Field next() {
952                  prime();
953                  Field f = next;
954                  next = null;
955                  return f;
956               }
957
958               @Override
959               public void remove() {
960               }
961            };
962         }
963      };
964   }
965
966   /**
967    * Returns all the methods in the specified class and all parent classes.
968    * 
969    * <p>
970    * Methods are ordered in either parent-to-child, or child-to-parent order, then alphabetically.
971    * 
972    * @param c The class to get all methods on.
973    * @param parentFirst Order them in parent-class-to-child-class order, otherwise child-class-to-parent-class order.
974    * @return An iterable of all methods in the specified class.
975    */
976   @SuppressWarnings("rawtypes")
977   public static Iterable<Method> getAllMethods(final Class c, final boolean parentFirst) {
978      return new Iterable<Method>() {
979         @Override
980         public Iterator<Method> iterator() {
981            return new Iterator<Method>(){
982               final Iterator<Class<?>> classIterator = getParentClasses(c, parentFirst, true);
983               Method[] methods = classIterator.hasNext() ? sort(classIterator.next().getDeclaredMethods()) : new Method[0];
984               int mIndex = 0;
985               Method next;
986
987               @Override
988               public boolean hasNext() {
989                  prime();
990                  return next != null;
991               }
992
993               private void prime() {
994                  if (next == null) {
995                     while (mIndex >= methods.length) {
996                        if (classIterator.hasNext()) {
997                           methods = sort(classIterator.next().getDeclaredMethods());
998                           mIndex = 0;
999                        } else {
1000                           mIndex = -1;
1001                        }
1002                     }
1003                     if (mIndex != -1)
1004                        next = methods[mIndex++];
1005                  }
1006               }
1007
1008               @Override
1009               public Method next() {
1010                  prime();
1011                  Method m = next;
1012                  next = null;
1013                  return m;
1014               }
1015
1016               @Override
1017               public void remove() {
1018               }
1019            };
1020         }
1021      };
1022   }
1023
1024   private static Comparator<Method> METHOD_COMPARATOR = new Comparator<Method>() {
1025
1026      @Override
1027      public int compare(Method o1, Method o2) {
1028         int i = o1.getName().compareTo(o2.getName());
1029         if (i == 0) {
1030            i = o1.getParameterTypes().length - o2.getParameterTypes().length;
1031            if (i == 0) {
1032               for (int j = 0; j < o1.getParameterTypes().length && i == 0; j++) {
1033                  i = o1.getParameterTypes()[j].getName().compareTo(o2.getParameterTypes()[j].getName());
1034               }
1035            }
1036         }
1037         return i;
1038      }
1039   };
1040
1041   /**
1042    * Sorts methods in alphabetical order.
1043    * 
1044    * @param m The methods to sort.
1045    * @return The same array, but with elements sorted.
1046    */
1047   public static Method[] sort(Method[] m) {
1048      Arrays.sort(m, METHOD_COMPARATOR);
1049      return m;
1050   }
1051
1052   private static Comparator<Field> FIELD_COMPARATOR = new Comparator<Field>() {
1053
1054      @Override
1055      public int compare(Field o1, Field o2) {
1056         return o1.getName().compareTo(o2.getName());
1057      }
1058   };
1059
1060   /**
1061    * Sorts methods in alphabetical order.
1062    * 
1063    * @param m The methods to sort.
1064    * @return The same array, but with elements sorted.
1065    */
1066   public static Field[] sort(Field[] m) {
1067      Arrays.sort(m, FIELD_COMPARATOR);
1068      return m;
1069   }
1070
1071   /**
1072    * Returns a list of all the parent classes of the specified class including the class itself.
1073    * 
1074    * @param c The class to retrieve the parent classes.
1075    * @param parentFirst In parent-to-child order, otherwise child-to-parent.
1076    * @param includeInterfaces Include interfaces.
1077    * @return An iterator of parent classes in the class hierarchy.
1078    */
1079   public static Iterator<Class<?>> getParentClasses(final Class<?> c, boolean parentFirst, boolean includeInterfaces) {
1080      List<Class<?>> l = getParentClasses(new ArrayList<Class<?>>(), c, parentFirst, includeInterfaces);
1081      return l.iterator();
1082   }
1083
1084   private static List<Class<?>> getParentClasses(List<Class<?>> l, Class<?> c, boolean parentFirst, boolean includeInterfaces) {
1085      if (parentFirst) {
1086         if (includeInterfaces)
1087            for (Class<?> i : c.getInterfaces())
1088               l.add(i);
1089         if (c.getSuperclass() != Object.class && c.getSuperclass() != null)
1090            getParentClasses(l, c.getSuperclass(), parentFirst, includeInterfaces);
1091         l.add(c);
1092      } else {
1093         l.add(c);
1094         if (c.getSuperclass() != Object.class && c.getSuperclass() != null)
1095            getParentClasses(l, c.getSuperclass(), parentFirst, includeInterfaces);
1096         if (includeInterfaces)
1097            for (Class<?> i : c.getInterfaces())
1098               l.add(i);
1099      }
1100      return l;
1101   }
1102
1103   /**
1104    * Returns the default value for the specified primitive class.
1105    * 
1106    * @param primitiveClass The primitive class to get the default value for.
1107    * @return The default value, or <jk>null</jk> if the specified class is not a primitive class.
1108    */
1109   public static Object getPrimitiveDefault(Class<?> primitiveClass) {
1110      return primitiveDefaultMap.get(primitiveClass);
1111   }
1112
1113   private static final Map<Class<?>,Object> primitiveDefaultMap = Collections.unmodifiableMap(
1114      new AMap<Class<?>,Object>()
1115         .append(Boolean.TYPE, false)
1116         .append(Character.TYPE, (char)0)
1117         .append(Short.TYPE, (short)0)
1118         .append(Integer.TYPE, 0)
1119         .append(Long.TYPE, 0l)
1120         .append(Float.TYPE, 0f)
1121         .append(Double.TYPE, 0d)
1122         .append(Byte.TYPE, (byte)0)
1123         .append(Boolean.class, false)
1124         .append(Character.class, (char)0)
1125         .append(Short.class, (short)0)
1126         .append(Integer.class, 0)
1127         .append(Long.class, 0l)
1128         .append(Float.class, 0f)
1129         .append(Double.class, 0d)
1130         .append(Byte.class, (byte)0)
1131   );
1132
1133   /**
1134    * Returns a readable representation of the specified method.
1135    * 
1136    * <p>
1137    * The format of the string is <js>"full-qualified-class.method-name(parameter-simple-class-names)"</js>.
1138    * 
1139    * @param m The method to stringify.
1140    * @return The stringified method.
1141    */
1142   public static String toString(Method m) {
1143      StringBuilder sb = new StringBuilder(m.getDeclaringClass().getName() + "." + m.getName() + "(");
1144      for (int i = 0; i < m.getParameterTypes().length; i++) {
1145         if (i > 0)
1146            sb.append(",");
1147         sb.append(m.getParameterTypes()[i].getSimpleName());
1148      }
1149      sb.append(")");
1150      return sb.toString();
1151   }
1152
1153   /**
1154    * Returns a readable representation of the specified field.
1155    * 
1156    * <p>
1157    * The format of the string is <js>"full-qualified-class.field-name"</js>.
1158    * 
1159    * @param f The field to stringify.
1160    * @return The stringified field.
1161    */
1162   public static String toString(Field f) {
1163      return f.getDeclaringClass().getName() + "." + f.getName();
1164   }
1165
1166   /**
1167    * Throws an {@link IllegalArgumentException} if the parameters on the method are not in the specified list provided.
1168    * 
1169    * @param m The method to test.
1170    * @param args The valid class types (exact) for the arguments.
1171    * @throws FormattedIllegalArgumentException If any of the parameters on the method weren't in the list.
1172    */
1173   public static void assertArgsOfType(Method m, Class<?>...args) throws FormattedIllegalArgumentException {
1174      for (Class<?> c1 : m.getParameterTypes()) {
1175         boolean foundMatch = false;
1176         for (Class<?> c2 : args)
1177            if (c1 == c2)
1178               foundMatch = true;
1179         if (! foundMatch)
1180            throw new FormattedIllegalArgumentException("Invalid argument of type {0} passed in method {1}.  Only arguments of type {2} are allowed.", c1, m, args);
1181      }
1182   }
1183   
1184   /**
1185    * Finds the public static "fromString" method on the specified class.
1186    * 
1187    * <p>
1188    * Looks for the following method names:
1189    * <ul>
1190    *    <li><code>fromString</code>
1191    *    <li><code>fromValue</code>
1192    *    <li><code>valueOf</code>
1193    *    <li><code>parse</code>
1194    *    <li><code>parseString</code>
1195    *    <li><code>forName</code>
1196    *    <li><code>forString</code>
1197    * </ul>
1198    * 
1199    * @param c The class to find the method on.
1200    * @return The static method, or <jk>null</jk> if it couldn't be found.
1201    */
1202   public static Method findPublicFromStringMethod(Class<?> c) {
1203      for (String methodName : new String[]{"create","fromString","fromValue","valueOf","parse","parseString","forName","forString"}) {
1204         for (Method m : c.getMethods()) {
1205            if (isStatic(m) && isPublic(m) && isNotDeprecated(m)) {
1206               String mName = m.getName();
1207               if (mName.equals(methodName) && m.getReturnType() == c) {
1208                  Class<?>[] args = m.getParameterTypes();
1209                  if (args.length == 1 && args[0] == String.class) {
1210                     return m;
1211                  }
1212               }
1213            }
1214         }
1215      }
1216      return null;
1217   }
1218   
1219   /**
1220    * Constructs a new instance of the specified class from the specified string.
1221    * 
1222    * <p>
1223    * Class must be one of the following:
1224    * <ul>
1225    *    <li>Have a public constructor that takes in a single <code>String</code> argument.
1226    *    <li>Have a static <code>fromString(String)</code> (or related) method.
1227    *       <br>See {@link #findPublicFromStringMethod(Class)} for the list of possible static method names.
1228    *    <li>Be an <code>enum</code>.
1229    * </ul>
1230    * 
1231    * @param c The class.
1232    * @param s The string to create the instance from.
1233    * @return A new object instance, or <jk>null</jk> if a method for converting the string to an object could not be found.
1234    */
1235   @SuppressWarnings({ "unchecked" })
1236   public static <T> T fromString(Class<T> c, String s) {
1237      return (T)getStringify(c).fromString(s);
1238   }
1239   
1240   /**
1241    * Converts an object to a string.
1242    * 
1243    * <p>
1244    * Normally, this is just going to call <code>toString()</code> on the object.
1245    * However, the {@link Locale} and {@link TimeZone} objects are treated special so that the returned value
1246    * works with the {@link #fromString(Class, String)} method. 
1247    * 
1248    * @param o The object to convert to a string.
1249    * @return The stringified object, or <jk>null</jk> if the object was <jk>null</jk>.
1250    */
1251   @SuppressWarnings({ "unchecked" })
1252   public static String toString(Object o) {
1253      if (o == null)
1254         return null;
1255      return getStringify(o.getClass()).toString(o);
1256   }
1257   
1258   @SuppressWarnings({ "unchecked", "rawtypes" })
1259   private static Stringify getStringify(Class c) {
1260      Stringify fs = STRINGIFY_CACHE.get(c);
1261      if (fs == null) {
1262         for (Iterator<Class<?>> i = getParentClasses(c, false, true); i.hasNext(); ) {
1263            Class c2 = i.next();
1264            fs = STRINGIFY_CACHE.get(c2);
1265            if (fs != null) {
1266               STRINGIFY_CACHE.put(c, fs);
1267               break;
1268            }
1269         }
1270         if (fs == null) {
1271            fs = new Stringify(c);
1272            STRINGIFY_CACHE.put(c, fs);
1273         }
1274      }
1275      return fs;
1276   }
1277   
1278   @SuppressWarnings({"unchecked","rawtypes"})
1279   private static class Stringify<T> {
1280      final Constructor<?> constructor;
1281      final Method fromStringMethod;
1282      final Class<? extends Enum> enumClass;
1283      
1284      Stringify(Class<?> c) {
1285         enumClass = c.isEnum() ? (Class<? extends Enum>)c : null;
1286         fromStringMethod = enumClass != null ? null : findPublicFromStringMethod(c);
1287         constructor = enumClass != null || fromStringMethod != null ? null : findPublicConstructor(c, String.class);
1288      }
1289      
1290      public T fromString(String s) {
1291         try {
1292            if (fromStringMethod != null)
1293               return (T)fromStringMethod.invoke(null, s);
1294            if (constructor != null)
1295               return (T)constructor.newInstance(s);
1296            if (enumClass != null)
1297               return (T)Enum.valueOf(enumClass, s);
1298            return null;
1299         } catch (Exception e) {
1300            throw new RuntimeException(e);
1301         }
1302      }
1303
1304      public String toString(T t) {
1305         return t.toString(); 
1306      }
1307   }
1308}