| 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, |
| fieldValueLength, 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(" }"); |
| } |
| }; |
| } |
| } |