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