blob: 184a810535a5870a932b2a202c7e22e93e5e88ae [file] [log] [blame]
package edu.uci.ics.asterix.dataflow.data.nontagged.printers;
import java.io.PrintStream;
import edu.uci.ics.asterix.common.exceptions.AsterixException;
import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserializer;
import edu.uci.ics.asterix.formats.nontagged.AqlPrinterFactoryProvider;
import edu.uci.ics.asterix.om.types.ARecordType;
import edu.uci.ics.asterix.om.types.ATypeTag;
import edu.uci.ics.asterix.om.types.AUnionType;
import edu.uci.ics.asterix.om.types.EnumDeserializer;
import edu.uci.ics.asterix.om.types.IAType;
import edu.uci.ics.asterix.om.util.NonTaggedFormatUtil;
import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
import edu.uci.ics.hyracks.algebricks.data.IPrinter;
import edu.uci.ics.hyracks.algebricks.data.IPrinterFactory;
public class ARecordPrinterFactory implements IPrinterFactory {
private static final long serialVersionUID = 1L;
private final ARecordType recType;
public ARecordPrinterFactory(ARecordType recType) {
this.recType = recType;
}
@Override
public IPrinter createPrinter() {
return new IPrinter() {
private IPrinter[] fieldPrinters;
private IAType[] fieldTypes;
private int[] fieldOffsets;
private int numberOfSchemaFields, numberOfOpenFields, openPartOffset, fieldOffset, offsetArrayOffset,
fieldValueLength, nullBitMapOffset, recordOffset;
private boolean isExpanded, hasNullableFields;
private ATypeTag tag;
@Override
public void init() throws AlgebricksException {
numberOfSchemaFields = 0;
if (recType != null) {
numberOfSchemaFields = recType.getFieldNames().length;
fieldPrinters = new IPrinter[numberOfSchemaFields];
fieldTypes = new IAType[numberOfSchemaFields];
fieldOffsets = new int[numberOfSchemaFields];
for (int i = 0; i < numberOfSchemaFields; i++) {
fieldTypes[i] = recType.getFieldTypes()[i];
if (fieldTypes[i].getTypeTag() == ATypeTag.UNION
&& NonTaggedFormatUtil.isOptionalField((AUnionType) fieldTypes[i]))
fieldPrinters[i] = (AqlPrinterFactoryProvider.INSTANCE
.getPrinterFactory(((AUnionType) fieldTypes[i]).getUnionList().get(
NonTaggedFormatUtil.OPTIONAL_TYPE_INDEX_IN_UNION_LIST))).createPrinter();
else
fieldPrinters[i] = (AqlPrinterFactoryProvider.INSTANCE.getPrinterFactory(fieldTypes[i]))
.createPrinter();
fieldPrinters[i].init();
}
}
}
@Override
public void print(byte[] b, int start, int l, PrintStream ps) throws AlgebricksException {
ps.print("{ ");
isExpanded = false;
openPartOffset = 0;
int s = start;
recordOffset = s;
if (recType == null) {
openPartOffset = s + AInt32SerializerDeserializer.getInt(b, s + 6);
s += 8;
isExpanded = true;
} else {
if (recType.isOpen()) {
isExpanded = b[s + 5] == 1 ? true : false;
if (isExpanded) {
openPartOffset = s + AInt32SerializerDeserializer.getInt(b, s + 6);
s += 10;
} else
s += 6;
} else
s += 5;
}
try {
if (numberOfSchemaFields > 0) {
s += 4;
nullBitMapOffset = 0;
hasNullableFields = NonTaggedFormatUtil.hasNullableField(recType);
if (hasNullableFields) {
nullBitMapOffset = s;
offsetArrayOffset = s
+ (this.numberOfSchemaFields % 8 == 0 ? numberOfSchemaFields / 8
: numberOfSchemaFields / 8 + 1);
} else {
offsetArrayOffset = s;
}
for (int i = 0; i < numberOfSchemaFields; i++) {
fieldOffsets[i] = AInt32SerializerDeserializer.getInt(b, offsetArrayOffset) + recordOffset;
offsetArrayOffset += 4;
}
for (int fieldNumber = 0; fieldNumber < numberOfSchemaFields; fieldNumber++) {
if (fieldNumber != 0) {
ps.print(", ");
}
ps.print("\"");
ps.print(recType.getFieldNames()[fieldNumber]);
ps.print("\": ");
if (hasNullableFields) {
byte b1 = b[nullBitMapOffset + fieldNumber / 8];
int p = 1 << (7 - (fieldNumber % 8));
if ((b1 & p) == 0) {
ps.print("null");
continue;
}
}
if (fieldTypes[fieldNumber].getTypeTag() == ATypeTag.UNION) {
if (NonTaggedFormatUtil.isOptionalField((AUnionType) fieldTypes[fieldNumber])) {
tag = ((AUnionType) fieldTypes[fieldNumber]).getUnionList()
.get(NonTaggedFormatUtil.OPTIONAL_TYPE_INDEX_IN_UNION_LIST).getTypeTag();
fieldValueLength = NonTaggedFormatUtil.getFieldValueLength(b,
fieldOffsets[fieldNumber], tag, false);
fieldPrinters[fieldNumber].print(b, fieldOffsets[fieldNumber] - 1,
fieldOffsets[fieldNumber], ps);
}
} else {
tag = fieldTypes[fieldNumber].getTypeTag();
fieldValueLength = NonTaggedFormatUtil.getFieldValueLength(b,
fieldOffsets[fieldNumber], tag, false);
fieldPrinters[fieldNumber]
.print(b, fieldOffsets[fieldNumber] - 1, fieldValueLength, ps);
}
}
if (isExpanded)
ps.print(", ");
}
if (isExpanded) {
numberOfOpenFields = AInt32SerializerDeserializer.getInt(b, openPartOffset);
fieldOffset = openPartOffset + 4 + (8 * numberOfOpenFields);
for (int i = 0; i < numberOfOpenFields; i++) {
// we print the field name
fieldValueLength = NonTaggedFormatUtil.getFieldValueLength(b, fieldOffset, ATypeTag.STRING,
false);
AStringPrinter.INSTANCE.print(b, fieldOffset - 1, fieldValueLength, ps);
fieldOffset += fieldValueLength;
ps.print(": ");
// now we print the value
tag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(b[fieldOffset]);
fieldValueLength = NonTaggedFormatUtil.getFieldValueLength(b, fieldOffset, tag, true) + 1;
AObjectPrinter.INSTANCE.print(b, fieldOffset, fieldValueLength, ps);
fieldOffset += fieldValueLength;
if (i + 1 < numberOfOpenFields)
ps.print(", ");
}
}
} catch (AsterixException e) {
throw new AlgebricksException(e);
}
ps.print(" }");
}
};
}
}