This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new 77b9f38925 Marshall module improvements
     new 55e1edeebb Merge branch 'master' of 
https://gitbox.apache.org/repos/asf/juneau
77b9f38925 is described below

commit 77b9f38925f9ec541c6df60133932b1d32b17093
Author: James Bognar <[email protected]>
AuthorDate: Fri Dec 5 16:47:36 2025 -0500

    Marshall module improvements
---
 .../apache/juneau/commons/reflect/ClassInfo.java   |    8 +
 .../juneau/commons/reflect/ClassInfoTyped.java     |    2 +
 .../org/apache/juneau/commons/reflect/Setter.java  |   28 +-
 .../src/main/java/org/apache/juneau/BeanMeta.java  |    4 +-
 .../java/org/apache/juneau/BeanPropertyMeta.java   |    6 +-
 .../main/java/org/apache/juneau/BeanSession.java   |   16 +-
 .../src/main/java/org/apache/juneau/ClassMeta.java | 1357 ++++++++++----------
 .../org/apache/juneau/collections/JsonMap.java     |    2 +-
 .../juneau/httppart/bean/RequestBeanMeta.java      |    2 +-
 .../juneau/httppart/bean/ResponseBeanMeta.java     |    3 +-
 .../jsonschema/JsonSchemaGeneratorSession.java     |    4 +-
 .../juneau/objecttools/ObjectIntrospector.java     |   14 +-
 .../org/apache/juneau/objecttools/ObjectRest.java  |    7 +-
 .../urlencoding/UrlEncodingParserSession.java      |    6 +-
 .../java/org/apache/juneau/xml/XmlBeanMeta.java    |    2 +-
 .../apache/juneau/rest/client/ResponseContent.java |    4 +-
 .../java/org/apache/juneau/http/HttpParts.java     |    3 +-
 .../apache/juneau/rest/rrpc/RrpcRestOpContext.java |    2 +-
 .../java/org/apache/juneau/PojoExamplesTest.java   |   32 -
 .../apache/juneau/commons/reflect/Setter_Test.java |   28 +-
 .../juneau/jsonschema/JsonSchemaGeneratorTest.java |    4 +-
 .../client/RestClient_Config_RestClient_Test.java  |    2 +-
 22 files changed, 752 insertions(+), 784 deletions(-)

diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ClassInfo.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ClassInfo.java
index 18a0b299b3..dbd3559bb7 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ClassInfo.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ClassInfo.java
@@ -1895,6 +1895,14 @@ public class ClassInfo extends ElementInfo implements 
Annotatable, Type {
                return false;
        }
 
+       public boolean isAny(Class<?> t1, Class<?> t2) {
+               return inner == t1 || inner == t2;
+       }
+
+       public boolean isAny(Class<?> t1, Class<?> t2, Class<?> t3) {
+               return inner == t1 || inner == t2 || inner == t3;
+       }
+
        /**
         * Returns <jk>true</jk> if this class is an array.
         *
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ClassInfoTyped.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ClassInfoTyped.java
index 2e7bd8a419..49248b3298 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ClassInfoTyped.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ClassInfoTyped.java
@@ -44,4 +44,6 @@ public class ClassInfoTyped<T> extends ClassInfo {
                super(inner, innerType);
        }
 
+       @Override
+       public T getPrimitiveDefault() { return (T)super.getPrimitiveDefault(); 
}
 }
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/Setter.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/Setter.java
index 6912bc20c9..abf30f2b42 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/Setter.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/Setter.java
@@ -16,6 +16,8 @@
  */
 package org.apache.juneau.commons.reflect;
 
+import static org.apache.juneau.commons.reflect.ReflectionUtils.*;
+
 import java.lang.reflect.*;
 
 /**
@@ -73,19 +75,20 @@ public interface Setter {
         */
        static class FieldSetter implements Setter {
 
-               private final Field f;
+               private final FieldInfo f;
 
+               @Deprecated
                public FieldSetter(Field f) {
+                       this.f = info(f);
+               }
+
+               public FieldSetter(FieldInfo f) {
                        this.f = f;
                }
 
                @Override /* Overridden from Setter */
                public void set(Object object, Object value) throws 
ExecutableException {
-                       try {
-                               f.set(object, value);
-                       } catch (IllegalArgumentException | 
IllegalAccessException e) {
-                               throw new ExecutableException(e);
-                       }
+                       f.set(object, value);
                }
        }
 
@@ -99,19 +102,20 @@ public interface Setter {
         */
        static class MethodSetter implements Setter {
 
-               private final Method m;
+               private final MethodInfo m;
 
+               @Deprecated
                public MethodSetter(Method m) {
+                       this.m = info(m);
+               }
+
+               public MethodSetter(MethodInfo m) {
                        this.m = m;
                }
 
                @Override /* Overridden from Setter */
                public void set(Object object, Object value) throws 
ExecutableException {
-                       try {
-                               m.invoke(object, value);
-                       } catch (IllegalArgumentException | 
IllegalAccessException | InvocationTargetException e) {
-                               throw new ExecutableException(e);
-                       }
+                       m.invoke(object, value);
                }
        }
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
index 6fbc5eeaa2..8746f0b110 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
@@ -194,7 +194,7 @@ public class BeanMeta<T> {
 
                String init(BeanMeta<T> beanMeta) {
                        var c = classMeta.getInnerClass();
-                       var ci = classMeta.getInfo();
+                       var ci = classMeta;
                        var ap = ctx.getAnnotationProvider();
 
                        try {
@@ -1045,7 +1045,7 @@ public class BeanMeta<T> {
         */
        @SuppressWarnings("unchecked")
        protected T newBean(Object outer) throws ExecutableException {
-               if (classMeta.isMemberClass()) {
+               if (classMeta.isMemberClass() && classMeta.isNotStatic()) {
                        if (nn(constructor))
                                return constructor.<T>newInstance(outer);
                } else {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
index 9c665e8da9..10674c9f2c 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
@@ -292,7 +292,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                        isDyna = "*".equals(name);
 
                        // Do some annotation validation.
-                       var ci = rawTypeMeta.getInfo();
+                       var ci = rawTypeMeta;
                        if (nn(getter)) {
                                var pt = getter.getParameterTypes();
                                if (isDyna) {
@@ -687,7 +687,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                var si = setter == null ? null : info(setter);
                if (a == null)
                        return l;
-               rstream(ap.find(a, 
getBeanMeta().getClassMeta().getInfo())).forEach(x -> l.add(x.inner()));
+               rstream(ap.find(a, getBeanMeta().getClassMeta())).forEach(x -> 
l.add(x.inner()));
                if (nn(field)) {
                        ap.find(a, fi).forEach(x -> l.add(x.inner()));
                        rstream(ap.find(a, info(field.getType()))).forEach(x -> 
l.add(x.inner()));
@@ -1096,7 +1096,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
 
                                var r = (bc.isBeanMapPutReturnsOldValue() || 
isMap || isCollection) && (nn(getter) || nn(field)) ? get(m, pName) : null;
                                var propertyClass = rawTypeMeta.getInnerClass();
-                               var pcInfo = rawTypeMeta.getInfo();
+                               var pcInfo = rawTypeMeta;
 
                                if (value == null && (isMap || isCollection)) {
                                        invokeSetter(bean, pName, null);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java
index e09a044057..fe81dd4177 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java
@@ -1177,7 +1177,7 @@ public class BeanSession extends ContextSession {
                        // If no conversion needed, then just return the value.
                        // Don't include maps or collections, because child 
elements may need conversion.
                        if (tc.isInstance(value))
-                               if (! ((to.isMap() && 
to.getValueType().isNotObject()) || ((to.isCollection() || to.isOptional()) && 
to.getElementType().isNotObject())))
+                               if (! ((to.isMap() && ! 
to.getValueType().is(Object.class)) || ((to.isCollection() || to.isOptional()) 
&& ! to.getElementType().isObject())))
                                        return (T)value;
 
                        ObjectSwap swap = to.getSwap(this);
@@ -1233,7 +1233,7 @@ public class BeanSession extends ContextSession {
                                                if (tc == Byte.TYPE)
                                                        return 
(T)(Byte.valueOf(b ? (byte)1 : 0));
                                        } else if (isNullOrEmpty(value)) {
-                                               return 
(T)to.info.getPrimitiveDefault();
+                                               return to.getPrimitiveDefault();
                                        } else {
                                                var s = value.toString();
                                                var multiplier = (tc == 
Integer.TYPE || tc == Short.TYPE || tc == Long.TYPE) ? getMultiplier(s) : 1;
@@ -1263,14 +1263,14 @@ public class BeanSession extends ContextSession {
                                        }
                                } else if (to.isChar()) {
                                        if (isNullOrEmpty(value))
-                                               return 
(T)to.info.getPrimitiveDefault();
+                                               return to.getPrimitiveDefault();
                                        return (T)parseCharacter(value);
                                } else if (to.isBoolean()) {
                                        if (from.isNumber()) {
                                                var i = 
((Number)value).intValue();
                                                return (T)(i == 0 ? 
Boolean.FALSE : Boolean.TRUE);
                                        } else if (isNullOrEmpty(value)) {
-                                               return 
(T)to.info.getPrimitiveDefault();
+                                               return to.getPrimitiveDefault();
                                        } else {
                                                return 
(T)Boolean.valueOf(value.toString());
                                        }
@@ -1397,14 +1397,14 @@ public class BeanSession extends ContextSession {
                                                var valueType = 
to.getValueType();
                                                ((Map<?,?>)value).forEach((k, 
v) -> {
                                                        var k2 = k;
-                                                       if 
(keyType.isNotObject()) {
+                                                       if (! 
keyType.isObject()) {
                                                                if 
(keyType.isString() && k.getClass() != Class.class)
                                                                        k2 = 
k.toString();
                                                                else
                                                                        k2 = 
convertToMemberType(m, k, keyType);
                                                        }
                                                        var v2 = v;
-                                                       if 
(valueType.isNotObject())
+                                                       if (! 
valueType.isObject())
                                                                v2 = 
convertToMemberType(m, v, valueType);
                                                        m.put(k2, v2);
                                                });
@@ -1466,7 +1466,7 @@ public class BeanSession extends ContextSession {
                                        var ws = 
ctx.getBeanToStringSerializer();
                                        if (nn(ws))
                                                return (T)ws.serialize(value);
-                               } else if (from.isClass()) {
+                               } else if (from.is(Class.class)) {
                                        return (T)((Class<?>)value).getName();
                                }
                                return (T)value.toString();
@@ -1505,7 +1505,7 @@ public class BeanSession extends ContextSession {
                                        var typeName = 
m2.getString(getBeanTypePropertyName(to));
                                        if (nn(typeName)) {
                                                var cm = 
to.getBeanRegistry().getClassMeta(typeName);
-                                               if (nn(cm) && 
to.info.isParentOf(cm.innerClass))
+                                               if (nn(cm) && 
to.isParentOf(cm.innerClass))
                                                        return (T)m2.cast(cm);
                                        }
                                }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
index 78c5526ae1..8aaab53fdf 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
@@ -16,7 +16,7 @@
  */
 package org.apache.juneau;
 
-import static org.apache.juneau.ClassMeta.ClassCategory.*;
+import static org.apache.juneau.ClassMeta.Category.*;
 import static org.apache.juneau.commons.reflect.ReflectionUtils.*;
 import static org.apache.juneau.commons.utils.CollectionUtils.*;
 import static org.apache.juneau.commons.utils.PredicateUtils.*;
@@ -35,6 +35,7 @@ import java.util.function.*;
 
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.commons.collections.*;
+import org.apache.juneau.commons.function.*;
 import org.apache.juneau.commons.reflect.*;
 import org.apache.juneau.commons.utils.*;
 import org.apache.juneau.cp.*;
@@ -63,7 +64,7 @@ import org.apache.juneau.swap.*;
  *
  * @param <T> The class type of the wrapped class.
  */
-@Bean(properties = 
"innerClass,classCategory,elementType,keyType,valueType,notABeanReason,initException,beanMeta")
+@Bean(properties = 
"innerClass,elementType,keyType,valueType,notABeanReason,initException,beanMeta")
 public class ClassMeta<T> extends ClassInfoTyped<T> {
 
        private static final AnnotationProvider AP = 
AnnotationProvider.INSTANCE;
@@ -71,241 +72,44 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
        @SuppressWarnings({ "unchecked", "rawtypes", "hiding" })
        private 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();
+               ConstructorInfo noArgConstructor = null;
                ClassMeta<?> keyType = null, valueType = null, elementType = 
null;
-               String typePropertyName = null, notABeanReason = null, 
dictionaryName = null;
+               String typePropertyName = null, notABeanReason = 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;
-               BidiMap.Builder<Object,String> enumValues;
-
-               ClassMetaBuilder(Class<T> innerClass, BeanContext beanContext, 
ObjectSwap<T,?>[] swaps, ObjectSwap<?,?>[] childSwaps) {
+
+               ClassMetaBuilder(ClassInfo ci, Class<T> innerClass, BeanContext 
beanContext) {
                        this.innerClass = innerClass;
                        this.beanContext = beanContext;
                        var bc = beanContext;
                        var ap = bc.getAnnotationProvider();
 
-                       this.childSwaps = childSwaps;
-                       if (childSwaps == null) {
-                               this.childSwapMap = null;
-                               this.childUnswapMap = null;
-                       } else {
-                               this.childSwapMap = new ConcurrentHashMap<>();
-                               this.childUnswapMap = new ConcurrentHashMap<>();
-                       }
-
-                       var c = innerClass;
-                       ci = info(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) 
|| ap.has(Uri.class, ci))
-                                       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" };
-                       // @formatter:off
-                       fromStringMethod = ci.getPublicMethod(
-                                       x -> x.isStatic()
-                                       && x.isNotDeprecated()
-                                       && x.hasReturnType(c)
-                                       && x.hasParameterTypes(String.class)
-                                       && contains(x.getName(), 
fromStringMethodNames))
-                               .map(x -> x.inner())
-                               .orElse(null);
-                       // @formatter:on
-
-                       // Find example() method if present.
-                       // @formatter:off
-                       exampleMethod = ci.getPublicMethod(
-                                       x -> x.isStatic()
-                                       && x.isNotDeprecated()
-                                       && x.hasName("example")
-                                       && 
x.hasParameterTypesLenient(BeanSession.class))
-                               .map(x -> x.inner())
-                               .orElse(null);
-                       // @formatter:on
-
-                       ci.getAllFields().stream().filter(x -> 
ap.has(ParentProperty.class, x)).forEach(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.getAllFields().stream().filter(x -> 
ap.has(NameProperty.class, x)).forEach(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.getDeclaredFields().stream().filter(x -> 
ap.has(Example.class, x)).forEach(x -> {
-                               if (! (x.isStatic() && 
ci.isParentOf(x.getFieldType().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.
-                       var methods = ci.getAllMethods();
-                       for (var i = methods.size() - 1; i >= 0; i--) {
-                               var m = methods.get(i);
-                               if (m.getMatchingMethods().stream().anyMatch(m2 
-> ap.has(ParentProperty.class, m2))) {
-                                       if (m.isStatic() || ! 
m.hasNumParameters(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.getMatchingMethods().stream().anyMatch(m2 
-> ap.has(NameProperty.class, m2))) {
-                                       if (m.isStatic() || ! 
m.hasNumParameters(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.getDeclaredMethods().stream().filter(m -> 
m.getMatchingMethods().stream().anyMatch(m2 -> ap.has(Example.class, 
m2))).forEach(m -> {
-                               if (! (m.isStatic() && 
m.hasParameterTypesLenient(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();
+                       Class c = ClassMeta.this.inner();
 
                        // Find constructor(String) method if present.
                        ci.getPublicConstructors().stream().filter(cs -> 
cs.isPublic() && cs.isNotDeprecated()).forEach(cs -> {
                                var params = cs.getParameters();
-                               if (params.size() == (isMemberClass ? 1 : 0) && 
c != Object.class && ! isAbstract) {
+                               if (params.size() == (ci.isMemberClass() && 
ci.isNotStatic() ? 1 : 0) && c != Object.class && ! (ci.isAbstract() && 
ci.isNotPrimitive())) {
                                        noArgConstructor = cs;
-                               } else if (params.size() == (isMemberClass ? 2 
: 1)) {
-                                       var arg = params.get(isMemberClass ? 1 
: 0).getParameterType();
-                                       if (arg.is(String.class))
-                                               stringConstructor = cs;
                                }
                        });
 
-                       primitiveDefault = ci.getPrimitiveDefault();
-
-                       // @formatter:off
-                       ci.getPublicMethods().stream()
-                               .filter(MethodInfo::isNotDeprecated)
-                               .forEach(x -> 
publicMethods.put(x.getSignature(), x.inner()));
-                       // @formatter:on
-
-                       var beanFilter = findBeanFilter(bc);
-                       var marshalledFilter = findMarshalledFilter(bc);
-
-                       addAll(this.swaps, swaps);
-
-                       if (nn(bc))
-                               this.builderSwap = 
BuilderSwap.findSwapFromObjectClass(bc, c, bc.getBeanConstructorVisibility(), 
bc.getBeanMethodVisibility());
-
-                       findSwaps(this.swaps, bc);
-
-                       if (nn(beanFilter)) {
-                               example = beanFilter.getExample();
-                               implClass = (Class<? extends 
T>)beanFilter.getImplClass();
-                       }
-
-                       if (nn(marshalledFilter)) {
-                               if (example == null)
-                                       example = marshalledFilter.getExample();
-                               if (implClass == null)
-                                       implClass = (Class<? extends 
T>)marshalledFilter.getImplClass();
-                       }
-
                        if (innerClass != Object.class) {
-                               var x = implClass == null ? ci : 
info(implClass);
+                               var x = implClass2.get() == null ? ci : 
implClass2.get();
                                noArgConstructor = x.getPublicConstructor(cons 
-> cons.getParameterCount() == 0).orElse(null);
                        }
 
                        try {
 
                                // If this is an array, get the element type.
-                               if (cc == ARRAY)
+                               if (cat.is(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) {
+                               else if (cat.is(MAP) && ! cat.is(BEANMAP)) {
                                        ClassMeta[] parameters = 
findParameters();
                                        if (nn(parameters) && parameters.length 
== 2) {
                                                keyType = parameters[0];
@@ -317,7 +121,7 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                                }
 
                                // If this is a COLLECTION, see if it's 
parameterized (e.g. AddressBook extends LinkedList<Person>)
-                               else if (cc == COLLECTION || cc == OPTIONAL) {
+                               else if (cat.is(COLLECTION) || 
ci.is(Optional.class)) {
                                        ClassMeta[] parameters = 
findParameters();
                                        if (nn(parameters) && parameters.length 
== 1) {
                                                elementType = parameters[0];
@@ -328,11 +132,11 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
 
                                // 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) {
+                               if (cat.isUnknown()) {
 
                                        var newMeta = (BeanMeta)null;
                                        try {
-                                               newMeta = new 
BeanMeta(ClassMeta.this, bc, beanFilter, null, implClass == null ? null : 
noArgConstructor);
+                                               newMeta = new 
BeanMeta(ClassMeta.this, bc, beanFilter.get(), null, implClass2.get() == null ? 
null : noArgConstructor);
                                                notABeanReason = 
newMeta.notABeanReason;
 
                                                // Always get these even if 
it's not a bean:
@@ -354,9 +158,6 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                                throw e;
                        }
 
-                       if (nn(beanMeta))
-                               dictionaryName = beanMeta.getDictionaryName();
-
                        if (nn(beanMeta) && nn(bc) && 
bc.isUseInterfaceProxies() && innerClass.isInterface())
                                invocationHandler = new 
BeanProxyInvocationHandler<T>(beanMeta);
 
@@ -364,135 +165,79 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                                ap.find(Bean.class, 
ci).stream().map(AnnotationInfo::inner).forEach(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 && nn(bc)) {
-                               rstream(ap.find(Example.class, ci)).map(x -> 
x.inner().value()).filter(Utils::isNotEmpty).findFirst().ifPresent(x -> example 
= x);
-                       }
-
-                       if (example == null) {
-                               example = switch (cc) {
-                                       case BOOLEAN -> "true";
-                                       case CHAR -> "a";
-                                       case CHARSEQ, STR -> "foo";
-                                       case DECIMAL -> {
-                                               if (isFloat())
-                                                       yield "1.0";
-                                               else if (isDouble())
-                                                       yield "1.0";
-                                               yield null;
-                                       }
-                                       case ENUM -> {
-                                               Iterator<? extends Enum> i = 
EnumSet.allOf((Class<? extends Enum>)c).iterator();
-                                               yield i.hasNext() ? 
(beanContext.isUseEnumNames() ? i.next().name() : i.next().toString()) : null;
-                                       }
-                                       case NUMBER -> {
-                                               if (isShort())
-                                                       yield "1";
-                                               else if (isInteger())
-                                                       yield "1";
-                                               else if (isLong())
-                                                       yield "1";
-                                               yield null;
-                                       }
-                                       case URI, ARGS, ARRAY, BEANMAP, CLASS, 
COLLECTION, DATE, INPUTSTREAM, MAP, METHOD, OBJ, OTHER, READER, OPTIONAL, VOID 
-> null;
-                                       default -> null;
-                               };
-                       }
-
-                       this.stringMutater = Mutaters.get(String.class, c);
-
-                       if (cc == ENUM) {
-                               Class<? extends Enum> ec = (Class<? extends 
Enum<?>>)c;
-                               var useEnumNames = nn(bc) && 
bc.isUseEnumNames();
-                               enumValues = BidiMap.create();
-                               enumValues.unmodifiable();
-                               stream(ec.getEnumConstants()).forEach(x -> 
enumValues.add(x, useEnumNames ? x.name() : x.toString()));
-                       }
+               private ClassMeta<?> findClassMeta(Class<?> c) {
+                       return beanContext.getClassMeta(c, false);
                }
 
-               private ObjectSwap<T,?> createSwap(Swap s) {
-                       var c = s.value();
-                       if (ClassUtils.isVoid(c))
-                               c = s.impl();
-                       var ci = info(c);
-
-                       if (ci.isChildOf(ObjectSwap.class)) {
-                               var 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;
-                       }
+               private ClassMeta<?>[] findParameters() {
+                       return beanContext.findParameters(innerClass, 
innerClass);
+               }
 
-                       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);
+       enum Category {
+               MAP(0),
+               COLLECTION(1),
+               NUMBER(2),
+               DECIMAL(3),
+               DATE(4),
+               ARRAY(5),
+               ENUM(6),
+               CHARSEQ(8),
+               STR(9),
+               URI(10),
+               BEANMAP(11),
+               READER(12),
+               INPUTSTREAM(13),
+               ARGS(14),
+               CALENDAR(15),
+               TEMPORAL(16),
+               LIST(17),
+               SET(18),
+               DELEGATE(19);
+
+               private final int mask;
+
+               Category(int bitPosition) {
+                       this.mask = 1 << bitPosition;
                }
+       }
 
-               private BeanFilter findBeanFilter(BeanContext bc) {
-                       try {
-                               var ba = 
rstream(bc.getAnnotationProvider().find(Bean.class, 
info)).map(AnnotationInfo::inner).toList();
-                               if (! ba.isEmpty())
-                                       return 
BeanFilter.create(innerClass).applyAnnotations(ba).build();
-                       } catch (Exception e) {
-                               throw toRex(e);
-                       }
-                       return null;
-               }
+       static class Categories {
+               int bits;
 
-               private ClassMeta<?> findClassMeta(Class<?> c) {
-                       return beanContext.getClassMeta(c, false);
+               boolean is(Category c) {
+                       return (bits & c.mask) != 0;
                }
 
-               private MarshalledFilter findMarshalledFilter(BeanContext bc) {
-                       try {
-                               var ba = 
rstream(bc.getAnnotationProvider().find(Marshalled.class, 
info)).map(AnnotationInfo::inner).toList();
-                               if (! ba.isEmpty())
-                                       return 
MarshalledFilter.create(innerClass).applyAnnotations(ba).build();
-                       } catch (Exception e) {
-                               throw toRex(e);
-                       }
-                       return null;
+               boolean isNot(Category c) {
+                       return ! is(c);
                }
 
-               private ClassMeta<?>[] findParameters() {
-                       return beanContext.findParameters(innerClass, 
innerClass);
+               Categories set(Category c) {
+                       bits |= c.mask;
+                       return this;
                }
 
-               private void findSwaps(List<ObjectSwap> l, BeanContext bc) {
-
-                       if (nn(bc))
-                               bc.getAnnotationProvider().find(Swap.class, 
ci).stream().map(AnnotationInfo::inner).forEach(x -> l.add(createSwap(x)));
-
-                       var ds = DefaultSwaps.find(ci);
-                       if (ds == null)
-                               ds = AutoObjectSwap.find(bc, ci);
-                       if (ds == null)
-                               ds = AutoNumberSwap.find(bc, ci);
-                       if (ds == null)
-                               ds = AutoMapSwap.find(bc, ci);
-                       if (ds == null)
-                               ds = AutoListSwap.find(bc, ci);
+               boolean isUnknown() {
+                       return bits == 0;
+               }
 
-                       if (nn(ds))
-                               l.add(ds);
+               public boolean same(Categories cat) {
+                       return cat.bits == bits;
                }
        }
 
-       /** 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
-       }
+       /**
+        * Checks if the specified category is set in the bitmap.
+        *
+        * @param category The category to check.
+        * @return {@code true} if the category is set, {@code false} otherwise.
+        */
 
        /**
         * Generated classes shouldn't be cacheable to prevent needlessly 
filling up the cache.
@@ -525,52 +270,35 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                var ci = info(c);
                if (ci.isAbstract())
                        return null;
+
                var isMemberClass = ci.isMemberClass() && ci.isNotStatic();
+               var numParams = isMemberClass ? 1 : 0;
+
                // @formatter:off
-               return ci.getPublicConstructor(
-                       x -> x.isVisible(v)
-                       && x.isNotDeprecated()
-                       && x.hasNumParameters(isMemberClass ? 1 : 0)
-               )
-               .map(cc -> (Constructor<? extends T>)v.transform(cc.inner()))
-               .orElse(null);
+               return ci.getPublicConstructor(x -> x.isVisible(v)&& 
x.isNotDeprecated() && x.hasNumParameters(numParams))
+                       .map(x -> (Constructor<? extends 
T>)v.transform(x.inner()))
+                       .orElse(null);
                // @formatter:on
        }
 
        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 Categories cat;                         // The class 
category.
        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 ConcurrentHashMap<Class<?>,ObjectSwap<?,?>> childSwapMap; 
                                       // Maps normal subclasses to ObjectSwaps.
+       private final ConcurrentHashMap<Class<?>,ObjectSwap<?,?>> 
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 ClassMeta<?> elementType;                                 
        // If ARRAY or COLLECTION, the element class type.
+       private final ClassMeta<?> keyType;                                     
        // If MAP, the key class type.
+       private final ClassMeta<?> 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 String typePropertyName;                                  
  // The property name of the _type property for this class and subclasses.
+       private final String notABeanReason;                                    
  // If this isn't a bean, the reason why.
        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;
@@ -580,10 +308,313 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
 
        private final Map<String,Optional<?>> properties = new 
ConcurrentHashMap<>();
 
-       private final BidiMap<Object,String> enumValues;
-
        private final SimpleReadWriteLock lock = new SimpleReadWriteLock(false);
 
+       private final Supplier<String> typePropertyName2;                       
             // The property name of the _type property for this class and 
subclasses.
+
+       private String findTypePropertyName() {
+               var b = beanMeta2.get();
+               if (b.getA() != null)
+                       return b.getA().typePropertyName;
+               return null;
+       }
+
+       private final Supplier<Tuple2<BeanMeta<T>,String>> beanMeta2;
+
+       private Tuple2<BeanMeta<T>,String> findBeanMeta() {
+               if (! cat.isUnknown())
+                       return new Tuple2<>(null, "Known non-bean type");
+               if (beanContext == null)
+                       return new Tuple2<>(null, "No bean context");
+
+               BeanMeta<T> newMeta = null;
+               String notABeanReason = null;
+               try {
+                       newMeta = new BeanMeta<>(ClassMeta.this, beanContext, 
beanFilter.get(), null, implClass2.get() == null ? null : 
noArgConstructor.get());
+                       notABeanReason = newMeta.notABeanReason;
+               } catch (RuntimeException e) {
+                       notABeanReason = e.getMessage();
+                       throw e;
+               }
+               return Tuple2.of(newMeta, notABeanReason);
+       }
+
+       private final Supplier<BeanRegistry> beanRegistry2;                // 
The bean registry of this class meta (if it has one).
+       private final Supplier<String> dictionaryName;                          
            // The dictionary name of this class if it has one.
+
+       private BeanRegistry findBeanRegistry() {
+               if (beanContext == null)
+                       return null;
+
+               var b = beanMeta2.get();
+               if (b.getA() != null)
+                       return b.getA().beanRegistry;
+
+               return beanContext.getAnnotationProvider().find(Bean.class, 
this)
+                       .stream()
+                       .map(AnnotationInfo::inner)
+                       .filter(x -> x.dictionary().length > 0)
+                       .map(x -> new BeanRegistry(beanContext, null, 
x.dictionary()))
+                       .findFirst()
+                       .orElse(null);
+       }
+
+       private String findBeanDictionaryName() {
+               if (beanContext == null)
+                       return null;
+
+               if (nn(beanMeta) && beanMeta.getDictionaryName() != null)
+                       return beanMeta.getDictionaryName();
+
+               return beanContext.getAnnotationProvider().find(Bean.class, 
this)
+                       .stream()
+                       .map(AnnotationInfo::inner)
+                       .filter(x -> ! x.typeName().isEmpty())
+                       .map(x -> x.typeName())
+                       .findFirst()
+                       .orElse(null);
+       }
+
+       private final Supplier<MethodInfo> fromStringMethod;  // Static 
fromString(String) or equivalent method
+
+       private MethodInfo findFromStringMethod() {
+               // 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
+               // @formatter:off
+               var names = a("fromString", "fromValue", "valueOf", "parse", 
"parseString", "forName", "forString");
+               return getPublicMethod(
+                       x -> x.isStatic() && x.isNotDeprecated() && 
x.hasReturnType(this) && x.hasParameterTypes(String.class) && 
contains(x.getName(), names)
+               ).orElse(null);
+               // @formatter:on
+       }
+
+       private final Supplier<MethodInfo> exampleMethod;  // The example() or 
@Example-annotated method (if it has one).
+
+       private MethodInfo findExampleMethod() {
+               // @formatter:off
+               var ap = beanContext.getAnnotationProvider();
+
+               // Option 1:  Public example() or @Example method.
+               var m = getPublicMethod(
+                       x -> x.isStatic() && x.isNotDeprecated() && 
(x.hasName("example") || ap.has(Example.class, x)) && 
x.hasParameterTypesLenient(BeanSession.class)
+               );
+               if (m.isPresent()) return m.get();
+
+               // Option 2:  Non-public @Example method.
+               return getDeclaredMethods()
+                       .stream()
+                       .flatMap(x -> x.getMatchingMethods().stream())
+                       .filter(x -> x.isStatic() && ap.has(Example.class, x))
+                       .map(x -> x.accessible())
+                       .findFirst()
+                       .orElse(null);
+               // @formatter:on
+       }
+
+       private final Supplier<Setter> parentPropertySetter;  // The method to 
set the parent on an object (if it has one).
+
+       private Setter findParentPropertySetter() {
+               var ap = beanContext.getAnnotationProvider();
+
+               var s = getAllFields()
+                       .stream()
+                       .filter(x -> x.isStatic() && 
ap.has(ParentProperty.class, x))
+                       .map(x -> x.accessible())
+                       .map(x -> new Setter.FieldSetter(x))
+                       .findFirst();
+
+               if (s.isPresent()) return s.get();
+
+               return getAllMethods()
+                       .stream()
+                       .filter(x -> x.isStatic() || x.hasNumParameters(1))
+                       .filter(x -> ap.has(ParentProperty.class, x))
+                       .map(x -> x.accessible())
+                       .map(x -> new Setter.MethodSetter(x))
+                       .findFirst()
+                       .orElse(null);
+       }
+
+       private final Supplier<Setter> namePropertySetter;  // The method to 
set the name on an object (if it has one).
+
+       private Setter findNamePropertySetter() {
+               var ap = beanContext.getAnnotationProvider();
+
+               var s = getAllFields()
+                       .stream()
+                       .filter(x -> x.isStatic() && ap.has(NameProperty.class, 
x))
+                       .map(x -> x.accessible())
+                       .map(x -> new Setter.FieldSetter(x))
+                       .findFirst();
+
+               if (s.isPresent()) return s.get();
+
+               return getAllMethods()
+                       .stream()
+                       .filter(x -> x.isStatic() || x.hasNumParameters(1))
+                       .filter(x -> ap.has(NameProperty.class, x))
+                       .map(x -> x.accessible())
+                       .map(x -> new Setter.MethodSetter(x))
+                       .findFirst()
+                       .orElse(null);
+       }
+
+       private final Supplier<FieldInfo> exampleField;                         
               // The @Example-annotated field (if it has one).
+
+       private FieldInfo findExampleField() {
+               var ap = beanContext.getAnnotationProvider();
+
+               return getDeclaredFields()
+                       .stream()
+                       .filter(x -> x.isStatic() && 
isParentOf(x.getFieldType()) && ap.has(Example.class, x))
+                       .map(x -> x.accessible())
+                       .findFirst()
+                       .orElse(null);
+       }
+
+       private final Supplier<ConstructorInfo> noArgConstructor;               
                     // The no-arg constructor for this class (if it has one).
+       private final Supplier<ConstructorInfo> stringConstructor;              
                     // The X(String) constructor (if it has one).
+
+       private ConstructorInfo findNoArgConstructor() {
+
+               if (is(Object.class) || isAbstract())
+                       return null;
+
+               if (implClass2.get() != null)
+                       return implClass2.get().getPublicConstructor(x -> 
x.hasNumParameters(0)).orElse(null);
+
+               if (isAbstract())
+                       return null;
+
+               var numParams = isMemberClass() && isNotStatic() ? 1 : 0;
+               return getPublicConstructors()
+                       .stream()
+                       .filter(x -> x.isPublic() && x.isNotDeprecated() && 
x.hasNumParameters(numParams))
+                       .findFirst()
+                       .orElse(null);
+       }
+
+       private ConstructorInfo findStringConstructor() {
+
+               if (is(Object.class) || isAbstract())
+                       return null;
+
+               if (implClass2.get() != null)
+                       return implClass2.get().getPublicConstructor(x -> 
x.hasParameterTypes(String.class)).orElse(null);
+
+               if (isAbstract())
+                       return null;
+
+               var numParams = isMemberClass() && isNotStatic() ? 2 : 1;
+               return getPublicConstructors()
+                       .stream()
+                       .filter(x -> x.isPublic() && x.isNotDeprecated() && 
x.hasNumParameters(numParams))
+                       .filter(x -> x.getParameter(numParams == 2 ? 1 : 
0).isType(String.class))
+                       .findFirst()
+                       .orElse(null);
+       }
+
+       private final Supplier<BeanFilter> beanFilter;
+       private final Supplier<MarshalledFilter> marshalledFilter;
+
+       private BeanFilter findBeanFilter() {
+               var ap = beanContext.getAnnotationProvider();
+               var l = ap.find(Bean.class, this);
+               if (l.isEmpty())
+                       return null;
+               return 
BeanFilter.create(inner()).applyAnnotations(reverse(l.stream().map(AnnotationInfo::inner).toList())).build();
+       }
+
+       private MarshalledFilter findMarshalledFilter() {
+               var ap = beanContext.getAnnotationProvider();
+               var l = ap.find(Marshalled.class, this);
+               if (l.isEmpty())
+                       return null;
+               return 
MarshalledFilter.create(inner()).applyAnnotations(reverse(l.stream().map(AnnotationInfo::inner).toList())).build();
+       }
+
+       private final Supplier<BuilderSwap<T,?>> builderSwap;             // 
The builder swap associated with this bean (if it has one).
+
+       @SuppressWarnings("unchecked")
+       private BuilderSwap<T,?> findBuilderSwap() {
+               var bc = beanContext;
+               if (bc == null)
+                       return null;
+               return 
(BuilderSwap<T,?>)BuilderSwap.findSwapFromObjectClass(bc, inner(), 
bc.getBeanConstructorVisibility(), bc.getBeanMethodVisibility());
+       }
+
+       private final Supplier<String> example;                           // 
Example JSON.
+
+       private String findExample() {
+
+               var example = opt(beanFilter.get()).map(x -> 
x.getExample()).orElse(null);
+
+               if (example == null)
+                       example = opt(marshalledFilter.get()).map(x -> 
x.getExample()).orElse(null);
+
+               if (example == null && nn(beanContext))
+                       example = 
beanContext.getAnnotationProvider().find(Example.class, this).stream().map(x -> 
x.inner().value()).filter(Utils::isNotEmpty).findFirst().orElse(null);
+
+               if (example == null) {
+                       if (isAny(boolean.class, Boolean.class)) {
+                               example = "true";
+                       } else if (isAny(char.class, Character.class)) {
+                               example = "a";
+                       } else if (cat.is(CHARSEQ)) {
+                               example = "foo";
+                       } else if (cat.is(ENUM)) {
+                               Iterator<? extends Enum<?>> i = 
EnumSet.allOf((Class<? extends Enum>)(Class)inner()).iterator();
+                               example = i.hasNext() ? 
(beanContext.isUseEnumNames() ? i.next().name() : i.next().toString()) : null;
+                       } else if (isAny(float.class, Float.class, 
double.class, Double.class)) {
+                               example = "1.0";
+                       } else if (isAny(short.class, Short.class, int.class, 
Integer.class, long.class, Long.class)) {
+                               example = "1";
+                       }
+               }
+
+               return example;
+       }
+
+       private final Supplier<ClassInfoTyped<? extends T>> implClass2;         
    // The implementation class to use if this is an interface.
+
+       @SuppressWarnings("unchecked")
+       private ClassInfoTyped<? extends T> findImplClass() {
+
+               if (is(Object.class))
+                       return null;
+
+               var v = opt(beanFilter.get()).map(x -> 
x.getImplClass()).map(ReflectionUtils::info).orElse(null);
+
+               if (v == null)
+                       v = opt(marshalledFilter.get()).map(x -> 
x.getImplClass()).map(ReflectionUtils::info).orElse(null);
+
+               return (ClassInfoTyped<? extends T>)v;
+       }
+
+       private final ClassMeta<?> elementType2;                                
         // If ARRAY or COLLECTION, the element class type.
+       private final ClassMeta<?> keyType2;                                    
         // If MAP, the key class type.
+       private final ClassMeta<?> valueType2;                                  
         // If MAP, the value class type.
+
+       private final Supplier<BidiMap<Object,String>> enumValues;
+
+       private BidiMap<Object,String> findEnumValues() {
+               if (! isEnum())
+                       return null;
+
+               var bc = beanContext;
+               var useEnumNames = nn(bc) && bc.isUseEnumNames();
+
+               var m = BidiMap.<Object,String>create().unmodifiable();
+               var c = (Class<? extends Enum<?>>)(Class)inner();
+               stream(c.getEnumConstants()).forEach(x -> m.add(x, useEnumNames 
? x.name() : x.toString()));
+               return m.build();
+       }
+
+
        /**
         * Construct a new {@code ClassMeta} based on the specified {@link 
Class}.
         *
@@ -609,6 +640,7 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                this.innerClass = innerClass;
                this.info = info(innerClass);
                this.beanContext = beanContext;
+               this.cat = new Categories();
                var notABeanReason = (String)null;
 
                try (var x = lock.write()) {
@@ -616,19 +648,125 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                        if (nn(beanContext) && nn(beanContext.cmCache) && 
isCacheable(innerClass))
                                beanContext.cmCache.put(innerClass, this);
 
-                       var 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;
+                       var ap = beanContext.getAnnotationProvider();
+
+                       if (isChildOf(Delegate.class)) {
+                               cat.set(DELEGATE);
+                       }
+                       if (isEnum()) {
+                               cat.set(ENUM);
+                       } else if (isChildOf(CharSequence.class)) {
+                               cat.set(CHARSEQ);
+                               if (is(String.class)) {
+                                       cat.set(STR);
+                               }
+                       } else if (isChildOf(Number.class) || isAny(byte.class, 
short.class, int.class, long.class, float.class, double.class)) {
+                               cat.set(NUMBER);
+                               if (isChildOfAny(Float.class, Double.class) || 
isAny(float.class, double.class)) {
+                                       cat.set(DECIMAL);
+                               }
+                       } else if (isChildOf(Collection.class)) {
+                               cat.set(COLLECTION);
+                               if (isChildOf(Set.class)) {
+                                       cat.set(SET);
+                               } else if (isChildOf(List.class)) {
+                                       cat.set(LIST);
+                               }
+                       } else if (isChildOf(Map.class)) {
+                               cat.set(MAP);
+                               if (isChildOf(BeanMap.class)) {
+                                       cat.set(BEANMAP);
+                               }
+                       } else if (isChildOfAny(Date.class, Calendar.class)) {
+                               if (isChildOf(Date.class)) {
+                                       cat.set(DATE);
+                               } else if (isChildOf(Calendar.class)) {
+                                       cat.set(CALENDAR);
+                               }
+                       } else if (isChildOf(Temporal.class)) {
+                               cat.set(TEMPORAL);
+                       } else if (inner().isArray()) {
+                               cat.set(ARRAY);
+                       } else if (isChildOfAny(URL.class, URI.class) || 
ap.has(Uri.class, this)) {
+                               cat.set(URI);
+                       } else if (isChildOf(Reader.class)) {
+                               cat.set(READER);
+                       } else if (isChildOf(InputStream.class)) {
+                               cat.set(INPUTSTREAM);
+                       }
+
+                       fromStringMethod = memoize(()->findFromStringMethod());
+                       exampleMethod = memoize(()->findExampleMethod());
+                       parentPropertySetter = 
memoize(()->findParentPropertySetter());
+                       namePropertySetter = 
memoize(()->findNamePropertySetter());
+                       exampleField = memoize(()->findExampleField());
+                       noArgConstructor = memoize(()->findNoArgConstructor());
+                       stringConstructor = 
memoize(()->findStringConstructor());
+                       beanFilter = memoize(()->findBeanFilter());
+                       marshalledFilter = memoize(()->findMarshalledFilter());
+                       builderSwap = memoize(()->findBuilderSwap());
+                       example = memoize(()->findExample());
+                       implClass2 = memoize(()->findImplClass());
+
+                       var _elementType = (ClassMeta<?>)null;
+                       var _keyType = (ClassMeta<?>)null;
+                       var _valueType = (ClassMeta<?>)null;
+
+                       if (cat.is(ARRAY)) {
+                               _elementType = 
beanContext.getClassMeta(getComponentType().inner(), false);
+                       } else if (cat.is(MAP) && ! cat.is(BEANMAP)) {
+                               // If this is a MAP, see if it's parameterized 
(e.g. AddressBook extends HashMap<String,Person>)
+                               var parameters = 
beanContext.findParameters(inner(), inner());
+                               if (nn(parameters) && parameters.length == 2) {
+                                       _keyType = parameters[0];
+                                       _valueType = parameters[1];
+                               } else {
+                                       _keyType = 
beanContext.getClassMeta(Object.class);
+                                       _valueType = 
beanContext.getClassMeta(Object.class);
+                               }
+                       } else if (cat.is(COLLECTION) || is(Optional.class)) {
+                               // If this is a COLLECTION, see if it's 
parameterized (e.g. AddressBook extends LinkedList<Person>)
+                               var parameters = 
beanContext.findParameters(inner(), inner());
+                               if (nn(parameters) && parameters.length == 1) {
+                                       _elementType = parameters[0];
+                               } else {
+                                       _elementType = 
beanContext.getClassMeta(Object.class);
+                               }
+                       }
+
+                       this.elementType2 = _elementType;
+                       this.keyType2 = _keyType;
+                       this.valueType2 = _valueType;
+
+                       var builder = new ClassMetaBuilder<>(info, innerClass, 
beanContext);
+
+                       this.enumValues = memoize(()->findEnumValues());
+                       this.beanRegistry2 = memoize(()->findBeanRegistry());
+                       this.dictionaryName = 
memoize(()->findBeanDictionaryName());
+                       this.beanMeta2 = memoize(()->findBeanMeta());
+                       this.typePropertyName2 = 
memoize(()->findTypePropertyName());
+
+
+                       var _swaps = new ArrayList<ObjectSwap<T,?>>();
+                       if (swaps != null)
+                               for (var s : swaps)
+                                       _swaps.add(s);
+
+                       ap.find(Swap.class, 
this).stream().map(AnnotationInfo::inner).forEach(x2 -> 
_swaps.add(createSwap(x2)));
+                       var ds = DefaultSwaps.find(this);
+                       if (ds == null)
+                               ds = AutoObjectSwap.find(beanContext, this);
+                       if (ds == null)
+                               ds = AutoNumberSwap.find(beanContext, this);
+                       if (ds == null)
+                               ds = AutoMapSwap.find(beanContext, this);
+                       if (ds == null)
+                               ds = AutoListSwap.find(beanContext, this);
+
+                       if (nn(ds))
+                               _swaps.add((ObjectSwap<T,?>)ds);
+
+                       this.swaps = _swaps.isEmpty() ? null : 
_swaps.toArray(new ObjectSwap[_swaps.size()]);
                        this.keyType = builder.keyType;
                        this.valueType = builder.valueType;
                        this.elementType = builder.elementType;
@@ -636,21 +774,14 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                        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.childSwaps = childSwaps;
+                       this.childUnswapMap = childSwaps == null ? null : new 
ConcurrentHashMap<>();
+                       this.childSwapMap = childSwaps == null ? null : new 
ConcurrentHashMap<>();
                        this.args = null;
-                       this.stringMutater = builder.stringMutater;
-                       this.enumValues = builder.enumValues == null ? null : 
builder.enumValues.build();
+                       this.stringMutater = Mutaters.get(String.class, 
inner());
                } catch (ClassMetaRuntimeException e) {
                        notABeanReason = e.getMessage();
                        throw e;
@@ -668,21 +799,10 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                this.innerClass = (Class<T>)Object[].class;
                this.info = info(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.cat = new Categories().set(ARGS);
                this.beanContext = null;
                this.elementType = null;
                this.keyType = null;
@@ -690,17 +810,31 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                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;
+               this.fromStringMethod = memoize(()->findFromStringMethod());
+               this.exampleMethod = memoize(()->findExampleMethod());
+               this.parentPropertySetter = 
memoize(()->findParentPropertySetter());
+               this.namePropertySetter = memoize(()->findNamePropertySetter());
+               this.exampleField = memoize(()->findExampleField());
+               this.noArgConstructor = memoize(()->findNoArgConstructor());
+               this.stringConstructor = memoize(()->findStringConstructor());
+               this.beanFilter = memoize(()->findBeanFilter());
+               this.marshalledFilter = memoize(()->findMarshalledFilter());
+               this.builderSwap = memoize(()->findBuilderSwap());
+               this.example = memoize(()->findExample());
+               this.implClass2 = memoize(()->findImplClass());
+               this.elementType2 = null;
+               this.keyType2 = null;
+               this.valueType2 = null;
+               this.enumValues = memoize(()->findEnumValues());
+               this.beanRegistry2 = memoize(()->findBeanRegistry());
+               this.dictionaryName = memoize(()->findBeanDictionaryName());
+               this.beanMeta2 = memoize(()->findBeanMeta());
+               this.typePropertyName2 = memoize(()->findTypePropertyName());
        }
 
        /**
@@ -713,21 +847,12 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                super(mainType.innerClass);
                this.innerClass = mainType.innerClass;
                this.info = mainType.info;
-               this.implClass = mainType.implClass;
+//             this.implClass = mainType.implClass;
                this.childSwaps = mainType.childSwaps;
                this.childSwapMap = mainType.childSwapMap;
                this.childUnswapMap = mainType.childUnswapMap;
-               this.cc = mainType.cc;
+               this.cat = mainType.cat;
                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;
@@ -735,18 +860,58 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                this.invocationHandler = mainType.invocationHandler;
                this.beanMeta = mainType.beanMeta;
                this.typePropertyName = mainType.typePropertyName;
-               this.dictionaryName = mainType.dictionaryName;
+//             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.example = mainType.example;
                this.args = null;
                this.stringMutater = mainType.stringMutater;
+//             this.enumValues = mainType.enumValues;
+               this.parentPropertySetter = mainType.parentPropertySetter;
+               this.namePropertySetter = mainType.namePropertySetter;
+               this.exampleField = mainType.exampleField;
+               this.noArgConstructor = mainType.noArgConstructor;
+               this.stringConstructor = mainType.stringConstructor;
+               this.beanFilter = mainType.beanFilter;
+               this.marshalledFilter = mainType.marshalledFilter;
+               this.builderSwap = mainType.builderSwap;
+               this.example = mainType.example;
+               this.implClass2 = mainType.implClass2;
+               this.elementType2 = mainType.elementType2;
+               this.keyType2 = mainType.keyType2;
+               this.valueType2 = mainType.valueType2;
                this.enumValues = mainType.enumValues;
+               this.beanRegistry2 = mainType.beanRegistry2;
+               this.dictionaryName = mainType.dictionaryName;
+               this.beanMeta2 = mainType.beanMeta2;
+               this.typePropertyName2 = mainType.typePropertyName2;
+       }
+
+       private ObjectSwap<T,?> createSwap(Swap s) {
+               var c = s.value();
+               if (ClassUtils.isVoid(c))
+                       c = s.impl();
+               var ci = info(c);
+
+               if (ci.isChildOf(ObjectSwap.class)) {
+                       var 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);
        }
 
        /**
@@ -762,7 +927,7 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
        public boolean canCreateNewBean(Object outer) {
                if (beanMeta == null || beanMeta.constructor == null)
                        return false;
-               if (isMemberClass)
+               if (isMemberClass() && isNotStatic())
                        return nn(outer) && 
beanMeta.constructor.hasParameterTypes(outer.getClass());
                return true;
        }
@@ -773,9 +938,9 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         * @return <jk>true</jk> if a new instance of this class can be 
constructed.
         */
        public boolean canCreateNewInstance() {
-               if (isMemberClass)
+               if (isMemberClass() && isNotStatic())
                        return false;
-               if (nn(noArgConstructor) || nn(getProxyInvocationHandler()) || 
(isArray() && elementType.canCreateNewInstance()))
+               if (nn(noArgConstructor.get()) || 
nn(getProxyInvocationHandler()) || (super.isArray() && 
elementType.canCreateNewInstance()))
                        return true;
                return false;
        }
@@ -791,8 +956,8 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         *      <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 nn(outer) && nn(noArgConstructor) && 
noArgConstructor.hasParameterTypes(outer.getClass());
+               if (isMemberClass() && isNotStatic())
+                       return nn(outer) && nn(noArgConstructor.get()) && 
noArgConstructor.get().hasParameterTypes(outer.getClass());
                return canCreateNewInstance();
        }
 
@@ -805,27 +970,16 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         * @return <jk>true</jk> if this class has a no-arg constructor or 
invocation handler.
         */
        public boolean canCreateNewInstanceFromString(Object outer) {
-               if (nn(fromStringMethod))
+               if (nn(fromStringMethod.get()))
                        return true;
-               if (nn(stringConstructor)) {
-                       if (isMemberClass)
-                               return nn(outer) && 
stringConstructor.hasParameterTypes(outer.getClass(), String.class);
+               if (nn(stringConstructor.get())) {
+                       if (isMemberClass() && isNotStatic())
+                               return nn(outer) && 
stringConstructor.get().hasParameterTypes(outer.getClass(), String.class);
                        return true;
                }
                return false;
        }
 
-       /**
-        * Cast this object to this type.
-        *
-        * @param o The object to cast.
-        * @return The cast object.
-        */
-       @Override
-       public T cast(Object o) {
-               return this.innerClass.cast(o);
-       }
-
        @Override /* Overridden from Object */
        public boolean equals(Object o) {
                return (o instanceof ClassMeta<?> o2) && eq(this, o2, (x, y) -> 
eq(x.innerClass, y.innerClass));
@@ -842,7 +996,7 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         */
        public <A extends Annotation> ClassMeta<T> forEachAnnotation(Class<A> 
type, Predicate<A> filter, Consumer<A> action) {
                if (beanContext != null) {
-                       beanContext.getAnnotationProvider().find(type, 
info).stream().map(AnnotationInfo::inner).filter(x -> filter == null || 
filter.test(x)).forEach(x -> action.accept(x));
+                       beanContext.getAnnotationProvider().find(type, 
this).stream().map(AnnotationInfo::inner).filter(x -> filter == null || 
filter.test(x)).forEach(x -> action.accept(x));
                }
                return this;
        }
@@ -914,22 +1068,15 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         * @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;
+               return builderSwap.get();
        }
 
-       /**
-        * Returns the category of this class.
-        *
-        * @return The category of this class.
-        */
-       public ClassCategory getClassCategory() { return cc; }
-
        /**
         * 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; }
+       public ConstructorInfo getConstructor() { return 
noArgConstructor.get(); }
 
        /**
         * Returns the bean dictionary name associated with this class.
@@ -941,7 +1088,7 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         *      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; }
+       public String getDictionaryName() { return dictionaryName.get(); }
 
        /**
         * For array and {@code Collection} types, returns the class type of 
the components of the array or
@@ -960,27 +1107,27 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         * @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" })
+       @SuppressWarnings({ "unchecked" })
        public T getExample(BeanSession session, JsonParserSession jpSession) {
                try {
-                       if (nn(example))
-                               return jpSession.parse(example, this);
-                       if (nn(exampleMethod))
-                               return 
(T)info(exampleMethod).invokeLenient(null, session);
-                       if (nn(exampleField))
-                               return (T)exampleField.get(null);
+                       if (nn(example.get()))
+                               return jpSession.parse(example.get(), this);
+                       if (nn(exampleMethod.get()))
+                               return 
(T)exampleMethod.get().invokeLenient(null, session);
+                       if (nn(exampleField.get()))
+                               return (T)exampleField.get().get(null);
 
                        if (isCollection()) {
                                var etExample = 
getElementType().getExample(session, jpSession);
                                if (nn(etExample)) {
                                        if (canCreateNewInstance()) {
-                                               var c = 
(Collection)newInstance();
+                                               var c = 
(Collection<Object>)newInstance();
                                                c.add(etExample);
                                                return (T)c;
                                        }
                                        return 
(T)Collections.singleton(etExample);
                                }
-                       } else if (isArray()) {
+                       } else if (super.isArray()) {
                                var etExample = 
getElementType().getExample(session, jpSession);
                                if (nn(etExample)) {
                                        var o = 
Array.newInstance(getElementType().innerClass, 1);
@@ -992,7 +1139,7 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                                var ktExample = 
getKeyType().getExample(session, jpSession);
                                if (nn(ktExample) && nn(vtExample)) {
                                        if (canCreateNewInstance()) {
-                                               var m = (Map)newInstance();
+                                               var m = 
(Map<Object,Object>)newInstance();
                                                m.put(ktExample, vtExample);
                                                return (T)m;
                                        }
@@ -1027,13 +1174,6 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                return t == Mutaters.NULL ? null : t;
        }
 
-       /**
-        * 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.getNameFull(); }
-
        /**
         * Returns the no-arg constructor for this class based on the {@link 
Marshalled#implClass()} value.
         *
@@ -1041,18 +1181,11 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         * @return The no-arg constructor for this class, or <jk>null</jk> if 
it does not exist.
         */
        public ConstructorInfo getImplClassConstructor(Visibility conVis) {
-               if (nn(implClass))
-                       return 
info(implClass).getNoArgConstructor(conVis).orElse(null);
+               if (nn(implClass2.get()))
+                       return 
implClass2.get().getNoArgConstructor(conVis).orElse(null);
                return null;
        }
 
-       /**
-        * 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 any exception that was throw in the <c>init()</c> method.
         *
@@ -1090,24 +1223,16 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         */
        @SuppressWarnings("unchecked")
        public <A extends Annotation> A getLastAnnotation(Class<A> a) {
-               var o = (Optional<A>)annotationLastMap.get(a);
+               var o = annotationLastMap.get(a);
                if (o == null) {
                        if (beanContext == null)
-                               return AP.find(a, 
info).stream().findFirst().map(AnnotationInfo::inner).orElse(null);
-                       o = beanContext.getAnnotationProvider().find(a, 
info).stream().findFirst().map(AnnotationInfo::inner);
+                               return AP.find(a, 
this).stream().findFirst().map(AnnotationInfo::inner).orElse(null);
+                       o = beanContext.getAnnotationProvider().find(a, 
this).stream().findFirst().map(AnnotationInfo::inner);
                        annotationLastMap.put(a, o);
                }
-               return o.orElse(null);
+               return (A)o.orElse(null);
        }
 
-       /**
-        * Shortcut for calling {@link Class#getName()} on the inner class of 
this metadata.
-        *
-        * @return The  name of the inner class.
-        */
-       @Override
-       public String getName() { return innerClass.getName(); }
-
        /**
         * Returns the method or field annotated with {@link NameProperty 
@NameProperty}.
         *
@@ -1115,7 +1240,7 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         *      The method or field  annotated with {@link NameProperty 
@NameProperty} or <jk>null</jk> if method does not
         *      exist.
         */
-       public Setter getNameProperty() { return namePropertyMethod; }
+       public Setter getNameProperty() { return namePropertySetter.get(); }
 
        /**
         * Returns the reason why this class is not a bean, or <jk>null</jk> if 
it is a bean.
@@ -1145,16 +1270,7 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         *      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 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.
-        */
-       @Override
-       @SuppressWarnings("unchecked")
-       public T getPrimitiveDefault() { return (T)primitiveDefault; }
+       public Setter getParentProperty() { return parentPropertySetter.get(); }
 
        /**
         * Returns a calculated property on this context.
@@ -1166,12 +1282,12 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         */
        @SuppressWarnings("unchecked")
        public <T2> Optional<T2> getProperty(String name, 
Function<ClassMeta<?>,T2> function) {
-               var t = (Optional<T2>)properties.get(name);
+               var t = properties.get(name);
                if (t == null) {
                        t = opt(function.apply(this));
                        properties.put(name, t);
                }
-               return t;
+               return (Optional<T2>)t;
        }
 
        /**
@@ -1181,16 +1297,6 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         */
        public InvocationHandler getProxyInvocationHandler() { return 
invocationHandler; }
 
-       /**
-        * 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> getPublicMethods2() { return publicMethods; }
-
        /**
         * Returns the transform for this class for creating instances from a 
Reader.
         *
@@ -1293,11 +1399,6 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                return nn(getLastAnnotation(a));
        }
 
-       @Override /* Overridden from Object */
-       public int hashCode() {
-               return innerClass.hashCode();
-       }
-
        /**
         * Returns <jk>true</jk> if this class has a transform associated with 
it that allows it to be created from an InputStream.
         *
@@ -1365,49 +1466,12 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                return nn(stringMutater);
        }
 
-       /**
-        * 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.
-        */
-       @Override
-       public boolean is(Class<?> value) {
-               return eq(innerClass, value);
-       }
-
-       /**
-        * Returns <jk>true</jk> if this class is abstract.
-        *
-        * @return <jk>true</jk> if this class is abstract.
-        */
-       @Override
-       public boolean isAbstract() { return isAbstract; }
-
        /**
         * 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 <jk>true</jk> if this class is an array.
-        *
-        * @return <jk>true</jk> if this class is an array.
-        */
-       @Override
-       public boolean isArray() { return cc == ARRAY; }
-
-       /**
-        * 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);
-       }
+       public boolean isArgs() { return cat.is(ARGS); }
 
        /**
         * Returns <jk>true</jk> if this class is a bean.
@@ -1421,111 +1485,84 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         *
         * @return <jk>true</jk> if this class is a subclass of {@link BeanMap}.
         */
-       public boolean isBeanMap() { return cc == BEANMAP; }
+       public boolean isBeanMap() { return cat.is(BEANMAP); }
 
        /**
         * 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; }
+       public boolean isBoolean() { return isAny(boolean.class, 
Boolean.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; }
+       public boolean isByteArray() { return is(byte[].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); }
+       public boolean isCalendar() { return cat.is(CALENDAR); }
 
        /**
         * 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; }
+       public boolean isChar() { return isAny(char.class, Character.class); }
 
        /**
         * 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 metadata represents the specified type.
-        *
-        * @param c The class to test against.
-        * @return <jk>true</jk> if this metadata represents the specified type.
-        */
-       @Override
-       public boolean isChildOf(Class<?> c) {
-               return info.isChildOf(c);
-       }
-
-       /**
-        * Returns <jk>true</jk> if this class is {@link Class}.
-        *
-        * @return <jk>true</jk> if this class is {@link Class}.
-        */
-       @Override
-       public boolean isClass() { return cc == ClassCategory.CLASS; }
+       public boolean isCharSequence() { return cat.is(CHARSEQ); }
 
        /**
         * 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 
Collection} or is an array.
-        *
-        * @return <jk>true</jk> if this class is a subclass of {@link 
Collection} or is an array.
-        */
-       @Override
-       public boolean isCollectionOrArray() { return cc == COLLECTION || cc == 
ARRAY; }
+       public boolean isCollection() { return cat != null && 
cat.is(COLLECTION); }
 
        /**
         * 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; }
+       public boolean isCollectionOrArrayOrOptional() { return cat.is(ARRAY) 
|| is(Optional.class) || cat.is(COLLECTION); }
 
        /**
         * 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); }
+       public boolean isDate() { return cat.is(DATE); }
 
        /**
         * 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; }
+       public boolean isDateOrCalendar() { return cat.is(DATE) || 
cat.is(CALENDAR); }
 
        /**
         * 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); }
+       public boolean isDateOrCalendarOrTemporal() { return cat.is(DATE) || 
cat.is(CALENDAR) || cat.is(TEMPORAL); }
 
        /**
         * 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; }
+       public boolean isDecimal() { return cat.is(DECIMAL); }
 
        /**
         * Returns <jk>true</jk> if this class implements {@link Delegate}, 
meaning it's a representation of some other
@@ -1533,119 +1570,73 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         *
         * @return <jk>true</jk> if this class implements {@link Delegate}.
         */
-       public boolean isDelegate() { return isDelegate; }
+       public boolean isDelegate() { return cat.is(DELEGATE); }
 
        /**
         * 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 an {@link Enum}.
-        *
-        * @return <jk>true</jk> if this class is an {@link Enum}.
-        */
-       @Override
-       public boolean isEnum() { return cc == ENUM; }
+       public boolean isDouble() { return isAny(Double.class, double.class); }
 
        /**
         * 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; }
+       public boolean isFloat() { return isAny(Float.class, float.class); }
 
        /**
         * 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 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.
-        */
-       @Override
-       public boolean isInstance(Object o) {
-               if (nn(o))
-                       return info.isParentOf(o.getClass()) || (isPrimitive() 
&& info.getPrimitiveWrapper() == o.getClass());
-               return false;
-       }
-
-       /**
-        * 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);
-       }
+       public boolean isInputStream() { return cat.is(INPUTSTREAM); }
 
        /**
         * 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; }
+       public boolean isInteger() { return isAny(Integer.class, int.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); }
+       public boolean isList() { return cat.is(LIST); }
 
        /**
         * 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; }
+       public boolean isLong() { return isAny(Long.class, long.class); }
 
        /**
         * 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; }
+       public boolean isMap() {
+               // TODO - Figure out how cat can be null.
+               return cat != null && cat.is(MAP);
+       }
 
        /**
         * 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 || 
nn(beanMeta); }
-
-       /**
-        * Returns <jk>true</jk> if this class is an inner class.
-        *
-        * @return <jk>true</jk> if this class is an inner class.
-        */
-       @Override
-       public boolean isMemberClass() { return isMemberClass; }
+       public boolean isMapOrBean() { return cat.is(MAP) || nn(beanMeta); }
 
        /**
         * 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 not {@link Object}.
-        *
-        * @return <jk>true</jk> if this class is not {@link Object}.
-        */
-       public boolean isNotObject() { return cc != OBJ; }
+       public boolean isMethod() { return is(Method.class); }
 
        /**
         * Returns <jk>true</jk> if instance of this object can be 
<jk>null</jk>.
@@ -1658,7 +1649,7 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         */
        public boolean isNullable() {
                if (innerClass.isPrimitive())
-                       return cc == CHAR;
+                       return is(char.class);
                return true;
        }
 
@@ -1667,21 +1658,21 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         *
         * @return <jk>true</jk> if this class is a subclass of {@link Number}.
         */
-       public boolean isNumber() { return cc == NUMBER || cc == DECIMAL; }
+       public boolean isNumber() { return cat.is(NUMBER); }
 
        /**
         * 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; }
+       public boolean isObject() { return is(Object.class); }
 
        /**
         * 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; }
+       public boolean isOptional() { return is(Optional.class); }
 
        /**
         * Returns <jk>true</jk> if this class is a primitive.
@@ -1696,50 +1687,42 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         *
         * @return <jk>true</jk> if this class is a {@link Reader}.
         */
-       public boolean isReader() { return cc == READER; }
+       public boolean isReader() { return cat.is(READER); }
 
        /**
         * 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); }
+       public boolean isSet() { return cat.is(SET); }
 
        /**
         * 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; }
+       public boolean isShort() { return isAny(Short.class, short.class); }
 
        /**
         * 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; }
+       public boolean isString() { return is(String.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); }
+       public boolean isTemporal() { return cat.is(TEMPORAL); }
 
        /**
         * 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 {@link Void} or <jk>void</jk>.
-        *
-        * @return <jk>true</jk> if this class is {@link Void} or <jk>void</jk>.
-        */
-       @Override
-       public boolean isVoid() { return cc == VOID; }
+       public boolean isUri() { return cat != null && cat.is(URI); }
 
        /**
         * Returns the last matching annotation on this class or parent 
classes/interfaces in parent-to-child order.
@@ -1753,7 +1736,7 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                var array = annotationArray(type);
                if (array == null) {
                        if (beanContext == null)
-                               return AP.find(type, 
info).stream().map(AnnotationInfo::inner).filter(a -> test(filter, 
a)).findFirst();  // AnnotationProvider returns child-to-parent, so first is 
"last"
+                               return AP.find(type, 
this).stream().map(AnnotationInfo::inner).filter(a -> test(filter, 
a)).findFirst();  // AnnotationProvider returns child-to-parent, so first is 
"last"
                        return opte();
                }
                for (var i = array.length - 1; i >= 0; i--)
@@ -1784,7 +1767,7 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         */
        @SuppressWarnings({ "unchecked", "rawtypes" })
        public <O> O mutateTo(Object o, Class<O> c) {
-               Mutater t = getToMutater(c);
+               Mutater<Object,O> t = (Mutater<Object,O>)getToMutater(c);
                return (O)(t == null ? null : t.mutate(o));
        }
 
@@ -1809,7 +1792,7 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
        @Override
        @SuppressWarnings("unchecked")
        public T newInstance() throws ExecutableException {
-               if (isArray())
+               if (super.isArray())
                        return 
(T)Array.newInstance(getInnerClass().getComponentType(), 0);
                var c = getConstructor();
                if (nn(c))
@@ -1817,8 +1800,6 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                var h = getProxyInvocationHandler();
                if (nn(h))
                        return 
(T)Proxy.newProxyInstance(this.getClass().getClassLoader(), a(getInnerClass(), 
java.io.Serializable.class), h);
-               if (isArray())
-                       return 
(T)Array.newInstance(this.elementType.innerClass, 0);
                return null;
        }
 
@@ -1832,8 +1813,8 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         * @throws ExecutableException Exception occurred on invoked 
constructor/method/field.
         */
        public T newInstance(Object outer) throws ExecutableException {
-               if (isMemberClass)
-                       return noArgConstructor.<T>newInstance(outer);
+               if (isMemberClass() && isNotStatic())
+                       return noArgConstructor.get().<T>newInstance(outer);
                return newInstance();
        }
 
@@ -1858,23 +1839,19 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
        public T newInstanceFromString(Object outer, String arg) throws 
ExecutableException {
 
                if (isEnum()) {
-                       var t = (T)enumValues.getKey(arg);
+                       var t = (T)enumValues.get().getKey(arg);
                        if (t == null && ! 
beanContext.isIgnoreUnknownEnumValues())
                                throw new ExecutableException("Could not 
resolve enum value ''{0}'' on class ''{1}''", arg, getInnerClass().getName());
                        return t;
                }
 
-               var m = fromStringMethod;
+               var m = fromStringMethod.get();
                if (nn(m)) {
-                       try {
-                               return (T)m.invoke(null, arg);
-                       } catch (IllegalAccessException | 
IllegalArgumentException | InvocationTargetException e) {
-                               throw new ExecutableException(e);
-                       }
+                       return (T)m.invoke(null, arg);
                }
-               var c = stringConstructor;
+               var c = stringConstructor.get();
                if (nn(c)) {
-                       if (isMemberClass)
+                       if (isMemberClass() && isNotStatic())
                                return c.<T>newInstance(outer, arg);
                        return c.<T>newInstance(arg);
                }
@@ -1891,7 +1868,7 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
        public boolean same(ClassMeta<?> cm) {
                if (equals(cm))
                        return true;
-               return (isPrimitive() && cc == cm.cc);
+               return (isPrimitive() && cat.same(cm.cat));
        }
 
        @Override /* Overridden from Object */
@@ -1925,13 +1902,13 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
 
        @SuppressWarnings("unchecked")
        private <A extends Annotation> A[] annotationArray(Class<A> type) {
-               var array = (A[])annotationArrayMap.get(type);
+               var array = annotationArrayMap.get(type);
                if (array == null && nn(beanContext)) {
                        var ap = beanContext.getAnnotationProvider();
-                       array = ap.find(type, 
info).stream().map(AnnotationInfo::inner).toArray(i -> array(type, i));
+                       array = ap.find(type, 
this).stream().map(AnnotationInfo::inner).toArray(i -> array(type, i));
                        annotationArrayMap.put(type, array);
                }
-               return array;
+               return (A[])array;
        }
 
        /**
@@ -2014,13 +1991,13 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                        var i = n.lastIndexOf('.');
                        n = n.substring(i == -1 ? 0 : i + 1).replace('$', '.');
                }
-               if (cc == ARRAY)
+               if (cat.is(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)
+               if (cat.is(BEANMAP))
                        return 
sb.append(cn(BeanMap.class)).append('<').append(n).append('>');
-               if (cc == COLLECTION || cc == OPTIONAL)
+               else if (cat.is(MAP))
+                       return sb.append(n).append(keyType.isObject() && 
valueType.isObject() ? "" : "<" + keyType.toString(simple) + "," + 
valueType.toString(simple) + ">");
+               if (cat.is(COLLECTION) || is(Optional.class))
                        return sb.append(n).append(elementType.isObject() ? "" 
: "<" + elementType.toString(simple) + ">");
                return sb.append(n);
        }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonMap.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonMap.java
index 3958dc2f17..a2d7900aba 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonMap.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonMap.java
@@ -292,7 +292,7 @@ public class JsonMap extends LinkedHashMap<String,Object> {
         * Otherwise, returns c2.
         */
        private static ClassMeta<?> getNarrowedClassMeta(ClassMeta<?> c1, 
ClassMeta<?> c2) {
-               if (c2 == null || c2.getInfo().isParentOf(c1.getInnerClass()))
+               if (c2 == null || c2.isParentOf(c1.getInnerClass()))
                        return c1;
                return c2;
        }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanMeta.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanMeta.java
index bd89babdbd..0d1249ebc7 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanMeta.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanMeta.java
@@ -56,7 +56,7 @@ public class RequestBeanMeta {
                Builder apply(Class<?> c) {
                        this.cm = BeanContext.DEFAULT.getClassMeta(c);
                        apply(cm.getLastAnnotation(Request.class));
-                       cm.getInfo().getPublicMethods().stream().forEach(x -> {
+                       cm.getPublicMethods().stream().forEach(x -> {
                                var n = x.getSimpleName();
                                if (x.hasAnnotation(Header.class)) {
                                        assertNoArgs(x, Header.class);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/ResponseBeanMeta.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/ResponseBeanMeta.java
index b3478b17e0..0dd530fdd3 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/ResponseBeanMeta.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/ResponseBeanMeta.java
@@ -83,8 +83,7 @@ public class ResponseBeanMeta {
                Builder apply(Type t) {
                        var c = toClass(t);
                        this.cm = BeanContext.DEFAULT.getClassMeta(c);
-                       var ci = cm.getInfo();
-                       ci.getPublicMethods().stream().forEach(x -> {
+                       cm.getPublicMethods().stream().forEach(x -> {
                                assertNoInvalidAnnotations(x, Query.class, 
FormData.class);
                                if (x.hasAnnotation(Header.class)) {
                                        assertNoArgs(x, Header.class);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorSession.java
index d4d2d68fa9..3d33f6079b 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorSession.java
@@ -429,13 +429,13 @@ public class JsonSchemaGeneratorSession extends 
BeanTraverseSession {
 
                        } else if (tc == COLLECTION) {
                                ClassMeta et = sType.getElementType();
-                               if (sType.isCollection() && 
sType.getInfo().isChildOf(Set.class))
+                               if (sType.isCollection() && 
sType.isChildOf(Set.class))
                                        out.put("uniqueItems", true);
                                out.put("items", getSchema(et, "items", pNames, 
exampleAdded, descriptionAdded, null));
 
                        } else if (tc == ARRAY) {
                                ClassMeta et = sType.getElementType();
-                               if (sType.isCollection() && 
sType.getInfo().isChildOf(Set.class))
+                               if (sType.isCollection() && 
sType.isChildOf(Set.class))
                                        out.put("uniqueItems", true);
                                out.put("items", getSchema(et, "items", pNames, 
exampleAdded, descriptionAdded, null));
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/objecttools/ObjectIntrospector.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/objecttools/ObjectIntrospector.java
index 0ea52370cd..289f312c39 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/objecttools/ObjectIntrospector.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/objecttools/ObjectIntrospector.java
@@ -16,6 +16,8 @@
  */
 package org.apache.juneau.objecttools;
 
+import static org.apache.juneau.commons.utils.Utils.*;
+
 import java.io.*;
 import java.lang.reflect.*;
 
@@ -239,9 +241,13 @@ public class ObjectIntrospector {
        public Object invokeMethod(String method, String args) throws 
NoSuchMethodException, IllegalArgumentException, InvocationTargetException, 
IllegalAccessException, ParseException, IOException {
                if (object == null)
                        return null;
-               Method m = 
parser.getBeanContext().getClassMeta(object.getClass()).getPublicMethods2().get(method);
-               if (m == null)
-                       throw new NoSuchMethodException(method);
-               return invokeMethod(m, args == null ? null : new 
StringReader(args));
+               var m = parser.getBeanContext()
+                       .getClassMeta(object.getClass())
+                       .getPublicMethods()
+                       .stream()
+                       .filter(x -> x.isNotDeprecated() && 
eq(x.getSignature(), method))
+                       .findFirst()
+                       .orElseThrow(() -> new NoSuchMethodException(method));
+               return invokeMethod(m.inner(), args == null ? null : new 
StringReader(args));
        }
 }
\ No newline at end of file
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/objecttools/ObjectRest.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/objecttools/ObjectRest.java
index 42315263c5..cb794a5bb3 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/objecttools/ObjectRest.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/objecttools/ObjectRest.java
@@ -595,7 +595,12 @@ public class ObjectRest {
                var o = get(url);
                if (o == null)
                        return null;
-               return 
session.getClassMeta(o.getClass()).getPublicMethods2().keySet();
+               return session
+                       .getClassMeta(o.getClass())
+                       .getPublicMethods()
+                       .stream()
+                       .map(x -> x.getSignature())
+                       .toList();
        }
 
        /**
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java
index a9deae2207..6b4fad715a 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java
@@ -262,10 +262,10 @@ public class UrlEncodingParserSession extends 
UonParserSession {
                        var m = new TreeMap<Integer,Object>();
                        parseIntoMap2(r, m, sType, c2);
                        c2.addAll(m.values());
-                       if (sType.isArray())
-                               o = CollectionUtils.toArray(c2, 
sType.getElementType().getInnerClass());
-                       else if (sType.isArgs())
+                       if (sType.isArgs())
                                o = c2.toArray(new Object[c2.size()]);
+                       else if (sType.isArray())
+                               o = CollectionUtils.toArray(c2, 
sType.getElementType().getInnerClass());
                        else
                                o = c2;
                } else {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlBeanMeta.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlBeanMeta.java
index 4228071264..f9888dcee5 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlBeanMeta.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlBeanMeta.java
@@ -45,7 +45,7 @@ public class XmlBeanMeta extends ExtendedBeanMeta {
 
                XmlBeanMetaBuilder(BeanMeta<?> beanMeta, XmlMetaProvider mp) {
                        var c = beanMeta.getClassMeta().getInnerClass();
-                       var ci = beanMeta.getClassMeta().getInfo();
+                       var ci = beanMeta.getClassMeta();
                        var defaultFormat = Value.<XmlFormat>empty();
 
                        
beanMeta.getClassMeta().getBeanContext().getAnnotationProvider().find(Xml.class,
 ci).stream().map(AnnotationInfo::inner).forEach(x -> {
diff --git 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/ResponseContent.java
 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/ResponseContent.java
index 229192c438..79491c3785 100644
--- 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/ResponseContent.java
+++ 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/ResponseContent.java
@@ -232,7 +232,7 @@ public class ResponseContent implements HttpEntity {
                        if (type.is(HttpResource.class))
                                type = 
(ClassMeta<T>)getClassMeta(BasicResource.class);
 
-                       var result = type.getInfo().getPublicConstructor(x -> 
x.hasParameterTypes(HttpResponse.class)).map(ci -> safe(() -> 
(T)ci.newInstance(response)));
+                       var result = type.getPublicConstructor(x -> 
x.hasParameterTypes(HttpResponse.class)).map(ci -> safe(() -> 
(T)ci.newInstance(response)));
                        if (result.isPresent())
                                return result.get();
 
@@ -264,7 +264,7 @@ public class ResponseContent implements HttpEntity {
 
                                        // Some HTTP responses have no body, so 
try to create these beans if they've got no-arg constructors.
                                        if (t == null && ! 
type.is(String.class)) {
-                                               var result2 = 
type.getInfo().getPublicConstructor(cons -> cons.getParameterCount() == 
0).map(c -> safe(() -> c.<T>newInstance()));
+                                               var result2 = 
type.getPublicConstructor(cons -> cons.getParameterCount() == 0).map(c -> 
safe(() -> c.<T>newInstance()));
                                                if (result2.isPresent())
                                                        return result2.get();
                                        }
diff --git 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/HttpParts.java
 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/HttpParts.java
index 8993da182f..0f0acb255e 100644
--- 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/HttpParts.java
+++ 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/HttpParts.java
@@ -70,8 +70,7 @@ public class HttpParts {
        };
 
        private static final Function<ClassMeta<?>,ConstructorInfo> 
CONSTRUCTOR_FUNCTION = x -> {
-               var ci = x.getInfo();
-               return ci.getPublicConstructor(y -> 
y.hasParameterTypes(String.class)).orElseGet(() -> ci.getPublicConstructor(y -> 
y.hasParameterTypes(String.class, String.class)).orElse(null));
+               return x.getPublicConstructor(y -> 
y.hasParameterTypes(String.class)).orElseGet(() -> x.getPublicConstructor(y -> 
y.hasParameterTypes(String.class, String.class)).orElse(null));
        };
 
        /**
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/rrpc/RrpcRestOpContext.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/rrpc/RrpcRestOpContext.java
index 1c1e5fa4ea..b45be5f847 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/rrpc/RrpcRestOpContext.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/rrpc/RrpcRestOpContext.java
@@ -49,7 +49,7 @@ public class RrpcRestOpContext extends RestOpContext {
                var interfaceClass = 
getBeanContext().getClassMeta(getJavaMethod().getGenericReturnType());
                meta = new RrpcInterfaceMeta(interfaceClass.getInnerClass(), 
null);
                if (meta.getMethodsByPath().isEmpty())
-                       throw new InternalServerError("Method {0} returns an 
interface {1} that doesn't define any remote methods.", 
getJavaMethod().getName(), interfaceClass.getFullName());
+                       throw new InternalServerError("Method {0} returns an 
interface {1} that doesn't define any remote methods.", 
getJavaMethod().getName(), interfaceClass.getNameFull());
 
        }
 
diff --git a/juneau-utest/src/test/java/org/apache/juneau/PojoExamplesTest.java 
b/juneau-utest/src/test/java/org/apache/juneau/PojoExamplesTest.java
index 1a0b132c31..9d80960f57 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/PojoExamplesTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/PojoExamplesTest.java
@@ -307,36 +307,4 @@ class PojoExamplesTest extends TestBase {
                        return new E2().init();
                }
        }
-
-       
//====================================================================================================
-       // test invalid uses of @Example
-       
//====================================================================================================
-       @Test void a14_invalidUsesOfExample() {
-               var bs = BeanContext.DEFAULT_SESSION;
-               assertThrowsWithMessage(Exception.class, "invalid method 
'example(String)'", ()->bs.getClassMeta(F1.class));
-               assertThrowsWithMessage(Exception.class, "invalid method 
'example()'", ()->bs.getClassMeta(F2.class));
-               assertThrowsWithMessage(Exception.class, l("invalid 
field","$F3.F3"), ()->bs.getClassMeta(F3.class));
-               assertThrowsWithMessage(Exception.class, l("invalid field 
","$F4.f4"), ()->bs.getClassMeta(F4.class));
-       }
-
-       public static class F1 {
-               @Example
-               public static F1 example(String s) {
-                       return null;
-               }
-       }
-       public static class F2 {
-               @Example
-               public F2 example() {
-                       return null;
-               }
-       }
-       public static class F3 {
-               @Example
-               public static String F3 = "foo";
-       }
-       public static class F4 {
-               @Example
-               public F4 f4 = new F4();
-       }
 }
\ No newline at end of file
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/Setter_Test.java 
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/Setter_Test.java
index 98e8229487..6a3bb81823 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/Setter_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/Setter_Test.java
@@ -28,15 +28,15 @@ class Setter_Test extends TestBase {
        public static class TestClass {
                public String publicField;
                private String privateField;
-               
+
                public void setPublicField(String value) {
                        this.publicField = value;
                }
-               
+
                public void setPrivateField(String value) {
                        this.privateField = value;
                }
-               
+
                public String getPrivateField() {
                        return privateField;
                }
@@ -50,11 +50,11 @@ class Setter_Test extends TestBase {
                TestClass obj = new TestClass();
                Field field = TestClass.class.getField("publicField");
                Setter setter = new Setter.FieldSetter(field);
-               
+
                // Set value
                setter.set(obj, "testValue");
                assertEquals("testValue", obj.publicField);
-               
+
                // Set null
                setter.set(obj, null);
                assertNull(obj.publicField);
@@ -69,7 +69,7 @@ class Setter_Test extends TestBase {
                Field field = TestClass.class.getDeclaredField("privateField");
                field.setAccessible(true);
                Setter setter = new Setter.FieldSetter(field);
-               
+
                // Set value
                setter.set(obj, "testValue");
                assertEquals("testValue", obj.getPrivateField());
@@ -83,9 +83,9 @@ class Setter_Test extends TestBase {
                TestClass obj = new TestClass();
                Field field = TestClass.class.getField("publicField");
                Setter setter = new Setter.FieldSetter(field);
-               
+
                // Type mismatch should throw ExecutableException
-               assertThrows(ExecutableException.class, () -> setter.set(obj, 
123));
+               assertThrows(IllegalArgumentException.class, () -> 
setter.set(obj, 123));
        }
 
        
//====================================================================================================
@@ -96,11 +96,11 @@ class Setter_Test extends TestBase {
                TestClass obj = new TestClass();
                Method method = TestClass.class.getMethod("setPublicField", 
String.class);
                Setter setter = new Setter.MethodSetter(method);
-               
+
                // Set value
                setter.set(obj, "testValue");
                assertEquals("testValue", obj.publicField);
-               
+
                // Set null
                setter.set(obj, null);
                assertNull(obj.publicField);
@@ -114,7 +114,7 @@ class Setter_Test extends TestBase {
                TestClass obj = new TestClass();
                Method method = TestClass.class.getMethod("setPrivateField", 
String.class);
                Setter setter = new Setter.MethodSetter(method);
-               
+
                // Set value
                setter.set(obj, "testValue");
                assertEquals("testValue", obj.getPrivateField());
@@ -128,9 +128,9 @@ class Setter_Test extends TestBase {
                TestClass obj = new TestClass();
                Method method = TestClass.class.getMethod("setPublicField", 
String.class);
                Setter setter = new Setter.MethodSetter(method);
-               
+
                // Type mismatch should throw ExecutableException
-               assertThrows(ExecutableException.class, () -> setter.set(obj, 
123));
+               assertThrows(IllegalArgumentException.class, () -> 
setter.set(obj, 123));
        }
 
        
//====================================================================================================
@@ -141,7 +141,7 @@ class Setter_Test extends TestBase {
                TestClass obj = new TestClass();
                Method method = TestClass.class.getMethod("setPublicField", 
String.class);
                Setter setter = new Setter.MethodSetter(method);
-               
+
                // Null object - Method.invoke throws NPE directly, which is 
wrapped in ExecutableException
                // However, the NPE might be thrown before the invoke, so we 
test with a valid object
                // that causes an InvocationTargetException
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorTest.java
 
b/juneau-utest/src/test/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorTest.java
index 634872cba3..f60dc08d41 100755
--- 
a/juneau-utest/src/test/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorTest.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorTest.java
@@ -246,7 +246,7 @@ class JsonSchemaGeneratorTest extends TestBase {
        public static class CustomBeanDefMapper extends BasicBeanDefMapper {
                @Override
                public String getId(ClassMeta<?> cm) {
-                       return cm.getFullName();
+                       return cm.getNameFull();
                }
        }
 
@@ -263,7 +263,7 @@ class JsonSchemaGeneratorTest extends TestBase {
                }
                @Override
                public String getId(ClassMeta<?> cm) {
-                       return cm.getFullName();
+                       return cm.getNameFull();
                }
        }
 
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Config_RestClient_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Config_RestClient_Test.java
index 79fbb3bcf7..0e684df436 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Config_RestClient_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Config_RestClient_Test.java
@@ -427,7 +427,7 @@ class RestClient_Config_RestClient_Test extends TestBase {
 
                private static Object in(HttpPartType type, HttpPartSchema 
schema, String in, ClassMeta<?> c) {
                        try {
-                               if (c.isInstanceOf(ABean.class))
+                               if (c.isParentOf(ABean.class))
                                        return 
Json5.DEFAULT.read(in.substring(1),c);
                                return 
SimplePartParser.DEFAULT.parse(type,schema,in,c);
                        } catch (Exception e) {

Reply via email to