]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/serialization/impl/OptionalSerializer.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / serialization / impl / OptionalSerializer.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.OptionalBinding;
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
18 public class OptionalSerializer  extends CompositeSerializer {
19
20         OptionalBinding binding;
21         public Serializer componentSerializer;          
22         boolean componentImmutable;             
23         Integer fixedSize;
24         
25         /**
26          * Create optional serializer
27          * 
28          * @param binding
29          * @param componentSerializer (optional), can be set after
30          */
31         public OptionalSerializer(OptionalBinding binding, Serializer componentSerializer) {
32                 super( IsReferableQuery.isReferable( binding.type() ) != Result.No );
33                 this.componentSerializer = componentSerializer;
34                 this.binding = binding;
35                 this.componentImmutable = binding.getComponentBinding().isImmutable();                  
36         }
37         
38         @Override
39         public void finalizeConstruction() {
40                 Integer fixedSizeOfComponent = componentSerializer.getConstantSize();
41                 if (fixedSizeOfComponent!=null && fixedSizeOfComponent==0) {
42                         fixedSize = fixedSizeOfComponent + 1;
43                 }
44         }
45
46         @Override
47         public Object deserialize(DataInput in, List<Object> identities) throws IOException {
48                 try {
49                         byte x = in.readByte();
50                         if (x == 0) return binding.createNoValue();
51                         else if (x == 1) {
52                                 Object componentValue = componentSerializer.deserialize(in, identities);
53                                 return binding.createValue(componentValue);
54                         }
55                         else throw new SerializationException("Unexpected marker for option "+x+" 0 or 1 expected.");
56                 } catch (BindingException e) {
57                         throw new IOException( e ); 
58                 }
59         }
60         
61         @Override
62         public void deserializeTo(DataInput in, List<Object> identities,
63                         Object obj) throws IOException {
64                 try {
65                         byte x = in.readByte();
66                         if (x == 0) {
67                                 if (binding.hasValue(obj)) binding.setNoValue(obj);
68                         } else if (x == 1) {
69                                 if (componentImmutable) {
70                                         Object component = componentSerializer.deserialize(in, identities);
71                                         binding.setValue(obj, component);
72                                 } else {
73                                         Object component = binding.hasValue(obj) ? binding.getValue(obj) : binding.componentBinding.createDefault();
74                                         component = componentSerializer.deserializeToTry(in, identities, component);
75                                         binding.setValue(obj, component);
76                                 }
77                                 
78                         }
79                         else throw new SerializationException("Unexpected marker for option "+x+" 0 or 1 expected.");
80                 } catch (BindingException e) {
81                         throw new IOException( e ); 
82                 }
83         }
84
85         @Override
86         public void skip(DataInput in, List<Object> identities) throws IOException, SerializationException {
87                 int x = in.readByte();
88                 if (x==1) componentSerializer.skip(in, identities);
89         }
90         
91         @Override
92         public void serialize(DataOutput out, TObjectIntHashMap<Object> identities, Object obj) throws IOException {
93                 try {
94                         if (!binding.hasValue(obj)) {
95                                 out.write((byte)0);
96                         } else {
97                                 out.write((byte)1);
98                                 Object componentValue = binding.getValue(obj);
99                                 componentSerializer.serialize(out, identities, componentValue);
100                         }
101                 } catch (BindingException e) {
102                         throw new IOException( e ); 
103                 }
104                         
105         }
106
107         @Override
108         public Integer getConstantSize() {
109                 return fixedSize;
110         }
111
112         @Override
113         public int getSize(Object obj, TObjectIntHashMap<Object> identities) throws IOException {
114                 try {
115                         if (fixedSize!=null) return fixedSize;
116                         if (!binding.hasValue(obj)) return 1;
117                         Object componentValue = binding.getValue(obj);
118                         return 1 + componentSerializer.getSize(componentValue, identities);
119                 } catch (BindingException e) {
120                         throw new IOException( e ); 
121                 }                       
122         }
123         
124         @Override
125         public int getMinSize() {
126                 return 1;
127         }
128         
129 }