blob: 6fa2d3ecb8a57c765c1240fe39bd1c8735c2921c [file] [log] [blame]
package edu.uci.ics.asterix.builders;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import edu.uci.ics.asterix.dataflow.data.nontagged.serde.SerializerDeserializerUtil;
import edu.uci.ics.asterix.om.types.ATypeTag;
import edu.uci.ics.asterix.om.types.AbstractCollectionType;
import edu.uci.ics.asterix.om.util.NonTaggedFormatUtil;
import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
import edu.uci.ics.hyracks.data.std.api.IValueReference;
import edu.uci.ics.hyracks.data.std.util.GrowableArray;
import edu.uci.ics.hyracks.storage.am.common.ophelpers.IntArrayList;
public abstract class AbstractListBuilder implements IAsterixListBuilder {
protected static final byte serNullTypeTag = ATypeTag.NULL.serialize();
protected final GrowableArray outputStorage;
protected final DataOutputStream outputStream;
protected final IntArrayList offsets;
protected int metadataInfoSize;
protected byte[] offsetArray;
protected int offsetPosition;
protected int headerSize;
protected ATypeTag itemTypeTag;
protected final ATypeTag listType;
protected boolean fixedSize = false;
protected int numberOfItems;
public AbstractListBuilder(ATypeTag listType) {
this.outputStorage = new GrowableArray();
this.outputStream = (DataOutputStream) outputStorage.getDataOutput();
this.offsets = new IntArrayList(10, 10);
this.metadataInfoSize = 0;
this.offsetArray = null;
this.offsetPosition = 0;
this.listType = listType;
}
@Override
public void reset(AbstractCollectionType listType) {
this.outputStorage.reset();
this.offsetArray = null;
this.offsets.clear();
this.offsetPosition = 0;
this.numberOfItems = 0;
if (listType == null || listType.getItemType() == null) {
this.itemTypeTag = ATypeTag.ANY;
fixedSize = false;
} else {
this.itemTypeTag = listType.getItemType().getTypeTag();
fixedSize = NonTaggedFormatUtil.isFixedSizedCollection(listType.getItemType());
}
headerSize = 2;
metadataInfoSize = 8;
// 8 = 4 (# of items) + 4 (the size of the list)
}
@Override
public void addItem(IValueReference item) throws HyracksDataException {
try {
if (!fixedSize)
this.offsets.add((short) outputStorage.getLength());
if (itemTypeTag == ATypeTag.ANY
|| (itemTypeTag == ATypeTag.NULL && item.getByteArray()[0] == serNullTypeTag)) {
this.numberOfItems++;
this.outputStream.write(item.getByteArray(), item.getStartOffset(), item.getLength());
} else if (item.getByteArray()[0] != serNullTypeTag) {
this.numberOfItems++;
this.outputStream.write(item.getByteArray(), item.getStartOffset() + 1, item.getLength() - 1);
}
} catch (IOException e) {
throw new HyracksDataException(e);
}
}
@Override
public void write(DataOutput out, boolean writeTypeTag) throws HyracksDataException {
try {
if (!fixedSize)
metadataInfoSize += offsets.size() * 4;
if (offsetArray == null || offsetArray.length < metadataInfoSize)
offsetArray = new byte[metadataInfoSize];
SerializerDeserializerUtil.writeIntToByteArray(offsetArray,
headerSize + metadataInfoSize + outputStorage.getLength(), offsetPosition);
SerializerDeserializerUtil.writeIntToByteArray(offsetArray, this.numberOfItems, offsetPosition + 4);
if (!fixedSize) {
offsetPosition += 8;
for (int i = 0; i < offsets.size(); i++) {
SerializerDeserializerUtil.writeIntToByteArray(offsetArray, offsets.get(i) + metadataInfoSize
+ headerSize, offsetPosition);
offsetPosition += 4;
}
}
if (writeTypeTag) {
out.writeByte(listType.serialize());
}
out.writeByte(itemTypeTag.serialize());
out.write(offsetArray, 0, metadataInfoSize);
out.write(outputStorage.getByteArray(), 0, outputStorage.getLength());
} catch (IOException e) {
throw new HyracksDataException(e);
}
}
}