]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/serialization/impl/GenericRecordSerializer.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / serialization / impl / GenericRecordSerializer.java
1 package org.simantics.databoard.serialization.impl;
2
3 import gnu.trove.map.hash.TObjectIntHashMap;
4
5 import java.io.DataInput;
6 import java.io.DataOutput;
7 import java.io.IOException;
8 import java.util.List;
9
10 import org.simantics.databoard.binding.Binding;
11 import org.simantics.databoard.binding.RecordBinding;
12 import org.simantics.databoard.binding.error.BindingException;
13 import org.simantics.databoard.binding.reflection.ClassBinding;
14 import org.simantics.databoard.binding.util.IsReferableQuery;
15 import org.simantics.databoard.binding.util.Result;
16 import org.simantics.databoard.serialization.SerializationException;
17 import org.simantics.databoard.serialization.Serializer;
18 import org.simantics.databoard.serialization.Serializer.CompositeSerializer;
19
20 public class GenericRecordSerializer extends CompositeSerializer {
21
22         RecordBinding binding;
23         public Serializer[] componentSerializers;
24         Integer fixedSize;
25         int minSize;
26         boolean createPartial;
27         
28         /**
29          * Field type for each field
30          *  0 - Object
31          *  1 - boolean
32          *  2 - byte
33          *  3 - int
34          *  4 - long
35          *  5 - float
36          *  6 - double
37          */
38         public int[] fieldType;
39         
40         /**
41          * 
42          * @param binding
43          * @param componentSerializers (optional) can be set later
44          */
45         public GenericRecordSerializer(RecordBinding binding, Serializer[] componentSerializers) {              
46                 super( IsReferableQuery.isReferable( binding.type() ) != Result.No );
47                 this.binding = binding;                 
48                 this.componentSerializers = componentSerializers;
49         }
50         
51         @Override
52         public void finalizeConstruction() {
53                 fixedSize = null;
54
55                 createPartial = !binding.isImmutable();
56                 
57                 if ( binding instanceof ClassBinding ) {
58                         ClassBinding cb = (ClassBinding) binding;
59                         createPartial &= cb.ci.partialConstructionPossible;
60                 }
61                 
62                 fieldType = new int[componentSerializers.length];
63                 for (int i=0; i<componentSerializers.length; i++) {
64                         Serializer cs = componentSerializers[i];
65                         //createPartial &= !binding.getComponentBinding(i).isImmutable(); 
66                         minSize += cs.getMinSize();
67                         Integer componentFixedSize = cs.getConstantSize();
68                         if (componentFixedSize==null) {
69                                 fixedSize = null;
70                                 break;
71                         }
72                         fixedSize = fixedSize==null ? componentFixedSize : fixedSize+componentFixedSize;
73                         
74                         int type = 0;
75                         if ( cs instanceof BooleanSerializer ) type = 1;
76                         else if ( cs instanceof ByteSerializer ) type = 2;
77                         else if ( cs instanceof IntSerializer ) type = 3;
78                         else if ( cs instanceof LongSerializer ) type = 4;
79                         else if ( cs instanceof FloatSerializer ) type = 5;
80                         else if ( cs instanceof DoubleSerializer ) type = 6;
81                         fieldType[i] = type;
82                 }
83                 
84 //              if ( binding instanceof ClassBinding ) {
85 //                      ClassBinding cb = (ClassBinding) binding;
86 //                      System.out.println(cb.ci.clazz.getName()+" = "+createPartial);
87 //              }
88                 
89         }
90
91         @Override
92         public Object deserialize(DataInput in, List<Object> identities) throws IOException {
93 //              assertRemainingBytes(in, minSize);
94                 try {
95                         if (createPartial) {
96                                 Object obj = binding.createPartial();
97                                 deserializeTo(in, identities, obj);
98                                 return obj;
99                         } else {                                
100                                 Object[] temp = new Object[componentSerializers.length];
101                                 for(int i=0;i<componentSerializers.length;++i) {
102                                         temp[i] = componentSerializers[i].deserialize(in, identities);
103                                 }
104                                 return binding.create(temp);
105                         }
106                         
107                 } catch (BindingException e) {
108                         throw new IOException( e ); 
109                 }
110         }
111         
112         @Override
113         public void deserializeTo(DataInput in, List<Object> identities, Object obj) throws IOException {
114 //              assertRemainingBytes(in, minSize);
115                 try {
116                         for(int i=0;i<componentSerializers.length;++i) {
117                                 Serializer cs = componentSerializers[i];
118                                 int type = fieldType[i];
119                                 
120                                 switch (type) {
121                                 case 0:
122                                         Binding cb = binding.componentBindings[i];
123                                         boolean csImmutable = cb.isImmutable();
124                                         if (csImmutable) {
125                                                 Object component = cs.deserialize(in, identities);
126                                                 binding.setComponent(obj, i, component);
127                                         } else {
128                                                 Object component = binding.getComponent(obj, i);
129                                                 if ( component == null ) {
130                                                         component = cs.deserialize(in, identities);
131                                                         binding.setComponent(obj, i, component);
132                                                 } else {
133                                                         Object newComponent = cs.deserializeToTry(in, identities, component);
134                                                         if (newComponent!=component) binding.setComponent(obj, i, newComponent);
135                                                 }
136                                         }
137                                         break;
138                                 case 1:
139                                         binding.setBoolean(obj, i, ((BooleanSerializer)cs).getBoolean(in));
140                                         break;
141                                 case 2:
142                                         binding.setByte(obj, i, ((ByteSerializer)cs).getByte(in));
143                                         break;
144                                 case 3:
145                                         binding.setInt(obj, i, ((IntSerializer)cs).getInt(in));
146                                         break;
147                                 case 4:
148                                         binding.setLong(obj, i, ((LongSerializer)cs).getLong(in));
149                                         break;
150                                 case 5:
151                                         binding.setFloat(obj, i, ((FloatSerializer)cs).getFloat(in));
152                                         break;
153                                 case 6:
154                                         binding.setDouble(obj, i, ((DoubleSerializer)cs).getDouble(in));
155                                         break;
156                                 }
157                                 
158                         }
159                 } catch (BindingException e) {
160                         throw new IOException( e ); 
161                 }
162         }
163
164         @Override
165         public void skip(DataInput in, List<Object> identities) throws IOException, SerializationException {
166                 if (fixedSize != null) {
167                         in.skipBytes(fixedSize);
168                 } else {
169                         for(int i=0;i<componentSerializers.length;++i)
170                                 componentSerializers[i].skip(in, identities);                           
171                 }
172         }               
173         
174         @Override
175         public void serialize(DataOutput out, TObjectIntHashMap<Object> identities, Object obj) throws IOException {
176                 try {
177                         for(int i=0;i<componentSerializers.length;++i) {
178                                 int type = fieldType[i];
179                                 Serializer cs = componentSerializers[i];
180                                 switch( type ) {
181                                 case 0: cs.serialize(out, identities, binding.getComponent(obj, i));
182                                         break;  
183                                 case 1: ((BooleanSerializer)cs).putBoolean(out, binding.getBoolean(obj, i));
184                                 break;
185                                 case 2: ((ByteSerializer)cs).putByte(out, binding.getByte(obj, i));
186                                 break;
187                                 case 3: ((IntSerializer)cs).putInt(out, binding.getInt(obj, i));
188                                 break;
189                                 case 4: ((LongSerializer)cs).putLong(out, binding.getLong(obj, i));
190                                 break;
191                                 case 5: ((FloatSerializer)cs).putFloat(out, binding.getFloat(obj, i));
192                                 break;
193                                 case 6: ((DoubleSerializer)cs).putDouble(out, binding.getDouble(obj, i));
194                                 break;
195                                 }
196                         }
197                 } catch (BindingException e) {
198                         throw new IOException( e ); 
199                 }
200         }
201
202         @Override
203         public Integer getConstantSize() {                      
204                 return fixedSize;
205         }
206
207         @Override
208         public int getSize(Object obj, TObjectIntHashMap<Object> identities) throws IOException {
209                 try {
210                         if (fixedSize!=null) return fixedSize;
211                         int result = 0;
212                         for(int i=0;i<componentSerializers.length;++i)
213                                 result += componentSerializers[i].getSize( binding.getComponent(obj, i), identities );                  
214                         return result;
215                 } catch (BindingException e) {
216                         throw new IOException( e ); 
217                 }
218         }
219         
220         /**
221          * @return the minSize
222          */
223         public int getMinSize() {
224                 return minSize;
225         }
226         
227 }