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= 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>>= 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); } @Override public byte[] serialize(Object obj) throws IOException { TransferableGraph1 tg = (TransferableGraph1)obj; return Bindings .getSerializerUnchecked(TransferableGraph1.class) .serialize(tg); } 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(); } } }