]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - 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
diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/serialization/impl/GenericRecordSerializer.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/serialization/impl/GenericRecordSerializer.java
new file mode 100644 (file)
index 0000000..beebb1d
--- /dev/null
@@ -0,0 +1,227 @@
+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.Binding;\r
+import org.simantics.databoard.binding.RecordBinding;\r
+import org.simantics.databoard.binding.error.BindingException;\r
+import org.simantics.databoard.binding.reflection.ClassBinding;\r
+import org.simantics.databoard.binding.util.IsReferableQuery;\r
+import org.simantics.databoard.binding.util.Result;\r
+import org.simantics.databoard.serialization.SerializationException;\r
+import org.simantics.databoard.serialization.Serializer;\r
+import org.simantics.databoard.serialization.Serializer.CompositeSerializer;\r
+\r
+public class GenericRecordSerializer extends CompositeSerializer {\r
+\r
+       RecordBinding binding;\r
+       public Serializer[] componentSerializers;\r
+       Integer fixedSize;\r
+       int minSize;\r
+       boolean createPartial;\r
+       \r
+       /**\r
+        * Field type for each field\r
+        *  0 - Object\r
+        *  1 - boolean\r
+        *  2 - byte\r
+        *  3 - int\r
+        *  4 - long\r
+        *  5 - float\r
+        *  6 - double\r
+        */\r
+       public int[] fieldType;\r
+       \r
+       /**\r
+        * \r
+        * @param binding\r
+        * @param componentSerializers (optional) can be set later\r
+        */\r
+       public GenericRecordSerializer(RecordBinding binding, Serializer[] componentSerializers) {              \r
+               super( IsReferableQuery.isReferable( binding.type() ) != Result.No );\r
+               this.binding = binding;                 \r
+               this.componentSerializers = componentSerializers;\r
+       }\r
+       \r
+       @Override\r
+       public void finalizeConstruction() {\r
+               fixedSize = null;\r
+\r
+               createPartial = !binding.isImmutable();\r
+               \r
+               if ( binding instanceof ClassBinding ) {\r
+                       ClassBinding cb = (ClassBinding) binding;\r
+                       createPartial &= cb.ci.partialConstructionPossible;\r
+               }\r
+               \r
+               fieldType = new int[componentSerializers.length];\r
+               for (int i=0; i<componentSerializers.length; i++) {\r
+                       Serializer cs = componentSerializers[i];\r
+                       //createPartial &= !binding.getComponentBinding(i).isImmutable(); \r
+                       minSize += cs.getMinSize();\r
+                       Integer componentFixedSize = cs.getConstantSize();\r
+                       if (componentFixedSize==null) {\r
+                               fixedSize = null;\r
+                               break;\r
+                       }\r
+                       fixedSize = fixedSize==null ? componentFixedSize : fixedSize+componentFixedSize;\r
+                       \r
+                       int type = 0;\r
+                       if ( cs instanceof BooleanSerializer ) type = 1;\r
+                       else if ( cs instanceof ByteSerializer ) type = 2;\r
+                       else if ( cs instanceof IntSerializer ) type = 3;\r
+                       else if ( cs instanceof LongSerializer ) type = 4;\r
+                       else if ( cs instanceof FloatSerializer ) type = 5;\r
+                       else if ( cs instanceof DoubleSerializer ) type = 6;\r
+                       fieldType[i] = type;\r
+               }\r
+               \r
+//             if ( binding instanceof ClassBinding ) {\r
+//                     ClassBinding cb = (ClassBinding) binding;\r
+//                     System.out.println(cb.ci.clazz.getName()+" = "+createPartial);\r
+//             }\r
+               \r
+       }\r
+\r
+       @Override\r
+       public Object deserialize(DataInput in, List<Object> identities) throws IOException {\r
+//             assertRemainingBytes(in, minSize);\r
+               try {\r
+                       if (createPartial) {\r
+                               Object obj = binding.createPartial();\r
+                               deserializeTo(in, identities, obj);\r
+                               return obj;\r
+                       } else {                                \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
+                               }\r
+                               return binding.create(temp);\r
+                       }\r
+                       \r
+               } catch (BindingException e) {\r
+                       throw new IOException( e ); \r
+               }\r
+       }\r
+       \r
+       @Override\r
+       public void deserializeTo(DataInput in, List<Object> identities, Object obj) throws IOException {\r
+//             assertRemainingBytes(in, minSize);\r
+               try {\r
+                       for(int i=0;i<componentSerializers.length;++i) {\r
+                               Serializer cs = componentSerializers[i];\r
+                               int type = fieldType[i];\r
+                               \r
+                               switch (type) {\r
+                               case 0:\r
+                                       Binding cb = binding.componentBindings[i];\r
+                                       boolean csImmutable = cb.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
+                                               if ( component == null ) {\r
+                                                       component = cs.deserialize(in, identities);\r
+                                                       binding.setComponent(obj, i, component);\r
+                                               } else {\r
+                                                       Object newComponent = cs.deserializeToTry(in, identities, component);\r
+                                                       if (newComponent!=component) binding.setComponent(obj, i, newComponent);\r
+                                               }\r
+                                       }\r
+                                       break;\r
+                               case 1:\r
+                                       binding.setBoolean(obj, i, ((BooleanSerializer)cs).getBoolean(in));\r
+                                       break;\r
+                               case 2:\r
+                                       binding.setByte(obj, i, ((ByteSerializer)cs).getByte(in));\r
+                                       break;\r
+                               case 3:\r
+                                       binding.setInt(obj, i, ((IntSerializer)cs).getInt(in));\r
+                                       break;\r
+                               case 4:\r
+                                       binding.setLong(obj, i, ((LongSerializer)cs).getLong(in));\r
+                                       break;\r
+                               case 5:\r
+                                       binding.setFloat(obj, i, ((FloatSerializer)cs).getFloat(in));\r
+                                       break;\r
+                               case 6:\r
+                                       binding.setDouble(obj, i, ((DoubleSerializer)cs).getDouble(in));\r
+                                       break;\r
+                               }\r
+                               \r
+                       }\r
+               } catch (BindingException e) {\r
+                       throw new IOException( e ); \r
+               }\r
+       }\r
+\r
+       @Override\r
+       public void skip(DataInput in, List<Object> identities) throws IOException, SerializationException {\r
+               if (fixedSize != null) {\r
+                       in.skipBytes(fixedSize);\r
+               } else {\r
+                       for(int i=0;i<componentSerializers.length;++i)\r
+                               componentSerializers[i].skip(in, identities);                           \r
+               }\r
+       }               \r
+       \r
+       @Override\r
+       public void serialize(DataOutput out, TObjectIntHashMap<Object> identities, Object obj) throws IOException {\r
+               try {\r
+                       for(int i=0;i<componentSerializers.length;++i) {\r
+                               int type = fieldType[i];\r
+                               Serializer cs = componentSerializers[i];\r
+                               switch( type ) {\r
+                               case 0: cs.serialize(out, identities, binding.getComponent(obj, i));\r
+                                       break;  \r
+                               case 1: ((BooleanSerializer)cs).putBoolean(out, binding.getBoolean(obj, i));\r
+                               break;\r
+                               case 2: ((ByteSerializer)cs).putByte(out, binding.getByte(obj, i));\r
+                               break;\r
+                               case 3: ((IntSerializer)cs).putInt(out, binding.getInt(obj, i));\r
+                               break;\r
+                               case 4: ((LongSerializer)cs).putLong(out, binding.getLong(obj, i));\r
+                               break;\r
+                               case 5: ((FloatSerializer)cs).putFloat(out, binding.getFloat(obj, i));\r
+                               break;\r
+                               case 6: ((DoubleSerializer)cs).putDouble(out, binding.getDouble(obj, i));\r
+                               break;\r
+                               }\r
+                       }\r
+               } catch (BindingException e) {\r
+                       throw new IOException( e ); \r
+               }\r
+       }\r
+\r
+       @Override\r
+       public Integer getConstantSize() {                      \r
+               return fixedSize;\r
+       }\r
+\r
+       @Override\r
+       public int getSize(Object obj, TObjectIntHashMap<Object> identities) throws IOException {\r
+               try {\r
+                       if (fixedSize!=null) return fixedSize;\r
+                       int result = 0;\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
+        * @return the minSize\r
+        */\r
+       public int getMinSize() {\r
+               return minSize;\r
+       }\r
+       \r
+}\r