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