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.Iterator; import java.util.List; import org.simantics.databoard.binding.ArrayBinding; import org.simantics.databoard.binding.Binding; import org.simantics.databoard.binding.error.BindingException; import org.simantics.databoard.binding.impl.ArrayListBinding; 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; import org.simantics.databoard.type.ArrayType; import org.simantics.databoard.util.Range; public class ArraySerializer extends CompositeSerializer { Range length; Integer fixedLength; Integer fixedSize; Integer fixedSizeOfComponent; public Serializer componentSerializer; boolean componentImmutable; ArrayBinding binding; DefaultValueIterator componentValueItr; /** * * @param binding * @param componentSerializer (optional) can be set after */ public ArraySerializer(ArrayBinding binding, Serializer componentSerializer) { super( IsReferableQuery.isReferable( binding.type() ) != Result.No ); ArrayType arrayType = (ArrayType) binding.type(); this.componentSerializer = componentSerializer; this.binding = binding; this.length = arrayType.getLength(); this.componentImmutable = binding.getComponentBinding().isImmutable(); this.componentValueItr = new DefaultValueIterator(); componentValueItr.binding = binding.componentBinding; } @Override public void finalizeConstruction() { fixedSizeOfComponent = componentSerializer.getConstantSize(); if (fixedSizeOfComponent!=null && length!=null && length.getLower().equals(length.getUpper()) && length.getLower().getValue()!=null) { fixedLength = length.getLower().getValue().intValue(); fixedSize = fixedLength * fixedSizeOfComponent; } } @Override public Object deserialize(DataInput in, List identities) throws IOException { try { int length = fixedLength != null ? fixedLength : in.readInt(); if (length<0) throw new SerializationException("Cannot use negative array length"); assertRemainingBytes(in, ((long)length)*componentSerializer.getMinSize()); ArrayList temp = new ArrayList(length); for(int i=0;i identities, Object obj) throws IOException { try { int length = fixedLength != null ? fixedLength : in.readInt(); if (length<0) throw new SerializationException("Cannot use negative array length"); assertRemainingBytes(in, ((long)length)*componentSerializer.getMinSize()); int oldLen = binding.size(obj); if (oldLen!=length) { if ( binding.isResizable() ) { binding.setSize(obj, length); } else { obj = binding.create(length, componentValueItr); oldLen = length; } } if ( componentImmutable ) { for(int i=0;ilength) binding.setSize(obj, length); } return obj; } catch (BindingException e) { throw new IOException( e ); } } @Override public void deserializeTo(DataInput in, List identities, Object obj) throws IOException { try { int length = fixedLength != null ? fixedLength : in.readInt(); if (length<0) throw new SerializationException("Cannot use negative array length"); assertRemainingBytes(in, ((long)length)*componentSerializer.getMinSize()); int oldLen = binding.size(obj); if (oldLen!=length) { if ( binding.isResizable() ) { binding.setSize(obj, length); } else { throw new IOException("Cannot resize array"); } } if ( componentImmutable ) { for(int i=0;ilength) binding.setSize(obj, length); } } catch (BindingException e) { throw new IOException( e ); } } @Override public void skip(DataInput in, List identities) throws IOException { if (fixedSize!=null) { in.skipBytes(fixedSize); return; } int length = fixedLength != null ? fixedLength : in.readInt(); if (fixedSizeOfComponent!=null) { // Skip all elements in.skipBytes(length * fixedSizeOfComponent); } else { // Skip each element individualy for(int i=0;i identities, Object obj) throws IOException { try { int length = binding.size(obj); if (fixedLength==null) { out.writeInt(length); } else { if (length!=fixedLength) throw new SerializationException("Unexpected array length "+length+", size is restricted to "+fixedLength); } // Serialize elements for(int i=0;i identities) throws IOException { try { if (fixedSize!=null) return fixedSize; int length = binding.size(obj); if (fixedSizeOfComponent!=null) return 4 + fixedSizeOfComponent * length; int result = 4; for(int i=0;i { Binding binding; @Override public boolean hasNext() { return true; } @Override public Object next() { try { return binding.createDefault(); } catch (BindingException e) { return null; } } @Override public void remove() { } }