Documented valid dobj types in DObject; implemented value marshaller which

can read and write all of the valid dobj types over the network; wired up
the attribute changed events to serialize and unserialize their values.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@35 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2001-06-12 02:57:30 +00:00
parent 89083f4708
commit c8b13e3bca
4 changed files with 550 additions and 8 deletions
@@ -1,5 +1,5 @@
//
// $Id: AttributeChangedEvent.java,v 1.4 2001/06/11 17:44:04 mdb Exp $
// $Id: AttributeChangedEvent.java,v 1.5 2001/06/12 02:57:30 mdb Exp $
package com.threerings.cocktail.cher.dobj;
@@ -8,7 +8,7 @@ import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import com.threerings.cocktail.cher.Log;
import com.threerings.cocktail.cher.dobj.io.ValueMarshaller;
/**
* An attribute changed event is dispatched when a single attribute of a
@@ -123,7 +123,7 @@ public class AttributeChangedEvent extends TypedEvent
{
super.writeTo(out);
out.writeUTF(_name);
// out.write...(_value);
ValueMarshaller.writeTo(out, _value);
}
public void readFrom (DataInputStream in)
@@ -131,7 +131,7 @@ public class AttributeChangedEvent extends TypedEvent
{
super.readFrom(in);
_name = in.readUTF();
// _value = in.read...
_value = ValueMarshaller.readFrom(in);
}
public String toString ()
@@ -1,5 +1,5 @@
//
// $Id: AttributesChangedEvent.java,v 1.3 2001/06/11 17:44:04 mdb Exp $
// $Id: AttributesChangedEvent.java,v 1.4 2001/06/12 02:57:30 mdb Exp $
package com.threerings.cocktail.cher.dobj;
@@ -7,6 +7,8 @@ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import com.threerings.cocktail.cher.dobj.io.ValueMarshaller;
/**
* An attribute<em>s</em> changed event is dispatched when multiple
* attributes of a distributed object have been changed in a single
@@ -171,7 +173,7 @@ public class AttributesChangedEvent extends TypedEvent
out.writeInt(_count);
for (int i = 0; i < _count; i++) {
out.writeUTF(_names[i]);
// out.write...(_values[i]);
ValueMarshaller.writeTo(out, _values[i]);
}
}
@@ -184,7 +186,7 @@ public class AttributesChangedEvent extends TypedEvent
_values = new Object[_count];
for (int i = 0; i < _count; i++) {
_names[i] = in.readUTF();
// _values[i] = ...
_values[i] = ValueMarshaller.readFrom(in);
}
}
@@ -1,5 +1,5 @@
//
// $Id: DObject.java,v 1.9 2001/06/09 23:39:04 mdb Exp $
// $Id: DObject.java,v 1.10 2001/06/12 02:57:30 mdb Exp $
package com.threerings.cocktail.cher.dobj;
@@ -70,6 +70,15 @@ import java.util.ArrayList;
*
* These method calls on the actual distributed object will result in the
* proper attribute change events being generated and dispatched.
*
* <p> Note that distributed object fields can only be of a limited set of
* supported types. These types are:
*
* <code><pre>
* byte, short, int, long, float, double
* Byte, Short, Integer, Long, Float, Double, String
* byte[], short[], int[], long[], float[], double[], String[]
* </pre></code>
*/
public class DObject
{
@@ -0,0 +1,531 @@
//
// $Id: ValueMarshaller.java,v 1.1 2001/06/12 02:57:30 mdb Exp $
package com.threerings.cocktail.cher.dobj.io;
import java.io.*;
import java.util.HashMap;
import com.samskivert.util.IntMap;
/**
* The value marshaller provides a mechanism for marshalling and
* unmarshalling values of valid distributed object attribute types
* (<code>int</code>, <code>String</code>, etc.). It is used when the type
* needs to be accompanied by a type identifier because it cannot be
* inferred from the context.
*
* <p> For example, when we are serializing a distributed object, we don't
* use the value marshaller because we can just write the attributes out
* in a known order and infer their types on the receiving end. On the
* other hand, when serializing an event, we need to use the value
* marshaller because we only have an oid, an attribute name and some
* arbitrary value at that point. We can't be sure that the oid maps to an
* object on the receiving end from which we could determine the type of
* that particular attribute.
*
* <p> Note also that we only deal with distributed object types in object
* form (meaning <code>int</code> values have been converted into
* <code>Integer</code> instances, etc.).
*/
public class ValueMarshaller
{
/**
* Writes the supplied value to the output stream preceeded by a type
* identifier that will allow us to read it back in on the other end.
* The value must be one of the valid distributed object attribute
* types.
*
* @see DObject
* @see #readFrom
*/
public static void writeTo (DataOutputStream out, Object value)
throws IOException
{
Marshaller marsh = (Marshaller)_outmap.get(value.getClass());
if (marsh == null) {
throw new RuntimeException("Requested to serialize invalid " +
"type [value=" + value + ", type=" +
value.getClass().getName() + "].");
}
// write the value out using the appropriate marshaller
out.writeByte(marsh.code);
marsh.writeValue(out, value);
}
/**
* Reads a value in from the stream that was previously written out
* with <code>writeTo</code>.
*
* @see #writeTo
*/
public static Object readFrom (DataInputStream in)
throws IOException
{
byte code = in.readByte();
Marshaller marsh = (Marshaller)_inmap.get((int)code);
if (marsh == null) {
throw new RuntimeException("Requested to unserialize invalid " +
"type [code=" + code + "].");
}
return marsh.readValue(in);
}
// test these suckers out
public static void main (String[] args)
{
Object[] values = new Object[14];
values[0] = new Byte((byte)1);
values[1] = new Short((short)2);
values[2] = new Integer(3);
values[3] = new Long(4l);
values[4] = new Float(5.0f);
values[5] = new Double(6.0);
values[6] = "this is a string";
values[7] = new byte[] { 0, 1, 2, 3 };
values[8] = new short[] { 0, 1, 2, 3 };
values[9] = new int[] { 0, 1, 2, 3 };
values[10] = new long[] { 0, 1, 2, 3 };
values[11] = new float[] { 0.0f, 1.0f, 2.0f, 3.0f };
values[12] = new double[] { 0.0, 1.0, 2.0, 3.0 };
values[13] = new String[] { "one", "two", "three", "four" };
File file = new File("test.dat");
try {
FileOutputStream fout = new FileOutputStream(file);
BufferedOutputStream bout = new BufferedOutputStream(fout);
DataOutputStream dout = new DataOutputStream(bout);
// write out our values
for (int i = 0; i < values.length; i++) {
writeTo(dout, values[i]);
}
// close the file
dout.flush();
fout.close();
// and read it all back in
FileInputStream fin = new FileInputStream(file);
BufferedInputStream bin = new BufferedInputStream(fin);
DataInputStream din = new DataInputStream(bin);
for (int i = 0; i < values.length; i++) {
Object value = readFrom(din);
System.out.println(value.getClass().getName() + ": " + value);
}
fin.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
// delete our temp file
file.delete();
}
/**
* Used to marshall and unmarshall values.
*/
protected static abstract class Marshaller
{
public byte code;
public Marshaller (byte code)
{
this.code = code;
}
public abstract void writeValue (DataOutputStream out, Object value)
throws IOException;
public abstract Object readValue (DataInputStream in)
throws IOException;
}
protected static class ByteMarshaller extends Marshaller
{
public ByteMarshaller ()
{
super((byte)1);
}
public void writeValue (DataOutputStream out, Object value)
throws IOException
{
out.writeByte(((Byte)value).byteValue());
}
public Object readValue (DataInputStream in)
throws IOException
{
return new Byte(in.readByte());
}
}
protected static class ShortMarshaller extends Marshaller
{
public ShortMarshaller ()
{
super((byte)2);
}
public void writeValue (DataOutputStream out, Object value)
throws IOException
{
out.writeShort(((Short)value).shortValue());
}
public Object readValue (DataInputStream in)
throws IOException
{
return new Short(in.readShort());
}
}
protected static class IntegerMarshaller extends Marshaller
{
public IntegerMarshaller ()
{
super((byte)3);
}
public void writeValue (DataOutputStream out, Object value)
throws IOException
{
out.writeInt(((Integer)value).intValue());
}
public Object readValue (DataInputStream in)
throws IOException
{
return new Integer(in.readInt());
}
}
protected static class LongMarshaller extends Marshaller
{
public LongMarshaller ()
{
super((byte)4);
}
public void writeValue (DataOutputStream out, Object value)
throws IOException
{
out.writeLong(((Long)value).longValue());
}
public Object readValue (DataInputStream in)
throws IOException
{
return new Long(in.readLong());
}
}
protected static class FloatMarshaller extends Marshaller
{
public FloatMarshaller ()
{
super((byte)5);
}
public void writeValue (DataOutputStream out, Object value)
throws IOException
{
out.writeFloat(((Float)value).floatValue());
}
public Object readValue (DataInputStream in)
throws IOException
{
return new Float(in.readFloat());
}
}
protected static class DoubleMarshaller extends Marshaller
{
public DoubleMarshaller ()
{
super((byte)6);
}
public void writeValue (DataOutputStream out, Object value)
throws IOException
{
out.writeDouble(((Double)value).doubleValue());
}
public Object readValue (DataInputStream in)
throws IOException
{
return new Double(in.readDouble());
}
}
protected static class StringMarshaller extends Marshaller
{
public StringMarshaller ()
{
super((byte)7);
}
public void writeValue (DataOutputStream out, Object value)
throws IOException
{
out.writeUTF((String)value);
}
public Object readValue (DataInputStream in)
throws IOException
{
return in.readUTF();
}
}
protected static class ByteArrayMarshaller extends Marshaller
{
public ByteArrayMarshaller ()
{
super((byte)8);
}
public void writeValue (DataOutputStream out, Object value)
throws IOException
{
byte[] data = (byte[])value;
out.writeInt(data.length);
for (int i = 0; i < data.length; i++) {
out.writeByte(data[i]);
}
}
public Object readValue (DataInputStream in)
throws IOException
{
byte[] data = new byte[in.readInt()];
for (int i = 0; i < data.length; i++) {
data[i] = in.readByte();
}
return data;
}
}
protected static class ShortArrayMarshaller extends Marshaller
{
public ShortArrayMarshaller ()
{
super((byte)9);
}
public void writeValue (DataOutputStream out, Object value)
throws IOException
{
short[] data = (short[])value;
out.writeInt(data.length);
for (int i = 0; i < data.length; i++) {
out.writeShort(data[i]);
}
}
public Object readValue (DataInputStream in)
throws IOException
{
short[] data = new short[in.readInt()];
for (int i = 0; i < data.length; i++) {
data[i] = in.readShort();
}
return data;
}
}
protected static class IntegerArrayMarshaller extends Marshaller
{
public IntegerArrayMarshaller ()
{
super((byte)10);
}
public void writeValue (DataOutputStream out, Object value)
throws IOException
{
int[] data = (int[])value;
out.writeInt(data.length);
for (int i = 0; i < data.length; i++) {
out.writeInt(data[i]);
}
}
public Object readValue (DataInputStream in)
throws IOException
{
int[] data = new int[in.readInt()];
for (int i = 0; i < data.length; i++) {
data[i] = in.readInt();
}
return data;
}
}
protected static class LongArrayMarshaller extends Marshaller
{
public LongArrayMarshaller ()
{
super((byte)11);
}
public void writeValue (DataOutputStream out, Object value)
throws IOException
{
long[] data = (long[])value;
out.writeInt(data.length);
for (int i = 0; i < data.length; i++) {
out.writeLong(data[i]);
}
}
public Object readValue (DataInputStream in)
throws IOException
{
long[] data = new long[in.readInt()];
for (int i = 0; i < data.length; i++) {
data[i] = in.readLong();
}
return data;
}
}
protected static class FloatArrayMarshaller extends Marshaller
{
public FloatArrayMarshaller ()
{
super((byte)12);
}
public void writeValue (DataOutputStream out, Object value)
throws IOException
{
float[] data = (float[])value;
out.writeInt(data.length);
for (int i = 0; i < data.length; i++) {
out.writeFloat(data[i]);
}
}
public Object readValue (DataInputStream in)
throws IOException
{
float[] data = new float[in.readInt()];
for (int i = 0; i < data.length; i++) {
data[i] = in.readFloat();
}
return data;
}
}
protected static class DoubleArrayMarshaller extends Marshaller
{
public DoubleArrayMarshaller ()
{
super((byte)13);
}
public void writeValue (DataOutputStream out, Object value)
throws IOException
{
double[] data = (double[])value;
out.writeInt(data.length);
for (int i = 0; i < data.length; i++) {
out.writeDouble(data[i]);
}
}
public Object readValue (DataInputStream in)
throws IOException
{
double[] data = new double[in.readInt()];
for (int i = 0; i < data.length; i++) {
data[i] = in.readDouble();
}
return data;
}
}
protected static class StringArrayMarshaller extends Marshaller
{
public StringArrayMarshaller ()
{
super((byte)14);
}
public void writeValue (DataOutputStream out, Object value)
throws IOException
{
String[] data = (String[])value;
out.writeInt(data.length);
for (int i = 0; i < data.length; i++) {
out.writeUTF(data[i]);
}
}
public Object readValue (DataInputStream in)
throws IOException
{
String[] data = new String[in.readInt()];
for (int i = 0; i < data.length; i++) {
data[i] = in.readUTF();
}
return data;
}
}
protected static HashMap _outmap = new HashMap();
protected static IntMap _inmap = new IntMap();
protected static Class[] _classes = {
Byte.class,
Short.class,
Integer.class,
Long.class,
Float.class,
Double.class,
String.class,
(new byte[0]).getClass(),
(new short[0]).getClass(),
(new int[0]).getClass(),
(new long[0]).getClass(),
(new float[0]).getClass(),
(new double[0]).getClass(),
(new String[0]).getClass()
};
protected static Marshaller[] _marshallers = {
new ByteMarshaller(),
new ShortMarshaller(),
new IntegerMarshaller(),
new LongMarshaller(),
new FloatMarshaller(),
new DoubleMarshaller(),
new StringMarshaller(),
new ByteArrayMarshaller(),
new ShortArrayMarshaller(),
new IntegerArrayMarshaller(),
new LongArrayMarshaller(),
new FloatArrayMarshaller(),
new DoubleArrayMarshaller(),
new StringArrayMarshaller()
};
// register our marshallers
static {
Marshaller marsh;
for (int i = 0; i < _classes.length; i++) {
marsh = _marshallers[i];
_outmap.put(_classes[i], marsh);
_inmap.put(marsh.code, marsh);
}
}
}