package uk.ac.imperial.lsds.seep.api.data; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.Random; import uk.ac.imperial.lsds.seep.errors.SchemaException; public abstract class Type { public final static int SIZE_OVERHEAD = Integer.BYTES; public abstract String toString(); public abstract void write(ByteBuffer buffer, Object o); public abstract Object read(ByteBuffer buffer); public abstract int sizeOf(Object o); public abstract boolean isVariableSize(); public abstract Object defaultValue(); public abstract Object randomValue(); private static Random rnd = new Random(); public boolean equals(Type t) { return this.toString().equals(t.toString()); } public enum JavaType{ BYTE, SHORT, INT, LONG, STRING, BYTES, FLOAT, DOUBLE } public static final Type BYTE = new Type() { public String toString(){ return "BYTE"; } @Override public void write(ByteBuffer buffer, Object o) { buffer.put((byte)o); } @Override public Object read(ByteBuffer buffer) { Object o = buffer.get(); return o; } @Override public int sizeOf(Object o) { return Byte.BYTES; } @Override public boolean isVariableSize() { return false; } @Override public Object defaultValue() { return (byte)0; } @Override public Object randomValue() { return (byte)(rnd.nextInt()); } }; public static final Type SHORT = new Type() { public String toString(){ return "SHORT"; } @Override public void write(ByteBuffer buffer, Object o) { buffer.putShort((short)o); } @Override public Object read(ByteBuffer buffer) { Object o = buffer.getShort(); return o; } @Override public int sizeOf(Object o) { return Short.BYTES; } @Override public boolean isVariableSize() { return false; } @Override public Object defaultValue() { return (short)0; } @Override public Object randomValue() { return (short)(rnd.nextInt()); } }; public static final Type INT = new Type() { public String toString(){ return "INT"; } @Override public void write(ByteBuffer buffer, Object o) { buffer.putInt((int)o); } @Override public Object read(ByteBuffer buffer) { return buffer.getInt(); } @Override public int sizeOf(Object o) { return Integer.BYTES; } @Override public boolean isVariableSize() { return false; } @Override public Object defaultValue() { return 0; } @Override public Object randomValue() { return (int)(rnd.nextInt()); } }; public static final Type LONG = new Type() { public String toString(){ return "LONG"; } @Override public Object read(ByteBuffer buffer) { return buffer.getLong(); } @Override public void write(ByteBuffer buffer, Object o) { buffer.putLong((long)o); } @Override public int sizeOf(Object o) { return Long.BYTES; } @Override public boolean isVariableSize() { return false; } @Override public Object defaultValue() { return (long)0L; } @Override public Object randomValue() { return (long)(rnd.nextLong()); } }; public static final Type STRING = new Type(){ public String toString(){ return "STRING"; } @Override public Object read(ByteBuffer buffer) { int length = buffer.getInt(); byte[] bytes = new byte[length]; buffer.get(bytes); String str = null; try { str = new String(bytes, "UTF8"); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return str; } @Override public void write(ByteBuffer buffer, Object o) { byte[] bytes = null; try { bytes = ((String)o).getBytes("UTF8"); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (bytes.length > Integer.MAX_VALUE) throw new SchemaException("A string or charsequence cannot be longer than Integer.MAX_VALUE"); buffer.putInt((int) bytes.length); buffer.put(bytes); } @Override public int sizeOf(Object o) { return Integer.BYTES + uk.ac.imperial.lsds.seep.util.Utils.utf8Length((String)o); } @Override public boolean isVariableSize() { return true; } @Override public Object defaultValue() { return "string"; } @Override public Object randomValue() { return new Integer((rnd.nextInt())).toString(); } }; public static final Type SHORTSTRING = new Type(){ private final int maxSize = 64; // bytes @Override public String toString() { return "SHORTSTRING"; } @Override public void write(ByteBuffer buffer, Object o) { // TODO; } @Override public Object read(ByteBuffer buffer) { // TODO: return null; } @Override public int sizeOf(Object o) { return maxSize; } @Override public boolean isVariableSize() { return false; } @Override public Object defaultValue() { return "string"; } @Override public Object randomValue() { return new Integer((rnd.nextInt())).toString(); } }; public static final Type BYTES = new Type() { public String toString(){ return "BYTES"; } @Override public Object read(ByteBuffer buffer) { // int size = buffer.getInt(); // ByteBuffer val = buffer.slice(); // val.limit(size); // buffer.position(buffer.position() + size); // return val; int length = buffer.getInt(); byte[] bytes = new byte[length]; buffer.get(bytes); return bytes; } @Override public void write(ByteBuffer buffer, Object o) { // ByteBuffer arg = (ByteBuffer) o; // int pos = arg.position(); // buffer.putInt(arg.remaining()); // buffer.put(arg); // arg.position(pos); byte[] bytes = (byte[]) o; buffer.putInt(bytes.length); buffer.put(bytes); } @Override public int sizeOf(Object o) { // ByteBuffer buffer = (ByteBuffer) o; // return Integer.BYTES + buffer.remaining(); byte[] bytes = (byte[]) o; return Integer.BYTES + bytes.length; } @Override public boolean isVariableSize() { return true; } @Override public Object defaultValue() { return new byte[1]; } @Override public Object randomValue() { return new byte[1]; } }; public static final Type FLOAT = new Type() { public String toString(){ return "FLOAT"; } @Override public void write(ByteBuffer buffer, Object o) { buffer.putFloat((float)o); } @Override public Object read(ByteBuffer buffer) { return buffer.getFloat(); } @Override public int sizeOf(Object o) { return Float.BYTES; } @Override public boolean isVariableSize() { return false; } @Override public Object defaultValue() { return 0.0f; } @Override public Object randomValue() { return (float)(rnd.nextFloat()); } }; public static final Type DOUBLE = new Type() { public String toString(){ return "DOUBLE"; } @Override public void write(ByteBuffer buffer, Object o) { buffer.putDouble((double)o); } @Override public Object read(ByteBuffer buffer) { return buffer.getDouble(); } @Override public int sizeOf(Object o) { return Double.BYTES; } @Override public boolean isVariableSize() { return false; } @Override public Object defaultValue() { return 0.0d; } @Override public Object randomValue() { return (double)(rnd.nextDouble()); } }; }