]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.common/src/org/simantics/db/common/WriteBindings.java
Add support for strings that are longer than 127 characters
[simantics/platform.git] / bundles / org.simantics.db.common / src / org / simantics / db / common / WriteBindings.java
index d749d6e91684fc793d067502bab11e964d1663a0..e9ecce63c8ba0eac39b71e933edb801247f17b04 100644 (file)
-package org.simantics.db.common;\r
-\r
-import java.io.IOException;\r
-import java.io.UTFDataFormatException;\r
-import java.nio.charset.Charset;\r
-import java.util.Arrays;\r
-\r
-import org.simantics.databoard.Bindings;\r
-import org.simantics.databoard.Datatypes;\r
-import org.simantics.databoard.binding.Binding;\r
-import org.simantics.databoard.binding.error.BindingConstructionException;\r
-import org.simantics.databoard.binding.impl.LongBindingDefault;\r
-import org.simantics.databoard.binding.impl.StringBindingDefault;\r
-import org.simantics.databoard.binding.mutable.Variant;\r
-import org.simantics.databoard.serialization.RuntimeSerializerConstructionException;\r
-import org.simantics.databoard.serialization.SerializationException;\r
-import org.simantics.databoard.serialization.Serializer;\r
-import org.simantics.databoard.serialization.impl.LongSerializer;\r
-import org.simantics.databoard.serialization.impl.ModifiedUTF8StringSerializer;\r
-import org.simantics.graph.representation.External;\r
-import org.simantics.graph.representation.Identity;\r
-import org.simantics.graph.representation.Internal;\r
-import org.simantics.graph.representation.Optional;\r
-import org.simantics.graph.representation.Root;\r
-import org.simantics.graph.representation.TransferableGraph1;\r
-import org.simantics.graph.representation.Value;\r
-\r
-public class WriteBindings {\r
-\r
-       static class STRING_SERIALIZER extends ModifiedUTF8StringSerializer {\r
-\r
-               public static final Charset UTF8 = Charset.forName("utf-8");\r
-\r
-               public static STRING_SERIALIZER INSTANCE = new STRING_SERIALIZER();\r
-\r
-               public STRING_SERIALIZER() {\r
-                       super(STRING_BINDING.INSTANCE);\r
-               }\r
-\r
-               static byte[] writeUTF(String str) throws IOException {\r
-\r
-                       int strlen = str.length();\r
-                       int utflen = 0;\r
-                       int c/*, count = 0*/;\r
-\r
-                       /* use charAt instead of copying String to char array */\r
-                       for (int i = 0; i < strlen; i++) {\r
-                               c = str.charAt(i);\r
-                               if ((c >= 0x0001) && (c <= 0x007F)) {\r
-                                       utflen++;\r
-                               } else if (c > 0x07FF) {\r
-                                       utflen += 3;\r
-                               } else {\r
-                                       utflen += 2;\r
-                               }\r
-                       }\r
-\r
-                       if (utflen > 65535)\r
-                               throw new UTFDataFormatException(\r
-                                               "encoded string too long: " + utflen + " bytes");\r
-\r
-                       int byteIndex = 0;\r
-                       byte[] bytearr;\r
-\r
-                       if(utflen < 0x80) {\r
-                               bytearr = new byte[utflen+1];\r
-                               bytearr[byteIndex++] = ((byte)utflen);\r
-                       }\r
-                       else {\r
-                               utflen -= 0x80;\r
-                               if(utflen < 0x4000) {\r
-                                       bytearr = new byte[utflen+2];\r
-                                       bytearr[byteIndex++] = (byte)( ((utflen&0x3f) | 0x80) );\r
-                                       bytearr[byteIndex++] = (byte)( (utflen>>>6) );\r
-                               }\r
-                               else {\r
-                                       utflen -= 0x4000;\r
-                                       if(utflen < 0x200000) {\r
-                                               bytearr = new byte[utflen+3];\r
-                                               bytearr[byteIndex++] = (byte)( ((utflen&0x1f) | 0xc0) );\r
-                                               bytearr[byteIndex++] = (byte)( ((utflen>>>5)&0xff) );\r
-                                               bytearr[byteIndex++] = (byte)( ((utflen>>>13)&0xff) );  \r
-                                       }\r
-                                       else {\r
-                                               utflen -= 0x200000;\r
-                                               if(utflen < 0x10000000) {\r
-                                                       bytearr = new byte[utflen+4];\r
-                                                       bytearr[byteIndex++] = (byte)( ((utflen&0x0f) | 0xe0) );\r
-                                                       bytearr[byteIndex++] = (byte)( ((utflen>>>4)&0xff) );\r
-                                                       bytearr[byteIndex++] = (byte)( ((utflen>>>12)&0xff) );  \r
-                                                       bytearr[byteIndex++] = (byte)( ((utflen>>>20)&0xff) );\r
-                                               }\r
-                                               else {\r
-                                                       utflen -= 0x10000000;\r
-                                                       bytearr = new byte[utflen+5];\r
-                                                       bytearr[byteIndex++] = (byte)( ((utflen&0x07) | 0xf0) );\r
-                                                       bytearr[byteIndex++] = (byte)( ((utflen>>>3)&0xff) );\r
-                                                       bytearr[byteIndex++] = (byte)( ((utflen>>>11)&0xff) );  \r
-                                                       bytearr[byteIndex++] = (byte)( ((utflen>>>19)&0xff) );\r
-                                                       bytearr[byteIndex++] = (byte)( ((utflen>>>27)&0xff) );\r
-                                               }\r
-                                       }                               \r
-                               }\r
-                       }       \r
-\r
-\r
-                       int i=0;\r
-                       for (i=0; i<strlen; i++) {\r
-                               c = str.charAt(i);\r
-                               if (!((c >= 0x0001) && (c <= 0x007F))) break;\r
-                               bytearr[byteIndex++] = (byte)(c);\r
-                       }\r
-\r
-                       for (;i < strlen; i++){\r
-                               c = str.charAt(i);\r
-                               if ((c >= 0x0001) && (c <= 0x007F)) {\r
-                                       bytearr[byteIndex++] = (byte)( c );\r
-                               } else if (c > 0x07FF) {\r
-                                       bytearr[byteIndex++] = (byte)(0xE0 | ((c >> 12) & 0x0F));\r
-                                       bytearr[byteIndex++] = (byte)(0x80 | ((c >>  6) & 0x3F));\r
-                                       bytearr[byteIndex++] = (byte)(0x80 | ((c >>  0) & 0x3F));\r
-                               } else {\r
-                                       bytearr[byteIndex++] = (byte)(0xC0 | ((c >>  6) & 0x1F));\r
-                                       bytearr[byteIndex++] = (byte)(0x80 | ((c >>  0) & 0x3F));\r
-                               }\r
-                       }\r
-\r
-                       return bytearr;\r
-\r
-               }\r
-\r
-               @Override\r
-               public byte[] serialize(Object obj) throws IOException {\r
-                       try {\r
-                               return writeUTF((String)obj);\r
-                       } catch (IOException e) {\r
-                               throw new SerializationException();\r
-                       }\r
-                       \r
-               }\r
-               \r
-       }\r
-\r
-       static class BYTE_ARRAY_SERIALIZER extends LongSerializer {\r
-\r
-               public static BYTE_ARRAY_SERIALIZER INSTANCE = new BYTE_ARRAY_SERIALIZER();\r
-\r
-               public BYTE_ARRAY_SERIALIZER() {\r
-                       super(BYTE_ARRAY_BINDING.INSTANCE);\r
-               }\r
-               \r
-               @Override\r
-               public byte[] serialize(Object obj) throws IOException {\r
-                       \r
-                       return (byte[])obj;\r
-\r
-               }\r
-               \r
-               @Override\r
-               public Object deserialize(byte[] data) throws IOException {\r
-                       return data;\r
-               }\r
-               \r
-       }\r
-\r
-       final static class LONG_ARRAY_SERIALIZER extends LongSerializer {\r
-\r
-               public static LONG_ARRAY_SERIALIZER INSTANCE = new LONG_ARRAY_SERIALIZER();\r
-\r
-               public LONG_ARRAY_SERIALIZER() {\r
-                       super(LONG_ARRAY_BINDING.INSTANCE);\r
-               }\r
-               \r
-               final private void loop(byte[] result, int index, long l) {\r
-                       result[index+7] = (byte)l;l >>>= 8;\r
-                       result[index+6] = (byte)l;l >>>= 8;\r
-                       result[index+5] = (byte)l;l >>>= 8;\r
-                       result[index+4] = (byte)l;l >>>= 8;\r
-                       result[index+3] = (byte)l;l >>>= 8;\r
-                       result[index+2] = (byte)l;l >>>= 8;\r
-                       result[index+1] = (byte)l;l >>>= 8;\r
-                       result[index] = (byte)l;l >>>= 8;\r
-                       \r
-//                     result[index+6] = (byte)(l & 0xFF);\r
-//                     l >>>= 8;\r
-//                     result[index+5] = (byte)(l & 0xFF);\r
-//                     l >>>= 8;\r
-//                     result[index+4] = (byte)(l & 0xFF);\r
-//                     l >>>= 8;\r
-//                     result[index+3] = (byte)(l & 0xFF);\r
-//                     l >>>= 8;\r
-//                     result[index+2] = (byte)(l & 0xFF);\r
-//                     l >>>= 8;\r
-//                     result[index+1] = (byte)(l & 0xFF);\r
-//                     l >>>= 8;\r
-//                     result[index] = (byte)(l & 0xFF);\r
-//                     l >>>= 8;\r
-               }\r
-               \r
-               @Override\r
-               public byte[] serialize(Object obj) throws IOException {\r
-                       \r
-                       long[] data = (long[])obj;\r
-                       byte[] result = new byte[4+8*data.length];\r
-                       \r
-                       int len = data.length;\r
-                       \r
-                       result[3] = (byte)(len & 0xFF);\r
-                       len >>>= 8;\r
-                       result[2] = (byte)(len & 0xFF);\r
-                       len >>>= 8;\r
-                       result[1] = (byte)(len & 0xFF);\r
-                       len >>>= 8;\r
-                       result[0] = (byte)(len & 0xFF);\r
-\r
-                       int index = 4;\r
-\r
-                       for(int i=0;i<data.length;i++) {\r
-\r
-                               loop(result, index, data[i]);\r
-\r
-//                             long l = data[i];\r
-\r
-//                             result[index+7] = (byte)(l & 0xFF);\r
-//                             l >>>= 8;\r
-//                             result[index+6] = (byte)(l & 0xFF);\r
-//                             l >>>= 8;\r
-//                             result[index+5] = (byte)(l & 0xFF);\r
-//                             l >>>= 8;\r
-//                             result[index+4] = (byte)(l & 0xFF);\r
-//                             l >>>= 8;\r
-//                             result[index+3] = (byte)(l & 0xFF);\r
-//                             l >>>= 8;\r
-//                             result[index+2] = (byte)(l & 0xFF);\r
-//                             l >>>= 8;\r
-//                             result[index+1] = (byte)(l & 0xFF);\r
-//                             l >>>= 8;\r
-//                             result[index] = (byte)(l & 0xFF);\r
-//                             l >>>= 8;\r
-                               \r
-                               index += 8;\r
-\r
-                       }\r
-                       \r
-                       return result;\r
-\r
-               }\r
-               \r
-       }\r
-\r
-       static class TRANSFERABLE_GRAPH_SERIALIZER extends LongSerializer {\r
-\r
-               public static TRANSFERABLE_GRAPH_SERIALIZER INSTANCE = new TRANSFERABLE_GRAPH_SERIALIZER();\r
-\r
-               public TRANSFERABLE_GRAPH_SERIALIZER() {\r
-                       super(TRANSFERABLE_GRAPH_BINDING.INSTANCE);\r
-               }\r
-               \r
-               static int writeUTF(String str, byte[] bytearr, int byteIndex) throws IOException {\r
-                       \r
-                       int strlen = str.length();\r
-                       int utflen = 0;\r
-                       int c;\r
-                       int count = byteIndex;\r
-\r
-                       /* use charAt instead of copying String to char array */\r
-                       for (int i = 0; i < strlen; i++) {\r
-                               c = str.charAt(i);\r
-                               if ((c >= 0x0001) && (c <= 0x007F)) {\r
-                                       utflen++;\r
-                               } else if (c > 0x07FF) {\r
-                                       utflen += 3;\r
-                               } else {\r
-                                       utflen += 2;\r
-                               }\r
-                       }\r
-\r
-                       if (utflen > 65535)\r
-                               throw new UTFDataFormatException(\r
-                                               "encoded string too long: " + utflen + " bytes");\r
-\r
-//                     byte[] bytearr = new byte[utflen+2];\r
-\r
-                       if(utflen < 0x80) {\r
-                               bytearr[count++] = ((byte)utflen);\r
-                       }\r
-                       else {\r
-                               utflen -= 0x80;\r
-                               if(utflen < 0x4000) {\r
-                                       bytearr[count++] = (byte)( ((utflen&0x3f) | 0x80) );\r
-                                       bytearr[count++] = (byte)( (utflen>>>6) );\r
-                               }\r
-                               else {\r
-                                       utflen -= 0x4000;\r
-                                       if(utflen < 0x200000) {\r
-                                               bytearr[count++] = (byte)( ((utflen&0x1f) | 0xc0) );\r
-                                               bytearr[count++] = (byte)( ((utflen>>>5)&0xff) );\r
-                                               bytearr[count++] = (byte)( ((utflen>>>13)&0xff) );      \r
-                                       }\r
-                                       else {\r
-                                               utflen -= 0x200000;\r
-                                               if(utflen < 0x10000000) {\r
-                                                       bytearr[count++] = (byte)( ((utflen&0x0f) | 0xe0) );\r
-                                                       bytearr[count++] = (byte)( ((utflen>>>4)&0xff) );\r
-                                                       bytearr[count++] = (byte)( ((utflen>>>12)&0xff) );      \r
-                                                       bytearr[count++] = (byte)( ((utflen>>>20)&0xff) );\r
-                                               }\r
-                                               else {\r
-                                                       utflen -= 0x10000000;\r
-                                                       bytearr[count++] = (byte)( ((utflen&0x07) | 0xf0) );\r
-                                                       bytearr[count++] = (byte)( ((utflen>>>3)&0xff) );\r
-                                                       bytearr[count++] = (byte)( ((utflen>>>11)&0xff) );      \r
-                                                       bytearr[count++] = (byte)( ((utflen>>>19)&0xff) );\r
-                                                       bytearr[count++] = (byte)( ((utflen>>>27)&0xff) );\r
-                                               }\r
-                                       }                               \r
-                               }\r
-                       }       \r
-\r
-                       int i=0;\r
-                       for (i=0; i<strlen; i++) {\r
-                               c = str.charAt(i);\r
-                               if (!((c >= 0x0001) && (c <= 0x007F))) break;\r
-                               bytearr[count++] = (byte) c;\r
-                       }\r
-\r
-                       for (;i < strlen; i++){\r
-                               c = str.charAt(i);\r
-                               if ((c >= 0x0001) && (c <= 0x007F)) {\r
-                                       bytearr[count++] = (byte) c;\r
-\r
-                               } else if (c > 0x07FF) {\r
-                                       bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));\r
-                                       bytearr[count++] = (byte) (0x80 | ((c >>  6) & 0x3F));\r
-                                       bytearr[count++] = (byte) (0x80 | ((c >>  0) & 0x3F));\r
-                               } else {\r
-                                       bytearr[count++] = (byte) (0xC0 | ((c >>  6) & 0x1F));\r
-                                       bytearr[count++] = (byte) (0x80 | ((c >>  0) & 0x3F));\r
-                               }\r
-                       }\r
-                       \r
-                       return count - byteIndex;\r
-                       \r
-               }\r
-               \r
-               @Override\r
-               public byte[] serialize(Object obj) throws IOException {\r
-                       \r
-                       TransferableGraph1 tg = (TransferableGraph1)obj;\r
-                       \r
-                       return Bindings\r
-                                       .getSerializerUnchecked(TransferableGraph1.class)\r
-                                       .serialize(tg);\r
-/*\r
-                       // 16 = resourceCount + 3 arrays\r
-//                     long start = System.nanoTime();\r
-                       int actualSize = 16 + 8*tg.values.length + 4*tg.statements.length + 5*tg.identities.length;\r
-                       for(Value v : tg.values) actualSize += v.value.length;\r
-                       for(Identity id : tg.identities) { \r
-                               if(id.definition instanceof Internal) actualSize += (4 + ((Internal)id.definition).name.length() + 5);\r
-                               else if(id.definition instanceof External) actualSize += (4 + ((External)id.definition).name.length() + 5);\r
-                               else if(id.definition instanceof Root) actualSize += (((Root)id.definition).name.length() + ((Root)id.definition).type.length() + 10);\r
-                               else if(id.definition instanceof Optional) actualSize += (4 + ((Optional)id.definition).name.length() + 5);\r
-                       }\r
-//                     long end = System.nanoTime() - start;\r
-//                     System.err.println("size took " + 1e-9*end);\r
-                       \r
-//                     long start2 = System.nanoTime();\r
-                       \r
-                       \r
-                       byte[] bytes = new byte[actualSize];\r
-                       int byteIndex = 0;\r
-\r
-                       int i = tg.resourceCount;\r
-                       \r
-                       bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;\r
-                       bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;\r
-                       bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;\r
-                       bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;\r
-                       byteIndex+=4;\r
-                       \r
-                       i = tg.identities.length;\r
-\r
-                       bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;\r
-                       bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;\r
-                       bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;\r
-                       bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;\r
-                       byteIndex+=4;\r
-                       \r
-                       for(Identity id : tg.identities) {\r
-\r
-                               i = id.resource;\r
-                               bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;\r
-                               bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;\r
-                               bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;\r
-                               bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;\r
-                               byteIndex+=4;\r
-                               \r
-                               if(id.definition instanceof Internal) {\r
-\r
-                                       Internal r = (Internal)id.definition;\r
-\r
-                                       bytes[byteIndex++] = 3;\r
-\r
-                                       i = r.parent;\r
-                                       bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;\r
-                                       bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;\r
-                                       bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;\r
-                                       bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;\r
-                                       byteIndex+=4;\r
-                                       \r
-                                       byteIndex += writeUTF(r.name, bytes, byteIndex);\r
-\r
-                               } else if(id.definition instanceof External) {\r
-\r
-                                       External r = (External)id.definition;\r
-\r
-                                       bytes[byteIndex++] = 1;\r
-\r
-                                       i = r.parent;\r
-                                       bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;\r
-                                       bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;\r
-                                       bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;\r
-                                       bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;\r
-                                       byteIndex+=4;\r
-                                       \r
-                                       byteIndex += writeUTF(r.name, bytes, byteIndex);\r
-                                       \r
-                               } else if(id.definition instanceof Root) {\r
-                                       \r
-                                       bytes[byteIndex++] = 0;\r
-                                       \r
-                                       Root r = (Root)id.definition;\r
-                                       byteIndex += writeUTF(r.name, bytes, byteIndex);\r
-                                       byteIndex += writeUTF(r.type, bytes, byteIndex);\r
-                                       \r
-                               } else if(id.definition instanceof Optional) {\r
-\r
-                                       Optional r = (Optional)id.definition;\r
-\r
-                                       bytes[byteIndex++] = 2;\r
-\r
-                                       i = r.parent;\r
-                                       bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;\r
-                                       bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;\r
-                                       bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;\r
-                                       bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;\r
-                                       byteIndex+=4;\r
-                                       \r
-                                       byteIndex += writeUTF(r.name, bytes, byteIndex);\r
-                                       \r
-                               }\r
-                               \r
-                       }\r
-                       \r
-                       i = tg.statements.length;\r
-                       bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;\r
-                       bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;\r
-                       bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;\r
-                       bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;\r
-                       byteIndex+=4;\r
-                       \r
-                       for(int s : tg.statements) {\r
-                               i = s;\r
-                               bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;\r
-                               bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;\r
-                               bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;\r
-                               bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;\r
-                               byteIndex+=4;\r
-                       }\r
-\r
-                       i = tg.values.length;\r
-                       bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;\r
-                       bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;\r
-                       bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;\r
-                       bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;\r
-                       byteIndex+=4;\r
-\r
-                       for(Value v : tg.values) {\r
-                               \r
-                               i = v.resource;\r
-                               bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;\r
-                               bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;\r
-                               bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;\r
-                               bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;\r
-                               byteIndex+=4;\r
-\r
-                               i = v.value.length;\r
-                               bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;\r
-                               bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;\r
-                               bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;\r
-                               bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;\r
-                               byteIndex+=4;\r
-                               \r
-                               System.arraycopy(v.value, 0, bytes, byteIndex, v.value.length);\r
-                               byteIndex += v.value.length;\r
-                               \r
-                       }\r
-\r
-//                     return bytes;\r
-                       \r
-//                     byte[] result = new byte[byteIndex];\r
-//                     System.arraycopy(bytes, 0, result, 0, byteIndex);\r
-//                     \r
-//                     byte[] result = Arrays.copyOf(bytes, byteIndex); \r
-                       \r
-//                     long end2 = System.nanoTime() - start2;\r
-//                     System.err.println("size2 took " + 1e-9*end2);\r
-\r
-                       return bytes; \r
-                       \r
-//                     long[] data = (long[])obj;\r
-//                     byte[] result = new byte[4+8*data.length];\r
-//                     \r
-//                     int len = data.length;\r
-//                     \r
-//                     result[3] = (byte)(len & 0xFF);\r
-//                     len >>>= 8;\r
-//                     result[2] = (byte)(len & 0xFF);\r
-//                     len >>>= 8;\r
-//                     result[1] = (byte)(len & 0xFF);\r
-//                     len >>>= 8;\r
-//                     result[0] = (byte)(len & 0xFF);\r
-//\r
-//                     int index = 4;\r
-//\r
-//                     for(int i=0;i<data.length;i++) {\r
-//                             \r
-//                             long l = data[i];\r
-//\r
-//                             result[index+7] = (byte)(l & 0xFF);\r
-//                             l >>>= 8;\r
-//                             result[index+6] = (byte)(l & 0xFF);\r
-//                             l >>>= 8;\r
-//                             result[index+5] = (byte)(l & 0xFF);\r
-//                             l >>>= 8;\r
-//                             result[index+4] = (byte)(l & 0xFF);\r
-//                             l >>>= 8;\r
-//                             result[index+3] = (byte)(l & 0xFF);\r
-//                             l >>>= 8;\r
-//                             result[index+2] = (byte)(l & 0xFF);\r
-//                             l >>>= 8;\r
-//                             result[index+1] = (byte)(l & 0xFF);\r
-//                             l >>>= 8;\r
-//                             result[index] = (byte)(l & 0xFF);\r
-//                             l >>>= 8;\r
-//                             \r
-//                             index += 8;\r
-//\r
-//                     }\r
-//                     \r
-//                     return result;\r
-*/\r
-               }\r
-               \r
-               \r
-               final private String utf(byte[] bytes) {\r
-                       \r
-                       char[] chars = new char[bytes.length];\r
-                       \r
-                       int index = 0;\r
-                       int length = bytes[index++]&0xff; \r
-                       if(length >= 0x80) {\r
-                               if(length >= 0xc0) {\r
-                                       if(length >= 0xe0) {\r
-                                               if(length >= 0xf0) {\r
-                                                       length &= 0x0f;\r
-                                                       length += ((bytes[index++]&0xff)<<3);\r
-                                                       length += ((bytes[index++]&0xff)<<11);\r
-                                                       length += ((bytes[index++]&0xff)<<19);\r
-                                                       length += 0x10204080;\r
-                                               }\r
-                                               else {\r
-                                                       length &= 0x1f;\r
-                                                       length += ((bytes[index++]&0xff)<<4);\r
-                                                       length += ((bytes[index++]&0xff)<<12);\r
-                                                       length += ((bytes[index++]&0xff)<<20);\r
-                                                       length += 0x204080;\r
-                                               }\r
-                                       }\r
-                                       else {\r
-                                               length &= 0x3f;\r
-                                               length += ((bytes[index++]&0xff)<<5);\r
-                                               length += ((bytes[index++]&0xff)<<13);\r
-                                               length += 0x4080;\r
-                                       }\r
-                               }\r
-                               else {\r
-                                       length &= 0x7f;\r
-                                       length += ((bytes[index++]&0xff)<<6);\r
-                                       length += 0x80;\r
-                               }\r
-                       }\r
-                       \r
-                       int i = 0;\r
-                       int target = length+index;\r
-                       while(index < target) {\r
-                               int c = bytes[index++]&0xff;\r
-                               if(c <= 0x7F) {\r
-                                       chars[i++] = (char)(c&0x7F);\r
-                               } else if (c > 0x07FF) {\r
-                                       int c2 = bytes[index++]&0xff;\r
-                                       int c3 = bytes[index++]&0xff;\r
-                                       chars[i++] = (char)(((c&0xf)<<12) + ((c2&0x3f)<<6) + (c3&0x3f)); \r
-                               } else {\r
-                                       int c2 = bytes[index++]&0xff;\r
-                                       chars[i++] = (char)(((c&0x1f)<<6) + (c2&0x3f)); \r
-                               }\r
-                               \r
-                       }\r
-                       \r
-                       return new String(chars, 0, i);\r
-                       \r
-               }\r
-\r
-               \r
-               @Override\r
-               public Object deserialize(byte[] data) throws IOException {\r
-                       return utf(data);\r
-               }\r
-               \r
-       }\r
-\r
-       static class STRING_BINDING extends StringBindingDefault {\r
-               \r
-               public static STRING_BINDING INSTANCE = new STRING_BINDING();\r
-               \r
-               public STRING_BINDING() {\r
-                       super(Datatypes.STRING);\r
-               }\r
-               \r
-               @Override\r
-               public Serializer serializer() throws RuntimeSerializerConstructionException {\r
-                       \r
-                       return STRING_SERIALIZER.INSTANCE;\r
-                       \r
-               }\r
-               \r
-               @Override\r
-               public boolean isInstance(Object obj) {\r
-                       return obj instanceof String;\r
-               }\r
-               \r
-       }\r
-       \r
-       static class BYTE_ARRAY_BINDING extends LongBindingDefault {\r
-               \r
-               public static BYTE_ARRAY_BINDING INSTANCE = new BYTE_ARRAY_BINDING();\r
-               \r
-               public BYTE_ARRAY_BINDING() {\r
-                       super(Datatypes.LONG);\r
-               }\r
-               \r
-               @Override\r
-               public Serializer serializer() throws RuntimeSerializerConstructionException {\r
-                       \r
-                       return BYTE_ARRAY_SERIALIZER.INSTANCE;\r
-                       \r
-               }\r
-               \r
-               @Override\r
-               public boolean isInstance(Object obj) {\r
-                       return obj instanceof byte[];\r
-               }\r
-               \r
-       }\r
-\r
-       static class LONG_ARRAY_BINDING extends LongBindingDefault {\r
-               \r
-               public static LONG_ARRAY_BINDING INSTANCE = new LONG_ARRAY_BINDING();\r
-               \r
-               public LONG_ARRAY_BINDING() {\r
-                       super(Datatypes.LONG);\r
-               }\r
-               \r
-               @Override\r
-               public Serializer serializer() throws RuntimeSerializerConstructionException {\r
-                       \r
-                       return LONG_ARRAY_SERIALIZER.INSTANCE;\r
-                       \r
-               }\r
-               \r
-       }\r
-\r
-       \r
-       static class TRANSFERABLE_GRAPH_BINDING extends LongBindingDefault {\r
-               \r
-               public static TRANSFERABLE_GRAPH_BINDING INSTANCE = new TRANSFERABLE_GRAPH_BINDING();\r
-               \r
-               public TRANSFERABLE_GRAPH_BINDING() {\r
-                       super(Datatypes.LONG);\r
-               }\r
-               \r
-               @Override\r
-               public Serializer serializer() throws RuntimeSerializerConstructionException {\r
-                       \r
-                       return TRANSFERABLE_GRAPH_SERIALIZER.INSTANCE;\r
-                       \r
-               }\r
-               \r
-       }\r
-\r
-       public static Binding STRING = STRING_BINDING.INSTANCE;\r
-       public static Binding BYTE_ARRAY = BYTE_ARRAY_BINDING.INSTANCE;\r
-       public static Binding LONG_ARRAY = LONG_ARRAY_BINDING.INSTANCE;\r
-       public static Binding TRANSFERABLE_GRAPH = TRANSFERABLE_GRAPH_BINDING.INSTANCE;\r
-\r
-       public static void main(String[] args) {\r
-\r
-               TransferableGraph1 tg = new TransferableGraph1(123,new Identity[] { \r
-                               new Identity(11, new Root("foo", "bar1")), \r
-                               new Identity(12, new External(21, "bar2")), \r
-                               new Identity(13, new Internal(22, "bar3")), \r
-                               new Identity(14, new Optional(23, "bar4")) },\r
-                               new int[] { 1, 2, 3 },\r
-                               new Value[] { new Value(31, new Variant(Bindings.INTEGER, 123)) });\r
-\r
-               try {\r
-                       System.err.println(Arrays.toString(Bindings.getSerializerUnchecked(Bindings.getBinding(TransferableGraph1.class)).serialize(tg)));\r
-                       System.err.println(Arrays.toString(WriteBindings.TRANSFERABLE_GRAPH_SERIALIZER.INSTANCE.serialize(tg)));\r
-               } catch (RuntimeSerializerConstructionException e) {\r
-                       // TODO Auto-generated catch block\r
-                       e.printStackTrace();\r
-               } catch (IOException e) {\r
-                       // TODO Auto-generated catch block\r
-                       e.printStackTrace();\r
-               } catch (BindingConstructionException e) {\r
-                       // TODO Auto-generated catch block\r
-                       e.printStackTrace();\r
-               }\r
-               \r
-       }\r
-       \r
-}\r
+package org.simantics.db.common;
+
+import java.io.IOException;
+import java.io.UTFDataFormatException;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.Datatypes;
+import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.binding.error.BindingConstructionException;
+import org.simantics.databoard.binding.impl.LongBindingDefault;
+import org.simantics.databoard.binding.impl.StringBindingDefault;
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.databoard.serialization.RuntimeSerializerConstructionException;
+import org.simantics.databoard.serialization.SerializationException;
+import org.simantics.databoard.serialization.Serializer;
+import org.simantics.databoard.serialization.impl.LongSerializer;
+import org.simantics.databoard.serialization.impl.ModifiedUTF8StringSerializer;
+import org.simantics.graph.representation.External;
+import org.simantics.graph.representation.Identity;
+import org.simantics.graph.representation.Internal;
+import org.simantics.graph.representation.Optional;
+import org.simantics.graph.representation.Root;
+import org.simantics.graph.representation.TransferableGraph1;
+import org.simantics.graph.representation.Value;
+
+public class WriteBindings {
+
+       static class STRING_SERIALIZER extends ModifiedUTF8StringSerializer {
+
+               public static final Charset UTF8 = Charset.forName("utf-8");
+
+               public static STRING_SERIALIZER INSTANCE = new STRING_SERIALIZER();
+
+               public STRING_SERIALIZER() {
+                       super(STRING_BINDING.INSTANCE);
+               }
+
+               static byte[] writeUTF(String str) throws IOException {
+
+                       int strlen = str.length();
+                       int utflen = 0;
+                       int c/*, count = 0*/;
+
+                       /* use charAt instead of copying String to char array */
+                       for (int i = 0; i < strlen; i++) {
+                               c = str.charAt(i);
+                               if ((c >= 0x0001) && (c <= 0x007F)) {
+                                       utflen++;
+                               } else if (c > 0x07FF) {
+                                       utflen += 3;
+                               } else {
+                                       utflen += 2;
+                               }
+                       }
+
+                       if (utflen > 65535)
+                               throw new UTFDataFormatException(
+                                               "encoded string too long: " + utflen + " bytes");
+
+                       int byteIndex = 0;
+                       byte[] bytearr;
+                       
+                       int lengthTester = utflen;
+                       
+                       if(lengthTester < 0x80) {
+                               bytearr = new byte[utflen+1];
+                               bytearr[byteIndex++] = ((byte)utflen);
+                       }
+                       else {
+                               lengthTester -= 0x80;
+                               if(lengthTester < 0x4000) {
+                                       bytearr = new byte[utflen+2];
+                                       bytearr[byteIndex++] = (byte)( ((lengthTester&0x3f) | 0x80) );
+                                       bytearr[byteIndex++] = (byte)( (lengthTester>>>6) );
+                               }
+                               else {
+                                       lengthTester -= 0x4000;
+                                       if(lengthTester < 0x200000) {
+                                               bytearr = new byte[utflen+3];
+                                               bytearr[byteIndex++] = (byte)( ((lengthTester&0x1f) | 0xc0) );
+                                               bytearr[byteIndex++] = (byte)( ((lengthTester>>>5)&0xff) );
+                                               bytearr[byteIndex++] = (byte)( ((lengthTester>>>13)&0xff) );    
+                                       }
+                                       else {
+                                               lengthTester -= 0x200000;
+                                               if(lengthTester < 0x10000000) {
+                                                       bytearr = new byte[utflen+4];
+                                                       bytearr[byteIndex++] = (byte)( ((lengthTester&0x0f) | 0xe0) );
+                                                       bytearr[byteIndex++] = (byte)( ((lengthTester>>>4)&0xff) );
+                                                       bytearr[byteIndex++] = (byte)( ((lengthTester>>>12)&0xff) );    
+                                                       bytearr[byteIndex++] = (byte)( ((lengthTester>>>20)&0xff) );
+                                               }
+                                               else {
+                                                       lengthTester -= 0x10000000;
+                                                       bytearr = new byte[utflen+5];
+                                                       bytearr[byteIndex++] = (byte)( ((lengthTester&0x07) | 0xf0) );
+                                                       bytearr[byteIndex++] = (byte)( ((lengthTester>>>3)&0xff) );
+                                                       bytearr[byteIndex++] = (byte)( ((lengthTester>>>11)&0xff) );    
+                                                       bytearr[byteIndex++] = (byte)( ((lengthTester>>>19)&0xff) );
+                                                       bytearr[byteIndex++] = (byte)( ((lengthTester>>>27)&0xff) );
+                                               }
+                                       }                               
+                               }
+                       }       
+
+
+                       int i=0;
+                       for (i=0; i<strlen; i++) {
+                               c = str.charAt(i);
+                               if (!((c >= 0x0001) && (c <= 0x007F))) break;
+                               bytearr[byteIndex++] = (byte)(c);
+                       }
+
+                       for (;i < strlen; i++){
+                               c = str.charAt(i);
+                               if ((c >= 0x0001) && (c <= 0x007F)) {
+                                       bytearr[byteIndex++] = (byte)( c );
+                               } else if (c > 0x07FF) {
+                                       bytearr[byteIndex++] = (byte)(0xE0 | ((c >> 12) & 0x0F));
+                                       bytearr[byteIndex++] = (byte)(0x80 | ((c >>  6) & 0x3F));
+                                       bytearr[byteIndex++] = (byte)(0x80 | ((c >>  0) & 0x3F));
+                               } else {
+                                       bytearr[byteIndex++] = (byte)(0xC0 | ((c >>  6) & 0x1F));
+                                       bytearr[byteIndex++] = (byte)(0x80 | ((c >>  0) & 0x3F));
+                               }
+                       }
+
+                       return bytearr;
+
+               }
+
+               @Override
+               public byte[] serialize(Object obj) throws IOException {
+                       try {
+                               return writeUTF((String)obj);
+                       } catch (IOException e) {
+                               throw new SerializationException();
+                       }
+                       
+               }
+               
+       }
+
+       static class BYTE_ARRAY_SERIALIZER extends LongSerializer {
+
+               public static BYTE_ARRAY_SERIALIZER INSTANCE = new BYTE_ARRAY_SERIALIZER();
+
+               public BYTE_ARRAY_SERIALIZER() {
+                       super(BYTE_ARRAY_BINDING.INSTANCE);
+               }
+               
+               @Override
+               public byte[] serialize(Object obj) throws IOException {
+                       
+                       return (byte[])obj;
+
+               }
+               
+               @Override
+               public Object deserialize(byte[] data) throws IOException {
+                       return data;
+               }
+               
+       }
+
+       final static class LONG_ARRAY_SERIALIZER extends LongSerializer {
+
+               public static LONG_ARRAY_SERIALIZER INSTANCE = new LONG_ARRAY_SERIALIZER();
+
+               public LONG_ARRAY_SERIALIZER() {
+                       super(LONG_ARRAY_BINDING.INSTANCE);
+               }
+               
+               final private void loop(byte[] result, int index, long l) {
+                       result[index+7] = (byte)l;l >>>= 8;
+                       result[index+6] = (byte)l;l >>>= 8;
+                       result[index+5] = (byte)l;l >>>= 8;
+                       result[index+4] = (byte)l;l >>>= 8;
+                       result[index+3] = (byte)l;l >>>= 8;
+                       result[index+2] = (byte)l;l >>>= 8;
+                       result[index+1] = (byte)l;l >>>= 8;
+                       result[index] = (byte)l;l >>>= 8;
+                       
+//                     result[index+6] = (byte)(l & 0xFF);
+//                     l >>>= 8;
+//                     result[index+5] = (byte)(l & 0xFF);
+//                     l >>>= 8;
+//                     result[index+4] = (byte)(l & 0xFF);
+//                     l >>>= 8;
+//                     result[index+3] = (byte)(l & 0xFF);
+//                     l >>>= 8;
+//                     result[index+2] = (byte)(l & 0xFF);
+//                     l >>>= 8;
+//                     result[index+1] = (byte)(l & 0xFF);
+//                     l >>>= 8;
+//                     result[index] = (byte)(l & 0xFF);
+//                     l >>>= 8;
+               }
+               
+               @Override
+               public byte[] serialize(Object obj) throws IOException {
+                       
+                       long[] data = (long[])obj;
+                       byte[] result = new byte[4+8*data.length];
+                       
+                       int len = data.length;
+                       
+                       result[3] = (byte)(len & 0xFF);
+                       len >>>= 8;
+                       result[2] = (byte)(len & 0xFF);
+                       len >>>= 8;
+                       result[1] = (byte)(len & 0xFF);
+                       len >>>= 8;
+                       result[0] = (byte)(len & 0xFF);
+
+                       int index = 4;
+
+                       for(int i=0;i<data.length;i++) {
+
+                               loop(result, index, data[i]);
+
+//                             long l = data[i];
+
+//                             result[index+7] = (byte)(l & 0xFF);
+//                             l >>>= 8;
+//                             result[index+6] = (byte)(l & 0xFF);
+//                             l >>>= 8;
+//                             result[index+5] = (byte)(l & 0xFF);
+//                             l >>>= 8;
+//                             result[index+4] = (byte)(l & 0xFF);
+//                             l >>>= 8;
+//                             result[index+3] = (byte)(l & 0xFF);
+//                             l >>>= 8;
+//                             result[index+2] = (byte)(l & 0xFF);
+//                             l >>>= 8;
+//                             result[index+1] = (byte)(l & 0xFF);
+//                             l >>>= 8;
+//                             result[index] = (byte)(l & 0xFF);
+//                             l >>>= 8;
+                               
+                               index += 8;
+
+                       }
+                       
+                       return result;
+
+               }
+               
+       }
+
+       static class TRANSFERABLE_GRAPH_SERIALIZER extends LongSerializer {
+
+               public static TRANSFERABLE_GRAPH_SERIALIZER INSTANCE = new TRANSFERABLE_GRAPH_SERIALIZER();
+
+               public TRANSFERABLE_GRAPH_SERIALIZER() {
+                       super(TRANSFERABLE_GRAPH_BINDING.INSTANCE);
+               }
+               
+               static int writeUTF(String str, byte[] bytearr, int byteIndex) throws IOException {
+                       
+                       int strlen = str.length();
+                       int utflen = 0;
+                       int c;
+                       int count = byteIndex;
+
+                       /* use charAt instead of copying String to char array */
+                       for (int i = 0; i < strlen; i++) {
+                               c = str.charAt(i);
+                               if ((c >= 0x0001) && (c <= 0x007F)) {
+                                       utflen++;
+                               } else if (c > 0x07FF) {
+                                       utflen += 3;
+                               } else {
+                                       utflen += 2;
+                               }
+                       }
+
+                       if (utflen > 65535)
+                               throw new UTFDataFormatException(
+                                               "encoded string too long: " + utflen + " bytes");
+
+//                     byte[] bytearr = new byte[utflen+2];
+
+                       if(utflen < 0x80) {
+                               bytearr[count++] = ((byte)utflen);
+                       }
+                       else {
+                               utflen -= 0x80;
+                               if(utflen < 0x4000) {
+                                       bytearr[count++] = (byte)( ((utflen&0x3f) | 0x80) );
+                                       bytearr[count++] = (byte)( (utflen>>>6) );
+                               }
+                               else {
+                                       utflen -= 0x4000;
+                                       if(utflen < 0x200000) {
+                                               bytearr[count++] = (byte)( ((utflen&0x1f) | 0xc0) );
+                                               bytearr[count++] = (byte)( ((utflen>>>5)&0xff) );
+                                               bytearr[count++] = (byte)( ((utflen>>>13)&0xff) );      
+                                       }
+                                       else {
+                                               utflen -= 0x200000;
+                                               if(utflen < 0x10000000) {
+                                                       bytearr[count++] = (byte)( ((utflen&0x0f) | 0xe0) );
+                                                       bytearr[count++] = (byte)( ((utflen>>>4)&0xff) );
+                                                       bytearr[count++] = (byte)( ((utflen>>>12)&0xff) );      
+                                                       bytearr[count++] = (byte)( ((utflen>>>20)&0xff) );
+                                               }
+                                               else {
+                                                       utflen -= 0x10000000;
+                                                       bytearr[count++] = (byte)( ((utflen&0x07) | 0xf0) );
+                                                       bytearr[count++] = (byte)( ((utflen>>>3)&0xff) );
+                                                       bytearr[count++] = (byte)( ((utflen>>>11)&0xff) );      
+                                                       bytearr[count++] = (byte)( ((utflen>>>19)&0xff) );
+                                                       bytearr[count++] = (byte)( ((utflen>>>27)&0xff) );
+                                               }
+                                       }                               
+                               }
+                       }       
+
+                       int i=0;
+                       for (i=0; i<strlen; i++) {
+                               c = str.charAt(i);
+                               if (!((c >= 0x0001) && (c <= 0x007F))) break;
+                               bytearr[count++] = (byte) c;
+                       }
+
+                       for (;i < strlen; i++){
+                               c = str.charAt(i);
+                               if ((c >= 0x0001) && (c <= 0x007F)) {
+                                       bytearr[count++] = (byte) c;
+
+                               } else if (c > 0x07FF) {
+                                       bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
+                                       bytearr[count++] = (byte) (0x80 | ((c >>  6) & 0x3F));
+                                       bytearr[count++] = (byte) (0x80 | ((c >>  0) & 0x3F));
+                               } else {
+                                       bytearr[count++] = (byte) (0xC0 | ((c >>  6) & 0x1F));
+                                       bytearr[count++] = (byte) (0x80 | ((c >>  0) & 0x3F));
+                               }
+                       }
+                       
+                       return count - byteIndex;
+                       
+               }
+               
+               @Override
+               public byte[] serialize(Object obj) throws IOException {
+                       
+                       TransferableGraph1 tg = (TransferableGraph1)obj;
+                       
+                       return Bindings
+                                       .getSerializerUnchecked(TransferableGraph1.class)
+                                       .serialize(tg);
+/*
+                       // 16 = resourceCount + 3 arrays
+//                     long start = System.nanoTime();
+                       int actualSize = 16 + 8*tg.values.length + 4*tg.statements.length + 5*tg.identities.length;
+                       for(Value v : tg.values) actualSize += v.value.length;
+                       for(Identity id : tg.identities) { 
+                               if(id.definition instanceof Internal) actualSize += (4 + ((Internal)id.definition).name.length() + 5);
+                               else if(id.definition instanceof External) actualSize += (4 + ((External)id.definition).name.length() + 5);
+                               else if(id.definition instanceof Root) actualSize += (((Root)id.definition).name.length() + ((Root)id.definition).type.length() + 10);
+                               else if(id.definition instanceof Optional) actualSize += (4 + ((Optional)id.definition).name.length() + 5);
+                       }
+//                     long end = System.nanoTime() - start;
+//                     System.err.println("size took " + 1e-9*end);
+                       
+//                     long start2 = System.nanoTime();
+                       
+                       
+                       byte[] bytes = new byte[actualSize];
+                       int byteIndex = 0;
+
+                       int i = tg.resourceCount;
+                       
+                       bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
+                       bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
+                       bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
+                       bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
+                       byteIndex+=4;
+                       
+                       i = tg.identities.length;
+
+                       bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
+                       bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
+                       bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
+                       bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
+                       byteIndex+=4;
+                       
+                       for(Identity id : tg.identities) {
+
+                               i = id.resource;
+                               bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
+                               bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
+                               bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
+                               bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
+                               byteIndex+=4;
+                               
+                               if(id.definition instanceof Internal) {
+
+                                       Internal r = (Internal)id.definition;
+
+                                       bytes[byteIndex++] = 3;
+
+                                       i = r.parent;
+                                       bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
+                                       bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
+                                       bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
+                                       bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
+                                       byteIndex+=4;
+                                       
+                                       byteIndex += writeUTF(r.name, bytes, byteIndex);
+
+                               } else if(id.definition instanceof External) {
+
+                                       External r = (External)id.definition;
+
+                                       bytes[byteIndex++] = 1;
+
+                                       i = r.parent;
+                                       bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
+                                       bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
+                                       bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
+                                       bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
+                                       byteIndex+=4;
+                                       
+                                       byteIndex += writeUTF(r.name, bytes, byteIndex);
+                                       
+                               } else if(id.definition instanceof Root) {
+                                       
+                                       bytes[byteIndex++] = 0;
+                                       
+                                       Root r = (Root)id.definition;
+                                       byteIndex += writeUTF(r.name, bytes, byteIndex);
+                                       byteIndex += writeUTF(r.type, bytes, byteIndex);
+                                       
+                               } else if(id.definition instanceof Optional) {
+
+                                       Optional r = (Optional)id.definition;
+
+                                       bytes[byteIndex++] = 2;
+
+                                       i = r.parent;
+                                       bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
+                                       bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
+                                       bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
+                                       bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
+                                       byteIndex+=4;
+                                       
+                                       byteIndex += writeUTF(r.name, bytes, byteIndex);
+                                       
+                               }
+                               
+                       }
+                       
+                       i = tg.statements.length;
+                       bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
+                       bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
+                       bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
+                       bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
+                       byteIndex+=4;
+                       
+                       for(int s : tg.statements) {
+                               i = s;
+                               bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
+                               bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
+                               bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
+                               bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
+                               byteIndex+=4;
+                       }
+
+                       i = tg.values.length;
+                       bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
+                       bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
+                       bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
+                       bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
+                       byteIndex+=4;
+
+                       for(Value v : tg.values) {
+                               
+                               i = v.resource;
+                               bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
+                               bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
+                               bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
+                               bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
+                               byteIndex+=4;
+
+                               i = v.value.length;
+                               bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
+                               bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
+                               bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
+                               bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
+                               byteIndex+=4;
+                               
+                               System.arraycopy(v.value, 0, bytes, byteIndex, v.value.length);
+                               byteIndex += v.value.length;
+                               
+                       }
+
+//                     return bytes;
+                       
+//                     byte[] result = new byte[byteIndex];
+//                     System.arraycopy(bytes, 0, result, 0, byteIndex);
+//                     
+//                     byte[] result = Arrays.copyOf(bytes, byteIndex); 
+                       
+//                     long end2 = System.nanoTime() - start2;
+//                     System.err.println("size2 took " + 1e-9*end2);
+
+                       return bytes; 
+                       
+//                     long[] data = (long[])obj;
+//                     byte[] result = new byte[4+8*data.length];
+//                     
+//                     int len = data.length;
+//                     
+//                     result[3] = (byte)(len & 0xFF);
+//                     len >>>= 8;
+//                     result[2] = (byte)(len & 0xFF);
+//                     len >>>= 8;
+//                     result[1] = (byte)(len & 0xFF);
+//                     len >>>= 8;
+//                     result[0] = (byte)(len & 0xFF);
+//
+//                     int index = 4;
+//
+//                     for(int i=0;i<data.length;i++) {
+//                             
+//                             long l = data[i];
+//
+//                             result[index+7] = (byte)(l & 0xFF);
+//                             l >>>= 8;
+//                             result[index+6] = (byte)(l & 0xFF);
+//                             l >>>= 8;
+//                             result[index+5] = (byte)(l & 0xFF);
+//                             l >>>= 8;
+//                             result[index+4] = (byte)(l & 0xFF);
+//                             l >>>= 8;
+//                             result[index+3] = (byte)(l & 0xFF);
+//                             l >>>= 8;
+//                             result[index+2] = (byte)(l & 0xFF);
+//                             l >>>= 8;
+//                             result[index+1] = (byte)(l & 0xFF);
+//                             l >>>= 8;
+//                             result[index] = (byte)(l & 0xFF);
+//                             l >>>= 8;
+//                             
+//                             index += 8;
+//
+//                     }
+//                     
+//                     return result;
+*/
+               }
+               
+               
+               final private String utf(byte[] bytes) {
+                       
+                       char[] chars = new char[bytes.length];
+                       
+                       int index = 0;
+                       int length = bytes[index++]&0xff; 
+                       if(length >= 0x80) {
+                               if(length >= 0xc0) {
+                                       if(length >= 0xe0) {
+                                               if(length >= 0xf0) {
+                                                       length &= 0x0f;
+                                                       length += ((bytes[index++]&0xff)<<3);
+                                                       length += ((bytes[index++]&0xff)<<11);
+                                                       length += ((bytes[index++]&0xff)<<19);
+                                                       length += 0x10204080;
+                                               }
+                                               else {
+                                                       length &= 0x1f;
+                                                       length += ((bytes[index++]&0xff)<<4);
+                                                       length += ((bytes[index++]&0xff)<<12);
+                                                       length += ((bytes[index++]&0xff)<<20);
+                                                       length += 0x204080;
+                                               }
+                                       }
+                                       else {
+                                               length &= 0x3f;
+                                               length += ((bytes[index++]&0xff)<<5);
+                                               length += ((bytes[index++]&0xff)<<13);
+                                               length += 0x4080;
+                                       }
+                               }
+                               else {
+                                       length &= 0x7f;
+                                       length += ((bytes[index++]&0xff)<<6);
+                                       length += 0x80;
+                               }
+                       }
+                       
+                       int i = 0;
+                       int target = length+index;
+                       while(index < target) {
+                               int c = bytes[index++]&0xff;
+                               if(c <= 0x7F) {
+                                       chars[i++] = (char)(c&0x7F);
+                               } else if (c > 0x07FF) {
+                                       int c2 = bytes[index++]&0xff;
+                                       int c3 = bytes[index++]&0xff;
+                                       chars[i++] = (char)(((c&0xf)<<12) + ((c2&0x3f)<<6) + (c3&0x3f)); 
+                               } else {
+                                       int c2 = bytes[index++]&0xff;
+                                       chars[i++] = (char)(((c&0x1f)<<6) + (c2&0x3f)); 
+                               }
+                               
+                       }
+                       
+                       return new String(chars, 0, i);
+                       
+               }
+
+               
+               @Override
+               public Object deserialize(byte[] data) throws IOException {
+                       return utf(data);
+               }
+               
+       }
+
+       static class STRING_BINDING extends StringBindingDefault {
+               
+               public static STRING_BINDING INSTANCE = new STRING_BINDING();
+               
+               public STRING_BINDING() {
+                       super(Datatypes.STRING);
+               }
+               
+               @Override
+               public Serializer serializer() throws RuntimeSerializerConstructionException {
+                       
+                       return STRING_SERIALIZER.INSTANCE;
+                       
+               }
+               
+               @Override
+               public boolean isInstance(Object obj) {
+                       return obj instanceof String;
+               }
+               
+       }
+       
+       static class BYTE_ARRAY_BINDING extends LongBindingDefault {
+               
+               public static BYTE_ARRAY_BINDING INSTANCE = new BYTE_ARRAY_BINDING();
+               
+               public BYTE_ARRAY_BINDING() {
+                       super(Datatypes.LONG);
+               }
+               
+               @Override
+               public Serializer serializer() throws RuntimeSerializerConstructionException {
+                       
+                       return BYTE_ARRAY_SERIALIZER.INSTANCE;
+                       
+               }
+               
+               @Override
+               public boolean isInstance(Object obj) {
+                       return obj instanceof byte[];
+               }
+               
+       }
+
+       static class LONG_ARRAY_BINDING extends LongBindingDefault {
+               
+               public static LONG_ARRAY_BINDING INSTANCE = new LONG_ARRAY_BINDING();
+               
+               public LONG_ARRAY_BINDING() {
+                       super(Datatypes.LONG);
+               }
+               
+               @Override
+               public Serializer serializer() throws RuntimeSerializerConstructionException {
+                       
+                       return LONG_ARRAY_SERIALIZER.INSTANCE;
+                       
+               }
+               
+       }
+
+       
+       static class TRANSFERABLE_GRAPH_BINDING extends LongBindingDefault {
+               
+               public static TRANSFERABLE_GRAPH_BINDING INSTANCE = new TRANSFERABLE_GRAPH_BINDING();
+               
+               public TRANSFERABLE_GRAPH_BINDING() {
+                       super(Datatypes.LONG);
+               }
+               
+               @Override
+               public Serializer serializer() throws RuntimeSerializerConstructionException {
+                       
+                       return TRANSFERABLE_GRAPH_SERIALIZER.INSTANCE;
+                       
+               }
+               
+       }
+
+       public static Binding STRING = STRING_BINDING.INSTANCE;
+       public static Binding BYTE_ARRAY = BYTE_ARRAY_BINDING.INSTANCE;
+       public static Binding LONG_ARRAY = LONG_ARRAY_BINDING.INSTANCE;
+       public static Binding TRANSFERABLE_GRAPH = TRANSFERABLE_GRAPH_BINDING.INSTANCE;
+
+       public static void main(String[] args) {
+
+               TransferableGraph1 tg = new TransferableGraph1(123,new Identity[] { 
+                               new Identity(11, new Root("foo", "bar1")), 
+                               new Identity(12, new External(21, "bar2")), 
+                               new Identity(13, new Internal(22, "bar3")), 
+                               new Identity(14, new Optional(23, "bar4")) },
+                               new int[] { 1, 2, 3 },
+                               new Value[] { new Value(31, new Variant(Bindings.INTEGER, 123)) });
+
+               try {
+                       System.err.println(Arrays.toString(Bindings.getSerializerUnchecked(Bindings.getBinding(TransferableGraph1.class)).serialize(tg)));
+                       System.err.println(Arrays.toString(WriteBindings.TRANSFERABLE_GRAPH_SERIALIZER.INSTANCE.serialize(tg)));
+               } catch (RuntimeSerializerConstructionException e) {
+                       // TODO Auto-generated catch block
+                       e.printStackTrace();
+               } catch (IOException e) {
+                       // TODO Auto-generated catch block
+                       e.printStackTrace();
+               } catch (BindingConstructionException e) {
+                       // TODO Auto-generated catch block
+                       e.printStackTrace();
+               }
+               
+       }
+       
+}