package org.simantics.graph.representation; import gnu.trove.map.hash.TObjectIntHashMap; import java.io.DataInput; import java.io.DataOutput; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.UTFDataFormatException; import java.util.List; import org.simantics.databoard.Bindings; import org.simantics.databoard.serialization.Serializer; public class TransferableGraph1Serializer extends Serializer { public static final TransferableGraph1Serializer INSTANCE = new TransferableGraph1Serializer(); private TransferableGraph1Serializer() {} 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"); 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= 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 Object deserialize(File file) throws IOException { TransferableGraphFileReader reader = new TransferableGraphFileReader(file); try { return reader.readTG(); } finally { reader.close(); } } public Object deserialize(InputStream in) throws IOException { TransferableGraphFileReader reader = new TransferableGraphFileReader(in); try { return reader.readTG(); } finally { reader.close(); } } @Override public byte[] serialize(Object obj) throws IOException { TransferableGraph1 tg = (TransferableGraph1)obj; Extensions ex = new Extensions(tg.extensions); byte[] extensions = Bindings.getSerializerUnchecked(Bindings.getBindingUnchecked(Extensions.class)).serialize(ex); Serializer variantSerializer = Bindings.getSerializerUnchecked(Bindings.VARIANT); int actualSize = 16 + 4*tg.values.length + 4*tg.statements.length + 5*tg.identities.length + extensions.length; for(Value v : tg.values) actualSize += variantSerializer.getSize(v.value); 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); } 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; byte[] temp = variantSerializer.serialize(v.value); System.arraycopy(temp, 0, bytes, byteIndex, temp.length); byteIndex += temp.length; } System.arraycopy(extensions, 0, bytes, byteIndex, extensions.length); return bytes; } @Override public void serialize(DataOutput out, TObjectIntHashMap identities, Object obj) throws IOException { TransferableGraph1.SERIALIZER.serialize(out, identities, obj); } @Override public void serialize(DataOutput out, Object obj) throws IOException { TransferableGraph1.SERIALIZER.serialize(out, obj); } @Override public Object deserialize(DataInput in, List identities) throws IOException { return TransferableGraph1.SERIALIZER.deserialize(in, identities); } @Override public Object deserialize(DataInput in) throws IOException { return TransferableGraph1.SERIALIZER.deserialize(in); } @Override public void deserializeTo(DataInput in, List identities, Object obj) throws IOException { TransferableGraph1.SERIALIZER.deserializeTo(in, identities, obj); } @Override public void deserializeTo(DataInput in, Object obj) throws IOException { TransferableGraph1.SERIALIZER.deserializeTo(in, obj); } @Override public void skip(DataInput in, List identities) throws IOException { TransferableGraph1.SERIALIZER.skip(in, identities); } @Override public void skip(DataInput in) throws IOException { TransferableGraph1.SERIALIZER.skip(in); } @Override public Integer getConstantSize() { return TransferableGraph1.SERIALIZER.getConstantSize(); } @Override public int getSize(Object obj, TObjectIntHashMap identities) throws IOException { return TransferableGraph1.SERIALIZER.getSize(obj, identities); } @Override public int getSize(Object obj) throws IOException { return TransferableGraph1.SERIALIZER.getSize(obj); } @Override public int getMinSize() { return TransferableGraph1.SERIALIZER.getMinSize(); } }