package org.neo4j.rdf.fulltext;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
/**
* A helper class for dealing with fundamental types and nio, basically
* asking for size, putting into a byte buffer, reading from a byte buffer
* a.s.o. So instead of having:
*
* if ( cls.equals( Boolean.class ) )
* // buffer.put( .... )
* else if ( cls.equals( Integer.class ) )
* // buffer.putInt( .... )
*
* And have that in at least two places (when you deal with these things)
* you could instead use this util class to simplify things and reduce bugs
*/
public abstract class FundamentalTypeNioUtil
{
private static Map<Class<? extends Object>, FundamentalTypeNioUtil> byClass
= new HashMap<Class<? extends Object>, FundamentalTypeNioUtil>();
private static Map<Byte, FundamentalTypeNioUtil> byByteKey =
new HashMap<Byte, FundamentalTypeNioUtil>();
static
{
new BooleanType();
new CharacterType();
new ByteType();
new ShortType();
new IntegerType();
new LongType();
new FloatType();
new DoubleType();
new StringType();
}
private Class<? extends Object> cls;
private byte byteKey;
private FundamentalTypeNioUtil( Class<? extends Object> cls, byte byteKey )
{
this.cls = cls;
this.byteKey = byteKey;
byClass.put( cls, this );
byByteKey.put( byteKey, this );
}
public static FundamentalTypeNioUtil getInstance(
Class<? extends Object> cls )
{
if ( !byClass.containsKey( cls ) )
{
throw new IllegalArgumentException( "Invalid class " + cls );
}
return byClass.get( cls );
}
public static FundamentalTypeNioUtil getInstance( byte byteKey )
{
if ( !byByteKey.containsKey( byteKey ) )
{
throw new IllegalArgumentException( "Invalid byte key " + byteKey );
}
return byByteKey.get( byteKey );
}
public Class<? extends Object> typeClass()
{
return this.cls;
}
public byte byteKey()
{
return this.byteKey;
}
public abstract int size( Object value );
public abstract void putIntoByteBuffer( ByteBuffer buffer, Object value );
public abstract Object readFromByteBuffer( ByteBuffer buffer );
private static class BooleanType extends FundamentalTypeNioUtil
{
public BooleanType()
{
super( Boolean.class, ( byte ) 1 );
}
@Override
public void putIntoByteBuffer( ByteBuffer buffer, Object value )
{
byte byteValue = ( Boolean ) value ? ( byte ) 1 : ( byte ) 0;
buffer.put( byteValue );
}
@Override
public Object readFromByteBuffer( ByteBuffer buffer )
{
byte value = buffer.get();
return value != 0;
}
@Override
public int size( Object value )
{
return 1;
}
}
private static abstract class NumberType extends FundamentalTypeNioUtil
{
private int size;
public NumberType( Class<? extends Object> cls, byte byteKey,
int numberOfBits )
{
super( cls, byteKey );
this.size = numberOfBits / 8;
assert this.size > 0;
}
@Override
public int size( Object value )
{
return size;
}
}
private static class CharacterType extends NumberType
{
public CharacterType()
{
super( Character.class, ( byte ) 2, Character.SIZE );
}
@Override
public void putIntoByteBuffer( ByteBuffer buffer, Object value )
{
buffer.putChar( ( Character ) value );
}
@Override
public Object readFromByteBuffer( ByteBuffer buffer )
{
return buffer.getChar();
}
}
private static class ByteType extends NumberType
{
public ByteType()
{
super( Byte.class, ( byte ) 3, Byte.SIZE );
}
@Override
public void putIntoByteBuffer( ByteBuffer buffer, Object value )
{
buffer.put( ( ( Number ) value ).byteValue() );
}
@Override
public Object readFromByteBuffer( ByteBuffer buffer )
{
return buffer.get();
}
}
private static class ShortType extends NumberType
{
public ShortType()
{
super( Short.class, ( byte ) 4, Short.SIZE );
}
@Override
public void putIntoByteBuffer( ByteBuffer buffer, Object value )
{
buffer.putShort( ( ( Number ) value ).shortValue() );
}
@Override
public Object readFromByteBuffer( ByteBuffer buffer )
{
return buffer.getShort();
}
}
private static class IntegerType extends NumberType
{
public IntegerType()
{
super( Integer.class, ( byte ) 5, Integer.SIZE );
}
@Override
public void putIntoByteBuffer( ByteBuffer buffer, Object value )
{
buffer.putInt( ( ( Number ) value ).intValue() );
}
@Override
public Object readFromByteBuffer( ByteBuffer buffer )
{
return buffer.getInt();
}
}
private static class LongType extends NumberType
{
public LongType()
{
super( Long.class, ( byte ) 6, Long.SIZE );
}
@Override
public void putIntoByteBuffer( ByteBuffer buffer, Object value )
{
buffer.putLong( ( ( Number ) value ).longValue() );
}
@Override
public Object readFromByteBuffer( ByteBuffer buffer )
{
return buffer.getLong();
}
}
private static class FloatType extends NumberType
{
public FloatType()
{
super( Float.class, ( byte ) 7, Float.SIZE );
}
@Override
public void putIntoByteBuffer( ByteBuffer buffer, Object value )
{
buffer.putFloat( ( ( Number ) value ).floatValue() );
}
@Override
public Object readFromByteBuffer( ByteBuffer buffer )
{
return buffer.getFloat();
}
}
private static class DoubleType extends NumberType
{
public DoubleType()
{
super( Double.class, ( byte ) 8, Double.SIZE );
}
@Override
public void putIntoByteBuffer( ByteBuffer buffer, Object value )
{
buffer.putDouble( ( ( Number ) value ).doubleValue() );
}
@Override
public Object readFromByteBuffer( ByteBuffer buffer )
{
return buffer.getDouble();
}
}
private static class StringType extends FundamentalTypeNioUtil
{
public StringType()
{
super( String.class, ( byte ) 9 );
}
@Override
public void putIntoByteBuffer( ByteBuffer buffer, Object value )
{
String string = ( String ) value;
byte[] bytes = string.getBytes();
buffer.putInt( bytes.length );
buffer.put( bytes );
}
@Override
public Object readFromByteBuffer( ByteBuffer buffer )
{
int length = buffer.getInt();
byte[] bytes = new byte[ length ];
buffer.get( bytes );
return new String( bytes );
}
@Override
public int size( Object value )
{
return ( Integer.SIZE / 8 ) +
( ( String ) value ).getBytes().length;
}
}
}