1 package org.simantics.databoard.serialization.impl;
3 import gnu.trove.map.hash.TObjectIntHashMap;
5 import java.io.DataInput;
6 import java.io.DataOutput;
7 import java.io.IOException;
9 import java.util.TreeSet;
11 import org.simantics.databoard.binding.MapBinding;
12 import org.simantics.databoard.binding.error.BindingException;
13 import org.simantics.databoard.binding.util.IsReferableQuery;
14 import org.simantics.databoard.binding.util.Result;
15 import org.simantics.databoard.serialization.SerializationException;
16 import org.simantics.databoard.serialization.Serializer;
17 import org.simantics.databoard.serialization.Serializer.CompositeSerializer;
19 public class MapSerializer extends CompositeSerializer {
21 Integer fixedSizeOfKey, fixedSizeOfValue, fixedSizeOfEntry;
22 public Serializer keySerializer, valueSerializer;
28 * @param keySerializer (optional) can be set later
29 * @param valueSerializer (optional) can be set later
31 public MapSerializer(MapBinding binding, Serializer keySerializer, Serializer valueSerializer) {
32 super( IsReferableQuery.isReferable( binding.type() ) != Result.No );
33 this.keySerializer = keySerializer;
34 this.valueSerializer = valueSerializer;
35 this.binding = binding;
40 public void finalizeConstruction() {
41 fixedSizeOfKey = keySerializer.getConstantSize();
42 fixedSizeOfValue = valueSerializer.getConstantSize();
43 fixedSizeOfEntry = (fixedSizeOfKey!=null && fixedSizeOfValue!=null) ? (fixedSizeOfKey+fixedSizeOfValue) : null;
47 public Object deserialize(DataInput in, List<Object> identities) throws IOException{
49 int length = in.readInt();
50 if (length<0) throw new SerializationException("Cannot use negative array length");
51 assertRemainingBytes(in, (long)length*((long)keySerializer.getMinSize()+(long)valueSerializer.getMinSize()));
53 Object keys[] = new Object[length];
54 Object values[] = new Object[length];
56 for(int i=0;i<length;++i) {
57 keys[i] = keySerializer.deserialize(in, identities);
58 values[i] = valueSerializer.deserialize(in, identities);
60 return binding.create(keys, values);
61 } catch (BindingException e) {
62 throw new IOException( e );
67 public void deserializeTo(DataInput in, List<Object> identities, Object obj) throws IOException {
69 TreeSet<Object> oldKeys = new TreeSet<Object>( binding.getKeyBinding() );
70 binding.getKeys(obj, oldKeys);
72 int length = in.readInt();
73 if (length<0) throw new SerializationException("Cannot use negative array length");
74 assertRemainingBytes(in, (long)length*((long)keySerializer.getMinSize()+(long)valueSerializer.getMinSize()));
76 for(int i=0;i<length;++i) {
77 Object key = keySerializer.deserialize(in, identities);
78 Object value = valueSerializer.deserialize(in, identities);
79 binding.put(obj, key, value);
84 for (Object key : oldKeys)
85 binding.remove(obj, key);
86 } catch (BindingException e) {
87 throw new IOException( e );
93 public void skip(DataInput in, List<Object> identities)
94 throws IOException, SerializationException {
95 int length = in.readInt();
96 if (fixedSizeOfEntry!=null) {
97 in.skipBytes( length * fixedSizeOfEntry );
100 for(int i=0;i<length;++i) {
101 if (fixedSizeOfKey!=null) {
102 in.skipBytes(fixedSizeOfKey);
104 keySerializer.skip(in, identities);
107 if (fixedSizeOfValue!=null) {
108 in.skipBytes(fixedSizeOfValue);
110 valueSerializer.skip(in, identities);
116 public void serialize(DataOutput out, TObjectIntHashMap<Object> identities, Object map) throws IOException {
118 int length = binding.size(map);
119 //if (binding.isOrderedMap(map))
121 Object[] keys = new Object[length];
122 Object[] values = new Object[length];
123 binding.getAll(map, keys, values);
124 out.writeInt(length);
125 for(int i=0;i<length;++i) {
126 Object key = keys[i];
127 Object value = values[i];
128 keySerializer.serialize(out, identities, key);
129 valueSerializer.serialize(out, identities, value);
134 // Sort keys by putting into a treemap
135 TreeMap<Object, Object> copyMap = new TreeMap<Object, Object>(binding.getKeyBinding());
136 binding.getAll(map, copyMap);
137 Iterator<Entry<Object, Object>> iter = copyMap.entrySet().iterator();
138 putLength(out, length);
139 while (iter.hasNext()) {
140 Entry<Object, Object> e = iter.next();
141 Object key = e.getKey();
142 Object value = e.getValue();
143 keySerializer.serialize(out, identities, key);
144 valueSerializer.serialize(out, identities, value);
147 } catch (BindingException e) {
148 throw new IOException( e );
153 public Integer getConstantSize() {
158 public int getSize(Object obj, TObjectIntHashMap<Object> identities) throws IOException {
160 int length = binding.size(obj);
161 if (fixedSizeOfEntry!=null)
162 return 4 + fixedSizeOfEntry * length;
164 Object keys[] = binding.getKeys(obj);
165 for(int i=0;i<length;++i) {
166 Object key = keys[i];
167 Object value = binding.get(obj, key);
168 result += keySerializer.getSize(key, identities);
169 result += valueSerializer.getSize(value, identities);
172 } catch (BindingException e) {
173 throw new IOException( e );
178 public int getMinSize() {