1 package org.simantics.db.common;
3 import java.io.IOException;
4 import java.io.UTFDataFormatException;
5 import java.nio.charset.Charset;
6 import java.util.Arrays;
8 import org.simantics.databoard.Bindings;
9 import org.simantics.databoard.Datatypes;
10 import org.simantics.databoard.binding.Binding;
11 import org.simantics.databoard.binding.error.BindingConstructionException;
12 import org.simantics.databoard.binding.impl.LongBindingDefault;
13 import org.simantics.databoard.binding.impl.StringBindingDefault;
14 import org.simantics.databoard.binding.mutable.Variant;
15 import org.simantics.databoard.serialization.RuntimeSerializerConstructionException;
16 import org.simantics.databoard.serialization.SerializationException;
17 import org.simantics.databoard.serialization.Serializer;
18 import org.simantics.databoard.serialization.impl.LongSerializer;
19 import org.simantics.databoard.serialization.impl.ModifiedUTF8StringSerializer;
20 import org.simantics.graph.representation.External;
21 import org.simantics.graph.representation.Identity;
22 import org.simantics.graph.representation.Internal;
23 import org.simantics.graph.representation.Optional;
24 import org.simantics.graph.representation.Root;
25 import org.simantics.graph.representation.TransferableGraph1;
26 import org.simantics.graph.representation.Value;
28 public class WriteBindings {
30 static class STRING_SERIALIZER extends ModifiedUTF8StringSerializer {
32 public static final Charset UTF8 = Charset.forName("utf-8");
34 public static STRING_SERIALIZER INSTANCE = new STRING_SERIALIZER();
36 public STRING_SERIALIZER() {
37 super(STRING_BINDING.INSTANCE);
40 static byte[] writeUTF(String str) throws IOException {
42 int strlen = str.length();
46 /* use charAt instead of copying String to char array */
47 for (int i = 0; i < strlen; i++) {
49 if ((c >= 0x0001) && (c <= 0x007F)) {
51 } else if (c > 0x07FF) {
59 throw new UTFDataFormatException(
60 "encoded string too long: " + utflen + " bytes");
65 int lengthTester = utflen;
67 if(lengthTester < 0x80) {
68 bytearr = new byte[utflen+1];
69 bytearr[byteIndex++] = ((byte)utflen);
73 if(lengthTester < 0x4000) {
74 bytearr = new byte[utflen+2];
75 bytearr[byteIndex++] = (byte)( ((lengthTester&0x3f) | 0x80) );
76 bytearr[byteIndex++] = (byte)( (lengthTester>>>6) );
79 lengthTester -= 0x4000;
80 if(lengthTester < 0x200000) {
81 bytearr = new byte[utflen+3];
82 bytearr[byteIndex++] = (byte)( ((lengthTester&0x1f) | 0xc0) );
83 bytearr[byteIndex++] = (byte)( ((lengthTester>>>5)&0xff) );
84 bytearr[byteIndex++] = (byte)( ((lengthTester>>>13)&0xff) );
87 lengthTester -= 0x200000;
88 if(lengthTester < 0x10000000) {
89 bytearr = new byte[utflen+4];
90 bytearr[byteIndex++] = (byte)( ((lengthTester&0x0f) | 0xe0) );
91 bytearr[byteIndex++] = (byte)( ((lengthTester>>>4)&0xff) );
92 bytearr[byteIndex++] = (byte)( ((lengthTester>>>12)&0xff) );
93 bytearr[byteIndex++] = (byte)( ((lengthTester>>>20)&0xff) );
96 lengthTester -= 0x10000000;
97 bytearr = new byte[utflen+5];
98 bytearr[byteIndex++] = (byte)( ((lengthTester&0x07) | 0xf0) );
99 bytearr[byteIndex++] = (byte)( ((lengthTester>>>3)&0xff) );
100 bytearr[byteIndex++] = (byte)( ((lengthTester>>>11)&0xff) );
101 bytearr[byteIndex++] = (byte)( ((lengthTester>>>19)&0xff) );
102 bytearr[byteIndex++] = (byte)( ((lengthTester>>>27)&0xff) );
110 for (i=0; i<strlen; i++) {
112 if (!((c >= 0x0001) && (c <= 0x007F))) break;
113 bytearr[byteIndex++] = (byte)(c);
116 for (;i < strlen; i++){
118 if ((c >= 0x0001) && (c <= 0x007F)) {
119 bytearr[byteIndex++] = (byte)( c );
120 } else if (c > 0x07FF) {
121 bytearr[byteIndex++] = (byte)(0xE0 | ((c >> 12) & 0x0F));
122 bytearr[byteIndex++] = (byte)(0x80 | ((c >> 6) & 0x3F));
123 bytearr[byteIndex++] = (byte)(0x80 | ((c >> 0) & 0x3F));
125 bytearr[byteIndex++] = (byte)(0xC0 | ((c >> 6) & 0x1F));
126 bytearr[byteIndex++] = (byte)(0x80 | ((c >> 0) & 0x3F));
135 public byte[] serialize(Object obj) throws IOException {
137 return writeUTF((String)obj);
138 } catch (IOException e) {
139 throw new SerializationException();
146 static class BYTE_ARRAY_SERIALIZER extends LongSerializer {
148 public static BYTE_ARRAY_SERIALIZER INSTANCE = new BYTE_ARRAY_SERIALIZER();
150 public BYTE_ARRAY_SERIALIZER() {
151 super(BYTE_ARRAY_BINDING.INSTANCE);
155 public byte[] serialize(Object obj) throws IOException {
162 public Object deserialize(byte[] data) throws IOException {
168 final static class LONG_ARRAY_SERIALIZER extends LongSerializer {
170 public static LONG_ARRAY_SERIALIZER INSTANCE = new LONG_ARRAY_SERIALIZER();
172 public LONG_ARRAY_SERIALIZER() {
173 super(LONG_ARRAY_BINDING.INSTANCE);
176 final private void loop(byte[] result, int index, long l) {
177 result[index+7] = (byte)l;l >>>= 8;
178 result[index+6] = (byte)l;l >>>= 8;
179 result[index+5] = (byte)l;l >>>= 8;
180 result[index+4] = (byte)l;l >>>= 8;
181 result[index+3] = (byte)l;l >>>= 8;
182 result[index+2] = (byte)l;l >>>= 8;
183 result[index+1] = (byte)l;l >>>= 8;
184 result[index] = (byte)l;l >>>= 8;
186 // result[index+6] = (byte)(l & 0xFF);
188 // result[index+5] = (byte)(l & 0xFF);
190 // result[index+4] = (byte)(l & 0xFF);
192 // result[index+3] = (byte)(l & 0xFF);
194 // result[index+2] = (byte)(l & 0xFF);
196 // result[index+1] = (byte)(l & 0xFF);
198 // result[index] = (byte)(l & 0xFF);
203 public byte[] serialize(Object obj) throws IOException {
205 long[] data = (long[])obj;
206 byte[] result = new byte[4+8*data.length];
208 int len = data.length;
210 result[3] = (byte)(len & 0xFF);
212 result[2] = (byte)(len & 0xFF);
214 result[1] = (byte)(len & 0xFF);
216 result[0] = (byte)(len & 0xFF);
220 for(int i=0;i<data.length;i++) {
222 loop(result, index, data[i]);
226 // result[index+7] = (byte)(l & 0xFF);
228 // result[index+6] = (byte)(l & 0xFF);
230 // result[index+5] = (byte)(l & 0xFF);
232 // result[index+4] = (byte)(l & 0xFF);
234 // result[index+3] = (byte)(l & 0xFF);
236 // result[index+2] = (byte)(l & 0xFF);
238 // result[index+1] = (byte)(l & 0xFF);
240 // result[index] = (byte)(l & 0xFF);
253 static class TRANSFERABLE_GRAPH_SERIALIZER extends LongSerializer {
255 public static TRANSFERABLE_GRAPH_SERIALIZER INSTANCE = new TRANSFERABLE_GRAPH_SERIALIZER();
257 public TRANSFERABLE_GRAPH_SERIALIZER() {
258 super(TRANSFERABLE_GRAPH_BINDING.INSTANCE);
261 static int writeUTF(String str, byte[] bytearr, int byteIndex) throws IOException {
263 int strlen = str.length();
266 int count = byteIndex;
268 /* use charAt instead of copying String to char array */
269 for (int i = 0; i < strlen; i++) {
271 if ((c >= 0x0001) && (c <= 0x007F)) {
273 } else if (c > 0x07FF) {
281 throw new UTFDataFormatException(
282 "encoded string too long: " + utflen + " bytes");
284 // byte[] bytearr = new byte[utflen+2];
287 bytearr[count++] = ((byte)utflen);
291 if(utflen < 0x4000) {
292 bytearr[count++] = (byte)( ((utflen&0x3f) | 0x80) );
293 bytearr[count++] = (byte)( (utflen>>>6) );
297 if(utflen < 0x200000) {
298 bytearr[count++] = (byte)( ((utflen&0x1f) | 0xc0) );
299 bytearr[count++] = (byte)( ((utflen>>>5)&0xff) );
300 bytearr[count++] = (byte)( ((utflen>>>13)&0xff) );
304 if(utflen < 0x10000000) {
305 bytearr[count++] = (byte)( ((utflen&0x0f) | 0xe0) );
306 bytearr[count++] = (byte)( ((utflen>>>4)&0xff) );
307 bytearr[count++] = (byte)( ((utflen>>>12)&0xff) );
308 bytearr[count++] = (byte)( ((utflen>>>20)&0xff) );
311 utflen -= 0x10000000;
312 bytearr[count++] = (byte)( ((utflen&0x07) | 0xf0) );
313 bytearr[count++] = (byte)( ((utflen>>>3)&0xff) );
314 bytearr[count++] = (byte)( ((utflen>>>11)&0xff) );
315 bytearr[count++] = (byte)( ((utflen>>>19)&0xff) );
316 bytearr[count++] = (byte)( ((utflen>>>27)&0xff) );
323 for (i=0; i<strlen; i++) {
325 if (!((c >= 0x0001) && (c <= 0x007F))) break;
326 bytearr[count++] = (byte) c;
329 for (;i < strlen; i++){
331 if ((c >= 0x0001) && (c <= 0x007F)) {
332 bytearr[count++] = (byte) c;
334 } else if (c > 0x07FF) {
335 bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
336 bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F));
337 bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
339 bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
340 bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
344 return count - byteIndex;
349 public byte[] serialize(Object obj) throws IOException {
351 TransferableGraph1 tg = (TransferableGraph1)obj;
354 .getSerializerUnchecked(TransferableGraph1.class)
357 // 16 = resourceCount + 3 arrays
358 // long start = System.nanoTime();
359 int actualSize = 16 + 8*tg.values.length + 4*tg.statements.length + 5*tg.identities.length;
360 for(Value v : tg.values) actualSize += v.value.length;
361 for(Identity id : tg.identities) {
362 if(id.definition instanceof Internal) actualSize += (4 + ((Internal)id.definition).name.length() + 5);
363 else if(id.definition instanceof External) actualSize += (4 + ((External)id.definition).name.length() + 5);
364 else if(id.definition instanceof Root) actualSize += (((Root)id.definition).name.length() + ((Root)id.definition).type.length() + 10);
365 else if(id.definition instanceof Optional) actualSize += (4 + ((Optional)id.definition).name.length() + 5);
367 // long end = System.nanoTime() - start;
368 // System.err.println("size took " + 1e-9*end);
370 // long start2 = System.nanoTime();
373 byte[] bytes = new byte[actualSize];
376 int i = tg.resourceCount;
378 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
379 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
380 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
381 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
384 i = tg.identities.length;
386 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
387 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
388 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
389 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
392 for(Identity id : tg.identities) {
395 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
396 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
397 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
398 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
401 if(id.definition instanceof Internal) {
403 Internal r = (Internal)id.definition;
405 bytes[byteIndex++] = 3;
408 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
409 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
410 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
411 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
414 byteIndex += writeUTF(r.name, bytes, byteIndex);
416 } else if(id.definition instanceof External) {
418 External r = (External)id.definition;
420 bytes[byteIndex++] = 1;
423 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
424 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
425 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
426 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
429 byteIndex += writeUTF(r.name, bytes, byteIndex);
431 } else if(id.definition instanceof Root) {
433 bytes[byteIndex++] = 0;
435 Root r = (Root)id.definition;
436 byteIndex += writeUTF(r.name, bytes, byteIndex);
437 byteIndex += writeUTF(r.type, bytes, byteIndex);
439 } else if(id.definition instanceof Optional) {
441 Optional r = (Optional)id.definition;
443 bytes[byteIndex++] = 2;
446 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
447 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
448 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
449 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
452 byteIndex += writeUTF(r.name, bytes, byteIndex);
458 i = tg.statements.length;
459 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
460 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
461 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
462 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
465 for(int s : tg.statements) {
467 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
468 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
469 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
470 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
474 i = tg.values.length;
475 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
476 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
477 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
478 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
481 for(Value v : tg.values) {
484 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
485 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
486 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
487 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
491 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
492 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
493 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
494 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
497 System.arraycopy(v.value, 0, bytes, byteIndex, v.value.length);
498 byteIndex += v.value.length;
504 // byte[] result = new byte[byteIndex];
505 // System.arraycopy(bytes, 0, result, 0, byteIndex);
507 // byte[] result = Arrays.copyOf(bytes, byteIndex);
509 // long end2 = System.nanoTime() - start2;
510 // System.err.println("size2 took " + 1e-9*end2);
514 // long[] data = (long[])obj;
515 // byte[] result = new byte[4+8*data.length];
517 // int len = data.length;
519 // result[3] = (byte)(len & 0xFF);
521 // result[2] = (byte)(len & 0xFF);
523 // result[1] = (byte)(len & 0xFF);
525 // result[0] = (byte)(len & 0xFF);
529 // for(int i=0;i<data.length;i++) {
533 // result[index+7] = (byte)(l & 0xFF);
535 // result[index+6] = (byte)(l & 0xFF);
537 // result[index+5] = (byte)(l & 0xFF);
539 // result[index+4] = (byte)(l & 0xFF);
541 // result[index+3] = (byte)(l & 0xFF);
543 // result[index+2] = (byte)(l & 0xFF);
545 // result[index+1] = (byte)(l & 0xFF);
547 // result[index] = (byte)(l & 0xFF);
559 final private String utf(byte[] bytes) {
561 char[] chars = new char[bytes.length];
564 int length = bytes[index++]&0xff;
570 length += ((bytes[index++]&0xff)<<3);
571 length += ((bytes[index++]&0xff)<<11);
572 length += ((bytes[index++]&0xff)<<19);
573 length += 0x10204080;
577 length += ((bytes[index++]&0xff)<<4);
578 length += ((bytes[index++]&0xff)<<12);
579 length += ((bytes[index++]&0xff)<<20);
585 length += ((bytes[index++]&0xff)<<5);
586 length += ((bytes[index++]&0xff)<<13);
592 length += ((bytes[index++]&0xff)<<6);
598 int target = length+index;
599 while(index < target) {
600 int c = bytes[index++]&0xff;
602 chars[i++] = (char)(c&0x7F);
603 } else if (c > 0x07FF) {
604 int c2 = bytes[index++]&0xff;
605 int c3 = bytes[index++]&0xff;
606 chars[i++] = (char)(((c&0xf)<<12) + ((c2&0x3f)<<6) + (c3&0x3f));
608 int c2 = bytes[index++]&0xff;
609 chars[i++] = (char)(((c&0x1f)<<6) + (c2&0x3f));
614 return new String(chars, 0, i);
620 public Object deserialize(byte[] data) throws IOException {
626 static class STRING_BINDING extends StringBindingDefault {
628 public static STRING_BINDING INSTANCE = new STRING_BINDING();
630 public STRING_BINDING() {
631 super(Datatypes.STRING);
635 public Serializer serializer() throws RuntimeSerializerConstructionException {
637 return STRING_SERIALIZER.INSTANCE;
642 public boolean isInstance(Object obj) {
643 return obj instanceof String;
648 static class BYTE_ARRAY_BINDING extends LongBindingDefault {
650 public static BYTE_ARRAY_BINDING INSTANCE = new BYTE_ARRAY_BINDING();
652 public BYTE_ARRAY_BINDING() {
653 super(Datatypes.LONG);
657 public Serializer serializer() throws RuntimeSerializerConstructionException {
659 return BYTE_ARRAY_SERIALIZER.INSTANCE;
664 public boolean isInstance(Object obj) {
665 return obj instanceof byte[];
670 static class LONG_ARRAY_BINDING extends LongBindingDefault {
672 public static LONG_ARRAY_BINDING INSTANCE = new LONG_ARRAY_BINDING();
674 public LONG_ARRAY_BINDING() {
675 super(Datatypes.LONG);
679 public Serializer serializer() throws RuntimeSerializerConstructionException {
681 return LONG_ARRAY_SERIALIZER.INSTANCE;
688 static class TRANSFERABLE_GRAPH_BINDING extends LongBindingDefault {
690 public static TRANSFERABLE_GRAPH_BINDING INSTANCE = new TRANSFERABLE_GRAPH_BINDING();
692 public TRANSFERABLE_GRAPH_BINDING() {
693 super(Datatypes.LONG);
697 public Serializer serializer() throws RuntimeSerializerConstructionException {
699 return TRANSFERABLE_GRAPH_SERIALIZER.INSTANCE;
705 public static Binding STRING = STRING_BINDING.INSTANCE;
706 public static Binding BYTE_ARRAY = BYTE_ARRAY_BINDING.INSTANCE;
707 public static Binding LONG_ARRAY = LONG_ARRAY_BINDING.INSTANCE;
708 public static Binding TRANSFERABLE_GRAPH = TRANSFERABLE_GRAPH_BINDING.INSTANCE;
710 public static void main(String[] args) {
712 TransferableGraph1 tg = new TransferableGraph1(123,new Identity[] {
713 new Identity(11, new Root("foo", "bar1")),
714 new Identity(12, new External(21, "bar2")),
715 new Identity(13, new Internal(22, "bar3")),
716 new Identity(14, new Optional(23, "bar4")) },
717 new int[] { 1, 2, 3 },
718 new Value[] { new Value(31, new Variant(Bindings.INTEGER, 123)) });
721 System.err.println(Arrays.toString(Bindings.getSerializerUnchecked(Bindings.getBinding(TransferableGraph1.class)).serialize(tg)));
722 System.err.println(Arrays.toString(WriteBindings.TRANSFERABLE_GRAPH_SERIALIZER.INSTANCE.serialize(tg)));
723 } catch (RuntimeSerializerConstructionException e) {
724 // TODO Auto-generated catch block
726 } catch (IOException e) {
727 // TODO Auto-generated catch block
729 } catch (BindingConstructionException e) {
730 // TODO Auto-generated catch block