-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.UnionBinding;\r
-import org.simantics.databoard.binding.error.BindingException;\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
-import org.simantics.databoard.type.UnionType;\r
-import org.simantics.databoard.util.binary.Endian;\r
-\r
-public class UnionSerializer extends CompositeSerializer {\r
-\r
- UnionBinding binding;\r
- public Serializer[] componentSerializers;\r
- int tagTypeCount;\r
- Integer fixedSize;\r
- int minSize;\r
- \r
- /**\r
- * \r
- * @param binding\r
- * @param componentSerializers (optional) can be set later\r
- */\r
- public UnionSerializer(UnionBinding binding, Serializer[] componentSerializers) \r
- {\r
- super( IsReferableQuery.isReferable( binding.type() ) != Result.No );\r
- tagTypeCount = ((UnionType) binding.type()).components.length;\r
- this.binding = binding;\r
- this.componentSerializers = componentSerializers;\r
- }\r
- \r
- @Override\r
- public void finalizeConstruction() {\r
- // Calculate Fixed Size\r
- for (Serializer s : componentSerializers)\r
- {\r
- Integer fixedSizeOfComponentSerializer = s.getConstantSize();\r
- if (fixedSizeOfComponentSerializer==null) {\r
- fixedSize = null;\r
- break;\r
- }\r
- if (fixedSize!=null && fixedSizeOfComponentSerializer!=fixedSize) {\r
- fixedSize = null;\r
- break;\r
- }\r
- fixedSize = fixedSizeOfComponentSerializer;\r
- }\r
- if (componentSerializers.length == 0) fixedSize = 0;\r
- if (fixedSize!=null) fixedSize += Endian.getUIntLength(tagTypeCount-1);\r
- \r
- if (componentSerializers.length>0) {\r
- minSize = Integer.MAX_VALUE;\r
- for (Serializer s : componentSerializers) minSize = Math.min(minSize, s.getMinSize());\r
- minSize += Endian.getUIntLength( tagTypeCount-1 );\r
- }\r
- \r
- }\r
-\r
- @Override\r
- public Object deserialize(DataInput in, List<Object> identities) throws IOException {\r
- try {\r
- int tag = Endian.getUInt(in, tagTypeCount-1);\r
- return binding.create(tag, componentSerializers[tag].deserialize(in, identities));\r
- } catch (BindingException e) {\r
- throw new IOException( e ); \r
- }\r
- }\r
- \r
- public Object deserializeToTry(DataInput in, List<Object> identities, Object dst) throws IOException \r
- {\r
- if (binding.isTagMutable()) {\r
- return deserialize(in, identities);\r
- } else {\r
- deserializeTo(in, identities, dst);\r
- return dst; \r
- }\r
- }\r
- \r
- \r
- @Override\r
- public void deserializeTo(DataInput in, List<Object> identities, Object obj) throws IOException {\r
- try {\r
- int tag = Endian.getUInt(in, tagTypeCount-1);\r
- int oldTag = binding.getTag(obj);\r
- Serializer cs = componentSerializers[tag];\r
- boolean csImmutable = binding.getComponentBinding(tag).isImmutable();\r
- \r
- if (oldTag==tag && !csImmutable) {\r
- Object component = binding.getValue(obj);\r
- component = componentSerializers[tag].deserializeToTry(in, identities, component);\r
- binding.setValue(obj, tag, component);\r
- } else {\r
- Object component = cs.deserialize(in, identities);\r
- binding.setValue(obj, tag, component);\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
- int tag = Endian.getUInt(in, tagTypeCount-1);\r
- componentSerializers[tag].skip(in, identities);\r
- }\r
- \r
- @Override\r
- public void serialize(DataOutput out, TObjectIntHashMap<Object> identities, Object obj) throws IOException {\r
- try {\r
- int tag = binding.getTag(obj);\r
- Endian.putUInt(out, tag, tagTypeCount-1);\r
- componentSerializers[tag].serialize(out, identities, binding.getValue(obj));\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 tag = binding.getTag(obj);\r
- return Endian.getUIntLength( tagTypeCount-1 ) +\r
- componentSerializers[tag].getSize(binding.getValue(obj), identities);\r
- } catch (BindingException e) {\r
- throw new IOException( e ); \r
- }\r
- }\r
- \r
- @Override\r
- public int getMinSize() {\r
- return minSize;\r
- }\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.UnionBinding;
+import org.simantics.databoard.binding.error.BindingException;
+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;
+import org.simantics.databoard.type.UnionType;
+import org.simantics.databoard.util.binary.Endian;
+
+public class UnionSerializer extends CompositeSerializer {
+
+ UnionBinding binding;
+ public Serializer[] componentSerializers;
+ int tagTypeCount;
+ Integer fixedSize;
+ int minSize;
+
+ /**
+ *
+ * @param binding
+ * @param componentSerializers (optional) can be set later
+ */
+ public UnionSerializer(UnionBinding binding, Serializer[] componentSerializers)
+ {
+ super( IsReferableQuery.isReferable( binding.type() ) != Result.No );
+ tagTypeCount = ((UnionType) binding.type()).components.length;
+ this.binding = binding;
+ this.componentSerializers = componentSerializers;
+ }
+
+ @Override
+ public void finalizeConstruction() {
+ // Calculate Fixed Size
+ for (Serializer s : componentSerializers)
+ {
+ Integer fixedSizeOfComponentSerializer = s.getConstantSize();
+ if (fixedSizeOfComponentSerializer==null) {
+ fixedSize = null;
+ break;
+ }
+ if (fixedSize!=null && !fixedSize.equals(fixedSizeOfComponentSerializer)) {
+ fixedSize = null;
+ break;
+ }
+ fixedSize = fixedSizeOfComponentSerializer;
+ }
+ if (componentSerializers.length == 0) fixedSize = 0;
+ if (fixedSize!=null) fixedSize += Endian.getUIntLength(tagTypeCount-1);
+
+ if (componentSerializers.length>0) {
+ minSize = Integer.MAX_VALUE;
+ for (Serializer s : componentSerializers) minSize = Math.min(minSize, s.getMinSize());
+ minSize += Endian.getUIntLength( tagTypeCount-1 );
+ }
+
+ }
+
+ @Override
+ public Object deserialize(DataInput in, List<Object> identities) throws IOException {
+ try {
+ int tag = Endian.getUInt(in, tagTypeCount-1);
+ return binding.create(tag, componentSerializers[tag].deserialize(in, identities));
+ } catch (BindingException e) {
+ throw new IOException( e );
+ }
+ }
+
+ public Object deserializeToTry(DataInput in, List<Object> identities, Object dst) throws IOException
+ {
+ if (binding.isTagMutable()) {
+ return deserialize(in, identities);
+ } else {
+ deserializeTo(in, identities, dst);
+ return dst;
+ }
+ }
+
+
+ @Override
+ public void deserializeTo(DataInput in, List<Object> identities, Object obj) throws IOException {
+ try {
+ int tag = Endian.getUInt(in, tagTypeCount-1);
+ int oldTag = binding.getTag(obj);
+ Serializer cs = componentSerializers[tag];
+ boolean csImmutable = binding.getComponentBinding(tag).isImmutable();
+
+ if (oldTag==tag && !csImmutable) {
+ Object component = binding.getValue(obj);
+ component = componentSerializers[tag].deserializeToTry(in, identities, component);
+ binding.setValue(obj, tag, component);
+ } else {
+ Object component = cs.deserialize(in, identities);
+ binding.setValue(obj, tag, component);
+ }
+ } catch (BindingException e) {
+ throw new IOException( e );
+ }
+ }
+
+ @Override
+ public void skip(DataInput in, List<Object> identities) throws IOException, SerializationException {
+ int tag = Endian.getUInt(in, tagTypeCount-1);
+ componentSerializers[tag].skip(in, identities);
+ }
+
+ @Override
+ public void serialize(DataOutput out, TObjectIntHashMap<Object> identities, Object obj) throws IOException {
+ try {
+ int tag = binding.getTag(obj);
+ Endian.putUInt(out, tag, tagTypeCount-1);
+ componentSerializers[tag].serialize(out, identities, binding.getValue(obj));
+ } 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 tag = binding.getTag(obj);
+ return Endian.getUIntLength( tagTypeCount-1 ) +
+ componentSerializers[tag].getSize(binding.getValue(obj), identities);
+ } catch (BindingException e) {
+ throw new IOException( e );
+ }
+ }
+
+ @Override
+ public int getMinSize() {
+ return minSize;
+ }
+
+
+}