| TypeSerializer.java |
/* Copyright (C) 2009 CSE,IIT Bombay http://www.cse.iitb.ac.in
This file is part of the ConStore open source storage facility for concept-nets.
ConStore is free software and distributed under the
Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License;
you can copy, distribute and transmit the work
with the work attribution in the manner specified by the author or licensor.
You may not use this work for commercial purposes and may not alter,
transform, or build upon this work.
Please refer the legal code of the license, available at
http://creativecommons.org/licenses/by-nc-nd/3.0/legalcode
ConStore is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. */
package iitb.con.ds;
import iitb.con.core.Attribute;
import iitb.con.core.Entity;
import iitb.con.core.Relation;
import iitb.con.core.Type;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
/**
* TypeSerializer serializes <tt>Type</tt> to bytes and vice versa
*
* @author Prathab K
* @see Type
*/
public class TypeSerializer implements ItemSerializer<Type> {
/**
* Serializes <tt>Type</tt> to bytes
* @param type Type
* @return serialized <tt>Type</tt> as {@link ByteBuffer}
*/
public ByteBuffer serialize(Type type) {
int typeElementSize = computeSize(type);
ByteBuffer buf = ByteBuffer.allocate(typeElementSize);
//Type Element Size
buf.putInt(typeElementSize);
if(type instanceof Entity) {
buf.put((byte)0); //for category 0-entity; 1-relation
}else {
Relation r = (Relation) type;
buf.put((byte)1); //for category
buf.putShort(r.getLeftEntityId()); //left entity id
buf.putShort(r.getRightEntityId()); //right entity id
buf.put(r.getDirection()); //direction
if(r.leftRole != null) {
buf.putShort((short) r.leftRole.length()); //left role length
buf.put(r.leftRole.getBytes()); //left role length
}else{
buf.putShort((short)0);//left role length
}
if(r.rightRole != null) {
buf.putShort((short) r.rightRole.length()); //right role length
buf.put(r.rightRole.getBytes()); //right role length
}else{
buf.putShort((short)0);//right role length
}
}
buf.putShort(type.id); //type id
buf.putShort((short) type.name.length()); //type name length
buf.put(type.name.getBytes()); //type name
buf.putShort((short)type.getAttributesCount());
List<Attribute> attributes = type.getAllAttributes();
for(Attribute attribute : attributes) {
buf.putShort(attribute.id);
if(attribute.repeating)
buf.put((byte)1);
else
buf.put((byte)0);
buf.put(attribute.dataType);
//buf.put(attribute.position);
buf.putShort((short)attribute.name.length());
buf.put(attribute.name.getBytes());
if(attribute.defaultValue != null) {
buf.putShort((short)attribute.defaultValue.length());
buf.put(attribute.defaultValue.getBytes());
}else{
buf.putShort((short)0);
}
}
buf.rewind();
return buf;
}
/**
* Deserializes the given bytes as <tt>Type</tt>
* @param buf bytes as {@link ByteBuffer}
* @return deserialized bytes as <tt>Type</tt>
*/
public Type deSerialize(ByteBuffer buf) {
Type type = null;
//buf.position(0);
buf.getInt(); // getting the total element size
Byte b = buf.get();
if(b == 0) { // checking for category 0-entity; 1-relation
type = deSerializeEntityType(buf);
}else {
type = deSerializeRelationType(buf);
}
return type;
}
/**
* Deserializes the specified attribute to object value
* @param buf bytes as {@link ByteBuffer}
* @param name attribute name
* @return deserialized attribute value as <tt>Object</tt>
*/
public Object attributeDeSerialize(ByteBuffer buf, Object name) {
return null;
}
/**
* Deserializes the Entity type
* @param buf bytes as {@link ByteBuffer}
* @return Entity Type
* @see Entity
*/
private Type deSerializeEntityType(ByteBuffer buf) {
Entity type = new Entity("");
type.id = buf.getShort();
short size = buf.getShort();
byte[] tempBuf = new byte[size];
buf.get(tempBuf);
type.name = new String(tempBuf);
type.setAllAttributes(deSerializeAttributes(buf));
return type;
}
/**
* Deserializes the Relation type
* @param buf bytes as {@link ByteBuffer}
* @return Relation Type
* @see Relation
*/
private Type deSerializeRelationType(ByteBuffer buf) {
Relation type = new Relation("");
type.setLeftEntityId(buf.getShort());
type.setRightEntityId(buf.getShort());
type.setDirection(buf.get());
short size = buf.getShort();
byte[] tempBuf = new byte[size];
buf.get(tempBuf);
type.leftRole = new String(tempBuf);
size = buf.getShort();
tempBuf = new byte[size];
buf.get(tempBuf);
type.rightRole = new String(tempBuf);
type.id = buf.getShort();
size = buf.getShort();
tempBuf = new byte[size];
buf.get(tempBuf);
type.name = new String(tempBuf);
type.setAllAttributes(deSerializeAttributes(buf));
return type;
}
/**
* Deserializes the type attributes
* @param buf bytes as {@link ByteBuffer}
* @return Attribute List
* @see Attribute
*/
private List<Attribute> deSerializeAttributes(ByteBuffer buf) {
short attribute_count = buf.getShort();
List<Attribute> attributes = new ArrayList<Attribute>();
for(short i = 0; i < attribute_count ; i++ ) {
Attribute attribute = new Attribute();
attribute.id = buf.getShort();
if (buf.get() == 0)
attribute.repeating = false;
else
attribute.repeating = true;
attribute.dataType = buf.get();
//attribute.position = buf.get();
short size = buf.getShort();
byte[] tempBuf = new byte[size];
buf.get(tempBuf);
attribute.name = new String(tempBuf);
size = buf.getShort();
if(size > 0) {
tempBuf = new byte[size];
buf.get(tempBuf);
attribute.defaultValue = new String(tempBuf);
}
attributes.add(attribute);
}
return attributes;
}
/**
* Computes the size of the given Type in terms of bytes
* @param type Type
* @return size in bytes
*/
private int computeSize(Type type) {
int size = 0;
size += 2; // no. of attributes size
//id(2) + repeating(1) + data type(1) + position (1) + name size(2) + value(2) = 9 bytes
short attributeStaticHeaderSize = 9;
List<Attribute> attributes = type.getAllAttributes();
for(Attribute attribute : attributes) {
size += attribute.name.length();
if(attribute.defaultValue !=null)
size += attribute.defaultValue.length();
size += attributeStaticHeaderSize;
}
//type id(2) + type name size(2) = 4 bytes
size += 4;
size += type.name.length();
if(type instanceof Entity) {
size++; //for category
}else {
Relation r = (Relation) type;
//catg(1) + left entity id(2) + right entity id (2)
//direction(1) + left role size(2) + right role size(2) = 10 bytes
size += 10;
if(r.leftRole != null)
size += r.leftRole.length();
if(r.rightRole != null)
size += r.rightRole.length();
}
//for type element size (4 bytes)
size += 4;
return size;
}
}