]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/serialization/impl/ReferableRecordSerializer.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / serialization / impl / ReferableRecordSerializer.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.RecordBinding;
11 import org.simantics.databoard.binding.error.BindingException;
12 import org.simantics.databoard.serialization.SerializationException;
13 import org.simantics.databoard.serialization.Serializer;
14 import org.simantics.databoard.serialization.Serializer.RecursiveSerializer;
15 import org.simantics.databoard.type.RecordType;
16
17 public class ReferableRecordSerializer extends RecursiveSerializer {
18
19         RecordBinding binding;
20         public Serializer[] componentSerializers;
21         
22         /** The combined size elements, or <code>null</code> */ 
23         Integer fixedSizeOfContent;
24         int minContentSize;
25         
26         public ReferableRecordSerializer(RecordBinding binding, Serializer[] componentSerializers) {
27                 this.binding = binding;
28                 this.componentSerializers = componentSerializers;
29         }
30         
31         @Override
32         public void finalizeConstruction() {
33                 fixedSizeOfContent = null;
34                 for (Serializer componentSerializer : componentSerializers) {
35                         minContentSize += componentSerializer.getMinSize();
36                         Integer componentFixedSize = componentSerializer.getConstantSize();
37                         if (componentFixedSize==null) {
38                                 fixedSizeOfContent = null;
39                                 break;
40                         }
41                         fixedSizeOfContent = fixedSizeOfContent==null ? componentFixedSize : fixedSizeOfContent + componentFixedSize; 
42                 }
43         }
44
45         boolean referable() {
46                 return ((RecordType)binding.type()).isReferable();
47         }
48         
49         @Override
50         public Object deserialize(DataInput in, List<Object> identities) throws IOException {
51                 try {
52                         int id = in.readInt();
53                         if(id > 0)
54                                 return identities.get(id-1);                    
55                         
56                         Object result = binding.createPartial();
57                         identities.add(result);
58                         
59 //                      assertRemainingBytes(in, minContentSize);
60                         Object[] temp = new Object[componentSerializers.length];
61                         for(int i=0;i<componentSerializers.length;++i)
62                                 temp[i] = componentSerializers[i].deserialize(in, identities);
63                         binding.setComponents(result, temp);
64                         
65                         return result;
66                 } catch (BindingException e) {
67                         throw new IOException( e ); 
68                 }
69         }
70         
71         @Override
72         public void deserializeTo(DataInput in, List<Object> identities,
73                         Object obj) throws IOException {
74                 try {
75                         int id = in.readInt();
76                         if(id > 0) {
77                                 Object alreadyDeserializedObject = identities.get(id-1);
78                                 if (alreadyDeserializedObject!=obj) {
79                                         for (int i=0; i<binding.getComponentCount(); ++i) {
80                                                 Object component = binding.getComponent(alreadyDeserializedObject, i);
81                                                 binding.setComponent(obj, i, component);
82                                         }
83                                 }
84                                 return;
85                         }
86                         
87                         identities.add(obj);
88 //                      assertRemainingBytes(in, minContentSize);
89                         for(int i=0;i<componentSerializers.length;++i) {
90                                 Serializer cs = componentSerializers[i];
91                                 boolean csImmutable = binding.getComponentBinding(i).isImmutable();
92                                 if (csImmutable) {
93                                         Object component = cs.deserialize(in, identities);
94                                         binding.setComponent(obj, i, component);
95                                 } else {
96                                         Object component = binding.getComponent(obj, i);
97                                         component = cs.deserializeToTry(in, identities, component);
98                                         binding.setComponent(obj, i, component);
99                                 }
100                         }
101                 } catch (BindingException e) {
102                         throw new IOException( e ); 
103                 }
104                 
105         }
106         
107         @Override
108         public void skip(DataInput in, List<Object> identities) throws IOException, SerializationException {
109                 
110                 int id = in.readInt();
111                 if(id > 0) return;                      
112                 
113                 for(int i=0;i<componentSerializers.length;++i)
114                         componentSerializers[i].skip(in, identities);
115         }
116
117         @Override
118         public void serialize(DataOutput out, TObjectIntHashMap<Object> identities, Object obj) throws IOException {
119                 try {
120                         int id = identities.get(obj);
121                         if(id > 0) {
122                                 out.writeInt(id);
123                         }
124                         else {
125                                 out.writeInt(0);
126                                 identities.put(obj, identities.size() + 1);
127                                 for(int i=0;i<componentSerializers.length;++i)
128                                         componentSerializers[i].serialize(out, identities, binding.getComponent(obj, i));
129                         }
130                 } catch (BindingException e) {
131                         throw new IOException( e ); 
132                 }
133                         
134         }
135
136         @Override
137         public Integer getConstantSize() {
138                 return null;
139         }
140
141         @Override
142         public int getSize(Object obj, TObjectIntHashMap<Object> identities) throws IOException {
143                 try {
144                         int id = identities.get(obj);
145                         if (id>0) return 4;
146                         identities.put(obj, identities.size()+1);
147                         if (fixedSizeOfContent!=null) return 4+fixedSizeOfContent;
148                         int result = 4;                 
149                         for(int i=0;i<componentSerializers.length;++i)
150                                 result += componentSerializers[i].getSize( binding.getComponent(obj, i), identities );                  
151                         return result;
152                 } catch (BindingException e) {
153                         throw new IOException( e ); 
154                 }
155                         
156         }
157         
158         @Override
159         public int getMinSize() {
160                 return 4;
161         }
162         
163 }
164