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.Binding;
\r
11 import org.simantics.databoard.binding.RecordBinding;
\r
12 import org.simantics.databoard.binding.error.BindingException;
\r
13 import org.simantics.databoard.binding.reflection.ClassBinding;
\r
14 import org.simantics.databoard.binding.util.IsReferableQuery;
\r
15 import org.simantics.databoard.binding.util.Result;
\r
16 import org.simantics.databoard.serialization.SerializationException;
\r
17 import org.simantics.databoard.serialization.Serializer;
\r
18 import org.simantics.databoard.serialization.Serializer.CompositeSerializer;
\r
20 public class GenericRecordSerializer extends CompositeSerializer {
\r
22 RecordBinding binding;
\r
23 public Serializer[] componentSerializers;
\r
26 boolean createPartial;
\r
29 * Field type for each field
\r
38 public int[] fieldType;
\r
43 * @param componentSerializers (optional) can be set later
\r
45 public GenericRecordSerializer(RecordBinding binding, Serializer[] componentSerializers) {
\r
46 super( IsReferableQuery.isReferable( binding.type() ) != Result.No );
\r
47 this.binding = binding;
\r
48 this.componentSerializers = componentSerializers;
\r
52 public void finalizeConstruction() {
\r
55 createPartial = !binding.isImmutable();
\r
57 if ( binding instanceof ClassBinding ) {
\r
58 ClassBinding cb = (ClassBinding) binding;
\r
59 createPartial &= cb.ci.partialConstructionPossible;
\r
62 fieldType = new int[componentSerializers.length];
\r
63 for (int i=0; i<componentSerializers.length; i++) {
\r
64 Serializer cs = componentSerializers[i];
\r
65 //createPartial &= !binding.getComponentBinding(i).isImmutable();
\r
66 minSize += cs.getMinSize();
\r
67 Integer componentFixedSize = cs.getConstantSize();
\r
68 if (componentFixedSize==null) {
\r
72 fixedSize = fixedSize==null ? componentFixedSize : fixedSize+componentFixedSize;
\r
75 if ( cs instanceof BooleanSerializer ) type = 1;
\r
76 else if ( cs instanceof ByteSerializer ) type = 2;
\r
77 else if ( cs instanceof IntSerializer ) type = 3;
\r
78 else if ( cs instanceof LongSerializer ) type = 4;
\r
79 else if ( cs instanceof FloatSerializer ) type = 5;
\r
80 else if ( cs instanceof DoubleSerializer ) type = 6;
\r
81 fieldType[i] = type;
\r
84 // if ( binding instanceof ClassBinding ) {
\r
85 // ClassBinding cb = (ClassBinding) binding;
\r
86 // System.out.println(cb.ci.clazz.getName()+" = "+createPartial);
\r
92 public Object deserialize(DataInput in, List<Object> identities) throws IOException {
\r
93 // assertRemainingBytes(in, minSize);
\r
95 if (createPartial) {
\r
96 Object obj = binding.createPartial();
\r
97 deserializeTo(in, identities, obj);
\r
100 Object[] temp = new Object[componentSerializers.length];
\r
101 for(int i=0;i<componentSerializers.length;++i) {
\r
102 temp[i] = componentSerializers[i].deserialize(in, identities);
\r
104 return binding.create(temp);
\r
107 } catch (BindingException e) {
\r
108 throw new IOException( e );
\r
113 public void deserializeTo(DataInput in, List<Object> identities, Object obj) throws IOException {
\r
114 // assertRemainingBytes(in, minSize);
\r
116 for(int i=0;i<componentSerializers.length;++i) {
\r
117 Serializer cs = componentSerializers[i];
\r
118 int type = fieldType[i];
\r
122 Binding cb = binding.componentBindings[i];
\r
123 boolean csImmutable = cb.isImmutable();
\r
125 Object component = cs.deserialize(in, identities);
\r
126 binding.setComponent(obj, i, component);
\r
128 Object component = binding.getComponent(obj, i);
\r
129 if ( component == null ) {
\r
130 component = cs.deserialize(in, identities);
\r
131 binding.setComponent(obj, i, component);
\r
133 Object newComponent = cs.deserializeToTry(in, identities, component);
\r
134 if (newComponent!=component) binding.setComponent(obj, i, newComponent);
\r
139 binding.setBoolean(obj, i, ((BooleanSerializer)cs).getBoolean(in));
\r
142 binding.setByte(obj, i, ((ByteSerializer)cs).getByte(in));
\r
145 binding.setInt(obj, i, ((IntSerializer)cs).getInt(in));
\r
148 binding.setLong(obj, i, ((LongSerializer)cs).getLong(in));
\r
151 binding.setFloat(obj, i, ((FloatSerializer)cs).getFloat(in));
\r
154 binding.setDouble(obj, i, ((DoubleSerializer)cs).getDouble(in));
\r
159 } catch (BindingException e) {
\r
160 throw new IOException( e );
\r
165 public void skip(DataInput in, List<Object> identities) throws IOException, SerializationException {
\r
166 if (fixedSize != null) {
\r
167 in.skipBytes(fixedSize);
\r
169 for(int i=0;i<componentSerializers.length;++i)
\r
170 componentSerializers[i].skip(in, identities);
\r
175 public void serialize(DataOutput out, TObjectIntHashMap<Object> identities, Object obj) throws IOException {
\r
177 for(int i=0;i<componentSerializers.length;++i) {
\r
178 int type = fieldType[i];
\r
179 Serializer cs = componentSerializers[i];
\r
181 case 0: cs.serialize(out, identities, binding.getComponent(obj, i));
\r
183 case 1: ((BooleanSerializer)cs).putBoolean(out, binding.getBoolean(obj, i));
\r
185 case 2: ((ByteSerializer)cs).putByte(out, binding.getByte(obj, i));
\r
187 case 3: ((IntSerializer)cs).putInt(out, binding.getInt(obj, i));
\r
189 case 4: ((LongSerializer)cs).putLong(out, binding.getLong(obj, i));
\r
191 case 5: ((FloatSerializer)cs).putFloat(out, binding.getFloat(obj, i));
\r
193 case 6: ((DoubleSerializer)cs).putDouble(out, binding.getDouble(obj, i));
\r
197 } catch (BindingException e) {
\r
198 throw new IOException( e );
\r
203 public Integer getConstantSize() {
\r
208 public int getSize(Object obj, TObjectIntHashMap<Object> identities) throws IOException {
\r
210 if (fixedSize!=null) return fixedSize;
\r
212 for(int i=0;i<componentSerializers.length;++i)
\r
213 result += componentSerializers[i].getSize( binding.getComponent(obj, i), identities );
\r
215 } catch (BindingException e) {
\r
216 throw new IOException( e );
\r
221 * @return the minSize
\r
223 public int getMinSize() {
\r