StandardSerializer
来源:互联网 发布:lable java 编辑:程序博客网 时间:2024/06/05 18:28
StandardSerializer implements 2 interfaces.
* Serializer
public interface Serializer extends AttributeHandler, Closeable { public Object readClassAndObject(ScanBuffer buffer); public <T> T readObject(ScanBuffer buffer, Class<T> type); public <T> T readObjectByteOrder(ScanBuffer buffer, Class<T> type); public <T> T readObjectNotNull(ScanBuffer buffer, Class<T> type); public DataOutput getDataOutput(int initialCapacity);}
ScanBuffer
Scan Buffer allows sequential reads. Should not be used by multiple threads.
public interface ScanBuffer { public boolean hasRemaining(); public byte getByte(); public boolean getBoolean(); public short getShort(); public int getInt(); public long getLong(); public char getChar(); public float getFloat(); public double getDouble(); public byte[] getBytes(int length); public short[] getShorts(int length); public int[] getInts(int length); public long[] getLongs(int length); public char[] getChars(int length); public float[] getFloats(int length); public double[] getDoubles(int length);}
WriteBuffer
WriteBuffer is a Buffer that allows simple writes and returns the result as a {@link StaticBuffer}.
public interface WriteBuffer { public WriteBuffer putByte(byte val); public WriteBuffer putBytes(byte[] val); public WriteBuffer putBytes(StaticBuffer val); public WriteBuffer putBoolean(boolean val); public WriteBuffer putShort(short val); public WriteBuffer putInt(int val); public WriteBuffer putLong(long val); public WriteBuffer putChar(char val); public WriteBuffer putFloat(float val); public WriteBuffer putDouble(double val); public StaticBuffer getStaticBuffer(); public int getPosition(); public StaticBuffer getStaticBufferFlipBytes(int from, int to);}
- AttributeHandler
public interface AttributeHandler { public <T> void registerClass(int registrationNo, Class<T> type, AttributeSerializer<T> attributeHandler); public boolean validDataType(Class datatype); public<V> void verifyAttribute(Class<V> datatype, Object value); /** * Converts the given (not-null) value to the this datatype V. * The given object will NOT be of type V. * Throws an {@link IllegalArgumentException} if it cannot be converted. * * @param value to convert * @return converted to expected datatype */ public<V> V convert(Class<V> datatype, Object value); public boolean isOrderPreservingDatatype(Class<?> datatype);}
- Fields List
/** * This offset is used by user registration to make sure they don't collide with internal class * registrations. It must be ensured that this number is LARGER than any internally used * registration number. * This value may NEVER EVER be changed or compatibility to older versions breaks */ private static final int CLASS_REGISTRATION_OFFSET = 100; private static final int MAX_REGISTRATION_NO = 100000; private final BiMap<Integer,Class> registrations = new HashMap<>(60); /* * A {@link BiMap} backed by two hash tables. This implementation allows null keys and values. A * {@code HashBiMap} and its inverse are both serializable. */ private final Map<Class,AttributeSerializer> handlers = HashBiMap.create(60);
Then resister a large amount of serializer.
registerClassInternal(11,Short.class, new ShortSerializer());public synchronized <V> void registerClassInternal(int registrationNo, Class<? extends V> datatype, AttributeSerializer<V> serializer) { registrations.put(registrationNo, datatype); if (serializer instanceof SerializerInjected) ((SerializerInjected)serializer).setSerializer(this); handlers.put(datatype, serializer); }
SerializerInjected uses the StandardSerializer to read the content from ScanBuffer. Take
ParameterSerializer for example.
public class ParameterSerializer implements AttributeSerializer<Parameter>, SerializerInjected { private Serializer serializer; @Override public Parameter read(ScanBuffer buffer) { String key = serializer.readObjectNotNull(buffer,String.class); Object value = serializer.readClassAndObject(buffer); return new Parameter(key,value); } @Override public void write(WriteBuffer buffer, Parameter attribute) { DataOutput out = (DataOutput)buffer; out.writeObjectNotNull(attribute.key()); out.writeClassAndObject(attribute.value()); } @Override public void setSerializer(Serializer serializer) { Preconditions.checkNotNull(serializer); this.serializer=serializer; }}
Take ShortSerializer for example.
registerClassInternal(11,Short.class, new ShortSerializer());registerClassInternal(18,String.class, new StringSerializer()); //supports null serialization
public class ShortSerializer implements OrderPreservingSerializer<Short> { private static final long serialVersionUID = 117423419862504186L; @Override public Short read(ScanBuffer buffer) { return Short.valueOf((short)(buffer.getShort() + Short.MIN_VALUE)); } @Override public void write(WriteBuffer out, Short object) { out.putShort((short)(object.shortValue() - Short.MIN_VALUE)); } @Override public Short readByteOrder(ScanBuffer buffer) { return read(buffer); } @Override public void writeByteOrder(WriteBuffer buffer, Short attribute) { write(buffer,attribute); } /* ====== These methods apply to all whole numbers with minor modifications ======== ====== byte, short, int, long ====== */ @Override public Short convert(Object value) { if (value instanceof Number) { double d = ((Number)value).doubleValue(); if (Double.isNaN(d) || Math.round(d)!=d) throw new IllegalArgumentException("Not a valid short: " + value); long l = ((Number)value).longValue(); if (l>=Short.MIN_VALUE && l<=Short.MAX_VALUE) return Short.valueOf((short)l); else throw new IllegalArgumentException("Value too large for short: " + value); } else if (value instanceof String) { return Short.parseShort((String)value); } else return null; }}
Method getDataOutput in StandardSerializer.
public DataOutput getDataOutput(int initialCapacity) { return new StandardDataOutput(initialCapacity); }
- writeObject
@Override public DataOutput writeObject(Object object, Class type) { return writeObjectInternal(object,type,false); }
- writeObjectInternal
private DataOutput writeObjectInternal(Object object, Class type, boolean byteOrder) { if (supportsNullSerialization(type)) { AttributeSerializer s = getSerializer(type); if (byteOrder) ensureOrderPreserving(s,type).writeByteOrder(this,object); else s.write(this, object); } else { //write flag for null or not if (object==null) { putByte((byte)-1); } else { putByte((byte)0); writeObjectNotNullInternal(object,byteOrder); } } return this; }
- supportsNullSerialization
private boolean supportsNullSerialization(Class type) { return getSerializer(type) instanceof SupportsNullSerializer; }
When write a object, you must call getDataOutput to get a DataOutput object.
Then call writeObject method of DataOutput to write a object.
At last to get a StaticBuffer object by call getStaticBufferFlipBytes(int from, int to);
Meanwhile we call readObject method of StandardSerializer to read a object, pass StaticBuffer object as a parameter.
* Method readObject is a member of StandardSerializer.
public <T> T readObject(ScanBuffer buffer, Class<T> type) { return readObjectInternal(buffer,type,false); }