--- /dev/null
+package org.simantics.databoard.serialization.impl;\r
+\r
+import gnu.trove.map.hash.TObjectIntHashMap;\r
+\r
+import java.io.DataInput;\r
+import java.io.DataOutput;\r
+import java.io.IOException;\r
+import java.util.List;\r
+\r
+import org.simantics.databoard.binding.RecordBinding;\r
+import org.simantics.databoard.binding.error.BindingException;\r
+import org.simantics.databoard.serialization.SerializationException;\r
+import org.simantics.databoard.serialization.Serializer;\r
+import org.simantics.databoard.serialization.Serializer.RecursiveSerializer;\r
+import org.simantics.databoard.type.RecordType;\r
+\r
+public class ReferableRecordSerializer extends RecursiveSerializer {\r
+\r
+ RecordBinding binding;\r
+ public Serializer[] componentSerializers;\r
+ \r
+ /** The combined size elements, or <code>null</code> */ \r
+ Integer fixedSizeOfContent;\r
+ int minContentSize;\r
+ \r
+ public ReferableRecordSerializer(RecordBinding binding, Serializer[] componentSerializers) {\r
+ this.binding = binding;\r
+ this.componentSerializers = componentSerializers;\r
+ }\r
+ \r
+ @Override\r
+ public void finalizeConstruction() {\r
+ fixedSizeOfContent = null;\r
+ for (Serializer componentSerializer : componentSerializers) {\r
+ minContentSize += componentSerializer.getMinSize();\r
+ Integer componentFixedSize = componentSerializer.getConstantSize();\r
+ if (componentFixedSize==null) {\r
+ fixedSizeOfContent = null;\r
+ break;\r
+ }\r
+ fixedSizeOfContent = fixedSizeOfContent==null ? componentFixedSize : fixedSizeOfContent + componentFixedSize; \r
+ }\r
+ }\r
+\r
+ boolean referable() {\r
+ return ((RecordType)binding.type()).isReferable();\r
+ }\r
+ \r
+ @Override\r
+ public Object deserialize(DataInput in, List<Object> identities) throws IOException {\r
+ try {\r
+ int id = in.readInt();\r
+ if(id > 0)\r
+ return identities.get(id-1); \r
+ \r
+ Object result = binding.createPartial();\r
+ identities.add(result);\r
+ \r
+// assertRemainingBytes(in, minContentSize);\r
+ Object[] temp = new Object[componentSerializers.length];\r
+ for(int i=0;i<componentSerializers.length;++i)\r
+ temp[i] = componentSerializers[i].deserialize(in, identities);\r
+ binding.setComponents(result, temp);\r
+ \r
+ return result;\r
+ } catch (BindingException e) {\r
+ throw new IOException( e ); \r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void deserializeTo(DataInput in, List<Object> identities,\r
+ Object obj) throws IOException {\r
+ try {\r
+ int id = in.readInt();\r
+ if(id > 0) {\r
+ Object alreadyDeserializedObject = identities.get(id-1);\r
+ if (alreadyDeserializedObject!=obj) {\r
+ for (int i=0; i<binding.getComponentCount(); ++i) {\r
+ Object component = binding.getComponent(alreadyDeserializedObject, i);\r
+ binding.setComponent(obj, i, component);\r
+ }\r
+ }\r
+ return;\r
+ }\r
+ \r
+ identities.add(obj);\r
+// assertRemainingBytes(in, minContentSize);\r
+ for(int i=0;i<componentSerializers.length;++i) {\r
+ Serializer cs = componentSerializers[i];\r
+ boolean csImmutable = binding.getComponentBinding(i).isImmutable();\r
+ if (csImmutable) {\r
+ Object component = cs.deserialize(in, identities);\r
+ binding.setComponent(obj, i, component);\r
+ } else {\r
+ Object component = binding.getComponent(obj, i);\r
+ component = cs.deserializeToTry(in, identities, component);\r
+ binding.setComponent(obj, i, component);\r
+ }\r
+ }\r
+ } catch (BindingException e) {\r
+ throw new IOException( e ); \r
+ }\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void skip(DataInput in, List<Object> identities) throws IOException, SerializationException {\r
+ \r
+ int id = in.readInt();\r
+ if(id > 0) return; \r
+ \r
+ for(int i=0;i<componentSerializers.length;++i)\r
+ componentSerializers[i].skip(in, identities);\r
+ }\r
+\r
+ @Override\r
+ public void serialize(DataOutput out, TObjectIntHashMap<Object> identities, Object obj) throws IOException {\r
+ try {\r
+ int id = identities.get(obj);\r
+ if(id > 0) {\r
+ out.writeInt(id);\r
+ }\r
+ else {\r
+ out.writeInt(0);\r
+ identities.put(obj, identities.size() + 1);\r
+ for(int i=0;i<componentSerializers.length;++i)\r
+ componentSerializers[i].serialize(out, identities, binding.getComponent(obj, i));\r
+ }\r
+ } catch (BindingException e) {\r
+ throw new IOException( e ); \r
+ }\r
+ \r
+ }\r
+\r
+ @Override\r
+ public Integer getConstantSize() {\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ public int getSize(Object obj, TObjectIntHashMap<Object> identities) throws IOException {\r
+ try {\r
+ int id = identities.get(obj);\r
+ if (id>0) return 4;\r
+ identities.put(obj, identities.size()+1);\r
+ if (fixedSizeOfContent!=null) return 4+fixedSizeOfContent;\r
+ int result = 4; \r
+ for(int i=0;i<componentSerializers.length;++i)\r
+ result += componentSerializers[i].getSize( binding.getComponent(obj, i), identities ); \r
+ return result;\r
+ } catch (BindingException e) {\r
+ throw new IOException( e ); \r
+ }\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public int getMinSize() {\r
+ return 4;\r
+ }\r
+ \r
+}\r
+\r