wink-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ngalla...@apache.org
Subject svn commit: r1021933 [4/9] - in /incubator/wink/trunk: ./ wink-json4j/ wink-json4j/src/ wink-json4j/src/main/ wink-json4j/src/main/java/ wink-json4j/src/main/java/org/ wink-json4j/src/main/java/org/apache/ wink-json4j/src/main/java/org/apache/wink/ win...
Date Tue, 12 Oct 2010 21:30:32 GMT
Added: incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/compat/impl/ApacheJSONWriterDelegate.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/compat/impl/ApacheJSONWriterDelegate.java?rev=1021933&view=auto
==============================================================================
--- incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/compat/impl/ApacheJSONWriterDelegate.java (added)
+++ incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/compat/impl/ApacheJSONWriterDelegate.java Tue Oct 12 21:30:30 2010
@@ -0,0 +1,127 @@
+/*
+ * 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.wink.json4j.compat.impl;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.apache.wink.json4j.compat.JSONException;
+import org.apache.wink.json4j.compat.JSONWriter;
+
+/**
+ *
+ */
+public class ApacheJSONWriterDelegate implements JSONWriter {
+
+    protected org.apache.wink.json4j.JSONWriter delegate = null;
+
+    protected Writer writer = null;
+
+    public ApacheJSONWriterDelegate(Writer writer) {
+        this.delegate = new org.apache.wink.json4j.JSONWriter(writer);
+        this.writer = writer;
+    }
+
+    public JSONWriter object() throws IOException, IllegalStateException {
+        delegate.object();
+        return this;
+    }
+    public JSONWriter array() throws IOException, IllegalStateException {
+        delegate.array();
+        return this;
+    }
+
+    public JSONWriter endArray() throws IOException, IllegalStateException {
+        delegate.endArray();
+        return this;
+    }
+
+    public JSONWriter endObject() throws IOException, IllegalStateException {
+        delegate.endObject();
+        return this;
+    }
+
+    public JSONWriter key(String s) throws IOException, IllegalStateException {
+        delegate.key(s);
+        return this;
+    }
+
+    public JSONWriter value(boolean b) throws IOException, IllegalStateException {
+        delegate.value(b);
+        return this;
+    }
+
+    public JSONWriter value(double d) throws IOException, IllegalStateException {
+        delegate.value(d);
+        return this;
+    }
+
+    public JSONWriter value(long l) throws IOException, IllegalStateException {
+        delegate.value(l);
+        return this;
+    }
+
+    public JSONWriter value(short s) throws IOException, IllegalStateException {
+        delegate.value(s);
+        return this;
+    }
+
+    public JSONWriter value(Object obj) throws IOException, IllegalStateException, JSONException {
+        try{
+            if (obj == null) {
+                delegate.value((Object)null);
+            } else {
+                Class clazz = obj.getClass();
+                if (org.apache.wink.json4j.compat.impl.ApacheJSONObjectDelegate.class.isAssignableFrom(clazz)) {
+                    this.delegate.value(((org.apache.wink.json4j.compat.impl.ApacheJSONObjectDelegate)obj).delegate);
+                } else if (org.apache.wink.json4j.compat.impl.ApacheJSONArrayDelegate.class.isAssignableFrom(clazz)) {
+                    this.delegate.value(((org.apache.wink.json4j.compat.impl.ApacheJSONArrayDelegate)obj).delegate);
+                }else if (Number.class.isAssignableFrom(clazz)) {
+                    this.delegate.value(obj);
+                } else if (Boolean.class.isAssignableFrom(clazz)) {
+                    this.delegate.value(obj);
+                } else if (String.class.isAssignableFrom(clazz)) {
+                    this.delegate.value(obj);
+                }
+            }
+            return this;
+        } catch (Exception ex) {
+            if(ex instanceof IOException){
+                throw (IOException)ex;
+            } else if (ex instanceof IllegalStateException) {
+                throw (IllegalStateException)ex;
+            } else {
+                JSONException jex = new JSONException(ex.getMessage());
+                jex.initCause(ex);
+                throw jex;
+            }
+        }
+    }
+
+    public void close() throws IOException, IllegalStateException {
+        delegate.close();
+    }
+
+    public JSONWriter flush() throws IOException {
+        delegate.flush();
+        return this;
+    }
+
+}

Added: incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/BeanSerializer.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/BeanSerializer.java?rev=1021933&view=auto
==============================================================================
--- incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/BeanSerializer.java (added)
+++ incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/BeanSerializer.java Tue Oct 12 21:30:30 2010
@@ -0,0 +1,583 @@
+/*
+ * 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.wink.json4j.internal;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Iterator;
+import java.util.Collection;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.HashMap;
+import java.lang.reflect.Method;
+import java.lang.NoSuchMethodException;
+
+import org.apache.wink.json4j.JSONArray;
+import org.apache.wink.json4j.JSONArtifact;
+import org.apache.wink.json4j.JSONException;
+import org.apache.wink.json4j.JSONObject;
+
+/**
+ * Private class to introspect a JavaBean and convert it to its respective JSON type.
+ */
+public class BeanSerializer {
+
+    /** 
+     * This method inspects a bean and converts it to its corrisponding JSON. 
+     * This function expects non-basic types (no String, Number, etc).
+     * @param obj The Object to inspect.
+     * @param includeSuperclass Boolean indicating if superclass properties should be included in the output JSON.                       
+     * @return An instance of the JSONArtifact that best represents the data in this JavaBean
+     * @throws IllegalArgumentException Thrown if input type is a String, Number, Boolean, etc.
+     * @throws JSONException Thrown if a JSON conversion error occurs.
+     */
+    public static JSONArtifact toJson(Object obj, boolean includeSuperclass) throws IllegalArgumentException, JSONException {
+        JSONArtifact ja = null;
+
+        if (obj != null) {
+            Class clazz = obj.getClass();
+            if (String.class  == clazz) {
+                throw new IllegalArgumentException("Class was String type, not a Javabean.");
+            } else if (Boolean.class == clazz) {
+                throw new IllegalArgumentException("Class was Boolean type, not a Javabean.");
+            } else if (Number.class.isAssignableFrom(clazz)) {
+                throw new IllegalArgumentException("Class was Number type, not a Javabean.");
+            } else if (JSONObject.class.isAssignableFrom(clazz)) {
+                ja = (JSONObject)obj;
+            } else if (JSONArray.class.isAssignableFrom(clazz)) {
+                ja = (JSONArray)obj;
+            } else if (Map.class.isAssignableFrom(clazz)) {
+                ja = new JSONObject((Map)obj);
+            } else if (Collection.class.isAssignableFrom(clazz)) {
+                ja = new JSONArray((Collection)obj);
+            } else {
+                //TODO:  Bean introspection time.
+                ja = introspectBean(obj,includeSuperclass, new ArrayList());
+            }
+        }
+        return ja;
+    }
+
+    /**
+     * Internal method for introspecting a bean and converting it to a JSONAble type.
+     * @param obj The Object to inspect.
+     * @param includeSuperclass Boolean indicating if superclass properties should be included in the output JSON.                       
+     * @param parsedObjects An array list of objects traversed to try and avoid loops in graphs
+     * @throws JSONException Thrown if a JSON conversion error occurs.
+     */
+    private static JSONArtifact introspectBean(Object obj, boolean includeSuperclass, ArrayList parsedObjects) throws JSONException {
+        JSONObject ja = null;
+        boolean found = false; 
+        for (int i = 0; i < parsedObjects.size(); i++) {
+            // Check and try to avoid graphs by parsing the same 
+            // object multiple times, which may indicate a cycle.
+            Object possibleObj = parsedObjects.get(i);
+            if (possibleObj != null && obj == possibleObj) {
+                found = true;
+                break;
+            }
+        }
+
+        if (!found) {
+            parsedObjects.add(obj);
+            ja = new JSONObject();
+
+            Class clazz = obj.getClass();
+
+            ja.put("_type", "JavaClass");
+            ja.put("_classname", clazz.getName());
+
+            // Fetch all the methods, based on including superclass or not.
+            Method[] methods = null;
+            if (includeSuperclass) {
+                methods = clazz.getMethods();
+            } else {
+                methods = clazz.getDeclaredMethods();
+            }
+
+            if (methods != null && methods.length > 0) {
+                for (int i = 0; i < methods.length; i++) {
+                    Method m = methods[i];
+                    // Include all superclass methods if requested, 
+                    // or only those that are part of the actual declaring class.
+                    String mName = m.getName();
+                    Class[] types = m.getParameterTypes();
+
+                    // Getter, so we can assume this accesses a field.
+                    if (mName.startsWith("get") && mName.length() > 3 && (types == null || types.length == 0)) {
+                        String attr = mName.substring(3, mName.length());
+                        attr = Character.toLowerCase(attr.charAt(0)) + attr.substring(1, attr.length());
+                        try {
+                            Object val = m.invoke(obj, null);
+                            if (val == null) {
+                                ja.put(attr, (Object)null);
+                            } else {
+                                Class vClazz = val.getClass();
+                                if (String.class == vClazz) {
+                                    ja.put(attr, val);
+                                } else if (Boolean.class == vClazz) {
+                                    ja.put(attr, val);
+                                } else if (Class.class == vClazz) {
+                                    ja.put(attr, ((Class)val).getName());
+                                } else if (Number.class.isAssignableFrom(vClazz)) {
+                                    ja.put(attr, val);
+                                } else if (JSONObject.class.isAssignableFrom(vClazz)) {
+                                    ja.put(attr, val);
+                                } else if (JSONArray.class.isAssignableFrom(vClazz)) {
+                                    ja.put(attr, val);
+                                } else if (Map.class.isAssignableFrom(vClazz)) {
+                                    ja.put(attr, new JSONObject((Map)val));
+                                } else if (Collection.class.isAssignableFrom(vClazz)) {
+                                    ja.put(attr, new JSONArray((Collection)obj));
+                                } else {
+                                    if (val != obj) {
+                                        // Try to avoid processing references to itself.
+                                        ja.put(attr, introspectBean(val, includeSuperclass, parsedObjects));
+                                    }
+                                }
+                            }
+                        } catch (Exception ex) {
+                            ja.put(attr, (Object)null);
+                        }
+                    }
+                }
+            }
+        }
+        return ja;
+    }
+
+    /**
+     * Method to try to convert a JSONObject back into its class representation.
+     * @param jo The JSONObject to try to convert back to a class.
+     * @throws NullPointerException Thrown if jo is null.
+     * @throws JSONException Thrown if the JSON cannot be converted to a java class.
+     * @return An instance of a Java Object that corrisponds to the type in _classname
+     */
+    public static Object fromJson(JSONObject jo) throws NullPointerException, JSONException {
+        Object obj = null;
+        if (jo == null) {
+            throw new NullPointerException("Input JSONObject cannot be null");
+        } else {
+            if (jo.get("_classname") != null && "JavaClass".equals(jo.get("_type"))) {
+                // Okay, we can try to process this back to a class.
+                try {
+                    String cName = (String)jo.get("_classname");
+                    Class clazz = Class.forName(cName);
+                    if (clazz != null) {
+                        Method[] methods = clazz.getMethods();
+
+                        obj = clazz.newInstance();
+                        Iterator keys = jo.keys();
+                        if (keys != null) {
+                            while (keys.hasNext()) {
+                                String key = (String)keys.next();
+                                // Ignore our specially named attributes.
+                                if(key != null && !key.equals("_classname") && !key.equals("_type")){
+                                    Method m = null;
+
+                                    String setter = "set" + Character.toUpperCase(key.charAt(0)) + key.substring(1, key.length());
+                                    Object val = jo.get(key);
+
+                                    if (val != null) {
+                                        Class vClazz = val.getClass();
+
+                                        // Try to locate the best matching method.
+                                        if (String.class == vClazz) {
+                                            // Handle locating a String method.
+                                            for (int i = 0; i < methods.length; i++) {
+                                                Method tM = methods[i];
+                                                if(tM.getName().equals(setter)){
+                                                    Class[] mParms = tM.getParameterTypes();
+                                                    if (mParms != null && mParms.length == 1) {
+                                                        // Possible method, lets check the type.
+                                                        Class c = mParms[0];
+                                                        if (c == vClazz) {
+                                                            // We have a String match, stop here.
+                                                            m = tM;
+                                                            break;
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        } else if (Boolean.class == vClazz) {
+                                            // Handle locating a boolean method.
+                                            for (int i = 0; i < methods.length; i++) {
+                                                Method tM = methods[i];
+                                                if(tM.getName().equals(setter)){
+                                                    Class[] mParms = tM.getParameterTypes();
+                                                    if (mParms != null && mParms.length == 1) {
+                                                        // Possible method, lets check the type.
+                                                        Class c = mParms[0];
+                                                        if (c == vClazz || Boolean.TYPE == c) {
+                                                            // We have a boolean match, stop here.
+                                                            m = tM;
+                                                            break;
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        } else if (Number.class.isAssignableFrom(vClazz)) {
+                                            // Handle locating the best-matching number method.
+                                            if(Double.class.isAssignableFrom(vClazz)){
+                                                for (int i = 0; i < methods.length; i++) {
+                                                    Method tM = methods[i];
+                                                    if(tM.getName().equals(setter)){
+                                                        Class[] mParms = tM.getParameterTypes();
+                                                        if (mParms != null && mParms.length == 1) {
+                                                            // Possible method, lets check the type.
+                                                            Class c = mParms[0];
+                                                            if (c == Double.class || Double.TYPE == c) {
+                                                                // We have a double match, stop here.
+                                                                m = tM;
+                                                                break;
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                                if(m == null){
+                                                    // Look for a float assigner and if found, set the value to a Float
+                                                    // type.
+                                                    for (int i = 0; i < methods.length; i++) {
+                                                        Method tM = methods[i];
+                                                        if(tM.getName().equals(setter)){
+                                                            Class[] mParms = tM.getParameterTypes();
+                                                            if (mParms != null && mParms.length == 1) {
+                                                                // Possible method, lets check the type.
+                                                                Class c = mParms[0];
+                                                                if (c == Float.class || Float.TYPE == c) {
+                                                                    // We have a Float match, stop here.
+                                                                    m = tM;
+                                                                    val = new Float(((Number)val).floatValue());
+                                                                    break;
+                                                                }
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                            } else if (Float.class.isAssignableFrom(vClazz)) {
+                                                for (int i = 0; i < methods.length; i++) {
+                                                    Method tM = methods[i];
+                                                    if(tM.getName().equals(setter)){
+                                                        Class[] mParms = tM.getParameterTypes();
+                                                        if (mParms != null && mParms.length == 1) {
+                                                            // Possible method, lets check the type.
+                                                            Class c = mParms[0];
+                                                            if (c == Float.class || Float.TYPE == c) {
+                                                                // We have a Float match, stop here.
+                                                                m = tM;
+                                                                break;
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                                if(m == null){
+                                                    // Look for a double assigner and if found, set the value to a Float
+                                                    // type.
+                                                    for (int i = 0; i < methods.length; i++) {
+                                                        Method tM = methods[i];
+                                                        if(tM.getName().equals(setter)){
+                                                            Class[] mParms = tM.getParameterTypes();
+                                                            if (mParms != null && mParms.length == 1) {
+                                                                // Possible method, lets check the type.
+                                                                Class c = mParms[0];
+                                                                if (c == Double.class || Double.TYPE == c) {
+                                                                    // We have a Double match, stop here.
+                                                                    m = tM;
+                                                                    val = new Double(((Number)val).doubleValue());
+                                                                    break;
+                                                                }
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                            } else if (Long.class.isAssignableFrom(vClazz)){
+                                                for (int i = 0; i < methods.length; i++) {
+                                                    Method tM = methods[i];
+                                                    if(tM.getName().equals(setter)){
+                                                        Class[] mParms = tM.getParameterTypes();
+                                                        if (mParms != null && mParms.length == 1) {
+                                                            // Possible method, lets check the type.
+                                                            Class c = mParms[0];
+                                                            if (c == Long.class || Long.TYPE == c) {
+                                                                // We have a Long match, stop here.
+                                                                m = tM;
+                                                                break;
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                                if(m == null){
+                                                    // Look for a integer assigner and if found, set the value to a int
+                                                    // type.
+                                                    for (int i = 0; i < methods.length; i++) {
+                                                        Method tM = methods[i];
+                                                        if(tM.getName().equals(setter)){
+                                                            Class[] mParms = tM.getParameterTypes();
+                                                            if (mParms != null && mParms.length == 1) {
+                                                                // Possible method, lets check the type.
+                                                                Class c = mParms[0];
+                                                                if (c == Integer.class || Integer.TYPE == c) {
+                                                                    // We have an int match, stop here.
+                                                                    m = tM;
+                                                                    val = new Integer(((Number)val).intValue());
+                                                                    break;
+                                                                }
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                                if(m == null){
+                                                    // Look for a short assigner and if found, set the value to a int
+                                                    // type.
+                                                    for (int i = 0; i < methods.length; i++) {
+                                                        Method tM = methods[i];
+                                                        if(tM.getName().equals(setter)){
+                                                            Class[] mParms = tM.getParameterTypes();
+                                                            if (mParms != null && mParms.length == 1) {
+                                                                // Possible method, lets check the type.
+                                                                Class c = mParms[0];
+                                                                if (c == Short.class || Short.TYPE == c) {
+                                                                    // We have a short match, stop here.
+                                                                    m = tM;
+                                                                    val = new Short(((Number)val).shortValue());
+                                                                    break;
+                                                                }
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                            } else if (Integer.class.isAssignableFrom(vClazz)){
+                                                for (int i = 0; i < methods.length; i++) {
+                                                    Method tM = methods[i];
+                                                    if(tM.getName().equals(setter)){
+                                                        Class[] mParms = tM.getParameterTypes();
+                                                        if (mParms != null && mParms.length == 1) {
+                                                            // Possible method, lets check the type.
+                                                            Class c = mParms[0];
+                                                            if (c == Integer.class || Integer.TYPE == c) {
+                                                                // We have an int match, stop here.
+                                                                m = tM;
+                                                                break;
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                                if(m == null){
+                                                    // Look for a Long assigner and if found, set the value to a int
+                                                    // type.
+                                                    for (int i = 0; i < methods.length; i++) {
+                                                        Method tM = methods[i];
+                                                        if(tM.getName().equals(setter)){
+                                                            Class[] mParms = tM.getParameterTypes();
+                                                            if (mParms != null && mParms.length == 1) {
+                                                                // Possible method, lets check the type.
+                                                                Class c = mParms[0];
+                                                                if (c == Long.class || Long.TYPE == c) {
+                                                                    // We have a long match, stop here.
+                                                                    m = tM;
+                                                                    val = new Long(((Number)val).longValue());
+                                                                    break;
+                                                                }
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                                if(m == null){
+                                                    // Look for a short assigner and if found, set the value to a int
+                                                    // type.
+                                                    for (int i = 0; i < methods.length; i++) {
+                                                        Method tM = methods[i];
+                                                        if(tM.getName().equals(setter)){
+                                                            Class[] mParms = tM.getParameterTypes();
+                                                            if (mParms != null && mParms.length == 1) {
+                                                                // Possible method, lets check the type.
+                                                                Class c = mParms[0];
+                                                                if (c == Short.class || Short.TYPE == c) {
+                                                                    // We have a short match, stop here.
+                                                                    m = tM;
+                                                                    val = new Short(((Number)val).shortValue());
+                                                                    break;
+                                                                }
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                            } else if (Short.class.isAssignableFrom(vClazz)){
+                                                for (int i = 0; i < methods.length; i++) {
+                                                    Method tM = methods[i];
+                                                    if(tM.getName().equals(setter)){
+                                                        Class[] mParms = tM.getParameterTypes();
+                                                        if (mParms != null && mParms.length == 1) {
+                                                            // Possible method, lets check the type.
+                                                            Class c = mParms[0];
+                                                            if (c == Short.class || Short.TYPE == c) {
+                                                                // We have a short match, stop here.
+                                                                m = tM;
+                                                                break;
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                                if(m == null){
+                                                    // Look for a integer assigner and if found, set the value to a int
+                                                    // type.
+                                                    for (int i = 0; i < methods.length; i++) {
+                                                        Method tM = methods[i];
+                                                        if(tM.getName().equals(setter)){
+                                                            Class[] mParms = tM.getParameterTypes();
+                                                            if (mParms != null && mParms.length == 1) {
+                                                                // Possible method, lets check the type.
+                                                                Class c = mParms[0];
+                                                                if (c == Integer.class || Integer.TYPE == c) {
+                                                                    // We have a int match, stop here.
+                                                                    m = tM;
+                                                                    val = new Integer(((Number)val).intValue());
+                                                                    break;
+                                                                }
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                                if(m == null){
+                                                    // Look for a Long assigner and if found, set the value to a int
+                                                    // type.
+                                                    for (int i = 0; i < methods.length; i++) {
+                                                        Method tM = methods[i];
+                                                        if(tM.getName().equals(setter)){
+                                                            Class[] mParms = tM.getParameterTypes();
+                                                            if (mParms != null && mParms.length == 1) {
+                                                                // Possible method, lets check the type.
+                                                                Class c = mParms[0];
+                                                                if (c == Long.class || Long.TYPE == c) {
+                                                                    // We have a long match, stop here.
+                                                                    m = tM;
+                                                                    val = new Long(((Number)val).longValue());
+                                                                    break;
+                                                                }
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        } else if (JSONArray.class.isAssignableFrom(vClazz)) {
+                                            // Handle determining a collection type to set, which means 
+                                            // we need to find a Collection setter.
+                                            for (int i = 0; i < methods.length; i++) {
+                                                Method tM = methods[i];
+                                                if(tM.getName().equals(setter)){
+                                                    Class[] mParms = tM.getParameterTypes();
+                                                    if (mParms != null && mParms.length == 1) {
+                                                        // Possible method, lets check the type.
+                                                        Class c = mParms[0];
+                                                        if (List.class.isAssignableFrom(c)) {
+                                                            // We have a Collections match, so we'll use it.
+                                                            m = tM;
+                                                            if(c != JSONArray.class){
+                                                                // Convert it.  Whee.
+                                                                List list = (List)c.newInstance();
+
+                                                                JSONArray array = (JSONArray)val;
+                                                                for (int j = 0; j < array.length(); j++) {
+                                                                    // Convert each type as needed.
+                                                                    Object aVal = array.get(j);
+                                                                    if(aVal != null){
+                                                                        Class aVClazz = aVal.getClass();
+                                                                        if(Number.class.isAssignableFrom(aVClazz) ||
+                                                                            Boolean.class.isAssignableFrom(aVClazz) ||
+                                                                            String.class.isAssignableFrom(aVClazz)) {
+                                                                            list.add(aVal);
+                                                                        } else if (JSONObject.class.isAssignableFrom(aVClazz)) {
+                                                                            list.add(fromJson((JSONObject)aVal));
+                                                                        } else if (JSONObject.class.isAssignableFrom(aVClazz)) {
+                                                                            // Not sure what to do here!
+                                                                        }
+                                                                    } else {
+                                                                        list.add(null);
+                                                                    }
+                                                                }
+                                                                val = list;
+                                                            }
+                                                            break;
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        } else if (JSONObject.class.isAssignableFrom(vClazz)) {
+                                            // Handle determining a map type to set, if there is one.
+                                            JSONObject jObj = (JSONObject)val;
+                                            Class vC = val.getClass();
+                                            if(jObj.get("_classname") != null && "JavaClass".equals(jObj.get("_type"))){
+                                                val = fromJson(jObj);
+                                                vC = val.getClass();
+                                            }
+
+                                            // Handle locating a boolean method.
+                                            for (int i = 0; i < methods.length; i++) {
+                                                Method tM = methods[i];
+                                                if(tM.getName().equals(setter)){
+                                                    Class[] mParms = tM.getParameterTypes();
+                                                    if (mParms != null && mParms.length == 1) {
+                                                        // Possible method, lets check the type.
+                                                        Class c = mParms[0];
+                                                        if (c.isAssignableFrom(vC)) {
+                                                            // We have setter for the conversion.
+                                                            m = tM;
+                                                            break;
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        } else {
+                                            // Dunno?
+                                            throw new JSONException("Unknown type: [" + vClazz.getName() + "]");
+                                        }
+                                    } else {
+                                        try {
+                                            m = clazz.getMethod(setter, null);
+                                        } catch (NoSuchMethodException nmex){
+                                            // Ignore, no setter.
+                                        }
+                                    }
+                                    if (m != null) {
+                                        m.invoke(obj, new Object[] { val });
+                                    }
+                                }
+                            }
+                        }
+                    } else {
+                        throw new JSONException("Could not locate class: [" + cName + "]");
+                    }
+                } catch (Exception ex) {
+                    if (ex instanceof JSONException) {
+                        throw (JSONException)ex;
+                    } else {
+                        JSONException jex = new JSONException("Error in converting JSON to Java Class");
+                        jex.initCause(ex);
+                        throw jex;
+                    }
+                }
+            } else {
+                throw new JSONException("Provided JSONObject does not contain attributes '_classname' or '_type'");
+            }
+        }
+        return obj;
+    }
+}
+

Added: incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/Null.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/Null.java?rev=1021933&view=auto
==============================================================================
--- incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/Null.java (added)
+++ incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/Null.java Tue Oct 12 21:30:30 2010
@@ -0,0 +1,57 @@
+/*
+ * 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.wink.json4j.internal;
+
+import org.apache.wink.json4j.JSONString;
+
+/**
+ * An simple class provided for API compatibility to other JSON models that 'represents' 
+ * 'null' in an actual object.
+ */
+public class Null implements JSONString {
+
+    /**
+     * Equals function that returns true for comparisons to null.
+     */
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * toString method that just returns 'null' as the string.
+     */
+    public String toString() {
+        return "null";
+
+    }
+
+    /**
+     * Method to return a JSON compliant representation of this object.
+     * @return a JSON formatted string.
+     */
+    public String toJSONString() {
+        return this.toString();
+    }
+
+}

Added: incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/Parser.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/Parser.java?rev=1021933&view=auto
==============================================================================
--- incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/Parser.java (added)
+++ incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/Parser.java Tue Oct 12 21:30:30 2010
@@ -0,0 +1,345 @@
+/*
+ * 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.wink.json4j.internal;
+
+import java.io.IOException;
+import java.io.Reader;
+
+import org.apache.wink.json4j.JSONArray;
+import org.apache.wink.json4j.JSONArtifact;
+import org.apache.wink.json4j.JSONException;
+import org.apache.wink.json4j.JSONObject;
+import org.apache.wink.json4j.OrderedJSONObject;
+
+/**
+ * Private parser class which handles doing the parsing of the JSON string into tokens.
+ */
+public class Parser {
+
+    private Tokenizer tokenizer;
+    private Token     lastToken;
+
+    private JSONArtifact jArtifact;
+
+    private boolean firstArtifact = false;
+
+    /**
+     * Contructor
+     * @param reader The Reader to use when reading in the JSON stream/string.
+     *
+     * @throws JSONException Thrown if an error occurs in tokenizing the JSON string.
+     */
+    public Parser(Reader reader) throws JSONException {
+        super();     
+        try {
+            this.tokenizer = new Tokenizer(reader, false);
+        } catch (IOException iox) {
+            JSONException jex = new JSONException("Error occurred during input read.");
+            jex.initCause(iox);
+            throw jex;
+        }
+    }
+
+    /**
+     * Contructor
+     * @param reader The Reader to use when reading in the JSON stream/string.
+     * @param strict Boolean indicating if the parser should parse in strict mode, meaning unqoted strings and comments are not allowed.
+     *
+     * @throws JSONException Thrown if an error occurs in tokenizing the JSON string.
+     */
+    public Parser(Reader reader, boolean strict) throws JSONException {
+        super();     
+        try {
+            this.tokenizer = new Tokenizer(reader, strict);
+        } catch (IOException iox) {
+            JSONException jex = new JSONException("Error occurred during input read.");
+            jex.initCause(iox);
+            throw jex;
+        }
+    }
+
+    /**
+     * Method to initiate the parse of the toplevel JSON object, which will in turn parse all child JSON objects contained within.
+     * Same as calling parse(false);
+     * 
+     * @throws JSONException Thrown if an IO error occurd during parse of the JSON object(s).
+     */
+    public JSONObject parse() throws JSONException {
+        return parse(false, (JSONObject)null);
+    }
+
+    /**
+     * Method to initiate the parse of the toplevel JSON object, which will in turn parse all child JSON objects contained within.
+     * Same as calling parse(false);
+     * 
+     * @throws JSONException Thrown if an IO error occurd during parse of the JSON object(s).
+     */
+    public JSONObject parse(JSONObject jObj) throws JSONException {
+        return parse(false, jObj);
+    }
+
+    /**
+     * Method to initiate the parse of the toplevel JSON object, which will in turn parse all child JSON objects contained within.
+     * @param ordered Flag to denote if the parse should contruct a JSON object which maintains serialization order of the attributes.
+     * 
+     * @throws JSONException Thrown if an IO error occurd during parse of the JSON object(s).
+     */
+    public JSONObject parse(boolean ordered) throws JSONException {
+        try {
+            lastToken = tokenizer.next();
+        } catch (IOException iox) {
+            JSONException jex = new JSONException("Error occurred during input read.");
+            jex.initCause(iox);
+            throw jex;
+        }
+        return parseObject(ordered, null);
+    }
+
+    /**
+     * Method to initiate the parse of the toplevel JSON object, which will in turn parse all child JSON objects contained within.
+     * @param ordered Flag to denote if the parse should contruct a JSON object which maintains serialization order of the attributes.
+     * @param jObj The JSONObjetc to fill out from the parsing.  If null, create a new one.
+     * 
+     * @throws JSONException Thrown if an IO error occurd during parse of the JSON object(s).
+     */
+    public JSONObject parse(boolean ordered, JSONObject jObj) throws JSONException {
+        try {
+            lastToken = tokenizer.next();
+        } catch (IOException iox) {
+            JSONException jex = new JSONException("Error occurred during input read.");
+            jex.initCause(iox);
+            throw jex;
+        }
+        return parseObject(ordered, jObj);
+    }
+
+    /**
+     * Method to initiate the parse of the toplevel JSON object, which will in turn parse all child JSON objects contained within.
+     * @param jObj The JSONArray to fill out from the parsing.  If null, create a new one.
+     * 
+     * @throws JSONException Thrown if an IO error occurd during parse of the JSON object(s).
+     */
+    public JSONArray parse(JSONArray jObj) throws JSONException {
+        return parse(false, jObj);
+    }
+
+    /**
+     * Method to initiate the parse of the toplevel JSON object, which will in turn parse all child JSON objects contained within.
+     * @param ordered Flag to denote if the parse should contruct for all JSON objects encounted, a JSON object which maintains serialization order of the attributes.
+     * @param jObj The JSONArray to fill out from the parsing.  If null, create a new one.
+     * 
+     * @throws JSONException Thrown if an IO error occurd during parse of the JSON object(s).
+     */
+    public JSONArray parse(boolean ordered, JSONArray jObj) throws JSONException {
+        try {
+            lastToken = tokenizer.next();
+        } catch (IOException iox) {
+            JSONException jex = new JSONException("Error occurred during input read.");
+            jex.initCause(iox);
+            throw jex;
+        }
+        return parseArray(ordered, jObj);
+    }
+
+
+    /**
+     * Method to parse a JSON object out of the current JSON string position.
+     * @return JSONObject Returns the parsed out JSON object.
+     *
+     * @throws JSONException Thrown if an IO error occurs during parse, such as a malformed JSON object.
+     */
+    public JSONObject parseObject() throws JSONException {
+        return parseObject(false, null);
+    }
+
+    /**
+     * Method to parse a JSON object out of the current JSON string position.
+     * @param ordered Flag to denote if the parse should contruct a JSON object which maintains serialization order of the attributes.     
+     * @return JSONObject Returns the parsed out JSON object.
+     *
+     * @throws JSONException Thrown if an IO error occurs during parse, such as a malformed JSON object.
+     */
+    public JSONObject parseObject(boolean ordered, JSONObject rootObject) throws JSONException {
+
+        try {
+            JSONObject result = null;
+            if (rootObject != null) {
+                result = rootObject;
+            } else {
+                if (!ordered) {
+                    result = new JSONObject();
+                } else {
+                    result = new OrderedJSONObject();
+                }
+            }
+
+            if (lastToken != Token.TokenBraceL) throw new JSONException("Expecting '{' " + tokenizer.onLineCol() + " instead, obtained token: '" + lastToken + "'");
+            lastToken = tokenizer.next();
+
+            while (true) {
+                if (lastToken == Token.TokenEOF) throw new JSONException("Unterminated object " + tokenizer.onLineCol());
+
+                if (lastToken == Token.TokenBraceR) {
+                    lastToken = tokenizer.next();
+                    break;
+                }
+
+                if (!lastToken.isString()) throw new JSONException("Expecting string key " + tokenizer.onLineCol());
+                String key = lastToken.getString();
+
+                lastToken = tokenizer.next();
+                if (lastToken != Token.TokenColon) throw new JSONException("Expecting colon " + tokenizer.onLineCol());
+
+                lastToken = tokenizer.next();
+                Object val = parseValue(ordered);
+
+                result.put(key, val);
+
+                if (lastToken == Token.TokenComma) {
+                    lastToken = tokenizer.next();
+                }
+
+                else if (lastToken != Token.TokenBraceR) {
+                    throw new JSONException("expecting either ',' or '}' " + tokenizer.onLineCol());
+                }
+            }
+            return result;
+        } catch (IOException iox) {
+            JSONException jex = new JSONException("Error occurred during object input read.");
+            jex.initCause(iox);
+            throw jex;
+        }
+    }
+
+    /**
+     * Method to parse out a JSON array from a JSON string
+     * Same as calling parseArray(false, null)
+     * 
+     * @throws JSONException Thrown if a parse error occurs, such as a malformed JSON array.
+     */
+    public JSONArray parseArray() throws JSONException {
+        return parseArray(false, null);
+    }
+    /**
+     * Method to parse out a JSON array from a JSON string
+     * @param ordered Flag to denote if the parse should contruct JSON objects which maintain serialization order of the attributes for all JSONOjects in the array.     
+     * *param array An array instance to populate instead of creating a new one.
+     * 
+     * @throws JSONException Thrown if a parse error occurs, such as a malformed JSON array.
+     */
+    public JSONArray parseArray(boolean ordered, JSONArray array) throws JSONException {
+        JSONArray result = null;
+        if(array != null){
+            result = array;
+        } else {
+            result = new JSONArray();
+        }
+
+        try {
+            if (lastToken != Token.TokenBrackL) throw new JSONException("Expecting '[' " + tokenizer.onLineCol());
+            lastToken = tokenizer.next();
+            while (true) {
+                if (lastToken == Token.TokenEOF) throw new JSONException("Unterminated array " + tokenizer.onLineCol());
+
+                /**
+                 * End of the array.
+                 */
+                if (lastToken == Token.TokenBrackR) {
+                    lastToken = tokenizer.next();
+                    break;
+                }
+
+                Object val = parseValue(ordered);
+                result.add(val);
+
+                if (lastToken == Token.TokenComma) {
+                    lastToken = tokenizer.next();
+                } else if (lastToken != Token.TokenBrackR) {
+                    throw new JSONException("expecting either ',' or ']' " + tokenizer.onLineCol());
+                }
+            }
+        } catch (IOException iox) {
+            JSONException jex = new JSONException("Error occurred during array input read.");
+            jex.initCause(iox);
+            throw jex;
+        }
+        return result;
+    }
+
+    /**
+     * Method to parse the current JSON property value from the last token. 
+     * @return The java object type that represents the JSON value.
+     *
+     * @throws JSONException Thrown if an IO error (read incomplete token) occurs.
+     */
+    public Object parseValue() throws JSONException {
+        return parseValue(false);
+    }
+
+    /**
+     * Method to parse the current JSON property value from the last token. 
+     * @return The java object type that represents the JSON value.
+     * @param ordered Flag to denote if the parse should contruct JSON objects and arrays which maintain serialization order of the attributes.     
+     *
+     * @throws JSONException Thrown if an IO error (read incomplete token) occurs.
+     */
+    public Object parseValue(boolean ordered) throws JSONException {
+        if (lastToken == Token.TokenEOF) throw new JSONException("Expecting property value " + tokenizer.onLineCol());
+
+        try {
+            if (lastToken.isNumber()) {
+                Object result = lastToken.getNumber();
+                lastToken = tokenizer.next();
+                return result;
+            }
+
+            if (lastToken.isString()) {
+                Object result = lastToken.getString();
+                lastToken = tokenizer.next();
+                return result;
+            }
+
+            if (lastToken == Token.TokenFalse) {
+                lastToken = tokenizer.next();
+                return Boolean.FALSE;
+            }
+
+            if (lastToken == Token.TokenTrue) {
+                lastToken = tokenizer.next();
+                return Boolean.TRUE;
+            }
+
+            if (lastToken == Token.TokenNull) {
+                lastToken = tokenizer.next();
+                return null;
+            }
+
+            if (lastToken == Token.TokenBrackL) return parseArray(ordered, null);
+            if (lastToken == Token.TokenBraceL) return parseObject(ordered, null);
+
+        } catch (IOException iox) {
+            JSONException jex = new JSONException("Error occurred during value input read.");
+            jex.initCause(iox);
+            throw jex;
+        }
+        throw new JSONException("Invalid token " + tokenizer.onLineCol());
+    }
+
+}

Added: incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/Serializer.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/Serializer.java?rev=1021933&view=auto
==============================================================================
--- incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/Serializer.java (added)
+++ incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/Serializer.java Tue Oct 12 21:30:30 2010
@@ -0,0 +1,328 @@
+/*
+ * 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.wink.json4j.internal;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.wink.json4j.JSONArray;
+import org.apache.wink.json4j.JSONException;
+import org.apache.wink.json4j.JSONObject;
+import org.apache.wink.json4j.JSONString;
+import org.apache.wink.json4j.OrderedJSONObject;
+
+/**
+ * Class to handle serialization of a JSON object to a JSON string.
+ */
+public class Serializer {
+
+    /**
+     * The writer to use when writing this JSON object.
+     */
+    private Writer writer;
+
+    /**
+     * Create a serializer on the specified output stream writer.
+     */
+    public Serializer(Writer writer) {
+        super();
+
+        this.writer = writer;
+    }
+
+    /**
+     * Method to flush the current writer.
+     * @throws IOException Thrown if an error occurs during writer flush.
+     */
+    public void flush() throws IOException {
+        writer.flush();
+    }
+
+    /**
+     * Method to close the current writer.
+     * @throws IOException Thrown if an error occurs during writer close.
+     */
+    public void close() throws IOException {
+        writer.close();
+    }
+
+    /**
+     * Method to write a raw string to the writer.
+     * @param s The String to write.
+     * @throws IOException Thrown if an error occurs during write.
+     */
+    public Serializer writeRawString(String s) throws IOException {
+        writer.write(s);
+
+        return this;
+    }
+
+    /**
+     * Method to write the text string 'null' to the output stream (null JSON object).
+     * @throws IOException Thrown if an error occurs during write.
+     */
+    public Serializer writeNull() throws IOException {
+        writeRawString("null");
+        return this;
+    }
+
+    /**
+     * Method to write a number to the current writer.
+     * @param value The number to write to the JSON output string.
+     * @throws IOException Thrown if an error occurs during write.
+     */
+    public Serializer writeNumber(Number value) throws IOException {
+        if (null == value) return writeNull();
+
+        if (value instanceof Float) {
+            if (((Float)value).isNaN()) return writeNull();
+            if (Float.NEGATIVE_INFINITY == value.floatValue()) return writeNull();
+            if (Float.POSITIVE_INFINITY == value.floatValue()) return writeNull();
+        }
+
+        if (value instanceof Double) {
+            if (((Double)value).isNaN()) return writeNull();
+            if (Double.NEGATIVE_INFINITY == value.doubleValue()) return writeNull();
+            if (Double.POSITIVE_INFINITY == value.doubleValue()) return writeNull();
+        }
+
+        writeRawString(value.toString());
+
+        return this;
+    }
+
+    /**
+     * Method to write a boolean value to the output stream.
+     * @param value The Boolean object to write out as a JSON boolean.
+     * @throws IOException Thrown if an error occurs during write.
+     */
+    public Serializer writeBoolean(Boolean value) throws IOException {
+        if (null == value) return writeNull();
+
+        writeRawString(value.toString());
+
+        return this;
+    }
+
+    /**
+     * Method to generate a string with a particular width.  Alignment is done using zeroes if it does not meet the width requirements.
+     * @param s The string to write
+     * @param len The minimum length it should be, and to align with zeroes if length is smaller.
+     * @return A string properly aligned/correct width.
+     */
+    private String rightAlignedZero(String s, int len) {
+        if (len == s.length()) return s;
+
+        StringBuffer sb = new StringBuffer(s);
+
+        while (sb.length() < len) {
+            sb.insert(0, '0');
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * Method to write a String out to the writer, encoding special characters and unicode characters properly.
+     * @param value The string to write out.
+     * @throws IOException Thrown if an error occurs during write.
+     */
+    public Serializer writeString(String value) throws IOException {
+        if (null == value) return writeNull();
+
+        writer.write('"');
+
+        char[] chars = value.toCharArray();
+
+        for (int i=0; i<chars.length; i++) {
+            char c = chars[i];
+            switch (c) {
+                case  '"': writer.write("\\\""); break;
+                case '\\': writer.write("\\\\"); break;
+                case    0: writer.write("\\0"); break;
+                case '\b': writer.write("\\b"); break;
+                case '\t': writer.write("\\t"); break;
+                case '\n': writer.write("\\n"); break;
+                case '\f': writer.write("\\f"); break;
+                case '\r': writer.write("\\r"); break;
+                case '/': writer.write("\\/"); break;
+                default:
+                    if ((c >= 32) && (c <= 126)) {
+                        writer.write(c);
+                    } else {
+                        writer.write("\\u");
+                        writer.write(rightAlignedZero(Integer.toHexString(c),4));
+                    }
+            }
+        }
+
+        writer.write('"');
+
+        return this;
+    }
+
+    /**
+     * Method to write out a generic JSON type.
+     * @param object The JSON compatible object to serialize.
+     * @throws IOException Thrown if an error occurs during write, or if a nonJSON compatible Java object is passed..
+     */
+    private Serializer write(Object object) throws IOException {
+        if (null == object) return writeNull();
+        
+        // Serialize the various types!
+        Class clazz = object.getClass();
+        if (Number.class.isAssignableFrom(clazz)) return writeNumber((Number) object);
+        if (Boolean.class.isAssignableFrom(clazz)) return writeBoolean((Boolean) object);
+        if (JSONObject.class.isAssignableFrom(clazz)) return writeObject((JSONObject) object);
+        if (JSONArray.class.isAssignableFrom(clazz)) return writeArray((JSONArray) object);
+        if (JSONString.class.isAssignableFrom(clazz)) return writeRawString(((JSONString) object).toJSONString());
+        if (String.class.isAssignableFrom(clazz)) return writeString((String) object);
+
+        throw new IOException("Attempting to serialize unserializable object: '" + object + "'");
+    }
+
+    /**
+     * Method to write a complete JSON object to the stream.
+     * @param object The JSON object to write out.
+     * @throws IOException Thrown if an error occurs during write.
+     */
+    public Serializer writeObject(JSONObject object) throws IOException {
+        if (null == object) return writeNull();
+
+        // write header
+        writeRawString("{");
+        indentPush();
+
+        Iterator iter = null;
+        if (object instanceof OrderedJSONObject) {
+            iter = ((OrderedJSONObject)object).getOrder();
+        } else {
+            List propertyNames = getPropertyNames(object);
+            iter = propertyNames.iterator();
+        }
+
+        while ( iter.hasNext() ) {
+            Object key = iter.next();
+            if (!(key instanceof String)) throw new IOException("attempting to serialize object with an invalid property name: '" + key + "'" );
+
+            Object value = object.get(key);
+            if (!JSONObject.isValidObject(value)) throw new IOException("attempting to serialize object with an invalid property value: '" + value + "'");
+
+            newLine();
+            indent();
+            writeString((String)key);
+            writeRawString(":");
+            space();
+            write(value);
+
+            if (iter.hasNext()) writeRawString(",");
+        }
+
+        // write trailer
+        indentPop();
+        newLine();
+        indent();
+        writeRawString("}");
+
+        return this;
+    }
+
+    /**
+     * Method to write a JSON array out to the stream.
+     * @param value The JSON array to write out.
+     * @throws IOException Thrown if an error occurs during write.
+     */
+    public Serializer writeArray(JSONArray value) throws IOException {
+        if (null == value) return writeNull();
+
+        // write header
+        writeRawString("[");
+        indentPush();
+
+        for (Iterator iter=value.iterator(); iter.hasNext(); ) {
+            Object element = iter.next();
+            if (!JSONObject.isValidObject(element)) throw new IOException("attempting to serialize array with an invalid element: '" + value + "'");
+
+            newLine();
+            indent();
+            write(element);
+
+            if (iter.hasNext()) writeRawString(",");
+        }
+
+        // write trailer
+        indentPop();
+        newLine();
+        indent();
+        writeRawString("]");
+
+        return this;
+    }
+
+    //---------------------------------------------------------------
+    // pretty printing overridables
+    //---------------------------------------------------------------
+
+    /**
+     * Method to write a space to the output writer.
+     * @throws IOException Thrown if an error occurs during write.
+     */
+    public void space() throws IOException {
+    }
+
+    /**
+     * Method to write a newline to the output writer.
+     * @throws IOException Thrown if an error occurs during write.
+     */
+    public void newLine() throws IOException {
+    }
+
+    /**
+     * Method to write an indent to the output writer.
+     * @throws IOException Thrown if an error occurs during write.
+     */
+    public void indent() throws IOException {
+    }
+
+    /**
+     * Method to increase the indent depth of the output writer.
+     * @throws IOException Thrown if an error occurs during write.
+     */
+    public void indentPush() {
+    }
+
+    /**
+     * Method to reduce the indent depth of the output writer.
+     */
+    public void indentPop() {
+    }
+
+    /**
+     * Method to get a list of all the property names stored in a map.
+     */
+    public List getPropertyNames(Map map) {
+        return new ArrayList(map.keySet());
+    }
+
+}

Added: incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/SerializerVerbose.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/SerializerVerbose.java?rev=1021933&view=auto
==============================================================================
--- incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/SerializerVerbose.java (added)
+++ incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/SerializerVerbose.java Tue Oct 12 21:30:30 2010
@@ -0,0 +1,118 @@
+/*
+ * 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.wink.json4j.internal;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Map;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Internaql class for handling the serialization of JSON objects in a verbose
+ * format, meaning newlines and indention.
+ */
+public class SerializerVerbose extends Serializer {
+
+    /**
+     * Internal tracker keeping indent position.
+     */
+    private int indent = 0;
+
+    /**
+     * The indent string to use when serializing.
+     */
+    private String indentStr = "\t";
+
+    /**
+     * Constructor.
+     */
+    public SerializerVerbose(Writer writer) {
+        super(writer);
+    }
+
+    /**
+     * Constructor.
+     * @param Writer The writer to serialize JSON to.
+     * @param indentSpaces: How many spaces to indent by (0 to 8).  
+     * The default indent is the TAB character. 
+     */
+    public SerializerVerbose(Writer writer, int indentSpaces) {
+        super(writer);
+        if(indentSpaces > 0 && indentSpaces < 8){
+            this.indentStr = "";
+            for(int i = 0; i < indentSpaces; i++){
+                this.indentStr += " ";
+            }
+        }
+    }
+
+    /**
+     * Method to write a space to the output writer.
+     * @throws IOException Thrown if an error occurs during write.
+     */
+    public void space() throws IOException {
+        writeRawString(" ");
+    }
+
+    /**
+     * Method to write a newline to the output writer.
+     * @throws IOException Thrown if an error occurs during write.
+     */
+    public void newLine() throws IOException {
+        writeRawString("\n");
+    }
+
+    /**
+     * Method to write an indent to the output writer.
+     * @throws IOException Thrown if an error occurs during write.
+     */
+    public void indent() throws IOException {
+        for (int i=0; i<indent; i++) writeRawString(this.indentStr);
+    }
+
+    /**
+     * Method to increase the indent depth of the output writer.
+     * @throws IOException Thrown if an error occurs during write.
+     */
+    public void indentPush() {
+        indent++;
+    }
+
+    /**
+     * Method to reduce the indent depth of the output writer.
+     */
+    public void indentPop() {
+        indent--;
+        if (indent < 0) throw new IllegalStateException();
+    }
+
+    /**
+     * Method to get a list of all the property names stored in a map.
+     */
+    public List getPropertyNames(Map map) {
+        List propertyNames = super.getPropertyNames(map);
+
+        Collections.sort(propertyNames);
+
+        return propertyNames;
+    }
+
+}

Added: incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/Token.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/Token.java?rev=1021933&view=auto
==============================================================================
--- incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/Token.java (added)
+++ incubator/wink/trunk/wink-json4j/src/main/java/org/apache/wink/json4j/internal/Token.java Tue Oct 12 21:30:30 2010
@@ -0,0 +1,117 @@
+/*
+ * 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.wink.json4j.internal;
+
+/**
+ * Class representing a JSON token.
+ */
+public class Token {
+
+    static final public Token TokenEOF    = new Token();
+    static final public Token TokenBraceL = new Token();
+    static final public Token TokenBraceR = new Token();
+    static final public Token TokenBrackL = new Token();
+    static final public Token TokenBrackR = new Token();
+    static final public Token TokenColon  = new Token();
+    static final public Token TokenComma  = new Token();
+    static final public Token TokenTrue   = new Token();
+    static final public Token TokenFalse  = new Token();
+    static final public Token TokenNull   = new Token();
+
+    private String  valueString;
+    private Number  valueNumber;
+    private boolean  isConstant;
+
+
+    /**
+     * Constructor
+     */
+    public Token() {
+        super();
+    }
+
+    /**
+     * Constructor
+     * @param value The value of the token as a string
+     */
+    public Token(String value) {
+        super();
+        valueString = value;
+    }
+    
+    /**
+     * Constructor
+     * @param value The value of the token as a number
+     */
+    public Token(Number value) {
+        super();
+
+        valueNumber = value;
+    }
+
+    /**
+     * Method to obtain the string value of this token
+     */
+    public String getString() {
+        return valueString;
+    }
+
+    /**
+     * Method to obtain the number value of this token
+     */
+    public Number getNumber() {
+        return valueNumber;
+    }
+
+    /**
+     * Method to indicate if this token is string based or not.
+     */
+    public boolean isString() {
+        return (null != valueString) && !isConstant;
+    }
+
+    /**
+     * Method to indicate if this token is number based or not.
+     */
+    public boolean isNumber() {
+        return null != valueNumber;
+    }
+
+    /**
+     * Method to convert the token to a string representation.
+     */
+    public String toString() {
+        if (this == TokenEOF)    return "Token: EOF";
+        if (this == TokenBraceL) return "Token: {";
+        if (this == TokenBraceR) return "Token: }";
+        if (this == TokenBrackL) return "Token: [";
+        if (this == TokenBrackR) return "Token: ]";
+        if (this == TokenColon)  return "Token: :";
+        if (this == TokenComma)  return "Token: ,";
+        if (this == TokenTrue)   return "Token: true";
+        if (this == TokenFalse)  return "Token: false";
+        if (this == TokenNull)   return "Token: null";
+
+        if (this.isNumber()) return "Token: Number - " + getNumber();
+        if (this.isString()) return "Token: String - '" + getString() + "'";
+
+        return "Token: unknown.";
+    }
+}



Mime
View raw message