/** * Copyright (c) 2002-2013 "Neo Technology," * Network Engine for Objects in Lund AB [http://neotechnology.com] * * This file is part of Neo4j. * * Neo4j is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.neo4j.kernel.impl.nioneo.store; import org.neo4j.kernel.impl.util.Bits; /** * Defines valid property types. */ public enum PropertyType { BOOL( 1 ) { @Override public Object getValue( PropertyBlock block, PropertyStore store ) { return getValue( block.getSingleValueLong() ); } private Boolean getValue( long propBlock ) { return ( propBlock & 0x1 ) == 1 ? Boolean.TRUE : Boolean.FALSE; } @Override public PropertyData newPropertyData( PropertyBlock block, long propertyId, Object extractedValue ) { // TODO : The masking off of bits should not happen here return PropertyDatas.forBoolean( block.getKeyIndexId(), propertyId, getValue( block.getSingleValueLong() ).booleanValue() ); } }, BYTE( 2 ) { @Override public Object getValue( PropertyBlock block, PropertyStore store ) { return Byte.valueOf( (byte) block.getSingleValueByte() ); } @Override public PropertyData newPropertyData( PropertyBlock block, long propertyId, Object extractedValue ) { // TODO : The masking off of bits should not happen here return PropertyDatas.forByte( block.getKeyIndexId(), propertyId, block.getSingleValueByte() ); } }, SHORT( 3 ) { @Override public Object getValue( PropertyBlock block, PropertyStore store ) { return Short.valueOf( block.getSingleValueShort() ); } @Override public PropertyData newPropertyData( PropertyBlock block, long propertyId, Object extractedValue ) { // TODO : The masking off of bits should not happen here return PropertyDatas.forShort( block.getKeyIndexId(), propertyId, block.getSingleValueShort() ); } }, CHAR( 4 ) { @Override public Object getValue( PropertyBlock block, PropertyStore store ) { return Character.valueOf( (char) block.getSingleValueShort() ); } @Override public PropertyData newPropertyData( PropertyBlock block, long propertyId, Object extractedValue ) { // TODO : The masking off of bits should not happen here return PropertyDatas.forChar( block.getKeyIndexId(), propertyId, (char) block.getSingleValueShort() ); } }, INT( 5 ) { @Override public Object getValue( PropertyBlock block, PropertyStore store ) { return Integer.valueOf( block.getSingleValueInt() ); } @Override public PropertyData newPropertyData( PropertyBlock block, long propertyId, Object extractedValue ) { // TODO : The masking off of bits should not happen here return PropertyDatas.forInt( block.getKeyIndexId(), propertyId, block.getSingleValueInt() ); } }, LONG( 6 ) { @Override public Object getValue( PropertyBlock block, PropertyStore store ) { return Long.valueOf( getLongValue( block ) ); } private long getLongValue( PropertyBlock block ) { long firstBlock = block.getSingleValueBlock(); return valueIsInlined( firstBlock ) ? (block.getSingleValueLong() >>> 1) : block.getValueBlocks()[1]; } @Override public PropertyData newPropertyData( PropertyBlock block, long propertyId, Object extractedValue ) { return PropertyDatas.forLong( block.getKeyIndexId(), propertyId, getLongValue( block ) ); } private boolean valueIsInlined( long firstBlock ) { // [][][][][ i,tttt][kkkk,kkkk][kkkk,kkkk][kkkk,kkkk] return (firstBlock & 0x10000000L) > 0; } @Override public int calculateNumberOfBlocksUsed( long firstBlock ) { return valueIsInlined( firstBlock ) ? 1 : 2; } }, FLOAT( 7 ) { @Override public Object getValue( PropertyBlock block, PropertyStore store ) { return Float.valueOf( getValue( block.getSingleValueInt() ) ); } private float getValue( int propBlock ) { return Float.intBitsToFloat( (int) propBlock ); } @Override public PropertyData newPropertyData( PropertyBlock block, long propertyId, Object extractedValue ) { return PropertyDatas.forFloat( block.getKeyIndexId(), propertyId, getValue( block.getSingleValueInt() ) ); } }, DOUBLE( 8 ) { @Override public Object getValue( PropertyBlock block, PropertyStore store ) { return Double.valueOf( getValue( block.getValueBlocks()[1] ) ); } private double getValue( long propBlock ) { return Double.longBitsToDouble( propBlock ); } @Override public PropertyData newPropertyData( PropertyBlock block, long propertyId, Object extractedValue ) { return PropertyDatas.forDouble( block.getKeyIndexId(), propertyId, getValue( block.getValueBlocks()[1] ) ); } @Override public int calculateNumberOfBlocksUsed( long firstBlock ) { return 2; } }, STRING( 9 ) { @Override public Object getValue( PropertyBlock block, PropertyStore store ) { if ( store == null ) return null; return store.getStringFor( block ); } @Override public PropertyData newPropertyData( PropertyBlock block, long propertyId, Object extractedValue ) { return PropertyDatas.forStringOrArray( block.getKeyIndexId(), propertyId, extractedValue ); } }, ARRAY( 10 ) { @Override public Object getValue( PropertyBlock block, PropertyStore store ) { if ( store == null ) return null; return store.getArrayFor( block ); } @Override public PropertyData newPropertyData( PropertyBlock block, long propertyId, Object extractedValue ) { return PropertyDatas.forStringOrArray( block.getKeyIndexId(), propertyId, extractedValue ); } }, SHORT_STRING( 11 ) { @Override public Object getValue( PropertyBlock block, PropertyStore store ) { return LongerShortString.decode( block ); } @Override public PropertyData newPropertyData( PropertyBlock block, long propertyId, Object extractedValue ) { return PropertyDatas.forStringOrArray( block.getKeyIndexId(), propertyId, getValue( block, null ) ); } @Override public int calculateNumberOfBlocksUsed( long firstBlock ) { return LongerShortString.calculateNumberOfBlocksUsed( firstBlock ); } }, SHORT_ARRAY( 12 ) { @Override public Object getValue( PropertyBlock block, PropertyStore store ) { return ShortArray.decode( block ); } @Override public PropertyData newPropertyData( PropertyBlock block, long propertyId, Object extractedValue ) { return PropertyDatas.forStringOrArray( block.getKeyIndexId(), propertyId, getValue( block, null ) ); } @Override public int calculateNumberOfBlocksUsed( long firstBlock ) { return ShortArray.calculateNumberOfBlocksUsed( firstBlock ); } }; private final int type; // TODO In wait of a better place private static int payloadSize = PropertyStore.DEFAULT_PAYLOAD_SIZE; PropertyType( int type ) { this.type = type; } /** * Returns an int value representing the type. * * @return The int value for this property type */ public int intValue() { return type; } /** * Returns a byte value representing the type. As long as there are * < 128 PropertyTypes, this should be equal to intValue(). When this * statement no longer holds, this method should be removed. * * @return The byte value for this property type */ public byte byteValue() { return (byte) type; } public abstract Object getValue( PropertyBlock block, PropertyStore store ); public abstract PropertyData newPropertyData( PropertyBlock block, long propertyId, Object extractedValue ); public static PropertyType getPropertyType( long propBlock, boolean nullOnIllegal ) { // [][][][][ ,tttt][kkkk,kkkk][kkkk,kkkk][kkkk,kkkk] int type = (int)((propBlock&0x000000000F000000L)>>24); switch ( type ) { case 1: return BOOL; case 2: return BYTE; case 3: return SHORT; case 4: return CHAR; case 5: return INT; case 6: return LONG; case 7: return FLOAT; case 8: return DOUBLE; case 9: return STRING; case 10: return ARRAY; case 11: return SHORT_STRING; case 12: return SHORT_ARRAY; default: if (nullOnIllegal) return null; throw new InvalidRecordException( "Unknown property type for type " + type ); } } public static void main( String[] args ) { System.out.println( Bits.bits( 8 ).put( (long)-78 ) ); } // TODO In wait of a better place public static int getPayloadSize() { return payloadSize; } // TODO In wait of a better place public static int getPayloadSizeLongs() { return payloadSize >>> 3; } // TODO In wait of a better place public static void setPayloadSize( int newPayloadSize ) { if ( newPayloadSize%8 != 0 ) { throw new RuntimeException( "Payload must be divisible by 8" ); } payloadSize = newPayloadSize; } public int calculateNumberOfBlocksUsed( long firstBlock ) { return 1; } }