Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    *  Copyright (c) 2012 Jan Kotek
    *
    *  Licensed under the Apache License, Version 2.0 (the "License");
    *  you may not use this file except in compliance with the License.
    *  You may obtain a copy of the License at
    *
    *    http://www.apache.org/licenses/LICENSE-2.0
    *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */
  package org.mapdb;
  
  import java.io.*;
  import java.util.*;

Serializer which uses 'header byte' to serialize/deserialize most of classes from 'java.lang' and 'java.util' packages.

Author(s):
Jan Kotek
  
  @SuppressWarnings({ "unchecked""rawtypes" })
  public class SerializerBase implements Serializer{
  
  
      static final class knownSerializable{
          static final Set get = new HashSet(Arrays.asList(
              .,
              .,
              .,
  
              ...,
              .,
              .
  
      ));
      }
  
      public static void assertSerializable(Object o){
          if(o!=null && !(o instanceof Serializable)
                  && !..contains(o)){
              throw new IllegalArgumentException("Not serializable: "+o.getClass());
          }
      }

    
Utility class similar to ArrayList, but with fast identity search.
  
      protected final static class FastArrayList<K> {
  
          public int size ;
          public K[] data ;
  
          public FastArrayList(){
              =0;
               = (K[]) new Object[1];
          }
  
          public boolean forwardRefs = false;
  
  
          public void add(K o) {
              if (. == ) {
                  //grow array if necessary
                   = Arrays.copyOf(. * 2);
              }
  
              [] = o;
              ++;
          }



        
This method is reason why ArrayList is not used. Search an item in list and returns its index. It uses identity rather than 'equalsTo' One could argue that TreeMap should be used instead, but we do not expect large object trees. This search is VERY FAST compared to Maps, it does not allocate new instances or uses method calls.

Parameters:
obj to find in list
Returns:
index of object in list or -1 if not found
  
          public int identityIndexOf(Object obj) {
              for (int i = 0; i < i++) {
                  if (obj == [i]){
                       = true;
                     return i;
                 }
             }
             return -1;
         }
 
     }
 
 
 
 
     @Override
     public void serialize(final DataOutput outfinal Object objthrows IOException {
         serialize(outobjnull);
     }
 
 
     public void serialize(final DataOutput outfinal Object objFastArrayList<ObjectobjectStackthrows IOException {

        
try to find object on stack if it exist
 
         if (objectStack != null) {
             int indexInObjectStack = objectStack.identityIndexOf(obj);
             if (indexInObjectStack != -1) {
                 //object was already serialized, just write reference to it and return
                 out.write(.);
                 Utils.packInt(outindexInObjectStack);
                 return;
             }
             //add this object to objectStack
             objectStack.add(obj);
         }
 
         if (obj == null) {
             out.write(.);
             return;
         }
 
         final Class clazz = obj.getClass();

        
first try to serialize object without initializing object stac
 
         if (clazz == Integer.class) {
             serializeInt(out,  obj);
             return;
         } else if (clazz == Long.class) {
             serializeLong(out,  obj);
             return;
         } else if (clazz == String.class) {
             serializeString(out,  obj);
             return;
         }else if (clazz == Boolean.class) {
             out.write(((Boolean)obj)?.:.);
             return;
         } else if (clazz == Byte.class) {
             serializeByte(out,  obj);
             return;
         } else if (clazz == Character.class) {
             serializerChar(out,  obj);
             return;
         } else if (clazz == Short.class) {
             serializeShort(out,  obj);
             return;
         } else if (clazz == Float.class) {
             serializeFloat(out,  obj);
             return;
         } else if (clazz == Double.class) {
             serializeDouble(out,  obj);
             return;
         }
 
         serialize2(outobjobjectStackclazz);
 
     }
 
     private void serialize2(DataOutput outObject objFastArrayList<ObjectobjectStackClass clazzthrows IOException {
         if (obj instanceof byte[]) {
             byte[] b = (byte[]) obj;
             serializeByteArray(outb);
             return;
 
         } else if (obj instanceof boolean[]) {
             out.write(.);
             boolean[] a_bool = (boolean[]) obj;
             Utils.packInt(outa_bool.length);//write the number of booleans not the number of bytes
             byte[] a = booleanToByteArray(a_bool);
             out.write(a);
             return;
         } else if (obj instanceof short[]) {
             out.write(.);
             short[] a = (short[]) obj;
             Utils.packInt(outa.length);
             for(short s:aout.writeShort(s);
             return;
         } else if (obj instanceof char[]) {
             out.write(.);
             char[] a = (char[]) obj;
             Utils.packInt(outa.length);
             for(char s:aout.writeChar(s);
             return;
         } else if (obj instanceof float[]) {
             out.write(.);
             float[] a = (float[]) obj;
             Utils.packInt(outa.length);
             for(float s:aout.writeFloat(s);
             return;
         } else if (obj instanceof double[]) {
             out.write(.);
             double[] a = (double[]) obj;
             Utils.packInt(outa.length);
             for(double s:aout.writeDouble(s);
             return;
         } else if (obj instanceof int[]) {
             serializeIntArray(out, (int[]) obj);
             return;
         } else if (obj instanceof long[]) {
             serializeLongArray(out, (long[]) obj);
             return;
         } else if (clazz == BigInteger.class) {
             out.write(.);
             byte[] buf = ((BigIntegerobj).toByteArray();
             Utils.packInt(outbuf.length);
             out.write(buf);
             return;
         } else if (clazz == BigDecimal.class) {
             out.write(.);
             BigDecimal d = (BigDecimalobj;
             byte[] buf = d.unscaledValue().toByteArray();
             Utils.packInt(outbuf.length);
             out.write(buf);
             Utils.packInt(outd.scale());
             return;
         } else if (obj instanceof Class) {
             out.write(.);
             serializeClass(out, (Classobj);
             return;
         } else if (clazz == Date.class) {
             out.write(.);
             out.writeLong(((Dateobj).getTime());
             return;
         } else if (clazz == UUID.class) {
             out.write(.);
             out.writeLong(((UUIDobj).getMostSignificantBits());
             out.writeLong(((UUIDobj).getLeastSignificantBits());
             return;
         } else if(obj == .){
             out.write(.);
         } else if(clazz == BTreeKeySerializer.BasicKeySerializer.class){
             out.write(.);
             Utils.packInt(out.);
             assert(((BTreeKeySerializer.BasicKeySerializer)obj).==this);
             return;
         } else if(obj == .){
             out.write(.);
             Utils.packInt(out.);
             return;
         } else if(obj == .){
             out.write(.);
             Utils.packInt(out.);
             return;
         } else if(obj == .){
             out.write(.);
             Utils.packInt(out.);
             return;
         } else if(obj == .){
             out.write(.);
             Utils.packInt(out.);
             return;
         } else if(obj == .){
             out.write(.);
             Utils.packInt(out.);
             return;
         } else if(obj == .){
             out.write(.);
             Utils.packInt(out.);
             return;
         } else if(obj == .){
             out.write(.);
             Utils.packInt(out.);
             return;
         } else if(obj == .){
             out.write(.);
             Utils.packInt(out.);
             return;
         } else if(obj == .){
             out.write(.);
             Utils.packInt(out.);
             return;
         } else if(obj == ){
             out.write(.);
             Utils.packInt(out.);
             return;
         } else if(obj == ){
             out.write(.);
             Utils.packInt(out.);
             return;
         } else if(obj == ){
             out.write(.);
             Utils.packInt(out.);
             return;
         } else if(obj == .){
             out.write(.);
             Utils.packInt(out.);
             return;
 
 
         } else if(obj == this){
             out.write(.);
             Utils.packInt(out.);
             return;
         }


        
classes bellow need object stack, so initialize it if not alredy initialize
 
         if (objectStack == null) {
             objectStack = new FastArrayList();
             objectStack.add(obj);
         }
 
 
         if (obj instanceof Object[]) {
             Object[] b = (Object[]) obj;
             boolean packableLongs = b.length <= 255;
             boolean allNull = true;
             if (packableLongs) {
                 //check if it contains packable longs
                 for (Object o : b) {
                     if(o!=null){
                         allNull=false;
                         if (o.getClass() != Long.class || ((Longo < 0 && (Longo != .)) {
                             packableLongs = false;
                         }
                     }
 
                     if(!packableLongs && !allNull)
                         break;
                 }
             }else{
                 //check for all null
                 for (Object o : b) {
                     if(o!=null){
                         allNull=false;
                         break;
                     }
                 }
             }
             if(allNull){
                 out.write(.);
                 Utils.packInt(outb.length);
 
                 // Write classfor components
                 Class<?> componentType = obj.getClass().getComponentType();
                 serializeClass(outcomponentType);
 
             }else if (packableLongs) {
                 //packable Longs is special case,  it is often used in MapDB to reference fields
                 out.write(.);
                 out.write(b.length);
                 for (Object o : b) {
                     if (o == null)
                         Utils.packLong(out, 0);
                     else
                         Utils.packLong(out, (Longo + 1);
                 }
 
             } else {
                 out.write(.);
                 Utils.packInt(outb.length);
 
                 // Write classfor components
                 Class<?> componentType = obj.getClass().getComponentType();
                 serializeClass(outcomponentType);
 
                 for (Object o : b)
                     serialize(outoobjectStack);
 
             }
 
         } else if (clazz == ArrayList.class) {
             ArrayList l = (ArrayListobj;
             boolean packableLongs = l.size() < 255;
             if (packableLongs) {
                 //packable Longs is special case,  it is often used in MapDB to reference fields
                 for (Object o : l) {
                     if (o != null && (o.getClass() != Long.class || ((Longo < 0 && (Longo != .))) {
                         packableLongs = false;
                         break;
                     }
                 }
             }
             if (packableLongs) {
                 out.write(.);
                 out.write(l.size());
                 for (Object o : l) {
                     if (o == null)
                         Utils.packLong(out, 0);
                     else
                         Utils.packLong(out, (Longo + 1);
                 }
             } else {
                 serializeCollection(.outobjobjectStack);
             }
 
         } else if (clazz == LinkedList.class) {
             serializeCollection(.outobjobjectStack);
         } else if (clazz == TreeSet.class) {
             TreeSet l = (TreeSetobj;
             out.write(.);
             Utils.packInt(outl.size());
             serialize(outl.comparator(), objectStack);
             for (Object o : l)
                 serialize(outoobjectStack);
         } else if (clazz == HashSet.class) {
             serializeCollection(.outobjobjectStack);
         } else if (clazz == LinkedHashSet.class) {
             serializeCollection(.outobjobjectStack);
         } else if (clazz == TreeMap.class) {
             TreeMap l = (TreeMapobj;
             out.write(.);
             Utils.packInt(outl.size());
             serialize(outl.comparator(), objectStack);
             for (Object o : l.keySet()) {
                 serialize(outoobjectStack);
                 serialize(outl.get(o), objectStack);
             }
         } else if (clazz == HashMap.class) {
             serializeMap(.outobjobjectStack);
         } else if (clazz == LinkedHashMap.class) {
             serializeMap(.outobjobjectStack);
         } else if (clazz == Properties.class) {
             serializeMap(.outobjobjectStack);
         } else if (clazz == Fun.Tuple2.class){
             out.write(.);
             Fun.Tuple2 t = (Fun.Tuple2obj;
             serialize(outt.aobjectStack);
             serialize(outt.bobjectStack);
         } else if (clazz == Fun.Tuple3.class){
             out.write(.);
             Fun.Tuple3 t = (Fun.Tuple3obj;
             serialize(outt.aobjectStack);
             serialize(outt.bobjectStack);
             serialize(outt.cobjectStack);
         } else if (clazz == Fun.Tuple4.class){
             out.write(.);
             Fun.Tuple4 t = (Fun.Tuple4obj;
             serialize(outt.aobjectStack);
             serialize(outt.bobjectStack);
             serialize(outt.cobjectStack);
             serialize(outt.dobjectStack);
         } else if (clazz == BTreeKeySerializer.Tuple2KeySerializer.class){
             out.write(.);
             Utils.packInt(out.);
             serialize(outs.aComparator);
             serialize(outs.aSerializer);
             serialize(outs.bSerializer);
         } else if (clazz == BTreeKeySerializer.Tuple3KeySerializer.class){
             out.write(.);
             Utils.packInt(out.);
             serialize(outs.aComparator);
             serialize(outs.bComparator);
             serialize(outs.aSerializer);
             serialize(outs.bSerializer);
             serialize(outs.cSerializer);
         } else if (clazz == BTreeKeySerializer.Tuple4KeySerializer.class){
             out.write(.);
             Utils.packInt(out.);
             serialize(outs.aComparator);
             serialize(outs.bComparator);
             serialize(outs.cComparator);
             serialize(outs.aSerializer);
             serialize(outs.bSerializer);
             serialize(outs.cSerializer);
             serialize(outs.dSerializer);
         } else {
             serializeUnknownObject(outobjobjectStack);
         }
     }
 
     private void serializeString(DataOutput outObject objthrows IOException {
         String val = (Stringobj;
         int len = val.length();
         if(len == 0){
             out.write(.);
         }else{
             if (len<=10){
                 out.write(.+len);
             }else{
                 out.write(.);
                 Utils.packInt(outlen);
             }
             //TODO investigate if c could be negative here
             //TODO how about characters over 65K
             for (int i = 0; i < leni++)
                 Utils.packInt(out,(int)((Stringobj).charAt(i));
         }
         return;
     }
 
     private void serializeLongArray(DataOutput outlong[] objthrows IOException {
         long[] val = (long[]) obj;
         long max = .;
         long min = .;
         for (long i : val) {
             max = Math.max(maxi);
             min = Math.min(mini);
         }
         if (.<=min && max<=.) {
             out.write(.);
             Utils.packInt(outval.length);
             for (long i : valout.write((inti);
         }else if (. <= min && max <= .){
             out.write(.);
             Utils.packInt(outval.length);
             for (long i : valout.writeShort((inti);
         } else if (0 <= min) {
             out.write(.);
             Utils.packInt(outval.length);
             for (long l : val) Utils.packLong(outl);
         }else if (. <= min && max <= .){
             out.write(.);
             Utils.packInt(outval.length);
             for (long i : valout.writeInt((inti);
         } else {
             out.write(.);
             Utils.packInt(outval.length);
             for (long i : valout.writeLong(i);
         }
         return;
     }
 
     private void serializeIntArray(DataOutput outint[] objthrows IOException {
         int[] val = (int[]) obj;
         int max = .;
         int min = .;
         for (int i : val) {
             max = Math.max(maxi);
             min = Math.min(mini);
         }
         if (.<=min && max<=.) {
             out.write(.);
             Utils.packInt(outval.length);
             for (int i : valout.write(i);
         }else if (. <= min && max <= .){
             out.write(.);
             Utils.packInt(outval.length);
             for (int i : valout.writeShort(i);
         } else if (0 <= min) {
             out.write(.);
             Utils.packInt(outval.length);
             for (int l : val) Utils.packInt(outl);
         } else {
             out.write(.);
             Utils.packInt(outval.length);
             for (int i : valout.writeInt(i);
         }
         return;
     }
 
     private void serializeDouble(DataOutput outObject objthrows IOException {
         double v = (Doubleobj;
         if (v == -1D){
             out.write(.);
         }else if (v == 0D){
             out.write(.);
         }else if (v == 1D){
             out.write(.);
         }else if (v >= 0 && v <= 255 && (intv == v) {
             out.write(.);
             out.write((intv);
         } else if (v >= . && v <= . && (shortv == v) {
             out.write(.);
             out.writeShort((intv);
         } else if (v >= . && v <= . && (intv == v) {
             out.write(.);
             out.writeInt((intv);
         } else {
             out.write(.);
             out.writeDouble(v);
         }
         return;
     }
 
     private void serializeFloat(DataOutput outObject objthrows IOException {
         float v = (Floatobj;
         if (v == -1f)
             out.write(.);
         else if (v == 0f)
             out.write(.);
         else if (v == 1f)
             out.write(.);
         else if (v >= 0 && v <= 255 && (intv == v) {
             out.write(.);
             out.write((intv);
         } else if (v >= . && v <= . && (shortv == v) {
             out.write(.);
             out.writeShort((intv);
         } else {
             out.write(.);
             out.writeFloat(v);
         }
         return;
     }
 
     private void serializeShort(DataOutput outObject objthrows IOException {
         short val = (Shortobj;
         if (val == -1){
             out.write(.);
         }else if (val == 0){
             out.write(.);
         }else if (val == 1){
             out.write(.);
         }else if (val > 0 && val < 255) {
             out.write(.);
             out.write(val);
         }else if (val < 0 && val > -255) {
             out.write(.);
             out.write(-val);
         } else {
             out.write(.);
             out.writeShort(val);
         }
         return;
     }
 
     private void serializerChar(DataOutput outObject objthrows IOException {
         char val = (Character)obj;
         if(val==0){
             out.write(.);
         }else if(val==1){
             out.write(.);
         }else if (val<=255){
             out.write(.);
             out.write(val);
         }else{
             out.write(.);
             out.writeChar((Characterobj);
         }
         return;
     }
 
     private void serializeByte(DataOutput outObject objthrows IOException {
         byte val = (Byteobj;
         if (val == -1)
             out.write(.);
         else if (val == 0)
             out.write(.);
         else if (val == 1)
             out.write(.);
         else {
             out.write(.);
             out.writeByte(val);
         }
         return;
     }
 
     private void serializeLong(DataOutput outObject objthrows IOException {
         long val = (Longobj;
         if(val>=-9 && val<=16){
             out.write((int) (. + (val + 9)));
             return;
         }else if (val == .){
             out.write(.);
             return;
         }else if (val == .){
             out.write(.);
             return;
         } else if(((val>>>56)&0x7F)!=0){
             out.write(.);
             out.writeLong(val);
             return;
         }
 
         //calculate N bytes
         int size = 48;
         while(((val>>size)&0xFFL)==0 ){
             size-=8;
         }
 
         //write header
         out.write(. + (size/8)*2 + (val<0?-1:0));
 
         //write data
         while(size>=0){
             out.write((int) ((val>>size)&0xFFL));
             size-=8;
         }
     }
 
     private void serializeInt(DataOutput outObject objthrows IOException {
         int val = (Integerobj;
 
         switch(val){
             case -9:
             case -8:
             case -7:
             case -6:
             case -5:
             case -4:
             case -3:
             case -2:
             case -1:
             case 0:
             case 1:
             case 2:
             case 3:
             case 4:
             case 5:
             case 6:
             case 7:
             case 8:
             case 9:
             case 10:
             case 11:
             case 12:
             case 13:
             case 14:
             case 15:
             case 16:
                 out.write( (. + (val + 9)));
                 return;
             case .:
                 out.write(.);
                 return;
             case .:
                 out.write(.);
                 return;
 
         }
         if(((val>>>24)&0x7F)!=0){
             out.write(.);
             out.writeInt(val);
             return;
         }
 
         //calculate N bytes
         int size = 24;
         while(((val>>size)&0xFFL)==0 ){
             size-=8;
         }
 
         //write header
         out.write(. + (size/8)*2 + (val<0?-1:0));
 
         //write data
         while(size>=0){
             out.write((int) ((val>>size)&0xFFL));
             size-=8;
         }
     }
 
     protected void serializeClass(DataOutput outClass clazzthrows IOException {
         //TODO override in SerializerPojo
         out.writeUTF(clazz.getName());
     }
 
 
     private void serializeMap(int headerDataOutput outObject objFastArrayList<ObjectobjectStackthrows IOException {
         Map l = (Mapobj;
         out.write(header);
         Utils.packInt(outl.size());
         for (Object o : l.keySet()) {
             serialize(outoobjectStack);
             serialize(outl.get(o), objectStack);
         }
     }
 
     private void serializeCollection(int headerDataOutput outObject objFastArrayList<ObjectobjectStackthrows IOException {
         Collection l = (Collectionobj;
         out.write(header);
         Utils.packInt(outl.size());
 
         for (Object o : l)
             serialize(outoobjectStack);
 
     }
 
     private void serializeByteArray(DataOutput outbyte[] bthrows IOException {
         boolean allEqual = b.length>0;
         //check if all values in byte[] are equal
         for(int i=1;i<b.length;i++){
             if(b[i-1]!=b[i]){
                 allEqual=false;
                 break;
             }
         }
         if(allEqual){
             out.write(.);
             Utils.packInt(outb.length);
             out.write(b[0]);
         }else{
             out.write(.);
             Utils.packInt(outb.length);
             out.write(b);
         }
     }
 
 
     static String deserializeString(DataInput bufint lenthrows IOException {
         char[] b = new char[len];
         for (int i = 0; i < leni++)
             b[i] = (char) Utils.unpackInt(buf);
 
         return new String(b);
     }
 
 
     @Override
     public Object deserialize(DataInput isint capacitythrows IOException {
         if(capacity==0) return null;
         return deserialize(isnull);
     }
 
     public Object deserialize(DataInput isFastArrayList<ObjectobjectStackthrows IOException {
 
         Object ret = null;
 
         int ir = 0;
         long lr = 0;
         final int head = is.readUnsignedByte();

        
first try to deserialize object without allocating object stac
 
         switch (head) {
             case .:
                 throw new IOError(new IOException("Zero Header, data corrupted"));
             case .:
                 break;
             case .:
                 ret = .;
                 break;
             case .:
                 ret = .;
                 break;
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
                 ret = (head-.-9);
                 break;
             case .:
                 ret = .;
                 break;
             case .:
                 ret = .;
                 break;
 
             case .:
             case .:
                 ir =  (is.readUnsignedByte()&0xFF);
             case .:
             case .:
                 ir = (ir<<8) | (is.readUnsignedByte()&0xFF);
             case .:
             case .:
                 ir = (ir<<8) | (is.readUnsignedByte()&0xFF);
                 if(head%2==0) ir=-ir;
                 ret = ir;
                 break;
 
             case .:
                 ret = is.readInt();
                 break;
 
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
                 ret = (long) (head - . - 9);
                 break;
             case .:
                 ret = .;
                 break;
             case .:
                 ret = .;
                 break;
 
             case .:
             case .:
                 lr = is.readUnsignedByte()&0xFFL;
             case .:
             case .:
                 lr = (lr<<8) | (is.readUnsignedByte()&0xFFL);
             case .:
             case .:
                 lr = (lr<<8) | (is.readUnsignedByte()&0xFFL);
             case .:
             case .:
                 lr = (lr<<8) | (is.readUnsignedByte()&0xFFL);
             case .:
             case .:
                 lr = (lr<<8) | (is.readUnsignedByte()&0xFFL);
             case .:
             case .:
                 lr = (lr<<8) | (is.readUnsignedByte()&0xFFL);
             case .:
             case .:
                 lr = (lr<<8) | (is.readUnsignedByte()&0xFFL);
                 if(head%2==1) lr=-lr;
                 ret = lr;
                 break;
 
             case .:
                 ret = is.readLong();
                 break;
 
             case .:
                 ret = (byte) -1;
                 break;
             case .:
                 ret = (byte) 0;
                 break;
             case .:
                 ret = (byte) 1;
                 break;
             case .:
                 ret = is.readByte();
                 break;
 
             case .:
                 ret = (char) 0;
                 break;
             case .:
                 ret = (char) 1;
                 break;
             case .:
                 ret = (charis.readUnsignedByte();
                 break;
             case .:
                 ret = is.readChar();
                 break;
 
 
             case .:
                 ret = (short) -1;
                 break;
             case .:
                 ret = (short) 0;
                 break;
             case .:
                 ret = (short) 1;
                 break;
             case .:
                 ret = (shortis.readUnsignedByte();
                 break;
             case .:
                 ret = ((short) -is.readUnsignedByte());
                 break;
             case .:
                 ret = is.readShort();
                 break;
 
             case .:
                 ret = (float) -1;
                 break;
             case .:
                 ret = (float) 0;
                break;