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;
014
015import static org.apache.juneau.ClassMeta.ClassCategory.*;
016import static org.apache.juneau.internal.ClassUtils.*;
017import static org.apache.juneau.internal.ObjectUtils.*;
018import static org.apache.juneau.reflect.ReflectFlags.*;
019
020import java.io.*;
021import java.lang.annotation.*;
022import java.lang.reflect.*;
023import java.lang.reflect.Proxy;
024import java.net.*;
025import java.net.URI;
026import java.time.temporal.*;
027import java.util.*;
028import java.util.Date;
029import java.util.concurrent.*;
030import java.util.concurrent.locks.*;
031
032import org.apache.juneau.annotation.*;
033import org.apache.juneau.collections.*;
034import org.apache.juneau.http.*;
035import org.apache.juneau.internal.*;
036import org.apache.juneau.json.*;
037import org.apache.juneau.reflect.*;
038import org.apache.juneau.transform.*;
039
040/**
041 * A wrapper class around the {@link Class} object that provides cached information about that class.
042 *
043 * <p>
044 * Instances of this class can be created through the {@link BeanContext#getClassMeta(Class)} method.
045 *
046 * <p>
047 * The {@link BeanContext} class will cache and reuse instances of this class except for the following class types:
048 * <ul>
049 *    <li>Arrays
050 *    <li>Maps with non-Object key/values.
051 *    <li>Collections with non-Object key/values.
052 * </ul>
053 *
054 * <p>
055 * This class is tied to the {@link BeanContext} class because it's that class that makes the determination of what is
056 * a bean.
057 *
058 * @param <T> The class type of the wrapped class.
059 */
060@Bean(bpi="innerClass,classCategory,elementType,keyType,valueType,notABeanReason,initException,beanMeta")
061public final class ClassMeta<T> implements Type {
062
063   /** Class categories. */
064   enum ClassCategory {
065      MAP, COLLECTION, CLASS, METHOD, NUMBER, DECIMAL, BOOLEAN, CHAR, DATE, ARRAY, ENUM, OTHER, CHARSEQ, STR, OBJ, URI, BEANMAP, READER, INPUTSTREAM, VOID, ARGS, OPTIONAL
066   }
067
068   final Class<T> innerClass;                              // The class being wrapped.
069   final ClassInfo info;
070
071   private final Class<? extends T> implClass;             // The implementation class to use if this is an interface.
072   private final ClassCategory cc;                         // The class category.
073   private final Method fromStringMethod;                  // The static valueOf(String) or fromString(String) or forString(String) method (if it has one).
074   private final ConstructorInfo
075      noArgConstructor,                                    // The no-arg constructor for this class (if it has one).
076      stringConstructor;                                   // The X(String) constructor (if it has one).
077   private final Method
078      exampleMethod;                                       // The example() or @Example-annotated method (if it has one).
079   private final Field
080      exampleField;                                        // The @Example-annotated field (if it has one).
081   private final Setter
082      namePropertyMethod,                                  // The method to set the name on an object (if it has one).
083      parentPropertyMethod;                                // The method to set the parent on an object (if it has one).
084   private final boolean
085      isDelegate,                                          // True if this class extends Delegate.
086      isAbstract,                                          // True if this class is abstract.
087      isMemberClass;                                       // True if this is a non-static member class.
088   private final Object primitiveDefault;                  // Default value for primitive type classes.
089   private final Map<String,Method>
090      publicMethods;                                       // All public methods, including static methods.
091   private final PojoSwap<?,?>[] childPojoSwaps;           // Any PojoSwaps where the normal type is a subclass of this class.
092   private final ConcurrentHashMap<Class<?>,PojoSwap<?,?>>
093      childSwapMap,                                        // Maps normal subclasses to PojoSwaps.
094      childUnswapMap;                                      // Maps swap subclasses to PojoSwaps.
095   private final PojoSwap<T,?>[] swaps;                     // The object POJO swaps associated with this bean (if it has any).
096   private final BeanFilter beanFilter;                    // The bean filter associated with this bean (if it has one).
097   private final BuilderSwap<T,?> builderSwap;             // The builder swap associated with this bean (if it has one).
098   private final BeanContext beanContext;                  // The bean context that created this object.
099   private final ClassMeta<?>
100      elementType,                                         // If ARRAY or COLLECTION, the element class type.
101      keyType,                                             // If MAP, the key class type.
102      valueType;                                           // If MAP, the value class type.
103   private final BeanMeta<T> beanMeta;                     // The bean meta for this bean class (if it's a bean).
104   private final String
105      typePropertyName,                                    // The property name of the _type property for this class and subclasses.
106      notABeanReason,                                      // If this isn't a bean, the reason why.
107      dictionaryName;                                      // The dictionary name of this class if it has one.
108   private final Throwable initException;                  // Any exceptions thrown in the init() method.
109   private final InvocationHandler invocationHandler;      // The invocation handler for this class (if it has one).
110   private final BeanRegistry beanRegistry;                // The bean registry of this class meta (if it has one).
111   private final ClassMeta<?>[] args;                      // Arg types if this is an array of args.
112   private final Object example;                          // Example object.
113   private final Map<Class<?>,Mutater<?,T>> fromMutaters = new ConcurrentHashMap<>();
114   private final Map<Class<?>,Mutater<T,?>> toMutaters = new ConcurrentHashMap<>();
115   private final Mutater<String,T> stringMutater;
116
117   private final ReadWriteLock lock = new ReentrantReadWriteLock(false);
118   private final Lock rLock = lock.readLock(), wLock = lock.writeLock();
119
120   /**
121    * Construct a new {@code ClassMeta} based on the specified {@link Class}.
122    *
123    * @param innerClass The class being wrapped.
124    * @param beanContext The bean context that created this object.
125    * @param implClass
126    *    For interfaces and abstract classes, this represents the "real" class to instantiate.
127    *    Can be <jk>null</jk>.
128    * @param beanFilter
129    *    The {@link BeanFilter} programmatically associated with this class.
130    *    Can be <jk>null</jk>.
131    * @param pojoSwap
132    *    The {@link PojoSwap} programmatically associated with this class.
133    *    Can be <jk>null</jk>.
134    * @param childPojoSwap
135    *    The child {@link PojoSwap PojoSwaps} programmatically associated with this class.
136    *    These are the <c>PojoSwaps</c> that have normal classes that are subclasses of this class.
137    *    Can be <jk>null</jk>.
138    * @param delayedInit
139    *    Don't call init() in constructor.
140    *    Used for delayed initialization when the possibility of class reference loops exist.
141    */
142   @SuppressWarnings({ "rawtypes", "unchecked" })
143   ClassMeta(Class<T> innerClass, BeanContext beanContext, Class<? extends T> implClass, BeanFilter beanFilter, PojoSwap<T,?>[] swaps, PojoSwap<?,?>[] childPojoSwaps, Object example) {
144      this.innerClass = innerClass;
145      this.info = ClassInfo.of(innerClass);
146      this.beanContext = beanContext;
147      String notABeanReason = null;
148
149      wLock.lock();
150      try {
151         // We always immediately add this class meta to the bean context cache so that we can resolve recursive references.
152         if (beanContext != null && beanContext.cmCache != null && isCacheable(innerClass))
153            beanContext.cmCache.put(innerClass, this);
154
155         ClassMetaBuilder<T> builder = new ClassMetaBuilder(innerClass, beanContext, implClass, beanFilter, swaps, childPojoSwaps, example);
156
157         this.cc = builder.cc;
158         this.isDelegate = builder.isDelegate;
159         this.fromStringMethod = builder.fromStringMethod;
160         this.parentPropertyMethod = builder.parentPropertyMethod;
161         this.namePropertyMethod = builder.namePropertyMethod;
162         this.noArgConstructor = builder.noArgConstructor;
163         this.stringConstructor = builder.stringConstructor;
164         this.primitiveDefault = builder.primitiveDefault;
165         this.publicMethods = builder.publicMethods;
166         this.beanFilter = beanFilter;
167         this.swaps = builder.swaps.isEmpty() ? null : builder.swaps.toArray(new PojoSwap[builder.swaps.size()]);
168         this.builderSwap = builder.builderSwap;
169         this.keyType = builder.keyType;
170         this.valueType = builder.valueType;
171         this.elementType = builder.elementType;
172         notABeanReason = builder.notABeanReason;
173         this.beanMeta = builder.beanMeta;
174         this.initException = builder.initException;
175         this.typePropertyName = builder.typePropertyName;
176         this.dictionaryName = builder.dictionaryName;
177         this.invocationHandler = builder.invocationHandler;
178         this.beanRegistry = builder.beanRegistry;
179         this.isMemberClass = builder.isMemberClass;
180         this.isAbstract = builder.isAbstract;
181         this.implClass = builder.implClass;
182         this.childUnswapMap = builder.childUnswapMap;
183         this.childSwapMap = builder.childSwapMap;
184         this.childPojoSwaps = builder.childPojoSwaps;
185         this.exampleMethod = builder.exampleMethod;
186         this.exampleField = builder.exampleField;
187         this.example = builder.example;
188         this.args = null;
189         this.stringMutater = builder.stringMutater;
190      } catch (ClassMetaRuntimeException e) {
191         notABeanReason = e.getMessage();
192         throw e;
193      } finally {
194         this.notABeanReason = notABeanReason;
195         wLock.unlock();
196      }
197   }
198
199   /**
200    * Generated classes shouldn't be cacheable to prevent needlessly filling up the cache.
201    */
202   private static boolean isCacheable(Class<?> c) {
203      String n = c.getName();
204      char x = n.charAt(n.length()-1);  // All generated classes appear to end with digits.
205      if (x >= '0' && x <= '9') {
206         if (n.indexOf("$$") != -1 || n.startsWith("sun") || n.startsWith("com.sun") || n.indexOf("$Proxy") != -1)
207            return false;
208      }
209      return true;
210   }
211
212   /**
213    * Causes thread to wait until constructor has exited.
214    */
215   final void waitForInit() {
216      rLock.lock();
217      rLock.unlock();
218   }
219
220   /**
221    * Copy constructor.
222    *
223    * <p>
224    * Used for creating Map and Collection class metas that shouldn't be cached.
225    */
226   ClassMeta(ClassMeta<T> mainType, ClassMeta<?> keyType, ClassMeta<?> valueType, ClassMeta<?> elementType) {
227      this.innerClass = mainType.innerClass;
228      this.info = mainType.info;
229      this.implClass = mainType.implClass;
230      this.childPojoSwaps = mainType.childPojoSwaps;
231      this.childSwapMap = mainType.childSwapMap;
232      this.childUnswapMap = mainType.childUnswapMap;
233      this.cc = mainType.cc;
234      this.fromStringMethod = mainType.fromStringMethod;
235      this.noArgConstructor = mainType.noArgConstructor;
236      this.stringConstructor = mainType.stringConstructor;
237      this.namePropertyMethod = mainType.namePropertyMethod;
238      this.parentPropertyMethod = mainType.parentPropertyMethod;
239      this.isDelegate = mainType.isDelegate;
240      this.isAbstract = mainType.isAbstract;
241      this.isMemberClass = mainType.isMemberClass;
242      this.primitiveDefault = mainType.primitiveDefault;
243      this.publicMethods = mainType.publicMethods;
244      this.beanContext = mainType.beanContext;
245      this.elementType = elementType;
246      this.keyType = keyType;
247      this.valueType = valueType;
248      this.invocationHandler = mainType.invocationHandler;
249      this.beanMeta = mainType.beanMeta;
250      this.typePropertyName = mainType.typePropertyName;
251      this.dictionaryName = mainType.dictionaryName;
252      this.notABeanReason = mainType.notABeanReason;
253      this.swaps = mainType.swaps;
254      this.builderSwap = mainType.builderSwap;
255      this.beanFilter = mainType.beanFilter;
256      this.initException = mainType.initException;
257      this.beanRegistry = mainType.beanRegistry;
258      this.exampleMethod = mainType.exampleMethod;
259      this.exampleField = mainType.exampleField;
260      this.example = mainType.example;
261      this.args = null;
262      this.stringMutater = mainType.stringMutater;
263   }
264
265   /**
266    * Constructor for args-arrays.
267    */
268   @SuppressWarnings("unchecked")
269   ClassMeta(ClassMeta<?>[] args) {
270      this.innerClass = (Class<T>) Object[].class;
271      this.info = ClassInfo.of(innerClass);
272      this.args = args;
273      this.implClass = null;
274      this.childPojoSwaps = null;
275      this.childSwapMap = null;
276      this.childUnswapMap = null;
277      this.cc = ARGS;
278      this.fromStringMethod = null;
279      this.noArgConstructor = null;
280      this.stringConstructor = null;
281      this.namePropertyMethod = null;
282      this.parentPropertyMethod = null;
283      this.isDelegate = false;
284      this.isAbstract = false;
285      this.isMemberClass = false;
286      this.primitiveDefault = null;
287      this.publicMethods = null;
288      this.beanContext = null;
289      this.elementType = null;
290      this.keyType = null;
291      this.valueType = null;
292      this.invocationHandler = null;
293      this.beanMeta = null;
294      this.typePropertyName = null;
295      this.dictionaryName = null;
296      this.notABeanReason = null;
297      this.swaps = null;
298      this.builderSwap = null;
299      this.beanFilter = null;
300      this.initException = null;
301      this.beanRegistry = null;
302      this.exampleMethod = null;
303      this.exampleField = null;
304      this.example = null;
305      this.stringMutater = null;
306   }
307
308   @SuppressWarnings({"unchecked","rawtypes","hiding"})
309   private final class ClassMetaBuilder<T> {
310      Class<T> innerClass;
311      ClassInfo ci;
312      Class<? extends T> implClass;
313      BeanContext beanContext;
314      ClassCategory cc = ClassCategory.OTHER;
315      boolean
316         isDelegate = false,
317         isMemberClass = false,
318         isAbstract = false;
319      Method
320         fromStringMethod = null;
321      Setter
322         parentPropertyMethod = null,
323         namePropertyMethod = null;
324      ConstructorInfo
325         noArgConstructor = null,
326         stringConstructor = null;
327      Object primitiveDefault = null;
328      Map<String,Method>
329         publicMethods = new LinkedHashMap<>();
330      ClassMeta<?>
331         keyType = null,
332         valueType = null,
333         elementType = null;
334      String
335         typePropertyName = null,
336         notABeanReason = null,
337         dictionaryName = null;
338      Throwable initException = null;
339      BeanMeta beanMeta = null;
340      AList<PojoSwap> swaps = AList.of();
341      BuilderSwap builderSwap;
342      InvocationHandler invocationHandler = null;
343      BeanRegistry beanRegistry = null;
344      PojoSwap<?,?>[] childPojoSwaps;
345      ConcurrentHashMap<Class<?>,PojoSwap<?,?>>
346         childSwapMap,
347         childUnswapMap;
348      Method exampleMethod;
349      Field exampleField;
350      Object example;
351      Mutater<String,T> stringMutater;
352
353      @SuppressWarnings("deprecation")
354      ClassMetaBuilder(Class<T> innerClass, BeanContext beanContext, Class<? extends T> implClass, BeanFilter beanFilter, PojoSwap<T,?>[] swaps, PojoSwap<?,?>[] childPojoSwaps, Object example) {
355         this.innerClass = innerClass;
356         this.beanContext = beanContext;
357         BeanContext bc = beanContext;
358
359         this.implClass = implClass;
360         ClassInfo ici = ClassInfo.of(implClass);
361         this.childPojoSwaps = childPojoSwaps;
362         if (childPojoSwaps == null) {
363            this.childSwapMap = null;
364            this.childUnswapMap = null;
365         } else {
366            this.childSwapMap = new ConcurrentHashMap<>();
367            this.childUnswapMap = new ConcurrentHashMap<>();
368         }
369
370         Class<T> c = innerClass;
371         ci = ClassInfo.of(c);
372         if (ci.isProxy()) {
373            ci = ci.getProxyFor();
374            innerClass = this.innerClass = ci.inner();
375         }
376
377         if (c.isPrimitive()) {
378            if (c == Boolean.TYPE)
379               cc = BOOLEAN;
380            else if (c == Byte.TYPE || c == Short.TYPE || c == Integer.TYPE || c == Long.TYPE || c == Float.TYPE || c == Double.TYPE) {
381               if (c == Float.TYPE || c == Double.TYPE)
382                  cc = DECIMAL;
383               else
384                  cc = NUMBER;
385            }
386            else if (c == Character.TYPE)
387               cc = CHAR;
388            else if (c == void.class || c == Void.class)
389               cc = VOID;
390         } else {
391            if (ci.isChildOf(Delegate.class))
392               isDelegate = true;
393
394            if (c == Object.class)
395               cc = OBJ;
396            else if (c.isEnum())
397               cc = ENUM;
398            else if (c.equals(Class.class))
399               cc = ClassCategory.CLASS;
400            else if (ci.isChildOf(Method.class))
401               cc = METHOD;
402            else if (ci.isChildOf(CharSequence.class)) {
403               if (c.equals(String.class))
404                  cc = STR;
405               else
406                  cc = CHARSEQ;
407            }
408            else if (ci.isChildOf(Number.class)) {
409               if (ci.isChildOfAny(Float.class, Double.class))
410                  cc = DECIMAL;
411               else
412                  cc = NUMBER;
413            }
414            else if (ci.isChildOf(Collection.class))
415               cc = COLLECTION;
416            else if (ci.isChildOf(Map.class)) {
417               if (ci.isChildOf(BeanMap.class))
418                  cc = BEANMAP;
419               else
420                  cc = MAP;
421            }
422            else if (c == Character.class)
423               cc = CHAR;
424            else if (c == Boolean.class)
425               cc = BOOLEAN;
426            else if (ci.isChildOfAny(Date.class, Calendar.class))
427               cc = DATE;
428            else if (c.isArray())
429               cc = ARRAY;
430            else if (ci.isChildOfAny(URL.class, URI.class) || bc.hasAnnotation(org.apache.juneau.annotation.URI.class, c))
431               cc = URI;
432            else if (ci.isChildOf(Reader.class))
433               cc = READER;
434            else if (ci.isChildOf(InputStream.class))
435               cc = INPUTSTREAM;
436            else if (ci.is(Optional.class))
437               cc = OPTIONAL;
438         }
439
440         isMemberClass = ci.isMemberClass() && ci.isNotStatic();
441
442         // Find static fromString(String) or equivalent method.
443         // fromString() must be checked before valueOf() so that Enum classes can create their own
444         //    specialized fromString() methods to override the behavior of Enum.valueOf(String).
445         // valueOf() is used by enums.
446         // parse() is used by the java logging Level class.
447         // forName() is used by Class and Charset
448         for (String methodName : new String[]{"fromString","fromValue","valueOf","parse","parseString","forName","forString"}) {
449            if (fromStringMethod == null) {
450               for (MethodInfo m : ci.getPublicMethods()) {
451                  if (m.isAll(STATIC, PUBLIC, NOT_DEPRECATED) && m.hasName(methodName) && m.hasReturnType(c) && m.hasParamTypes(String.class)) {
452                     fromStringMethod = m.inner();
453                     break;
454                  }
455               }
456            }
457         }
458
459         // Find example() method if present.
460         for (MethodInfo m : ci.getPublicMethods()) {
461            if (m.isAll(PUBLIC, NOT_DEPRECATED, STATIC) && m.hasName("example") && m.hasFuzzyParamTypes(BeanSession.class)) {
462               exampleMethod = m.inner();
463               break;
464            }
465         }
466
467         for (FieldInfo f : ci.getAllFieldsParentFirst()) {
468            if (bc.hasAnnotation(ParentProperty.class, f)) {
469               if (f.isStatic())
470                  throw new ClassMetaRuntimeException(c, "@ParentProperty used on invalid field ''{0}''.  Must be static.", f);
471               f.setAccessible();
472               parentPropertyMethod = new Setter.FieldSetter(f.inner());
473            }
474            if (bc.hasAnnotation(NameProperty.class, f)) {
475               if (f.isStatic())
476                  throw new ClassMetaRuntimeException(c, "@NameProperty used on invalid field ''{0}''.  Must be static.", f);
477               f.setAccessible();
478               namePropertyMethod = new Setter.FieldSetter(f.inner());
479            }
480         }
481
482         for (FieldInfo f : ci.getDeclaredFields()) {
483            if (bc.hasAnnotation(Example.class, f)) {
484               if (! (f.isStatic() && ci.isParentOf(f.getType().inner())))
485                  throw new ClassMetaRuntimeException(c, "@Example used on invalid field ''{0}''.  Must be static and an instance of the type.", f);
486               f.setAccessible();
487               exampleField = f.inner();
488            }
489         }
490
491         // Find @NameProperty and @ParentProperty methods if present.
492         for (MethodInfo m : ci.getAllMethodsParentFirst()) {
493            if (bc.hasAnnotation(ParentProperty.class, m)) {
494               if (m.isStatic() || ! m.hasNumParams(1))
495                  throw new ClassMetaRuntimeException(c, "@ParentProperty used on invalid method ''{0}''.  Must not be static and have one argument.", m);
496               m.setAccessible();
497               parentPropertyMethod = new Setter.MethodSetter(m.inner());
498            }
499            if (bc.hasAnnotation(NameProperty.class, m)) {
500               if (m.isStatic() || ! m.hasNumParams(1))
501                  throw new ClassMetaRuntimeException(c, "@NameProperty used on invalid method ''{0}''.  Must not be static and have one argument.", m);
502               m.setAccessible();
503               namePropertyMethod = new Setter.MethodSetter(m.inner());
504            }
505         }
506
507         for (MethodInfo m : ci.getDeclaredMethods()) {
508            if (bc.hasAnnotation(Example.class, m)) {
509               if (! (m.isStatic() && m.hasFuzzyParamTypes(BeanSession.class) && ci.isParentOf(m.getReturnType().inner())))
510                  throw new ClassMetaRuntimeException(c, "@Example used on invalid method ''{0}''.  Must be static and return an instance of the declaring class.", m);
511               m.setAccessible();
512               exampleMethod = m.inner();
513            }
514         }
515
516         // Note:  Primitive types are normally abstract.
517         isAbstract = ci.isAbstract() && ci.isNotPrimitive();
518
519         // Find constructor(String) method if present.
520         for (ConstructorInfo cs : ci.getPublicConstructors()) {
521            if (cs.isPublic() && cs.isNotDeprecated()) {
522               List<ClassInfo> pt = cs.getParamTypes();
523               if (pt.size() == (isMemberClass ? 1 : 0) && c != Object.class && ! isAbstract) {
524                  noArgConstructor = cs;
525               } else if (pt.size() == (isMemberClass ? 2 : 1)) {
526                  ClassInfo arg = pt.get(isMemberClass ? 1 : 0);
527                  if (arg.is(String.class))
528                     stringConstructor = cs;
529               }
530            }
531         }
532
533         primitiveDefault = ci.getPrimitiveDefault();
534
535         for (MethodInfo m : ci.getPublicMethods())
536            if (m.isAll(PUBLIC, NOT_DEPRECATED))
537               publicMethods.put(m.getSignature(), m.inner());
538
539         if (innerClass != Object.class) {
540            ClassInfo x = implClass == null ? ci : ici;
541            noArgConstructor = x.getPublicConstructor();
542         }
543
544         if (beanFilter == null)
545            beanFilter = findBeanFilter(bc);
546
547         if (swaps != null)
548            this.swaps.a(swaps);
549
550         if (bc != null)
551            this.builderSwap = BuilderSwap.findSwapFromPojoClass(bc, c, bc.getBeanConstructorVisibility(), bc.getBeanMethodVisibility());
552
553         findSwaps(this.swaps, bc);
554
555         try {
556
557            // If this is an array, get the element type.
558            if (cc == ARRAY)
559               elementType = findClassMeta(innerClass.getComponentType());
560
561            // If this is a MAP, see if it's parameterized (e.g. AddressBook extends HashMap<String,Person>)
562            else if (cc == MAP) {
563               ClassMeta[] parameters = findParameters();
564               if (parameters != null && parameters.length == 2) {
565                  keyType = parameters[0];
566                  valueType = parameters[1];
567               } else {
568                  keyType = findClassMeta(Object.class);
569                  valueType = findClassMeta(Object.class);
570               }
571            }
572
573            // If this is a COLLECTION, see if it's parameterized (e.g. AddressBook extends LinkedList<Person>)
574            else if (cc == COLLECTION || cc == OPTIONAL) {
575               ClassMeta[] parameters = findParameters();
576               if (parameters != null && parameters.length == 1) {
577                  elementType = parameters[0];
578               } else {
579                  elementType = findClassMeta(Object.class);
580               }
581            }
582
583            // If the category is unknown, see if it's a bean.
584            // Note that this needs to be done after all other initialization has been done.
585            else if (cc == OTHER) {
586
587               BeanMeta newMeta = null;
588               try {
589                  newMeta = new BeanMeta(ClassMeta.this, bc, beanFilter, null);
590                  notABeanReason = newMeta.notABeanReason;
591
592                  // Always get these even if it's not a bean:
593                  beanRegistry = newMeta.beanRegistry;
594                  typePropertyName = newMeta.typePropertyName;
595
596               } catch (RuntimeException e) {
597                  notABeanReason = e.getMessage();
598                  throw e;
599               }
600               if (notABeanReason == null)
601                  beanMeta = newMeta;
602            }
603
604         } catch (NoClassDefFoundError e) {
605            initException = e;
606         } catch (RuntimeException e) {
607            initException = e;
608            throw e;
609         }
610
611         if (beanMeta != null)
612            dictionaryName = beanMeta.getDictionaryName();
613
614         if (beanMeta != null && bc != null && bc.isUseInterfaceProxies() && innerClass.isInterface())
615            invocationHandler = new BeanProxyInvocationHandler<T>(beanMeta);
616
617         if (bc != null) {
618            for (Bean b : bc.getAnnotations(Bean.class, c)) {
619               if (b.beanDictionary().length != 0)
620                  beanRegistry = new BeanRegistry(bc, null, b.beanDictionary());
621               if (b.dictionary().length != 0)
622                  beanRegistry = new BeanRegistry(bc, null, b.dictionary());
623
624               // This could be a non-bean POJO with a type name.
625               if (dictionaryName == null && ! b.typeName().isEmpty())
626                  dictionaryName = b.typeName();
627            }
628         }
629
630         if (example == null && bc != null)
631            for (Example e : bc.getAnnotations(Example.class, c))
632               if (! e.value().isEmpty())
633                  example = e.value();
634
635         if (example == null) {
636            switch(cc) {
637               case BOOLEAN:
638                  example = true;
639                  break;
640               case CHAR:
641                  example = 'a';
642                  break;
643               case CHARSEQ:
644               case STR:
645                  example = "foo";
646                  break;
647               case DECIMAL:
648                  if (isFloat())
649                     example = new Float(1f);
650                  else if (isDouble())
651                     example = new Double(1d);
652                  break;
653               case ENUM:
654                  Iterator<? extends Enum> i = EnumSet.allOf((Class<? extends Enum>)c).iterator();
655                  if (i.hasNext())
656                     example = i.next();
657                  break;
658               case NUMBER:
659                  if (isShort())
660                     example = new Short((short)1);
661                  else if (isInteger())
662                     example = new Integer(1);
663                  else if (isLong())
664                     example = new Long(1l);
665                  break;
666               case URI:
667               case ARGS:
668               case ARRAY:
669               case BEANMAP:
670               case CLASS:
671               case COLLECTION:
672               case DATE:
673               case INPUTSTREAM:
674               case MAP:
675               case METHOD:
676               case OBJ:
677               case OTHER:
678               case READER:
679               case OPTIONAL:
680               case VOID:
681                  break;
682            }
683         }
684
685         this.example = example;
686
687         this.stringMutater = Mutaters.get(String.class, c);
688      }
689
690      private BeanFilter findBeanFilter(BeanContext bc) {
691         try {
692            List<Bean> ba = info.getAnnotations(Bean.class, bc);
693            if (! ba.isEmpty())
694               return new AnnotationBeanFilterBuilder(innerClass, ba).build();
695         } catch (Exception e) {
696            throw new RuntimeException(e);
697         }
698         return null;
699      }
700
701      private void findSwaps(List<PojoSwap> l, BeanContext bc) {
702
703         if (bc != null) {
704            for (Swap swap : bc.getAnnotations(Swap.class, innerClass))
705               l.add(createPojoSwap(swap));
706            for (Swaps swaps : bc.getAnnotations(Swaps.class, innerClass))
707               for (Swap swap : swaps.value())
708                  l.add(createPojoSwap(swap));
709         }
710
711         PojoSwap defaultSwap = DefaultSwaps.find(ci);
712         if (defaultSwap == null)
713            defaultSwap = AutoObjectSwap.find(bc, ci);
714         if (defaultSwap == null)
715            defaultSwap = AutoNumberSwap.find(bc, ci);
716         if (defaultSwap == null)
717            defaultSwap = AutoMapSwap.find(bc, ci);
718         if (defaultSwap == null)
719            defaultSwap = AutoListSwap.find(bc, ci);
720         if (defaultSwap != null)
721            l.add(defaultSwap);
722      }
723
724      private PojoSwap<T,?> createPojoSwap(Swap s) {
725         Class<?> c = s.value();
726         if (c == Null.class)
727            c = s.impl();
728         ClassInfo ci = ClassInfo.of(c);
729
730         if (ci.isChildOf(PojoSwap.class)) {
731            PojoSwap ps = castOrCreate(PojoSwap.class, c);
732            if (s.mediaTypes().length > 0)
733               ps.forMediaTypes(MediaType.ofAll(s.mediaTypes()));
734            if (! s.template().isEmpty())
735               ps.withTemplate(s.template());
736            return ps;
737         }
738
739         if (ci.isChildOf(Surrogate.class)) {
740            List<SurrogateSwap<?,?>> l = SurrogateSwap.findPojoSwaps(c, beanContext);
741            if (! l.isEmpty())
742               return (PojoSwap<T,?>)l.iterator().next();
743         }
744
745         throw new ClassMetaRuntimeException(c, "Invalid swap class ''{0}'' specified.  Must extend from PojoSwap or Surrogate.", c);
746      }
747
748      private ClassMeta<?> findClassMeta(Class<?> c) {
749         return beanContext.getClassMeta(c, false);
750      }
751
752      private ClassMeta<?>[] findParameters() {
753         return beanContext.findParameters(innerClass, innerClass);
754      }
755   }
756
757   /**
758    * Returns the {@link ClassInfo} wrapper for the underlying class.
759    *
760    * @return The {@link ClassInfo} wrapper for the underlying class, never <jk>null</jk>.
761    */
762   public ClassInfo getInfo() {
763      return info;
764   }
765
766   /**
767    * Returns the type property name associated with this class and subclasses.
768    *
769    * <p>
770    * If <jk>null</jk>, <js>"_type"</js> should be assumed.
771    *
772    * @return
773    *    The type property name associated with this bean class, or <jk>null</jk> if there is no explicit type
774    *    property name defined or this isn't a bean.
775    */
776   public String getBeanTypePropertyName() {
777      return typePropertyName;
778   }
779
780   /**
781    * Returns the bean dictionary name associated with this class.
782    *
783    * <p>
784    * The lexical name is defined by {@link Bean#typeName() @Bean(typeName)}.
785    *
786    * @return
787    *    The type name associated with this bean class, or <jk>null</jk> if there is no type name defined or this
788    *    isn't a bean.
789    */
790   public String getDictionaryName() {
791      return dictionaryName;
792   }
793
794   /**
795    * Returns the bean registry for this class.
796    *
797    * <p>
798    * This bean registry contains names specified in the {@link Bean#dictionary() @Bean(dictionary)} annotation
799    * defined on the class, regardless of whether the class is an actual bean.
800    * This allows interfaces to define subclasses with type names.
801    *
802    * @return The bean registry for this class, or <jk>null</jk> if no bean registry is associated with it.
803    */
804   public BeanRegistry getBeanRegistry() {
805      return beanRegistry;
806   }
807
808   /**
809    * Returns the category of this class.
810    *
811    * @return The category of this class.
812    */
813   public ClassCategory getClassCategory() {
814      return cc;
815   }
816
817   /**
818    * Returns <jk>true</jk> if this class is a superclass of or the same as the specified class.
819    *
820    * @param c The comparison class.
821    * @return <jk>true</jk> if this class is a superclass of or the same as the specified class.
822    */
823   public boolean isAssignableFrom(Class<?> c) {
824      return info.isChildOf(c);
825   }
826
827   /**
828    * Returns <jk>true</jk> if this class is a subclass of or the same as the specified class.
829    *
830    * @param c The comparison class.
831    * @return <jk>true</jk> if this class is a subclass of or the same as the specified class.
832    */
833   public boolean isInstanceOf(Class<?> c) {
834      return info.isParentOf(c);
835   }
836
837   /**
838    * Returns <jk>true</jk> if this class or any child classes has a {@link PojoSwap} associated with it.
839    *
840    * <p>
841    * Used when transforming bean properties to prevent having to look up transforms if we know for certain that no
842    * transforms are associated with a bean property.
843    *
844    * @return <jk>true</jk> if this class or any child classes has a {@link PojoSwap} associated with it.
845    */
846   protected boolean hasChildPojoSwaps() {
847      return childPojoSwaps != null;
848   }
849
850   /**
851    * Returns the {@link PojoSwap} where the specified class is the same/subclass of the normal class of one of the
852    * child POJO swaps associated with this class.
853    *
854    * @param normalClass The normal class being resolved.
855    * @return The resolved {@link PojoSwap} or <jk>null</jk> if none were found.
856    */
857   protected PojoSwap<?,?> getChildPojoSwapForSwap(Class<?> normalClass) {
858      if (childSwapMap != null) {
859         PojoSwap<?,?> s = childSwapMap.get(normalClass);
860         if (s == null) {
861            for (PojoSwap<?,?> f : childPojoSwaps)
862               if (s == null && f.getNormalClass().isParentOf(normalClass))
863                  s = f;
864            if (s == null)
865               s = PojoSwap.NULL;
866            PojoSwap<?,?> s2 = childSwapMap.putIfAbsent(normalClass, s);
867            if (s2 != null)
868               s = s2;
869         }
870         if (s == PojoSwap.NULL)
871            return null;
872         return s;
873      }
874      return null;
875   }
876
877   /**
878    * Returns the {@link PojoSwap} where the specified class is the same/subclass of the swap class of one of the child
879    * POJO swaps associated with this class.
880    *
881    * @param swapClass The swap class being resolved.
882    * @return The resolved {@link PojoSwap} or <jk>null</jk> if none were found.
883    */
884   protected PojoSwap<?,?> getChildPojoSwapForUnswap(Class<?> swapClass) {
885      if (childUnswapMap != null) {
886         PojoSwap<?,?> s = childUnswapMap.get(swapClass);
887         if (s == null) {
888            for (PojoSwap<?,?> f : childPojoSwaps)
889               if (s == null && f.getSwapClass().isParentOf(swapClass))
890                  s = f;
891            if (s == null)
892               s = PojoSwap.NULL;
893            PojoSwap<?,?> s2 = childUnswapMap.putIfAbsent(swapClass, s);
894            if (s2 != null)
895               s = s2;
896         }
897         if (s == PojoSwap.NULL)
898            return null;
899         return s;
900      }
901      return null;
902   }
903
904   /**
905    * Locates the no-arg constructor for the specified class.
906    *
907    * <p>
908    * Constructor must match the visibility requirements specified by parameter 'v'.
909    * If class is abstract, always returns <jk>null</jk>.
910    * Note that this also returns the 1-arg constructor for non-static member classes.
911    *
912    * @param c The class from which to locate the no-arg constructor.
913    * @param v The minimum visibility.
914    * @return The constructor, or <jk>null</jk> if no no-arg constructor exists with the required visibility.
915    */
916   @SuppressWarnings({"unchecked"})
917   protected static <T> Constructor<? extends T> findNoArgConstructor(Class<?> c, Visibility v) {
918      ClassInfo ci = ClassInfo.of(c);
919      if (ci.isAbstract())
920         return null;
921      boolean isMemberClass = ci.isMemberClass() && ci.isNotStatic();
922      for (ConstructorInfo cc : ci.getPublicConstructors()) {
923         if (cc.hasNumParams(isMemberClass ? 1 : 0) && cc.isVisible(v) && cc.isNotDeprecated())
924            return (Constructor<? extends T>) v.transform(cc.inner());
925      }
926      return null;
927   }
928
929   /**
930    * Returns the {@link Class} object that this class type wraps.
931    *
932    * @return The wrapped class object.
933    */
934   public Class<T> getInnerClass() {
935      return innerClass;
936   }
937
938   /**
939    * Returns the serialized (swapped) form of this class if there is an {@link PojoSwap} associated with it.
940    *
941    * @param session
942    *    The bean session.
943    *    <br>Required because the swap used may depend on the media type being serialized or parsed.
944    * @return The serialized class type, or this object if no swap is associated with the class.
945    */
946   @BeanIgnore
947   public ClassMeta<?> getSerializedClassMeta(BeanSession session) {
948      PojoSwap<T,?> ps = getSwap(session);
949      return (ps == null ? this : ps.getSwapClassMeta(session));
950   }
951
952   /**
953    * Returns the example of this class.
954    *
955    * @param session
956    *    The bean session.
957    *    <br>Required because the example method may take it in as a parameter.
958    * @return The serialized class type, or this object if no swap is associated with the class.
959    */
960   @SuppressWarnings({"unchecked","rawtypes"})
961   @BeanIgnore
962   public T getExample(BeanSession session) {
963      try {
964         if (example != null) {
965            if (isInstance(example))
966               return (T)example;
967            if (example instanceof String) {
968               if (isCharSequence())
969                  return (T)example;
970               String s = example.toString();
971               if (isMapOrBean() && StringUtils.isJsonObject(s, false))
972                  return JsonParser.DEFAULT.parse(s, this);
973               if (isCollectionOrArray() && StringUtils.isJsonArray(s, false))
974                  return JsonParser.DEFAULT.parse(s, this);
975            }
976            if (example instanceof Map && isMapOrBean()) {
977               return JsonParser.DEFAULT.parse(SimpleJsonSerializer.DEFAULT_READABLE.toString(example), this);
978            }
979            if (example instanceof Collection && isCollectionOrArray()) {
980               return JsonParser.DEFAULT.parse(SimpleJsonSerializer.DEFAULT_READABLE.serialize(example), this);
981            }
982         }
983         if (exampleMethod != null)
984            return (T)MethodInfo.of(exampleMethod).invokeFuzzy(null, session);
985         if (exampleField != null)
986            return (T)exampleField.get(null);
987
988         if (isCollection()) {
989            Object etExample = getElementType().getExample(session);
990            if (etExample != null) {
991               if (canCreateNewInstance()) {
992                  Collection c = (Collection)newInstance();
993                  c.add(etExample);
994                  return (T)c;
995               }
996               return (T)Collections.singleton(etExample);
997            }
998         } else if (isArray()) {
999            Object etExample = getElementType().getExample(session);
1000            if (etExample != null) {
1001               Object o = Array.newInstance(getElementType().innerClass, 1);
1002               Array.set(o, 0, etExample);
1003               return (T)o;
1004            }
1005         } else if (isMap()) {
1006            Object vtExample = getValueType().getExample(session);
1007            Object ktExample = getKeyType().getExample(session);
1008            if (ktExample != null && vtExample != null) {
1009               if (canCreateNewInstance()) {
1010                  Map m = (Map)newInstance();
1011                  m.put(ktExample, vtExample);
1012                  return (T)m;
1013               }
1014               return (T)Collections.singletonMap(ktExample, vtExample);
1015            }
1016         }
1017
1018         return null;
1019      } catch (Exception e) {
1020         throw new ClassMetaRuntimeException(e);
1021      }
1022   }
1023
1024   /**
1025    * For array and {@code Collection} types, returns the class type of the components of the array or
1026    * {@code Collection}.
1027    *
1028    * @return The element class type, or <jk>null</jk> if this class is not an array or Collection.
1029    */
1030   public ClassMeta<?> getElementType() {
1031      return elementType;
1032   }
1033
1034   /**
1035    * For {@code Map} types, returns the class type of the keys of the {@code Map}.
1036    *
1037    * @return The key class type, or <jk>null</jk> if this class is not a Map.
1038    */
1039   public ClassMeta<?> getKeyType() {
1040      return keyType;
1041   }
1042
1043   /**
1044    * For {@code Map} types, returns the class type of the values of the {@code Map}.
1045    *
1046    * @return The value class type, or <jk>null</jk> if this class is not a Map.
1047    */
1048   public ClassMeta<?> getValueType() {
1049      return valueType;
1050   }
1051
1052   /**
1053    * Returns <jk>true</jk> if this class implements {@link Delegate}, meaning it's a representation of some other
1054    * object.
1055    *
1056    * @return <jk>true</jk> if this class implements {@link Delegate}.
1057    */
1058   public boolean isDelegate() {
1059      return isDelegate;
1060   }
1061
1062   /**
1063    * Returns <jk>true</jk> if this class is a subclass of {@link Map}.
1064    *
1065    * @return <jk>true</jk> if this class is a subclass of {@link Map}.
1066    */
1067   public boolean isMap() {
1068      return cc == MAP || cc == BEANMAP;
1069   }
1070
1071   /**
1072    * Returns <jk>true</jk> if this class is a subclass of {@link Map} or it's a bean.
1073    *
1074    * @return <jk>true</jk> if this class is a subclass of {@link Map} or it's a bean.
1075    */
1076   public boolean isMapOrBean() {
1077      return cc == MAP || cc == BEANMAP || beanMeta != null;
1078   }
1079
1080   /**
1081    * Returns <jk>true</jk> if this class is a subclass of {@link BeanMap}.
1082    *
1083    * @return <jk>true</jk> if this class is a subclass of {@link BeanMap}.
1084    */
1085   public boolean isBeanMap() {
1086      return cc == BEANMAP;
1087   }
1088
1089   /**
1090    * Returns <jk>true</jk> if this class is a subclass of {@link Collection}.
1091    *
1092    * @return <jk>true</jk> if this class is a subclass of {@link Collection}.
1093    */
1094   public boolean isCollection() {
1095      return cc == COLLECTION;
1096   }
1097
1098   /**
1099    * Returns <jk>true</jk> if this class is a subclass of {@link Optional}.
1100    *
1101    * @return <jk>true</jk> if this class is a subclass of {@link Optional}.
1102    */
1103   public boolean isOptional() {
1104      return cc == OPTIONAL;
1105   }
1106
1107   /**
1108    * Returns <jk>true</jk> if this class is a subclass of {@link Collection} or is an array.
1109    *
1110    * @return <jk>true</jk> if this class is a subclass of {@link Collection} or is an array.
1111    */
1112   public boolean isCollectionOrArray() {
1113      return cc == COLLECTION || cc == ARRAY;
1114   }
1115
1116   /**
1117    * Returns <jk>true</jk> if this class is a subclass of {@link Collection} or is an array or {@link Optional}.
1118    *
1119    * @return <jk>true</jk> if this class is a subclass of {@link Collection} or is an array or {@link Optional}.
1120    */
1121   public boolean isCollectionOrArrayOrOptional() {
1122      return cc == COLLECTION || cc == ARRAY || cc == OPTIONAL;
1123   }
1124
1125   /**
1126    * Returns <jk>true</jk> if this class extends from {@link Set}.
1127    *
1128    * @return <jk>true</jk> if this class extends from {@link Set}.
1129    */
1130   public boolean isSet() {
1131      return cc == COLLECTION && info.isChildOf(Set.class);
1132   }
1133
1134   /**
1135    * Returns <jk>true</jk> if this class extends from {@link List}.
1136    *
1137    * @return <jk>true</jk> if this class extends from {@link List}.
1138    */
1139   public boolean isList() {
1140      return cc == COLLECTION && info.isChildOf(List.class);
1141   }
1142
1143   /**
1144    * Returns <jk>true</jk> if this class is <code><jk>byte</jk>[]</code>.
1145    *
1146    * @return <jk>true</jk> if this class is <code><jk>byte</jk>[]</code>.
1147    */
1148   public boolean isByteArray() {
1149      return cc == ARRAY && this.innerClass == byte[].class;
1150   }
1151
1152   /**
1153    * Returns <jk>true</jk> if this class is {@link Class}.
1154    *
1155    * @return <jk>true</jk> if this class is {@link Class}.
1156    */
1157   public boolean isClass() {
1158      return cc == ClassCategory.CLASS;
1159   }
1160
1161   /**
1162    * Returns <jk>true</jk> if this class is {@link Method}.
1163    *
1164    * @return <jk>true</jk> if this class is {@link Method}.
1165    */
1166   public boolean isMethod() {
1167      return cc == METHOD;
1168   }
1169
1170   /**
1171    * Returns <jk>true</jk> if this class is an {@link Enum}.
1172    *
1173    * @return <jk>true</jk> if this class is an {@link Enum}.
1174    */
1175   public boolean isEnum() {
1176      return cc == ENUM;
1177   }
1178
1179   /**
1180    * Returns <jk>true</jk> if this class is an array.
1181    *
1182    * @return <jk>true</jk> if this class is an array.
1183    */
1184   public boolean isArray() {
1185      return cc == ARRAY;
1186   }
1187
1188   /**
1189    * Returns <jk>true</jk> if this class is a bean.
1190    *
1191    * @return <jk>true</jk> if this class is a bean.
1192    */
1193   public boolean isBean() {
1194      return beanMeta != null;
1195   }
1196
1197   /**
1198    * Returns <jk>true</jk> if this class is {@link Object}.
1199    *
1200    * @return <jk>true</jk> if this class is {@link Object}.
1201    */
1202   public boolean isObject() {
1203      return cc == OBJ;
1204   }
1205
1206   /**
1207    * Returns <jk>true</jk> if this class is not {@link Object}.
1208    *
1209    * @return <jk>true</jk> if this class is not {@link Object}.
1210    */
1211   public boolean isNotObject() {
1212      return cc != OBJ;
1213   }
1214
1215   /**
1216    * Returns <jk>true</jk> if this class is a subclass of {@link Number}.
1217    *
1218    * @return <jk>true</jk> if this class is a subclass of {@link Number}.
1219    */
1220   public boolean isNumber() {
1221      return cc == NUMBER || cc == DECIMAL;
1222   }
1223
1224   /**
1225    * Returns <jk>true</jk> if this class is a subclass of {@link Float} or {@link Double}.
1226    *
1227    * @return <jk>true</jk> if this class is a subclass of {@link Float} or {@link Double}.
1228    */
1229   public boolean isDecimal() {
1230      return cc == DECIMAL;
1231   }
1232
1233   /**
1234    * Returns <jk>true</jk> if this class is either {@link Float} or <jk>float</jk>.
1235    *
1236    * @return <jk>true</jk> if this class is either {@link Float} or <jk>float</jk>.
1237    */
1238   public boolean isFloat() {
1239      return innerClass == Float.class || innerClass == float.class;
1240   }
1241
1242   /**
1243    * Returns <jk>true</jk> if this class is either {@link Double} or <jk>double</jk>.
1244    *
1245    * @return <jk>true</jk> if this class is either {@link Double} or <jk>double</jk>.
1246    */
1247   public boolean isDouble() {
1248      return innerClass == Double.class || innerClass == double.class;
1249   }
1250
1251   /**
1252    * Returns <jk>true</jk> if this class is either {@link Short} or <jk>short</jk>.
1253    *
1254    * @return <jk>true</jk> if this class is either {@link Short} or <jk>short</jk>.
1255    */
1256   public boolean isShort() {
1257      return innerClass == Short.class || innerClass == short.class;
1258   }
1259
1260   /**
1261    * Returns <jk>true</jk> if this class is either {@link Integer} or <jk>int</jk>.
1262    *
1263    * @return <jk>true</jk> if this class is either {@link Integer} or <jk>int</jk>.
1264    */
1265   public boolean isInteger() {
1266      return innerClass == Integer.class || innerClass == int.class;
1267   }
1268
1269   /**
1270    * Returns <jk>true</jk> if this class is either {@link Long} or <jk>long</jk>.
1271    *
1272    * @return <jk>true</jk> if this class is either {@link Long} or <jk>long</jk>.
1273    */
1274   public boolean isLong() {
1275      return innerClass == Long.class || innerClass == long.class;
1276   }
1277
1278   /**
1279    * Returns <jk>true</jk> if this metadata represents the specified type.
1280    *
1281    * @param c The class to test against.
1282    * @return <jk>true</jk> if this metadata represents the specified type.
1283    */
1284   public boolean isType(Class<?> c) {
1285      return info.isChildOf(c);
1286   }
1287
1288   /**
1289    * Returns <jk>true</jk> if this class is a {@link Boolean}.
1290    *
1291    * @return <jk>true</jk> if this class is a {@link Boolean}.
1292    */
1293   public boolean isBoolean() {
1294      return cc == BOOLEAN;
1295   }
1296
1297   /**
1298    * Returns <jk>true</jk> if this class is a subclass of {@link CharSequence}.
1299    *
1300    * @return <jk>true</jk> if this class is a subclass of {@link CharSequence}.
1301    */
1302   public boolean isCharSequence() {
1303      return cc == STR || cc == CHARSEQ;
1304   }
1305
1306   /**
1307    * Returns <jk>true</jk> if this class is a {@link String}.
1308    *
1309    * @return <jk>true</jk> if this class is a {@link String}.
1310    */
1311   public boolean isString() {
1312      return cc == STR;
1313   }
1314
1315   /**
1316    * Returns <jk>true</jk> if this class is a {@link Character}.
1317    *
1318    * @return <jk>true</jk> if this class is a {@link Character}.
1319    */
1320   public boolean isChar() {
1321      return cc == CHAR;
1322   }
1323
1324   /**
1325    * Returns <jk>true</jk> if this class is a primitive.
1326    *
1327    * @return <jk>true</jk> if this class is a primitive.
1328    */
1329   public boolean isPrimitive() {
1330      return innerClass.isPrimitive();
1331   }
1332
1333   /**
1334    * Returns <jk>true</jk> if this class is a {@link Date} or {@link Calendar}.
1335    *
1336    * @return <jk>true</jk> if this class is a {@link Date} or {@link Calendar}.
1337    */
1338   public boolean isDateOrCalendar() {
1339      return cc == DATE;
1340   }
1341
1342   /**
1343    * Returns <jk>true</jk> if this class is a {@link Date} or {@link Calendar} or {@link Temporal}.
1344    *
1345    * @return <jk>true</jk> if this class is a {@link Date} or {@link Calendar} or {@link Temporal}.
1346    */
1347   public boolean isDateOrCalendarOrTemporal() {
1348      return cc == DATE || info.isChildOf(Temporal.class);
1349   }
1350
1351   /**
1352    * Returns <jk>true</jk> if this class is a {@link Date}.
1353    *
1354    * @return <jk>true</jk> if this class is a {@link Date}.
1355    */
1356   public boolean isDate() {
1357      return cc == DATE && info.isChildOf(Date.class);
1358   }
1359
1360   /**
1361    * Returns <jk>true</jk> if this class is a {@link Temporal}.
1362    *
1363    * @return <jk>true</jk> if this class is a {@link Temporal}.
1364    */
1365   public boolean isTemporal() {
1366      return info.isChildOf(Temporal.class);
1367   }
1368
1369   /**
1370    * Returns <jk>true</jk> if this class is a {@link Calendar}.
1371    *
1372    * @return <jk>true</jk> if this class is a {@link Calendar}.
1373    */
1374   public boolean isCalendar() {
1375      return cc == DATE && info.isChildOf(Calendar.class);
1376   }
1377
1378   /**
1379    * Returns <jk>true</jk> if this class is a {@link URI} or {@link URL}.
1380    *
1381    * @return <jk>true</jk> if this class is a {@link URI} or {@link URL}.
1382    */
1383   public boolean isUri() {
1384      return cc == URI;
1385   }
1386
1387   /**
1388    * Returns <jk>true</jk> if this class is a {@link Reader}.
1389    *
1390    * @return <jk>true</jk> if this class is a {@link Reader}.
1391    */
1392   public boolean isReader() {
1393      return cc == READER;
1394   }
1395
1396   /**
1397    * Returns <jk>true</jk> if this class is an {@link InputStream}.
1398    *
1399    * @return <jk>true</jk> if this class is an {@link InputStream}.
1400    */
1401   public boolean isInputStream() {
1402      return cc == INPUTSTREAM;
1403   }
1404
1405   /**
1406    * Returns <jk>true</jk> if this class is {@link Void} or <jk>void</jk>.
1407    *
1408    * @return <jk>true</jk> if this class is {@link Void} or <jk>void</jk>.
1409    */
1410   public boolean isVoid() {
1411      return cc == VOID;
1412   }
1413
1414   /**
1415    * Returns <jk>true</jk> if this metadata represents an array of argument types.
1416    *
1417    * @return <jk>true</jk> if this metadata represents an array of argument types.
1418    */
1419   public boolean isArgs() {
1420      return cc == ARGS;
1421   }
1422
1423   /**
1424    * Returns the argument types of this meta.
1425    *
1426    * @return The argument types of this meta, or <jk>null</jk> if this isn't an array of argument types.
1427    */
1428   public ClassMeta<?>[] getArgs() {
1429      return args;
1430   }
1431
1432   /**
1433    * Returns the argument metadata at the specified index if this is an args metadata object.
1434    *
1435    * @param index The argument index.
1436    * @return The The argument metadata.  Never <jk>null</jk>.
1437    * @throws BeanRuntimeException If this metadata object is not a list of arguments, or the index is out of range.
1438    */
1439   public ClassMeta<?> getArg(int index) {
1440      if (args != null && index >= 0 && index < args.length)
1441         return args[index];
1442      throw new BeanRuntimeException("Invalid argument index specified:  {0}.  Only {1} arguments are defined.", index, args == null ? 0 : args.length);
1443   }
1444
1445   /**
1446    * Returns <jk>true</jk> if instance of this object can be <jk>null</jk>.
1447    *
1448    * <p>
1449    * Objects can be <jk>null</jk>, but primitives cannot, except for chars which can be represented by
1450    * <code>(<jk>char</jk>)0</code>.
1451    *
1452    * @return <jk>true</jk> if instance of this class can be null.
1453    */
1454   public boolean isNullable() {
1455      if (innerClass.isPrimitive())
1456         return cc == CHAR;
1457      return true;
1458   }
1459
1460   /**
1461    * Returns <jk>true</jk> if this class is abstract.
1462    *
1463    * @return <jk>true</jk> if this class is abstract.
1464    */
1465   public boolean isAbstract() {
1466      return isAbstract;
1467   }
1468
1469   /**
1470    * Returns <jk>true</jk> if this class is an inner class.
1471    *
1472    * @return <jk>true</jk> if this class is an inner class.
1473    */
1474   public boolean isMemberClass() {
1475      return isMemberClass;
1476   }
1477
1478   /**
1479    * All public methods on this class including static methods.
1480    *
1481    * <p>
1482    * Keys are method signatures.
1483    *
1484    * @return The public methods on this class.
1485    */
1486   public Map<String,Method> getPublicMethods() {
1487      return publicMethods;
1488   }
1489
1490   /**
1491    * Returns the {@link PojoSwap} associated with this class that's the best match for the specified session.
1492    *
1493    * @param session
1494    *    The current bean session.
1495    *    <br>If multiple swaps are associated with a class, only the first one with a matching media type will
1496    *    be returned.
1497    * @return
1498    *    The {@link PojoSwap} associated with this class, or <jk>null</jk> if there are no POJO swaps associated with
1499    *    this class.
1500    */
1501   public PojoSwap<T,?> getSwap(BeanSession session) {
1502      if (swaps != null) {
1503         int matchQuant = 0, matchIndex = -1;
1504
1505         for (int i = 0; i < swaps.length; i++) {
1506            int q = swaps[i].match(session);
1507            if (q > matchQuant) {
1508               matchQuant = q;
1509               matchIndex = i;
1510            }
1511         }
1512
1513         if (matchIndex > -1)
1514            return swaps[matchIndex];
1515      }
1516      return null;
1517   }
1518
1519   /**
1520    * Returns the builder swap associated with this class.
1521    *
1522    * @param session The current bean session.
1523    * @return The builder swap associated with this class, or <jk>null</jk> if it doesn't exist.
1524    */
1525   public BuilderSwap<T,?> getBuilderSwap(BeanSession session) {
1526      return builderSwap;
1527   }
1528
1529   /**
1530    * Returns the {@link BeanMeta} associated with this class.
1531    *
1532    * @return
1533    *    The {@link BeanMeta} associated with this class, or <jk>null</jk> if there is no bean meta associated with
1534    *    this class.
1535    */
1536   public BeanMeta<T> getBeanMeta() {
1537      return beanMeta;
1538   }
1539
1540   /**
1541    * Returns the no-arg constructor for this class.
1542    *
1543    * @return The no-arg constructor for this class, or <jk>null</jk> if it does not exist.
1544    */
1545   public ConstructorInfo getConstructor() {
1546      return noArgConstructor;
1547   }
1548
1549   /**
1550    * Returns the interface proxy invocation handler for this class.
1551    *
1552    * @return The interface proxy invocation handler, or <jk>null</jk> if it does not exist.
1553    */
1554   public InvocationHandler getProxyInvocationHandler() {
1555      return invocationHandler;
1556   }
1557
1558   /**
1559    * Returns <jk>true</jk> if this class has a no-arg constructor or invocation handler.
1560    *
1561    * @return <jk>true</jk> if a new instance of this class can be constructed.
1562    */
1563   public boolean canCreateNewInstance() {
1564      if (isMemberClass)
1565         return false;
1566      if (noArgConstructor != null)
1567         return true;
1568      if (getProxyInvocationHandler() != null)
1569         return true;
1570      if (isArray() && elementType.canCreateNewInstance())
1571         return true;
1572      return false;
1573   }
1574
1575   /**
1576    * Returns <jk>true</jk> if this class has a no-arg constructor or invocation handler.
1577    * Returns <jk>false</jk> if this is a non-static member class and the outer object does not match the class type of
1578    * the defining class.
1579    *
1580    * @param outer
1581    *    The outer class object for non-static member classes.  Can be <jk>null</jk> for non-member or static classes.
1582    * @return
1583    *    <jk>true</jk> if a new instance of this class can be created within the context of the specified outer object.
1584    */
1585   public boolean canCreateNewInstance(Object outer) {
1586      if (isMemberClass)
1587         return outer != null && noArgConstructor != null && noArgConstructor.hasParamTypes(outer.getClass());
1588      return canCreateNewInstance();
1589   }
1590
1591   /**
1592    * Returns <jk>true</jk> if this class can be instantiated as a bean.
1593    * Returns <jk>false</jk> if this is a non-static member class and the outer object does not match the class type of
1594    * the defining class.
1595    *
1596    * @param outer
1597    *    The outer class object for non-static member classes.  Can be <jk>null</jk> for non-member or static classes.
1598    * @return
1599    *    <jk>true</jk> if a new instance of this bean can be created within the context of the specified outer object.
1600    */
1601   public boolean canCreateNewBean(Object outer) {
1602      if (beanMeta == null)
1603         return false;
1604      if (beanMeta.constructor == null)
1605         return false;
1606      if (isMemberClass)
1607         return outer != null && beanMeta.constructor.hasParamTypes(outer.getClass());
1608      return true;
1609   }
1610
1611   /**
1612    * Returns <jk>true</jk> if this class can call the {@link #newInstanceFromString(Object, String)} method.
1613    *
1614    * @param outer
1615    *    The outer class object for non-static member classes.
1616    *    Can be <jk>null</jk> for non-member or static classes.
1617    * @return <jk>true</jk> if this class has a no-arg constructor or invocation handler.
1618    */
1619   public boolean canCreateNewInstanceFromString(Object outer) {
1620      if (fromStringMethod != null)
1621         return true;
1622      if (stringConstructor != null) {
1623         if (isMemberClass)
1624            return outer != null && stringConstructor.hasParamTypes(outer.getClass(), String.class);
1625         return true;
1626      }
1627      return false;
1628   }
1629
1630   /**
1631    * Returns the method or field annotated with {@link NameProperty @NameProperty}.
1632    *
1633    * @return
1634    *    The method or field  annotated with {@link NameProperty @NameProperty} or <jk>null</jk> if method does not
1635    *    exist.
1636    */
1637   public Setter getNameProperty() {
1638      return namePropertyMethod;
1639   }
1640
1641   /**
1642    * Returns the method or field annotated with {@link ParentProperty @ParentProperty}.
1643    *
1644    * @return
1645    *    The method or field annotated with {@link ParentProperty @ParentProperty} or <jk>null</jk> if method does not
1646    *    exist.
1647    */
1648   public Setter getParentProperty() {
1649      return parentPropertyMethod;
1650   }
1651
1652   /**
1653    * Returns the reason why this class is not a bean, or <jk>null</jk> if it is a bean.
1654    *
1655    * @return The reason why this class is not a bean, or <jk>null</jk> if it is a bean.
1656    */
1657   public synchronized String getNotABeanReason() {
1658      return notABeanReason;
1659   }
1660
1661   /**
1662    * Returns any exception that was throw in the <c>init()</c> method.
1663    *
1664    * @return The cached exception.
1665    */
1666   public Throwable getInitException() {
1667      return initException;
1668   }
1669
1670   /**
1671    * Returns the {@link BeanContext} that created this object.
1672    *
1673    * @return The bean context.
1674    */
1675   public BeanContext getBeanContext() {
1676      return beanContext;
1677   }
1678
1679   /**
1680    * Returns the default value for primitives such as <jk>int</jk> or <jk>Integer</jk>.
1681    *
1682    * @return The default value, or <jk>null</jk> if this class type is not a primitive.
1683    */
1684   @SuppressWarnings("unchecked")
1685   public T getPrimitiveDefault() {
1686      return (T)primitiveDefault;
1687   }
1688
1689   /**
1690    * If this is an {@link Optional}, returns an empty optional.
1691    *
1692    * <p>
1693    * Note that if this is a nested optional, will recursively create empty optionals.
1694    *
1695    * @return An empty optional, or <jk>null</jk> if this isn't an optional.
1696    */
1697   public Optional<?> getOptionalDefault() {
1698      if (isOptional())
1699         return Optional.ofNullable(getElementType().getOptionalDefault());
1700      return null;
1701   }
1702
1703   /**
1704    * Converts the specified object to a string.
1705    *
1706    * @param t The object to convert.
1707    * @return The object converted to a string, or <jk>null</jk> if the object was null.
1708    */
1709   public String toString(Object t) {
1710      if (t == null)
1711         return null;
1712      if (isEnum() && beanContext.isUseEnumNames())
1713         return ((Enum<?>)t).name();
1714      return t.toString();
1715   }
1716
1717   /**
1718    * Create a new instance of the main class of this declared type from a <c>String</c> input.
1719    *
1720    * <p>
1721    * In order to use this method, the class must have one of the following methods:
1722    * <ul>
1723    *    <li><code><jk>public static</jk> T valueOf(String in);</code>
1724    *    <li><code><jk>public static</jk> T fromString(String in);</code>
1725    *    <li><code><jk>public</jk> T(String in);</code>
1726    * </ul>
1727    *
1728    * @param outer
1729    *    The outer class object for non-static member classes.  Can be <jk>null</jk> for non-member or static classes.
1730    * @param arg The input argument value.
1731    * @return A new instance of the object, or <jk>null</jk> if there is no string constructor on the object.
1732    * @throws ExecutableException Exception occurred on invoked constructor/method/field.
1733    */
1734   @SuppressWarnings({ "unchecked", "rawtypes" })
1735   public T newInstanceFromString(Object outer, String arg) throws ExecutableException {
1736
1737      if (isEnum() && beanContext.isUseEnumNames() && fromStringMethod != null)
1738         return (T)Enum.valueOf((Class<? extends Enum>)this.innerClass, arg);
1739
1740      Method m = fromStringMethod;
1741      if (m != null) {
1742         try {
1743            return (T)m.invoke(null, arg);
1744         } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
1745            throw new ExecutableException(e);
1746         }
1747      }
1748      ConstructorInfo c = stringConstructor;
1749      if (c != null) {
1750         if (isMemberClass)
1751            return c.<T>invoke(outer, arg);
1752         return c.<T>invoke(arg);
1753      }
1754      throw new InstantiationError("No string constructor or valueOf(String) method found for class '"+getInnerClass().getName()+"'");
1755   }
1756
1757   /**
1758    * Create a new instance of the main class of this declared type.
1759    *
1760    * @return A new instance of the object, or <jk>null</jk> if there is no no-arg constructor on the object.
1761    * @throws ExecutableException Exception occurred on invoked constructor/method/field.
1762    */
1763   @SuppressWarnings("unchecked")
1764   public T newInstance() throws ExecutableException {
1765      if (isArray())
1766         return (T)Array.newInstance(getInnerClass().getComponentType(), 0);
1767      ConstructorInfo c = getConstructor();
1768      if (c != null)
1769         return c.<T>invoke((Object[])null);
1770      InvocationHandler h = getProxyInvocationHandler();
1771      if (h != null)
1772         return (T)Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] { getInnerClass(), java.io.Serializable.class }, h);
1773      if (isArray())
1774         return (T)Array.newInstance(this.elementType.innerClass,0);
1775      return null;
1776   }
1777
1778   /**
1779    * Same as {@link #newInstance()} except for instantiating non-static member classes.
1780    *
1781    * @param outer
1782    *    The instance of the owning object of the member class instance.
1783    *    Can be <jk>null</jk> if instantiating a non-member or static class.
1784    * @return A new instance of the object, or <jk>null</jk> if there is no no-arg constructor on the object.
1785    * @throws ExecutableException Exception occurred on invoked constructor/method/field.
1786    */
1787   public T newInstance(Object outer) throws ExecutableException {
1788      if (isMemberClass)
1789         return noArgConstructor.<T>invoke(outer);
1790      return newInstance();
1791   }
1792
1793   /**
1794    * Similar to {@link #equals(Object)} except primitive and Object types that are similar are considered the same.
1795    * (e.g. <jk>boolean</jk> == <c>Boolean</c>).
1796    *
1797    * @param cm The class meta to compare to.
1798    * @return <jk>true</jk> if the specified class-meta is equivalent to this one.
1799    */
1800   public boolean same(ClassMeta<?> cm) {
1801      if (equals(cm))
1802         return true;
1803      return (isPrimitive() && cc == cm.cc);
1804   }
1805
1806   @Override /* Object */
1807   public String toString() {
1808      return toString(false);
1809   }
1810
1811   /**
1812    * Same as {@link #toString()} except use simple class names.
1813    *
1814    * @param simple Print simple class names only (no package).
1815    * @return A new string.
1816    */
1817   public String toString(boolean simple) {
1818      return toString(new StringBuilder(), simple).toString();
1819   }
1820
1821   /**
1822    * Appends this object as a readable string to the specified string builder.
1823    *
1824    * @param sb The string builder to append this object to.
1825    * @param simple Print simple class names only (no package).
1826    * @return The same string builder passed in (for method chaining).
1827    */
1828   protected StringBuilder toString(StringBuilder sb, boolean simple) {
1829      String n = innerClass.getName();
1830      if (simple) {
1831         int i = n.lastIndexOf('.');
1832         n = n.substring(i == -1 ? 0 : i+1).replace('$', '.');
1833      }
1834      if (cc == ARRAY)
1835         return elementType.toString(sb, simple).append('[').append(']');
1836      if (cc == MAP)
1837         return sb.append(n).append(keyType.isObject() && valueType.isObject() ? "" : "<"+keyType.toString(simple)+","+valueType.toString(simple)+">");
1838      if (cc == BEANMAP)
1839         return sb.append(BeanMap.class.getName()).append('<').append(n).append('>');
1840      if (cc == COLLECTION || cc == OPTIONAL)
1841         return sb.append(n).append(elementType.isObject() ? "" : "<"+elementType.toString(simple)+">");
1842      return sb.append(n);
1843   }
1844
1845   /**
1846    * Returns <jk>true</jk> if the specified object is an instance of this class.
1847    *
1848    * <p>
1849    * This is a simple comparison on the base class itself and not on any generic parameters.
1850    *
1851    * @param o The object to check.
1852    * @return <jk>true</jk> if the specified object is an instance of this class.
1853    */
1854   public boolean isInstance(Object o) {
1855      if (o != null)
1856         return info.isParentOf(o.getClass()) || (isPrimitive() && info.getPrimitiveWrapper() == o.getClass());
1857      return false;
1858   }
1859
1860   /**
1861    * Returns a readable name for this class (e.g. <js>"java.lang.String"</js>, <js>"boolean[]"</js>).
1862    *
1863    * @return The readable name for this class.
1864    */
1865   public String getFullName() {
1866      return info.getFullName();
1867   }
1868
1869   /**
1870    * Shortcut for calling {@link Class#getName()} on the inner class of this metadata.
1871    *
1872    * @return The  name of the inner class.
1873    */
1874   public String getName() {
1875      return innerClass.getName();
1876   }
1877
1878   /**
1879    * Shortcut for calling {@link Class#getSimpleName()} on the inner class of this metadata.
1880    *
1881    * @return The simple name of the inner class.
1882    */
1883   public String getSimpleName() {
1884      return innerClass.getSimpleName();
1885   }
1886
1887   /**
1888    * Returns <jk>true</jk> if this class has a transform associated with it that allows it to be created from a Reader.
1889    *
1890    * @return <jk>true</jk> if this class has a transform associated with it that allows it to be created from a Reader.
1891    */
1892   public boolean hasReaderMutater() {
1893      return hasMutaterFrom(Reader.class);
1894   }
1895
1896   /**
1897    * Returns the transform for this class for creating instances from a Reader.
1898    *
1899    * @return The transform, or <jk>null</jk> if no such transform exists.
1900    */
1901   public Mutater<Reader,T> getReaderMutater() {
1902      return getFromMutater(Reader.class);
1903   }
1904
1905   /**
1906    * Returns <jk>true</jk> if this class has a transform associated with it that allows it to be created from an InputStream.
1907    *
1908    * @return <jk>true</jk> if this class has a transform associated with it that allows it to be created from an InputStream.
1909    */
1910   public boolean hasInputStreamMutater() {
1911      return hasMutaterFrom(InputStream.class);
1912   }
1913
1914   /**
1915    * Returns the transform for this class for creating instances from an InputStream.
1916    *
1917    * @return The transform, or <jk>null</jk> if no such transform exists.
1918    */
1919   public Mutater<InputStream,T> getInputStreamMutater() {
1920      return getFromMutater(InputStream.class);
1921   }
1922
1923   /**
1924    * Returns <jk>true</jk> if this class has a transform associated with it that allows it to be created from a String.
1925    *
1926    * @return <jk>true</jk> if this class has a transform associated with it that allows it to be created from a String.
1927    */
1928   public boolean hasStringMutater() {
1929      return stringMutater != null;
1930   }
1931
1932   /**
1933    * Returns the transform for this class for creating instances from a String.
1934    *
1935    * @return The transform, or <jk>null</jk> if no such transform exists.
1936    */
1937   public Mutater<String,T> getStringMutater() {
1938      return stringMutater;
1939   }
1940
1941   /**
1942    * Returns <jk>true</jk> if this class can be instantiated from the specified type.
1943    *
1944    * @param c The class type to convert from.
1945    * @return <jk>true</jk> if this class can be instantiated from the specified type.
1946    */
1947   public boolean hasMutaterFrom(Class<?> c) {
1948      return getFromMutater(c) != null;
1949   }
1950
1951   /**
1952    * Returns <jk>true</jk> if this class can be instantiated from the specified type.
1953    *
1954    * @param c The class type to convert from.
1955    * @return <jk>true</jk> if this class can be instantiated from the specified type.
1956    */
1957   public boolean hasMutaterFrom(ClassMeta<?> c) {
1958      return getFromMutater(c.getInnerClass()) != null;
1959   }
1960
1961   /**
1962    * Returns <jk>true</jk> if this class can be transformed to the specified type.
1963    *
1964    * @param c The class type to convert from.
1965    * @return <jk>true</jk> if this class can be transformed to the specified type.
1966    */
1967   public boolean hasMutaterTo(Class<?> c) {
1968      return getToMutater(c) != null;
1969   }
1970
1971   /**
1972    * Returns <jk>true</jk> if this class can be transformed to the specified type.
1973    *
1974    * @param c The class type to convert from.
1975    * @return <jk>true</jk> if this class can be transformed to the specified type.
1976    */
1977   public boolean hasMutaterTo(ClassMeta<?> c) {
1978      return getToMutater(c.getInnerClass()) != null;
1979   }
1980
1981   /**
1982    * Transforms the specified object into an instance of this class.
1983    *
1984    * @param o The object to transform.
1985    * @return The transformed object.
1986    */
1987   @SuppressWarnings({"unchecked","rawtypes"})
1988   public T mutateFrom(Object o) {
1989      Mutater t = getFromMutater(o.getClass());
1990      return (T)(t == null ? null : t.mutate(o));
1991   }
1992
1993   /**
1994    * Transforms the specified object into an instance of this class.
1995    *
1996    * @param o The object to transform.
1997    * @param c The class
1998    * @return The transformed object.
1999    */
2000   @SuppressWarnings({"unchecked","rawtypes"})
2001   public <O> O mutateTo(Object o, Class<O> c) {
2002      Mutater t = getToMutater(c);
2003      return (O)(t == null ? null : t.mutate(o));
2004   }
2005
2006   /**
2007    * Transforms the specified object into an instance of this class.
2008    *
2009    * @param o The object to transform.
2010    * @param c The class
2011    * @return The transformed object.
2012    */
2013   public <O> O mutateTo(Object o, ClassMeta<O> c) {
2014      return mutateTo(o, c.getInnerClass());
2015   }
2016
2017   /**
2018    * Returns the transform for this class for creating instances from other object types.
2019    *
2020    * @param c The transform-from class.
2021    * @return The transform, or <jk>null</jk> if no such transform exists.
2022    */
2023   @SuppressWarnings({ "rawtypes", "unchecked" })
2024   public <I> Mutater<I,T> getFromMutater(Class<I> c) {
2025      Mutater t = fromMutaters.get(c);
2026      if (t == Mutaters.NULL)
2027         return null;
2028      if (t == null) {
2029         t = Mutaters.get(c, innerClass);
2030         if (t == null)
2031            t = Mutaters.NULL;
2032         fromMutaters.put(c, t);
2033      }
2034      return t == Mutaters.NULL ? null : t;
2035   }
2036
2037   /**
2038    * Returns the transform for this class for creating instances from other object types.
2039    *
2040    * @param c The transform-from class.
2041    * @return The transform, or <jk>null</jk> if no such transform exists.
2042    */
2043   @SuppressWarnings({ "rawtypes", "unchecked" })
2044   public <O> Mutater<T,O> getToMutater(Class<O> c) {
2045      Mutater t = toMutaters.get(c);
2046      if (t == Mutaters.NULL)
2047         return null;
2048      if (t == null) {
2049         t = Mutaters.get(innerClass, c);
2050         if (t == null)
2051            t = Mutaters.NULL;
2052         toMutaters.put(c, t);
2053      }
2054      return t == Mutaters.NULL ? null : t;
2055   }
2056
2057   /**
2058    * Shortcut for calling <code>getInnerClass().getAnnotation(a) != <jk>null</jk></code>.
2059    *
2060    * @param a The annotation to check for.
2061    * @return <jk>true</jk> if the inner class has the annotation.
2062    */
2063   public boolean hasAnnotation(Class<? extends Annotation> a) {
2064      return getLastAnnotation(a) != null;
2065   }
2066
2067   /**
2068    * Shortcut for calling <c>getInnerClass().getAnnotation(a)</c>.
2069    *
2070    * @param a The annotation to retrieve.
2071    * @return The specified annotation, or <jk>null</jk> if the class does not have the specified annotation.
2072    */
2073   public <A extends Annotation> A getLastAnnotation(Class<A> a) {
2074      return info.getLastAnnotation(a, beanContext == null ? BeanContext.DEFAULT : beanContext);
2075   }
2076
2077   /**
2078    * Returns all annotations of the specified type defined on the specified class or parent classes/interfaces in parent-to-child order.
2079    *
2080    * @param a
2081    *    The annotation to search for.
2082    * @return
2083    *    A list of all matching annotations found or an empty list if none found.
2084    */
2085   public <A extends Annotation> List<A> getAnnotations(Class<A> a) {
2086      return info.getAnnotations(a, beanContext == null ? BeanContext.DEFAULT : beanContext);
2087   }
2088
2089   @Override /* Object */
2090   public int hashCode() {
2091      return innerClass.hashCode();
2092   }
2093
2094   @Override /* Object */
2095   public boolean equals(Object o) {
2096      return (o instanceof ClassMeta) && eq(this, (ClassMeta<?>)o, (x,y)->eq(x.innerClass, y.innerClass));
2097   }
2098}