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");
66 bytearr = new byte[utflen+1];
67 bytearr[byteIndex++] = ((byte)utflen);
72 bytearr = new byte[utflen+2];
73 bytearr[byteIndex++] = (byte)( ((utflen&0x3f) | 0x80) );
74 bytearr[byteIndex++] = (byte)( (utflen>>>6) );
78 if(utflen < 0x200000) {
79 bytearr = new byte[utflen+3];
80 bytearr[byteIndex++] = (byte)( ((utflen&0x1f) | 0xc0) );
81 bytearr[byteIndex++] = (byte)( ((utflen>>>5)&0xff) );
82 bytearr[byteIndex++] = (byte)( ((utflen>>>13)&0xff) );
86 if(utflen < 0x10000000) {
87 bytearr = new byte[utflen+4];
88 bytearr[byteIndex++] = (byte)( ((utflen&0x0f) | 0xe0) );
89 bytearr[byteIndex++] = (byte)( ((utflen>>>4)&0xff) );
90 bytearr[byteIndex++] = (byte)( ((utflen>>>12)&0xff) );
91 bytearr[byteIndex++] = (byte)( ((utflen>>>20)&0xff) );
95 bytearr = new byte[utflen+5];
96 bytearr[byteIndex++] = (byte)( ((utflen&0x07) | 0xf0) );
97 bytearr[byteIndex++] = (byte)( ((utflen>>>3)&0xff) );
98 bytearr[byteIndex++] = (byte)( ((utflen>>>11)&0xff) );
99 bytearr[byteIndex++] = (byte)( ((utflen>>>19)&0xff) );
100 bytearr[byteIndex++] = (byte)( ((utflen>>>27)&0xff) );
108 for (i=0; i<strlen; i++) {
110 if (!((c >= 0x0001) && (c <= 0x007F))) break;
111 bytearr[byteIndex++] = (byte)(c);
114 for (;i < strlen; i++){
116 if ((c >= 0x0001) && (c <= 0x007F)) {
117 bytearr[byteIndex++] = (byte)( c );
118 } else if (c > 0x07FF) {
119 bytearr[byteIndex++] = (byte)(0xE0 | ((c >> 12) & 0x0F));
120 bytearr[byteIndex++] = (byte)(0x80 | ((c >> 6) & 0x3F));
121 bytearr[byteIndex++] = (byte)(0x80 | ((c >> 0) & 0x3F));
123 bytearr[byteIndex++] = (byte)(0xC0 | ((c >> 6) & 0x1F));
124 bytearr[byteIndex++] = (byte)(0x80 | ((c >> 0) & 0x3F));
133 public byte[] serialize(Object obj) throws IOException {
135 return writeUTF((String)obj);
136 } catch (IOException e) {
137 throw new SerializationException();
144 static class BYTE_ARRAY_SERIALIZER extends LongSerializer {
146 public static BYTE_ARRAY_SERIALIZER INSTANCE = new BYTE_ARRAY_SERIALIZER();
148 public BYTE_ARRAY_SERIALIZER() {
149 super(BYTE_ARRAY_BINDING.INSTANCE);
153 public byte[] serialize(Object obj) throws IOException {
160 public Object deserialize(byte[] data) throws IOException {
166 final static class LONG_ARRAY_SERIALIZER extends LongSerializer {
168 public static LONG_ARRAY_SERIALIZER INSTANCE = new LONG_ARRAY_SERIALIZER();
170 public LONG_ARRAY_SERIALIZER() {
171 super(LONG_ARRAY_BINDING.INSTANCE);
174 final private void loop(byte[] result, int index, long l) {
175 result[index+7] = (byte)l;l >>>= 8;
176 result[index+6] = (byte)l;l >>>= 8;
177 result[index+5] = (byte)l;l >>>= 8;
178 result[index+4] = (byte)l;l >>>= 8;
179 result[index+3] = (byte)l;l >>>= 8;
180 result[index+2] = (byte)l;l >>>= 8;
181 result[index+1] = (byte)l;l >>>= 8;
182 result[index] = (byte)l;l >>>= 8;
184 // result[index+6] = (byte)(l & 0xFF);
186 // result[index+5] = (byte)(l & 0xFF);
188 // result[index+4] = (byte)(l & 0xFF);
190 // result[index+3] = (byte)(l & 0xFF);
192 // result[index+2] = (byte)(l & 0xFF);
194 // result[index+1] = (byte)(l & 0xFF);
196 // result[index] = (byte)(l & 0xFF);
201 public byte[] serialize(Object obj) throws IOException {
203 long[] data = (long[])obj;
204 byte[] result = new byte[4+8*data.length];
206 int len = data.length;
208 result[3] = (byte)(len & 0xFF);
210 result[2] = (byte)(len & 0xFF);
212 result[1] = (byte)(len & 0xFF);
214 result[0] = (byte)(len & 0xFF);
218 for(int i=0;i<data.length;i++) {
220 loop(result, index, data[i]);
224 // result[index+7] = (byte)(l & 0xFF);
226 // result[index+6] = (byte)(l & 0xFF);
228 // result[index+5] = (byte)(l & 0xFF);
230 // result[index+4] = (byte)(l & 0xFF);
232 // result[index+3] = (byte)(l & 0xFF);
234 // result[index+2] = (byte)(l & 0xFF);
236 // result[index+1] = (byte)(l & 0xFF);
238 // result[index] = (byte)(l & 0xFF);
251 static class TRANSFERABLE_GRAPH_SERIALIZER extends LongSerializer {
253 public static TRANSFERABLE_GRAPH_SERIALIZER INSTANCE = new TRANSFERABLE_GRAPH_SERIALIZER();
255 public TRANSFERABLE_GRAPH_SERIALIZER() {
256 super(TRANSFERABLE_GRAPH_BINDING.INSTANCE);
259 static int writeUTF(String str, byte[] bytearr, int byteIndex) throws IOException {
261 int strlen = str.length();
264 int count = byteIndex;
266 /* use charAt instead of copying String to char array */
267 for (int i = 0; i < strlen; i++) {
269 if ((c >= 0x0001) && (c <= 0x007F)) {
271 } else if (c > 0x07FF) {
279 throw new UTFDataFormatException(
280 "encoded string too long: " + utflen + " bytes");
282 // byte[] bytearr = new byte[utflen+2];
285 bytearr[count++] = ((byte)utflen);
289 if(utflen < 0x4000) {
290 bytearr[count++] = (byte)( ((utflen&0x3f) | 0x80) );
291 bytearr[count++] = (byte)( (utflen>>>6) );
295 if(utflen < 0x200000) {
296 bytearr[count++] = (byte)( ((utflen&0x1f) | 0xc0) );
297 bytearr[count++] = (byte)( ((utflen>>>5)&0xff) );
298 bytearr[count++] = (byte)( ((utflen>>>13)&0xff) );
302 if(utflen < 0x10000000) {
303 bytearr[count++] = (byte)( ((utflen&0x0f) | 0xe0) );
304 bytearr[count++] = (byte)( ((utflen>>>4)&0xff) );
305 bytearr[count++] = (byte)( ((utflen>>>12)&0xff) );
306 bytearr[count++] = (byte)( ((utflen>>>20)&0xff) );
309 utflen -= 0x10000000;
310 bytearr[count++] = (byte)( ((utflen&0x07) | 0xf0) );
311 bytearr[count++] = (byte)( ((utflen>>>3)&0xff) );
312 bytearr[count++] = (byte)( ((utflen>>>11)&0xff) );
313 bytearr[count++] = (byte)( ((utflen>>>19)&0xff) );
314 bytearr[count++] = (byte)( ((utflen>>>27)&0xff) );
321 for (i=0; i<strlen; i++) {
323 if (!((c >= 0x0001) && (c <= 0x007F))) break;
324 bytearr[count++] = (byte) c;
327 for (;i < strlen; i++){
329 if ((c >= 0x0001) && (c <= 0x007F)) {
330 bytearr[count++] = (byte) c;
332 } else if (c > 0x07FF) {
333 bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
334 bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F));
335 bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
337 bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
338 bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
342 return count - byteIndex;
347 public byte[] serialize(Object obj) throws IOException {
349 TransferableGraph1 tg = (TransferableGraph1)obj;
352 .getSerializerUnchecked(TransferableGraph1.class)
355 // 16 = resourceCount + 3 arrays
356 // long start = System.nanoTime();
357 int actualSize = 16 + 8*tg.values.length + 4*tg.statements.length + 5*tg.identities.length;
358 for(Value v : tg.values) actualSize += v.value.length;
359 for(Identity id : tg.identities) {
360 if(id.definition instanceof Internal) actualSize += (4 + ((Internal)id.definition).name.length() + 5);
361 else if(id.definition instanceof External) actualSize += (4 + ((External)id.definition).name.length() + 5);
362 else if(id.definition instanceof Root) actualSize += (((Root)id.definition).name.length() + ((Root)id.definition).type.length() + 10);
363 else if(id.definition instanceof Optional) actualSize += (4 + ((Optional)id.definition).name.length() + 5);
365 // long end = System.nanoTime() - start;
366 // System.err.println("size took " + 1e-9*end);
368 // long start2 = System.nanoTime();
371 byte[] bytes = new byte[actualSize];
374 int i = tg.resourceCount;
376 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
377 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
378 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
379 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
382 i = tg.identities.length;
384 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
385 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
386 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
387 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
390 for(Identity id : tg.identities) {
393 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
394 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
395 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
396 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
399 if(id.definition instanceof Internal) {
401 Internal r = (Internal)id.definition;
403 bytes[byteIndex++] = 3;
406 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
407 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
408 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
409 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
412 byteIndex += writeUTF(r.name, bytes, byteIndex);
414 } else if(id.definition instanceof External) {
416 External r = (External)id.definition;
418 bytes[byteIndex++] = 1;
421 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
422 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
423 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
424 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
427 byteIndex += writeUTF(r.name, bytes, byteIndex);
429 } else if(id.definition instanceof Root) {
431 bytes[byteIndex++] = 0;
433 Root r = (Root)id.definition;
434 byteIndex += writeUTF(r.name, bytes, byteIndex);
435 byteIndex += writeUTF(r.type, bytes, byteIndex);
437 } else if(id.definition instanceof Optional) {
439 Optional r = (Optional)id.definition;
441 bytes[byteIndex++] = 2;
444 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
445 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
446 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
447 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
450 byteIndex += writeUTF(r.name, bytes, byteIndex);
456 i = tg.statements.length;
457 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
458 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
459 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
460 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
463 for(int s : tg.statements) {
465 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
466 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
467 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
468 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
472 i = tg.values.length;
473 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
474 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
475 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
476 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
479 for(Value v : tg.values) {
482 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
483 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
484 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
485 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
489 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
490 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
491 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
492 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
495 System.arraycopy(v.value, 0, bytes, byteIndex, v.value.length);
496 byteIndex += v.value.length;
502 // byte[] result = new byte[byteIndex];
503 // System.arraycopy(bytes, 0, result, 0, byteIndex);
505 // byte[] result = Arrays.copyOf(bytes, byteIndex);
507 // long end2 = System.nanoTime() - start2;
508 // System.err.println("size2 took " + 1e-9*end2);
512 // long[] data = (long[])obj;
513 // byte[] result = new byte[4+8*data.length];
515 // int len = data.length;
517 // result[3] = (byte)(len & 0xFF);
519 // result[2] = (byte)(len & 0xFF);
521 // result[1] = (byte)(len & 0xFF);
523 // result[0] = (byte)(len & 0xFF);
527 // for(int i=0;i<data.length;i++) {
531 // result[index+7] = (byte)(l & 0xFF);
533 // result[index+6] = (byte)(l & 0xFF);
535 // result[index+5] = (byte)(l & 0xFF);
537 // result[index+4] = (byte)(l & 0xFF);
539 // result[index+3] = (byte)(l & 0xFF);
541 // result[index+2] = (byte)(l & 0xFF);
543 // result[index+1] = (byte)(l & 0xFF);
545 // result[index] = (byte)(l & 0xFF);
557 final private String utf(byte[] bytes) {
559 char[] chars = new char[bytes.length];
562 int length = bytes[index++]&0xff;
568 length += ((bytes[index++]&0xff)<<3);
569 length += ((bytes[index++]&0xff)<<11);
570 length += ((bytes[index++]&0xff)<<19);
571 length += 0x10204080;
575 length += ((bytes[index++]&0xff)<<4);
576 length += ((bytes[index++]&0xff)<<12);
577 length += ((bytes[index++]&0xff)<<20);
583 length += ((bytes[index++]&0xff)<<5);
584 length += ((bytes[index++]&0xff)<<13);
590 length += ((bytes[index++]&0xff)<<6);
596 int target = length+index;
597 while(index < target) {
598 int c = bytes[index++]&0xff;
600 chars[i++] = (char)(c&0x7F);
601 } else if (c > 0x07FF) {
602 int c2 = bytes[index++]&0xff;
603 int c3 = bytes[index++]&0xff;
604 chars[i++] = (char)(((c&0xf)<<12) + ((c2&0x3f)<<6) + (c3&0x3f));
606 int c2 = bytes[index++]&0xff;
607 chars[i++] = (char)(((c&0x1f)<<6) + (c2&0x3f));
612 return new String(chars, 0, i);
618 public Object deserialize(byte[] data) throws IOException {
624 static class STRING_BINDING extends StringBindingDefault {
626 public static STRING_BINDING INSTANCE = new STRING_BINDING();
628 public STRING_BINDING() {
629 super(Datatypes.STRING);
633 public Serializer serializer() throws RuntimeSerializerConstructionException {
635 return STRING_SERIALIZER.INSTANCE;
640 public boolean isInstance(Object obj) {
641 return obj instanceof String;
646 static class BYTE_ARRAY_BINDING extends LongBindingDefault {
648 public static BYTE_ARRAY_BINDING INSTANCE = new BYTE_ARRAY_BINDING();
650 public BYTE_ARRAY_BINDING() {
651 super(Datatypes.LONG);
655 public Serializer serializer() throws RuntimeSerializerConstructionException {
657 return BYTE_ARRAY_SERIALIZER.INSTANCE;
662 public boolean isInstance(Object obj) {
663 return obj instanceof byte[];
668 static class LONG_ARRAY_BINDING extends LongBindingDefault {
670 public static LONG_ARRAY_BINDING INSTANCE = new LONG_ARRAY_BINDING();
672 public LONG_ARRAY_BINDING() {
673 super(Datatypes.LONG);
677 public Serializer serializer() throws RuntimeSerializerConstructionException {
679 return LONG_ARRAY_SERIALIZER.INSTANCE;
686 static class TRANSFERABLE_GRAPH_BINDING extends LongBindingDefault {
688 public static TRANSFERABLE_GRAPH_BINDING INSTANCE = new TRANSFERABLE_GRAPH_BINDING();
690 public TRANSFERABLE_GRAPH_BINDING() {
691 super(Datatypes.LONG);
695 public Serializer serializer() throws RuntimeSerializerConstructionException {
697 return TRANSFERABLE_GRAPH_SERIALIZER.INSTANCE;
703 public static Binding STRING = STRING_BINDING.INSTANCE;
704 public static Binding BYTE_ARRAY = BYTE_ARRAY_BINDING.INSTANCE;
705 public static Binding LONG_ARRAY = LONG_ARRAY_BINDING.INSTANCE;
706 public static Binding TRANSFERABLE_GRAPH = TRANSFERABLE_GRAPH_BINDING.INSTANCE;
708 public static void main(String[] args) {
710 TransferableGraph1 tg = new TransferableGraph1(123,new Identity[] {
711 new Identity(11, new Root("foo", "bar1")),
712 new Identity(12, new External(21, "bar2")),
713 new Identity(13, new Internal(22, "bar3")),
714 new Identity(14, new Optional(23, "bar4")) },
715 new int[] { 1, 2, 3 },
716 new Value[] { new Value(31, new Variant(Bindings.INTEGER, 123)) });
719 System.err.println(Arrays.toString(Bindings.getSerializerUnchecked(Bindings.getBinding(TransferableGraph1.class)).serialize(tg)));
720 System.err.println(Arrays.toString(WriteBindings.TRANSFERABLE_GRAPH_SERIALIZER.INSTANCE.serialize(tg)));
721 } catch (RuntimeSerializerConstructionException e) {
722 // TODO Auto-generated catch block
724 } catch (IOException e) {
725 // TODO Auto-generated catch block
727 } catch (BindingConstructionException e) {
728 // TODO Auto-generated catch block