X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.databoard%2Fsrc%2Forg%2Fsimantics%2Fdataboard%2Fserialization%2Fimpl%2FOptionalSerializer.java;fp=bundles%2Forg.simantics.databoard%2Fsrc%2Forg%2Fsimantics%2Fdataboard%2Fserialization%2Fimpl%2FOptionalSerializer.java;h=ccf6e503e15f6f37192356239db3fef15032fe1b;hp=0000000000000000000000000000000000000000;hb=969bd23cab98a79ca9101af33334000879fb60c5;hpb=866dba5cd5a3929bbeae85991796acb212338a08 diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/serialization/impl/OptionalSerializer.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/serialization/impl/OptionalSerializer.java new file mode 100644 index 000000000..ccf6e503e --- /dev/null +++ b/bundles/org.simantics.databoard/src/org/simantics/databoard/serialization/impl/OptionalSerializer.java @@ -0,0 +1,129 @@ +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.List; + +import org.simantics.databoard.binding.OptionalBinding; +import org.simantics.databoard.binding.error.BindingException; +import org.simantics.databoard.binding.util.IsReferableQuery; +import org.simantics.databoard.binding.util.Result; +import org.simantics.databoard.serialization.SerializationException; +import org.simantics.databoard.serialization.Serializer; +import org.simantics.databoard.serialization.Serializer.CompositeSerializer; + +public class OptionalSerializer extends CompositeSerializer { + + OptionalBinding binding; + public Serializer componentSerializer; + boolean componentImmutable; + Integer fixedSize; + + /** + * Create optional serializer + * + * @param binding + * @param componentSerializer (optional), can be set after + */ + public OptionalSerializer(OptionalBinding binding, Serializer componentSerializer) { + super( IsReferableQuery.isReferable( binding.type() ) != Result.No ); + this.componentSerializer = componentSerializer; + this.binding = binding; + this.componentImmutable = binding.getComponentBinding().isImmutable(); + } + + @Override + public void finalizeConstruction() { + Integer fixedSizeOfComponent = componentSerializer.getConstantSize(); + if (fixedSizeOfComponent!=null && fixedSizeOfComponent==0) { + fixedSize = fixedSizeOfComponent + 1; + } + } + + @Override + public Object deserialize(DataInput in, List identities) throws IOException { + try { + byte x = in.readByte(); + if (x == 0) return binding.createNoValue(); + else if (x == 1) { + Object componentValue = componentSerializer.deserialize(in, identities); + return binding.createValue(componentValue); + } + else throw new SerializationException("Unexpected marker for option "+x+" 0 or 1 expected."); + } catch (BindingException e) { + throw new IOException( e ); + } + } + + @Override + public void deserializeTo(DataInput in, List identities, + Object obj) throws IOException { + try { + byte x = in.readByte(); + if (x == 0) { + if (binding.hasValue(obj)) binding.setNoValue(obj); + } else if (x == 1) { + if (componentImmutable) { + Object component = componentSerializer.deserialize(in, identities); + binding.setValue(obj, component); + } else { + Object component = binding.hasValue(obj) ? binding.getValue(obj) : binding.componentBinding.createDefault(); + component = componentSerializer.deserializeToTry(in, identities, component); + binding.setValue(obj, component); + } + + } + else throw new SerializationException("Unexpected marker for option "+x+" 0 or 1 expected."); + } catch (BindingException e) { + throw new IOException( e ); + } + } + + @Override + public void skip(DataInput in, List identities) throws IOException, SerializationException { + int x = in.readByte(); + if (x==1) componentSerializer.skip(in, identities); + } + + @Override + public void serialize(DataOutput out, TObjectIntHashMap identities, Object obj) throws IOException { + try { + if (!binding.hasValue(obj)) { + out.write((byte)0); + } else { + out.write((byte)1); + Object componentValue = binding.getValue(obj); + componentSerializer.serialize(out, identities, componentValue); + } + } catch (BindingException e) { + throw new IOException( e ); + } + + } + + @Override + public Integer getConstantSize() { + return fixedSize; + } + + @Override + public int getSize(Object obj, TObjectIntHashMap identities) throws IOException { + try { + if (fixedSize!=null) return fixedSize; + if (!binding.hasValue(obj)) return 1; + Object componentValue = binding.getValue(obj); + return 1 + componentSerializer.getSize(componentValue, identities); + } catch (BindingException e) { + throw new IOException( e ); + } + } + + @Override + public int getMinSize() { + return 1; + } + +}