]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.databoard/src/org/simantics/databoard/serialization/impl/MapSerializer.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / serialization / impl / MapSerializer.java
diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/serialization/impl/MapSerializer.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/serialization/impl/MapSerializer.java
new file mode 100644 (file)
index 0000000..0772180
--- /dev/null
@@ -0,0 +1,182 @@
+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
+import java.util.TreeSet;\r
+\r
+import org.simantics.databoard.binding.MapBinding;\r
+import org.simantics.databoard.binding.error.BindingException;\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 MapSerializer extends CompositeSerializer {\r
+\r
+       Integer fixedSizeOfKey, fixedSizeOfValue, fixedSizeOfEntry;\r
+       public Serializer keySerializer, valueSerializer;\r
+       MapBinding binding;\r
+       \r
+       /**\r
+        * \r
+        * @param binding\r
+        * @param keySerializer (optional) can be set later\r
+        * @param valueSerializer (optional) can be set later\r
+        */\r
+       public MapSerializer(MapBinding binding, Serializer keySerializer, Serializer valueSerializer) {\r
+               super( IsReferableQuery.isReferable( binding.type() ) != Result.No );\r
+               this.keySerializer = keySerializer;\r
+               this.valueSerializer = valueSerializer;\r
+               this.binding = binding;\r
+               \r
+       }\r
+       \r
+       @Override\r
+       public void finalizeConstruction() {\r
+               fixedSizeOfKey = keySerializer.getConstantSize();\r
+               fixedSizeOfValue = valueSerializer.getConstantSize();\r
+               fixedSizeOfEntry = (fixedSizeOfKey!=null && fixedSizeOfValue!=null) ? (fixedSizeOfKey+fixedSizeOfValue) : null; \r
+       }\r
+\r
+       @Override\r
+       public Object deserialize(DataInput in, List<Object> identities) throws IOException{\r
+               try {\r
+                       int length = in.readInt();\r
+                       if (length<0) throw new SerializationException("Cannot use negative array length");\r
+                       assertRemainingBytes(in, (long)length*((long)keySerializer.getMinSize()+(long)valueSerializer.getMinSize()));\r
+                       \r
+                       Object keys[] = new Object[length];\r
+                       Object values[] = new Object[length];\r
+                                               \r
+                       for(int i=0;i<length;++i) {\r
+                               keys[i] = keySerializer.deserialize(in, identities);\r
+                               values[i] = valueSerializer.deserialize(in, identities);                                \r
+                       }\r
+                       return binding.create(keys, values);\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
+               try {\r
+                       TreeSet<Object> oldKeys = new TreeSet<Object>( binding.getKeyBinding() );\r
+                       binding.getKeys(obj, oldKeys);\r
+                       \r
+                       int length = in.readInt();\r
+                       if (length<0) throw new SerializationException("Cannot use negative array length");\r
+                       assertRemainingBytes(in, (long)length*((long)keySerializer.getMinSize()+(long)valueSerializer.getMinSize()));\r
+                       \r
+                       for(int i=0;i<length;++i) {\r
+                               Object key = keySerializer.deserialize(in, identities);\r
+                               Object value = valueSerializer.deserialize(in, identities);\r
+                               binding.put(obj, key, value);\r
+                               oldKeys.remove(key);\r
+                       }\r
+                       \r
+                       // remove unused keys\r
+                       for (Object key : oldKeys)\r
+                               binding.remove(obj, key);\r
+               } catch (BindingException e) {\r
+                       throw new IOException( e ); \r
+               }\r
+                       \r
+       }\r
+       \r
+       @Override\r
+       public void skip(DataInput in, List<Object> identities)\r
+       throws IOException, SerializationException {\r
+               int length = in.readInt();\r
+               if (fixedSizeOfEntry!=null) {\r
+                       in.skipBytes( length * fixedSizeOfEntry );\r
+                       return;\r
+               }\r
+               for(int i=0;i<length;++i) {\r
+                       if (fixedSizeOfKey!=null) {\r
+                               in.skipBytes(fixedSizeOfKey);\r
+                       } else {\r
+                               keySerializer.skip(in, identities);\r
+                       }\r
+                       \r
+                       if (fixedSizeOfValue!=null) {\r
+                               in.skipBytes(fixedSizeOfValue);\r
+                       } else {\r
+                               valueSerializer.skip(in, identities);\r
+                       }\r
+               }\r
+       }\r
+\r
+       @Override\r
+       public void serialize(DataOutput out, TObjectIntHashMap<Object> identities, Object map) throws IOException {\r
+               try {\r
+                       int length = binding.size(map);\r
+                       //if (binding.isOrderedMap(map)) \r
+                       {\r
+                               Object[] keys = new Object[length];\r
+                               Object[] values = new Object[length];\r
+                               binding.getAll(map, keys, values);\r
+                               out.writeInt(length);\r
+                               for(int i=0;i<length;++i) {\r
+                                       Object key = keys[i];\r
+                                       Object value = values[i];\r
+                                       keySerializer.serialize(out, identities, key);\r
+                                       valueSerializer.serialize(out, identities, value);                              \r
+                               }\r
+                       }\r
+                       /*\r
+                       else {\r
+                               // Sort keys by putting into a treemap\r
+                               TreeMap<Object, Object> copyMap = new TreeMap<Object, Object>(binding.getKeyBinding());\r
+                               binding.getAll(map, copyMap);\r
+                               Iterator<Entry<Object, Object>> iter = copyMap.entrySet().iterator();\r
+                               putLength(out, length);\r
+                               while (iter.hasNext()) {\r
+                                       Entry<Object, Object> e = iter.next();\r
+                                       Object key = e.getKey();\r
+                                       Object value = e.getValue();\r
+                                       keySerializer.serialize(out, identities, key);\r
+                                       valueSerializer.serialize(out, identities, value);                              \r
+                               }\r
+                       }*/\r
+               } catch (BindingException e) {\r
+                       throw new IOException( e ); \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 length = binding.size(obj);\r
+                       if (fixedSizeOfEntry!=null)\r
+                               return 4 + fixedSizeOfEntry * length;\r
+                       int result = 4;\r
+                       Object keys[] = binding.getKeys(obj);\r
+                       for(int i=0;i<length;++i) {\r
+                               Object key = keys[i];\r
+                               Object value = binding.get(obj, key);\r
+                               result += keySerializer.getSize(key, identities);\r
+                               result += valueSerializer.getSize(value, identities);\r
+                       }\r
+                       return result;\r
+               } catch (BindingException e) {\r
+                       throw new IOException( e ); \r
+               }\r
+       }\r
+\r
+       @Override\r
+       public int getMinSize() {\r
+               return 4;\r
+       }\r
+       \r
+}      \r