added support for opensrf-serializable objects and JSON output of those objects....
authorerickson <erickson@9efc2488-bf62-4759-914b-345cdb29e865>
Thu, 10 May 2007 16:31:52 +0000 (16:31 +0000)
committererickson <erickson@9efc2488-bf62-4759-914b-345cdb29e865>
Thu, 10 May 2007 16:31:52 +0000 (16:31 +0000)
git-svn-id: svn://svn.open-ils.org/OpenSRF/trunk@881 9efc2488-bf62-4759-914b-345cdb29e865

src/java/org/opensrf/Message.java
src/java/org/opensrf/Method.java
src/java/org/opensrf/Result.java
src/java/org/opensrf/test/TestJSON.java
src/java/org/opensrf/util/JSON.java
src/java/org/opensrf/util/OSRFObject.java [new file with mode: 0644]
src/java/org/opensrf/util/OSRFRegistry.java [new file with mode: 0644]
src/java/org/opensrf/util/OSRFSerializable.java [new file with mode: 0644]

index 798839a..441172a 100644 (file)
@@ -1,7 +1,8 @@
 package org.opensrf;
+import org.opensrf.util.*;
 
 
-public class Message {
+public class Message implements OSRFSerializable {
 
     /** Message types */
     public enum Type {
@@ -19,6 +20,13 @@ public class Message {
     /** message payload */
     private Object payload;
 
+    /** Go ahead and register the Message object */
+    private static OSRFRegistry registry = 
+        OSRFRegistry.registerObject(
+            "osrfMessage", 
+            OSRFRegistry.WireProtocol.HASH, 
+            new String[] {"threadTrace", "type", "payload"});
+
     /**
      * @param id This message's ID
      * @param type The type of message
@@ -27,6 +35,7 @@ public class Message {
         setId(id);
         setType(type);
     }
+
     public int getId() {
         return id;
     }   
@@ -45,6 +54,23 @@ public class Message {
     public void setPayload(Object p) {
         payload = p;
     }
+
+    /**
+     * Implements the generic get() API required by OSRFSerializable
+     */
+    public Object get(String field) {
+        if("threadTrace".equals(field))
+            return getId();
+        if("type".equals(field))
+            return getType().toString();
+        if("payload".equals(field))
+            return getPayload();
+        return null;
+    }
+
+    public OSRFRegistry getRegistry() {
+        return registry;
+    }
 }
 
 
index 97a5ba3..b6dc7b4 100644 (file)
@@ -1,13 +1,22 @@
 package org.opensrf;
 import java.util.List;
 import java.util.ArrayList;
+import org.opensrf.util.*;
 
 
-public class Method {
+public class Method implements OSRFSerializable {
 
     private String name;
     private List<Object> params;
 
+    /** Register this object */
+    private static OSRFRegistry registry = 
+        OSRFRegistry.registerObject(
+            "osrfMethod", 
+            OSRFRegistry.WireProtocol.HASH, 
+            new String[] {"method", "params"});
+
+
     public Method(String name) {
         this.name = name;
         this.params = new ArrayList<Object>(8);
@@ -29,8 +38,24 @@ public class Method {
      * Pushes a new param object onto the set of params 
      * @param p The new param to add to the method.
      */
-    public void pushParam(Object p) {
+    public void addParam(Object p) {
         this.params.add(p);
     }
+
+    /**
+     * Implements the generic get() API required by OSRFSerializable
+     */
+    public Object get(String field) {
+        if("method".equals(field))
+            return getName();
+        if("params".equals(field))
+            return getParams();
+        return null;
+    }
+
+    public OSRFRegistry getRegistry() {
+        return registry;
+    }
+
 }
 
index f295a1a..a784899 100644 (file)
@@ -1,4 +1,5 @@
 package org.opensrf;
+import org.opensrf.util.*;
 
 
 /**
@@ -13,6 +14,15 @@ public class Result {
     /** Status code number */
     private int statusCode;
 
+
+    /** Register this object */
+    private static OSRFRegistry registry = 
+        OSRFRegistry.registerObject(
+            "osrfResult", 
+            OSRFRegistry.WireProtocol.HASH, 
+            new String[] {"status", "statusCode", "content"});
+
+
     public Result(String status, int statusCode, Object content) {
         this.status = status;
         this.statusCode = statusCode;
@@ -66,5 +76,23 @@ public class Result {
     public void setContent(Object content) {
         this.content = content;
     }
+
+    /**
+     * Implements the generic get() API required by OSRFSerializable
+     */
+    public Object get(String field) {
+        if("status".equals(field))
+            return getStatus();
+        if("statusCode".equals(field))
+            return getStatusCode();
+        if("content".equals(field))
+            return getContent();
+        return null;
+    }
+
+    public OSRFRegistry getRegistry() {
+        return registry;
+    }
+
 }
 
index 31a1550..e57f01e 100644 (file)
@@ -1,6 +1,7 @@
 package org.opensrf.test;
 
-import org.opensrf.util.JSON;
+import org.opensrf.*;
+import org.opensrf.util.*;
 import java.util.*;
 
 public class TestJSON {
@@ -21,6 +22,26 @@ public class TestJSON {
         list.add(null);
         map.put("key6", list);
 
-        System.out.println(JSON.toJSON(map));
+        System.out.println(JSON.toJSON(map) + "\n");
+
+        String[] fields = {"isnew", "name", "shortname", "ill_address"};
+        OSRFRegistry.registerObject("aou", OSRFRegistry.WireProtocol.ARRAY, fields);
+
+        OSRFObject obj = new OSRFObject(OSRFRegistry.getRegistry("aou"));
+        obj.put("name", "athens clarke county");
+        obj.put("ill_address", new Integer(1));
+        obj.put("shortname", "ARL-ATH");
+
+        map.put("key7", obj);
+        list.add(obj);
+        System.out.println(JSON.toJSON(map) + "\n");
+
+
+        Message m = new Message(1, Message.Type.REQUEST);
+        Method method = new Method("opensrf.settings.host_config.get");
+        method.addParam("app07.dev.gapines.org");
+        m.setPayload(method);
+
+        System.out.println(JSON.toJSON(m) + "\n");
     }
 }
index 4ba7066..9e17b5d 100644 (file)
@@ -8,7 +8,10 @@ import java.util.*;
  */
 public class JSON {
 
+    /** Special OpenSRF serializable object netClass key */
     public static final String JSON_CLASS_KEY = "__c";
+
+    /** Special OpenSRF serializable object payload key */
     public static final String JSON_PAYLOAD_KEY = "__p";
 
 
@@ -55,6 +58,12 @@ public class JSON {
             return;
         }
 
+        /** OpenSRF serializable objects */
+        if(obj instanceof OSRFSerializable) {
+            encodeOSRFSerializable((OSRFSerializable) obj, sb);
+            return;
+        }
+
         /** JSON object */
         if(obj instanceof Map) {
             encodeJSONObject((Map) obj, sb);
@@ -111,6 +120,36 @@ public class JSON {
             sb.deleteCharAt(sb.length()-1); 
         sb.append("}");
     }
+
+
+    /**
+     * Encodes a network-serializable OpenSRF object
+     */
+    private static void encodeOSRFSerializable(OSRFSerializable obj, StringBuffer sb) {
+
+        OSRFRegistry reg = obj.getRegistry();
+        String[] fields = reg.getFields();
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put(JSON_CLASS_KEY, reg.getNetClass());
+
+        if( reg.getWireProtocol() == OSRFRegistry.WireProtocol.ARRAY ) {
+
+            List<Object> list = new ArrayList<Object>(fields.length);
+            for(String s : fields)
+                list.add(obj.get(s));
+            map.put(JSON_PAYLOAD_KEY, list);
+
+        } else {
+            //map.put(JSON_PAYLOAD_KEY, new HashMap<String, Object>(obj));
+            Map<String, Object> subMap = new HashMap<String, Object>();
+            for(String s : fields)
+                map.put(s, obj.get(s));
+                
+        }
+
+        /** now serialize the encoded object */
+        toJSON(map, sb);
+    }
 }
 
 
diff --git a/src/java/org/opensrf/util/OSRFObject.java b/src/java/org/opensrf/util/OSRFObject.java
new file mode 100644 (file)
index 0000000..0f2c7af
--- /dev/null
@@ -0,0 +1,44 @@
+package org.opensrf.util;
+
+import java.util.HashMap;
+
+
+/**
+ * Generic OpenSRF network-serializable object.  This allows
+ * access to object fields.  
+ */
+public class OSRFObject extends HashMap<String, Object> implements OSRFSerializable {
+    
+    /** This objects registry */
+    private OSRFRegistry registry;
+
+    public OSRFObject() {
+    }
+
+    /**
+     * Creates a new object with the provided registry
+     */
+    public OSRFObject(OSRFRegistry reg) {
+        this();
+        registry = reg;
+    }
+
+
+    /**
+     * @return This object's registry
+     */
+    public OSRFRegistry getRegistry() {
+        return registry;
+    }
+
+
+    /**
+     * Gets the object at the given fields.  We override this here
+     * as part of the contract with OSRFSerializable
+     * @param field the field name to get.
+     * @return The object contained at the given field.
+     */
+    public Object get(String field) {
+        return super.get(field);
+    }
+}
diff --git a/src/java/org/opensrf/util/OSRFRegistry.java b/src/java/org/opensrf/util/OSRFRegistry.java
new file mode 100644 (file)
index 0000000..8a59913
--- /dev/null
@@ -0,0 +1,99 @@
+package org.opensrf.util;
+
+import java.util.Map;
+import java.util.HashMap;
+
+
+/**
+ * Manages the registration of OpenSRF network-serializable objects.  
+ * A serializable object has a class "hint" (called netClass within) which
+ * describes the type of object.  Each object also has a set of field names
+ * for accessing/mutating object properties.  Finally, objects have a 
+ * serialization wire protocol.  Currently supported protocols are HASH
+ * and ARRAY.
+ */
+public class OSRFRegistry {
+
+
+    /**
+     * Global collection of registered net objects.  
+     * Maps netClass names to registries.
+     */
+    private static HashMap<String, OSRFRegistry> 
+        registry = new HashMap<String, OSRFRegistry>();
+
+
+    /** Serialization types for registered objects */
+    public enum WireProtocol {
+        ARRAY, HASH
+    };
+
+
+    /** Array of field names for this registered object */
+    String fields[];
+    /** The wire protocol for this object */
+    WireProtocol wireProtocol;
+    /** The network class for this object */
+    String netClass;
+
+    /**
+     * Returns the array of field names
+     */
+    public String[] getFields() {
+        return this.fields;
+    }
+
+
+    /**
+     * Registers a new object.
+     * @param netClass The net class for this object
+     * @param wireProtocol The object's wire protocol
+     * @param fields An array of field names.  For objects whose
+     * wire protocol is ARRAY, the positions of the field names 
+     * will be used as the array indices for the fields at serialization time
+     */
+    public static OSRFRegistry registerObject(String netClass, WireProtocol wireProtocol, String fields[]) {
+        OSRFRegistry r = new OSRFRegistry(netClass, wireProtocol, fields);
+        registry.put(netClass, r);
+        return r;
+    }
+
+    /**
+     * Returns the registry for the given netclass
+     * @param netClass The network class to lookup
+     */
+    public static OSRFRegistry getRegistry(String netClass) {
+        if( netClass == null ) return null;
+        return (OSRFRegistry) registry.get(netClass);
+    }
+
+
+    /**
+     * @param field The name of the field to lookup
+     * @return the index into the fields array of the given field name.
+     */
+    public int getFieldIndex(String field) {
+        for( int i = 0; i < fields.length; i++ )
+            if( fields[i].equals(field) ) 
+                return i;
+        return -1;
+    }
+
+    public WireProtocol getWireProtocol() {
+        return this.wireProtocol;
+    }
+
+    public String getNetClass() {
+        return this.netClass;
+    }
+
+    /**
+     * Creates a new registry object */
+    public OSRFRegistry(String netClass, WireProtocol wireProtocol, String fields[]) {
+        this.netClass = netClass;
+        this.wireProtocol = wireProtocol;
+        this.fields = fields;
+    }
+}
+
+
diff --git a/src/java/org/opensrf/util/OSRFSerializable.java b/src/java/org/opensrf/util/OSRFSerializable.java
new file mode 100644 (file)
index 0000000..23d5896
--- /dev/null
@@ -0,0 +1,16 @@
+package org.opensrf.util;
+
+/**
+ * All network-serializable OpenSRF object must implement this interface.
+ */
+public interface OSRFSerializable {
+
+    /**
+     * Returns the object registry object for the implementing class.
+     */
+    public abstract OSRFRegistry getRegistry();
+
+    public abstract Object get(String field);
+}
+
+