// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
// * with the License.  You may obtain a copy of the License at                                                              *
// *                                                                                                                         *
// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
// *                                                                                                                         *
// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
// * specific language governing permissions and limitations under the License.                                              *
// ***************************************************************************************************************************
package org.apache.juneau;

import static org.apache.juneau.ClassMeta.ClassCategory.*;
import static org.apache.juneau.common.internal.ThrowableUtils.*;
import static org.apache.juneau.internal.CollectionUtils.*;
import static org.apache.juneau.internal.ConsumerUtils.*;
import static org.apache.juneau.internal.ObjectUtils.*;
import static java.util.Arrays.*;

import java.io.*;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.lang.reflect.Proxy;
import java.net.*;
import java.net.URI;
import java.time.temporal.*;
import java.util.*;
import java.util.Date;
import java.util.concurrent.*;
import java.util.function.*;

import org.apache.juneau.annotation.*;
import org.apache.juneau.cp.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.json.*;
import org.apache.juneau.reflect.*;
import org.apache.juneau.swap.*;

/**
 * A wrapper class around the {@link Class} object that provides cached information about that class.
 *
 * <p>
 * Instances of this class can be created through the {@link BeanContext#getClassMeta(Class)} method.
 *
 * <p>
 * The {@link BeanContext} class will cache and reuse instances of this class except for the following class types:
 * <ul>
 * 	<li>Arrays
 * 	<li>Maps with non-Object key/values.
 * 	<li>Collections with non-Object key/values.
 * </ul>
 *
 * <p>
 * This class is tied to the {@link BeanContext} class because it's that class that makes the determination of what is
 * a bean.
 *
 * <h5 class='section'>See Also:</h5><ul>
 * </ul>
 *
 * @param <T> The class type of the wrapped class.
 */
@Bean(properties="innerClass,classCategory,elementType,keyType,valueType,notABeanReason,initException,beanMeta")
public final class ClassMeta<T> implements Type {

	/** Class categories. */
	enum ClassCategory {
		MAP, COLLECTION, CLASS, METHOD, NUMBER, DECIMAL, BOOLEAN, CHAR, DATE, ARRAY, ENUM, OTHER, CHARSEQ, STR, OBJ, URI, BEANMAP, READER, INPUTSTREAM, VOID, ARGS, OPTIONAL
	}

	final Class<T> innerClass;                              // The class being wrapped.
	final ClassInfo info;

	private final Class<? extends T> implClass;             // The implementation class to use if this is an interface.
	private final ClassCategory cc;                         // The class category.
	private final Method fromStringMethod;                  // The static valueOf(String) or fromString(String) or forString(String) method (if it has one).
	private final ConstructorInfo
		noArgConstructor,                                    // The no-arg constructor for this class (if it has one).
		stringConstructor;                                   // The X(String) constructor (if it has one).
	private final Method
		exampleMethod;                                       // The example() or @Example-annotated method (if it has one).
	private final Field
		exampleField;                                        // The @Example-annotated field (if it has one).
	private final Setter
		namePropertyMethod,                                  // The method to set the name on an object (if it has one).
		parentPropertyMethod;                                // The method to set the parent on an object (if it has one).
	private final boolean
		isDelegate,                                          // True if this class extends Delegate.
		isAbstract,                                          // True if this class is abstract.
		isMemberClass;                                       // True if this is a non-static member class.
	private final Object primitiveDefault;                  // Default value for primitive type classes.
	private final Map<String,Method>
		publicMethods;                                       // All public methods, including static methods.
	private final ObjectSwap<?,?>[] childSwaps;              // Any ObjectSwaps where the normal type is a subclass of this class.
	private final ConcurrentHashMap<Class<?>,ObjectSwap<?,?>>
		childSwapMap,                                        // Maps normal subclasses to ObjectSwaps.
		childUnswapMap;                                      // Maps swap subclasses to ObjectSwaps.
	private final ObjectSwap<T,?>[] swaps;                     // The object POJO swaps associated with this bean (if it has any).
	private final BuilderSwap<T,?> builderSwap;             // The builder swap associated with this bean (if it has one).
	private final BeanContext beanContext;                  // The bean context that created this object.
	private final ClassMeta<?>
		elementType,                                         // If ARRAY or COLLECTION, the element class type.
		keyType,                                             // If MAP, the key class type.
		valueType;                                           // If MAP, the value class type.
	private final BeanMeta<T> beanMeta;                     // The bean meta for this bean class (if it's a bean).
	private final String
		typePropertyName,                                    // The property name of the _type property for this class and subclasses.
		notABeanReason,                                      // If this isn't a bean, the reason why.
		dictionaryName;                                      // The dictionary name of this class if it has one.
	private final Throwable initException;                  // Any exceptions thrown in the init() method.
	private final InvocationHandler invocationHandler;      // The invocation handler for this class (if it has one).
	private final BeanRegistry beanRegistry;                // The bean registry of this class meta (if it has one).
	private final ClassMeta<?>[] args;                      // Arg types if this is an array of args.
	private final String example;                           // Example JSON.
	private final Map<Class<?>,Mutater<?,T>> fromMutaters = new ConcurrentHashMap<>();
	private final Map<Class<?>,Mutater<T,?>> toMutaters = new ConcurrentHashMap<>();
	private final Mutater<String,T> stringMutater;
	private final Map<Class<?>,Annotation[]> annotationArrayMap = new ConcurrentHashMap<>();
	private final Map<Class<?>,Optional<?>> annotationLastMap = new ConcurrentHashMap<>();
	private final Map<String,Optional<?>> properties = new ConcurrentHashMap<>();
	private final BiMap<Object,String> enumValues;

	private final SimpleReadWriteLock lock = new SimpleReadWriteLock(false);

	/**
	 * Construct a new {@code ClassMeta} based on the specified {@link Class}.
	 *
	 * @param innerClass The class being wrapped.
	 * @param beanContext The bean context that created this object.
	 * @param implClass
	 * 	For interfaces and abstract classes, this represents the "real" class to instantiate.
	 * 	Can be <jk>null</jk>.
	 * @param swaps
	 * 	The {@link ObjectSwap} programmatically associated with this class.
	 * 	Can be <jk>null</jk>.
	 * @param childSwaps
	 * 	The child {@link ObjectSwap ObjectSwaps} programmatically associated with this class.
	 * 	These are the <c>ObjectSwaps</c> that have normal classes that are subclasses of this class.
	 * 	Can be <jk>null</jk>.
	 * @param delayedInit
	 * 	Don't call init() in constructor.
	 * 	Used for delayed initialization when the possibility of class reference loops exist.
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	ClassMeta(Class<T> innerClass, BeanContext beanContext, ObjectSwap<T,?>[] swaps, ObjectSwap<?,?>[] childSwaps) {
		this.innerClass = innerClass;
		this.info = ClassInfo.of(innerClass);
		this.beanContext = beanContext;
		String notABeanReason = null;

		try (SimpleLock x = lock.write()) {
			// We always immediately add this class meta to the bean context cache so that we can resolve recursive references.
			if (beanContext != null && beanContext.cmCache != null && isCacheable(innerClass))
				beanContext.cmCache.put(innerClass, this);

			ClassMetaBuilder<T> builder = new ClassMetaBuilder(innerClass, beanContext, swaps, childSwaps);

			this.cc = builder.cc;
			this.isDelegate = builder.isDelegate;
			this.fromStringMethod = builder.fromStringMethod;
			this.parentPropertyMethod = builder.parentPropertyMethod;
			this.namePropertyMethod = builder.namePropertyMethod;
			this.noArgConstructor = builder.noArgConstructor;
			this.stringConstructor = builder.stringConstructor;
			this.primitiveDefault = builder.primitiveDefault;
			this.publicMethods = builder.publicMethods;
			this.swaps = builder.swaps.isEmpty() ? null : builder.swaps.toArray(new ObjectSwap[builder.swaps.size()]);
			this.builderSwap = builder.builderSwap;
			this.keyType = builder.keyType;
			this.valueType = builder.valueType;
			this.elementType = builder.elementType;
			notABeanReason = builder.notABeanReason;
			this.beanMeta = builder.beanMeta;
			this.initException = builder.initException;
			this.typePropertyName = builder.typePropertyName;
			this.dictionaryName = builder.dictionaryName;
			this.invocationHandler = builder.invocationHandler;
			this.beanRegistry = builder.beanRegistry;
			this.isMemberClass = builder.isMemberClass;
			this.isAbstract = builder.isAbstract;
			this.implClass = builder.implClass;
			this.childUnswapMap = builder.childUnswapMap;
			this.childSwapMap = builder.childSwapMap;
			this.childSwaps = builder.childSwaps;
			this.exampleMethod = builder.exampleMethod;
			this.exampleField = builder.exampleField;
			this.example = builder.example;
			this.args = null;
			this.stringMutater = builder.stringMutater;
			this.enumValues = builder.enumValues == null ? null : builder.enumValues.build();
		} catch (ClassMetaRuntimeException e) {
			notABeanReason = e.getMessage();
			throw e;
		} finally {
			this.notABeanReason = notABeanReason;
		}
	}

	/**
	 * Generated classes shouldn't be cacheable to prevent needlessly filling up the cache.
	 */
	private static boolean isCacheable(Class<?> c) {
		String n = c.getName();
		char x = n.charAt(n.length()-1);  // All generated classes appear to end with digits.
		if (x >= '0' && x <= '9') {
			if (n.indexOf("$$") != -1 || n.startsWith("sun") || n.startsWith("com.sun") || n.indexOf("$Proxy") != -1)
				return false;
		}
		return true;
	}

	/**
	 * Causes thread to wait until constructor has exited.
	 */
	void waitForInit() {
		try (SimpleLock x = lock.read()) {}
	}

	/**
	 * Copy constructor.
	 *
	 * <p>
	 * Used for creating Map and Collection class metas that shouldn't be cached.
	 */
	ClassMeta(ClassMeta<T> mainType, ClassMeta<?> keyType, ClassMeta<?> valueType, ClassMeta<?> elementType) {
		this.innerClass = mainType.innerClass;
		this.info = mainType.info;
		this.implClass = mainType.implClass;
		this.childSwaps = mainType.childSwaps;
		this.childSwapMap = mainType.childSwapMap;
		this.childUnswapMap = mainType.childUnswapMap;
		this.cc = mainType.cc;
		this.fromStringMethod = mainType.fromStringMethod;
		this.noArgConstructor = mainType.noArgConstructor;
		this.stringConstructor = mainType.stringConstructor;
		this.namePropertyMethod = mainType.namePropertyMethod;
		this.parentPropertyMethod = mainType.parentPropertyMethod;
		this.isDelegate = mainType.isDelegate;
		this.isAbstract = mainType.isAbstract;
		this.isMemberClass = mainType.isMemberClass;
		this.primitiveDefault = mainType.primitiveDefault;
		this.publicMethods = mainType.publicMethods;
		this.beanContext = mainType.beanContext;
		this.elementType = elementType;
		this.keyType = keyType;
		this.valueType = valueType;
		this.invocationHandler = mainType.invocationHandler;
		this.beanMeta = mainType.beanMeta;
		this.typePropertyName = mainType.typePropertyName;
		this.dictionaryName = mainType.dictionaryName;
		this.notABeanReason = mainType.notABeanReason;
		this.swaps = mainType.swaps;
		this.builderSwap = mainType.builderSwap;
		this.initException = mainType.initException;
		this.beanRegistry = mainType.beanRegistry;
		this.exampleMethod = mainType.exampleMethod;
		this.exampleField = mainType.exampleField;
		this.example = mainType.example;
		this.args = null;
		this.stringMutater = mainType.stringMutater;
		this.enumValues = mainType.enumValues;
	}

	/**
	 * Constructor for args-arrays.
	 */
	@SuppressWarnings("unchecked")
	ClassMeta(ClassMeta<?>[] args) {
		this.innerClass = (Class<T>) Object[].class;
		this.info = ClassInfo.of(innerClass);
		this.args = args;
		this.implClass = null;
		this.childSwaps = null;
		this.childSwapMap = null;
		this.childUnswapMap = null;
		this.cc = ARGS;
		this.fromStringMethod = null;
		this.noArgConstructor = null;
		this.stringConstructor = null;
		this.namePropertyMethod = null;
		this.parentPropertyMethod = null;
		this.isDelegate = false;
		this.isAbstract = false;
		this.isMemberClass = false;
		this.primitiveDefault = null;
		this.publicMethods = null;
		this.beanContext = null;
		this.elementType = null;
		this.keyType = null;
		this.valueType = null;
		this.invocationHandler = null;
		this.beanMeta = null;
		this.typePropertyName = null;
		this.dictionaryName = null;
		this.notABeanReason = null;
		this.swaps = null;
		this.builderSwap = null;
		this.initException = null;
		this.beanRegistry = null;
		this.exampleMethod = null;
		this.exampleField = null;
		this.example = null;
		this.stringMutater = null;
		this.enumValues = null;
	}

	@SuppressWarnings({"unchecked","rawtypes","hiding"})
	private final class ClassMetaBuilder<T> {
		Class<T> innerClass;
		ClassInfo ci;
		Class<? extends T> implClass;
		BeanContext beanContext;
		ClassCategory cc = ClassCategory.OTHER;
		boolean
			isDelegate = false,
			isMemberClass = false,
			isAbstract = false;
		Method
			fromStringMethod = null;
		Setter
			parentPropertyMethod = null,
			namePropertyMethod = null;
		ConstructorInfo
			noArgConstructor = null,
			stringConstructor = null;
		Object primitiveDefault = null;
		Map<String,Method>
			publicMethods = map();
		ClassMeta<?>
			keyType = null,
			valueType = null,
			elementType = null;
		String
			typePropertyName = null,
			notABeanReason = null,
			dictionaryName = null;
		Throwable initException = null;
		BeanMeta beanMeta = null;
		List<ObjectSwap> swaps = list();
		BuilderSwap builderSwap;
		InvocationHandler invocationHandler = null;
		BeanRegistry beanRegistry = null;
		ObjectSwap<?,?>[] childSwaps;
		ConcurrentHashMap<Class<?>,ObjectSwap<?,?>>
			childSwapMap,
			childUnswapMap;
		Method exampleMethod;
		Field exampleField;
		String example;
		Mutater<String,T> stringMutater;
		BiMap.Builder<Object,String> enumValues;

		ClassMetaBuilder(Class<T> innerClass, BeanContext beanContext, ObjectSwap<T,?>[] swaps, ObjectSwap<?,?>[] childSwaps) {
			this.innerClass = innerClass;
			this.beanContext = beanContext;
			BeanContext bc = beanContext;

			this.childSwaps = childSwaps;
			if (childSwaps == null) {
				this.childSwapMap = null;
				this.childUnswapMap = null;
			} else {
				this.childSwapMap = new ConcurrentHashMap<>();
				this.childUnswapMap = new ConcurrentHashMap<>();
			}

			Class<T> c = innerClass;
			ci = ClassInfo.of(c);

			if (c.isPrimitive()) {
				if (c == Boolean.TYPE)
					cc = BOOLEAN;
				else if (c == Byte.TYPE || c == Short.TYPE || c == Integer.TYPE || c == Long.TYPE || c == Float.TYPE || c == Double.TYPE) {
					if (c == Float.TYPE || c == Double.TYPE)
						cc = DECIMAL;
					else
						cc = NUMBER;
				}
				else if (c == Character.TYPE)
					cc = CHAR;
				else if (c == void.class || c == Void.class)
					cc = VOID;
			} else {
				if (ci.isChildOf(Delegate.class))
					isDelegate = true;

				if (c == Object.class)
					cc = OBJ;
				else if (c.isEnum())
					cc = ENUM;
				else if (c.equals(Class.class))
					cc = ClassCategory.CLASS;
				else if (ci.isChildOf(Method.class))
					cc = METHOD;
				else if (ci.isChildOf(CharSequence.class)) {
					if (c.equals(String.class))
						cc = STR;
					else
						cc = CHARSEQ;
				}
				else if (ci.isChildOf(Number.class)) {
					if (ci.isChildOfAny(Float.class, Double.class))
						cc = DECIMAL;
					else
						cc = NUMBER;
				}
				else if (ci.isChildOf(Collection.class))
					cc = COLLECTION;
				else if (ci.isChildOf(Map.class)) {
					if (ci.isChildOf(BeanMap.class))
						cc = BEANMAP;
					else
						cc = MAP;
				}
				else if (c == Character.class)
					cc = CHAR;
				else if (c == Boolean.class)
					cc = BOOLEAN;
				else if (ci.isChildOfAny(Date.class, Calendar.class))
					cc = DATE;
				else if (c.isArray())
					cc = ARRAY;
				else if (ci.isChildOfAny(URL.class, URI.class) || ci.hasAnnotation(bc, Uri.class))
					cc = URI;
				else if (ci.isChildOf(Reader.class))
					cc = READER;
				else if (ci.isChildOf(InputStream.class))
					cc = INPUTSTREAM;
				else if (ci.is(Optional.class))
					cc = OPTIONAL;
			}

			isMemberClass = ci.isMemberClass() && ci.isNotStatic();

			// Find static fromString(String) or equivalent method.
			// fromString() must be checked before valueOf() so that Enum classes can create their own
			//		specialized fromString() methods to override the behavior of Enum.valueOf(String).
			// valueOf() is used by enums.
			// parse() is used by the java logging Level class.
			// forName() is used by Class and Charset
			String[] fromStringMethodNames = {"fromString","fromValue","valueOf","parse","parseString","forName","forString"};
			fromStringMethod = optional(
				ci.getPublicMethod(
					x -> x.isStatic()
					&& x.isNotDeprecated()
					&& x.hasReturnType(c)
					&& x.hasParamTypes(String.class)
					&& ArrayUtils.contains(x.getName(), fromStringMethodNames))
				).map(MethodInfo::inner)
				.orElse(null);

			// Find example() method if present.
			exampleMethod = optional(
				ci.getPublicMethod(
					x -> x.isStatic()
					&& x.isNotDeprecated()
					&& x.hasName("example")
					&& x.hasFuzzyParamTypes(BeanSession.class))
				).map(MethodInfo::inner)
				.orElse(null);

			ci.forEachAllField(x -> x.hasAnnotation(bc, ParentProperty.class), x -> {
				if (x.isStatic())
					throw new ClassMetaRuntimeException(c, "@ParentProperty used on invalid field ''{0}''.  Must be static.", x);
				parentPropertyMethod = new Setter.FieldSetter(x.accessible().inner());
			});

			ci.forEachAllField(x -> x.hasAnnotation(bc, NameProperty.class), x -> {
				if (x.isStatic())
					throw new ClassMetaRuntimeException(c, "@NameProperty used on invalid field ''{0}''.  Must be static.", x);
				namePropertyMethod = new Setter.FieldSetter(x.accessible().inner());
			});

			ci.forEachDeclaredField(x -> x.hasAnnotation(bc, Example.class), x -> {
				if (! (x.isStatic() && ci.isParentOf(x.getType().inner())))
					throw new ClassMetaRuntimeException(c, "@Example used on invalid field ''{0}''.  Must be static and an instance of the type.", x);
				exampleField = x.accessible().inner();
			});

			// Find @NameProperty and @ParentProperty methods if present.
			List<MethodInfo> methods = ci.getMethods();
			for (int i = methods.size()-1; i >=0; i--) {
				MethodInfo m = methods.get(i);
				if (m.hasAnnotation(bc, ParentProperty.class)) {
					if (m.isStatic() || ! m.hasNumParams(1))
						throw new ClassMetaRuntimeException(c, "@ParentProperty used on invalid method ''{0}''.  Must not be static and have one argument.", m);
					m.setAccessible();
					parentPropertyMethod = new Setter.MethodSetter(m.inner());
				}
				if (m.hasAnnotation(bc, NameProperty.class)) {
					if (m.isStatic() || ! m.hasNumParams(1))
						throw new ClassMetaRuntimeException(c, "@NameProperty used on invalid method ''{0}''.  Must not be static and have one argument.", m);
					m.setAccessible();
					namePropertyMethod = new Setter.MethodSetter(m.inner());
				}
			}

			ci.forEachDeclaredMethod(m -> m.hasAnnotation(bc, Example.class), m -> {
				if (! (m.isStatic() && m.hasFuzzyParamTypes(BeanSession.class) && ci.isParentOf(m.getReturnType().inner())))
					throw new ClassMetaRuntimeException(c, "@Example used on invalid method ''{0}''.  Must be static and return an instance of the declaring class.", m.toString());
				m.setAccessible();
				exampleMethod = m.inner();
			});

			// Note:  Primitive types are normally abstract.
			isAbstract = ci.isAbstract() && ci.isNotPrimitive();

			// Find constructor(String) method if present.
			ci.forEachPublicConstructor(cs -> cs.isPublic() && cs.isNotDeprecated(), cs -> {
				List<ClassInfo> pt = cs.getParamTypes();
				if (pt.size() == (isMemberClass ? 1 : 0) && c != Object.class && ! isAbstract) {
					noArgConstructor = cs;
				} else if (pt.size() == (isMemberClass ? 2 : 1)) {
					ClassInfo arg = pt.get(isMemberClass ? 1 : 0);
					if (arg.is(String.class))
						stringConstructor = cs;
				}
			});

			primitiveDefault = ci.getPrimitiveDefault();

			ci.forEachPublicMethod(
				MethodInfo::isNotDeprecated,
				x -> publicMethods.put(x.getSignature(), x.inner())
			);

			BeanFilter beanFilter = findBeanFilter(bc);
			MarshalledFilter marshalledFilter = findMarshalledFilter(bc);

			addAll(this.swaps, swaps);

			if (bc != null)
				this.builderSwap = BuilderSwap.findSwapFromObjectClass(bc, c, bc.getBeanConstructorVisibility(), bc.getBeanMethodVisibility());

			findSwaps(this.swaps, bc);

			if (beanFilter != null) {
				example = beanFilter.getExample();
				implClass = (Class<? extends T>) beanFilter.getImplClass();
			}

			if (marshalledFilter != null) {
				if (example == null)
					example = marshalledFilter.getExample();
				if (implClass == null)
					implClass = (Class<? extends T>) marshalledFilter.getImplClass();
			}

			if (innerClass != Object.class) {
				ClassInfo x = implClass == null ? ci : ClassInfo.of(implClass);
				noArgConstructor = x.getPublicConstructor(ConstructorInfo::hasNoParams);
			}

			try {

				// If this is an array, get the element type.
				if (cc == ARRAY)
					elementType = findClassMeta(innerClass.getComponentType());

				// If this is a MAP, see if it's parameterized (e.g. AddressBook extends HashMap<String,Person>)
				else if (cc == MAP) {
					ClassMeta[] parameters = findParameters();
					if (parameters != null && parameters.length == 2) {
						keyType = parameters[0];
						valueType = parameters[1];
					} else {
						keyType = findClassMeta(Object.class);
						valueType = findClassMeta(Object.class);
					}
				}

				// If this is a COLLECTION, see if it's parameterized (e.g. AddressBook extends LinkedList<Person>)
				else if (cc == COLLECTION || cc == OPTIONAL) {
					ClassMeta[] parameters = findParameters();
					if (parameters != null && parameters.length == 1) {
						elementType = parameters[0];
					} else {
						elementType = findClassMeta(Object.class);
					}
				}

				// If the category is unknown, see if it's a bean.
				// Note that this needs to be done after all other initialization has been done.
				else if (cc == OTHER) {

					BeanMeta newMeta = null;
					try {
						newMeta = new BeanMeta(ClassMeta.this, bc, beanFilter, null, implClass == null ? null : noArgConstructor);
						notABeanReason = newMeta.notABeanReason;

						// Always get these even if it's not a bean:
						beanRegistry = newMeta.beanRegistry;
						typePropertyName = newMeta.typePropertyName;

					} catch (RuntimeException e) {
						notABeanReason = e.getMessage();
						throw e;
					}
					if (notABeanReason == null)
						beanMeta = newMeta;
				}

			} catch (NoClassDefFoundError e) {
				initException = e;
			} catch (RuntimeException e) {
				initException = e;
				throw e;
			}

			if (beanMeta != null)
				dictionaryName = beanMeta.getDictionaryName();

			if (beanMeta != null && bc != null && bc.isUseInterfaceProxies() && innerClass.isInterface())
				invocationHandler = new BeanProxyInvocationHandler<T>(beanMeta);

			if (bc != null) {
				bc.forEachAnnotation(Bean.class, c, x -> true, x -> {
					if (x.dictionary().length != 0)
						beanRegistry = new BeanRegistry(bc, null, x.dictionary());
					// This could be a non-bean POJO with a type name.
					if (dictionaryName == null && ! x.typeName().isEmpty())
						dictionaryName = x.typeName();
				});
			}

			if (example == null && bc != null) {
				bc.forEachAnnotation(Example.class, c, x -> ! x.value().isEmpty(), x -> example = x.value());
			}

			if (example == null) {
				switch(cc) {
					case BOOLEAN:
						example = "true";
						break;
					case CHAR:
						example = "a";
						break;
					case CHARSEQ:
					case STR:
						example = "foo";
						break;
					case DECIMAL:
						if (isFloat())
							example = "1.0";
						else if (isDouble())
							example = "1.0";
						break;
					case ENUM:
						Iterator<? extends Enum> i = EnumSet.allOf((Class<? extends Enum>)c).iterator();
						if (i.hasNext())
							example = beanContext.isUseEnumNames() ? i.next().name() : i.next().toString();
						break;
					case NUMBER:
						if (isShort())
							example = "1";
						else if (isInteger())
							example = "1";
						else if (isLong())
							example = "1";
						break;
					case URI:
					case ARGS:
					case ARRAY:
					case BEANMAP:
					case CLASS:
					case COLLECTION:
					case DATE:
					case INPUTSTREAM:
					case MAP:
					case METHOD:
					case OBJ:
					case OTHER:
					case READER:
					case OPTIONAL:
					case VOID:
						break;
				}
			}

			this.stringMutater = Mutaters.get(String.class, c);

			if (cc == ENUM) {
				Class<? extends Enum> ec = (Class<? extends Enum<?>>)c;
				boolean useEnumNames = bc != null && bc.isUseEnumNames();
				enumValues = BiMap.create();
				enumValues.unmodifiable();
				stream(ec.getEnumConstants()).forEach(x -> enumValues.add(x, useEnumNames ? x.name() : x.toString()));
			}
		}

		private BeanFilter findBeanFilter(BeanContext bc) {
			try {
				List<Bean> ba = info.getAnnotations(bc, Bean.class);
				if (! ba.isEmpty())
					return BeanFilter.create(innerClass).applyAnnotations(ba).build();
			} catch (Exception e) {
				throw asRuntimeException(e);
			}
			return null;
		}

		private MarshalledFilter findMarshalledFilter(BeanContext bc) {
			try {
				List<Marshalled> ba = info.getAnnotations(bc, Marshalled.class);
				if (! ba.isEmpty())
					return MarshalledFilter.create(innerClass).applyAnnotations(ba).build();
			} catch (Exception e) {
				throw asRuntimeException(e);
			}
			return null;
		}

		private void findSwaps(List<ObjectSwap> l, BeanContext bc) {

			if (bc != null)
				bc.forEachAnnotation(Swap.class, innerClass, x -> true, x -> l.add(createSwap(x)));

			ObjectSwap defaultSwap = DefaultSwaps.find(ci);
			if (defaultSwap == null)
				defaultSwap = AutoObjectSwap.find(bc, ci);
			if (defaultSwap == null)
				defaultSwap = AutoNumberSwap.find(bc, ci);
			if (defaultSwap == null)
				defaultSwap = AutoMapSwap.find(bc, ci);
			if (defaultSwap == null)
				defaultSwap = AutoListSwap.find(bc, ci);
			if (defaultSwap != null)
				l.add(defaultSwap);
		}

		private ObjectSwap<T,?> createSwap(Swap s) {
			Class<?> c = s.value();
			if (ClassUtils.isVoid(c))
				c = s.impl();
			ClassInfo ci = ClassInfo.of(c);

			if (ci.isChildOf(ObjectSwap.class)) {
				ObjectSwap ps = BeanCreator.of(ObjectSwap.class).type(c).run();
				if (s.mediaTypes().length > 0)
					ps.forMediaTypes(MediaType.ofAll(s.mediaTypes()));
				if (! s.template().isEmpty())
					ps.withTemplate(s.template());
				return ps;
			}

			if (ci.isChildOf(Surrogate.class)) {
				List<SurrogateSwap<?,?>> l = SurrogateSwap.findObjectSwaps(c, beanContext);
				if (! l.isEmpty())
					return (ObjectSwap<T,?>)l.iterator().next();
			}

			throw new ClassMetaRuntimeException(c, "Invalid swap class ''{0}'' specified.  Must extend from ObjectSwap or Surrogate.", c);
		}

		private ClassMeta<?> findClassMeta(Class<?> c) {
			return beanContext.getClassMeta(c, false);
		}

		private ClassMeta<?>[] findParameters() {
			return beanContext.findParameters(innerClass, innerClass);
		}
	}

	/**
	 * Returns the {@link ClassInfo} wrapper for the underlying class.
	 *
	 * @return The {@link ClassInfo} wrapper for the underlying class, never <jk>null</jk>.
	 */
	public ClassInfo getInfo() {
		return info;
	}

	/**
	 * Returns the type property name associated with this class and subclasses.
	 *
	 * <p>
	 * If <jk>null</jk>, <js>"_type"</js> should be assumed.
	 *
	 * @return
	 * 	The type property name associated with this bean class, or <jk>null</jk> if there is no explicit type
	 * 	property name defined or this isn't a bean.
	 */
	public String getBeanTypePropertyName() {
		return typePropertyName;
	}

	/**
	 * Returns the bean dictionary name associated with this class.
	 *
	 * <p>
	 * The lexical name is defined by {@link Bean#typeName() @Bean(typeName)}.
	 *
	 * @return
	 * 	The type name associated with this bean class, or <jk>null</jk> if there is no type name defined or this
	 * 	isn't a bean.
	 */
	public String getDictionaryName() {
		return dictionaryName;
	}

	/**
	 * Returns the bean registry for this class.
	 *
	 * <p>
	 * This bean registry contains names specified in the {@link Bean#dictionary() @Bean(dictionary)} annotation
	 * defined on the class, regardless of whether the class is an actual bean.
	 * This allows interfaces to define subclasses with type names.
	 *
	 * @return The bean registry for this class, or <jk>null</jk> if no bean registry is associated with it.
	 */
	public BeanRegistry getBeanRegistry() {
		return beanRegistry;
	}

	/**
	 * Returns the category of this class.
	 *
	 * @return The category of this class.
	 */
	public ClassCategory getClassCategory() {
		return cc;
	}

	/**
	 * Returns <jk>true</jk> if this class is a superclass of or the same as the specified class.
	 *
	 * @param c The comparison class.
	 * @return <jk>true</jk> if this class is a superclass of or the same as the specified class.
	 */
	public boolean isAssignableFrom(Class<?> c) {
		return info.isChildOf(c);
	}

	/**
	 * Returns <jk>true</jk> if this class is a subclass of or the same as the specified class.
	 *
	 * @param c The comparison class.
	 * @return <jk>true</jk> if this class is a subclass of or the same as the specified class.
	 */
	public boolean isInstanceOf(Class<?> c) {
		return info.isParentOf(c);
	}

	/**
	 * Returns <jk>true</jk> if this class or any child classes has a {@link ObjectSwap} associated with it.
	 *
	 * <p>
	 * Used when transforming bean properties to prevent having to look up transforms if we know for certain that no
	 * transforms are associated with a bean property.
	 *
	 * @return <jk>true</jk> if this class or any child classes has a {@link ObjectSwap} associated with it.
	 */
	protected boolean hasChildSwaps() {
		return childSwaps != null;
	}

	/**
	 * Returns the {@link ObjectSwap} where the specified class is the same/subclass of the normal class of one of the
	 * child POJO swaps associated with this class.
	 *
	 * @param normalClass The normal class being resolved.
	 * @return The resolved {@link ObjectSwap} or <jk>null</jk> if none were found.
	 */
	protected ObjectSwap<?,?> getChildObjectSwapForSwap(Class<?> normalClass) {
		if (childSwapMap != null) {
			ObjectSwap<?,?> s = childSwapMap.get(normalClass);
			if (s == null) {
				for (ObjectSwap<?,?> f : childSwaps)
					if (s == null && f.getNormalClass().isParentOf(normalClass))
						s = f;
				if (s == null)
					s = ObjectSwap.NULL;
				ObjectSwap<?,?> s2 = childSwapMap.putIfAbsent(normalClass, s);
				if (s2 != null)
					s = s2;
			}
			if (s == ObjectSwap.NULL)
				return null;
			return s;
		}
		return null;
	}

	/**
	 * Returns the {@link ObjectSwap} where the specified class is the same/subclass of the swap class of one of the child
	 * POJO swaps associated with this class.
	 *
	 * @param swapClass The swap class being resolved.
	 * @return The resolved {@link ObjectSwap} or <jk>null</jk> if none were found.
	 */
	protected ObjectSwap<?,?> getChildObjectSwapForUnswap(Class<?> swapClass) {
		if (childUnswapMap != null) {
			ObjectSwap<?,?> s = childUnswapMap.get(swapClass);
			if (s == null) {
				for (ObjectSwap<?,?> f : childSwaps)
					if (s == null && f.getSwapClass().isParentOf(swapClass))
						s = f;
				if (s == null)
					s = ObjectSwap.NULL;
				ObjectSwap<?,?> s2 = childUnswapMap.putIfAbsent(swapClass, s);
				if (s2 != null)
					s = s2;
			}
			if (s == ObjectSwap.NULL)
				return null;
			return s;
		}
		return null;
	}

	/**
	 * Locates the no-arg constructor for the specified class.
	 *
	 * <p>
	 * Constructor must match the visibility requirements specified by parameter 'v'.
	 * If class is abstract, always returns <jk>null</jk>.
	 * Note that this also returns the 1-arg constructor for non-static member classes.
	 *
	 * @param <T> The class from which to locate the no-arg constructor.
	 * @param c The class from which to locate the no-arg constructor.
	 * @param v The minimum visibility.
	 * @return The constructor, or <jk>null</jk> if no no-arg constructor exists with the required visibility.
	 */
	@SuppressWarnings({"unchecked"})
	protected static <T> Constructor<? extends T> findNoArgConstructor(Class<?> c, Visibility v) {
		ClassInfo ci = ClassInfo.of(c);
		if (ci.isAbstract())
			return null;
		boolean isMemberClass = ci.isMemberClass() && ci.isNotStatic();
		ConstructorInfo cc = ci.getPublicConstructor(
			x -> x.isVisible(v)
			&& x.isNotDeprecated()
			&& x.hasNumParams(isMemberClass ? 1 : 0)
		);
		if (cc != null)
			return (Constructor<? extends T>) v.transform(cc.inner());
		return null;
	}

	/**
	 * Returns the {@link Class} object that this class type wraps.
	 *
	 * @return The wrapped class object.
	 */
	public Class<T> getInnerClass() {
		return innerClass;
	}

	/**
	 * Returns the serialized (swapped) form of this class if there is an {@link ObjectSwap} associated with it.
	 *
	 * @param session
	 * 	The bean session.
	 * 	<br>Required because the swap used may depend on the media type being serialized or parsed.
	 * @return The serialized class type, or this object if no swap is associated with the class.
	 */
	public ClassMeta<?> getSerializedClassMeta(BeanSession session) {
		ObjectSwap<T,?> ps = getSwap(session);
		return (ps == null ? this : ps.getSwapClassMeta(session));
	}

	/**
	 * Returns the example of this class.
	 *
	 * @param session
	 * 	The bean session.
	 * 	<br>Required because the example method may take it in as a parameter.
	 * @param jpSession The JSON parser for parsing examples into POJOs.
	 * @return The serialized class type, or this object if no swap is associated with the class.
	 */
	@SuppressWarnings({"unchecked","rawtypes"})
	public T getExample(BeanSession session, JsonParserSession jpSession) {
		try {
			if (example != null)
				return jpSession.parse(example, this);
			if (exampleMethod != null)
				return (T)MethodInfo.of(exampleMethod).invokeFuzzy(null, session);
			if (exampleField != null)
				return (T)exampleField.get(null);

			if (isCollection()) {
				Object etExample = getElementType().getExample(session, jpSession);
				if (etExample != null) {
					if (canCreateNewInstance()) {
						Collection c = (Collection)newInstance();
						c.add(etExample);
						return (T)c;
					}
					return (T)Collections.singleton(etExample);
				}
			} else if (isArray()) {
				Object etExample = getElementType().getExample(session, jpSession);
				if (etExample != null) {
					Object o = Array.newInstance(getElementType().innerClass, 1);
					Array.set(o, 0, etExample);
					return (T)o;
				}
			} else if (isMap()) {
				Object vtExample = getValueType().getExample(session, jpSession);
				Object ktExample = getKeyType().getExample(session, jpSession);
				if (ktExample != null && vtExample != null) {
					if (canCreateNewInstance()) {
						Map m = (Map)newInstance();
						m.put(ktExample, vtExample);
						return (T)m;
					}
					return (T)Collections.singletonMap(ktExample, vtExample);
				}
			}

			return null;
		} catch (Exception e) {
			throw new ClassMetaRuntimeException(e);
		}
	}

	/**
	 * For array and {@code Collection} types, returns the class type of the components of the array or
	 * {@code Collection}.
	 *
	 * @return The element class type, or <jk>null</jk> if this class is not an array or Collection.
	 */
	public ClassMeta<?> getElementType() {
		return elementType;
	}

	/**
	 * For {@code Map} types, returns the class type of the keys of the {@code Map}.
	 *
	 * @return The key class type, or <jk>null</jk> if this class is not a Map.
	 */
	public ClassMeta<?> getKeyType() {
		return keyType;
	}

	/**
	 * For {@code Map} types, returns the class type of the values of the {@code Map}.
	 *
	 * @return The value class type, or <jk>null</jk> if this class is not a Map.
	 */
	public ClassMeta<?> getValueType() {
		return valueType;
	}

	/**
	 * Returns <jk>true</jk> if this class implements {@link Delegate}, meaning it's a representation of some other
	 * object.
	 *
	 * @return <jk>true</jk> if this class implements {@link Delegate}.
	 */
	public boolean isDelegate() {
		return isDelegate;
	}

	/**
	 * Returns <jk>true</jk> if the specified class is an exact match for this metadata.
	 *
	 * @param value The value to check against.
	 * @return <jk>true</jk> if the specified class is an exact match for this metadata.
	 */
	public boolean is(Class<?> value) {
		return eq(innerClass, value);
	}

	/**
	 * Returns <jk>true</jk> if this metadata represents the specified type.
	 *
	 * @param c The class to test against.
	 * @return <jk>true</jk> if this metadata represents the specified type.
	 */
	public boolean isChildOf(Class<?> c) {
		return info.isChildOf(c);
	}

	/**
	 * Returns <jk>true</jk> if this class is a subclass of {@link Map}.
	 *
	 * @return <jk>true</jk> if this class is a subclass of {@link Map}.
	 */
	public boolean isMap() {
		return cc == MAP || cc == BEANMAP;
	}

	/**
	 * Returns <jk>true</jk> if this class is a subclass of {@link Map} or it's a bean.
	 *
	 * @return <jk>true</jk> if this class is a subclass of {@link Map} or it's a bean.
	 */
	public boolean isMapOrBean() {
		return cc == MAP || cc == BEANMAP || beanMeta != null;
	}

	/**
	 * Returns <jk>true</jk> if this class is a subclass of {@link BeanMap}.
	 *
	 * @return <jk>true</jk> if this class is a subclass of {@link BeanMap}.
	 */
	public boolean isBeanMap() {
		return cc == BEANMAP;
	}

	/**
	 * Returns <jk>true</jk> if this class is a subclass of {@link Collection}.
	 *
	 * @return <jk>true</jk> if this class is a subclass of {@link Collection}.
	 */
	public boolean isCollection() {
		return cc == COLLECTION;
	}

	/**
	 * Returns <jk>true</jk> if this class is a subclass of {@link Optional}.
	 *
	 * @return <jk>true</jk> if this class is a subclass of {@link Optional}.
	 */
	public boolean isOptional() {
		return cc == OPTIONAL;
	}

	/**
	 * Returns <jk>true</jk> if this class is a subclass of {@link Collection} or is an array.
	 *
	 * @return <jk>true</jk> if this class is a subclass of {@link Collection} or is an array.
	 */
	public boolean isCollectionOrArray() {
		return cc == COLLECTION || cc == ARRAY;
	}

	/**
	 * Returns <jk>true</jk> if this class is a subclass of {@link Collection} or is an array or {@link Optional}.
	 *
	 * @return <jk>true</jk> if this class is a subclass of {@link Collection} or is an array or {@link Optional}.
	 */
	public boolean isCollectionOrArrayOrOptional() {
		return cc == COLLECTION || cc == ARRAY || cc == OPTIONAL;
	}

	/**
	 * Returns <jk>true</jk> if this class extends from {@link Set}.
	 *
	 * @return <jk>true</jk> if this class extends from {@link Set}.
	 */
	public boolean isSet() {
		return cc == COLLECTION && info.isChildOf(Set.class);
	}

	/**
	 * Returns <jk>true</jk> if this class extends from {@link List}.
	 *
	 * @return <jk>true</jk> if this class extends from {@link List}.
	 */
	public boolean isList() {
		return cc == COLLECTION && info.isChildOf(List.class);
	}

	/**
	 * Returns <jk>true</jk> if this class is <code><jk>byte</jk>[]</code>.
	 *
	 * @return <jk>true</jk> if this class is <code><jk>byte</jk>[]</code>.
	 */
	public boolean isByteArray() {
		return cc == ARRAY && this.innerClass == byte[].class;
	}

	/**
	 * Returns <jk>true</jk> if this class is {@link Class}.
	 *
	 * @return <jk>true</jk> if this class is {@link Class}.
	 */
	public boolean isClass() {
		return cc == ClassCategory.CLASS;
	}

	/**
	 * Returns <jk>true</jk> if this class is {@link Method}.
	 *
	 * @return <jk>true</jk> if this class is {@link Method}.
	 */
	public boolean isMethod() {
		return cc == METHOD;
	}

	/**
	 * Returns <jk>true</jk> if this class is an {@link Enum}.
	 *
	 * @return <jk>true</jk> if this class is an {@link Enum}.
	 */
	public boolean isEnum() {
		return cc == ENUM;
	}

	/**
	 * Returns <jk>true</jk> if this class is an array.
	 *
	 * @return <jk>true</jk> if this class is an array.
	 */
	public boolean isArray() {
		return cc == ARRAY;
	}

	/**
	 * Returns <jk>true</jk> if this class is a bean.
	 *
	 * @return <jk>true</jk> if this class is a bean.
	 */
	public boolean isBean() {
		return beanMeta != null;
	}

	/**
	 * Returns <jk>true</jk> if this class is {@link Object}.
	 *
	 * @return <jk>true</jk> if this class is {@link Object}.
	 */
	public boolean isObject() {
		return cc == OBJ;
	}

	/**
	 * Returns <jk>true</jk> if this class is not {@link Object}.
	 *
	 * @return <jk>true</jk> if this class is not {@link Object}.
	 */
	public boolean isNotObject() {
		return cc != OBJ;
	}

	/**
	 * Returns <jk>true</jk> if this class is a subclass of {@link Number}.
	 *
	 * @return <jk>true</jk> if this class is a subclass of {@link Number}.
	 */
	public boolean isNumber() {
		return cc == NUMBER || cc == DECIMAL;
	}

	/**
	 * Returns <jk>true</jk> if this class is a subclass of {@link Float} or {@link Double}.
	 *
	 * @return <jk>true</jk> if this class is a subclass of {@link Float} or {@link Double}.
	 */
	public boolean isDecimal() {
		return cc == DECIMAL;
	}

	/**
	 * Returns <jk>true</jk> if this class is either {@link Float} or <jk>float</jk>.
	 *
	 * @return <jk>true</jk> if this class is either {@link Float} or <jk>float</jk>.
	 */
	public boolean isFloat() {
		return innerClass == Float.class || innerClass == float.class;
	}

	/**
	 * Returns <jk>true</jk> if this class is either {@link Double} or <jk>double</jk>.
	 *
	 * @return <jk>true</jk> if this class is either {@link Double} or <jk>double</jk>.
	 */
	public boolean isDouble() {
		return innerClass == Double.class || innerClass == double.class;
	}

	/**
	 * Returns <jk>true</jk> if this class is either {@link Short} or <jk>short</jk>.
	 *
	 * @return <jk>true</jk> if this class is either {@link Short} or <jk>short</jk>.
	 */
	public boolean isShort() {
		return innerClass == Short.class || innerClass == short.class;
	}

	/**
	 * Returns <jk>true</jk> if this class is either {@link Integer} or <jk>int</jk>.
	 *
	 * @return <jk>true</jk> if this class is either {@link Integer} or <jk>int</jk>.
	 */
	public boolean isInteger() {
		return innerClass == Integer.class || innerClass == int.class;
	}

	/**
	 * Returns <jk>true</jk> if this class is either {@link Long} or <jk>long</jk>.
	 *
	 * @return <jk>true</jk> if this class is either {@link Long} or <jk>long</jk>.
	 */
	public boolean isLong() {
		return innerClass == Long.class || innerClass == long.class;
	}

	/**
	 * Returns <jk>true</jk> if this class is a {@link Boolean}.
	 *
	 * @return <jk>true</jk> if this class is a {@link Boolean}.
	 */
	public boolean isBoolean() {
		return cc == BOOLEAN;
	}

	/**
	 * Returns <jk>true</jk> if this class is a subclass of {@link CharSequence}.
	 *
	 * @return <jk>true</jk> if this class is a subclass of {@link CharSequence}.
	 */
	public boolean isCharSequence() {
		return cc == STR || cc == CHARSEQ;
	}

	/**
	 * Returns <jk>true</jk> if this class is a {@link String}.
	 *
	 * @return <jk>true</jk> if this class is a {@link String}.
	 */
	public boolean isString() {
		return cc == STR;
	}

	/**
	 * Returns <jk>true</jk> if this class is a {@link Character}.
	 *
	 * @return <jk>true</jk> if this class is a {@link Character}.
	 */
	public boolean isChar() {
		return cc == CHAR;
	}

	/**
	 * Returns <jk>true</jk> if this class is a primitive.
	 *
	 * @return <jk>true</jk> if this class is a primitive.
	 */
	public boolean isPrimitive() {
		return innerClass.isPrimitive();
	}

	/**
	 * Returns <jk>true</jk> if this class is a {@link Date} or {@link Calendar}.
	 *
	 * @return <jk>true</jk> if this class is a {@link Date} or {@link Calendar}.
	 */
	public boolean isDateOrCalendar() {
		return cc == DATE;
	}

	/**
	 * Returns <jk>true</jk> if this class is a {@link Date} or {@link Calendar} or {@link Temporal}.
	 *
	 * @return <jk>true</jk> if this class is a {@link Date} or {@link Calendar} or {@link Temporal}.
	 */
	public boolean isDateOrCalendarOrTemporal() {
		return cc == DATE || info.isChildOf(Temporal.class);
	}

	/**
	 * Returns <jk>true</jk> if this class is a {@link Date}.
	 *
	 * @return <jk>true</jk> if this class is a {@link Date}.
	 */
	public boolean isDate() {
		return cc == DATE && info.isChildOf(Date.class);
	}

	/**
	 * Returns <jk>true</jk> if this class is a {@link Temporal}.
	 *
	 * @return <jk>true</jk> if this class is a {@link Temporal}.
	 */
	public boolean isTemporal() {
		return info.isChildOf(Temporal.class);
	}

	/**
	 * Returns <jk>true</jk> if this class is a {@link Calendar}.
	 *
	 * @return <jk>true</jk> if this class is a {@link Calendar}.
	 */
	public boolean isCalendar() {
		return cc == DATE && info.isChildOf(Calendar.class);
	}

	/**
	 * Returns <jk>true</jk> if this class is a {@link URI} or {@link URL}.
	 *
	 * @return <jk>true</jk> if this class is a {@link URI} or {@link URL}.
	 */
	public boolean isUri() {
		return cc == URI;
	}

	/**
	 * Returns <jk>true</jk> if this class is a {@link Reader}.
	 *
	 * @return <jk>true</jk> if this class is a {@link Reader}.
	 */
	public boolean isReader() {
		return cc == READER;
	}

	/**
	 * Returns <jk>true</jk> if this class is an {@link InputStream}.
	 *
	 * @return <jk>true</jk> if this class is an {@link InputStream}.
	 */
	public boolean isInputStream() {
		return cc == INPUTSTREAM;
	}

	/**
	 * Returns <jk>true</jk> if this class is {@link Void} or <jk>void</jk>.
	 *
	 * @return <jk>true</jk> if this class is {@link Void} or <jk>void</jk>.
	 */
	public boolean isVoid() {
		return cc == VOID;
	}

	/**
	 * Returns <jk>true</jk> if this metadata represents an array of argument types.
	 *
	 * @return <jk>true</jk> if this metadata represents an array of argument types.
	 */
	public boolean isArgs() {
		return cc == ARGS;
	}

	/**
	 * Returns the argument types of this meta.
	 *
	 * @return The argument types of this meta, or <jk>null</jk> if this isn't an array of argument types.
	 */
	public ClassMeta<?>[] getArgs() {
		return args;
	}

	/**
	 * Returns the argument metadata at the specified index if this is an args metadata object.
	 *
	 * @param index The argument index.
	 * @return The The argument metadata.  Never <jk>null</jk>.
	 * @throws BeanRuntimeException If this metadata object is not a list of arguments, or the index is out of range.
	 */
	public ClassMeta<?> getArg(int index) {
		if (args != null && index >= 0 && index < args.length)
			return args[index];
		throw new BeanRuntimeException("Invalid argument index specified:  {0}.  Only {1} arguments are defined.", index, args == null ? 0 : args.length);
	}

	/**
	 * Returns <jk>true</jk> if instance of this object can be <jk>null</jk>.
	 *
	 * <p>
	 * Objects can be <jk>null</jk>, but primitives cannot, except for chars which can be represented by
	 * <code>(<jk>char</jk>)0</code>.
	 *
	 * @return <jk>true</jk> if instance of this class can be null.
	 */
	public boolean isNullable() {
		if (innerClass.isPrimitive())
			return cc == CHAR;
		return true;
	}

	/**
	 * Returns <jk>true</jk> if this class is abstract.
	 *
	 * @return <jk>true</jk> if this class is abstract.
	 */
	public boolean isAbstract() {
		return isAbstract;
	}

	/**
	 * Returns <jk>true</jk> if this class is an inner class.
	 *
	 * @return <jk>true</jk> if this class is an inner class.
	 */
	public boolean isMemberClass() {
		return isMemberClass;
	}

	/**
	 * All public methods on this class including static methods.
	 *
	 * <p>
	 * Keys are method signatures.
	 *
	 * @return The public methods on this class.
	 */
	public Map<String,Method> getPublicMethods() {
		return publicMethods;
	}

	/**
	 * Returns the {@link ObjectSwap} associated with this class that's the best match for the specified session.
	 *
	 * @param session
	 * 	The current bean session.
	 * 	<br>If multiple swaps are associated with a class, only the first one with a matching media type will
	 * 	be returned.
	 * @return
	 * 	The {@link ObjectSwap} associated with this class, or <jk>null</jk> if there are no POJO swaps associated with
	 * 	this class.
	 */
	public ObjectSwap<T,?> getSwap(BeanSession session) {
		if (swaps != null) {
			int matchQuant = 0, matchIndex = -1;

			for (int i = 0; i < swaps.length; i++) {
				int q = swaps[i].match(session);
				if (q > matchQuant) {
					matchQuant = q;
					matchIndex = i;
				}
			}

			if (matchIndex > -1)
				return swaps[matchIndex];
		}
		return null;
	}

	/**
	 * Returns the builder swap associated with this class.
	 *
	 * @param session The current bean session.
	 * @return The builder swap associated with this class, or <jk>null</jk> if it doesn't exist.
	 */
	public BuilderSwap<T,?> getBuilderSwap(BeanSession session) {
		return builderSwap;
	}

	/**
	 * Returns the {@link BeanMeta} associated with this class.
	 *
	 * @return
	 * 	The {@link BeanMeta} associated with this class, or <jk>null</jk> if there is no bean meta associated with
	 * 	this class.
	 */
	public BeanMeta<T> getBeanMeta() {
		return beanMeta;
	}

	/**
	 * Returns the no-arg constructor for this class.
	 *
	 * @return The no-arg constructor for this class, or <jk>null</jk> if it does not exist.
	 */
	public ConstructorInfo getConstructor() {
		return noArgConstructor;
	}

	/**
	 * Returns the no-arg constructor for this class based on the {@link Marshalled#implClass()} value.
	 *
	 * @param conVis The constructor visibility.
	 * @return The no-arg constructor for this class, or <jk>null</jk> if it does not exist.
	 */
	public ConstructorInfo getImplClassConstructor(Visibility conVis) {
		if (implClass != null)
			return ClassInfo.of(implClass).getNoArgConstructor(conVis);
		return null;
	}

	/**
	 * Returns the interface proxy invocation handler for this class.
	 *
	 * @return The interface proxy invocation handler, or <jk>null</jk> if it does not exist.
	 */
	public InvocationHandler getProxyInvocationHandler() {
		return invocationHandler;
	}

	/**
	 * Returns <jk>true</jk> if this class has a no-arg constructor or invocation handler.
	 *
	 * @return <jk>true</jk> if a new instance of this class can be constructed.
	 */
	public boolean canCreateNewInstance() {
		if (isMemberClass)
			return false;
		if (noArgConstructor != null || getProxyInvocationHandler() != null || (isArray() && elementType.canCreateNewInstance()))
			return true;
		return false;
	}

	/**
	 * Returns <jk>true</jk> if this class has a no-arg constructor or invocation handler.
	 * Returns <jk>false</jk> if this is a non-static member class and the outer object does not match the class type of
	 * the defining class.
	 *
	 * @param outer
	 * 	The outer class object for non-static member classes.  Can be <jk>null</jk> for non-member or static classes.
	 * @return
	 * 	<jk>true</jk> if a new instance of this class can be created within the context of the specified outer object.
	 */
	public boolean canCreateNewInstance(Object outer) {
		if (isMemberClass)
			return outer != null && noArgConstructor != null && noArgConstructor.hasParamTypes(outer.getClass());
		return canCreateNewInstance();
	}

	/**
	 * Returns <jk>true</jk> if this class can be instantiated as a bean.
	 * Returns <jk>false</jk> if this is a non-static member class and the outer object does not match the class type of
	 * the defining class.
	 *
	 * @param outer
	 * 	The outer class object for non-static member classes.  Can be <jk>null</jk> for non-member or static classes.
	 * @return
	 * 	<jk>true</jk> if a new instance of this bean can be created within the context of the specified outer object.
	 */
	public boolean canCreateNewBean(Object outer) {
		if (beanMeta == null || beanMeta.constructor == null)
			return false;
		if (isMemberClass)
			return outer != null && beanMeta.constructor.hasParamTypes(outer.getClass());
		return true;
	}

	/**
	 * Returns <jk>true</jk> if this class can call the {@link #newInstanceFromString(Object, String)} method.
	 *
	 * @param outer
	 * 	The outer class object for non-static member classes.
	 * 	Can be <jk>null</jk> for non-member or static classes.
	 * @return <jk>true</jk> if this class has a no-arg constructor or invocation handler.
	 */
	public boolean canCreateNewInstanceFromString(Object outer) {
		if (fromStringMethod != null)
			return true;
		if (stringConstructor != null) {
			if (isMemberClass)
				return outer != null && stringConstructor.hasParamTypes(outer.getClass(), String.class);
			return true;
		}
		return false;
	}

	/**
	 * Returns the method or field annotated with {@link NameProperty @NameProperty}.
	 *
	 * @return
	 * 	The method or field  annotated with {@link NameProperty @NameProperty} or <jk>null</jk> if method does not
	 * 	exist.
	 */
	public Setter getNameProperty() {
		return namePropertyMethod;
	}

	/**
	 * Returns the method or field annotated with {@link ParentProperty @ParentProperty}.
	 *
	 * @return
	 * 	The method or field annotated with {@link ParentProperty @ParentProperty} or <jk>null</jk> if method does not
	 * 	exist.
	 */
	public Setter getParentProperty() {
		return parentPropertyMethod;
	}

	/**
	 * Returns the reason why this class is not a bean, or <jk>null</jk> if it is a bean.
	 *
	 * @return The reason why this class is not a bean, or <jk>null</jk> if it is a bean.
	 */
	public synchronized String getNotABeanReason() {
		return notABeanReason;
	}

	/**
	 * Returns any exception that was throw in the <c>init()</c> method.
	 *
	 * @return The cached exception.
	 */
	public Throwable getInitException() {
		return initException;
	}

	/**
	 * Returns the {@link BeanContext} that created this object.
	 *
	 * @return The bean context.
	 */
	public BeanContext getBeanContext() {
		return beanContext;
	}

	/**
	 * Returns the default value for primitives such as <jk>int</jk> or <jk>Integer</jk>.
	 *
	 * @return The default value, or <jk>null</jk> if this class type is not a primitive.
	 */
	@SuppressWarnings("unchecked")
	public T getPrimitiveDefault() {
		return (T)primitiveDefault;
	}

	/**
	 * If this is an {@link Optional}, returns an empty optional.
	 *
	 * <p>
	 * Note that if this is a nested optional, will recursively create empty optionals.
	 *
	 * @return An empty optional, or <jk>null</jk> if this isn't an optional.
	 */
	public Optional<?> getOptionalDefault() {
		if (isOptional())
			return optional(getElementType().getOptionalDefault());
		return null;
	}

	/**
	 * Converts the specified object to a string.
	 *
	 * @param t The object to convert.
	 * @return The object converted to a string, or <jk>null</jk> if the object was null.
	 */
	public String toString(Object t) {
		if (t == null)
			return null;
		if (isEnum() && beanContext.isUseEnumNames())
			return ((Enum<?>)t).name();
		return t.toString();
	}

	/**
	 * Create a new instance of the main class of this declared type from a <c>String</c> input.
	 *
	 * <p>
	 * In order to use this method, the class must have one of the following methods:
	 * <ul>
	 * 	<li><code><jk>public static</jk> T valueOf(String in);</code>
	 * 	<li><code><jk>public static</jk> T fromString(String in);</code>
	 * 	<li><code><jk>public</jk> T(String in);</code>
	 * </ul>
	 *
	 * @param outer
	 * 	The outer class object for non-static member classes.  Can be <jk>null</jk> for non-member or static classes.
	 * @param arg The input argument value.
	 * @return A new instance of the object, or <jk>null</jk> if there is no string constructor on the object.
	 * @throws ExecutableException Exception occurred on invoked constructor/method/field.
	 */
	@SuppressWarnings({ "unchecked" })
	public T newInstanceFromString(Object outer, String arg) throws ExecutableException {

		if (isEnum()) {
			T t = (T)enumValues.getKey(arg);
			if (t == null && ! beanContext.isIgnoreUnknownEnumValues())
				throw new ExecutableException("Could not resolve enum value '"+arg+"' on class '"+getInnerClass().getName()+"'");
			return t;
		}

		Method m = fromStringMethod;
		if (m != null) {
			try {
				return (T)m.invoke(null, arg);
			} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
				throw new ExecutableException(e);
			}
		}
		ConstructorInfo c = stringConstructor;
		if (c != null) {
			if (isMemberClass)
				return c.<T>invoke(outer, arg);
			return c.<T>invoke(arg);
		}
		throw new ExecutableException("No string constructor or valueOf(String) method found for class '"+getInnerClass().getName()+"'");
	}

	/**
	 * Create a new instance of the main class of this declared type.
	 *
	 * @return A new instance of the object, or <jk>null</jk> if there is no no-arg constructor on the object.
	 * @throws ExecutableException Exception occurred on invoked constructor/method/field.
	 */
	@SuppressWarnings("unchecked")
	public T newInstance() throws ExecutableException {
		if (isArray())
			return (T)Array.newInstance(getInnerClass().getComponentType(), 0);
		ConstructorInfo c = getConstructor();
		if (c != null)
			return c.<T>invoke();
		InvocationHandler h = getProxyInvocationHandler();
		if (h != null)
			return (T)Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] { getInnerClass(), java.io.Serializable.class }, h);
		if (isArray())
			return (T)Array.newInstance(this.elementType.innerClass,0);
		return null;
	}

	/**
	 * Same as {@link #newInstance()} except for instantiating non-static member classes.
	 *
	 * @param outer
	 * 	The instance of the owning object of the member class instance.
	 * 	Can be <jk>null</jk> if instantiating a non-member or static class.
	 * @return A new instance of the object, or <jk>null</jk> if there is no no-arg constructor on the object.
	 * @throws ExecutableException Exception occurred on invoked constructor/method/field.
	 */
	public T newInstance(Object outer) throws ExecutableException {
		if (isMemberClass)
			return noArgConstructor.<T>invoke(outer);
		return newInstance();
	}

	/**
	 * Similar to {@link #equals(Object)} except primitive and Object types that are similar are considered the same.
	 * (e.g. <jk>boolean</jk> == <c>Boolean</c>).
	 *
	 * @param cm The class meta to compare to.
	 * @return <jk>true</jk> if the specified class-meta is equivalent to this one.
	 */
	public boolean same(ClassMeta<?> cm) {
		if (equals(cm))
			return true;
		return (isPrimitive() && cc == cm.cc);
	}

	@Override /* Object */
	public String toString() {
		return toString(false);
	}

	/**
	 * Same as {@link #toString()} except use simple class names.
	 *
	 * @param simple Print simple class names only (no package).
	 * @return A new string.
	 */
	public String toString(boolean simple) {
		return toString(new StringBuilder(), simple).toString();
	}

	/**
	 * Appends this object as a readable string to the specified string builder.
	 *
	 * @param sb The string builder to append this object to.
	 * @param simple Print simple class names only (no package).
	 * @return The passed-in string builder.
	 */
	protected StringBuilder toString(StringBuilder sb, boolean simple) {
		String n = innerClass.getName();
		if (simple) {
			int i = n.lastIndexOf('.');
			n = n.substring(i == -1 ? 0 : i+1).replace('$', '.');
		}
		if (cc == ARRAY)
			return elementType.toString(sb, simple).append('[').append(']');
		if (cc == MAP)
			return sb.append(n).append(keyType.isObject() && valueType.isObject() ? "" : "<"+keyType.toString(simple)+","+valueType.toString(simple)+">");
		if (cc == BEANMAP)
			return sb.append(BeanMap.class.getName()).append('<').append(n).append('>');
		if (cc == COLLECTION || cc == OPTIONAL)
			return sb.append(n).append(elementType.isObject() ? "" : "<"+elementType.toString(simple)+">");
		return sb.append(n);
	}

	/**
	 * Returns <jk>true</jk> if the specified object is an instance of this class.
	 *
	 * <p>
	 * This is a simple comparison on the base class itself and not on any generic parameters.
	 *
	 * @param o The object to check.
	 * @return <jk>true</jk> if the specified object is an instance of this class.
	 */
	public boolean isInstance(Object o) {
		if (o != null)
			return info.isParentOf(o.getClass()) || (isPrimitive() && info.getPrimitiveWrapper() == o.getClass());
		return false;
	}

	/**
	 * Returns a readable name for this class (e.g. <js>"java.lang.String"</js>, <js>"boolean[]"</js>).
	 *
	 * @return The readable name for this class.
	 */
	public String getFullName() {
		return info.getFullName();
	}

	/**
	 * Shortcut for calling {@link Class#getName()} on the inner class of this metadata.
	 *
	 * @return The  name of the inner class.
	 */
	public String getName() {
		return innerClass.getName();
	}

	/**
	 * Shortcut for calling {@link Class#getSimpleName()} on the inner class of this metadata.
	 *
	 * @return The simple name of the inner class.
	 */
	public String getSimpleName() {
		return innerClass.getSimpleName();
	}

	/**
	 * Returns <jk>true</jk> if this class has a transform associated with it that allows it to be created from a Reader.
	 *
	 * @return <jk>true</jk> if this class has a transform associated with it that allows it to be created from a Reader.
	 */
	public boolean hasReaderMutater() {
		return hasMutaterFrom(Reader.class);
	}

	/**
	 * Returns the transform for this class for creating instances from a Reader.
	 *
	 * @return The transform, or <jk>null</jk> if no such transform exists.
	 */
	public Mutater<Reader,T> getReaderMutater() {
		return getFromMutater(Reader.class);
	}

	/**
	 * Returns <jk>true</jk> if this class has a transform associated with it that allows it to be created from an InputStream.
	 *
	 * @return <jk>true</jk> if this class has a transform associated with it that allows it to be created from an InputStream.
	 */
	public boolean hasInputStreamMutater() {
		return hasMutaterFrom(InputStream.class);
	}

	/**
	 * Returns the transform for this class for creating instances from an InputStream.
	 *
	 * @return The transform, or <jk>null</jk> if no such transform exists.
	 */
	public Mutater<InputStream,T> getInputStreamMutater() {
		return getFromMutater(InputStream.class);
	}

	/**
	 * Returns <jk>true</jk> if this class has a transform associated with it that allows it to be created from a String.
	 *
	 * @return <jk>true</jk> if this class has a transform associated with it that allows it to be created from a String.
	 */
	public boolean hasStringMutater() {
		return stringMutater != null;
	}

	/**
	 * Returns the transform for this class for creating instances from a String.
	 *
	 * @return The transform, or <jk>null</jk> if no such transform exists.
	 */
	public Mutater<String,T> getStringMutater() {
		return stringMutater;
	}

	/**
	 * Returns <jk>true</jk> if this class can be instantiated from the specified type.
	 *
	 * @param c The class type to convert from.
	 * @return <jk>true</jk> if this class can be instantiated from the specified type.
	 */
	public boolean hasMutaterFrom(Class<?> c) {
		return getFromMutater(c) != null;
	}

	/**
	 * Returns <jk>true</jk> if this class can be instantiated from the specified type.
	 *
	 * @param c The class type to convert from.
	 * @return <jk>true</jk> if this class can be instantiated from the specified type.
	 */
	public boolean hasMutaterFrom(ClassMeta<?> c) {
		return getFromMutater(c.getInnerClass()) != null;
	}

	/**
	 * Returns <jk>true</jk> if this class can be transformed to the specified type.
	 *
	 * @param c The class type to convert from.
	 * @return <jk>true</jk> if this class can be transformed to the specified type.
	 */
	public boolean hasMutaterTo(Class<?> c) {
		return getToMutater(c) != null;
	}

	/**
	 * Returns <jk>true</jk> if this class can be transformed to the specified type.
	 *
	 * @param c The class type to convert from.
	 * @return <jk>true</jk> if this class can be transformed to the specified type.
	 */
	public boolean hasMutaterTo(ClassMeta<?> c) {
		return getToMutater(c.getInnerClass()) != null;
	}

	/**
	 * Transforms the specified object into an instance of this class.
	 *
	 * @param o The object to transform.
	 * @return The transformed object.
	 */
	@SuppressWarnings({"unchecked","rawtypes"})
	public T mutateFrom(Object o) {
		Mutater t = getFromMutater(o.getClass());
		return (T)(t == null ? null : t.mutate(o));
	}

	/**
	 * Transforms the specified object into an instance of this class.
	 *
	 * @param <O> The transform-to class.
	 * @param o The object to transform.
	 * @param c The class
	 * @return The transformed object.
	 */
	@SuppressWarnings({"unchecked","rawtypes"})
	public <O> O mutateTo(Object o, Class<O> c) {
		Mutater t = getToMutater(c);
		return (O)(t == null ? null : t.mutate(o));
	}

	/**
	 * Transforms the specified object into an instance of this class.
	 *
	 * @param <O> The transform-to class.
	 * @param o The object to transform.
	 * @param c The class
	 * @return The transformed object.
	 */
	public <O> O mutateTo(Object o, ClassMeta<O> c) {
		return mutateTo(o, c.getInnerClass());
	}

	/**
	 * Returns the transform for this class for creating instances from other object types.
	 *
	 * @param <I> The transform-from class.
	 * @param c The transform-from class.
	 * @return The transform, or <jk>null</jk> if no such transform exists.
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public <I> Mutater<I,T> getFromMutater(Class<I> c) {
		Mutater t = fromMutaters.get(c);
		if (t == Mutaters.NULL)
			return null;
		if (t == null) {
			t = Mutaters.get(c, innerClass);
			if (t == null)
				t = Mutaters.NULL;
			fromMutaters.put(c, t);
		}
		return t == Mutaters.NULL ? null : t;
	}

	/**
	 * Returns the transform for this class for creating instances from other object types.
	 *
	 * @param <O> The transform-to class.
	 * @param c The transform-from class.
	 * @return The transform, or <jk>null</jk> if no such transform exists.
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public <O> Mutater<T,O> getToMutater(Class<O> c) {
		Mutater t = toMutaters.get(c);
		if (t == Mutaters.NULL)
			return null;
		if (t == null) {
			t = Mutaters.get(innerClass, c);
			if (t == null)
				t = Mutaters.NULL;
			toMutaters.put(c, t);
		}
		return t == Mutaters.NULL ? null : t;
	}

	/**
	 * Shortcut for calling <code>getInnerClass().getAnnotation(a) != <jk>null</jk></code>.
	 *
	 * @param a The annotation to check for.
	 * @return <jk>true</jk> if the inner class has the annotation.
	 */
	public boolean hasAnnotation(Class<? extends Annotation> a) {
		return getLastAnnotation(a) != null;
	}

	/**
	 * Shortcut for calling <c>getInnerClass().getAnnotation(a)</c>.
	 *
	 * @param <A> The annotation type to look for.
	 * @param a The annotation to retrieve.
	 * @return The specified annotation, or <jk>null</jk> if the class does not have the specified annotation.
	 */
	@SuppressWarnings("unchecked")
	public <A extends Annotation> A getLastAnnotation(Class<A> a) {
		Optional<A> o = (Optional<A>)annotationLastMap.get(a);
		if (o == null) {
			if (beanContext == null)
				return info.getAnnotation(BeanContext.DEFAULT, a);
			o = optional(info.getAnnotation(beanContext, a));
			annotationLastMap.put(a, o);
		}
		return o.orElse(null);
	}

	/**
	 * Performs an action on all matching annotations of the specified type defined on this class or parent classes/interfaces in parent-to-child order.
	 *
	 * @param <A> The annotation type to look for.
	 * @param type The annotation to search for.
	 * @param filter A predicate to apply to the entries to determine if action should be performed.  Can be <jk>null</jk>.
	 * @param action An action to perform on the entry.
	 * @return This object.
	 */
	public <A extends Annotation> ClassMeta<T> forEachAnnotation(Class<A> type, Predicate<A> filter, Consumer<A> action) {
		A[] array = annotationArray(type);
		if (array == null) {
			if (beanContext == null)
				info.forEachAnnotation(BeanContext.DEFAULT, type, filter, action);
			return this;
		}
		for (A a : array)
			consume(filter, action, a);
		return this;
	}

	/**
	 * Returns the first matching annotation on this class or parent classes/interfaces in parent-to-child order.
	 *
	 * @param <A> The annotation type to look for.
	 * @param type The annotation to search for.
	 * @param filter A predicate to apply to the entries to determine if annotation should be used.  Can be <jk>null</jk>.
	 * @return This object.
	 */
	public <A extends Annotation> Optional<A> firstAnnotation(Class<A> type, Predicate<A> filter) {
		A[] array = annotationArray(type);
		if (array == null) {
			if (beanContext == null)
				return Optional.ofNullable(info.firstAnnotation(BeanContext.DEFAULT, type, filter));
			return Optional.empty();
		}
		for (A a : array)
			if (test(filter, a))
				return Optional.of(a);
		return Optional.empty();
	}

	/**
	 * Returns the last matching annotation on this class or parent classes/interfaces in parent-to-child order.
	 *
	 * @param <A> The annotation type to look for.
	 * @param type The annotation to search for.
	 * @param filter A predicate to apply to the entries to determine if annotation should be used.  Can be <jk>null</jk>.
	 * @return This object.
	 */
	public <A extends Annotation> Optional<A> lastAnnotation(Class<A> type, Predicate<A> filter) {
		A[] array = annotationArray(type);
		if (array == null) {
			if (beanContext == null)
				return Optional.ofNullable(info.lastAnnotation(BeanContext.DEFAULT, type, filter));
			return Optional.empty();
		}
		for (int i = array.length-1; i >= 0; i--)
			if (test(filter, array[i]))
				return Optional.of(array[i]);
		return Optional.empty();
	}

	@SuppressWarnings("unchecked")
	private <A extends Annotation> A[] annotationArray(Class<A> type) {
		A[] array = (A[])annotationArrayMap.get(type);
		if (array == null && beanContext != null) {
			List<A> l = list();
			info.forEachAnnotation(beanContext, type, x-> true, x -> l.add(x));
			array = (A[])Array.newInstance(type, l.size());
			for (int i = 0; i < l.size(); i++)
				Array.set(array, i, l.get(i));
			annotationArrayMap.put(type, array);
		}
		return array;
	}

	/**
	 * Returns a calculated property on this context.
	 *
	 * @param <T2> The type to convert the property to.
	 * @param name The name of the property.
	 * @param function The function used to create this property.
	 * @return The property value.  Never <jk>null</jk>.
	 */
	@SuppressWarnings("unchecked")
	public <T2> Optional<T2> getProperty(String name, Function<ClassMeta<?>,T2> function) {
		Optional<T2> t = (Optional<T2>) properties.get(name);
		if (t == null) {
			t = optional(function.apply(this));
			properties.put(name, t);
		}
		return t;
	}

	@Override /* Object */
	public int hashCode() {
		return innerClass.hashCode();
	}

	@Override /* Object */
	public boolean equals(Object o) {
		return (o instanceof ClassMeta) && eq(this, (ClassMeta<?>)o, (x,y)->eq(x.innerClass, y.innerClass));
	}
}
