1 package org.simantics.databoard.serialization.impl;
3 import gnu.trove.map.hash.TObjectIntHashMap;
5 import java.io.DataInput;
6 import java.io.DataOutput;
7 import java.io.IOException;
10 import org.simantics.databoard.binding.UnionBinding;
11 import org.simantics.databoard.binding.error.BindingException;
12 import org.simantics.databoard.binding.util.IsReferableQuery;
13 import org.simantics.databoard.binding.util.Result;
14 import org.simantics.databoard.serialization.SerializationException;
15 import org.simantics.databoard.serialization.Serializer;
16 import org.simantics.databoard.serialization.Serializer.CompositeSerializer;
17 import org.simantics.databoard.type.UnionType;
18 import org.simantics.databoard.util.binary.Endian;
20 public class UnionSerializer extends CompositeSerializer {
23 public Serializer[] componentSerializers;
31 * @param componentSerializers (optional) can be set later
33 public UnionSerializer(UnionBinding binding, Serializer[] componentSerializers)
35 super( IsReferableQuery.isReferable( binding.type() ) != Result.No );
36 tagTypeCount = ((UnionType) binding.type()).components.length;
37 this.binding = binding;
38 this.componentSerializers = componentSerializers;
42 public void finalizeConstruction() {
43 // Calculate Fixed Size
44 for (Serializer s : componentSerializers)
46 Integer fixedSizeOfComponentSerializer = s.getConstantSize();
47 if (fixedSizeOfComponentSerializer==null) {
51 if (fixedSize!=null && fixedSizeOfComponentSerializer!=fixedSize) {
55 fixedSize = fixedSizeOfComponentSerializer;
57 if (componentSerializers.length == 0) fixedSize = 0;
58 if (fixedSize!=null) fixedSize += Endian.getUIntLength(tagTypeCount-1);
60 if (componentSerializers.length>0) {
61 minSize = Integer.MAX_VALUE;
62 for (Serializer s : componentSerializers) minSize = Math.min(minSize, s.getMinSize());
63 minSize += Endian.getUIntLength( tagTypeCount-1 );
69 public Object deserialize(DataInput in, List<Object> identities) throws IOException {
71 int tag = Endian.getUInt(in, tagTypeCount-1);
72 return binding.create(tag, componentSerializers[tag].deserialize(in, identities));
73 } catch (BindingException e) {
74 throw new IOException( e );
78 public Object deserializeToTry(DataInput in, List<Object> identities, Object dst) throws IOException
80 if (binding.isTagMutable()) {
81 return deserialize(in, identities);
83 deserializeTo(in, identities, dst);
90 public void deserializeTo(DataInput in, List<Object> identities, Object obj) throws IOException {
92 int tag = Endian.getUInt(in, tagTypeCount-1);
93 int oldTag = binding.getTag(obj);
94 Serializer cs = componentSerializers[tag];
95 boolean csImmutable = binding.getComponentBinding(tag).isImmutable();
97 if (oldTag==tag && !csImmutable) {
98 Object component = binding.getValue(obj);
99 component = componentSerializers[tag].deserializeToTry(in, identities, component);
100 binding.setValue(obj, tag, component);
102 Object component = cs.deserialize(in, identities);
103 binding.setValue(obj, tag, component);
105 } catch (BindingException e) {
106 throw new IOException( e );
111 public void skip(DataInput in, List<Object> identities) throws IOException, SerializationException {
112 int tag = Endian.getUInt(in, tagTypeCount-1);
113 componentSerializers[tag].skip(in, identities);
117 public void serialize(DataOutput out, TObjectIntHashMap<Object> identities, Object obj) throws IOException {
119 int tag = binding.getTag(obj);
120 Endian.putUInt(out, tag, tagTypeCount-1);
121 componentSerializers[tag].serialize(out, identities, binding.getValue(obj));
122 } catch (BindingException e) {
123 throw new IOException( e );
128 public Integer getConstantSize() {
133 public int getSize(Object obj, TObjectIntHashMap<Object> identities) throws IOException {
135 if (fixedSize!=null) return fixedSize;
136 int tag = binding.getTag(obj);
137 return Endian.getUIntLength( tagTypeCount-1 ) +
138 componentSerializers[tag].getSize(binding.getValue(obj), identities);
139 } catch (BindingException e) {
140 throw new IOException( e );
145 public int getMinSize() {