From 09540883f19e7c4a7d24357256454b2e85cf8593 Mon Sep 17 00:00:00 2001 From: erickson Date: Thu, 10 May 2007 16:31:52 +0000 Subject: [PATCH] added support for opensrf-serializable objects and JSON output of those objects. updated some JSON test code git-svn-id: svn://svn.open-ils.org/OpenSRF/trunk@881 9efc2488-bf62-4759-914b-345cdb29e865 --- src/java/org/opensrf/Message.java | 28 ++++++- src/java/org/opensrf/Method.java | 29 +++++++- src/java/org/opensrf/Result.java | 28 +++++++ src/java/org/opensrf/test/TestJSON.java | 25 ++++++- src/java/org/opensrf/util/JSON.java | 39 ++++++++++ src/java/org/opensrf/util/OSRFObject.java | 44 +++++++++++ src/java/org/opensrf/util/OSRFRegistry.java | 99 +++++++++++++++++++++++++ src/java/org/opensrf/util/OSRFSerializable.java | 16 ++++ 8 files changed, 303 insertions(+), 5 deletions(-) create mode 100644 src/java/org/opensrf/util/OSRFObject.java create mode 100644 src/java/org/opensrf/util/OSRFRegistry.java create mode 100644 src/java/org/opensrf/util/OSRFSerializable.java diff --git a/src/java/org/opensrf/Message.java b/src/java/org/opensrf/Message.java index 798839a..441172a 100644 --- a/src/java/org/opensrf/Message.java +++ b/src/java/org/opensrf/Message.java @@ -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; + } } diff --git a/src/java/org/opensrf/Method.java b/src/java/org/opensrf/Method.java index 97a5ba3..b6dc7b4 100644 --- a/src/java/org/opensrf/Method.java +++ b/src/java/org/opensrf/Method.java @@ -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 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(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; + } + } diff --git a/src/java/org/opensrf/Result.java b/src/java/org/opensrf/Result.java index f295a1a..a784899 100644 --- a/src/java/org/opensrf/Result.java +++ b/src/java/org/opensrf/Result.java @@ -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; + } + } diff --git a/src/java/org/opensrf/test/TestJSON.java b/src/java/org/opensrf/test/TestJSON.java index 31a1550..e57f01e 100644 --- a/src/java/org/opensrf/test/TestJSON.java +++ b/src/java/org/opensrf/test/TestJSON.java @@ -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"); } } diff --git a/src/java/org/opensrf/util/JSON.java b/src/java/org/opensrf/util/JSON.java index 4ba7066..9e17b5d 100644 --- a/src/java/org/opensrf/util/JSON.java +++ b/src/java/org/opensrf/util/JSON.java @@ -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 map = new HashMap(); + map.put(JSON_CLASS_KEY, reg.getNetClass()); + + if( reg.getWireProtocol() == OSRFRegistry.WireProtocol.ARRAY ) { + + List list = new ArrayList(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(obj)); + Map subMap = new HashMap(); + 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 index 0000000..0f2c7af --- /dev/null +++ b/src/java/org/opensrf/util/OSRFObject.java @@ -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 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 index 0000000..8a59913 --- /dev/null +++ b/src/java/org/opensrf/util/OSRFRegistry.java @@ -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 + registry = new HashMap(); + + + /** 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 index 0000000..23d5896 --- /dev/null +++ b/src/java/org/opensrf/util/OSRFSerializable.java @@ -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); +} + + -- 2.11.0