-package org.simantics.databoard.serialization.impl;\r
-\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-\r
-import java.io.DataInput;\r
-import java.io.DataOutput;\r
-import java.io.IOException;\r
-import java.util.List;\r
-\r
-import org.simantics.databoard.binding.Binding;\r
-import org.simantics.databoard.binding.RecordBinding;\r
-import org.simantics.databoard.binding.error.BindingException;\r
-import org.simantics.databoard.binding.reflection.ClassBinding;\r
-import org.simantics.databoard.binding.util.IsReferableQuery;\r
-import org.simantics.databoard.binding.util.Result;\r
-import org.simantics.databoard.serialization.SerializationException;\r
-import org.simantics.databoard.serialization.Serializer;\r
-import org.simantics.databoard.serialization.Serializer.CompositeSerializer;\r
-\r
-public class GenericRecordSerializer extends CompositeSerializer {\r
-\r
- RecordBinding binding;\r
- public Serializer[] componentSerializers;\r
- Integer fixedSize;\r
- int minSize;\r
- boolean createPartial;\r
- \r
- /**\r
- * Field type for each field\r
- * 0 - Object\r
- * 1 - boolean\r
- * 2 - byte\r
- * 3 - int\r
- * 4 - long\r
- * 5 - float\r
- * 6 - double\r
- */\r
- public int[] fieldType;\r
- \r
- /**\r
- * \r
- * @param binding\r
- * @param componentSerializers (optional) can be set later\r
- */\r
- public GenericRecordSerializer(RecordBinding binding, Serializer[] componentSerializers) { \r
- super( IsReferableQuery.isReferable( binding.type() ) != Result.No );\r
- this.binding = binding; \r
- this.componentSerializers = componentSerializers;\r
- }\r
- \r
- @Override\r
- public void finalizeConstruction() {\r
- fixedSize = null;\r
-\r
- createPartial = !binding.isImmutable();\r
- \r
- if ( binding instanceof ClassBinding ) {\r
- ClassBinding cb = (ClassBinding) binding;\r
- createPartial &= cb.ci.partialConstructionPossible;\r
- }\r
- \r
- fieldType = new int[componentSerializers.length];\r
- for (int i=0; i<componentSerializers.length; i++) {\r
- Serializer cs = componentSerializers[i];\r
- //createPartial &= !binding.getComponentBinding(i).isImmutable(); \r
- minSize += cs.getMinSize();\r
- Integer componentFixedSize = cs.getConstantSize();\r
- if (componentFixedSize==null) {\r
- fixedSize = null;\r
- break;\r
- }\r
- fixedSize = fixedSize==null ? componentFixedSize : fixedSize+componentFixedSize;\r
- \r
- int type = 0;\r
- if ( cs instanceof BooleanSerializer ) type = 1;\r
- else if ( cs instanceof ByteSerializer ) type = 2;\r
- else if ( cs instanceof IntSerializer ) type = 3;\r
- else if ( cs instanceof LongSerializer ) type = 4;\r
- else if ( cs instanceof FloatSerializer ) type = 5;\r
- else if ( cs instanceof DoubleSerializer ) type = 6;\r
- fieldType[i] = type;\r
- }\r
- \r
-// if ( binding instanceof ClassBinding ) {\r
-// ClassBinding cb = (ClassBinding) binding;\r
-// System.out.println(cb.ci.clazz.getName()+" = "+createPartial);\r
-// }\r
- \r
- }\r
-\r
- @Override\r
- public Object deserialize(DataInput in, List<Object> identities) throws IOException {\r
-// assertRemainingBytes(in, minSize);\r
- try {\r
- if (createPartial) {\r
- Object obj = binding.createPartial();\r
- deserializeTo(in, identities, obj);\r
- return obj;\r
- } else { \r
- Object[] temp = new Object[componentSerializers.length];\r
- for(int i=0;i<componentSerializers.length;++i) {\r
- temp[i] = componentSerializers[i].deserialize(in, identities);\r
- }\r
- return binding.create(temp);\r
- }\r
- \r
- } catch (BindingException e) {\r
- throw new IOException( e ); \r
- }\r
- }\r
- \r
- @Override\r
- public void deserializeTo(DataInput in, List<Object> identities, Object obj) throws IOException {\r
-// assertRemainingBytes(in, minSize);\r
- try {\r
- for(int i=0;i<componentSerializers.length;++i) {\r
- Serializer cs = componentSerializers[i];\r
- int type = fieldType[i];\r
- \r
- switch (type) {\r
- case 0:\r
- Binding cb = binding.componentBindings[i];\r
- boolean csImmutable = cb.isImmutable();\r
- if (csImmutable) {\r
- Object component = cs.deserialize(in, identities);\r
- binding.setComponent(obj, i, component);\r
- } else {\r
- Object component = binding.getComponent(obj, i);\r
- if ( component == null ) {\r
- component = cs.deserialize(in, identities);\r
- binding.setComponent(obj, i, component);\r
- } else {\r
- Object newComponent = cs.deserializeToTry(in, identities, component);\r
- if (newComponent!=component) binding.setComponent(obj, i, newComponent);\r
- }\r
- }\r
- break;\r
- case 1:\r
- binding.setBoolean(obj, i, ((BooleanSerializer)cs).getBoolean(in));\r
- break;\r
- case 2:\r
- binding.setByte(obj, i, ((ByteSerializer)cs).getByte(in));\r
- break;\r
- case 3:\r
- binding.setInt(obj, i, ((IntSerializer)cs).getInt(in));\r
- break;\r
- case 4:\r
- binding.setLong(obj, i, ((LongSerializer)cs).getLong(in));\r
- break;\r
- case 5:\r
- binding.setFloat(obj, i, ((FloatSerializer)cs).getFloat(in));\r
- break;\r
- case 6:\r
- binding.setDouble(obj, i, ((DoubleSerializer)cs).getDouble(in));\r
- break;\r
- }\r
- \r
- }\r
- } catch (BindingException e) {\r
- throw new IOException( e ); \r
- }\r
- }\r
-\r
- @Override\r
- public void skip(DataInput in, List<Object> identities) throws IOException, SerializationException {\r
- if (fixedSize != null) {\r
- in.skipBytes(fixedSize);\r
- } else {\r
- for(int i=0;i<componentSerializers.length;++i)\r
- componentSerializers[i].skip(in, identities); \r
- }\r
- } \r
- \r
- @Override\r
- public void serialize(DataOutput out, TObjectIntHashMap<Object> identities, Object obj) throws IOException {\r
- try {\r
- for(int i=0;i<componentSerializers.length;++i) {\r
- int type = fieldType[i];\r
- Serializer cs = componentSerializers[i];\r
- switch( type ) {\r
- case 0: cs.serialize(out, identities, binding.getComponent(obj, i));\r
- break; \r
- case 1: ((BooleanSerializer)cs).putBoolean(out, binding.getBoolean(obj, i));\r
- break;\r
- case 2: ((ByteSerializer)cs).putByte(out, binding.getByte(obj, i));\r
- break;\r
- case 3: ((IntSerializer)cs).putInt(out, binding.getInt(obj, i));\r
- break;\r
- case 4: ((LongSerializer)cs).putLong(out, binding.getLong(obj, i));\r
- break;\r
- case 5: ((FloatSerializer)cs).putFloat(out, binding.getFloat(obj, i));\r
- break;\r
- case 6: ((DoubleSerializer)cs).putDouble(out, binding.getDouble(obj, i));\r
- break;\r
- }\r
- }\r
- } catch (BindingException e) {\r
- throw new IOException( e ); \r
- }\r
- }\r
-\r
- @Override\r
- public Integer getConstantSize() { \r
- return fixedSize;\r
- }\r
-\r
- @Override\r
- public int getSize(Object obj, TObjectIntHashMap<Object> identities) throws IOException {\r
- try {\r
- if (fixedSize!=null) return fixedSize;\r
- int result = 0;\r
- for(int i=0;i<componentSerializers.length;++i)\r
- result += componentSerializers[i].getSize( binding.getComponent(obj, i), identities ); \r
- return result;\r
- } catch (BindingException e) {\r
- throw new IOException( e ); \r
- }\r
- }\r
- \r
- /**\r
- * @return the minSize\r
- */\r
- public int getMinSize() {\r
- return minSize;\r
- }\r
- \r
-}\r
+package org.simantics.databoard.serialization.impl;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.List;
+
+import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.binding.RecordBinding;
+import org.simantics.databoard.binding.error.BindingException;
+import org.simantics.databoard.binding.reflection.ClassBinding;
+import org.simantics.databoard.binding.util.IsReferableQuery;
+import org.simantics.databoard.binding.util.Result;
+import org.simantics.databoard.serialization.SerializationException;
+import org.simantics.databoard.serialization.Serializer;
+import org.simantics.databoard.serialization.Serializer.CompositeSerializer;
+
+public class GenericRecordSerializer extends CompositeSerializer {
+
+ RecordBinding binding;
+ public Serializer[] componentSerializers;
+ Integer fixedSize;
+ int minSize;
+ boolean createPartial;
+
+ /**
+ * Field type for each field
+ * 0 - Object
+ * 1 - boolean
+ * 2 - byte
+ * 3 - int
+ * 4 - long
+ * 5 - float
+ * 6 - double
+ */
+ public int[] fieldType;
+
+ /**
+ *
+ * @param binding
+ * @param componentSerializers (optional) can be set later
+ */
+ public GenericRecordSerializer(RecordBinding binding, Serializer[] componentSerializers) {
+ super( IsReferableQuery.isReferable( binding.type() ) != Result.No );
+ this.binding = binding;
+ this.componentSerializers = componentSerializers;
+ }
+
+ @Override
+ public void finalizeConstruction() {
+ fixedSize = null;
+
+ createPartial = !binding.isImmutable();
+
+ if ( binding instanceof ClassBinding ) {
+ ClassBinding cb = (ClassBinding) binding;
+ createPartial &= cb.ci.partialConstructionPossible;
+ }
+
+ fieldType = new int[componentSerializers.length];
+ for (int i=0; i<componentSerializers.length; i++) {
+ Serializer cs = componentSerializers[i];
+ //createPartial &= !binding.getComponentBinding(i).isImmutable();
+ minSize += cs.getMinSize();
+ Integer componentFixedSize = cs.getConstantSize();
+ if (componentFixedSize==null) {
+ fixedSize = null;
+ break;
+ }
+ fixedSize = fixedSize==null ? componentFixedSize : fixedSize+componentFixedSize;
+
+ int type = 0;
+ if ( cs instanceof BooleanSerializer ) type = 1;
+ else if ( cs instanceof ByteSerializer ) type = 2;
+ else if ( cs instanceof IntSerializer ) type = 3;
+ else if ( cs instanceof LongSerializer ) type = 4;
+ else if ( cs instanceof FloatSerializer ) type = 5;
+ else if ( cs instanceof DoubleSerializer ) type = 6;
+ fieldType[i] = type;
+ }
+
+// if ( binding instanceof ClassBinding ) {
+// ClassBinding cb = (ClassBinding) binding;
+// System.out.println(cb.ci.clazz.getName()+" = "+createPartial);
+// }
+
+ }
+
+ @Override
+ public Object deserialize(DataInput in, List<Object> identities) throws IOException {
+// assertRemainingBytes(in, minSize);
+ try {
+ if (createPartial) {
+ Object obj = binding.createPartial();
+ deserializeTo(in, identities, obj);
+ return obj;
+ } else {
+ Object[] temp = new Object[componentSerializers.length];
+ for(int i=0;i<componentSerializers.length;++i) {
+ temp[i] = componentSerializers[i].deserialize(in, identities);
+ }
+ return binding.create(temp);
+ }
+
+ } catch (BindingException e) {
+ throw new IOException( e );
+ }
+ }
+
+ @Override
+ public void deserializeTo(DataInput in, List<Object> identities, Object obj) throws IOException {
+// assertRemainingBytes(in, minSize);
+ try {
+ for(int i=0;i<componentSerializers.length;++i) {
+ Serializer cs = componentSerializers[i];
+ int type = fieldType[i];
+
+ switch (type) {
+ case 0:
+ Binding cb = binding.componentBindings[i];
+ boolean csImmutable = cb.isImmutable();
+ if (csImmutable) {
+ Object component = cs.deserialize(in, identities);
+ binding.setComponent(obj, i, component);
+ } else {
+ Object component = binding.getComponent(obj, i);
+ if ( component == null ) {
+ component = cs.deserialize(in, identities);
+ binding.setComponent(obj, i, component);
+ } else {
+ Object newComponent = cs.deserializeToTry(in, identities, component);
+ if (newComponent!=component) binding.setComponent(obj, i, newComponent);
+ }
+ }
+ break;
+ case 1:
+ binding.setBoolean(obj, i, ((BooleanSerializer)cs).getBoolean(in));
+ break;
+ case 2:
+ binding.setByte(obj, i, ((ByteSerializer)cs).getByte(in));
+ break;
+ case 3:
+ binding.setInt(obj, i, ((IntSerializer)cs).getInt(in));
+ break;
+ case 4:
+ binding.setLong(obj, i, ((LongSerializer)cs).getLong(in));
+ break;
+ case 5:
+ binding.setFloat(obj, i, ((FloatSerializer)cs).getFloat(in));
+ break;
+ case 6:
+ binding.setDouble(obj, i, ((DoubleSerializer)cs).getDouble(in));
+ break;
+ }
+
+ }
+ } catch (BindingException e) {
+ throw new IOException( e );
+ }
+ }
+
+ @Override
+ public void skip(DataInput in, List<Object> identities) throws IOException, SerializationException {
+ if (fixedSize != null) {
+ in.skipBytes(fixedSize);
+ } else {
+ for(int i=0;i<componentSerializers.length;++i)
+ componentSerializers[i].skip(in, identities);
+ }
+ }
+
+ @Override
+ public void serialize(DataOutput out, TObjectIntHashMap<Object> identities, Object obj) throws IOException {
+ try {
+ for(int i=0;i<componentSerializers.length;++i) {
+ int type = fieldType[i];
+ Serializer cs = componentSerializers[i];
+ switch( type ) {
+ case 0: cs.serialize(out, identities, binding.getComponent(obj, i));
+ break;
+ case 1: ((BooleanSerializer)cs).putBoolean(out, binding.getBoolean(obj, i));
+ break;
+ case 2: ((ByteSerializer)cs).putByte(out, binding.getByte(obj, i));
+ break;
+ case 3: ((IntSerializer)cs).putInt(out, binding.getInt(obj, i));
+ break;
+ case 4: ((LongSerializer)cs).putLong(out, binding.getLong(obj, i));
+ break;
+ case 5: ((FloatSerializer)cs).putFloat(out, binding.getFloat(obj, i));
+ break;
+ case 6: ((DoubleSerializer)cs).putDouble(out, binding.getDouble(obj, i));
+ break;
+ }
+ }
+ } catch (BindingException e) {
+ throw new IOException( e );
+ }
+ }
+
+ @Override
+ public Integer getConstantSize() {
+ return fixedSize;
+ }
+
+ @Override
+ public int getSize(Object obj, TObjectIntHashMap<Object> identities) throws IOException {
+ try {
+ if (fixedSize!=null) return fixedSize;
+ int result = 0;
+ for(int i=0;i<componentSerializers.length;++i)
+ result += componentSerializers[i].getSize( binding.getComponent(obj, i), identities );
+ return result;
+ } catch (BindingException e) {
+ throw new IOException( e );
+ }
+ }
+
+ /**
+ * @return the minSize
+ */
+ public int getMinSize() {
+ return minSize;
+ }
+
+}