Skip to content

Instantly share code, notes, and snippets.

Created September 16, 2013 18:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/dabd7fa2852a51a6d445 to your computer and use it in GitHub Desktop.
Save anonymous/dabd7fa2852a51a6d445 to your computer and use it in GitHub Desktop.
/**
* A utility serializer for data to be backwards compatible with Pelops. Use {@link AnnotatedCompositeSerializer} for all new daos.
* Of course, a closer look to the implementation of the AbstractCompositeSerializerPelopsCompatible reveals it is very error prone as it doesn't store
* object sizes, so, for example, a Composite key with two String keys will not be able to be deserialized.
* @param <T>
*/
public class AbstractCompositeSerializerPelopsCompatible<T> extends AnnotatedCompositeSerializer<T> {
private static final Integer READ_THE_REST = -1;
private final List<ComponentSerializer<?>> components;
private final Class<T> clazz;
public AbstractCompositeSerializerPelopsCompatible(Class<T> clazz) {
super(clazz);
this.clazz = clazz;
this.components = new ArrayList<ComponentSerializer<?>>();
for (Field field : ReflUtils.getAllDeclaredFields(clazz, true)) {
Component annotation = field.getAnnotation(Component.class);
if (annotation != null) {
Serializer s = SerializerTypeInferer.getSerializer(field.getType());
components.add(makeComponent(field, s, annotation.ordinal()));
}
}
Collections.sort(this.components);
}
@Override
public ByteBuffer toByteBuffer(T obj) {
int totalSize = 0;
List<ByteBuffer> buffList = new ArrayList<ByteBuffer>(components.size());
for (ComponentSerializer<?> serializer : components) {
try {
// First, serialize the ByteBuffer for this component
ByteBuffer cb = serializer.serialize(obj);
if (cb == null) {
cb = ByteBuffer.allocate(0);
}
totalSize += cb.capacity();
buffList.add(cb);
} catch (Exception ex) {
throw new RuntimeException("Could not convert obj to bytebuffer", ex);
}
}
ByteBuffer bb = ByteBuffer.allocate(totalSize);
for (ByteBuffer buff : buffList) {
bb.put(buff);
}
bb.flip();
return bb;
}
@Override
public T fromByteBuffer(ByteBuffer byteBuffer) {
byteBuffer = byteBuffer.duplicate();
try {
T obj = createContents(clazz);
for (ComponentSerializer<?> serializer : components) {
int bytesToRead = getByteSizeOf(serializer.getField().getType());
if (READ_THE_REST.equals(bytesToRead)) {
bytesToRead = byteBuffer.remaining();
}
ByteBuffer data = getBytes(byteBuffer, bytesToRead);
if (data != null) {
serializer.deserialize(obj, data);
} else {
throw new RuntimeException("Missing component data in composite type");
}
}
return obj;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static int getByteSizeOf(final Class<?> clazz) {
Class<?> classToCheck = clazz;
if (clazz.isPrimitive()) {
classToCheck = ClassUtils.primitiveToWrapper(clazz);
}
if (classToCheck.equals(Integer.class)) {
return Integer.SIZE / Byte.SIZE;
} else if (classToCheck.equals(Long.class)) {
return Long.SIZE / Byte.SIZE;
} else if (classToCheck.equals(UUID.class)) {
return (Long.SIZE + Long.SIZE) / Byte.SIZE;
} else if (classToCheck.equals(Boolean.class)) {
return 1;
} else if (classToCheck.equals(String.class)) {
return READ_THE_REST;
} else {
throw new RuntimeException("Unsupported conversion type " + clazz);
}
}
private T createContents(Class<T> clazz) throws InstantiationException, IllegalAccessException {
return clazz.newInstance();
}
private static <P> ComponentSerializer<P> makeComponent(Field field, Serializer<P> serializer, int ordinal) {
return new ComponentSerializer<P>(field, serializer, ordinal);
}
private static int getShortLength(ByteBuffer bb) {
int length = (bb.get() & 0xFF) << 8;
return length | (bb.get() & 0xFF);
}
private static ByteBuffer getBytes(ByteBuffer bb, int length) {
ByteBuffer copy = bb.duplicate();
copy.limit(copy.position() + length);
bb.position(bb.position() + length);
return copy;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment