Repository: incubator-juneau
Updated Branches:
  refs/heads/master 74a90ffa7 -> dba656f35


JUNEAU-32 - Improvements to BeanMeta class

Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/dba656f3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/dba656f3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/dba656f3

Branch: refs/heads/master
Commit: dba656f354ce59bdd423479ba15df1fd2e949b7d
Parents: 74a90ff
Author: JamesBognar <jamesbog...@apache.org>
Authored: Thu Feb 2 21:03:29 2017 -0500
Committer: JamesBognar <jamesbog...@apache.org>
Committed: Thu Feb 2 21:03:29 2017 -0500

----------------------------------------------------------------------
 .../java/org/apache/juneau/BeanContext.java     |   4 +-
 .../main/java/org/apache/juneau/BeanMeta.java   |   2 +-
 .../main/java/org/apache/juneau/ClassMeta.java  | 736 ++-----------------
 .../java/org/apache/juneau/ClassMetaSimple.java | 662 +++++++++++++++++
 .../org/apache/juneau/internal/ClassUtils.java  |  34 +-
 5 files changed, 751 insertions(+), 687 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/dba656f3/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/BeanContext.java 
b/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
index a699825..06e1f8f 100644
--- a/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
+++ b/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
@@ -1834,11 +1834,11 @@ public class BeanContext extends Context {
                while (cc != null) {
                        Class implClass = implClasses.get(cc);
                        if (implClass != null)
-                               return 
ClassMeta.findNoArgConstructor(implClass, v);
+                               return findNoArgConstructor(implClass, v);
                        for (Class ic : cc.getInterfaces()) {
                                implClass = implClasses.get(ic);
                                if (implClass != null)
-                                       return 
ClassMeta.findNoArgConstructor(implClass, v);
+                                       return findNoArgConstructor(implClass, 
v);
                        }
                        cc = cc.getSuperclass();
                }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/dba656f3/juneau-core/src/main/java/org/apache/juneau/BeanMeta.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/BeanMeta.java 
b/juneau-core/src/main/java/org/apache/juneau/BeanMeta.java
index 6b1b63d..e1b3d65 100644
--- a/juneau-core/src/main/java/org/apache/juneau/BeanMeta.java
+++ b/juneau-core/src/main/java/org/apache/juneau/BeanMeta.java
@@ -210,7 +210,7 @@ public class BeanMeta<T> {
                                        constructor = 
(Constructor<T>)ctx.getImplClassConstructor(c, conVis);
 
                                if (constructor == null)
-                                       constructor = 
(Constructor<T>)ClassMeta.findNoArgConstructor(c, conVis);
+                                       constructor = 
(Constructor<T>)findNoArgConstructor(c, conVis);
 
                                if (constructor == null && beanFilter == null 
&& ctx.beansRequireDefaultConstructor)
                                        return "Class does not have the 
required no-arg constructor";

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/dba656f3/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java 
b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
index d7f112b..42d5542 100644
--- a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
@@ -12,14 +12,10 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau;
 
-import static org.apache.juneau.ClassMeta.ClassCategory.*;
-import static org.apache.juneau.internal.ClassUtils.*;
+import static org.apache.juneau.ClassMetaSimple.ClassCategory.*;
 
-import java.io.*;
 import java.lang.reflect.*;
 import java.lang.reflect.Proxy;
-import java.net.*;
-import java.net.URI;
 import java.util.*;
 
 import org.apache.juneau.annotation.*;
@@ -49,16 +45,9 @@ import org.apache.juneau.utils.*;
  * @param <T> The class type of the wrapped class.
  */
 
@Bean(properties="innerClass,classCategory,elementType,keyType,valueType,notABeanReason,initException,beanMeta")
-public final class ClassMeta<T> implements Type {
-
-       /** Class categories. */
-       enum ClassCategory {
-               MAP, COLLECTION, CLASS, NUMBER, DECIMAL, BOOLEAN, CHAR, DATE, 
ARRAY, ENUM, BEAN, UNKNOWN, OTHER, CHARSEQ, STR, OBJ, URI, BEANMAP, READER, 
INPUTSTREAM
-       }
+public final class ClassMeta<T> extends ClassMetaSimple<T> {
 
        final BeanContext beanContext;                    // The bean context 
that created this object.
-       ClassCategory classCategory = UNKNOWN;            // The class category.
-       final Class<T> innerClass;                        // The class being 
wrapped.
        ClassMeta<?>
                serializedClassMeta,                           // The 
transformed class type (if class has swap associated with it).
                elementType = null,                            // If ARRAY or 
COLLECTION, the element class type.
@@ -67,40 +56,13 @@ public final class ClassMeta<T> implements Type {
        InvocationHandler invocationHandler;              // The invocation 
handler for this class (if it has one).
        BeanMeta<T> beanMeta;                             // The bean meta for 
this bean class (if it's a bean).
        String dictionaryName, resolvedDictionaryName;    // The dictionary 
name of this class if it has one.
-       Method fromStringMethod;                          // The static 
valueOf(String) or fromString(String) or forString(String) method (if it has 
one).
-       Constructor<? extends T> noArgConstructor;        // The no-arg 
constructor for this class (if it has one).
-       Constructor<T> stringConstructor;                 // The X(String) 
constructor (if it has one).
-       Constructor<T> numberConstructor;                 // The X(Number) 
constructor (if it has one).
-       Constructor<T> swapConstructor;                   // The X(Swappable) 
constructor (if it has one).
-       Class<? extends Number> numberConstructorType;    // The class type of 
the object in the number constructor.
-       Constructor<T> objectMapConstructor;              // The X(ObjectMap) 
constructor (if it has one).
-       Method toObjectMapMethod;                         // The toObjectMap() 
method (if it has one).
-       Method swapMethod;                                // The swap() method 
(if it has one).
-       Method namePropertyMethod;                        // The method to set 
the name on an object (if it has one).
-       Method parentPropertyMethod;                      // The method to set 
the parent on an object (if it has one).
        String notABeanReason;                            // If this isn't a 
bean, the reason why.
        PojoSwap<T,?> pojoSwap;                           // The object POJO 
swap associated with this bean (if it has one).
        BeanFilter beanFilter;                            // The bean filter 
associated with this bean (if it has one).
-       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 MetadataMap extMeta = new MetadataMap();  // Extended metadata
        private Throwable initException;                  // Any exceptions 
thrown in the init() method.
        private boolean hasChildPojoSwaps;                // True if this class 
or any subclass of this class has a PojoSwap associated with it.
-       private Object primitiveDefault;                  // Default value for 
primitive type classes.
-       private Map<String,Method> remoteableMethods,     // Methods annotated 
with @Remoteable.  Contains all public methods if class is annotated with 
@Remotable.
-               publicMethods;                                 // All public 
methods, including static methods.
-
-       private static final Boolean BOOLEAN_DEFAULT = false;
-       private static final Character CHARACTER_DEFAULT = (char)0;
-       private static final Short SHORT_DEFAULT = (short)0;
-       private static final Integer INTEGER_DEFAULT = 0;
-       private static final Long LONG_DEFAULT = 0l;
-       private static final Float FLOAT_DEFAULT = 0f;
-       private static final Double DOUBLE_DEFAULT = 0d;
-       private static final Byte BYTE_DEFAULT = (byte)0;
 
        /**
         * Shortcut for calling <code>ClassMeta(innerClass, beanContext, 
<jk>false</jk>)</code>.
@@ -118,7 +80,7 @@ public final class ClassMeta<T> implements Type {
         *      Used for delayed initialization when the possibility of class 
reference loops exist.
         */
        ClassMeta(Class<T> innerClass, BeanContext beanContext, boolean 
delayedInit) {
-               this.innerClass = innerClass;
+               super(innerClass);
                this.beanContext = beanContext;
                if (! delayedInit)
                        init();
@@ -132,161 +94,14 @@ public final class ClassMeta<T> implements Type {
                        beanFilter = findBeanFilter(beanContext);
                        pojoSwap = findPojoSwap(beanContext);
 
-                       serializedClassMeta = (pojoSwap == null ? this : 
beanContext.getClassMeta(pojoSwap.getSwapClass()));
-                       if (serializedClassMeta == null)
-                               serializedClassMeta = this;
-
-                       if (innerClass != Object.class) {
-                               this.noArgConstructor = 
beanContext.getImplClassConstructor(innerClass, Visibility.PUBLIC);
-                               if (noArgConstructor == null)
-                                       noArgConstructor = 
findNoArgConstructor(innerClass, Visibility.PUBLIC);
+                       if (innerClass != Object.class && this.noArgConstructor 
== null) {
+                               this.noArgConstructor = (Constructor<T>) 
beanContext.getImplClassConstructor(innerClass, Visibility.PUBLIC);
                        }
 
                        this.hasChildPojoSwaps = 
beanContext.hasChildPojoSwaps(innerClass);
 
-                       Class c = innerClass;
-
-                       if (c.isPrimitive()) {
-                               if (c == Boolean.TYPE)
-                                       classCategory = 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)
-                                               classCategory = DECIMAL;
-                                       else
-                                               classCategory = NUMBER;
-                               }
-                               else if (c == Character.TYPE)
-                                       classCategory = CHAR;
-                       } else {
-                               if (isParentClass(Delegate.class, c))
-                                       isDelegate = true;
-                               if (c == Object.class)
-                                       classCategory = OBJ;
-                               else if (c.isEnum())
-                                       classCategory = ENUM;
-                               else if (c.equals(Class.class))
-                                       classCategory = CLASS;
-                               else if (isParentClass(CharSequence.class, c)) {
-                                       if (c.equals(String.class))
-                                               classCategory = STR;
-                                       else
-                                               classCategory = CHARSEQ;
-                               }
-                               else if (isParentClass(Number.class, c)) {
-                                       if (isParentClass(Float.class, c) || 
isParentClass(Double.class, c))
-                                               classCategory = DECIMAL;
-                                       else
-                                               classCategory = NUMBER;
-                               }
-                               else if (isParentClass(Collection.class, c))
-                                       classCategory = COLLECTION;
-                               else if (isParentClass(Map.class, c)) {
-                                       if (isParentClass(BeanMap.class, c))
-                                               classCategory = BEANMAP;
-                                       else
-                                               classCategory = MAP;
-                               }
-                               else if (c == Character.class)
-                                       classCategory = CHAR;
-                               else if (c == Boolean.class)
-                                       classCategory = BOOLEAN;
-                               else if (isParentClass(Date.class, c) || 
isParentClass(Calendar.class, c))
-                                       classCategory = DATE;
-                               else if (c.isArray())
-                                       classCategory = ARRAY;
-                               else if (isParentClass(URL.class, c) || 
isParentClass(URI.class, c) || 
c.isAnnotationPresent(org.apache.juneau.annotation.URI.class))
-                                       classCategory = URI;
-                               else if (isParentClass(Reader.class, c))
-                                       classCategory = READER;
-                               else if (isParentClass(InputStream.class, c))
-                                       classCategory = INPUTSTREAM;
-                       }
-
-                       isMemberClass = c.isMemberClass() && ! isStatic(c);
-
-                       // 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
-                       for (String methodName : new 
String[]{"fromString","valueOf","parse","parseString","forName","forString"}) {
-                               if (this.fromStringMethod == null) {
-                                       for (Method m : c.getMethods()) {
-                                               if (isStatic(m) && isPublic(m) 
&& isNotDeprecated(m)) {
-                                                       String mName = 
m.getName();
-                                                       if 
(mName.equals(methodName) && m.getReturnType() == innerClass) {
-                                                               Class<?>[] args 
= m.getParameterTypes();
-                                                               if (args.length 
== 1 && args[0] == String.class) {
-                                                                       
this.fromStringMethod = m;
-                                                                       break;
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-
-                       // Special cases
-                       try {
-                               if (c == TimeZone.class)
-                                       this.fromStringMethod = 
c.getMethod("getTimeZone", String.class);
-                               else if (c == Locale.class)
-                                       this.fromStringMethod = 
LocaleAsString.class.getMethod("fromString", String.class);
-                       } catch (NoSuchMethodException e1) {}
-
-                       // Find toObjectMap() method if present.
-                       for (Method m : c.getMethods()) {
-                               if (isPublic(m) && isNotDeprecated(m) && ! 
isStatic(m)) {
-                                       String mName = m.getName();
-                                       if (mName.equals("toObjectMap")) {
-                                               if 
(m.getParameterTypes().length == 0 && m.getReturnType() == ObjectMap.class) {
-                                                       this.toObjectMapMethod 
= m;
-                                                       break;
-                                               }
-                                       } else if (mName.equals("swap")) {
-                                               if 
(m.getParameterTypes().length == 1 && m.getParameterTypes()[0] == 
BeanSession.class) {
-                                                       this.swapMethod = m;
-                                                       break;
-                                               }
-                                       }
-                               }
-                       }
-
-                       // Find @NameProperty and @ParentProperty methods if 
present.
-                       for (Method m : c.getDeclaredMethods()) {
-                               if (m.isAnnotationPresent(ParentProperty.class) 
&& m.getParameterTypes().length == 1) {
-                                       m.setAccessible(true);
-                                       parentPropertyMethod = m;
-                               }
-                               if (m.isAnnotationPresent(NameProperty.class) 
&& m.getParameterTypes().length == 1) {
-                                       m.setAccessible(true);
-                                       namePropertyMethod = m;
-                               }
-                       }
-
-                       // Find constructor(String) method if present.
-                       for (Constructor cs : c.getConstructors()) {
-                               if (isPublic(cs) && isNotDeprecated(cs)) {
-                                       Class<?>[] args = 
cs.getParameterTypes();
-                                       if (args.length == (isMemberClass ? 2 : 
1)) {
-                                               Class<?> arg = 
args[(isMemberClass ? 1 : 0)];
-                                               if (arg == String.class)
-                                                       this.stringConstructor 
= cs;
-                                               else if 
(ObjectMap.class.isAssignableFrom(arg))
-                                                       
this.objectMapConstructor = cs;
-                                               else if (swapMethod != null && 
swapMethod.getReturnType().getClass().isAssignableFrom(arg))
-                                                       this.swapConstructor = 
cs;
-                                               else if (classCategory != 
NUMBER && (Number.class.isAssignableFrom(arg) || (arg.isPrimitive() && (arg == 
int.class || arg == short.class || arg == long.class || arg == float.class || 
arg == double.class)))) {
-                                                       this.numberConstructor 
= cs;
-                                                       
this.numberConstructorType = (Class<? extends 
Number>)ClassUtils.getWrapperIfPrimitive(arg);
-                                               }
-                                       }
-                               }
-                       }
-
                        if (swapMethod != null) {
-                               this.pojoSwap = new PojoSwap<T,Object>(c, 
swapMethod.getReturnType()) {
+                               this.pojoSwap = new 
PojoSwap<T,Object>(innerClass, swapMethod.getReturnType()) {
                                        @Override
                                        public Object swap(BeanSession session, 
Object o) throws SerializeException {
                                                try {
@@ -308,15 +123,16 @@ public final class ClassMeta<T> implements Type {
                                };
                        }
 
-                       // Note:  Primitive types are normally abstract.
-                       isAbstract = Modifier.isAbstract(c.getModifiers()) && ! 
isPrimitive();
+                       serializedClassMeta = (pojoSwap == null ? this : 
beanContext.getClassMeta(pojoSwap.getSwapClass()));
+                       if (serializedClassMeta == null)
+                               serializedClassMeta = this;
 
                        // If this is an array, get the element type.
-                       if (classCategory == ARRAY)
+                       if (cc == ARRAY)
                                elementType = 
beanContext.getClassMeta(innerClass.getComponentType());
 
                        // If this is a MAP, see if it's parameterized (e.g. 
AddressBook extends HashMap<String,Person>)
-                       else if (classCategory == MAP) {
+                       else if (cc == MAP) {
                                ClassMeta[] parameters = 
beanContext.findParameters(innerClass, innerClass);
                                if (parameters != null && parameters.length == 
2) {
                                        keyType = parameters[0];
@@ -328,7 +144,7 @@ public final class ClassMeta<T> implements Type {
                        }
 
                        // If this is a COLLECTION, see if it's parameterized 
(e.g. AddressBook extends LinkedList<Person>)
-                       else if (classCategory == COLLECTION) {
+                       else if (cc == COLLECTION) {
                                ClassMeta[] parameters = 
beanContext.findParameters(innerClass, innerClass);
                                if (parameters != null && parameters.length == 
1) {
                                        elementType = parameters[0];
@@ -339,7 +155,7 @@ public final class ClassMeta<T> implements Type {
 
                        // 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 (classCategory == UNKNOWN) {
+                       else if (cc == OTHER) {
 
                                BeanMeta newMeta = null;
                                try {
@@ -349,49 +165,11 @@ public final class ClassMeta<T> implements Type {
                                        notABeanReason = e.getMessage();
                                        throw e;
                                }
-                               if (notABeanReason != null)
-                                       classCategory = OTHER;
-                               else {
+                               if (notABeanReason == null) {
                                        beanMeta = newMeta;
-                                       classCategory = BEAN;
                                }
                        }
 
-                       if (c.isPrimitive()) {
-                               if (c == Boolean.TYPE)
-                                       primitiveDefault = BOOLEAN_DEFAULT;
-                               else if (c == Character.TYPE)
-                                       primitiveDefault = CHARACTER_DEFAULT;
-                               else if (c == Short.TYPE)
-                                       primitiveDefault = SHORT_DEFAULT;
-                               else if (c == Integer.TYPE)
-                                       primitiveDefault = INTEGER_DEFAULT;
-                               else if (c == Long.TYPE)
-                                       primitiveDefault = LONG_DEFAULT;
-                               else if (c == Float.TYPE)
-                                       primitiveDefault = FLOAT_DEFAULT;
-                               else if (c == Double.TYPE)
-                                       primitiveDefault = DOUBLE_DEFAULT;
-                               else if (c == Byte.TYPE)
-                                       primitiveDefault = BYTE_DEFAULT;
-                       } else {
-                               if (c == Boolean.class)
-                                       primitiveDefault = BOOLEAN_DEFAULT;
-                               else if (c == Character.class)
-                                       primitiveDefault = CHARACTER_DEFAULT;
-                               else if (c == Short.class)
-                                       primitiveDefault = SHORT_DEFAULT;
-                               else if (c == Integer.class)
-                                       primitiveDefault = INTEGER_DEFAULT;
-                               else if (c == Long.class)
-                                       primitiveDefault = LONG_DEFAULT;
-                               else if (c == Float.class)
-                                       primitiveDefault = FLOAT_DEFAULT;
-                               else if (c == Double.class)
-                                       primitiveDefault = DOUBLE_DEFAULT;
-                               else if (c == Byte.class)
-                                       primitiveDefault = BYTE_DEFAULT;
-                       }
                } catch (NoClassDefFoundError e) {
                        this.initException = e;
                } catch (RuntimeException e) {
@@ -399,20 +177,6 @@ public final class ClassMeta<T> implements Type {
                        throw e;
                }
 
-               if (innerClass.getAnnotation(Remoteable.class) != null) {
-                       remoteableMethods = getPublicMethods();
-               } else {
-                       for (Method m : innerClass.getMethods()) {
-                               if (m.getAnnotation(Remoteable.class) != null) {
-                                       if (remoteableMethods == null)
-                                               remoteableMethods = new 
LinkedHashMap<String,Method>();
-                                       
remoteableMethods.put(ClassUtils.getMethodSignature(m), m);
-                               }
-                       }
-               }
-               if (remoteableMethods != null)
-                       remoteableMethods = 
Collections.unmodifiableMap(remoteableMethods);
-
                if (isBean())
                        dictionaryName = resolvedDictionaryName = 
getBeanMeta().getDictionaryName();
 
@@ -449,25 +213,6 @@ public final class ClassMeta<T> implements Type {
        }
 
        /**
-        * Returns the category of this class.
-        *
-        * @return The category of this class.
-        */
-       public ClassCategory getClassCategory() {
-               return classCategory;
-       }
-
-       /**
-        * 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 isParentClass(innerClass, c);
-       }
-
-       /**
         * Returns <jk>true</jk> if this class as subtypes defined through 
{@link Bean#subTypes}.
         *
         * @return <jk>true</jk> if this class has subtypes.
@@ -477,16 +222,6 @@ public final class ClassMeta<T> implements Type {
        }
 
        /**
-        * 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 isParentClass(c, innerClass);
-       }
-
-       /**
         * Returns <jk>true</jk> if this class or any child classes has a 
{@link PojoSwap} associated with it.
         * <p>
         * Used when transforming bean properties to prevent having to look up 
transforms if we know for certain
@@ -519,10 +254,10 @@ public final class ClassMeta<T> implements Type {
                try {
                        Pojo p = innerClass.getAnnotation(Pojo.class);
                        if (p != null) {
-                               Class<?> c = p.swap();
-                               if (c != Null.class) {
-                                       if 
(ClassUtils.isParentClass(PojoSwap.class, c))
-                                               return 
(PojoSwap<T,?>)c.newInstance();
+                               Class<?> swapClass = p.swap();
+                               if (swapClass != Null.class) {
+                                       if 
(ClassUtils.isParentClass(PojoSwap.class, swapClass))
+                                               return 
(PojoSwap<T,?>)swapClass.newInstance();
                                        throw new RuntimeException("TODO - 
Surrogate classes not yet supported.");
                                }
                        }
@@ -536,30 +271,6 @@ public final class ClassMeta<T> implements Type {
        }
 
        /**
-        * Locates the no-arg constructor for the specified class.
-        * Constructor must match the visibility requirements specified by 
parameter 'v'.
-        * If class is abstract, always returns <jk>null</jk>.
-        * Note that this also returns the 1-arg constructor for non-static 
member classes.
-        *
-        * @param c The class from which to locate the no-arg constructor.
-        * @param v The minimum visibility.
-        * @return The constructor, or <jk>null</jk> if no no-arg constructor 
exists with the required visibility.
-        */
-       @SuppressWarnings({"rawtypes","unchecked"})
-       protected static <T> Constructor<? extends T> 
findNoArgConstructor(Class<T> c, Visibility v) {
-               int mod = c.getModifiers();
-               if (Modifier.isAbstract(mod))
-                       return null;
-               boolean isMemberClass = c.isMemberClass() && ! isStatic(c);
-               for (Constructor cc : c.getConstructors()) {
-                       mod = cc.getModifiers();
-                       if (cc.getParameterTypes().length == (isMemberClass ? 1 
: 0) && v.isVisible(mod) && isNotDeprecated(cc))
-                               return v.transform(cc);
-               }
-               return null;
-       }
-
-       /**
         * Set element type on non-cached <code>Collection</code> types.
         *
         * @param elementType The class type for elements in the collection 
class represented by this metadata.
@@ -593,15 +304,6 @@ public final class ClassMeta<T> implements Type {
        }
 
        /**
-        * Returns the {@link Class} object that this class type wraps.
-        *
-        * @return The wrapped class object.
-        */
-       public Class<T> getInnerClass() {
-               return innerClass;
-       }
-
-       /**
         * Returns the serialized (swapped) form of this class if there is an 
{@link PojoSwap} associated with it.
         *
         * @return The serialized class type, or this object if no swap is 
associated with the class.
@@ -639,263 +341,21 @@ public final class ClassMeta<T> implements Type {
        }
 
        /**
-        * Returns <jk>true</jk> if this class implements {@link Delegate}, 
meaning
-        *      it's a representation of some other object.
-        *
-        * @return <jk>true</jk> if this class implements {@link Delegate}.
-        */
-       public boolean isDelegate() {
-               return isDelegate;
-       }
-
-       /**
-        * Returns <jk>true</jk> if 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 classCategory == MAP || classCategory == BEANMAP;
-       }
-
-       /**
-        * Returns <jk>true</jk> if this class is a subclass of {@link Map} or 
it's a bean.
-        *
-        * @return <jk>true</jk> if this class is a subclass of {@link Map} or 
it's a bean.
-        */
-       public boolean isMapOrBean() {
-               return classCategory == MAP || classCategory == BEANMAP || 
classCategory == BEAN;
-       }
-
-       /**
-        * Returns <jk>true</jk> if this class is a subclass of {@link BeanMap}.
-        *
-        * @return <jk>true</jk> if this class is a subclass of {@link BeanMap}.
-        */
-       public boolean isBeanMap() {
-               return classCategory == BEANMAP;
-       }
-
-       /**
-        * Returns <jk>true</jk> if this class is a subclass of {@link 
Collection}.
-        *
-        * @return <jk>true</jk> if this class is a subclass of {@link 
Collection}.
-        */
-       public boolean isCollection() {
-               return classCategory == 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.
-        */
-       public boolean isCollectionOrArray() {
-               return classCategory == COLLECTION || classCategory == ARRAY;
-       }
-
-       /**
-        * Returns <jk>true</jk> if this class is {@link Class}.
-        *
-        * @return <jk>true</jk> if this class is {@link Class}.
-        */
-       public boolean isClass() {
-               return classCategory == CLASS;
-       }
-
-       /**
-        * Returns <jk>true</jk> if this class is an {@link Enum}.
-        *
-        * @return <jk>true</jk> if this class is an {@link Enum}.
-        */
-       public boolean isEnum() {
-               return classCategory == ENUM;
-       }
-
-       /**
-        * Returns <jk>true</jk> if this class is an array.
-        *
-        * @return <jk>true</jk> if this class is an array.
-        */
-       public boolean isArray() {
-               return classCategory == ARRAY;
-       }
-
-       /**
         * Returns <jk>true</jk> if this class is a bean.
         *
         * @return <jk>true</jk> if this class is a bean.
         */
        public boolean isBean() {
-               return classCategory == BEAN;
-       }
-
-       /**
-        * Returns <jk>true</jk> if this class is {@link Object}.
-        *
-        * @return <jk>true</jk> if this class is {@link Object}.
-        */
-       public boolean isObject() {
-               return classCategory == OBJ;
-       }
-
-       /**
-        * Returns <jk>true</jk> if this class is not {@link Object}.
-        *
-        * @return <jk>true</jk> if this class is not {@link Object}.
-        */
-       public boolean isNotObject() {
-               return classCategory != OBJ;
-       }
-
-       /**
-        * Returns <jk>true</jk> if this class is a subclass of {@link Number}.
-        *
-        * @return <jk>true</jk> if this class is a subclass of {@link Number}.
-        */
-       public boolean isNumber() {
-               return classCategory == NUMBER || classCategory == DECIMAL;
-       }
-
-       /**
-        * Returns <jk>true</jk> if this class is a subclass of {@link Float} 
or {@link Double}.
-        *
-        * @return <jk>true</jk> if this class is a subclass of {@link Float} 
or {@link Double}.
-        */
-       public boolean isDecimal() {
-               return classCategory == DECIMAL;
-       }
-
-       /**
-        * 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 classCategory == BOOLEAN;
-       }
-
-       /**
-        * Returns <jk>true</jk> if this class is a subclass of {@link 
CharSequence}.
-        *
-        * @return <jk>true</jk> if this class is a subclass of {@link 
CharSequence}.
-        */
-       public boolean isCharSequence() {
-               return classCategory == STR || classCategory == CHARSEQ;
-       }
-
-       /**
-        * Returns <jk>true</jk> if this class is a {@link String}.
-        *
-        * @return <jk>true</jk> if this class is a {@link String}.
-        */
-       public boolean isString() {
-               return classCategory == STR;
-       }
-
-       /**
-        * Returns <jk>true</jk> if this class is a {@link Character}.
-        *
-        * @return <jk>true</jk> if this class is a {@link Character}.
-        */
-       public boolean isChar() {
-               return classCategory == CHAR;
-       }
-
-       /**
-        * Returns <jk>true</jk> if this class is a primitive.
-        *
-        * @return <jk>true</jk> if this class is a primitive.
-        */
-       public boolean isPrimitive() {
-               return innerClass.isPrimitive();
-       }
-
-       /**
-        * Returns <jk>true</jk> if this class is a {@link Date} or {@link 
Calendar}.
-        *
-        * @return <jk>true</jk> if this class is a {@link Date} or {@link 
Calendar}.
-        */
-       public boolean isDate() {
-               return classCategory == DATE;
-       }
-
-       /**
-        * 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 classCategory == URI;
-       }
-
-       /**
-        * Returns <jk>true</jk> if this class is a {@link Reader}.
-        *
-        * @return <jk>true</jk> if this class is a {@link Reader}.
-        */
-       public boolean isReader() {
-               return classCategory == READER;
-       }
-
-       /**
-        * Returns <jk>true</jk> if this class is an {@link InputStream}.
-        *
-        * @return <jk>true</jk> if this class is an {@link InputStream}.
-        */
-       public boolean isInputStream() {
-               return classCategory == INPUTSTREAM;
+               return beanMeta != null;
        }
 
        /**
-        * Returns <jk>true</jk> if instance of this object can be 
<jk>null</jk>.
-        * <p>
-        *      Objects can be <jk>null</jk>, but primitives cannot, except for 
chars which can be represented
-        *      by <code>(<jk>char</jk>)0</code>.
-        *
-        * @return <jk>true</jk> if instance of this class can be null.
-        */
-       public boolean isNullable() {
-               if (innerClass.isPrimitive())
-                       return classCategory == CHAR;
-               return true;
-       }
-
-       /**
-        * Returns <jk>true</jk> if this class or one of it's methods are 
annotated with {@link Remoteable @Remotable}.
-        *
-        * @return <jk>true</jk> if this class is remoteable.
-        */
-       public boolean isRemoteable() {
-               return remoteableMethods != null;
-       }
-
-       /**
-        * All methods on this class annotated with {@link Remoteable 
@Remotable}, or all public methods if class is annotated.
-        * Keys are method signatures.
-        *
-        * @return All remoteable methods on this class.
-        */
-       public Map<String,Method> getRemoteableMethods() {
-               return remoteableMethods;
-       }
-
-       /**
-        * All public methods on this class including static methods.
-        * Keys are method signatures.
+        * Returns <jk>true</jk> if this class is a subclass of {@link Map} or 
it's a bean.
         *
-        * @return The public methods on this class.
+        * @return <jk>true</jk> if this class is a subclass of {@link Map} or 
it's a bean.
         */
-       public Map<String,Method> getPublicMethods() {
-               if (publicMethods == null) {
-                       synchronized(this) {
-                               Map<String,Method> map = new 
LinkedHashMap<String,Method>();
-                               for (Method m : innerClass.getMethods())
-                                       if (isPublic(m) && isNotDeprecated(m))
-                                               
map.put(ClassUtils.getMethodSignature(m), m);
-                               publicMethods = 
Collections.unmodifiableMap(map);
-                       }
-               }
-               return publicMethods;
+       public boolean isMapOrBean() {
+               return cc == MAP || cc == BEANMAP || beanMeta != null;
        }
 
        /**
@@ -930,11 +390,11 @@ public final class ClassMeta<T> implements Type {
        /**
         * Returns the language-specified extended metadata on this class.
         *
-        * @param c The name of the metadata class to create.
+        * @param extMetaClass The name of the metadata class to create.
         * @return Extended metadata on this class.  Never <jk>null</jk>.
         */
-       public <M extends ClassMetaExtended> M getExtendedMeta(Class<M> c) {
-               return extMeta.get(c, this);
+       public <M extends ClassMetaExtended> M getExtendedMeta(Class<M> 
extMetaClass) {
+               return extMeta.get(extMetaClass, this);
        }
 
        /**
@@ -1057,50 +517,6 @@ public final class ClassMeta<T> implements Type {
        }
 
        /**
-        * Returns <jk>true</jk> if this class has an <code>ObjectMap 
toObjectMap()</code> method.
-        *
-        * @return <jk>true</jk> if class has a <code>toObjectMap()</code> 
method.
-        */
-       public boolean hasToObjectMapMethod() {
-               return toObjectMapMethod != null;
-       }
-
-       /**
-        * Returns the method annotated with {@link NameProperty @NameProperty}.
-        *
-        * @return The method annotated with {@link NameProperty @NameProperty} 
or <jk>null</jk> if method does not exist.
-        */
-       public Method getNameProperty() {
-               return namePropertyMethod;
-       }
-
-       /**
-        * Returns the method annotated with {@link ParentProperty 
@ParentProperty}.
-        *
-        * @return The method annotated with {@link ParentProperty 
@ParentProperty} or <jk>null</jk> if method does not exist.
-        */
-       public Method getParentProperty() {
-               return parentPropertyMethod;
-       }
-
-       /**
-        * Converts an instance of this class to an {@link ObjectMap}.
-        *
-        * @param t The object to convert to a map.
-        * @return The converted object, or <jk>null</jk> if method does not 
have a <code>toObjectMap()</code> method.
-        * @throws BeanRuntimeException Thrown by <code>toObjectMap()</code> 
method invocation.
-        */
-       public ObjectMap toObjectMap(Object t) throws BeanRuntimeException {
-               try {
-                       if (toObjectMapMethod != null)
-                               return (ObjectMap)toObjectMapMethod.invoke(t);
-                       return null;
-               } catch (Exception e) {
-                       throw new BeanRuntimeException(e);
-               }
-       }
-
-       /**
         * Returns the reason why this class is not a bean, or <jk>null</jk> if 
it is a bean.
         *
         * @return The reason why this class is not a bean, or <jk>null</jk> if 
it is a bean.
@@ -1136,16 +552,6 @@ public final class ClassMeta<T> implements Type {
        }
 
        /**
-        * Returns the default value for primitives such as <jk>int</jk> or 
<jk>Integer</jk>.
-        *
-        * @return The default value, or <jk>null</jk> if this class type is 
not a primitive.
-        */
-       @SuppressWarnings("unchecked")
-       public T getPrimitiveDefault() {
-               return (T)primitiveDefault;
-       }
-
-       /**
         * Create a new instance of the main class of this declared type from a 
<code>String</code> input.
         * <p>
         * In order to use this method, the class must have one of the 
following methods:
@@ -1169,11 +575,11 @@ public final class ClassMeta<T> implements Type {
                Method m = fromStringMethod;
                if (m != null)
                        return (T)m.invoke(null, arg);
-               Constructor<T> c = stringConstructor;
-               if (c != null) {
+               Constructor<T> con = stringConstructor;
+               if (con != null) {
                        if (isMemberClass)
-                               return c.newInstance(outer, arg);
-                       return c.newInstance(arg);
+                               return con.newInstance(outer, arg);
+                       return con.newInstance(arg);
                }
                throw new InstantiationError("No string constructor or 
valueOf(String) method found for class '"+getInnerClass().getName()+"'");
        }
@@ -1197,12 +603,12 @@ public final class ClassMeta<T> implements Type {
         * @throws InvocationTargetException If the underlying constructor 
throws an exception.
         */
        public T newInstanceFromNumber(BeanSession session, Object outer, 
Number arg) throws IllegalArgumentException, IllegalAccessException, 
InvocationTargetException, InstantiationException {
-               Constructor<T> c = numberConstructor;
-               if (c != null) {
+               Constructor<T> con = numberConstructor;
+               if (con != null) {
                        Object arg2 = session.convertToType(arg, 
numberConstructor.getParameterTypes()[0]);
                        if (isMemberClass)
-                               return c.newInstance(outer, arg2);
-                       return c.newInstance(arg2);
+                               return con.newInstance(outer, arg2);
+                       return con.newInstance(arg2);
                }
                throw new InstantiationError("No string constructor or 
valueOf(Number) method found for class '"+getInnerClass().getName()+"'");
        }
@@ -1225,11 +631,11 @@ public final class ClassMeta<T> implements Type {
         * @throws InvocationTargetException If the underlying constructor 
throws an exception.
         */
        public T newInstanceFromObjectMap(Object outer, ObjectMap arg) throws 
IllegalArgumentException, IllegalAccessException, InvocationTargetException, 
InstantiationException {
-               Constructor<T> c = objectMapConstructor;
-               if (c != null) {
+               Constructor<T> con = objectMapConstructor;
+               if (con != null) {
                        if (isMemberClass)
-                               return c.newInstance(outer, arg);
-                       return c.newInstance(arg);
+                               return con.newInstance(outer, arg);
+                       return con.newInstance(arg);
                }
                throw new InstantiationError("No map constructor method found 
for class '"+getInnerClass().getName()+"'");
        }
@@ -1253,9 +659,9 @@ public final class ClassMeta<T> implements Type {
        public T newInstance() throws IllegalArgumentException, 
InstantiationException, IllegalAccessException, InvocationTargetException {
                if (isArray())
                        return 
(T)Array.newInstance(getInnerClass().getComponentType(), 0);
-               Constructor<? extends T> c = getConstructor();
-               if (c != null)
-                       return c.newInstance((Object[])null);
+               Constructor<? extends T> con = getConstructor();
+               if (con != null)
+                       return con.newInstance((Object[])null);
                InvocationHandler h = getProxyInvocationHandler();
                if (h != null)
                        return 
(T)Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] { 
getInnerClass(), java.io.Serializable.class }, h);
@@ -1310,7 +716,7 @@ public final class ClassMeta<T> implements Type {
        public boolean same(ClassMeta<?> cm) {
                if (equals(cm))
                        return true;
-               return (isPrimitive() && classCategory == cm.classCategory);
+               return (isPrimitive() && cc == cm.cc);
        }
 
        @Override /* Object */
@@ -1341,51 +747,26 @@ public final class ClassMeta<T> implements Type {
                        int i = n.lastIndexOf('.');
                        n = n.substring(i == -1 ? 0 : i+1).replace('$', '.');
                }
-               switch(classCategory) {
-                       case ARRAY:
-                               return elementType.toString(sb, 
simple).append('[').append(']');
-                       case MAP:
-                               return sb.append(n).append(keyType.isObject() 
&& valueType.isObject() ? "" : 
"<"+keyType.toString(simple)+","+valueType.toString(simple)+">");
-                       case BEANMAP:
-                               return 
sb.append(BeanMap.class.getName()).append('<').append(n).append('>');
-                       case COLLECTION:
-                               return 
sb.append(n).append(elementType.isObject() ? "" : 
"<"+elementType.toString(simple)+">");
-                       case OTHER:
-                               if (simple)
-                                       return sb.append(n);
-                               
sb.append("OTHER-").append(n).append(",notABeanReason=").append(notABeanReason);
-                               if (initException != null)
-                                       
sb.append(",initException=").append(initException);
-                               return sb;
-                       default:
+               if (cc == ARRAY)
+                       return elementType.toString(sb, 
simple).append('[').append(']');
+               if (cc == MAP)
+                       return sb.append(n).append(keyType.isObject() && 
valueType.isObject() ? "" : 
"<"+keyType.toString(simple)+","+valueType.toString(simple)+">");
+               if (cc == BEANMAP)
+                       return 
sb.append(BeanMap.class.getName()).append('<').append(n).append('>');
+               if (cc == COLLECTION)
+                       return sb.append(n).append(elementType.isObject() ? "" 
: "<"+elementType.toString(simple)+">");
+               if (cc == OTHER && beanMeta == null) {
+                       if (simple)
                                return sb.append(n);
+                       
sb.append("OTHER-").append(n).append(",notABeanReason=").append(notABeanReason);
+                       if (initException != null)
+                               
sb.append(",initException=").append(initException);
+                       return sb;
                }
+               return sb.append(n);
        }
 
-       /**
-        * Returns <jk>true</jk> if the specified object is an instance of this 
class.
-        * This is a simple comparison on the base class itself and not on
-        * any generic parameters.
-        *
-        * @param o The object to check.
-        * @return <jk>true</jk> if the specified object is an instance of this 
class.
-        */
-       public boolean isInstance(Object o) {
-               if (o != null)
-                       return ClassUtils.isParentClass(this.innerClass, 
o.getClass());
-               return false;
-       }
-
-       /**
-        * Returns a readable name for this class (e.g. 
<js>"java.lang.String"</js>, <js>"boolean[]"</js>).
-        *
-        * @return The readable name for this class.
-        */
-       public String getReadableName() {
-               return ClassUtils.getReadableClassName(this.innerClass);
-       }
-
-       private static class LocaleAsString {
+       static class LocaleAsString {
                private static Method forLanguageTagMethod;
                static {
                        try {
@@ -1393,7 +774,6 @@ public final class ClassMeta<T> implements Type {
                        } catch (NoSuchMethodException e) {}
                }
 
-               @SuppressWarnings("unused")
                public static final Locale fromString(String localeString) {
                        if (forLanguageTagMethod != null) {
                                if (localeString.indexOf('_') != -1)

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/dba656f3/juneau-core/src/main/java/org/apache/juneau/ClassMetaSimple.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/ClassMetaSimple.java 
b/juneau-core/src/main/java/org/apache/juneau/ClassMetaSimple.java
new file mode 100644
index 0000000..b0de937
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/ClassMetaSimple.java
@@ -0,0 +1,662 @@
+// 
***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                
                                              *
+// *                                                                           
                                              *
+// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
+// *                                                                           
                                              *
+// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the 
License.                                              *
+// 
***************************************************************************************************************************
+package org.apache.juneau;
+
+import static org.apache.juneau.ClassMetaSimple.ClassCategory.*;
+import static org.apache.juneau.internal.ClassUtils.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.net.*;
+import java.net.URI;
+import java.util.*;
+
+import org.apache.juneau.ClassMeta.*;
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.internal.*;
+
+/**
+ * Information about a class that can be gathered through reflection alone.
+ *
+ * @param <T> The class type of the wrapped class.
+ */
+public class ClassMetaSimple<T> implements Type {
+
+       /** Class categories. */
+       enum ClassCategory {
+               MAP, COLLECTION, CLASS, NUMBER, DECIMAL, BOOLEAN, CHAR, DATE, 
ARRAY, ENUM, OTHER, CHARSEQ, STR, OBJ, URI, BEANMAP, READER, INPUTSTREAM
+       }
+
+       final Class<T> innerClass;                              // The class 
being wrapped.
+       final ClassCategory cc;                                 // The class 
category.
+       final Method fromStringMethod;                          // The static 
valueOf(String) or fromString(String) or forString(String) method (if it has 
one).
+       Constructor<T>
+               noArgConstructor;                                    // The 
no-arg constructor for this class (if it has one).
+       final Constructor<T>
+               stringConstructor,                                   // The 
X(String) constructor (if it has one).
+               numberConstructor,                                   // The 
X(Number) constructor (if it has one).
+               swapConstructor,                                     // The 
X(Swappable) constructor (if it has one).
+               objectMapConstructor;                                // The 
X(ObjectMap) constructor (if it has one).
+       final Class<? extends Number> numberConstructorType;    // The class 
type of the object in the number constructor.
+       final Method
+               toObjectMapMethod,                                   // The 
toObjectMap() method (if it has one).
+               swapMethod,                                          // The 
swap() method (if it has one).
+               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).
+       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.
+       final Object primitiveDefault;                          // Default 
value for primitive type classes.
+       final Map<String,Method>
+               remoteableMethods,                                   // Methods 
annotated with @Remoteable.  Contains all public methods if class is annotated 
with @Remotable.
+               publicMethods;                                       // All 
public methods, including static methods.
+
+       private static final Boolean BOOLEAN_DEFAULT = false;
+       private static final Character CHARACTER_DEFAULT = (char)0;
+       private static final Short SHORT_DEFAULT = (short)0;
+       private static final Integer INTEGER_DEFAULT = 0;
+       private static final Long LONG_DEFAULT = 0l;
+       private static final Float FLOAT_DEFAULT = 0f;
+       private static final Double DOUBLE_DEFAULT = 0d;
+       private static final Byte BYTE_DEFAULT = (byte)0;
+
+
+       @SuppressWarnings({"unchecked","rawtypes"})
+       ClassMetaSimple(Class<T> innerClass) {
+               this.innerClass = innerClass;
+
+               Class<T> c = innerClass;
+               ClassCategory _cc = ClassCategory.OTHER;
+               boolean _isDelegate = false;
+               Method
+                       _fromStringMethod = null,
+                       _toObjectMapMethod = null,
+                       _swapMethod = null,
+                       _parentPropertyMethod = null,
+                       _namePropertyMethod = null;
+               Constructor<T>
+                       _noArgConstructor = null,
+                       _stringConstructor = null,
+                       _objectMapConstructor = null,
+                       _swapConstructor = null,
+                       _numberConstructor = null;
+               Class<? extends Number> _numberConstructorType = null;
+               Object _primitiveDefault = null;
+               Map<String,Method>
+                       _publicMethods = new LinkedHashMap<String,Method>(),
+                       _remoteableMethods = null;
+
+               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 (isParentClass(Delegate.class, c))
+                               _isDelegate = true;
+                       if (c == Object.class)
+                               _cc = OBJ;
+                       else if (c.isEnum())
+                               _cc = ENUM;
+                       else if (c.equals(Class.class))
+                               _cc = CLASS;
+                       else if (isParentClass(CharSequence.class, c)) {
+                               if (c.equals(String.class))
+                                       _cc = STR;
+                               else
+                                       _cc = CHARSEQ;
+                       }
+                       else if (isParentClass(Number.class, c)) {
+                               if (isParentClass(Float.class, c) || 
isParentClass(Double.class, c))
+                                       _cc = DECIMAL;
+                               else
+                                       _cc = NUMBER;
+                       }
+                       else if (isParentClass(Collection.class, c))
+                               _cc = COLLECTION;
+                       else if (isParentClass(Map.class, c)) {
+                               if (isParentClass(BeanMap.class, c))
+                                       _cc = BEANMAP;
+                               else
+                                       _cc = MAP;
+                       }
+                       else if (c == Character.class)
+                               _cc = CHAR;
+                       else if (c == Boolean.class)
+                               _cc = BOOLEAN;
+                       else if (isParentClass(Date.class, c) || 
isParentClass(Calendar.class, c))
+                               _cc = DATE;
+                       else if (c.isArray())
+                               _cc = ARRAY;
+                       else if (isParentClass(URL.class, c) || 
isParentClass(URI.class, c) || 
c.isAnnotationPresent(org.apache.juneau.annotation.URI.class))
+                               _cc = URI;
+                       else if (isParentClass(Reader.class, c))
+                               _cc = READER;
+                       else if (isParentClass(InputStream.class, c))
+                               _cc = INPUTSTREAM;
+               }
+
+               isMemberClass = c.isMemberClass() && ! isStatic(c);
+
+               // 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
+               for (String methodName : new 
String[]{"fromString","valueOf","parse","parseString","forName","forString"}) {
+                       if (_fromStringMethod == null) {
+                               for (Method m : c.getMethods()) {
+                                       if (isStatic(m) && isPublic(m) && 
isNotDeprecated(m)) {
+                                               String mName = m.getName();
+                                               if (mName.equals(methodName) && 
m.getReturnType() == c) {
+                                                       Class<?>[] args = 
m.getParameterTypes();
+                                                       if (args.length == 1 && 
args[0] == String.class) {
+                                                               
_fromStringMethod = m;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               // Special cases
+               try {
+                       if (c == TimeZone.class)
+                               _fromStringMethod = c.getMethod("getTimeZone", 
String.class);
+                       else if (c == Locale.class)
+                               _fromStringMethod = 
LocaleAsString.class.getMethod("fromString", String.class);
+               } catch (NoSuchMethodException e1) {}
+
+               // Find toObjectMap() method if present.
+               for (Method m : c.getMethods()) {
+                       if (isPublic(m) && isNotDeprecated(m) && ! isStatic(m)) 
{
+                               String mName = m.getName();
+                               if (mName.equals("toObjectMap")) {
+                                       if (m.getParameterTypes().length == 0 
&& m.getReturnType() == ObjectMap.class) {
+                                               _toObjectMapMethod = m;
+                                               break;
+                                       }
+                               } else if (mName.equals("swap")) {
+                                       if (m.getParameterTypes().length == 1 
&& m.getParameterTypes()[0] == BeanSession.class) {
+                                               _swapMethod = m;
+                                               break;
+                                       }
+                               }
+                       }
+               }
+
+               // Find @NameProperty and @ParentProperty methods if present.
+               for (Method m : c.getDeclaredMethods()) {
+                       if (m.isAnnotationPresent(ParentProperty.class) && 
m.getParameterTypes().length == 1) {
+                               m.setAccessible(true);
+                               _parentPropertyMethod = m;
+                       }
+                       if (m.isAnnotationPresent(NameProperty.class) && 
m.getParameterTypes().length == 1) {
+                               m.setAccessible(true);
+                               _namePropertyMethod = m;
+                       }
+               }
+
+               // Note:  Primitive types are normally abstract.
+               isAbstract = Modifier.isAbstract(c.getModifiers()) && ! 
c.isPrimitive();
+
+               // Find constructor(String) method if present.
+               for (Constructor cs : c.getConstructors()) {
+                       if (isPublic(cs) && isNotDeprecated(cs)) {
+                               Class<?>[] args = cs.getParameterTypes();
+                               if (args.length == (isMemberClass ? 1 : 0) && c 
!= Object.class && ! isAbstract) {
+                                       _noArgConstructor = cs;
+                               } else if (args.length == (isMemberClass ? 2 : 
1)) {
+                                       Class<?> arg = args[(isMemberClass ? 1 
: 0)];
+                                       if (arg == String.class)
+                                               _stringConstructor = cs;
+                                       else if 
(ObjectMap.class.isAssignableFrom(arg))
+                                               _objectMapConstructor = cs;
+                                       else if (_swapMethod != null && 
_swapMethod.getReturnType().isAssignableFrom(arg))
+                                               _swapConstructor = cs;
+                                       else if (_cc != NUMBER && 
(Number.class.isAssignableFrom(arg) || (arg.isPrimitive() && (arg == int.class 
|| arg == short.class || arg == long.class || arg == float.class || arg == 
double.class)))) {
+                                               _numberConstructor = cs;
+                                               _numberConstructorType = 
(Class<? extends Number>)ClassUtils.getWrapperIfPrimitive(arg);
+                                       }
+                               }
+                       }
+               }
+
+
+               if (c.isPrimitive()) {
+                       if (c == Boolean.TYPE)
+                               _primitiveDefault = BOOLEAN_DEFAULT;
+                       else if (c == Character.TYPE)
+                               _primitiveDefault = CHARACTER_DEFAULT;
+                       else if (c == Short.TYPE)
+                               _primitiveDefault = SHORT_DEFAULT;
+                       else if (c == Integer.TYPE)
+                               _primitiveDefault = INTEGER_DEFAULT;
+                       else if (c == Long.TYPE)
+                               _primitiveDefault = LONG_DEFAULT;
+                       else if (c == Float.TYPE)
+                               _primitiveDefault = FLOAT_DEFAULT;
+                       else if (c == Double.TYPE)
+                               _primitiveDefault = DOUBLE_DEFAULT;
+                       else if (c == Byte.TYPE)
+                               _primitiveDefault = BYTE_DEFAULT;
+               } else {
+                       if (c == Boolean.class)
+                               _primitiveDefault = BOOLEAN_DEFAULT;
+                       else if (c == Character.class)
+                               _primitiveDefault = CHARACTER_DEFAULT;
+                       else if (c == Short.class)
+                               _primitiveDefault = SHORT_DEFAULT;
+                       else if (c == Integer.class)
+                               _primitiveDefault = INTEGER_DEFAULT;
+                       else if (c == Long.class)
+                               _primitiveDefault = LONG_DEFAULT;
+                       else if (c == Float.class)
+                               _primitiveDefault = FLOAT_DEFAULT;
+                       else if (c == Double.class)
+                               _primitiveDefault = DOUBLE_DEFAULT;
+                       else if (c == Byte.class)
+                               _primitiveDefault = BYTE_DEFAULT;
+               }
+
+               for (Method m : c.getMethods())
+                       if (isPublic(m) && isNotDeprecated(m))
+                               
_publicMethods.put(ClassUtils.getMethodSignature(m), m);
+
+               if (c.getAnnotation(Remoteable.class) != null) {
+                       _remoteableMethods = _publicMethods;
+               } else {
+                       for (Method m : c.getMethods()) {
+                               if (m.getAnnotation(Remoteable.class) != null) {
+                                       if (_remoteableMethods == null)
+                                               _remoteableMethods = new 
LinkedHashMap<String,Method>();
+                                       
_remoteableMethods.put(ClassUtils.getMethodSignature(m), m);
+                               }
+                       }
+               }
+
+               this.cc = _cc;
+               this.isDelegate = _isDelegate;
+               this.fromStringMethod = _fromStringMethod;
+               this.toObjectMapMethod = _toObjectMapMethod;
+               this.swapMethod = _swapMethod;
+               this.parentPropertyMethod = _parentPropertyMethod;
+               this.namePropertyMethod =_namePropertyMethod;
+               this.noArgConstructor = _noArgConstructor;
+               this.stringConstructor = _stringConstructor;
+               this.objectMapConstructor =_objectMapConstructor;
+               this.swapConstructor = _swapConstructor;
+               this.numberConstructor = _numberConstructor;
+               this.numberConstructorType = _numberConstructorType;
+               this.primitiveDefault = _primitiveDefault;
+               this.publicMethods = _publicMethods;
+               this.remoteableMethods = _remoteableMethods;
+       }
+
+       /**
+        * Returns the category of this class.
+        *
+        * @return The category of this class.
+        */
+       public final ClassCategory getClassCategory() {
+               return cc;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class is a superclass of or the same 
as the specified class.
+        *
+        * @param child The comparison class.
+        * @return <jk>true</jk> if this class is a superclass of or the same 
as the specified class.
+        */
+       public final boolean isAssignableFrom(Class<?> child) {
+               return isParentClass(this.innerClass, child);
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class is a subclass of or the same as 
the specified class.
+        *
+        * @param parent The comparison class.
+        * @return <jk>true</jk> if this class is a subclass of or the same as 
the specified class.
+        */
+       public final boolean isInstanceOf(Class<?> parent) {
+               return isParentClass(parent, this.innerClass);
+       }
+
+       /**
+        * Returns the {@link Class} object that this class type wraps.
+        *
+        * @return The wrapped class object.
+        */
+       public final Class<T> getInnerClass() {
+               return innerClass;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class implements {@link Delegate}, 
meaning
+        *      it's a representation of some other object.
+        *
+        * @return <jk>true</jk> if this class implements {@link Delegate}.
+        */
+       public final boolean isDelegate() {
+               return isDelegate;
+       }
+
+       /**
+        * 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 final boolean isMap() {
+               return cc == MAP || cc == BEANMAP;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class is a subclass of {@link BeanMap}.
+        *
+        * @return <jk>true</jk> if this class is a subclass of {@link BeanMap}.
+        */
+       public boolean isBeanMap() {
+               return cc == BEANMAP;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class is a subclass of {@link 
Collection}.
+        *
+        * @return <jk>true</jk> if this class is a subclass of {@link 
Collection}.
+        */
+       public boolean isCollection() {
+               return cc == COLLECTION;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class is a subclass of {@link 
Collection} or is an array.
+        *
+        * @return <jk>true</jk> if this class is a subclass of {@link 
Collection} or is an array.
+        */
+       public boolean isCollectionOrArray() {
+               return cc == COLLECTION || cc == ARRAY;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class is {@link Class}.
+        *
+        * @return <jk>true</jk> if this class is {@link Class}.
+        */
+       public boolean isClass() {
+               return cc == CLASS;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class is an {@link Enum}.
+        *
+        * @return <jk>true</jk> if this class is an {@link Enum}.
+        */
+       public boolean isEnum() {
+               return cc == ENUM;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class is an array.
+        *
+        * @return <jk>true</jk> if this class is an array.
+        */
+       public boolean isArray() {
+               return cc == ARRAY;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class is {@link Object}.
+        *
+        * @return <jk>true</jk> if this class is {@link Object}.
+        */
+       public boolean isObject() {
+               return cc == OBJ;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class is not {@link Object}.
+        *
+        * @return <jk>true</jk> if this class is not {@link Object}.
+        */
+       public boolean isNotObject() {
+               return cc != OBJ;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class is a subclass of {@link Number}.
+        *
+        * @return <jk>true</jk> if this class is a subclass of {@link Number}.
+        */
+       public boolean isNumber() {
+               return cc == NUMBER || cc == DECIMAL;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class is a subclass of {@link Float} 
or {@link Double}.
+        *
+        * @return <jk>true</jk> if this class is a subclass of {@link Float} 
or {@link Double}.
+        */
+       public boolean isDecimal() {
+               return cc == DECIMAL;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class is a {@link Boolean}.
+        *
+        * @return <jk>true</jk> if this class is a {@link Boolean}.
+        */
+       public boolean isBoolean() {
+               return cc == BOOLEAN;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class is a subclass of {@link 
CharSequence}.
+        *
+        * @return <jk>true</jk> if this class is a subclass of {@link 
CharSequence}.
+        */
+       public boolean isCharSequence() {
+               return cc == STR || cc == CHARSEQ;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class is a {@link String}.
+        *
+        * @return <jk>true</jk> if this class is a {@link String}.
+        */
+       public boolean isString() {
+               return cc == STR;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class is a {@link Character}.
+        *
+        * @return <jk>true</jk> if this class is a {@link Character}.
+        */
+       public boolean isChar() {
+               return cc == CHAR;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class is a primitive.
+        *
+        * @return <jk>true</jk> if this class is a primitive.
+        */
+       public boolean isPrimitive() {
+               return innerClass.isPrimitive();
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class is a {@link Date} or {@link 
Calendar}.
+        *
+        * @return <jk>true</jk> if this class is a {@link Date} or {@link 
Calendar}.
+        */
+       public boolean isDate() {
+               return cc == DATE;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class is a {@link URI} or {@link URL}.
+        *
+        * @return <jk>true</jk> if this class is a {@link URI} or {@link URL}.
+        */
+       public boolean isUri() {
+               return cc == URI;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class is a {@link Reader}.
+        *
+        * @return <jk>true</jk> if this class is a {@link Reader}.
+        */
+       public boolean isReader() {
+               return cc == READER;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class is an {@link InputStream}.
+        *
+        * @return <jk>true</jk> if this class is an {@link InputStream}.
+        */
+       public boolean isInputStream() {
+               return cc == INPUTSTREAM;
+       }
+
+       /**
+        * Returns <jk>true</jk> if instance of this object can be 
<jk>null</jk>.
+        * <p>
+        *      Objects can be <jk>null</jk>, but primitives cannot, except for 
chars which can be represented
+        *      by <code>(<jk>char</jk>)0</code>.
+        *
+        * @return <jk>true</jk> if instance of this class can be null.
+        */
+       public boolean isNullable() {
+               if (innerClass.isPrimitive())
+                       return cc == CHAR;
+               return true;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class or one of it's methods are 
annotated with {@link Remoteable @Remotable}.
+        *
+        * @return <jk>true</jk> if this class is remoteable.
+        */
+       public boolean isRemoteable() {
+               return remoteableMethods != null;
+       }
+
+       /**
+        * All methods on this class annotated with {@link Remoteable 
@Remotable}, or all public methods if class is annotated.
+        * Keys are method signatures.
+        *
+        * @return All remoteable methods on this class.
+        */
+       public Map<String,Method> getRemoteableMethods() {
+               return remoteableMethods;
+       }
+
+       /**
+        * All public methods on this class including static methods.
+        * Keys are method signatures.
+        *
+        * @return The public methods on this class.
+        */
+       public Map<String,Method> getPublicMethods() {
+               return publicMethods;
+       }
+
+       /**
+        * Returns <jk>true</jk> if this class has an <code>ObjectMap 
toObjectMap()</code> method.
+        *
+        * @return <jk>true</jk> if class has a <code>toObjectMap()</code> 
method.
+        */
+       public boolean hasToObjectMapMethod() {
+               return toObjectMapMethod != null;
+       }
+
+       /**
+        * Returns the method annotated with {@link NameProperty @NameProperty}.
+        *
+        * @return The method annotated with {@link NameProperty @NameProperty} 
or <jk>null</jk> if method does not exist.
+        */
+       public Method getNameProperty() {
+               return namePropertyMethod;
+       }
+
+       /**
+        * Returns the method annotated with {@link ParentProperty 
@ParentProperty}.
+        *
+        * @return The method annotated with {@link ParentProperty 
@ParentProperty} or <jk>null</jk> if method does not exist.
+        */
+       public Method getParentProperty() {
+               return parentPropertyMethod;
+       }
+
+       /**
+        * Converts an instance of this class to an {@link ObjectMap}.
+        *
+        * @param t The object to convert to a map.
+        * @return The converted object, or <jk>null</jk> if method does not 
have a <code>toObjectMap()</code> method.
+        * @throws BeanRuntimeException Thrown by <code>toObjectMap()</code> 
method invocation.
+        */
+       public ObjectMap toObjectMap(Object t) throws BeanRuntimeException {
+               try {
+                       if (toObjectMapMethod != null)
+                               return (ObjectMap)toObjectMapMethod.invoke(t);
+                       return null;
+               } catch (Exception e) {
+                       throw new BeanRuntimeException(e);
+               }
+       }
+
+       /**
+        * Returns the default value for primitives such as <jk>int</jk> or 
<jk>Integer</jk>.
+        *
+        * @return The default value, or <jk>null</jk> if this class type is 
not a primitive.
+        */
+       @SuppressWarnings("unchecked")
+       public T getPrimitiveDefault() {
+               return (T)primitiveDefault;
+       }
+
+       /**
+        * Returns <jk>true</jk> if the specified object is an instance of this 
class.
+        * This is a simple comparison on the base class itself and not on
+        * any generic parameters.
+        *
+        * @param o The object to check.
+        * @return <jk>true</jk> if the specified object is an instance of this 
class.
+        */
+       public boolean isInstance(Object o) {
+               if (o != null)
+                       return ClassUtils.isParentClass(this.innerClass, 
o.getClass());
+               return false;
+       }
+
+       /**
+        * Returns a readable name for this class (e.g. 
<js>"java.lang.String"</js>, <js>"boolean[]"</js>).
+        *
+        * @return The readable name for this class.
+        */
+       public String getReadableName() {
+               return ClassUtils.getReadableClassName(this.innerClass);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/dba656f3/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java 
b/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java
index 49c1083..c4fb6b6 100644
--- a/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java
+++ b/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java
@@ -316,19 +316,43 @@ public final class ClassUtils {
                return Modifier.isPublic(c.getModifiers());
        }
 
+
+       /**
+        * Locates the no-arg constructor for the specified class.
+        * Constructor must match the visibility requirements specified by 
parameter 'v'.
+        * If class is abstract, always returns <jk>null</jk>.
+        * Note that this also returns the 1-arg constructor for non-static 
member classes.
+        *
+        * @param c The class from which to locate the no-arg constructor.
+        * @param v The minimum visibility.
+        * @return The constructor, or <jk>null</jk> if no no-arg constructor 
exists with the required visibility.
+        */
+       @SuppressWarnings({"rawtypes","unchecked"})
+       public static final <T> Constructor<T> findNoArgConstructor(Class<T> c, 
Visibility v) {
+               int mod = c.getModifiers();
+               if (Modifier.isAbstract(mod))
+                       return null;
+               boolean isMemberClass = c.isMemberClass() && ! isStatic(c);
+               for (Constructor cc : c.getConstructors()) {
+                       mod = cc.getModifiers();
+                       if (cc.getParameterTypes().length == (isMemberClass ? 1 
: 0) && v.isVisible(mod) && isNotDeprecated(cc))
+                               return v.transform(cc);
+               }
+               return null;
+       }
+
        /**
         * Finds the real parameter type of the specified class.
         *
         * @param c The class containing the parameters (e.g. PojoSwap<T,S>)
         * @param index The zero-based index of the parameter to resolve.
-        * @param o The object we're trying to resolve the parameter type for.
+        * @param oc The class we're trying to resolve the parameter type for.
         * @return The resolved real class.
         */
-       public static Class<?> resolveParameterType(Class<?> c, int index, 
Object o) {
+       public static Class<?> resolveParameterType(Class<?> c, int index, 
Class<?> oc) {
 
                // We need to make up a mapping of type names.
                Map<Type,Type> typeMap = new HashMap<Type,Type>();
-               Class<?> oc = o.getClass();
                while (c != oc.getSuperclass()) {
                        extractTypes(typeMap, oc);
                        oc = oc.getSuperclass();
@@ -352,9 +376,7 @@ public final class ClassUtils {
                        List<Class<?>> nestedOuterTypes = new 
LinkedList<Class<?>>();
                        for (Class<?> ec = oc.getEnclosingClass(); ec != null; 
ec = ec.getEnclosingClass()) {
                                try {
-                                       Field this$0 = 
oc.getDeclaredField("this$0");
-                                       Object outerInstance = this$0.get(o);
-                                       Class<?> outerClass = 
outerInstance.getClass();
+                                       Class<?> outerClass = oc.getClass();
                                        nestedOuterTypes.add(outerClass);
                                        Map<Type,Type> outerTypeMap = new 
HashMap<Type,Type>();
                                        extractTypes(outerTypeMap, outerClass);

Reply via email to