]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
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 import java.util.TreeSet;\r
10 \r
11 import org.simantics.databoard.binding.MapBinding;\r
12 import org.simantics.databoard.binding.error.BindingException;\r
13 import org.simantics.databoard.binding.util.IsReferableQuery;\r
14 import org.simantics.databoard.binding.util.Result;\r
15 import org.simantics.databoard.serialization.SerializationException;\r
16 import org.simantics.databoard.serialization.Serializer;\r
17 import org.simantics.databoard.serialization.Serializer.CompositeSerializer;\r
18 \r
19 public class MapSerializer extends CompositeSerializer {\r
20 \r
21         Integer fixedSizeOfKey, fixedSizeOfValue, fixedSizeOfEntry;\r
22         public Serializer keySerializer, valueSerializer;\r
23         MapBinding binding;\r
24         \r
25         /**\r
26          * \r
27          * @param binding\r
28          * @param keySerializer (optional) can be set later\r
29          * @param valueSerializer (optional) can be set later\r
30          */\r
31         public MapSerializer(MapBinding binding, Serializer keySerializer, Serializer valueSerializer) {\r
32                 super( IsReferableQuery.isReferable( binding.type() ) != Result.No );\r
33                 this.keySerializer = keySerializer;\r
34                 this.valueSerializer = valueSerializer;\r
35                 this.binding = binding;\r
36                 \r
37         }\r
38         \r
39         @Override\r
40         public void finalizeConstruction() {\r
41                 fixedSizeOfKey = keySerializer.getConstantSize();\r
42                 fixedSizeOfValue = valueSerializer.getConstantSize();\r
43                 fixedSizeOfEntry = (fixedSizeOfKey!=null && fixedSizeOfValue!=null) ? (fixedSizeOfKey+fixedSizeOfValue) : null; \r
44         }\r
45 \r
46         @Override\r
47         public Object deserialize(DataInput in, List<Object> identities) throws IOException{\r
48                 try {\r
49                         int length = in.readInt();\r
50                         if (length<0) throw new SerializationException("Cannot use negative array length");\r
51                         assertRemainingBytes(in, (long)length*((long)keySerializer.getMinSize()+(long)valueSerializer.getMinSize()));\r
52                         \r
53                         Object keys[] = new Object[length];\r
54                         Object values[] = new Object[length];\r
55                                                 \r
56                         for(int i=0;i<length;++i) {\r
57                                 keys[i] = keySerializer.deserialize(in, identities);\r
58                                 values[i] = valueSerializer.deserialize(in, identities);                                \r
59                         }\r
60                         return binding.create(keys, values);\r
61                 } catch (BindingException e) {\r
62                         throw new IOException( e ); \r
63                 }                       \r
64         }\r
65         \r
66         @Override\r
67         public void deserializeTo(DataInput in, List<Object> identities, Object obj) throws IOException {\r
68                 try {\r
69                         TreeSet<Object> oldKeys = new TreeSet<Object>( binding.getKeyBinding() );\r
70                         binding.getKeys(obj, oldKeys);\r
71                         \r
72                         int length = in.readInt();\r
73                         if (length<0) throw new SerializationException("Cannot use negative array length");\r
74                         assertRemainingBytes(in, (long)length*((long)keySerializer.getMinSize()+(long)valueSerializer.getMinSize()));\r
75                         \r
76                         for(int i=0;i<length;++i) {\r
77                                 Object key = keySerializer.deserialize(in, identities);\r
78                                 Object value = valueSerializer.deserialize(in, identities);\r
79                                 binding.put(obj, key, value);\r
80                                 oldKeys.remove(key);\r
81                         }\r
82                         \r
83                         // remove unused keys\r
84                         for (Object key : oldKeys)\r
85                                 binding.remove(obj, key);\r
86                 } catch (BindingException e) {\r
87                         throw new IOException( e ); \r
88                 }\r
89                         \r
90         }\r
91         \r
92         @Override\r
93         public void skip(DataInput in, List<Object> identities)\r
94         throws IOException, SerializationException {\r
95                 int length = in.readInt();\r
96                 if (fixedSizeOfEntry!=null) {\r
97                         in.skipBytes( length * fixedSizeOfEntry );\r
98                         return;\r
99                 }\r
100                 for(int i=0;i<length;++i) {\r
101                         if (fixedSizeOfKey!=null) {\r
102                                 in.skipBytes(fixedSizeOfKey);\r
103                         } else {\r
104                                 keySerializer.skip(in, identities);\r
105                         }\r
106                         \r
107                         if (fixedSizeOfValue!=null) {\r
108                                 in.skipBytes(fixedSizeOfValue);\r
109                         } else {\r
110                                 valueSerializer.skip(in, identities);\r
111                         }\r
112                 }\r
113         }\r
114 \r
115         @Override\r
116         public void serialize(DataOutput out, TObjectIntHashMap<Object> identities, Object map) throws IOException {\r
117                 try {\r
118                         int length = binding.size(map);\r
119                         //if (binding.isOrderedMap(map)) \r
120                         {\r
121                                 Object[] keys = new Object[length];\r
122                                 Object[] values = new Object[length];\r
123                                 binding.getAll(map, keys, values);\r
124                                 out.writeInt(length);\r
125                                 for(int i=0;i<length;++i) {\r
126                                         Object key = keys[i];\r
127                                         Object value = values[i];\r
128                                         keySerializer.serialize(out, identities, key);\r
129                                         valueSerializer.serialize(out, identities, value);                              \r
130                                 }\r
131                         }\r
132                         /*\r
133                         else {\r
134                                 // Sort keys by putting into a treemap\r
135                                 TreeMap<Object, Object> copyMap = new TreeMap<Object, Object>(binding.getKeyBinding());\r
136                                 binding.getAll(map, copyMap);\r
137                                 Iterator<Entry<Object, Object>> iter = copyMap.entrySet().iterator();\r
138                                 putLength(out, length);\r
139                                 while (iter.hasNext()) {\r
140                                         Entry<Object, Object> e = iter.next();\r
141                                         Object key = e.getKey();\r
142                                         Object value = e.getValue();\r
143                                         keySerializer.serialize(out, identities, key);\r
144                                         valueSerializer.serialize(out, identities, value);                              \r
145                                 }\r
146                         }*/\r
147                 } catch (BindingException e) {\r
148                         throw new IOException( e ); \r
149                 }\r
150         }\r
151 \r
152         @Override\r
153         public Integer getConstantSize() {\r
154                 return null;\r
155         }\r
156 \r
157         @Override\r
158         public int getSize(Object obj, TObjectIntHashMap<Object> identities) throws IOException {\r
159                 try {\r
160                         int length = binding.size(obj);\r
161                         if (fixedSizeOfEntry!=null)\r
162                                 return 4 + fixedSizeOfEntry * length;\r
163                         int result = 4;\r
164                         Object keys[] = binding.getKeys(obj);\r
165                         for(int i=0;i<length;++i) {\r
166                                 Object key = keys[i];\r
167                                 Object value = binding.get(obj, key);\r
168                                 result += keySerializer.getSize(key, identities);\r
169                                 result += valueSerializer.getSize(value, identities);\r
170                         }\r
171                         return result;\r
172                 } catch (BindingException e) {\r
173                         throw new IOException( e ); \r
174                 }\r
175         }\r
176 \r
177         @Override\r
178         public int getMinSize() {\r
179                 return 4;\r
180         }\r
181         \r
182 }       \r