package org.simantics.databoard.serialization.impl; import gnu.trove.map.hash.TObjectIntHashMap; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.simantics.databoard.Bindings; import org.simantics.databoard.binding.Binding; import org.simantics.databoard.binding.VariantBinding; import org.simantics.databoard.binding.error.BindingException; import org.simantics.databoard.serialization.Serializer; import org.simantics.databoard.serialization.Serializer.RecursiveSerializer; import org.simantics.databoard.serialization.SerializerScheme; import org.simantics.databoard.type.Datatype; /** * Serializes Variant instances using bindings from Bindings.getBinding for * deserialization. These are assumed to be immutable bindings. * * @author Toni Kalajainen */ public class VariantSerializer extends RecursiveSerializer { VariantBinding binding; Serializer datatypeSerializer; SerializerScheme scheme; public VariantSerializer(VariantBinding binding, SerializerScheme scheme) { this.binding = binding; this.scheme = scheme; } @Override public void finalizeConstruction() { Binding dataTypeBinding = Bindings.getBindingUnchecked( Datatype.class ); this.datatypeSerializer = scheme.getSerializerUnchecked(dataTypeBinding); } @Override public Object deserialize(DataInput in, List identities) throws IOException { try { List typeIdentities = new ArrayList(1); Datatype type = (Datatype) datatypeSerializer.deserialize(in, typeIdentities); Binding valueBinding = Bindings.getBinding(type); Serializer valueSerializer = scheme.getSerializerUnchecked(valueBinding); assertRemainingBytes(in, valueSerializer.getMinSize()); Object value = valueSerializer.deserialize(in, identities); return binding.create(valueBinding, value); } catch (BindingException e) { throw new IOException( e ); } } @Override public void deserializeTo(DataInput in, List identities, Object obj) throws IOException { try { List typeIdentities = new ArrayList(1); Datatype type = (Datatype) datatypeSerializer.deserialize(in, typeIdentities); Datatype oldType = binding.getContentType(obj); if (type.equals(oldType)) { Binding valueBinding = binding.getContentBinding(obj); Serializer valueSerializer = scheme.getSerializerUnchecked(valueBinding); Object component = binding.getContent(obj); // assertRemainingBytes(in, valueSerializer.getMinSize()); component = valueSerializer.deserializeToTry(in, identities, component); binding.setContent(obj, valueBinding, component); } else { Binding valueBinding = Bindings.getBinding(type); Serializer valueSerializer = scheme.getSerializerUnchecked(valueBinding); // assertRemainingBytes(in, valueSerializer.getMinSize()); Object component = valueSerializer.deserialize(in, identities); binding.setContent(obj, valueBinding, component); } } catch (BindingException e) { throw new IOException( e ); } } @Override public void skip(DataInput in, List identities) throws IOException { List typeIdentities = new ArrayList(1); Datatype type = (Datatype) datatypeSerializer.deserialize(in, typeIdentities); Binding valueBinding = Bindings.getBinding(type); Serializer valueSerializer = scheme.getSerializerUnchecked(valueBinding); valueSerializer.skip(in, identities); } @Override public void serialize(DataOutput out, TObjectIntHashMap identities, Object variant) throws IOException { try { TObjectIntHashMap typeIdentities = new TObjectIntHashMap(1); Datatype type = binding.getContentType(variant); datatypeSerializer.serialize(out, typeIdentities, type); Binding valueBinding = binding.getContentBinding(variant); Object value = binding.getContent(variant, valueBinding); Serializer valueSerializer = scheme.getSerializerUnchecked(valueBinding); valueSerializer.serialize(out, identities, value); } catch (BindingException e) { throw new IOException( e ); } } @Override public Integer getConstantSize() { return null; } @Override public int getSize(Object variant, TObjectIntHashMap identities) throws IOException { try { TObjectIntHashMap typeIdentities = new TObjectIntHashMap(1); Datatype type = binding.getContentType(variant); int size = datatypeSerializer.getSize(type, typeIdentities); Binding valueBinding = binding.getContentBinding(variant); Object value = binding.getContent(variant, valueBinding); Serializer valueSerializer = scheme.getSerializerUnchecked(valueBinding); size += valueSerializer.getSize(value, identities); return size; } catch (BindingException e) { throw new IOException( e ); } } @Override public int getMinSize() { return datatypeSerializer.getMinSize(); } }