All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.netflix.astyanax.serializers.AnnotatedCompositeSerializer Maven / Gradle / Ivy

There is a newer version: 3.10.2
Show newest version
package com.netflix.astyanax.serializers;

import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.netflix.astyanax.Serializer;
import com.netflix.astyanax.annotations.Component;
import com.netflix.astyanax.model.Equality;
import com.netflix.astyanax.model.RangeEndpoint;
import java.util.Arrays;

/**
 * Serializer for a Pojo annotated with Component field annotations
 * 
 * Serialized data is formatted as a list of components with each component
 * having the format: <2 byte length><0>
 * 
 * @author elandau
 * 
 * @param 
 */
public class AnnotatedCompositeSerializer extends AbstractSerializer {
    private static final byte       END_OF_COMPONENT    = 0;
    private static final ByteBuffer EMPTY_BYTE_BUFFER   = ByteBuffer.allocate(0);
    private static final int        DEFAULT_BUFFER_SIZE = 128;
    private static final int        COMPONENT_OVERHEAD  = 3;
    
    /**
     * Serializer for a single component within the Pojo
     * 
     * @author elandau
     * 
     * @param 

*/ public static class ComponentSerializer

implements Comparable> { private Field field; private Serializer

serializer; private int ordinal; public ComponentSerializer(Field field, Serializer

serializer, int ordinal) { this.field = field; this.field.setAccessible(true); this.serializer = serializer; this.ordinal = ordinal; } public Field getField() { return this.field; } public ByteBuffer serialize(Object obj) throws IllegalArgumentException, IllegalAccessException { Object value = field.get(obj); ByteBuffer buf = serializer.toByteBuffer((P) value); return buf; } public void deserialize(Object obj, ByteBuffer value) throws IllegalArgumentException, IllegalAccessException { field.set(obj, serializer.fromByteBuffer(value)); } public ByteBuffer serializeValue(Object value) { ByteBuffer buf = serializer.toByteBuffer((P) value); return buf; } @Override public int compareTo(ComponentSerializer other) { return this.ordinal - other.ordinal; } } private final List> components; private final Class clazz; private final int bufferSize; public AnnotatedCompositeSerializer(Class clazz, boolean includeParentFields) { this(clazz, DEFAULT_BUFFER_SIZE, includeParentFields); } public AnnotatedCompositeSerializer(Class clazz) { this(clazz, DEFAULT_BUFFER_SIZE, false); } public AnnotatedCompositeSerializer(Class clazz, int bufferSize) { this(clazz, bufferSize, false); } public AnnotatedCompositeSerializer(Class clazz, int bufferSize, boolean includeParentFields) { this.clazz = clazz; this.components = new ArrayList>(); this.bufferSize = bufferSize; for (Field field : getFields(clazz, includeParentFields)) { 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); } private List getFields(Class clazz, boolean recursively) { List allFields = new ArrayList(); if (clazz.getDeclaredFields() != null && clazz.getDeclaredFields().length > 0) { allFields.addAll(Arrays.asList(clazz.getDeclaredFields())); } if (recursively && clazz.getSuperclass() != null && !clazz.getSuperclass().equals(Object.class)) { allFields.addAll(getFields(clazz.getSuperclass(), true)); } return allFields; } @Override public ByteBuffer toByteBuffer(T obj) { ByteBuffer bb = ByteBuffer.allocate(bufferSize); for (ComponentSerializer serializer : components) { try { // First, serialize the ByteBuffer for this component ByteBuffer cb = serializer.serialize(obj); if (cb == null) { cb = ByteBuffer.allocate(0); } if (cb.limit() + COMPONENT_OVERHEAD > bb.remaining()) { int exponent = (int) Math.ceil(Math.log((double) (cb.limit() + COMPONENT_OVERHEAD + bb.limit())) / Math.log(2)); int newBufferSize = (int) Math.pow(2, exponent); ByteBuffer temp = ByteBuffer.allocate(newBufferSize); bb.flip(); temp.put(bb); bb = temp; } // Write the data: <0> bb.putShort((short) cb.remaining()); bb.put(cb.slice()); bb.put(END_OF_COMPONENT); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } bb.flip(); return bb; } @Override public T fromByteBuffer(ByteBuffer byteBuffer) { byteBuffer = byteBuffer.duplicate(); try { T obj = createContents(clazz); for (ComponentSerializer serializer : components) { ByteBuffer data = getWithShortLength(byteBuffer); if (data != null) { if (data.remaining() > 0) { serializer.deserialize(obj, data); } byte end_of_component = byteBuffer.get(); if (end_of_component != END_OF_COMPONENT) { throw new RuntimeException("Invalid composite column. Expected END_OF_COMPONENT."); } } else { throw new RuntimeException("Missing component data in composite type"); } } return obj; } catch (Exception e) { throw new RuntimeException(e); } } @Override public ComparatorType getComparatorType() { return ComparatorType.COMPOSITETYPE; } private static int getShortLength(ByteBuffer bb) { int length = (bb.get() & 0xFF) << 8; return length | (bb.get() & 0xFF); } private static ByteBuffer getWithShortLength(ByteBuffer bb) { int length = getShortLength(bb); return getBytes(bb, length); } private static ByteBuffer getBytes(ByteBuffer bb, int length) { ByteBuffer copy = bb.duplicate(); copy.limit(copy.position() + length); bb.position(bb.position() + length); return copy; } private static

ComponentSerializer

makeComponent(Field field, Serializer

serializer, int ordinal) { return new ComponentSerializer

(field, serializer, ordinal); } private T createContents(Class clazz) throws InstantiationException, IllegalAccessException { return clazz.newInstance(); } public CompositeRangeBuilder buildRange() { return new CompositeRangeBuilder() { private int position = 0; public void nextComponent() { position++; } public void append(ByteBufferOutputStream out, Object value, Equality equality) { ComponentSerializer serializer = components.get(position); // First, serialize the ByteBuffer for this component ByteBuffer cb; try { cb = serializer.serializeValue(value); } catch (Exception e) { throw new RuntimeException(e); } if (cb == null) { cb = EMPTY_BYTE_BUFFER; } // Write the data: <0> out.writeShort((short) cb.remaining()); out.write(cb.slice()); out.write(equality.toByte()); } }; } public RangeEndpoint makeEndpoint(T1 value, Equality equality) { RangeEndpoint endpoint = new RangeEndpoint() { private ByteBuffer out = ByteBuffer.allocate(bufferSize); private int position = 0; private boolean done = false; @Override public RangeEndpoint append(Object value, Equality equality) { ComponentSerializer serializer = components.get(position); position++; // First, serialize the ByteBuffer for this component ByteBuffer cb; try { cb = serializer.serializeValue(value); } catch (Exception e) { throw new RuntimeException(e); } if (cb == null) { cb = EMPTY_BYTE_BUFFER; } if (cb.limit() + COMPONENT_OVERHEAD > out.remaining()) { int exponent = (int) Math.ceil(Math.log((double) (cb.limit() + COMPONENT_OVERHEAD) / (double) out.limit()) / Math.log(2)); int newBufferSize = out.limit() * (int) Math.pow(2, exponent); ByteBuffer temp = ByteBuffer.allocate(newBufferSize); out.flip(); temp.put(out); out = temp; } // Write the data: <0> out.putShort((short) cb.remaining()); out.put(cb.slice()); out.put(equality.toByte()); return this; } @Override public ByteBuffer toBytes() { if (!done) { out.flip(); done = true; } return out; } }; endpoint.append(value, equality); return endpoint; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy