Commits

John Marsden  committed 8e2cc86

Refactor and re-alignment with specifications 3 (Dont use this version - marshaler is broken)

  • Participants
  • Parent commits c99a700

Comments (0)

Files changed (19)

File src/main/java/cc/plural/jsonij/marshal/Inspector.java

 /**
  *
  * @author openecho
+ * @deprecated 
  */
 public class Inspector {
 

File src/main/java/cc/plural/jsonij/marshal/InspectorFilter.java

 import java.util.ArrayList;
 import java.util.List;
 
+/**
+ * @deprecated 
+ */
 public class InspectorFilter {
 
     protected List<Class<?>> classFilter;

File src/main/java/cc/plural/jsonij/marshal/InspectorProperty.java

 package cc.plural.jsonij.marshal;
 
 /**
- *
- * @author jmarsden
+ * @deprecated 
  */
 public class InspectorProperty {
 

File src/main/java/cc/plural/jsonij/marshal/JSONDocumentMarshaler.java

  */
 package cc.plural.jsonij.marshal;
 
+import cc.plural.jsonij.reflect.JavaType;
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 public class JSONDocumentMarshaler {
 
     public static String innerArrayAttribute;
+
     public static String innerObjectAttribute;
 
     static {
-	innerArrayAttribute = "_innerArray";
-	innerObjectAttribute = "_innerObject";
+        innerArrayAttribute = "_innerArray";
+        innerObjectAttribute = "_innerObject";
     }
 
     public Object marshalJSONDocument(JSON json, Class<?> objectClass) throws JSONMarshalerException {
-	Object resultObject = null;
-	Value jsonRoot = json.getRoot();
-	if (jsonRoot.type() == Value.TYPE.OBJECT) {
-	    JSON.Object<CharSequence, Value> jsonObjectRoot = (JSON.Object<CharSequence, Value>) jsonRoot;
-	    resultObject = marshalJSONDocumentObject(jsonObjectRoot, objectClass);
-	} else if (jsonRoot.type() == Value.TYPE.ARRAY) {
-	    JSON.Array<Value> jsonArrayRoot = (JSON.Array<Value>) jsonRoot;
-	    resultObject = marshalJSONDocumentArray(jsonArrayRoot, objectClass);
-	} else {
-	    //throw new Exception();
-	}
-	return resultObject;
+        Object resultObject = null;
+        Value jsonRoot = json.getRoot();
+        if(jsonRoot.type() == Value.TYPE.OBJECT) {
+            JSON.Object<CharSequence, Value> jsonObjectRoot = (JSON.Object<CharSequence, Value>) jsonRoot;
+            resultObject = marshalJSONDocumentObject(jsonObjectRoot, objectClass);
+        } else if(jsonRoot.type() == Value.TYPE.ARRAY) {
+            JSON.Array<Value> jsonArrayRoot = (JSON.Array<Value>) jsonRoot;
+            resultObject = marshalJSONDocumentArray(jsonArrayRoot, objectClass);
+        } else {
+            //throw new Exception();
+        }
+        return resultObject;
     }
 
     public Object marshalJSONDocument(Value value, Class<?> objectClass) throws JSONMarshalerException {
-	Object resultObject = null;
-	if (value.type() == Value.TYPE.OBJECT) {
-	    JSON.Object<CharSequence, Value> jsonObjectRoot = (JSON.Object<CharSequence, Value>) value;
-	    resultObject = marshalJSONDocumentObject(jsonObjectRoot, objectClass);
-	} else if (value.type() == Value.TYPE.ARRAY) {
-	    JSON.Array<Value> jsonArrayRoot = (JSON.Array<Value>) value;
-	    resultObject = marshalJSONDocumentArray(jsonArrayRoot, objectClass);
-	} else {
-	    //throw new Exception();
-	}
-	return resultObject;
+        Object resultObject = null;
+        if(value.type() == Value.TYPE.OBJECT) {
+            JSON.Object<CharSequence, Value> jsonObjectRoot = (JSON.Object<CharSequence, Value>) value;
+            resultObject = marshalJSONDocumentObject(jsonObjectRoot, objectClass);
+        } else if(value.type() == Value.TYPE.ARRAY) {
+            JSON.Array<Value> jsonArrayRoot = (JSON.Array<Value>) value;
+            resultObject = marshalJSONDocumentArray(jsonArrayRoot, objectClass);
+        } else {
+            //throw new Exception();
+        }
+        return resultObject;
     }
 
     public Object marshalJSONDocumentObject(JSON.Object<CharSequence, Value> jsonObject, Class<?> objectClass) throws JSONMarshalerException {
-	Object resultObject = null;
-
-	Set<Entry<CharSequence, Value>> entrySet = jsonObject.entrySet();
-	Iterator<Entry<CharSequence, Value>> entrySetIterator = entrySet.iterator();
-	Entry<CharSequence, Value> entry = null;
-	Inspector inspector = new Inspector(objectClass);
-	inspector.inspect();
-
-	List<MarshalerPropertyValue> marshalPropertyValues = new ArrayList<MarshalerPropertyValue>();
-	while (entrySetIterator.hasNext()) {
-	    entry = entrySetIterator.next();
-	    if (entry.getKey().toString().equals(innerObjectAttribute) && inspector.hasInnerObject()) {
-		/**
-		 * todo: handle the inner object
-		 */
-	    }
-	    String propertyName = entry.getKey().toString();
-	    if (inspector.hasProperty(propertyName)) {
-		MarshalerPropertyValue propertyValue = new MarshalerPropertyValue(propertyName, inspector.getProperty(propertyName), entry.getValue());
-		marshalPropertyValues.add(propertyValue);
-	    }
-	}
-
-
-	try {
-	    resultObject = objectClass.newInstance();
-	    for (MarshalerPropertyValue propertyValue : marshalPropertyValues) {
-		if (propertyValue.getValue().isNull()) {
-		    // TODO: Handle Null
-		}
-		InspectorProperty property = propertyValue.getProperty();
-		if (property.getAccessPropertyType() == InspectorProperty.TYPE.METHOD) {
-		    Method method = objectClass.getMethod(property.getMutateName(), property.getMutateInputType());
-		    JavaType mutateType = JavaType.inspectObjectType(property.getMutateInputType());
-
-		    JSON.Array<Value> arrayJSON = null;
-
-		    switch (mutateType) {
-			case BOOLEAN:
-			    method.invoke(resultObject, propertyValue.getValue().getBoolean());
-			    break;
-			case BYTE:
-			    method.invoke(resultObject, propertyValue.getValue().getNumber().byteValue());
-			    break;
-			case INTEGER:
-			    method.invoke(resultObject, propertyValue.getValue().getNumber().intValue());
-			    break;
-			case SHORT:
-			    method.invoke(resultObject, propertyValue.getValue().getNumber().shortValue());
-			    break;
-			case FLOAT:
-			    method.invoke(resultObject, propertyValue.getValue().getNumber().floatValue());
-			    break;
-			case LONG:
-			    method.invoke(resultObject, propertyValue.getValue().getNumber().longValue());
-			    break;
-			case DOUBLE:
-			    method.invoke(resultObject, propertyValue.getValue().getNumber().doubleValue());
-			    break;
-			case STRING:
-			    method.invoke(resultObject, propertyValue.getValue().getString());
-			    break;
-			case ENUM:
-			    method.invoke(resultObject, propertyValue.getValue().getString());
-			    break;
-			case MAP:
-
-			    break;
-			case LIST:
-
-			    break;
-			case OBJECT:
-			    JSON.Object<CharSequence, Value> objectJSON = (JSON.Object<CharSequence, Value>) propertyValue.getValue();
-			    method.invoke(resultObject, marshalJSONDocumentObject(objectJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY_BYTE:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY_SHORT:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY_INTEGER:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY_FLOAT:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY_DOUBLE:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY_LONG:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY_STRING:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY_ENUM:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY_LIST:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY_MAP:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			default:
-
-			    break;
-		    }
-		} else if (property.getAccessPropertyType() == InspectorProperty.TYPE.FIELD) {
-		    Field field = objectClass.getField(propertyValue.getProperty().getMutateName());
-		    JavaType mutateType = JavaType.inspectObjectType(property.getMutateInputType());
-
-		    JSON.Array<Value> arrayJSON = null;
-
-		    switch (mutateType) {
-			case BOOLEAN:
-			    field.set(resultObject, propertyValue.getValue().getBoolean());
-			    break;
-			case BYTE:
-			    field.set(resultObject, propertyValue.getValue().getNumber().byteValue());
-			    break;
-			case INTEGER:
-			    field.set(resultObject, propertyValue.getValue().getNumber().intValue());
-			    break;
-			case SHORT:
-			    field.set(resultObject, propertyValue.getValue().getNumber().shortValue());
-			    break;
-			case FLOAT:
-			    field.set(resultObject, propertyValue.getValue().getNumber().floatValue());
-			    break;
-			case LONG:
-			    field.set(resultObject, propertyValue.getValue().getNumber().longValue());
-			    break;
-			case DOUBLE:
-			    field.set(resultObject, propertyValue.getValue().getNumber().doubleValue());
-			    break;
-			case STRING:
-			    field.set(resultObject, propertyValue.getValue().getString());
-			    break;
-			case ENUM:
-
-			    break;
-			case MAP:
-
-			    break;
-			case LIST:
-
-			    break;
-			case OBJECT:
-			    JSON.Object<CharSequence, Value> objectJSON = (JSON.Object<CharSequence, Value>) propertyValue.getValue();
-			    field.set(resultObject, marshalJSONDocumentObject(objectJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY_BYTE:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY_SHORT:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY_INTEGER:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY_FLOAT:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY_DOUBLE:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY_LONG:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY_STRING:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY_ENUM:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY_LIST:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY_MAP:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			case ARRAY_ARRAY:
-			    arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-			    field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-			    break;
-			default:
-
-			    break;
-		    }
-		}
-
-	    }
-
-	} catch (InstantiationException ex) {
-	    Logger.getLogger(JSONDocumentMarshaler.class.getName()).log(Level.SEVERE, null, ex);
-	} catch (IllegalAccessException ex) {
-	    Logger.getLogger(JSONDocumentMarshaler.class.getName()).log(Level.SEVERE, null, ex);
-	} catch (NoSuchFieldException ex) {
-	    Logger.getLogger(JSONDocumentMarshaler.class.getName()).log(Level.SEVERE, null, ex);
-	} catch (NoSuchMethodException ex) {
-	    Logger.getLogger(JSONDocumentMarshaler.class.getName()).log(Level.SEVERE, null, ex);
-	} catch (InvocationTargetException ex) {
-	    Logger.getLogger(JSONDocumentMarshaler.class.getName()).log(Level.SEVERE, null, ex);
-	}
-	return resultObject;
+        Object resultObject = null;
+
+        Set<Entry<CharSequence, Value>> entrySet = jsonObject.entrySet();
+        Iterator<Entry<CharSequence, Value>> entrySetIterator = entrySet.iterator();
+        Entry<CharSequence, Value> entry = null;
+        Inspector inspector = new Inspector(objectClass);
+        inspector.inspect();
+
+        List<MarshalerPropertyValue> marshalPropertyValues = new ArrayList<MarshalerPropertyValue>();
+        while(entrySetIterator.hasNext()) {
+            entry = entrySetIterator.next();
+            if(entry.getKey().toString().equals(innerObjectAttribute) && inspector.hasInnerObject()) {
+                /**
+                 * todo: handle the inner object
+                 */
+            }
+            String propertyName = entry.getKey().toString();
+            if(inspector.hasProperty(propertyName)) {
+                MarshalerPropertyValue propertyValue = new MarshalerPropertyValue(propertyName, inspector.getProperty(propertyName), entry.getValue());
+                marshalPropertyValues.add(propertyValue);
+            }
+        }
+
+
+        try {
+            resultObject = objectClass.newInstance();
+            for(MarshalerPropertyValue propertyValue : marshalPropertyValues) {
+                if(propertyValue.getValue().isNull()) {
+                    // TODO: Handle Null
+                }
+                InspectorProperty property = propertyValue.getProperty();
+                if(property.getAccessPropertyType() == InspectorProperty.TYPE.METHOD) {
+                    Method method = objectClass.getMethod(property.getMutateName(), property.getMutateInputType());
+                    JavaType mutateType = JavaType.inspectObjectType(property.getMutateInputType());
+
+                    JSON.Array<Value> arrayJSON = null;
+
+                    switch(mutateType) {
+                        case BOOLEAN:
+                            method.invoke(resultObject, propertyValue.getValue().getBoolean());
+                            break;
+                        case BYTE:
+                            method.invoke(resultObject, propertyValue.getValue().getNumber().byteValue());
+                            break;
+                        case INTEGER:
+                            method.invoke(resultObject, propertyValue.getValue().getNumber().intValue());
+                            break;
+                        case SHORT:
+                            method.invoke(resultObject, propertyValue.getValue().getNumber().shortValue());
+                            break;
+                        case FLOAT:
+                            method.invoke(resultObject, propertyValue.getValue().getNumber().floatValue());
+                            break;
+                        case LONG:
+                            method.invoke(resultObject, propertyValue.getValue().getNumber().longValue());
+                            break;
+                        case DOUBLE:
+                            method.invoke(resultObject, propertyValue.getValue().getNumber().doubleValue());
+                            break;
+                        case STRING:
+                            method.invoke(resultObject, propertyValue.getValue().getString());
+                            break;
+                        case ENUM:
+                            method.invoke(resultObject, propertyValue.getValue().getString());
+                            break;
+                        case MAP:
+
+                            break;
+                        case LIST:
+
+                            break;
+                        case OBJECT:
+                            JSON.Object<CharSequence, Value> objectJSON = (JSON.Object<CharSequence, Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentObject(objectJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_BYTE:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_SHORT:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_INTEGER:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_FLOAT:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_DOUBLE:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_LONG:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_STRING:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_ENUM:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_LIST:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_MAP:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        default:
+
+                            break;
+                    }
+                } else if(property.getAccessPropertyType() == InspectorProperty.TYPE.FIELD) {
+                    Field field = objectClass.getField(propertyValue.getProperty().getMutateName());
+                    JavaType mutateType = JavaType.inspectObjectType(property.getMutateInputType());
+
+                    JSON.Array<Value> arrayJSON = null;
+
+                    switch(mutateType) {
+                        case BOOLEAN:
+                            field.set(resultObject, propertyValue.getValue().getBoolean());
+                            break;
+                        case BYTE:
+                            field.set(resultObject, propertyValue.getValue().getNumber().byteValue());
+                            break;
+                        case INTEGER:
+                            field.set(resultObject, propertyValue.getValue().getNumber().intValue());
+                            break;
+                        case SHORT:
+                            field.set(resultObject, propertyValue.getValue().getNumber().shortValue());
+                            break;
+                        case FLOAT:
+                            field.set(resultObject, propertyValue.getValue().getNumber().floatValue());
+                            break;
+                        case LONG:
+                            field.set(resultObject, propertyValue.getValue().getNumber().longValue());
+                            break;
+                        case DOUBLE:
+                            field.set(resultObject, propertyValue.getValue().getNumber().doubleValue());
+                            break;
+                        case STRING:
+                            field.set(resultObject, propertyValue.getValue().getString());
+                            break;
+                        case ENUM:
+
+                            break;
+                        case MAP:
+
+                            break;
+                        case LIST:
+
+                            break;
+                        case OBJECT:
+                            JSON.Object<CharSequence, Value> objectJSON = (JSON.Object<CharSequence, Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentObject(objectJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_BYTE:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_SHORT:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_INTEGER:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_FLOAT:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_DOUBLE:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_LONG:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_STRING:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_ENUM:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_LIST:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_MAP:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_ARRAY:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        default:
+
+                            break;
+                    }
+                }
+
+            }
+
+        } catch(InstantiationException ex) {
+            Logger.getLogger(JSONDocumentMarshaler.class.getName()).log(Level.SEVERE, null, ex);
+        } catch(IllegalAccessException ex) {
+            Logger.getLogger(JSONDocumentMarshaler.class.getName()).log(Level.SEVERE, null, ex);
+        } catch(NoSuchFieldException ex) {
+            Logger.getLogger(JSONDocumentMarshaler.class.getName()).log(Level.SEVERE, null, ex);
+        } catch(NoSuchMethodException ex) {
+            Logger.getLogger(JSONDocumentMarshaler.class.getName()).log(Level.SEVERE, null, ex);
+        } catch(InvocationTargetException ex) {
+            Logger.getLogger(JSONDocumentMarshaler.class.getName()).log(Level.SEVERE, null, ex);
+        }
+        return resultObject;
     }
 
     public Object marshalJSONDocument(InputStream stream, Class<?> objectClass) throws JSONMarshalerException {
-	JSON json;
-	try {
-	    json = JSON.parse(stream);
-
-	} catch (ParserException ex) {
-	    throw new JSONMarshalerException("", ex);
-	} catch (IOException ex) {
-	    throw new JSONMarshalerException("", ex);
-	}
-	return marshalJSONDocument(json, objectClass);
+        JSON json;
+        try {
+            json = JSON.parse(stream);
+
+        } catch(ParserException ex) {
+            throw new JSONMarshalerException("", ex);
+        } catch(IOException ex) {
+            throw new JSONMarshalerException("", ex);
+        }
+        return marshalJSONDocument(json, objectClass);
     }
 
     public Object marshalJSONDocument(String jsonString, Class<?> objectClass) throws JSONMarshalerException {
-	JSON json;
-	try {
-	    json = JSON.parse(jsonString);
-
-	} catch (ParserException ex) {
-	    throw new JSONMarshalerException("", ex);
-	} catch (IOException ex) {
-	    throw new JSONMarshalerException("", ex);
-	}
-	return marshalJSONDocument(json, objectClass);
+        JSON json;
+        try {
+            json = JSON.parse(jsonString);
+
+        } catch(ParserException ex) {
+            throw new JSONMarshalerException("", ex);
+        } catch(IOException ex) {
+            throw new JSONMarshalerException("", ex);
+        }
+        return marshalJSONDocument(json, objectClass);
     }
 
     /*
      * return null; }
      */
     public Object marshalJSONDocumentArray(JSON.Array<Value> jsonArray, Class<?> objectClass) throws JSONMarshalerException {
-	int size = jsonArray.size();
-	Class<?> componentClass = objectClass.getComponentType();
-	Object array = Array.newInstance(componentClass, size);
-	for (int i = 0; i < size; i++) {
-	    Value value =  jsonArray.get(i);
-	    if(value.getValueType() == Value.TYPE.OBJECT) {
-		Array.set(array, i, marshalJSONDocumentObject((JSON.Object<CharSequence, Value>) value, componentClass));
-	    } else if(value.getValueType() == Value.TYPE.ARRAY) {
-		Array.set(array, i, marshalJSONDocumentArray((JSON.Array<Value>) value, componentClass));
-	    } else if (componentClass.equals(int.class)) {
-		Array.set(array, i, jsonArray.get(i).getNumber().intValue());
-	    } else if (componentClass.equals(float.class)) {
-		Array.set(array, i, jsonArray.get(i).getNumber().floatValue());
-	    } else if (componentClass.equals(double.class)) {
-		Array.set(array, i, jsonArray.get(i).getNumber().doubleValue());
-	    } else if (componentClass.equals(byte.class)) {
-		Array.set(array, i, jsonArray.get(i).getNumber().byteValue());
-	    } else if (componentClass.equals(boolean.class)) {
-		Array.set(array, i, jsonArray.get(i).getBoolean());
-	    } else if (componentClass.equals(String.class)) {
-		Array.set(array, i, jsonArray.get(i).getString());
-	    } else {
-		//
-	    }
-	}
-	return array;
+        int size = jsonArray.size();
+        Class<?> componentClass = objectClass.getComponentType();
+        Object array = Array.newInstance(componentClass, size);
+        for(int i = 0; i < size; i++) {
+            Value value = jsonArray.get(i);
+            if(value.getValueType() == Value.TYPE.OBJECT) {
+                Array.set(array, i, marshalJSONDocumentObject((JSON.Object<CharSequence, Value>) value, componentClass));
+            } else if(value.getValueType() == Value.TYPE.ARRAY) {
+                Array.set(array, i, marshalJSONDocumentArray((JSON.Array<Value>) value, componentClass));
+            } else if(componentClass.equals(int.class)) {
+                Array.set(array, i, jsonArray.get(i).getNumber().intValue());
+            } else if(componentClass.equals(float.class)) {
+                Array.set(array, i, jsonArray.get(i).getNumber().floatValue());
+            } else if(componentClass.equals(double.class)) {
+                Array.set(array, i, jsonArray.get(i).getNumber().doubleValue());
+            } else if(componentClass.equals(byte.class)) {
+                Array.set(array, i, jsonArray.get(i).getNumber().byteValue());
+            } else if(componentClass.equals(boolean.class)) {
+                Array.set(array, i, jsonArray.get(i).getBoolean());
+            } else if(componentClass.equals(String.class)) {
+                Array.set(array, i, jsonArray.get(i).getString());
+            } else {
+                //
+            }
+        }
+        return array;
     }
 
     /*
      */
     public static class MarshalerPropertyValue {
 
-	String name;
-	InspectorProperty property;
-	Value value;
-
-	public MarshalerPropertyValue() {
-	    this.name = null;
-	    this.property = null;
-	    this.value = null;
-	}
-
-	public MarshalerPropertyValue(String name, InspectorProperty property, Value value) {
-	    this.name = name;
-	    this.property = property;
-	    this.value = value;
-	}
-
-	public String getName() {
-	    return name;
-	}
-
-	public void setName(String name) {
-	    this.name = name;
-	}
-
-	public InspectorProperty getProperty() {
-	    return property;
-	}
-
-	public void setProperty(InspectorProperty property) {
-	    this.property = property;
-	}
-
-	public Value getValue() {
-	    return value;
-	}
-
-	public void setValue(Value value) {
-	    this.value = value;
-	}
-
-	@Override
-	public String toString() {
-	    StringBuilder resultBuilder = new StringBuilder();
-	    resultBuilder.append("MarshalerPropertyValue [Name:").append(name).append('|');
-	    resultBuilder.append("Property:").append(property);
-	    resultBuilder.append("->");
-	    resultBuilder.append("Value:").append(value).append(']');
-	    return resultBuilder.toString();
-	}
+        String name;
+
+        InspectorProperty property;
+
+        Value value;
+
+        public MarshalerPropertyValue() {
+            this.name = null;
+            this.property = null;
+            this.value = null;
+        }
+
+        public MarshalerPropertyValue(String name, InspectorProperty property, Value value) {
+            this.name = name;
+            this.property = property;
+            this.value = value;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+
+        public InspectorProperty getProperty() {
+            return property;
+        }
+
+        public void setProperty(InspectorProperty property) {
+            this.property = property;
+        }
+
+        public Value getValue() {
+            return value;
+        }
+
+        public void setValue(Value value) {
+            this.value = value;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder resultBuilder = new StringBuilder();
+            resultBuilder.append("MarshalerPropertyValue [Name:").append(name).append('|');
+            resultBuilder.append("Property:").append(property);
+            resultBuilder.append("->");
+            resultBuilder.append("Value:").append(value).append(']');
+            return resultBuilder.toString();
+        }
     }
 }

File src/main/java/cc/plural/jsonij/marshal/JavaMarshaler.java

 
 import cc.plural.jsonij.JSON;
 import cc.plural.jsonij.Value;
+import cc.plural.jsonij.reflect.JavaType;
 
 /**
  *

File src/main/java/cc/plural/jsonij/marshal/JavaObjectMarshaler.java

  */
 package cc.plural.jsonij.marshal;
 
-import java.lang.reflect.Array;
+import cc.plural.jsonij.reflect.JavaType;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 
 import cc.plural.jsonij.JSON;
 import cc.plural.jsonij.Value;
 import cc.plural.jsonij.marshal.JavaMarshaler.CycleDetector;
 import cc.plural.jsonij.marshal.annotation.JSONEncoder;
-import cc.plural.jsonij.marshal.codec.ClassJSONCodec;
-import cc.plural.jsonij.marshal.codec.DateJSONCodec;
+import cc.plural.jsonij.reflect.ClassProperty;
+import cc.plural.jsonij.reflect.ClassProperty.ClassPropertyAccessor;
+import cc.plural.jsonij.reflect.Inspection;
 
 /**
  *
         inspectedClasses = new HashMap<Class<?>, Inspector>();
     }
 
+    /*
     public boolean isObjectType(Class<?> objectClass) {
-        Inspector inspector = JavaType.getInstpector(objectClass);
+        Inspector inspector = null;//JavaType.getInstpector(objectClass);
         InspectorProperty[] properties = inspector.getProperties();
         if (( properties != null && Array.getLength(properties) > 0 ) || inspector.hasInnerArray() || inspector.hasInnerObject()) {
             return true;
         }
         return false;
     }
-
+    */
+    
     public Value marshalJavaObject(Object o, CycleDetector cycleDetector) {
         Class<?> objectClass = o.getClass();
         // Check for JSONEncoder Annotation
         }
 
         // Find an object inspector
-        Inspector inspector = JavaType.getInstpector(objectClass);
+        Inspection inspection = JavaType.getInspection(objectClass);
 
         HashMap<String, Value> valueCollector = new HashMap<String, Value>();
-        InspectorProperty[] properties = inspector.getProperties();
+        List<ClassProperty> properties = inspection.getProperties();
         String name = null;
-        Value value = null;
+        Value value;
         int propCount = 0;
-        for (InspectorProperty property : properties) {
-            if (!property.hasAccessor()) {
+        for (ClassProperty property : properties) {
+            ClassPropertyAccessor accessor = property.getAccessor();
+            if (accessor == null || !accessor.canAccess()) {
                 continue;
             }
-            name = property.getPropertyName();
-            if (property.getAccessPropertyType() == InspectorProperty.TYPE.METHOD) {
-                String accessorName = property.getAccessName();
+            if (accessor.methodType()) {
                 try {
-                    Method method = objectClass.getMethod(accessorName);
+                    Method method = property.getAccessor().getMethod();
                     value = marshalObjectMethodValue(method, o, cycleDetector);
                     if (value == null) {
                         continue;
                 catch (Exception ex) {
                     value = new JSON.String(ex.toString());
                 }
-            } else if (property.getAccessPropertyType() == InspectorProperty.TYPE.FIELD) {
-                String accessorName = property.getAccessName();
+            } else if (accessor.fieldType()) {
                 try {
-                    Field field = objectClass.getField(accessorName);
+                    Field field = property.getAccessor().getField();
                     value = marshalObjectFieldValue(field, o, cycleDetector);
                     if (value == null) {
                         continue;
             propCount++;
             valueCollector.put(name, value);
         }
-        if (inspector.hasInnerArray()) {
+        if (inspection.hasInnerList()) {
             if (propCount > 0) {
                 valueCollector.put("innerArray", marshaler.marshalJavaList(o, cycleDetector));
             } else {
                 return marshaler.marshalJavaList(o, cycleDetector);
             }
         }
-        if (inspector.hasInnerObject()) {
+        if (inspection.hasInnerMap()) {
             if (propCount > 0) {
                 valueCollector.put("innerObject", marshaler.marshalJavaMap(o, cycleDetector));
             } else {

File src/main/java/cc/plural/jsonij/marshal/JavaType.java

-/*
- * Copyright 2011 jmarsden.
- *
- * Licensed 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 cc.plural.jsonij.marshal;
-
-import java.lang.reflect.Array;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * JavaType Utility. Queries objects for their types and manages inspector
- * instances so time is not wasted re-inspecting the same objects.
- *
- * Inspecting is the task of reflecting attributes and methods and their
- * types for access.
- *
- * @author jmarsden@plural.cc
- */
-public enum JavaType {
-
-    /**
-     * The JavaTypes possible for an inspection.
-     * UNKNOWN will be returned where an object cannot be decided.
-     * ARRAY will be returned for an array of Objects.
-     */
-    BOOLEAN,
-    BYTE,
-    SHORT,
-    INTEGER,
-    FLOAT,
-    DOUBLE,
-    LONG,
-    STRING,
-    LIST,
-    OBJECT,
-    MAP,
-    ENUM,
-    ARRAY,
-    ARRAY_BOOLEAN,
-    ARRAY_BYTE,
-    ARRAY_SHORT,
-    ARRAY_INTEGER,
-    ARRAY_FLOAT,
-    ARRAY_DOUBLE,
-    ARRAY_LONG,
-    ARRAY_STRING,
-    ARRAY_ENUM,
-    // HMMN
-    ARRAY_LIST,
-    ARRAY_MAP,
-    ARRAY_ARRAY,
-    UNKOWN;
-
-    boolean primitive;
-
-    JavaArrayType arrayType;
-
-    static final protected Map<Class<?>, Inspector> inspectedClasses;
-
-    static {
-        inspectedClasses = new HashMap<Class<?>, Inspector>();
-    }
-
-    JavaType() {
-        primitive = true;
-    }
-
-    public void setPrimitive(boolean primitive) {
-        this.primitive = primitive;
-    }
-
-    public boolean isPrimitive() {
-        return this.primitive;
-    }
-
-    public static JavaType inspectObjectType(Class<?> c) {
-        JavaType type = null;
-        if(c == boolean.class) {
-            type = JavaType.BOOLEAN;
-            type.setPrimitive(true);
-            return type;
-        } else if(c == Boolean.class) {
-            type = JavaType.BOOLEAN;
-            type.setPrimitive(false);
-            return type;
-        } else if(c == int.class) {
-            type = JavaType.INTEGER;
-            type.setPrimitive(true);
-            return type;
-        } else if(c == Integer.class) {
-            type = JavaType.INTEGER;
-            type.setPrimitive(false);
-            return type;
-        } else if(c == double.class) {
-            type = JavaType.DOUBLE;
-            type.setPrimitive(true);
-            return type;
-        } else if(c == Double.class) {
-            type = JavaType.DOUBLE;
-            type.setPrimitive(false);
-            return type;
-        } else if(c == float.class) {
-            type = JavaType.FLOAT;
-            type.setPrimitive(true);
-            return type;
-        } else if(c == Float.class) {
-            type = JavaType.FLOAT;
-            type.setPrimitive(false);
-            return type;
-        } else if(c == long.class) {
-            type = JavaType.LONG;
-            type.setPrimitive(true);
-            return type;
-        } else if(c == Long.class) {
-            type = JavaType.LONG;
-            type.setPrimitive(false);
-            return type;
-        } else if(c == short.class) {
-            type = JavaType.SHORT;
-            type.setPrimitive(true);
-            return type;
-        } else if(c == Short.class) {
-            type = JavaType.SHORT;
-            type.setPrimitive(false);
-            return type;
-        } else if(c == byte.class) {
-            type = JavaType.BYTE;
-            type.setPrimitive(true);
-            return type;
-        } else if(c == Byte.class) {
-            type = JavaType.BYTE;
-            type.setPrimitive(false);
-            return type;
-        } else if(c.isEnum()) {
-            type = JavaType.ENUM;
-            type.setPrimitive(false);
-            return type;
-        } else if(c == String.class || ((c == char.class || c == Character.class))) {
-            type = JavaType.STRING;
-            type.setPrimitive(false);
-            return type;
-        } else if(c.isArray()) {
-            type = getArrayType(c);
-            return type;
-        }
-        if(type == null) {
-            if(c == List.class) {
-                type = JavaType.LIST;
-                type.setPrimitive(false);
-                return type;
-            } else {
-                // Test if Object is a List
-                Class<?>[] interfaces = c.getInterfaces();
-                for(int i = 0; i < Array.getLength(interfaces); i++) {
-                    if(interfaces[i] == List.class) {
-                        type = JavaType.LIST;
-                        type.setPrimitive(false);
-                        return type;
-                    }
-                }
-            }
-            Class<?>[] interfaces = c.getInterfaces();
-            // Test if super classes are List
-            Class<?> parent = c.getSuperclass();
-            if(parent != null) {
-                do {
-                    interfaces = parent.getInterfaces();
-                    for(int i = 0; i < Array.getLength(interfaces); i++) {
-                        if(interfaces[i] == List.class) {
-                            type = JavaType.LIST;
-                            return type;
-                        }
-                    }
-                } while((parent = parent.getSuperclass()) != null);
-            }
-        }
-        if(type == null) {
-            if(c == Map.class) {
-                type = JavaType.MAP;
-                type.setPrimitive(false);
-                return type;
-            } else {
-                // Test if Object is a List
-                Class<?>[] interfaces = c.getInterfaces();
-                for(int i = 0; i < Array.getLength(interfaces); i++) {
-                    if(interfaces[i] == Map.class) {
-                        type = JavaType.MAP;
-                        type.setPrimitive(false);
-                        return type;
-                    }
-                }
-            }
-            Class<?>[] interfaces = c.getInterfaces();
-            Class<?> parent = c.getSuperclass();
-            if(parent != null) {
-                do {
-                    interfaces = parent.getInterfaces();
-                    for(int i = 0; i < Array.getLength(interfaces); i++) {
-                        if(interfaces[i] == Map.class) {
-                            type = JavaType.MAP;
-                            return type;
-                        }
-                    }
-                } while((parent = parent.getSuperclass()) != null);
-            }
-        }
-        if(c.getComponentType() ==  Class.class) {
-            type = JavaType.OBJECT;
-            return type;
-        }
-         
-        if(type == null) {
-            if(isObjectType(c)) {
-                type = JavaType.OBJECT;
-                type.setPrimitive(false);
-                return type;
-            }
-            
-        }
-        if(type != null) {
-            return type;
-        } else {
-            return JavaType.UNKOWN;
-        }
-    }
-
-    public static Inspector getInstpector(Class<?> objectClass) {
-        Inspector inspector = null;
-        synchronized(inspectedClasses) {
-            if(inspectedClasses.containsKey(objectClass)) {
-                inspector = inspectedClasses.get(objectClass);
-            } else {
-                inspector = new Inspector(objectClass);
-                inspector.inspect();
-                inspectedClasses.put(objectClass, inspector);
-            }
-        }
-        return inspector;
-    }
-
-    public static boolean isObjectType(Class<?> objectClass) {
-        Inspector inspector = getInstpector(objectClass);
-        InspectorProperty[] properties = inspector.getProperties();
-        if((properties != null && Array.getLength(properties) > 0) || inspector.hasInnerArray() || inspector.hasInnerObject()) {
-            return true;
-        }
-        return false;
-    }
-
-    @SuppressWarnings("unused")
-    public static JavaType getArrayType(Class<?> objectClass) {
-        JavaType resultType = null;
-        Class<?> objectComponentType = objectClass.getComponentType();
-
-        if(!objectComponentType.isArray()) {
-
-
-            JavaType componentType = inspectObjectType(objectComponentType);
-            //resultType.arrayType = new JavaArrayType(objectClass);
-            switch(componentType) {
-                case BOOLEAN:
-                    resultType = JavaType.ARRAY_BOOLEAN;
-                    resultType.setPrimitive(componentType.isPrimitive());
-                    break;
-                case BYTE:
-                    resultType = JavaType.ARRAY_BYTE;
-                    resultType.setPrimitive(componentType.isPrimitive());
-                    break;
-                case INTEGER:
-                    resultType = JavaType.ARRAY_INTEGER;
-                    resultType.setPrimitive(componentType.isPrimitive());
-                    break;
-                case SHORT:
-                    resultType = JavaType.ARRAY_SHORT;
-                    resultType.setPrimitive(componentType.isPrimitive());
-                    break;
-                case FLOAT:
-                    resultType = JavaType.ARRAY_FLOAT;
-                    resultType.setPrimitive(componentType.isPrimitive());
-                    break;
-                case LONG:
-                    resultType = JavaType.ARRAY_LONG;
-                    resultType.setPrimitive(componentType.isPrimitive());
-                    break;
-                case DOUBLE:
-                    resultType = JavaType.ARRAY_DOUBLE;
-                    resultType.setPrimitive(componentType.isPrimitive());
-                    break;
-                case STRING:
-                    resultType = JavaType.ARRAY_STRING;
-                    resultType.setPrimitive(componentType.isPrimitive());
-                    break;
-                case ENUM:
-                    resultType = JavaType.ARRAY_ENUM;
-                    resultType.setPrimitive(componentType.isPrimitive());
-                    break;
-                case MAP:
-                    resultType = JavaType.ARRAY_MAP;
-                    resultType.setPrimitive(componentType.isPrimitive());
-                    break;
-                case LIST:
-                    resultType = JavaType.ARRAY_LIST;
-                    resultType.setPrimitive(componentType.isPrimitive());
-                    break;
-                case OBJECT:
-                    resultType = JavaType.ARRAY;
-                    resultType.setPrimitive(componentType.isPrimitive());
-                    break;
-            }
-        } else {
-            resultType = JavaType.ARRAY_ARRAY;
-            resultType.setPrimitive(false);
-        }
-
-        if(resultType != null) {
-            return resultType;
-        } else {
-            return JavaType.UNKOWN;
-        }
-    }
-
-    public static class JavaArrayType {
-
-        Class<?> arrayType;
-
-        int dimension;
-
-        public JavaArrayType(Class<?> arrayType) {
-            this.arrayType = arrayType;
-            dimension = 0;
-            this.inspect();
-        }
-
-        public final void inspect() {
-            if(arrayType != null && arrayType.isArray()) {
-                Class<?> innerType = arrayType.getComponentType();
-                dimension = 1;
-                while(innerType.isArray() && (innerType = arrayType.getComponentType()) != null) {
-                    dimension++;
-                }
-            }
-        }
-
-        @Override
-        public String toString() {
-            return "Array " + arrayType.getSimpleName() + "[" + dimension + "]";
-        }
-    }
-}

File src/main/java/cc/plural/jsonij/reflect/ClassProperty.java

+/**
+ * Copyright (C) 2012 J.W.Marsden <jmarsden@plural.cc>
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package cc.plural.jsonij.reflect;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Objects;
+
+/**
+ *
+ * @author jmarsden@plural.cc
+ */
+public class ClassProperty {
+
+    private Class<?> klass;
+
+    private String propertyName;
+
+    private ClassPropertyAccessor accessor;
+
+    private ClassPropertyMutator mutator;
+
+    public ClassProperty() {
+    }
+
+    public ClassPropertyAccessor getAccessor() {
+        return accessor;
+    }
+
+    public void setAccessor(ClassPropertyAccessor accessor) {
+        this.accessor = accessor;
+    }
+
+    public Class<?> getKlass() {
+        return klass;
+    }
+
+    public void setKlass(Class<?> klass) {
+        this.klass = klass;
+    }
+
+    public ClassPropertyMutator getMutator() {
+        return mutator;
+    }
+
+    public void setMutator(ClassPropertyMutator mutator) {
+        this.mutator = mutator;
+    }
+
+    public String getPropertyName() {
+        return propertyName;
+    }
+
+    public void setPropertyName(String propertyName) {
+        this.propertyName = propertyName;
+    }
+
+    public void registerAccessor(Field field) {
+        if(accessor == null) {
+            accessor = new ClassPropertyAccessor();
+            accessor.field = field;
+            accessor.klass = field.getDeclaringClass();
+            accessor.type = field.getGenericType();
+        } else if(accessor.field == null) {
+            accessor.field = field;
+        }
+    }
+
+    public void registorMutator(Field field) {
+        if(mutator == null) {
+            mutator = new ClassPropertyMutator();
+            mutator.field = field;
+            mutator.klass = field.getDeclaringClass();
+            mutator.type = field.getGenericType();
+        } else if(mutator.field == null) {
+            mutator.field = field;
+        }
+    }
+
+    public void registerAccessor(Method method) {
+        if(accessor == null) {
+            accessor = new ClassPropertyAccessor();
+            accessor.method = method;
+            accessor.klass = method.getDeclaringClass();
+            accessor.type = method.getGenericReturnType();
+        } else if(accessor.method == null) {
+            accessor.method = method;
+        }
+    }
+
+    public void registorMutator(Method method) {
+        if(mutator == null) {
+            Type[] argumentTypes = method.getGenericParameterTypes();
+            if(argumentTypes.length == 1) {
+                mutator = new ClassPropertyMutator();
+                mutator.method = method;
+                mutator.klass = method.getDeclaringClass();
+
+                mutator.type = argumentTypes[0];
+            }
+        } else if(mutator.method == null) {
+            mutator.method = method;
+        }
+    }
+
+    public boolean isValid() {
+        return true;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if(obj == null) {
+            return false;
+        }
+        if(getClass() != obj.getClass()) {
+            return false;
+        }
+        final ClassProperty other = (ClassProperty) obj;
+        if(!Objects.equals(this.propertyName, other.propertyName)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 3;
+        hash = 67 * hash + Objects.hashCode(this.klass);
+        hash = 67 * hash + Objects.hashCode(this.propertyName);
+        return hash;
+    }
+
+    @Override
+    public String toString() {
+        return klass.getSimpleName() + "." + propertyName + "(" + mutator + "): " + accessor;
+    }
+
+    public static class ClassPropertyAccessor {
+
+        private Class<?> klass;
+
+        private Type type;
+
+        private Method method;
+
+        private Field field;
+
+        public Field getField() {
+            return field;
+        }
+
+        public void setField(Field field) {
+            this.field = field;
+        }
+
+        public Class<?> getKlass() {
+            return klass;
+        }
+
+        public void setKlass(Class<?> klass) {
+            this.klass = klass;
+        }
+
+        public Method getMethod() {
+            return method;
+        }
+
+        public void setMethod(Method method) {
+            this.method = method;
+        }
+
+        public Type getType() {
+            return type;
+        }
+
+        public void setType(Type type) {
+            this.type = type;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+
+            if(field != null) {
+                int modifiers = field.getModifiers();
+                builder.append(getModifierString(modifiers));
+                builder.append('f');
+            }
+
+            if(method != null) {
+                int modifiers = method.getModifiers();
+                builder.append(getModifierString(modifiers));
+                builder.append('m');
+            }
+            builder.append('[');
+            builder.append(getTypeString(type));
+            builder.append(']');
+            return builder.toString();
+        }
+
+        public boolean canAccess() {
+            throw new UnsupportedOperationException("Not yet implemented");
+        }
+
+        public boolean fieldType() {
+            throw new UnsupportedOperationException("Not yet implemented");
+        }
+
+        public boolean methodType() {
+            throw new UnsupportedOperationException("Not yet implemented");
+        }
+    }
+
+    public static class ClassPropertyMutator {
+
+        private Class<?> klass;
+
+        private Type type;
+
+        private Method method;
+
+        private Field field;
+
+        public Field getField() {
+            return field;
+        }
+
+        public void setField(Field field) {
+            this.field = field;
+        }
+
+        public Class<?> getKlass() {
+            return klass;
+        }
+
+        public void setKlass(Class<?> klass) {
+            this.klass = klass;
+        }
+
+        public Method getMethod() {
+            return method;
+        }
+
+        public void setMethod(Method method) {
+            this.method = method;
+        }
+
+        public Type getType() {
+            return type;
+        }
+
+        public void setType(Type type) {
+            this.type = type;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+
+            if(field != null) {
+                int modifiers = field.getModifiers();
+                builder.append(getModifierString(modifiers));
+                builder.append('f');
+            }
+
+            if(method != null) {
+                int modifiers = method.getModifiers();
+                builder.append(getModifierString(modifiers));
+                builder.append('m');
+            }
+            builder.append('[');
+            builder.append(getTypeString(type));
+            builder.append(']');
+            return builder.toString();
+        }
+    }
+
+    public static String getModifierString(int modifiers) {
+        String modifier = null;
+        if(Modifier.isPublic(modifiers)) {
+            modifier = "+";
+        } else if(Modifier.isPrivate(modifiers)) {
+            modifier = "-";
+        } else if(Modifier.isProtected(modifiers)) {
+            modifier = "#";
+        }
+        return modifier;
+    }
+
+    public static String getTypeString(Type genericType) {
+        StringBuilder builder = new StringBuilder();
+        if(genericType instanceof Class) {
+            Class<?> genericTypeClass = (Class<?>) genericType;
+            builder.append(genericTypeClass.getSimpleName());
+        } else if(genericType instanceof ParameterizedType) {
+            ParameterizedType genericParameterizedType = (ParameterizedType) genericType;
+            builder.append(getTypeString(genericParameterizedType.getRawType()));
+            Type[] innerTypes = genericParameterizedType.getActualTypeArguments();
+            builder.append('<');
+            if(innerTypes.length > 0) {
+                for(int i = 0; i < innerTypes.length - 1; i++) {
+                    builder.append(getTypeString(innerTypes[i])).append(',');
+                }
+                builder.append(getTypeString(innerTypes[innerTypes.length - 1]));
+            }
+            builder.append('>');
+        }
+        return builder.toString();
+    }
+}

File src/main/java/cc/plural/jsonij/reflect/Inspection.java

+/**
+ * Copyright (C) 2012 J.W.Marsden <jmarsden@plural.cc>
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package cc.plural.jsonij.reflect;
+
+import java.util.List;
+
+/**
+ *
+ * @author jmarsden@plural.cc
+ */
+public class Inspection {
+
+    private Class<?> klass;
+    private List<ClassProperty> properties; 
+    private boolean innerList;
+    private boolean innerMap;
+   
+    public Inspection() {
+        
+    }
+
+    public boolean hasInnerList() {
+        return innerList;
+    }
+    
+    public boolean isInnerList() {
+        return innerList;
+    }
+
+    public void setInnerList(boolean innerList) {
+        this.innerList = innerList;
+    }
+    
+    public boolean hasInnerMap() {
+        return innerMap;
+    }
+
+    public boolean isInnerMap() {
+        return innerMap;
+    }
+
+    public void setInnerMap(boolean innerMap) {
+        this.innerMap = innerMap;
+    }
+
+    public Class<?> getKlass() {
+        return klass;
+    }
+
+    public void setKlass(Class<?> klass) {
+        this.klass = klass;
+    }
+
+    public List<ClassProperty> getProperties() {
+        return properties;
+    }
+
+    public void setProperties(List<ClassProperty> properties) {
+        this.properties = properties;
+    }
+
+    @Override
+    public String toString() {
+        return "Inspection [" + klass  + " List:" + innerList + " Map:" + innerMap + " Properties:" + properties.size() + "]";
+    }
+}

File src/main/java/cc/plural/jsonij/reflect/InspectionException.java

+/**
+ * Copyright (C) 2012 J.W.Marsden <jmarsden@plural.cc>
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package cc.plural.jsonij.reflect;
+
+/**
+ *
+ * @author jmarsden@plural.cc
+ */
+public class InspectionException extends Exception {
+
+    public InspectionException(Throwable cause) {
+        super(cause);
+    }
+
+    public InspectionException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public InspectionException(String message) {
+        super(message);
+    }
+
+    public InspectionException() {
+    }
+
+}

File src/main/java/cc/plural/jsonij/reflect/InspectionFactory.java

+/**
+ * Copyright (C) 2012 J.W.Marsden <jmarsden@plural.cc>
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package cc.plural.jsonij.reflect;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ * @author jmarsden@plural.cc
+ */
+public class InspectionFactory {
+
+    public InspectionFilter filter;
+    
+    public static final String IS_PREFIX;
+
+    public static final String SET_PREFIX;
+
+    public static final String GET_PREFIX;
+    
+    static {
+        IS_PREFIX = "is";
+        SET_PREFIX = "set";
+        GET_PREFIX = "get";
+    }
+    
+    public InspectionFactory() {
+        filter = InspectionFilter.getDefaultFilters();
+    }
+
+    public Inspection inspect(Object object) {
+        return inspect(object.getClass());
+    }
+
+    public Inspection inspect(Class<?> klass) {
+        if(klass == null) {
+            throw new NullPointerException();
+        }
+        List<ClassProperty> classProperties = new ArrayList<ClassProperty>();
+        Class<?> currentClass = klass;
+        do {
+            if(filter.isFiltered(currentClass)) {
+                continue;
+            }
+            List<ClassProperty> currentClassProperties = inspectClassProperties(currentClass);
+            for(ClassProperty currentClassProperty: currentClassProperties) {
+                if(!classProperties.contains(currentClassProperty)) {
+                    classProperties.add(currentClassProperty);
+                } else {
+                    // TODO: Some kind of merge.
+                }
+            }
+        } while((currentClass = currentClass.getSuperclass()) != null);