package org.wonderdb.serialize; import java.sql.Types; import java.util.ArrayList; import java.util.List; import org.jboss.netty.buffer.ChannelBuffer; import org.wonderdb.types.BlockPtr; import org.wonderdb.types.BlockPtrList; import org.wonderdb.types.ByteArrayType; import org.wonderdb.types.DBType; import org.wonderdb.types.DoubleType; import org.wonderdb.types.FloatType; import org.wonderdb.types.IntType; import org.wonderdb.types.LongType; import org.wonderdb.types.SingleBlockPtr; import org.wonderdb.types.StringType; import org.wonderdb.types.TypeMetadata; public class DefaultSerializer implements TypeSerializer { public static DefaultSerializer instance = new DefaultSerializer(); public static final StringType NULL_STRING = new StringType(null); public static final IntType NULL_INT = new IntType(null); public static final LongType NULL_LONG = new LongType(null); public static final DoubleType NULL_DOUBLE = new DoubleType(null); public static final FloatType NULL_FLOAT = new FloatType(null); public static final BlockPtr NULL_BLKPTR = new SingleBlockPtr((byte) -1, -1); public static final BlockPtrList NULL_BLKPTRLIST = new BlockPtrList(null); public static final ByteArrayType NULL_BYTE_ARRAY = new ByteArrayType(null); private DefaultSerializer() { } public static DefaultSerializer getInstance() { return instance; } @Override public DBType unmarshal(int type, ChannelBuffer buffer, TypeMetadata meta) { switch (type) { case SerializerManager.STRING: case SerializerManager.BYTE_ARRAY_TYPE: int size = buffer.readInt(); byte[] bytes = new byte[size]; buffer.readBytes(bytes); if (type==SerializerManager.STRING) { return new StringType(new String(bytes)); } else { return new ByteArrayType(bytes); } case SerializerManager.INT: return new IntType(buffer.readInt()); case SerializerManager.LONG: return new LongType(buffer.readLong()); case SerializerManager.DOUBLE: return new DoubleType(buffer.readDouble()); case SerializerManager.FLOAT: return new FloatType(buffer.readFloat()); case SerializerManager.BLOCK_PTR: byte fileId = buffer.readByte(); long posn = buffer.readLong(); if (fileId < 0 || posn < 0) { return null; } return new SingleBlockPtr(fileId, posn); case SerializerManager.BLOCK_PTR_LIST_TYPE: int s = buffer.readInt(); List<BlockPtr> list = new ArrayList<BlockPtr>(s); for (int i = 0; i < s; i++) { BlockPtr ptr = (BlockPtr) unmarshal(SerializerManager.BLOCK_PTR, buffer, null); list.add(ptr); } return new BlockPtrList(list); default: return null; } } @Override public void toBytes(DBType object, ChannelBuffer buffer, TypeMetadata meta) { if (object instanceof StringType) { StringType s = (StringType) object; buffer.writeInt(s.get().getBytes().length); buffer.writeBytes(s.get().getBytes()); return; } if (object instanceof ByteArrayType) { ByteArrayType s = (ByteArrayType) object; buffer.writeInt(s.get().length); buffer.writeBytes(s.get()); return; } if (object instanceof IntType) { buffer.writeInt(((IntType) object).get()); return; } if (object instanceof LongType) { buffer.writeLong(((LongType) object).get()); return; } if (object instanceof DoubleType) { buffer.writeDouble(((DoubleType) object).get()); return; } if (object instanceof FloatType) { buffer.writeFloat(((FloatType) object).get()); return; } if (object instanceof BlockPtr) { BlockPtr p = (BlockPtr) object; buffer.writeByte(p.getFileId()); buffer.writeLong(p.getBlockPosn()); return; } if (object instanceof BlockPtrList) { BlockPtrList list = (BlockPtrList) object; buffer.writeInt(list.getPtrList().size()); for (int i = 0; i < list.getPtrList().size(); i++) { BlockPtr ptr = list.getPtrList().get(i); DefaultSerializer.getInstance().toBytes(ptr, buffer, null); } } } @Override public int getSize(DBType object, TypeMetadata meta) { if (object instanceof StringType) { String value = ((StringType) object).get(); return 1 + value.getBytes().length + Integer.SIZE/8; } if (object instanceof ByteArrayType) { byte[] array = ((ByteArrayType) object).get(); return 1 + array.length + Integer.SIZE/8; } if (object instanceof BlockPtr) { return 1+ 1 + Long.SIZE/8; } return 1+Long.SIZE/8; } @Override public boolean isNull(int type, DBType object) { switch (type) { case SerializerManager.STRING: return NULL_STRING.equals(object) || object == null; case SerializerManager.BYTE_ARRAY_TYPE: return NULL_BYTE_ARRAY.equals(object); case SerializerManager.INT: return NULL_INT.equals(object) || object == null; case SerializerManager.LONG: return NULL_LONG.equals(object) || object == null; case SerializerManager.DOUBLE: return NULL_DOUBLE.equals(object) || object == null; case SerializerManager.FLOAT: return NULL_FLOAT.equals(object) || object == null; case SerializerManager.BLOCK_PTR: return NULL_BLKPTR.equals(object) || object == null; case SerializerManager.BLOCK_PTR_LIST_TYPE: return NULL_BLKPTRLIST.equals(object) || object == null; default: return true; } } @Override public DBType getNull(int type) { return null; // switch (type) { // case SerializerManager.STRING: // return NULL_STRING; // case SerializerManager.INT: // return NULL_INT; // case SerializerManager.LONG: // return NULL_LONG; // case SerializerManager.DOUBLE: // return NULL_DOUBLE; // case SerializerManager.FLOAT: // return NULL_FLOAT; // case SerializerManager.BLOCK_PTR: // return NULL_BLKPTR; // case SerializerManager.BLOCK_PTR_LIST_TYPE: // return NULL_BLKPTRLIST; // default: // return null; // } } @Override public int getSQLType(int type) { switch (type) { case SerializerManager.STRING: return Types.VARCHAR; case SerializerManager.DOUBLE: return Types.DOUBLE; case SerializerManager.FLOAT: return Types.FLOAT; case SerializerManager.INT: return Types.INTEGER; case SerializerManager.LONG: return Types.NUMERIC; case SerializerManager.BYTE_ARRAY_TYPE: return Types.BINARY; default: return -1; } } @Override public DBType convert(int type, StringType st) { switch (type) { case SerializerManager.STRING: return st; case SerializerManager.DOUBLE: if (st == NULL_STRING) { return NULL_DOUBLE; } return new DoubleType(Double.parseDouble(st.get())); case SerializerManager.FLOAT: if (st == NULL_STRING) { return NULL_FLOAT; } return new FloatType(Float.parseFloat(st.get())); case SerializerManager.INT: if (st == NULL_STRING) { return NULL_FLOAT; } return new IntType(Integer.parseInt(st.get())); case SerializerManager.LONG: if (st == NULL_STRING) { return NULL_FLOAT; } return new LongType(Long.parseLong(st.get())); default: return null; } } }