EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.mvstore.type]

COVERAGE SUMMARY FOR SOURCE FILE [ObjectDataType.java]

nameclass, %method, %block, %line, %
ObjectDataType.java100% (18/18)97%  (104/107)95%  (2783/2937)96%  (643/670)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ObjectDataType$AutoDetectDataType100% (1/1)62%  (5/8)60%  (51/85)67%  (14/21)
read (ByteBuffer): Object 0%   (0/1)0%   (0/6)0%   (0/1)
read (ByteBuffer, Object [], int, boolean): void 0%   (0/1)0%   (0/14)0%   (0/3)
write (WriteBuffer, Object [], int, boolean): void 0%   (0/1)0%   (0/14)0%   (0/3)
ObjectDataType$AutoDetectDataType (ObjectDataType, int): void 100% (1/1)100% (9/9)100% (4/4)
compare (Object, Object): int 100% (1/1)100% (24/24)100% (6/6)
getMemory (Object): int 100% (1/1)100% (6/6)100% (1/1)
getType (Object): ObjectDataType$AutoDetectDataType 100% (1/1)100% (5/5)100% (1/1)
write (WriteBuffer, Object): void 100% (1/1)100% (7/7)100% (2/2)
     
class ObjectDataType$SerializedObjectType100% (1/1)100% (5/5)79%  (116/146)78%  (29/37)
compare (Object, Object): int 100% (1/1)65%  (46/71)65%  (11/17)
write (WriteBuffer, Object): void 100% (1/1)88%  (35/40)78%  (7/9)
ObjectDataType$SerializedObjectType (ObjectDataType): void 100% (1/1)100% (8/8)100% (3/3)
getMemory (Object): int 100% (1/1)100% (14/14)100% (4/4)
read (ByteBuffer, int): Object 100% (1/1)100% (13/13)100% (4/4)
     
class ObjectDataType100% (1/1)100% (19/19)91%  (569/622)95%  (126/133)
deserialize (byte []): Object 100% (1/1)46%  (13/28)60%  (3/5)
serialize (Object): byte [] 100% (1/1)52%  (15/29)67%  (4/6)
newType (int): ObjectDataType$AutoDetectDataType 100% (1/1)88%  (82/93)94%  (17/18)
read (ByteBuffer): Object 100% (1/1)89%  (87/98)97%  (30/31)
compareNotNull (byte [], byte []): int 100% (1/1)96%  (45/47)89%  (8/9)
<static initializer> 100% (1/1)100% (106/106)100% (6/6)
ObjectDataType (): void 100% (1/1)100% (9/9)100% (3/3)
compare (Object, Object): int 100% (1/1)100% (6/6)100% (1/1)
getCommonClassId (Class): Integer 100% (1/1)100% (28/28)100% (5/5)
getMemory (Object): int 100% (1/1)100% (5/5)100% (1/1)
getTypeId (Object): int 100% (1/1)100% (77/77)100% (31/31)
isArray (Object): boolean 100% (1/1)100% (10/10)100% (1/1)
isBigDecimal (Object): boolean 100% (1/1)100% (11/11)100% (1/1)
isBigInteger (Object): boolean 100% (1/1)100% (11/11)100% (1/1)
isDate (Object): boolean 100% (1/1)100% (11/11)100% (1/1)
read (ByteBuffer, Object [], int, boolean): void 100% (1/1)100% (14/14)100% (3/3)
switchType (Object): ObjectDataType$AutoDetectDataType 100% (1/1)100% (19/19)100% (5/5)
write (WriteBuffer, Object [], int, boolean): void 100% (1/1)100% (14/14)100% (3/3)
write (WriteBuffer, Object): void 100% (1/1)100% (6/6)100% (2/2)
     
class ObjectDataType$NullType100% (1/1)100% (5/5)96%  (44/46)94%  (15/16)
compare (Object, Object): int 100% (1/1)89%  (17/19)86%  (6/7)
ObjectDataType$NullType (ObjectDataType): void 100% (1/1)100% (5/5)100% (2/2)
getMemory (Object): int 100% (1/1)100% (8/8)100% (1/1)
read (ByteBuffer, int): Object 100% (1/1)100% (2/2)100% (1/1)
write (WriteBuffer, Object): void 100% (1/1)100% (12/12)100% (5/5)
     
class ObjectDataType$ObjectArrayType100% (1/1)100% (5/5)96%  (795/830)98%  (159/163)
read (ByteBuffer, int): Object 100% (1/1)82%  (163/198)90%  (36/40)
ObjectDataType$ObjectArrayType (ObjectDataType): void 100% (1/1)100% (10/10)100% (3/3)
compare (Object, Object): int 100% (1/1)100% (279/279)100% (51/51)
getMemory (Object): int 100% (1/1)100% (126/126)100% (27/27)
write (WriteBuffer, Object): void 100% (1/1)100% (217/217)100% (42/42)
     
class ObjectDataType$BigDecimalType100% (1/1)100% (5/5)100% (152/152)100% (39/39)
ObjectDataType$BigDecimalType (ObjectDataType): void 100% (1/1)100% (5/5)100% (2/2)
compare (Object, Object): int 100% (1/1)100% (21/21)100% (5/5)
getMemory (Object): int 100% (1/1)100% (9/9)100% (1/1)
read (ByteBuffer, int): Object 100% (1/1)100% (42/42)100% (12/12)
write (WriteBuffer, Object): void 100% (1/1)100% (75/75)100% (19/19)
     
class ObjectDataType$BigIntegerType100% (1/1)100% (5/5)100% (116/116)100% (30/30)
ObjectDataType$BigIntegerType (ObjectDataType): void 100% (1/1)100% (5/5)100% (2/2)
compare (Object, Object): int 100% (1/1)100% (21/21)100% (5/5)
getMemory (Object): int 100% (1/1)100% (9/9)100% (1/1)
read (ByteBuffer, int): Object 100% (1/1)100% (25/25)100% (8/8)
write (WriteBuffer, Object): void 100% (1/1)100% (56/56)100% (14/14)
     
class ObjectDataType$BooleanType100% (1/1)100% (5/5)100% (64/64)100% (15/15)
ObjectDataType$BooleanType (ObjectDataType): void 100% (1/1)100% (5/5)100% (2/2)
compare (Object, Object): int 100% (1/1)100% (21/21)100% (5/5)
getMemory (Object): int 100% (1/1)100% (9/9)100% (1/1)
read (ByteBuffer, int): Object 100% (1/1)100% (7/7)100% (1/1)
write (WriteBuffer, Object): void 100% (1/1)100% (22/22)100% (6/6)
     
class ObjectDataType$ByteType100% (1/1)100% (5/5)100% (58/58)100% (15/15)
ObjectDataType$ByteType (ObjectDataType): void 100% (1/1)100% (5/5)100% (2/2)
compare (Object, Object): int 100% (1/1)100% (21/21)100% (5/5)
getMemory (Object): int 100% (1/1)100% (9/9)100% (1/1)
read (ByteBuffer, int): Object 100% (1/1)100% (4/4)100% (1/1)
write (WriteBuffer, Object): void 100% (1/1)100% (19/19)100% (6/6)
     
class ObjectDataType$CharacterType100% (1/1)100% (5/5)100% (58/58)100% (15/15)
ObjectDataType$CharacterType (ObjectDataType): void 100% (1/1)100% (5/5)100% (2/2)
compare (Object, Object): int 100% (1/1)100% (21/21)100% (5/5)
getMemory (Object): int 100% (1/1)100% (9/9)100% (1/1)
read (ByteBuffer, int): Object 100% (1/1)100% (4/4)100% (1/1)
write (WriteBuffer, Object): void 100% (1/1)100% (19/19)100% (6/6)
     
class ObjectDataType$DateType100% (1/1)100% (5/5)100% (64/64)100% (17/17)
ObjectDataType$DateType (ObjectDataType): void 100% (1/1)100% (5/5)100% (2/2)
compare (Object, Object): int 100% (1/1)100% (21/21)100% (5/5)
getMemory (Object): int 100% (1/1)100% (9/9)100% (1/1)
read (ByteBuffer, int): Object 100% (1/1)100% (8/8)100% (2/2)
write (WriteBuffer, Object): void 100% (1/1)100% (21/21)100% (7/7)
     
class ObjectDataType$DoubleType100% (1/1)100% (5/5)100% (115/115)100% (29/29)
ObjectDataType$DoubleType (ObjectDataType): void 100% (1/1)100% (5/5)100% (2/2)
compare (Object, Object): int 100% (1/1)100% (21/21)100% (5/5)
getMemory (Object): int 100% (1/1)100% (9/9)100% (1/1)
read (ByteBuffer, int): Object 100% (1/1)100% (18/18)100% (5/5)
write (WriteBuffer, Object): void 100% (1/1)100% (62/62)100% (16/16)
     
class ObjectDataType$FloatType100% (1/1)100% (5/5)100% (106/106)100% (27/27)
ObjectDataType$FloatType (ObjectDataType): void 100% (1/1)100% (5/5)100% (2/2)
compare (Object, Object): int 100% (1/1)100% (21/21)100% (5/5)
getMemory (Object): int 100% (1/1)100% (9/9)100% (1/1)
read (ByteBuffer, int): Object 100% (1/1)100% (18/18)100% (5/5)
write (WriteBuffer, Object): void 100% (1/1)100% (53/53)100% (14/14)
     
class ObjectDataType$IntegerType100% (1/1)100% (5/5)100% (119/119)100% (27/27)
ObjectDataType$IntegerType (ObjectDataType): void 100% (1/1)100% (5/5)100% (2/2)
compare (Object, Object): int 100% (1/1)100% (21/21)100% (5/5)
getMemory (Object): int 100% (1/1)100% (9/9)100% (1/1)
read (ByteBuffer, int): Object 100% (1/1)100% (20/20)100% (5/5)
write (WriteBuffer, Object): void 100% (1/1)100% (64/64)100% (14/14)
     
class ObjectDataType$LongType100% (1/1)100% (5/5)100% (136/136)100% (31/31)
ObjectDataType$LongType (ObjectDataType): void 100% (1/1)100% (5/5)100% (2/2)
compare (Object, Object): int 100% (1/1)100% (21/21)100% (5/5)
getMemory (Object): int 100% (1/1)100% (9/9)100% (1/1)
read (ByteBuffer, int): Object 100% (1/1)100% (21/21)100% (5/5)
write (WriteBuffer, Object): void 100% (1/1)100% (80/80)100% (18/18)
     
class ObjectDataType$ShortType100% (1/1)100% (5/5)100% (58/58)100% (15/15)
ObjectDataType$ShortType (ObjectDataType): void 100% (1/1)100% (5/5)100% (2/2)
compare (Object, Object): int 100% (1/1)100% (21/21)100% (5/5)
getMemory (Object): int 100% (1/1)100% (9/9)100% (1/1)
read (ByteBuffer, int): Object 100% (1/1)100% (4/4)100% (1/1)
write (WriteBuffer, Object): void 100% (1/1)100% (19/19)100% (6/6)
     
class ObjectDataType$StringType100% (1/1)100% (5/5)100% (89/89)100% (22/22)
ObjectDataType$StringType (ObjectDataType): void 100% (1/1)100% (5/5)100% (2/2)
compare (Object, Object): int 100% (1/1)100% (17/17)100% (3/3)
getMemory (Object): int 100% (1/1)100% (15/15)100% (3/3)
read (ByteBuffer, int): Object 100% (1/1)100% (15/15)100% (4/4)
write (WriteBuffer, Object): void 100% (1/1)100% (37/37)100% (10/10)
     
class ObjectDataType$UUIDType100% (1/1)100% (5/5)100% (73/73)100% (18/18)
ObjectDataType$UUIDType (ObjectDataType): void 100% (1/1)100% (5/5)100% (2/2)
compare (Object, Object): int 100% (1/1)100% (21/21)100% (5/5)
getMemory (Object): int 100% (1/1)100% (9/9)100% (1/1)
read (ByteBuffer, int): Object 100% (1/1)100% (12/12)100% (2/2)
write (WriteBuffer, Object): void 100% (1/1)100% (26/26)100% (8/8)

1/*
2 * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
3 * and the EPL 1.0 (http://h2database.com/html/license.html).
4 * Initial Developer: H2 Group
5 */
6package org.h2.mvstore.type;
7 
8import java.io.ByteArrayInputStream;
9import java.io.ByteArrayOutputStream;
10import java.io.ObjectInputStream;
11import java.io.ObjectOutputStream;
12import java.lang.reflect.Array;
13import java.math.BigDecimal;
14import java.math.BigInteger;
15import java.nio.ByteBuffer;
16import java.util.Arrays;
17import java.util.Date;
18import java.util.HashMap;
19import java.util.UUID;
20import org.h2.mvstore.DataUtils;
21import org.h2.mvstore.WriteBuffer;
22import org.h2.util.New;
23 
24/**
25 * A data type implementation for the most common data types, including
26 * serializable objects.
27 */
28public class ObjectDataType implements DataType {
29 
30    /**
31     * The type constants are also used as tag values.
32     */
33    static final int TYPE_NULL = 0;
34    static final int TYPE_BOOLEAN = 1;
35    static final int TYPE_BYTE = 2;
36    static final int TYPE_SHORT = 3;
37    static final int TYPE_INT = 4;
38    static final int TYPE_LONG = 5;
39    static final int TYPE_BIG_INTEGER = 6;
40    static final int TYPE_FLOAT = 7;
41    static final int TYPE_DOUBLE = 8;
42    static final int TYPE_BIG_DECIMAL = 9;
43    static final int TYPE_CHAR = 10;
44    static final int TYPE_STRING = 11;
45    static final int TYPE_UUID = 12;
46    static final int TYPE_DATE = 13;
47    static final int TYPE_ARRAY = 14;
48    static final int TYPE_SERIALIZED_OBJECT = 19;
49 
50    /**
51     * For very common values (e.g. 0 and 1) we save space by encoding the value
52     * in the tag. e.g. TAG_BOOLEAN_TRUE and TAG_FLOAT_0.
53     */
54    static final int TAG_BOOLEAN_TRUE = 32;
55    static final int TAG_INTEGER_NEGATIVE = 33;
56    static final int TAG_INTEGER_FIXED = 34;
57    static final int TAG_LONG_NEGATIVE = 35;
58    static final int TAG_LONG_FIXED = 36;
59    static final int TAG_BIG_INTEGER_0 = 37;
60    static final int TAG_BIG_INTEGER_1 = 38;
61    static final int TAG_BIG_INTEGER_SMALL = 39;
62    static final int TAG_FLOAT_0 = 40;
63    static final int TAG_FLOAT_1 = 41;
64    static final int TAG_FLOAT_FIXED = 42;
65    static final int TAG_DOUBLE_0 = 43;
66    static final int TAG_DOUBLE_1 = 44;
67    static final int TAG_DOUBLE_FIXED = 45;
68    static final int TAG_BIG_DECIMAL_0 = 46;
69    static final int TAG_BIG_DECIMAL_1 = 47;
70    static final int TAG_BIG_DECIMAL_SMALL = 48;
71    static final int TAG_BIG_DECIMAL_SMALL_SCALED = 49;
72 
73    /**
74     * For small-values/small-arrays, we encode the value/array-length in the
75     * tag.
76     */
77    static final int TAG_INTEGER_0_15 = 64;
78    static final int TAG_LONG_0_7 = 80;
79    static final int TAG_STRING_0_15 = 88;
80    static final int TAG_BYTE_ARRAY_0_15 = 104;
81 
82    /**
83     * Constants for floating point synchronization.
84     */
85    static final int FLOAT_ZERO_BITS = Float.floatToIntBits(0.0f);
86    static final int FLOAT_ONE_BITS = Float.floatToIntBits(1.0f);
87    static final long DOUBLE_ZERO_BITS = Double.doubleToLongBits(0.0d);
88    static final long DOUBLE_ONE_BITS = Double.doubleToLongBits(1.0d);
89 
90    static final Class<?>[] COMMON_CLASSES = { boolean.class, byte.class,
91            short.class, char.class, int.class, long.class, float.class,
92            double.class, Object.class, Boolean.class, Byte.class, Short.class,
93            Character.class, Integer.class, Long.class, BigInteger.class,
94            Float.class, Double.class, BigDecimal.class, String.class,
95            UUID.class, Date.class };
96 
97    private static final HashMap<Class<?>, Integer> COMMON_CLASSES_MAP = New
98            .hashMap();
99 
100    private AutoDetectDataType last = new StringType(this);
101 
102    @Override
103    public int compare(Object a, Object b) {
104        return last.compare(a, b);
105    }
106 
107    @Override
108    public int getMemory(Object obj) {
109        return last.getMemory(obj);
110    }
111 
112    @Override
113    public void read(ByteBuffer buff, Object[] obj, int len, boolean key) {
114        for (int i = 0; i < len; i++) {
115            obj[i] = read(buff);
116        }
117    }
118 
119    @Override
120    public void write(WriteBuffer buff, Object[] obj, int len, boolean key) {
121        for (int i = 0; i < len; i++) {
122            write(buff, obj[i]);
123        }
124    }
125 
126    @Override
127    public void write(WriteBuffer buff, Object obj) {
128        last.write(buff, obj);
129    }
130 
131    private AutoDetectDataType newType(int typeId) {
132        switch (typeId) {
133        case TYPE_NULL:
134            return new NullType(this);
135        case TYPE_BOOLEAN:
136            return new BooleanType(this);
137        case TYPE_BYTE:
138            return new ByteType(this);
139        case TYPE_SHORT:
140            return new ShortType(this);
141        case TYPE_CHAR:
142            return new CharacterType(this);
143        case TYPE_INT:
144            return new IntegerType(this);
145        case TYPE_LONG:
146            return new LongType(this);
147        case TYPE_FLOAT:
148            return new FloatType(this);
149        case TYPE_DOUBLE:
150            return new DoubleType(this);
151        case TYPE_BIG_INTEGER:
152            return new BigIntegerType(this);
153        case TYPE_BIG_DECIMAL:
154            return new BigDecimalType(this);
155        case TYPE_STRING:
156            return new StringType(this);
157        case TYPE_UUID:
158            return new UUIDType(this);
159        case TYPE_DATE:
160            return new DateType(this);
161        case TYPE_ARRAY:
162            return new ObjectArrayType(this);
163        case TYPE_SERIALIZED_OBJECT:
164            return new SerializedObjectType(this);
165        }
166        throw DataUtils.newIllegalStateException(DataUtils.ERROR_INTERNAL,
167                "Unsupported type {0}", typeId);
168    }
169 
170    @Override
171    public Object read(ByteBuffer buff) {
172        int tag = buff.get();
173        int typeId;
174        if (tag <= TYPE_SERIALIZED_OBJECT) {
175            typeId = tag;
176        } else {
177            switch (tag) {
178            case TAG_BOOLEAN_TRUE:
179                typeId = TYPE_BOOLEAN;
180                break;
181            case TAG_INTEGER_NEGATIVE:
182            case TAG_INTEGER_FIXED:
183                typeId = TYPE_INT;
184                break;
185            case TAG_LONG_NEGATIVE:
186            case TAG_LONG_FIXED:
187                typeId = TYPE_LONG;
188                break;
189            case TAG_BIG_INTEGER_0:
190            case TAG_BIG_INTEGER_1:
191            case TAG_BIG_INTEGER_SMALL:
192                typeId = TYPE_BIG_INTEGER;
193                break;
194            case TAG_FLOAT_0:
195            case TAG_FLOAT_1:
196            case TAG_FLOAT_FIXED:
197                typeId = TYPE_FLOAT;
198                break;
199            case TAG_DOUBLE_0:
200            case TAG_DOUBLE_1:
201            case TAG_DOUBLE_FIXED:
202                typeId = TYPE_DOUBLE;
203                break;
204            case TAG_BIG_DECIMAL_0:
205            case TAG_BIG_DECIMAL_1:
206            case TAG_BIG_DECIMAL_SMALL:
207            case TAG_BIG_DECIMAL_SMALL_SCALED:
208                typeId = TYPE_BIG_DECIMAL;
209                break;
210            default:
211                if (tag >= TAG_INTEGER_0_15 && tag <= TAG_INTEGER_0_15 + 15) {
212                    typeId = TYPE_INT;
213                } else if (tag >= TAG_STRING_0_15
214                        && tag <= TAG_STRING_0_15 + 15) {
215                    typeId = TYPE_STRING;
216                } else if (tag >= TAG_LONG_0_7 && tag <= TAG_LONG_0_7 + 7) {
217                    typeId = TYPE_LONG;
218                } else if (tag >= TAG_BYTE_ARRAY_0_15
219                        && tag <= TAG_BYTE_ARRAY_0_15 + 15) {
220                    typeId = TYPE_ARRAY;
221                } else {
222                    throw DataUtils.newIllegalStateException(
223                            DataUtils.ERROR_FILE_CORRUPT, "Unknown tag {0}",
224                            tag);
225                }
226            }
227        }
228        AutoDetectDataType t = last;
229        if (typeId != t.typeId) {
230            last = t = newType(typeId);
231        }
232        return t.read(buff, tag);
233    }
234 
235    private static int getTypeId(Object obj) {
236        if (obj instanceof Integer) {
237            return TYPE_INT;
238        } else if (obj instanceof String) {
239            return TYPE_STRING;
240        } else if (obj instanceof Long) {
241            return TYPE_LONG;
242        } else if (obj instanceof Double) {
243            return TYPE_DOUBLE;
244        } else if (obj instanceof Float) {
245            return TYPE_FLOAT;
246        } else if (obj instanceof Boolean) {
247            return TYPE_BOOLEAN;
248        } else if (obj instanceof UUID) {
249            return TYPE_UUID;
250        } else if (obj instanceof Byte) {
251            return TYPE_BYTE;
252        } else if (obj instanceof Short) {
253            return TYPE_SHORT;
254        } else if (obj instanceof Character) {
255            return TYPE_CHAR;
256        } else if (obj == null) {
257            return TYPE_NULL;
258        } else if (isDate(obj)) {
259            return TYPE_DATE;
260        } else if (isBigInteger(obj)) {
261            return TYPE_BIG_INTEGER;
262        } else if (isBigDecimal(obj)) {
263            return TYPE_BIG_DECIMAL;
264        } else if (obj.getClass().isArray()) {
265            return TYPE_ARRAY;
266        }
267        return TYPE_SERIALIZED_OBJECT;
268    }
269 
270    /**
271     * Switch the last remembered type to match the type of the given object.
272     *
273     * @param obj the object
274     * @return the auto-detected type used
275     */
276    AutoDetectDataType switchType(Object obj) {
277        int typeId = getTypeId(obj);
278        AutoDetectDataType l = last;
279        if (typeId != l.typeId) {
280            last = l = newType(typeId);
281        }
282        return l;
283    }
284 
285    /**
286     * Check whether this object is a BigInteger.
287     *
288     * @param obj the object
289     * @return true if yes
290     */
291    static boolean isBigInteger(Object obj) {
292        return obj instanceof BigInteger && obj.getClass() == BigInteger.class;
293    }
294 
295    /**
296     * Check whether this object is a BigDecimal.
297     *
298     * @param obj the object
299     * @return true if yes
300     */
301    static boolean isBigDecimal(Object obj) {
302        return obj instanceof BigDecimal && obj.getClass() == BigDecimal.class;
303    }
304 
305    /**
306     * Check whether this object is a date.
307     *
308     * @param obj the object
309     * @return true if yes
310     */
311    static boolean isDate(Object obj) {
312        return obj instanceof Date && obj.getClass() == Date.class;
313    }
314 
315    /**
316     * Check whether this object is an array.
317     *
318     * @param obj the object
319     * @return true if yes
320     */
321    static boolean isArray(Object obj) {
322        return obj != null && obj.getClass().isArray();
323    }
324 
325    /**
326     * Get the class id, or null if not found.
327     *
328     * @param clazz the class
329     * @return the class id or null
330     */
331    static Integer getCommonClassId(Class<?> clazz) {
332        HashMap<Class<?>, Integer> map = COMMON_CLASSES_MAP;
333        if (map.size() == 0) {
334            // lazy initialization
335            for (int i = 0, size = COMMON_CLASSES.length; i < size; i++) {
336                COMMON_CLASSES_MAP.put(COMMON_CLASSES[i], i);
337            }
338        }
339        return map.get(clazz);
340    }
341 
342    /**
343     * Serialize the object to a byte array.
344     *
345     * @param obj the object to serialize
346     * @return the byte array
347     */
348    public static byte[] serialize(Object obj) {
349        try {
350            ByteArrayOutputStream out = new ByteArrayOutputStream();
351            ObjectOutputStream os = new ObjectOutputStream(out);
352            os.writeObject(obj);
353            return out.toByteArray();
354        } catch (Throwable e) {
355            throw DataUtils.newIllegalArgumentException(
356                    "Could not serialize {0}", obj, e);
357        }
358    }
359 
360    /**
361     * De-serialize the byte array to an object.
362     *
363     * @param data the byte array
364     * @return the object
365     */
366    public static Object deserialize(byte[] data) {
367        try {
368            ByteArrayInputStream in = new ByteArrayInputStream(data);
369            ObjectInputStream is = new ObjectInputStream(in);
370            return is.readObject();
371        } catch (Throwable e) {
372            throw DataUtils.newIllegalArgumentException(
373                    "Could not deserialize {0}", Arrays.toString(data), e);
374        }
375    }
376 
377    /**
378     * Compare the contents of two byte arrays. If the content or length of the
379     * first array is smaller than the second array, -1 is returned. If the
380     * content or length of the second array is smaller than the first array, 1
381     * is returned. If the contents and lengths are the same, 0 is returned.
382     * <p>
383     * This method interprets bytes as unsigned.
384     *
385     * @param data1 the first byte array (must not be null)
386     * @param data2 the second byte array (must not be null)
387     * @return the result of the comparison (-1, 1 or 0)
388     */
389    public static int compareNotNull(byte[] data1, byte[] data2) {
390        if (data1 == data2) {
391            return 0;
392        }
393        int len = Math.min(data1.length, data2.length);
394        for (int i = 0; i < len; i++) {
395            int b = data1[i] & 255;
396            int b2 = data2[i] & 255;
397            if (b != b2) {
398                return b > b2 ? 1 : -1;
399            }
400        }
401        return Integer.signum(data1.length - data2.length);
402    }
403 
404    /**
405     * The base class for auto-detect data types.
406     */
407    abstract static class AutoDetectDataType implements DataType {
408 
409        protected final ObjectDataType base;
410        protected final int typeId;
411 
412        AutoDetectDataType(ObjectDataType base, int typeId) {
413            this.base = base;
414            this.typeId = typeId;
415        }
416 
417        @Override
418        public int getMemory(Object o) {
419            return getType(o).getMemory(o);
420        }
421 
422        @Override
423        public int compare(Object aObj, Object bObj) {
424            AutoDetectDataType aType = getType(aObj);
425            AutoDetectDataType bType = getType(bObj);
426            int typeDiff = aType.typeId - bType.typeId;
427            if (typeDiff == 0) {
428                return aType.compare(aObj, bObj);
429            }
430            return Integer.signum(typeDiff);
431        }
432 
433        @Override
434        public void write(WriteBuffer buff, Object[] obj,
435                int len, boolean key) {
436            for (int i = 0; i < len; i++) {
437                write(buff, obj[i]);
438            }
439        }
440 
441        @Override
442        public void write(WriteBuffer buff, Object o) {
443            getType(o).write(buff, o);
444        }
445 
446        @Override
447        public void read(ByteBuffer buff, Object[] obj,
448                int len, boolean key) {
449            for (int i = 0; i < len; i++) {
450                obj[i] = read(buff);
451            }
452        }
453 
454        @Override
455        public final Object read(ByteBuffer buff) {
456            throw DataUtils.newIllegalStateException(DataUtils.ERROR_INTERNAL,
457                    "Internal error");
458        }
459 
460        /**
461         * Get the type for the given object.
462         *
463         * @param o the object
464         * @return the type
465         */
466        AutoDetectDataType getType(Object o) {
467            return base.switchType(o);
468        }
469 
470        /**
471         * Read an object from the buffer.
472         *
473         * @param buff the buffer
474         * @param tag the first byte of the object (usually the type)
475         * @return the read object
476         */
477        abstract Object read(ByteBuffer buff, int tag);
478 
479    }
480 
481    /**
482     * The type for the null value
483     */
484    static class NullType extends AutoDetectDataType {
485 
486        NullType(ObjectDataType base) {
487            super(base, TYPE_NULL);
488        }
489 
490        @Override
491        public int compare(Object aObj, Object bObj) {
492            if (aObj == null && bObj == null) {
493                return 0;
494            } else if (aObj == null) {
495                return -1;
496            } else if (bObj == null) {
497                return 1;
498            }
499            return super.compare(aObj, bObj);
500        }
501 
502        @Override
503        public int getMemory(Object obj) {
504            return obj == null ? 0 : super.getMemory(obj);
505        }
506 
507        @Override
508        public void write(WriteBuffer buff, Object obj) {
509            if (obj != null) {
510                super.write(buff, obj);
511                return;
512            }
513            buff.put((byte) TYPE_NULL);
514        }
515 
516        @Override
517        public Object read(ByteBuffer buff, int tag) {
518            return null;
519        }
520 
521    }
522 
523    /**
524     * The type for boolean true and false.
525     */
526    static class BooleanType extends AutoDetectDataType {
527 
528        BooleanType(ObjectDataType base) {
529            super(base, TYPE_BOOLEAN);
530        }
531 
532        @Override
533        public int compare(Object aObj, Object bObj) {
534            if (aObj instanceof Boolean && bObj instanceof Boolean) {
535                Boolean a = (Boolean) aObj;
536                Boolean b = (Boolean) bObj;
537                return a.compareTo(b);
538            }
539            return super.compare(aObj, bObj);
540        }
541 
542        @Override
543        public int getMemory(Object obj) {
544            return obj instanceof Boolean ? 0 : super.getMemory(obj);
545        }
546 
547        @Override
548        public void write(WriteBuffer buff, Object obj) {
549            if (!(obj instanceof Boolean)) {
550                super.write(buff, obj);
551                return;
552            }
553            int tag = ((Boolean) obj) ? TAG_BOOLEAN_TRUE : TYPE_BOOLEAN;
554            buff.put((byte) tag);
555        }
556 
557        @Override
558        public Object read(ByteBuffer buff, int tag) {
559            return tag == TYPE_BOOLEAN ? Boolean.FALSE : Boolean.TRUE;
560        }
561 
562    }
563 
564    /**
565     * The type for byte objects.
566     */
567    static class ByteType extends AutoDetectDataType {
568 
569        ByteType(ObjectDataType base) {
570            super(base, TYPE_BYTE);
571        }
572 
573        @Override
574        public int compare(Object aObj, Object bObj) {
575            if (aObj instanceof Byte && bObj instanceof Byte) {
576                Byte a = (Byte) aObj;
577                Byte b = (Byte) bObj;
578                return a.compareTo(b);
579            }
580            return super.compare(aObj, bObj);
581        }
582 
583        @Override
584        public int getMemory(Object obj) {
585            return obj instanceof Byte ? 0 : super.getMemory(obj);
586        }
587 
588        @Override
589        public void write(WriteBuffer buff, Object obj) {
590            if (!(obj instanceof Byte)) {
591                super.write(buff, obj);
592                return;
593            }
594            buff.put((byte) TYPE_BYTE);
595            buff.put(((Byte) obj).byteValue());
596        }
597 
598        @Override
599        public Object read(ByteBuffer buff, int tag) {
600            return Byte.valueOf(buff.get());
601        }
602 
603    }
604 
605    /**
606     * The type for character objects.
607     */
608    static class CharacterType extends AutoDetectDataType {
609 
610        CharacterType(ObjectDataType base) {
611            super(base, TYPE_CHAR);
612        }
613 
614        @Override
615        public int compare(Object aObj, Object bObj) {
616            if (aObj instanceof Character && bObj instanceof Character) {
617                Character a = (Character) aObj;
618                Character b = (Character) bObj;
619                return a.compareTo(b);
620            }
621            return super.compare(aObj, bObj);
622        }
623 
624        @Override
625        public int getMemory(Object obj) {
626            return obj instanceof Character ? 24 : super.getMemory(obj);
627        }
628 
629        @Override
630        public void write(WriteBuffer buff, Object obj) {
631            if (!(obj instanceof Character)) {
632                super.write(buff, obj);
633                return;
634            }
635            buff.put((byte) TYPE_CHAR);
636            buff.putChar(((Character) obj).charValue());
637        }
638 
639        @Override
640        public Object read(ByteBuffer buff, int tag) {
641            return Character.valueOf(buff.getChar());
642        }
643 
644    }
645 
646    /**
647     * The type for short objects.
648     */
649    static class ShortType extends AutoDetectDataType {
650 
651        ShortType(ObjectDataType base) {
652            super(base, TYPE_SHORT);
653        }
654 
655        @Override
656        public int compare(Object aObj, Object bObj) {
657            if (aObj instanceof Short && bObj instanceof Short) {
658                Short a = (Short) aObj;
659                Short b = (Short) bObj;
660                return a.compareTo(b);
661            }
662            return super.compare(aObj, bObj);
663        }
664 
665        @Override
666        public int getMemory(Object obj) {
667            return obj instanceof Short ? 24 : super.getMemory(obj);
668        }
669 
670        @Override
671        public void write(WriteBuffer buff, Object obj) {
672            if (!(obj instanceof Short)) {
673                super.write(buff, obj);
674                return;
675            }
676            buff.put((byte) TYPE_SHORT);
677            buff.putShort(((Short) obj).shortValue());
678        }
679 
680        @Override
681        public Object read(ByteBuffer buff, int tag) {
682            return Short.valueOf(buff.getShort());
683        }
684 
685    }
686 
687    /**
688     * The type for integer objects.
689     */
690    static class IntegerType extends AutoDetectDataType {
691 
692        IntegerType(ObjectDataType base) {
693            super(base, TYPE_INT);
694        }
695 
696        @Override
697        public int compare(Object aObj, Object bObj) {
698            if (aObj instanceof Integer && bObj instanceof Integer) {
699                Integer a = (Integer) aObj;
700                Integer b = (Integer) bObj;
701                return a.compareTo(b);
702            }
703            return super.compare(aObj, bObj);
704        }
705 
706        @Override
707        public int getMemory(Object obj) {
708            return obj instanceof Integer ? 24 : super.getMemory(obj);
709        }
710 
711        @Override
712        public void write(WriteBuffer buff, Object obj) {
713            if (!(obj instanceof Integer)) {
714                super.write(buff, obj);
715                return;
716            }
717            int x = (Integer) obj;
718            if (x < 0) {
719                // -Integer.MIN_VALUE is smaller than 0
720                if (-x < 0 || -x > DataUtils.COMPRESSED_VAR_INT_MAX) {
721                    buff.put((byte) TAG_INTEGER_FIXED).putInt(x);
722                } else {
723                    buff.put((byte) TAG_INTEGER_NEGATIVE).putVarInt(-x);
724                }
725            } else if (x <= 15) {
726                buff.put((byte) (TAG_INTEGER_0_15 + x));
727            } else if (x <= DataUtils.COMPRESSED_VAR_INT_MAX) {
728                buff.put((byte) TYPE_INT).putVarInt(x);
729            } else {
730                buff.put((byte) TAG_INTEGER_FIXED).putInt(x);
731            }
732        }
733 
734        @Override
735        public Object read(ByteBuffer buff, int tag) {
736            switch (tag) {
737            case TYPE_INT:
738                return DataUtils.readVarInt(buff);
739            case TAG_INTEGER_NEGATIVE:
740                return -DataUtils.readVarInt(buff);
741            case TAG_INTEGER_FIXED:
742                return buff.getInt();
743            }
744            return tag - TAG_INTEGER_0_15;
745        }
746 
747    }
748 
749    /**
750     * The type for long objects.
751     */
752    static class LongType extends AutoDetectDataType {
753 
754        LongType(ObjectDataType base) {
755            super(base, TYPE_LONG);
756        }
757 
758        @Override
759        public int compare(Object aObj, Object bObj) {
760            if (aObj instanceof Long && bObj instanceof Long) {
761                Long a = (Long) aObj;
762                Long b = (Long) bObj;
763                return a.compareTo(b);
764            }
765            return super.compare(aObj, bObj);
766        }
767 
768        @Override
769        public int getMemory(Object obj) {
770            return obj instanceof Long ? 30 : super.getMemory(obj);
771        }
772 
773        @Override
774        public void write(WriteBuffer buff, Object obj) {
775            if (!(obj instanceof Long)) {
776                super.write(buff, obj);
777                return;
778            }
779            long x = (Long) obj;
780            if (x < 0) {
781                // -Long.MIN_VALUE is smaller than 0
782                if (-x < 0 || -x > DataUtils.COMPRESSED_VAR_LONG_MAX) {
783                    buff.put((byte) TAG_LONG_FIXED);
784                    buff.putLong(x);
785                } else {
786                    buff.put((byte) TAG_LONG_NEGATIVE);
787                    buff.putVarLong(-x);
788                }
789            } else if (x <= 7) {
790                buff.put((byte) (TAG_LONG_0_7 + x));
791            } else if (x <= DataUtils.COMPRESSED_VAR_LONG_MAX) {
792                buff.put((byte) TYPE_LONG);
793                buff.putVarLong(x);
794            } else {
795                buff.put((byte) TAG_LONG_FIXED);
796                buff.putLong(x);
797            }
798        }
799 
800        @Override
801        public Object read(ByteBuffer buff, int tag) {
802            switch (tag) {
803            case TYPE_LONG:
804                return DataUtils.readVarLong(buff);
805            case TAG_LONG_NEGATIVE:
806                return -DataUtils.readVarLong(buff);
807            case TAG_LONG_FIXED:
808                return buff.getLong();
809            }
810            return Long.valueOf(tag - TAG_LONG_0_7);
811        }
812 
813    }
814 
815    /**
816     * The type for float objects.
817     */
818    static class FloatType extends AutoDetectDataType {
819 
820        FloatType(ObjectDataType base) {
821            super(base, TYPE_FLOAT);
822        }
823 
824        @Override
825        public int compare(Object aObj, Object bObj) {
826            if (aObj instanceof Float && bObj instanceof Float) {
827                Float a = (Float) aObj;
828                Float b = (Float) bObj;
829                return a.compareTo(b);
830            }
831            return super.compare(aObj, bObj);
832        }
833 
834        @Override
835        public int getMemory(Object obj) {
836            return obj instanceof Float ? 24 : super.getMemory(obj);
837        }
838 
839        @Override
840        public void write(WriteBuffer buff, Object obj) {
841            if (!(obj instanceof Float)) {
842                super.write(buff, obj);
843                return;
844            }
845            float x = (Float) obj;
846            int f = Float.floatToIntBits(x);
847            if (f == ObjectDataType.FLOAT_ZERO_BITS) {
848                buff.put((byte) TAG_FLOAT_0);
849            } else if (f == ObjectDataType.FLOAT_ONE_BITS) {
850                buff.put((byte) TAG_FLOAT_1);
851            } else {
852                int value = Integer.reverse(f);
853                if (value >= 0 && value <= DataUtils.COMPRESSED_VAR_INT_MAX) {
854                    buff.put((byte) TYPE_FLOAT).putVarInt(value);
855                } else {
856                    buff.put((byte) TAG_FLOAT_FIXED).putFloat(x);
857                }
858            }
859        }
860 
861        @Override
862        public Object read(ByteBuffer buff, int tag) {
863            switch (tag) {
864            case TAG_FLOAT_0:
865                return 0f;
866            case TAG_FLOAT_1:
867                return 1f;
868            case TAG_FLOAT_FIXED:
869                return buff.getFloat();
870            }
871            return Float.intBitsToFloat(Integer.reverse(DataUtils
872                    .readVarInt(buff)));
873        }
874 
875    }
876 
877    /**
878     * The type for double objects.
879     */
880    static class DoubleType extends AutoDetectDataType {
881 
882        DoubleType(ObjectDataType base) {
883            super(base, TYPE_DOUBLE);
884        }
885 
886        @Override
887        public int compare(Object aObj, Object bObj) {
888            if (aObj instanceof Double && bObj instanceof Double) {
889                Double a = (Double) aObj;
890                Double b = (Double) bObj;
891                return a.compareTo(b);
892            }
893            return super.compare(aObj, bObj);
894        }
895 
896        @Override
897        public int getMemory(Object obj) {
898            return obj instanceof Double ? 30 : super.getMemory(obj);
899        }
900 
901        @Override
902        public void write(WriteBuffer buff, Object obj) {
903            if (!(obj instanceof Double)) {
904                super.write(buff, obj);
905                return;
906            }
907            double x = (Double) obj;
908            long d = Double.doubleToLongBits(x);
909            if (d == ObjectDataType.DOUBLE_ZERO_BITS) {
910                buff.put((byte) TAG_DOUBLE_0);
911            } else if (d == ObjectDataType.DOUBLE_ONE_BITS) {
912                buff.put((byte) TAG_DOUBLE_1);
913            } else {
914                long value = Long.reverse(d);
915                if (value >= 0 && value <= DataUtils.COMPRESSED_VAR_LONG_MAX) {
916                    buff.put((byte) TYPE_DOUBLE);
917                    buff.putVarLong(value);
918                } else {
919                    buff.put((byte) TAG_DOUBLE_FIXED);
920                    buff.putDouble(x);
921                }
922            }
923        }
924 
925        @Override
926        public Object read(ByteBuffer buff, int tag) {
927            switch (tag) {
928            case TAG_DOUBLE_0:
929                return 0d;
930            case TAG_DOUBLE_1:
931                return 1d;
932            case TAG_DOUBLE_FIXED:
933                return buff.getDouble();
934            }
935            return Double.longBitsToDouble(Long.reverse(DataUtils
936                    .readVarLong(buff)));
937        }
938 
939    }
940 
941    /**
942     * The type for BigInteger objects.
943     */
944    static class BigIntegerType extends AutoDetectDataType {
945 
946        BigIntegerType(ObjectDataType base) {
947            super(base, TYPE_BIG_INTEGER);
948        }
949 
950        @Override
951        public int compare(Object aObj, Object bObj) {
952            if (isBigInteger(aObj) && isBigInteger(bObj)) {
953                BigInteger a = (BigInteger) aObj;
954                BigInteger b = (BigInteger) bObj;
955                return a.compareTo(b);
956            }
957            return super.compare(aObj, bObj);
958        }
959 
960        @Override
961        public int getMemory(Object obj) {
962            return isBigInteger(obj) ? 100 : super.getMemory(obj);
963        }
964 
965        @Override
966        public void write(WriteBuffer buff, Object obj) {
967            if (!isBigInteger(obj)) {
968                super.write(buff, obj);
969                return;
970            }
971            BigInteger x = (BigInteger) obj;
972            if (BigInteger.ZERO.equals(x)) {
973                buff.put((byte) TAG_BIG_INTEGER_0);
974            } else if (BigInteger.ONE.equals(x)) {
975                buff.put((byte) TAG_BIG_INTEGER_1);
976            } else {
977                int bits = x.bitLength();
978                if (bits <= 63) {
979                    buff.put((byte) TAG_BIG_INTEGER_SMALL).putVarLong(
980                            x.longValue());
981                } else {
982                    byte[] bytes = x.toByteArray();
983                    buff.put((byte) TYPE_BIG_INTEGER).putVarInt(bytes.length)
984                            .put(bytes);
985                }
986            }
987        }
988 
989        @Override
990        public Object read(ByteBuffer buff, int tag) {
991            switch (tag) {
992            case TAG_BIG_INTEGER_0:
993                return BigInteger.ZERO;
994            case TAG_BIG_INTEGER_1:
995                return BigInteger.ONE;
996            case TAG_BIG_INTEGER_SMALL:
997                return BigInteger.valueOf(DataUtils.readVarLong(buff));
998            }
999            int len = DataUtils.readVarInt(buff);
1000            byte[] bytes = DataUtils.newBytes(len);
1001            buff.get(bytes);
1002            return new BigInteger(bytes);
1003        }
1004 
1005    }
1006 
1007    /**
1008     * The type for BigDecimal objects.
1009     */
1010    static class BigDecimalType extends AutoDetectDataType {
1011 
1012        BigDecimalType(ObjectDataType base) {
1013            super(base, TYPE_BIG_DECIMAL);
1014        }
1015 
1016        @Override
1017        public int compare(Object aObj, Object bObj) {
1018            if (isBigDecimal(aObj) && isBigDecimal(bObj)) {
1019                BigDecimal a = (BigDecimal) aObj;
1020                BigDecimal b = (BigDecimal) bObj;
1021                return a.compareTo(b);
1022            }
1023            return super.compare(aObj, bObj);
1024        }
1025 
1026        @Override
1027        public int getMemory(Object obj) {
1028            return isBigDecimal(obj) ? 150 : super.getMemory(obj);
1029        }
1030 
1031        @Override
1032        public void write(WriteBuffer buff, Object obj) {
1033            if (!isBigDecimal(obj)) {
1034                super.write(buff, obj);
1035                return;
1036            }
1037            BigDecimal x = (BigDecimal) obj;
1038            if (BigDecimal.ZERO.equals(x)) {
1039                buff.put((byte) TAG_BIG_DECIMAL_0);
1040            } else if (BigDecimal.ONE.equals(x)) {
1041                buff.put((byte) TAG_BIG_DECIMAL_1);
1042            } else {
1043                int scale = x.scale();
1044                BigInteger b = x.unscaledValue();
1045                int bits = b.bitLength();
1046                if (bits < 64) {
1047                    if (scale == 0) {
1048                        buff.put((byte) TAG_BIG_DECIMAL_SMALL);
1049                    } else {
1050                        buff.put((byte) TAG_BIG_DECIMAL_SMALL_SCALED)
1051                                .putVarInt(scale);
1052                    }
1053                    buff.putVarLong(b.longValue());
1054                } else {
1055                    byte[] bytes = b.toByteArray();
1056                    buff.put((byte) TYPE_BIG_DECIMAL).putVarInt(scale)
1057                            .putVarInt(bytes.length).put(bytes);
1058                }
1059            }
1060        }
1061 
1062        @Override
1063        public Object read(ByteBuffer buff, int tag) {
1064            switch (tag) {
1065            case TAG_BIG_DECIMAL_0:
1066                return BigDecimal.ZERO;
1067            case TAG_BIG_DECIMAL_1:
1068                return BigDecimal.ONE;
1069            case TAG_BIG_DECIMAL_SMALL:
1070                return BigDecimal.valueOf(DataUtils.readVarLong(buff));
1071            case TAG_BIG_DECIMAL_SMALL_SCALED:
1072                int scale = DataUtils.readVarInt(buff);
1073                return BigDecimal.valueOf(DataUtils.readVarLong(buff), scale);
1074            }
1075            int scale = DataUtils.readVarInt(buff);
1076            int len = DataUtils.readVarInt(buff);
1077            byte[] bytes = DataUtils.newBytes(len);
1078            buff.get(bytes);
1079            BigInteger b = new BigInteger(bytes);
1080            return new BigDecimal(b, scale);
1081        }
1082 
1083    }
1084 
1085    /**
1086     * The type for string objects.
1087     */
1088    static class StringType extends AutoDetectDataType {
1089 
1090        StringType(ObjectDataType base) {
1091            super(base, TYPE_STRING);
1092        }
1093 
1094        @Override
1095        public int getMemory(Object obj) {
1096            if (!(obj instanceof String)) {
1097                return super.getMemory(obj);
1098            }
1099            return 24 + 2 * obj.toString().length();
1100        }
1101 
1102        @Override
1103        public int compare(Object aObj, Object bObj) {
1104            if (aObj instanceof String && bObj instanceof String) {
1105                return aObj.toString().compareTo(bObj.toString());
1106            }
1107            return super.compare(aObj, bObj);
1108        }
1109 
1110        @Override
1111        public void write(WriteBuffer buff, Object obj) {
1112            if (!(obj instanceof String)) {
1113                super.write(buff, obj);
1114                return;
1115            }
1116            String s = (String) obj;
1117            int len = s.length();
1118            if (len <= 15) {
1119                buff.put((byte) (TAG_STRING_0_15 + len));
1120            } else {
1121                buff.put((byte) TYPE_STRING).putVarInt(len);
1122            }
1123            buff.putStringData(s, len);
1124        }
1125 
1126        @Override
1127        public Object read(ByteBuffer buff, int tag) {
1128            int len;
1129            if (tag == TYPE_STRING) {
1130                len = DataUtils.readVarInt(buff);
1131            } else {
1132                len = tag - TAG_STRING_0_15;
1133            }
1134            return DataUtils.readString(buff, len);
1135        }
1136 
1137    }
1138 
1139    /**
1140     * The type for UUID objects.
1141     */
1142    static class UUIDType extends AutoDetectDataType {
1143 
1144        UUIDType(ObjectDataType base) {
1145            super(base, TYPE_UUID);
1146        }
1147 
1148        @Override
1149        public int getMemory(Object obj) {
1150            return obj instanceof UUID ? 40 : super.getMemory(obj);
1151        }
1152 
1153        @Override
1154        public int compare(Object aObj, Object bObj) {
1155            if (aObj instanceof UUID && bObj instanceof UUID) {
1156                UUID a = (UUID) aObj;
1157                UUID b = (UUID) bObj;
1158                return a.compareTo(b);
1159            }
1160            return super.compare(aObj, bObj);
1161        }
1162 
1163        @Override
1164        public void write(WriteBuffer buff, Object obj) {
1165            if (!(obj instanceof UUID)) {
1166                super.write(buff, obj);
1167                return;
1168            }
1169            buff.put((byte) TYPE_UUID);
1170            UUID a = (UUID) obj;
1171            buff.putLong(a.getMostSignificantBits());
1172            buff.putLong(a.getLeastSignificantBits());
1173        }
1174 
1175        @Override
1176        public Object read(ByteBuffer buff, int tag) {
1177            long a = buff.getLong(), b = buff.getLong();
1178            return new UUID(a, b);
1179        }
1180 
1181    }
1182 
1183    /**
1184     * The type for java.util.Date objects.
1185     */
1186    static class DateType extends AutoDetectDataType {
1187 
1188        DateType(ObjectDataType base) {
1189            super(base, TYPE_DATE);
1190        }
1191 
1192        @Override
1193        public int getMemory(Object obj) {
1194            return isDate(obj) ? 40 : super.getMemory(obj);
1195        }
1196 
1197        @Override
1198        public int compare(Object aObj, Object bObj) {
1199            if (isDate(aObj) && isDate(bObj)) {
1200                Date a = (Date) aObj;
1201                Date b = (Date) bObj;
1202                return a.compareTo(b);
1203            }
1204            return super.compare(aObj, bObj);
1205        }
1206 
1207        @Override
1208        public void write(WriteBuffer buff, Object obj) {
1209            if (!isDate(obj)) {
1210                super.write(buff, obj);
1211                return;
1212            }
1213            buff.put((byte) TYPE_DATE);
1214            Date a = (Date) obj;
1215            buff.putLong(a.getTime());
1216        }
1217 
1218        @Override
1219        public Object read(ByteBuffer buff, int tag) {
1220            long a = buff.getLong();
1221            return new Date(a);
1222        }
1223 
1224    }
1225 
1226    /**
1227     * The type for object arrays.
1228     */
1229    static class ObjectArrayType extends AutoDetectDataType {
1230 
1231        private final ObjectDataType elementType = new ObjectDataType();
1232 
1233        ObjectArrayType(ObjectDataType base) {
1234            super(base, TYPE_ARRAY);
1235        }
1236 
1237        @Override
1238        public int getMemory(Object obj) {
1239            if (!isArray(obj)) {
1240                return super.getMemory(obj);
1241            }
1242            int size = 64;
1243            Class<?> type = obj.getClass().getComponentType();
1244            if (type.isPrimitive()) {
1245                int len = Array.getLength(obj);
1246                if (type == boolean.class) {
1247                    size += len;
1248                } else if (type == byte.class) {
1249                    size += len;
1250                } else if (type == char.class) {
1251                    size += len * 2;
1252                } else if (type == short.class) {
1253                    size += len * 2;
1254                } else if (type == int.class) {
1255                    size += len * 4;
1256                } else if (type == float.class) {
1257                    size += len * 4;
1258                } else if (type == double.class) {
1259                    size += len * 8;
1260                } else if (type == long.class) {
1261                    size += len * 8;
1262                }
1263            } else {
1264                for (Object x : (Object[]) obj) {
1265                    if (x != null) {
1266                        size += elementType.getMemory(x);
1267                    }
1268                }
1269            }
1270            // we say they are larger, because these objects
1271            // use quite a lot of disk space
1272            return size * 2;
1273        }
1274 
1275        @Override
1276        public int compare(Object aObj, Object bObj) {
1277            if (!isArray(aObj) || !isArray(bObj)) {
1278                return super.compare(aObj, bObj);
1279            }
1280            if (aObj == bObj) {
1281                return 0;
1282            }
1283            Class<?> type = aObj.getClass().getComponentType();
1284            Class<?> bType = bObj.getClass().getComponentType();
1285            if (type != bType) {
1286                Integer classA = getCommonClassId(type);
1287                Integer classB = getCommonClassId(bType);
1288                if (classA != null) {
1289                    if (classB != null) {
1290                        return classA.compareTo(classB);
1291                    }
1292                    return -1;
1293                } else if (classB != null) {
1294                    return 1;
1295                }
1296                return type.getName().compareTo(bType.getName());
1297            }
1298            int aLen = Array.getLength(aObj);
1299            int bLen = Array.getLength(bObj);
1300            int len = Math.min(aLen, bLen);
1301            if (type.isPrimitive()) {
1302                if (type == byte.class) {
1303                    byte[] a = (byte[]) aObj;
1304                    byte[] b = (byte[]) bObj;
1305                    return compareNotNull(a, b);
1306                }
1307                for (int i = 0; i < len; i++) {
1308                    int x;
1309                    if (type == boolean.class) {
1310                        x = Integer.signum((((boolean[]) aObj)[i] ? 1 : 0)
1311                                - (((boolean[]) bObj)[i] ? 1 : 0));
1312                    } else if (type == char.class) {
1313                        x = Integer.signum((((char[]) aObj)[i])
1314                                - (((char[]) bObj)[i]));
1315                    } else if (type == short.class) {
1316                        x = Integer.signum((((short[]) aObj)[i])
1317                                - (((short[]) bObj)[i]));
1318                    } else if (type == int.class) {
1319                        int a = ((int[]) aObj)[i];
1320                        int b = ((int[]) bObj)[i];
1321                        x = a == b ? 0 : a < b ? -1 : 1;
1322                    } else if (type == float.class) {
1323                        x = Float.compare(((float[]) aObj)[i],
1324                                ((float[]) bObj)[i]);
1325                    } else if (type == double.class) {
1326                        x = Double.compare(((double[]) aObj)[i],
1327                                ((double[]) bObj)[i]);
1328                    } else {
1329                        long a = ((long[]) aObj)[i];
1330                        long b = ((long[]) bObj)[i];
1331                        x = a == b ? 0 : a < b ? -1 : 1;
1332                    }
1333                    if (x != 0) {
1334                        return x;
1335                    }
1336                }
1337            } else {
1338                Object[] a = (Object[]) aObj;
1339                Object[] b = (Object[]) bObj;
1340                for (int i = 0; i < len; i++) {
1341                    int comp = elementType.compare(a[i], b[i]);
1342                    if (comp != 0) {
1343                        return comp;
1344                    }
1345                }
1346            }
1347            return aLen == bLen ? 0 : aLen < bLen ? -1 : 1;
1348        }
1349 
1350        @Override
1351        public void write(WriteBuffer buff, Object obj) {
1352            if (!isArray(obj)) {
1353                super.write(buff, obj);
1354                return;
1355            }
1356            Class<?> type = obj.getClass().getComponentType();
1357            Integer classId = getCommonClassId(type);
1358            if (classId != null) {
1359                if (type.isPrimitive()) {
1360                    if (type == byte.class) {
1361                        byte[] data = (byte[]) obj;
1362                        int len = data.length;
1363                        if (len <= 15) {
1364                            buff.put((byte) (TAG_BYTE_ARRAY_0_15 + len));
1365                        } else {
1366                            buff.put((byte) TYPE_ARRAY)
1367                                    .put((byte) classId.intValue())
1368                                    .putVarInt(len);
1369                        }
1370                        buff.put(data);
1371                        return;
1372                    }
1373                    int len = Array.getLength(obj);
1374                    buff.put((byte) TYPE_ARRAY).put((byte) classId.intValue())
1375                            .putVarInt(len);
1376                    for (int i = 0; i < len; i++) {
1377                        if (type == boolean.class) {
1378                            buff.put((byte) (((boolean[]) obj)[i] ? 1 : 0));
1379                        } else if (type == char.class) {
1380                            buff.putChar(((char[]) obj)[i]);
1381                        } else if (type == short.class) {
1382                            buff.putShort(((short[]) obj)[i]);
1383                        } else if (type == int.class) {
1384                            buff.putInt(((int[]) obj)[i]);
1385                        } else if (type == float.class) {
1386                            buff.putFloat(((float[]) obj)[i]);
1387                        } else if (type == double.class) {
1388                            buff.putDouble(((double[]) obj)[i]);
1389                        } else {
1390                            buff.putLong(((long[]) obj)[i]);
1391                        }
1392                    }
1393                    return;
1394                }
1395                buff.put((byte) TYPE_ARRAY).put((byte) classId.intValue());
1396            } else {
1397                buff.put((byte) TYPE_ARRAY).put((byte) -1);
1398                String c = type.getName();
1399                StringDataType.INSTANCE.write(buff, c);
1400            }
1401            Object[] array = (Object[]) obj;
1402            int len = array.length;
1403            buff.putVarInt(len);
1404            for (Object x : array) {
1405                elementType.write(buff, x);
1406            }
1407        }
1408 
1409        @Override
1410        public Object read(ByteBuffer buff, int tag) {
1411            if (tag != TYPE_ARRAY) {
1412                byte[] data;
1413                int len = tag - TAG_BYTE_ARRAY_0_15;
1414                data = DataUtils.newBytes(len);
1415                buff.get(data);
1416                return data;
1417            }
1418            int ct = buff.get();
1419            Class<?> clazz;
1420            Object obj;
1421            if (ct == -1) {
1422                String componentType = StringDataType.INSTANCE.read(buff);
1423                try {
1424                    clazz = Class.forName(componentType);
1425                } catch (Exception e) {
1426                    throw DataUtils.newIllegalStateException(
1427                            DataUtils.ERROR_SERIALIZATION,
1428                            "Could not get class {0}", componentType, e);
1429                }
1430            } else {
1431                clazz = COMMON_CLASSES[ct];
1432            }
1433            int len = DataUtils.readVarInt(buff);
1434            try {
1435                obj = Array.newInstance(clazz, len);
1436            } catch (Exception e) {
1437                throw DataUtils.newIllegalStateException(
1438                        DataUtils.ERROR_SERIALIZATION,
1439                        "Could not create array of type {0} length {1}", clazz,
1440                        len, e);
1441            }
1442            if (clazz.isPrimitive()) {
1443                for (int i = 0; i < len; i++) {
1444                    if (clazz == boolean.class) {
1445                        ((boolean[]) obj)[i] = buff.get() == 1;
1446                    } else if (clazz == byte.class) {
1447                        ((byte[]) obj)[i] = buff.get();
1448                    } else if (clazz == char.class) {
1449                        ((char[]) obj)[i] = buff.getChar();
1450                    } else if (clazz == short.class) {
1451                        ((short[]) obj)[i] = buff.getShort();
1452                    } else if (clazz == int.class) {
1453                        ((int[]) obj)[i] = buff.getInt();
1454                    } else if (clazz == float.class) {
1455                        ((float[]) obj)[i] = buff.getFloat();
1456                    } else if (clazz == double.class) {
1457                        ((double[]) obj)[i] = buff.getDouble();
1458                    } else {
1459                        ((long[]) obj)[i] = buff.getLong();
1460                    }
1461                }
1462            } else {
1463                Object[] array = (Object[]) obj;
1464                for (int i = 0; i < len; i++) {
1465                    array[i] = elementType.read(buff);
1466                }
1467            }
1468            return obj;
1469        }
1470 
1471    }
1472 
1473    /**
1474     * The type for serialized objects.
1475     */
1476    static class SerializedObjectType extends AutoDetectDataType {
1477 
1478        private int averageSize = 10000;
1479 
1480        SerializedObjectType(ObjectDataType base) {
1481            super(base, TYPE_SERIALIZED_OBJECT);
1482        }
1483 
1484        @SuppressWarnings("unchecked")
1485        @Override
1486        public int compare(Object aObj, Object bObj) {
1487            if (aObj == bObj) {
1488                return 0;
1489            }
1490            DataType ta = getType(aObj);
1491            DataType tb = getType(bObj);
1492            if (ta != this || tb != this) {
1493                if (ta == tb) {
1494                    return ta.compare(aObj, bObj);
1495                }
1496                return super.compare(aObj, bObj);
1497            }
1498            // TODO ensure comparable type (both may be comparable but not
1499            // with each other)
1500            if (aObj instanceof Comparable) {
1501                if (aObj.getClass().isAssignableFrom(bObj.getClass())) {
1502                    return ((Comparable<Object>) aObj).compareTo(bObj);
1503                }
1504            }
1505            if (bObj instanceof Comparable) {
1506                if (bObj.getClass().isAssignableFrom(aObj.getClass())) {
1507                    return -((Comparable<Object>) bObj).compareTo(aObj);
1508                }
1509            }
1510            byte[] a = serialize(aObj);
1511            byte[] b = serialize(bObj);
1512            return compareNotNull(a, b);
1513        }
1514 
1515        @Override
1516        public int getMemory(Object obj) {
1517            DataType t = getType(obj);
1518            if (t == this) {
1519                return averageSize;
1520            }
1521            return t.getMemory(obj);
1522        }
1523 
1524        @Override
1525        public void write(WriteBuffer buff, Object obj) {
1526            DataType t = getType(obj);
1527            if (t != this) {
1528                t.write(buff, obj);
1529                return;
1530            }
1531            byte[] data = serialize(obj);
1532            // we say they are larger, because these objects
1533            // use quite a lot of disk space
1534            int size = data.length * 2;
1535            // adjust the average size
1536            // using an exponential moving average
1537            averageSize = (size + 15 * averageSize) / 16;
1538            buff.put((byte) TYPE_SERIALIZED_OBJECT).putVarInt(data.length)
1539                    .put(data);
1540        }
1541 
1542        @Override
1543        public Object read(ByteBuffer buff, int tag) {
1544            int len = DataUtils.readVarInt(buff);
1545            byte[] data = DataUtils.newBytes(len);
1546            buff.get(data);
1547            return deserialize(data);
1548        }
1549 
1550    }
1551 
1552}

[all classes][org.h2.mvstore.type]
EMMA 2.0.5312 (C) Vladimir Roubtsov