code review: print visitor for issue 29,55,134,166,201,205,208
git-svn-id: https://asterixdb.googlecode.com/svn/branches/asterix_stabilization_printerfix_staging@969 eaa15691-b419-025a-1212-ee371bd00084
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ABooleanPrinter.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ABooleanPrinter.java
index 60ee1fe..33866df 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ABooleanPrinter.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ABooleanPrinter.java
@@ -8,7 +8,6 @@
public class ABooleanPrinter implements IPrinter {
- private static final long serialVersionUID = 1L;
public static final ABooleanPrinter INSTANCE = new ABooleanPrinter();
@Override
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ACirclePrinter.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ACirclePrinter.java
index 812d93b..e2da96e 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ACirclePrinter.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ACirclePrinter.java
@@ -8,7 +8,6 @@
public class ACirclePrinter implements IPrinter {
- private static final long serialVersionUID = 1L;
public static final ACirclePrinter INSTANCE = new ACirclePrinter();
@Override
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ADatePrinter.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ADatePrinter.java
index 24aa144..918e286 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ADatePrinter.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ADatePrinter.java
@@ -9,11 +9,10 @@
public class ADatePrinter implements IPrinter {
- private static final long serialVersionUID = 1L;
private static long CHRONON_OF_DAY = 24 * 60 * 60 * 1000;
public static final ADatePrinter INSTANCE = new ADatePrinter();
private static final GregorianCalendarSystem gCalInstance = GregorianCalendarSystem.getInstance();
-
+
@Override
public void init() {
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ADateTimePrinter.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ADateTimePrinter.java
index d856a20..96df767 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ADateTimePrinter.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ADateTimePrinter.java
@@ -9,7 +9,6 @@
public class ADateTimePrinter implements IPrinter {
- private static final long serialVersionUID = 1L;
public static final ADateTimePrinter INSTANCE = new ADateTimePrinter();
private static final GregorianCalendarSystem gCalInstance = GregorianCalendarSystem.getInstance();
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ADoublePrinter.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ADoublePrinter.java
index 3a255c6..ae50d0e 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ADoublePrinter.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ADoublePrinter.java
@@ -8,7 +8,6 @@
public class ADoublePrinter implements IPrinter {
- private static final long serialVersionUID = 1L;
public static final ADoublePrinter INSTANCE = new ADoublePrinter();
@Override
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ADurationPrinter.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ADurationPrinter.java
index a59b9ac..061d372 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ADurationPrinter.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ADurationPrinter.java
@@ -12,7 +12,6 @@
public class ADurationPrinter implements IPrinter {
- private static final long serialVersionUID = 1L;
public static final ADurationPrinter INSTANCE = new ADurationPrinter();
private static final GregorianCalendarSystem gCalInstance = GregorianCalendarSystem.getInstance();
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AFloatPrinter.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AFloatPrinter.java
index 27d2e2c..96c9ee9 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AFloatPrinter.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AFloatPrinter.java
@@ -8,7 +8,6 @@
public class AFloatPrinter implements IPrinter {
- private static final long serialVersionUID = 1L;
public static final AFloatPrinter INSTANCE = new AFloatPrinter();
@Override
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AInt16Printer.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AInt16Printer.java
index 8961013..1687fb1 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AInt16Printer.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AInt16Printer.java
@@ -13,8 +13,6 @@
public class AInt16Printer implements IPrinter {
- private static final long serialVersionUID = 1L;
-
private static final String SUFFIX_STRING = "i16";
private static byte[] _suffix;
private static int _suffix_count;
@@ -23,6 +21,7 @@
DataOutput dout = new DataOutputStream(interm);
try {
dout.writeUTF(SUFFIX_STRING);
+ interm.close();
} catch (IOException e) {
e.printStackTrace();
}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AInt32Printer.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AInt32Printer.java
index a5c3245..b20db34 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AInt32Printer.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AInt32Printer.java
@@ -10,7 +10,6 @@
public class AInt32Printer implements IPrinter {
- private static final long serialVersionUID = 1L;
public static final AInt32Printer INSTANCE = new AInt32Printer();
@Override
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AInt64Printer.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AInt64Printer.java
index 318828e..312802a 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AInt64Printer.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AInt64Printer.java
@@ -13,8 +13,6 @@
public class AInt64Printer implements IPrinter {
- private static final long serialVersionUID = 1L;
-
private static final String SUFFIX_STRING = "i64";
private static byte[] _suffix;
private static int _suffix_count;
@@ -23,6 +21,7 @@
DataOutput dout = new DataOutputStream(interm);
try {
dout.writeUTF(SUFFIX_STRING);
+ interm.close();
} catch (IOException e) {
e.printStackTrace();
}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AInt8Printer.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AInt8Printer.java
index bd4139d..a5a421d 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AInt8Printer.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AInt8Printer.java
@@ -13,8 +13,6 @@
public class AInt8Printer implements IPrinter {
- private static final long serialVersionUID = 1L;
-
private static final String SUFFIX_STRING = "i8";
private static byte[] _suffix;
private static int _suffix_count;
@@ -23,6 +21,7 @@
DataOutput dout = new DataOutputStream(interm);
try {
dout.writeUTF(SUFFIX_STRING);
+ interm.close();
} catch (IOException e) {
e.printStackTrace();
}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ALinePrinter.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ALinePrinter.java
index f99727a..40f405c 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ALinePrinter.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ALinePrinter.java
@@ -8,7 +8,6 @@
public class ALinePrinter implements IPrinter {
- private static final long serialVersionUID = 1L;
public static final ALinePrinter INSTANCE = new ALinePrinter();
@Override
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ANullPrinter.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ANullPrinter.java
index 6abc0e1..daea967 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ANullPrinter.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ANullPrinter.java
@@ -5,11 +5,8 @@
import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
import edu.uci.ics.hyracks.algebricks.data.IPrinter;
-
-
public class ANullPrinter implements IPrinter {
- private static final long serialVersionUID = 1L;
public static final ANullPrinter INSTANCE = new ANullPrinter();
@Override
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AObjectPrinter.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AObjectPrinter.java
index aff30f7..edcfc8a 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AObjectPrinter.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AObjectPrinter.java
@@ -10,7 +10,6 @@
public class AObjectPrinter implements IPrinter {
- private static final long serialVersionUID = 1L;
public static final AObjectPrinter INSTANCE = new AObjectPrinter();
private IPrinter recordPrinter = new ARecordPrinterFactory(null).createPrinter();
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AOrderedlistPrinterFactory.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AOrderedlistPrinterFactory.java
index 563b14c..7d04ebc 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AOrderedlistPrinterFactory.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AOrderedlistPrinterFactory.java
@@ -2,22 +2,21 @@
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.pointables.PointableAllocator;
+import edu.uci.ics.asterix.om.pointables.base.DefaultOpenFieldType;
+import edu.uci.ics.asterix.om.pointables.base.IVisitablePointable;
+import edu.uci.ics.asterix.om.pointables.printer.APrintVisitor;
import edu.uci.ics.asterix.om.types.AOrderedListType;
import edu.uci.ics.asterix.om.types.ATypeTag;
-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.common.utils.Pair;
import edu.uci.ics.hyracks.algebricks.data.IPrinter;
import edu.uci.ics.hyracks.algebricks.data.IPrinterFactory;
public class AOrderedlistPrinterFactory implements IPrinterFactory {
private static final long serialVersionUID = 1L;
-
private AOrderedListType orderedlistType;
public AOrderedlistPrinterFactory(AOrderedListType orderedlistType) {
@@ -27,77 +26,29 @@
@Override
public IPrinter createPrinter() {
- return new IPrinter() {
+ PointableAllocator allocator = new PointableAllocator();
+ final IAType inputType = orderedlistType == null ? DefaultOpenFieldType
+ .getDefaultOpenFieldType(ATypeTag.ORDEREDLIST) : orderedlistType;
+ final IVisitablePointable listAccessor = allocator.allocateListValue(inputType);
+ final APrintVisitor printVisitor = new APrintVisitor();
+ final Pair<PrintStream, ATypeTag> arg = new Pair<PrintStream, ATypeTag>(null, null);
- private IPrinter itemPrinter;
- private IAType itemType;
- private ATypeTag itemTag;
- private boolean typedItemList = false;
+ return new IPrinter() {
@Override
public void init() throws AlgebricksException {
-
- if (orderedlistType != null && orderedlistType.getItemType() != null) {
- itemType = orderedlistType.getItemType();
- if (itemType.getTypeTag() == ATypeTag.ANY) {
- this.typedItemList = false;
- this.itemPrinter = AObjectPrinterFactory.INSTANCE.createPrinter();
- } else {
- this.typedItemList = true;
- itemPrinter = AqlPrinterFactoryProvider.INSTANCE.getPrinterFactory(itemType).createPrinter();
- itemTag = orderedlistType.getItemType().getTypeTag();
- }
- } else {
- this.typedItemList = false;
- this.itemPrinter = AObjectPrinterFactory.INSTANCE.createPrinter();
- }
- itemPrinter.init();
-
+ arg.second = inputType.getTypeTag();
}
@Override
- public void print(byte[] b, int s, int l, PrintStream ps) throws AlgebricksException {
- ps.print("[ ");
- int numberOfitems = AInt32SerializerDeserializer.getInt(b, s + 6);
- int itemOffset;
- if (typedItemList) {
- switch (itemTag) {
- case STRING:
- case RECORD:
- case ORDEREDLIST:
- case UNORDEREDLIST:
- case ANY:
- itemOffset = s + 10 + (numberOfitems * 4);
- break;
- default:
- itemOffset = s + 10;
- }
- } else
- itemOffset = s + 10 + (numberOfitems * 4);
- int itemLength = 0;
+ public void print(byte[] b, int start, int l, PrintStream ps) throws AlgebricksException {
try {
- if (typedItemList) {
- for (int i = 0; i < numberOfitems; i++) {
- itemLength = NonTaggedFormatUtil.getFieldValueLength(b, itemOffset, itemTag, false);
- itemPrinter.print(b, itemOffset - 1, itemLength, ps);
- itemOffset += itemLength;
- if (i + 1 < numberOfitems)
- ps.print(", ");
- }
- } else {
- for (int i = 0; i < numberOfitems; i++) {
- itemTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(b[itemOffset]);
- itemLength = NonTaggedFormatUtil.getFieldValueLength(b, itemOffset, itemTag, true) + 1;
- itemPrinter.print(b, itemOffset, itemLength, ps);
- itemOffset += itemLength;
- if (i + 1 < numberOfitems)
- ps.print(", ");
- }
- }
- } catch (AsterixException e) {
- throw new AlgebricksException(e);
+ listAccessor.set(b, start, l);
+ arg.first = ps;
+ listAccessor.accept(printVisitor, arg);
+ } catch (Exception ioe) {
+ throw new AlgebricksException(ioe);
}
- ps.print(" ]");
}
};
}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/APoint3DPrinter.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/APoint3DPrinter.java
index 699cb77..7394dc5 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/APoint3DPrinter.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/APoint3DPrinter.java
@@ -8,7 +8,6 @@
public class APoint3DPrinter implements IPrinter {
- private static final long serialVersionUID = 1L;
public static final APoint3DPrinter INSTANCE = new APoint3DPrinter();
@Override
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/APointPrinter.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/APointPrinter.java
index 50fbb0b..7c50905 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/APointPrinter.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/APointPrinter.java
@@ -8,7 +8,6 @@
public class APointPrinter implements IPrinter {
- private static final long serialVersionUID = 1L;
public static final APointPrinter INSTANCE = new APointPrinter();
@Override
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/APolygonPrinter.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/APolygonPrinter.java
index 794dae7..bc1e553 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/APolygonPrinter.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/APolygonPrinter.java
@@ -9,7 +9,6 @@
public class APolygonPrinter implements IPrinter {
- private static final long serialVersionUID = 1L;
public static final APolygonPrinter INSTANCE = new APolygonPrinter();
@Override
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ARecordPrinterFactory.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ARecordPrinterFactory.java
index fafe320..e4b2676 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ARecordPrinterFactory.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ARecordPrinterFactory.java
@@ -2,23 +2,21 @@
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.pointables.PointableAllocator;
+import edu.uci.ics.asterix.om.pointables.base.DefaultOpenFieldType;
+import edu.uci.ics.asterix.om.pointables.base.IVisitablePointable;
+import edu.uci.ics.asterix.om.pointables.printer.APrintVisitor;
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.common.utils.Pair;
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) {
@@ -28,137 +26,29 @@
@Override
public IPrinter createPrinter() {
- return new IPrinter() {
+ PointableAllocator allocator = new PointableAllocator();
+ final IAType inputType = recType == null ? DefaultOpenFieldType.getDefaultOpenFieldType(ATypeTag.RECORD)
+ : recType;
+ final IVisitablePointable recAccessor = allocator.allocateRecordValue(inputType);
+ final APrintVisitor printVisitor = new APrintVisitor();
+ final Pair<PrintStream, ATypeTag> arg = new Pair<PrintStream, ATypeTag>(null, null);
- 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;
+ return new IPrinter() {
@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();
- }
- }
+ arg.second = inputType.getTypeTag();
}
@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);
+ recAccessor.set(b, start, l);
+ arg.first = ps;
+ recAccessor.accept(printVisitor, arg);
+ } catch (Exception ioe) {
+ throw new AlgebricksException(ioe);
}
- ps.print(" }");
}
};
}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ARectanglePrinter.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ARectanglePrinter.java
index 17caa53..0618f28 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ARectanglePrinter.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ARectanglePrinter.java
@@ -8,7 +8,6 @@
public class ARectanglePrinter implements IPrinter {
- private static final long serialVersionUID = 1L;
public static final ARectanglePrinter INSTANCE = new ARectanglePrinter();
@Override
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AStringPrinter.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AStringPrinter.java
index 6f5b629..d491777 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AStringPrinter.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AStringPrinter.java
@@ -9,7 +9,6 @@
public class AStringPrinter implements IPrinter {
- private static final long serialVersionUID = 1L;
public static final AStringPrinter INSTANCE = new AStringPrinter();
@Override
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ATimePrinter.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ATimePrinter.java
index 72a6e37..b77ee64 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ATimePrinter.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ATimePrinter.java
@@ -9,10 +9,9 @@
public class ATimePrinter implements IPrinter {
- private static final long serialVersionUID = 1L;
public static final ATimePrinter INSTANCE = new ATimePrinter();
private static final GregorianCalendarSystem gCalInstance = GregorianCalendarSystem.getInstance();
-
+
@Override
public void init() {
@@ -21,7 +20,7 @@
@Override
public void print(byte[] b, int s, int l, PrintStream ps) throws AlgebricksException {
int time = AInt32SerializerDeserializer.getInt(b, s + 1);
-
+
ps.print("time(\"");
ps.append(String.format("%02d", gCalInstance.getHourOfDay(time))).append(":")
.append(String.format("%02d", gCalInstance.getMinOfHour(time))).append(":")
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AUnorderedlistPrinterFactory.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AUnorderedlistPrinterFactory.java
index 59af365..f779919 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AUnorderedlistPrinterFactory.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/AUnorderedlistPrinterFactory.java
@@ -2,22 +2,21 @@
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.pointables.PointableAllocator;
+import edu.uci.ics.asterix.om.pointables.base.DefaultOpenFieldType;
+import edu.uci.ics.asterix.om.pointables.base.IVisitablePointable;
+import edu.uci.ics.asterix.om.pointables.printer.APrintVisitor;
import edu.uci.ics.asterix.om.types.ATypeTag;
import edu.uci.ics.asterix.om.types.AUnorderedListType;
-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.common.utils.Pair;
import edu.uci.ics.hyracks.algebricks.data.IPrinter;
import edu.uci.ics.hyracks.algebricks.data.IPrinterFactory;
public class AUnorderedlistPrinterFactory implements IPrinterFactory {
private static final long serialVersionUID = 1L;
-
private AUnorderedListType unorderedlistType;
public AUnorderedlistPrinterFactory(AUnorderedListType unorderedlistType) {
@@ -27,77 +26,29 @@
@Override
public IPrinter createPrinter() {
- return new IPrinter() {
+ PointableAllocator allocator = new PointableAllocator();
+ final IAType inputType = unorderedlistType == null ? DefaultOpenFieldType
+ .getDefaultOpenFieldType(ATypeTag.UNORDEREDLIST) : unorderedlistType;
+ final IVisitablePointable listAccessor = allocator.allocateListValue(inputType);
+ final APrintVisitor printVisitor = new APrintVisitor();
+ final Pair<PrintStream, ATypeTag> arg = new Pair<PrintStream, ATypeTag>(null, null);
- private IPrinter itemPrinter;
- private IAType itemType;
- private ATypeTag itemTag;
- private boolean typedItemList = false;
+ return new IPrinter() {
@Override
public void init() throws AlgebricksException {
-
- if (unorderedlistType != null && unorderedlistType.getItemType() != null) {
- itemType = unorderedlistType.getItemType();
- if (itemType.getTypeTag() == ATypeTag.ANY) {
- this.typedItemList = false;
- this.itemPrinter = AObjectPrinterFactory.INSTANCE.createPrinter();
- } else {
- this.typedItemList = true;
- itemPrinter = AqlPrinterFactoryProvider.INSTANCE.getPrinterFactory(itemType).createPrinter();
- itemTag = unorderedlistType.getItemType().getTypeTag();
- }
- } else {
- this.typedItemList = false;
- this.itemPrinter = AObjectPrinterFactory.INSTANCE.createPrinter();
- }
- itemPrinter.init();
+ arg.second = inputType.getTypeTag();
}
@Override
- public void print(byte[] b, int s, int l, PrintStream ps) throws AlgebricksException {
- ps.print("{{ ");
- int numberOfitems = AInt32SerializerDeserializer.getInt(b, s + 6);
- int itemOffset;
- if (typedItemList) {
- switch (itemTag) {
- case STRING:
- case RECORD:
- case ORDEREDLIST:
- case UNORDEREDLIST:
- case ANY:
- itemOffset = s + 10 + (numberOfitems * 4);
- break;
- default:
- itemOffset = s + 10;
- }
- } else
- itemOffset = s + 10 + (numberOfitems * 4);
- int itemLength;
-
+ public void print(byte[] b, int start, int l, PrintStream ps) throws AlgebricksException {
try {
- if (typedItemList) {
- for (int i = 0; i < numberOfitems; i++) {
- itemLength = NonTaggedFormatUtil.getFieldValueLength(b, itemOffset, itemTag, false);
- itemPrinter.print(b, itemOffset - 1, itemLength, ps);
- itemOffset += itemLength;
- if (i + 1 < numberOfitems)
- ps.print(", ");
- }
- } else {
- for (int i = 0; i < numberOfitems; i++) {
- itemTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(b[itemOffset]);
- itemLength = NonTaggedFormatUtil.getFieldValueLength(b, itemOffset, itemTag, true) + 1;
- itemPrinter.print(b, itemOffset, itemLength, ps);
- itemOffset += itemLength;
- if (i + 1 < numberOfitems)
- ps.print(", ");
- }
- }
- } catch (AsterixException e) {
- throw new AlgebricksException(e);
+ listAccessor.set(b, start, l);
+ arg.first = ps;
+ listAccessor.accept(printVisitor, arg);
+ } catch (Exception ioe) {
+ throw new AlgebricksException(ioe);
}
- ps.print(" }}");
}
};
}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/serde/AOrderedListSerializerDeserializer.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/serde/AOrderedListSerializerDeserializer.java
index c68f82a..d37a4ea 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/serde/AOrderedListSerializerDeserializer.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/serde/AOrderedListSerializerDeserializer.java
@@ -26,9 +26,9 @@
public static final AOrderedListSerializerDeserializer SCHEMALESS_INSTANCE = new AOrderedListSerializerDeserializer();
private IAType itemType;
- @SuppressWarnings("unchecked")
+ @SuppressWarnings("rawtypes")
private ISerializerDeserializer serializer;
- @SuppressWarnings("unchecked")
+ @SuppressWarnings("rawtypes")
private ISerializerDeserializer deserializer;
private AOrderedListType orderedlistType;
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/formats/nontagged/AqlSerializerDeserializerProvider.java b/asterix-om/src/main/java/edu/uci/ics/asterix/formats/nontagged/AqlSerializerDeserializerProvider.java
index d4d4fb6..5492c5c 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/formats/nontagged/AqlSerializerDeserializerProvider.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/formats/nontagged/AqlSerializerDeserializerProvider.java
@@ -48,7 +48,7 @@
private AqlSerializerDeserializerProvider() {
}
- @SuppressWarnings("unchecked")
+ @SuppressWarnings("rawtypes")
@Override
public ISerializerDeserializer getSerializerDeserializer(Object typeInfo) {
IAType aqlType = (IAType) typeInfo;
@@ -63,7 +63,7 @@
}
}
- @SuppressWarnings("unchecked")
+ @SuppressWarnings("rawtypes")
public ISerializerDeserializer getNonTaggedSerializerDeserializer(IAType aqlType) {
switch (aqlType.getTypeTag()) {
case CIRCLE: {
@@ -139,7 +139,7 @@
}
}
- @SuppressWarnings("unchecked")
+ @SuppressWarnings("rawtypes")
private ISerializerDeserializer addTag(final ISerializerDeserializer nonTaggedSerde, final ATypeTag typeTag) {
return new ISerializerDeserializer<IAObject>() {
@@ -148,13 +148,15 @@
@Override
public IAObject deserialize(DataInput in) throws HyracksDataException {
try {
- ATypeTag typeTag = SerializerDeserializerUtil.deserializeTag(in);
+ //deserialize the tag to move the input cursor forward
+ SerializerDeserializerUtil.deserializeTag(in);
} catch (IOException e) {
throw new HyracksDataException(e);
}
return (IAObject) nonTaggedSerde.deserialize(in);
}
+ @SuppressWarnings("unchecked")
@Override
public void serialize(IAObject instance, DataOutput out) throws HyracksDataException {
SerializerDeserializerUtil.serializeTag(instance, out);
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/AFlatValuePointable.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/AFlatValuePointable.java
new file mode 100644
index 0000000..445e2a2
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/AFlatValuePointable.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2009-2010 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.uci.ics.asterix.om.pointables;
+
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.om.pointables.base.IVisitablePointable;
+import edu.uci.ics.asterix.om.pointables.visitor.IVisitablePointableVisitor;
+import edu.uci.ics.asterix.om.types.IAType;
+import edu.uci.ics.asterix.om.util.container.IObjectFactory;
+import edu.uci.ics.hyracks.data.std.api.IValueReference;
+
+/**
+ * This class represents a flat field, e.g., int field, string field, and
+ * so on, based on a binary representation.
+ */
+public class AFlatValuePointable extends AbstractVisitablePointable {
+
+ /**
+ * DO NOT allow to create AFlatValuePointable object arbitrarily, force to
+ * use object pool based allocator. The factory is not public so that it
+ * cannot called in other places than PointableAllocator.
+ */
+ static IObjectFactory<IVisitablePointable, IAType> FACTORY = new IObjectFactory<IVisitablePointable, IAType>() {
+ public AFlatValuePointable create(IAType type) {
+ return new AFlatValuePointable();
+ }
+ };
+
+ /**
+ * private constructor, to prevent arbitrary creation
+ */
+ private AFlatValuePointable() {
+
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof IValueReference))
+ return false;
+
+ // get right raw data
+ IValueReference ivf = (IValueReference) o;
+ byte[] odata = ivf.getByteArray();
+ int ostart = ivf.getStartOffset();
+ int olen = ivf.getLength();
+
+ // get left raw data
+ byte[] data = getByteArray();
+ int start = getStartOffset();
+ int len = getLength();
+
+ // bytes length should be equal
+ if (len != olen)
+ return false;
+
+ // check each byte
+ for (int i = 0; i < len; i++) {
+ if (data[start + i] != odata[ostart + i])
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public <R, T> R accept(IVisitablePointableVisitor<R, T> vistor, T tag) throws AsterixException {
+ return vistor.visit(this, tag);
+ }
+}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/AListPointable.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/AListPointable.java
new file mode 100644
index 0000000..ab32b6b
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/AListPointable.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2009-2010 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.uci.ics.asterix.om.pointables;
+
+import java.io.DataOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserializer;
+import edu.uci.ics.asterix.om.pointables.base.IVisitablePointable;
+import edu.uci.ics.asterix.om.pointables.visitor.IVisitablePointableVisitor;
+import edu.uci.ics.asterix.om.types.AOrderedListType;
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.AbstractCollectionType;
+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.asterix.om.util.ResettableByteArrayOutputStream;
+import edu.uci.ics.asterix.om.util.container.IObjectFactory;
+
+/**
+ * This class interprets the binary data representation of a list, one can
+ * call getItems and getItemTags to get pointable objects for items and item
+ * type tags.
+ */
+public class AListPointable extends AbstractVisitablePointable {
+
+ /**
+ * DO NOT allow to create AListPointable object arbitrarily, force to use
+ * object pool based allocator, in order to have object reuse.
+ */
+ static IObjectFactory<IVisitablePointable, IAType> FACTORY = new IObjectFactory<IVisitablePointable, IAType>() {
+ public IVisitablePointable create(IAType type) {
+ return new AListPointable((AbstractCollectionType) type);
+ }
+ };
+
+ private final List<IVisitablePointable> items = new ArrayList<IVisitablePointable>();
+ private final List<IVisitablePointable> itemTags = new ArrayList<IVisitablePointable>();
+ private final PointableAllocator allocator = new PointableAllocator();
+
+ private final ResettableByteArrayOutputStream dataBos = new ResettableByteArrayOutputStream();
+ private final DataOutputStream dataDos = new DataOutputStream(dataBos);
+
+ private IAType itemType;
+ private ATypeTag itemTag;
+ private boolean typedItemList = false;
+ private boolean ordered = false;
+
+ /**
+ * private constructor, to prevent constructing it arbitrarily
+ *
+ * @param inputType
+ */
+ private AListPointable(AbstractCollectionType inputType) {
+ if (inputType instanceof AOrderedListType) {
+ ordered = true;
+ }
+ if (inputType != null && inputType.getItemType() != null) {
+ itemType = inputType.getItemType();
+ if (itemType.getTypeTag() == ATypeTag.ANY) {
+ typedItemList = false;
+ } else {
+ typedItemList = true;
+ itemTag = inputType.getItemType().getTypeTag();
+ }
+ } else {
+ this.typedItemList = false;
+ }
+ }
+
+ private void reset() {
+ allocator.reset();
+ items.clear();
+ itemTags.clear();
+ dataBos.reset();
+ }
+
+ @Override
+ public void set(byte[] b, int s, int len) {
+ reset();
+
+ int numberOfitems = AInt32SerializerDeserializer.getInt(b, s + 6);
+ int itemOffset;
+ if (typedItemList) {
+ switch (itemTag) {
+ case STRING:
+ case RECORD:
+ case ORDEREDLIST:
+ case UNORDEREDLIST:
+ case ANY:
+ itemOffset = s + 10 + (numberOfitems * 4);
+ break;
+ default:
+ itemOffset = s + 10;
+ }
+ } else {
+ itemOffset = s + 10 + (numberOfitems * 4);
+ }
+ int itemLength = 0;
+ try {
+ if (typedItemList) {
+ for (int i = 0; i < numberOfitems; i++) {
+ itemLength = NonTaggedFormatUtil.getFieldValueLength(b, itemOffset, itemTag, false);
+ IVisitablePointable tag = allocator.allocateEmpty();
+ IVisitablePointable item = allocator.allocateFieldValue(itemType);
+
+ // set item type tag
+ int start = dataBos.size();
+ dataDos.writeByte(itemTag.serialize());
+ int end = dataBos.size();
+ tag.set(dataBos.getByteArray(), start, end - start);
+ itemTags.add(tag);
+
+ // set item value
+ start = dataBos.size();
+ dataDos.writeByte(itemTag.serialize());
+ dataDos.write(b, itemOffset, itemLength);
+ end = dataBos.size();
+ item.set(dataBos.getByteArray(), start, end - start);
+ itemOffset += itemLength;
+ items.add(item);
+ }
+ } else {
+ for (int i = 0; i < numberOfitems; i++) {
+ itemTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(b[itemOffset]);
+ itemLength = NonTaggedFormatUtil.getFieldValueLength(b, itemOffset, itemTag, true) + 1;
+ IVisitablePointable tag = allocator.allocateEmpty();
+ IVisitablePointable item = allocator.allocateFieldValue(itemTag);
+
+ // set item type tag
+ int start = dataBos.size();
+ dataDos.writeByte(itemTag.serialize());
+ int end = dataBos.size();
+ tag.set(dataBos.getByteArray(), start, end - start);
+ itemTags.add(tag);
+
+ // open part field already include the type tag
+ item.set(b, itemOffset, itemLength);
+ itemOffset += itemLength;
+ items.add(item);
+ }
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public <R, T> R accept(IVisitablePointableVisitor<R, T> vistor, T tag) throws AsterixException {
+ return vistor.visit(this, tag);
+ }
+
+ public List<IVisitablePointable> getItems() {
+ return items;
+ }
+
+ public List<IVisitablePointable> getItemTags() {
+ return itemTags;
+ }
+
+ public boolean ordered() {
+ return ordered;
+ }
+}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/ARecordPointable.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/ARecordPointable.java
new file mode 100644
index 0000000..7e097af
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/ARecordPointable.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2009-2010 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.uci.ics.asterix.om.pointables;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.dataflow.data.nontagged.AqlNullWriterFactory;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserializer;
+import edu.uci.ics.asterix.om.pointables.base.IVisitablePointable;
+import edu.uci.ics.asterix.om.pointables.visitor.IVisitablePointableVisitor;
+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.asterix.om.util.ResettableByteArrayOutputStream;
+import edu.uci.ics.asterix.om.util.container.IObjectFactory;
+import edu.uci.ics.hyracks.api.dataflow.value.INullWriter;
+
+/**
+ * This class interprets the binary data representation of a record. One can
+ * call getFieldNames, getFieldTypeTags and getFieldValues to get pointable
+ * objects for field names, field type tags, and field values.
+ *
+ */
+public class ARecordPointable extends AbstractVisitablePointable {
+
+ /**
+ * DO NOT allow to create ARecordPointable object arbitrarily, force to use
+ * object pool based allocator, in order to have object reuse
+ */
+ static IObjectFactory<IVisitablePointable, IAType> FACTORY = new IObjectFactory<IVisitablePointable, IAType>() {
+ public IVisitablePointable create(IAType type) {
+ return new ARecordPointable((ARecordType) type);
+ }
+ };
+
+ // access results: field names, field types, and field values
+ private final List<IVisitablePointable> fieldNames = new ArrayList<IVisitablePointable>();
+ private final List<IVisitablePointable> fieldTypeTags = new ArrayList<IVisitablePointable>();
+ private final List<IVisitablePointable> fieldValues = new ArrayList<IVisitablePointable>();
+
+ // pointable allocator
+ private final PointableAllocator allocator = new PointableAllocator();
+
+ private final ResettableByteArrayOutputStream typeBos = new ResettableByteArrayOutputStream();
+ private final DataOutputStream typeDos = new DataOutputStream(typeBos);
+
+ private final ResettableByteArrayOutputStream dataBos = new ResettableByteArrayOutputStream();
+ private final DataOutputStream dataDos = new DataOutputStream(dataBos);
+
+ private final ARecordType inputRecType;
+
+ private final int numberOfSchemaFields;
+ private final int[] fieldOffsets;
+ private final IVisitablePointable nullReference = AFlatValuePointable.FACTORY.create(null);
+
+ private int closedPartTypeInfoSize = 0;
+ private int offsetArrayOffset;
+ private ATypeTag typeTag;
+
+ /**
+ * private constructor, to prevent constructing it arbitrarily
+ *
+ * @param inputType
+ */
+ private ARecordPointable(ARecordType inputType) {
+ this.inputRecType = inputType;
+ IAType[] fieldTypes = inputType.getFieldTypes();
+ String[] fieldNameStrs = inputType.getFieldNames();
+ numberOfSchemaFields = fieldTypes.length;
+
+ // initialize the buffer for closed parts(fieldName bytes+ type bytes) +
+ // constant(null bytes)
+ typeBos.reset();
+ try {
+ for (int i = 0; i < numberOfSchemaFields; i++) {
+ ATypeTag ftypeTag = fieldTypes[i].getTypeTag();
+
+ if (fieldTypes[i].getTypeTag() == ATypeTag.UNION
+ && NonTaggedFormatUtil.isOptionalField((AUnionType) fieldTypes[i]))
+ // optional field: add the embedded non-null type tag
+ ftypeTag = ((AUnionType) fieldTypes[i]).getUnionList()
+ .get(NonTaggedFormatUtil.OPTIONAL_TYPE_INDEX_IN_UNION_LIST).getTypeTag();
+
+ // add type tag Reference
+ int tagStart = typeBos.size();
+ typeDos.writeByte(ftypeTag.serialize());
+ int tagEnd = typeBos.size();
+ IVisitablePointable typeTagReference = AFlatValuePointable.FACTORY.create(null);
+ typeTagReference.set(typeBos.getByteArray(), tagStart, tagEnd - tagStart);
+ fieldTypeTags.add(typeTagReference);
+
+ // add type name Reference (including a astring type tag)
+ int nameStart = typeBos.size();
+ typeDos.writeByte(ATypeTag.STRING.serialize());
+ typeDos.writeUTF(fieldNameStrs[i]);
+ int nameEnd = typeBos.size();
+ IVisitablePointable typeNameReference = AFlatValuePointable.FACTORY.create(null);
+ typeNameReference.set(typeBos.getByteArray(), nameStart, nameEnd - nameStart);
+ fieldNames.add(typeNameReference);
+ }
+
+ // initialize a constant: null value bytes reference
+ int nullFieldStart = typeBos.size();
+ INullWriter nullWriter = AqlNullWriterFactory.INSTANCE.createNullWriter();
+ nullWriter.writeNull(typeDos);
+ int nullFieldEnd = typeBos.size();
+ nullReference.set(typeBos.getByteArray(), nullFieldStart, nullFieldEnd - nullFieldStart);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ closedPartTypeInfoSize = typeBos.size();
+ fieldOffsets = new int[numberOfSchemaFields];
+ }
+
+ private void reset() {
+ typeBos.reset(closedPartTypeInfoSize);
+ dataBos.reset(0);
+ // reset the allocator
+ allocator.reset();
+
+ // clean up the returned containers
+ for (int i = fieldNames.size() - 1; i >= numberOfSchemaFields; i--)
+ fieldNames.remove(i);
+ for (int i = fieldTypeTags.size() - 1; i >= numberOfSchemaFields; i--)
+ fieldTypeTags.remove(i);
+ fieldValues.clear();
+ }
+
+ @Override
+ public void set(byte[] b, int start, int len) {
+ // clear the previous states
+ reset();
+ super.set(b, start, len);
+
+ boolean isExpanded = false;
+ int openPartOffset = 0;
+ int s = start;
+ int recordOffset = s;
+ if (inputRecType == null) {
+ openPartOffset = s + AInt32SerializerDeserializer.getInt(b, s + 6);
+ s += 8;
+ isExpanded = true;
+ } else {
+ if (inputRecType.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;
+ int nullBitMapOffset = 0;
+ boolean hasNullableFields = NonTaggedFormatUtil.hasNullableField(inputRecType);
+ 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 (hasNullableFields) {
+ byte b1 = b[nullBitMapOffset + fieldNumber / 8];
+ int p = 1 << (7 - (fieldNumber % 8));
+ if ((b1 & p) == 0) {
+ // set null value (including type tag inside)
+ fieldValues.add(nullReference);
+ continue;
+ }
+ }
+ IAType[] fieldTypes = inputRecType.getFieldTypes();
+ int fieldValueLength = 0;
+
+ IAType fieldType = fieldTypes[fieldNumber];
+ if (fieldTypes[fieldNumber].getTypeTag() == ATypeTag.UNION) {
+ if (NonTaggedFormatUtil.isOptionalField((AUnionType) fieldTypes[fieldNumber])) {
+ fieldType = ((AUnionType) fieldTypes[fieldNumber]).getUnionList().get(
+ NonTaggedFormatUtil.OPTIONAL_TYPE_INDEX_IN_UNION_LIST);
+ typeTag = fieldType.getTypeTag();
+ fieldValueLength = NonTaggedFormatUtil.getFieldValueLength(b, fieldOffsets[fieldNumber],
+ typeTag, false);
+ }
+ } else {
+ typeTag = fieldTypes[fieldNumber].getTypeTag();
+ fieldValueLength = NonTaggedFormatUtil.getFieldValueLength(b, fieldOffsets[fieldNumber],
+ typeTag, false);
+ }
+ // set field value (including the type tag)
+ int fstart = dataBos.size();
+ dataDos.writeByte(typeTag.serialize());
+ dataDos.write(b, fieldOffsets[fieldNumber], fieldValueLength);
+ int fend = dataBos.size();
+ IVisitablePointable fieldValue = allocator.allocateFieldValue(fieldType);
+ fieldValue.set(dataBos.getByteArray(), fstart, fend - fstart);
+ fieldValues.add(fieldValue);
+ }
+ }
+ if (isExpanded) {
+ int numberOfOpenFields = AInt32SerializerDeserializer.getInt(b, openPartOffset);
+ int fieldOffset = openPartOffset + 4 + (8 * numberOfOpenFields);
+ for (int i = 0; i < numberOfOpenFields; i++) {
+ // set the field name (including a type tag, which is
+ // astring)
+ int fieldValueLength = NonTaggedFormatUtil.getFieldValueLength(b, fieldOffset, ATypeTag.STRING,
+ false);
+ int fnstart = dataBos.size();
+ dataDos.writeByte(ATypeTag.STRING.serialize());
+ dataDos.write(b, fieldOffset, fieldValueLength);
+ int fnend = dataBos.size();
+ IVisitablePointable fieldName = allocator.allocateEmpty();
+ fieldName.set(dataBos.getByteArray(), fnstart, fnend - fnstart);
+ fieldNames.add(fieldName);
+ fieldOffset += fieldValueLength;
+
+ // set the field type tag
+ IVisitablePointable fieldTypeTag = allocator.allocateEmpty();
+ fieldTypeTag.set(b, fieldOffset, 1);
+ fieldTypeTags.add(fieldTypeTag);
+ typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(b[fieldOffset]);
+
+ // set the field value (already including type tag)
+ fieldValueLength = NonTaggedFormatUtil.getFieldValueLength(b, fieldOffset, typeTag, true) + 1;
+
+ // allocate
+ IVisitablePointable fieldValueAccessor = allocator.allocateFieldValue(typeTag);
+ fieldValueAccessor.set(b, fieldOffset, fieldValueLength);
+ fieldValues.add(fieldValueAccessor);
+ fieldOffset += fieldValueLength;
+ }
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public List<IVisitablePointable> getFieldNames() {
+ return fieldNames;
+ }
+
+ public List<IVisitablePointable> getFieldTypeTags() {
+ return fieldTypeTags;
+ }
+
+ public List<IVisitablePointable> getFieldValues() {
+ return fieldValues;
+ }
+
+ @Override
+ public <R, T> R accept(IVisitablePointableVisitor<R, T> vistor, T tag) throws AsterixException {
+ return vistor.visit(this, tag);
+ }
+
+}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/AbstractVisitablePointable.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/AbstractVisitablePointable.java
new file mode 100644
index 0000000..943a967
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/AbstractVisitablePointable.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2009-2010 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.uci.ics.asterix.om.pointables;
+
+import edu.uci.ics.asterix.om.pointables.base.IVisitablePointable;
+import edu.uci.ics.hyracks.data.std.api.IValueReference;
+
+/**
+ * This class implements several "routine" methods in IVisitablePointable
+ * interface, so that subclasses do not need to repeat the same code.
+ */
+public abstract class AbstractVisitablePointable implements IVisitablePointable {
+
+ private byte[] data;
+ private int start = -1;
+ private int len = -1;
+
+ @Override
+ public byte[] getByteArray() {
+ return data;
+ }
+
+ @Override
+ public int getLength() {
+ return len;
+ }
+
+ @Override
+ public int getStartOffset() {
+ return start;
+ }
+
+ @Override
+ public void set(byte[] b, int start, int len) {
+ this.data = b;
+ this.start = start;
+ this.len = len;
+ }
+
+ @Override
+ public void set(IValueReference ivf) {
+ set(ivf.getByteArray(), ivf.getStartOffset(), ivf.getLength());
+ }
+
+}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/PointableAllocator.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/PointableAllocator.java
new file mode 100644
index 0000000..5ad2ccb
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/PointableAllocator.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2009-2010 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.uci.ics.asterix.om.pointables;
+
+import edu.uci.ics.asterix.om.pointables.base.DefaultOpenFieldType;
+import edu.uci.ics.asterix.om.pointables.base.IVisitablePointable;
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.IAType;
+import edu.uci.ics.asterix.om.util.container.IObjectPool;
+import edu.uci.ics.asterix.om.util.container.ListObjectPool;
+
+/**
+ * This class is the ONLY place to create IVisitablePointable object instances,
+ * to enforce use of an object pool.
+ */
+public class PointableAllocator {
+
+ private IObjectPool<IVisitablePointable, IAType> flatValueAllocator = new ListObjectPool<IVisitablePointable, IAType>(
+ AFlatValuePointable.FACTORY);
+ private IObjectPool<IVisitablePointable, IAType> recordValueAllocator = new ListObjectPool<IVisitablePointable, IAType>(
+ ARecordPointable.FACTORY);
+ private IObjectPool<IVisitablePointable, IAType> listValueAllocator = new ListObjectPool<IVisitablePointable, IAType>(
+ AListPointable.FACTORY);
+
+ public IVisitablePointable allocateEmpty() {
+ return flatValueAllocator.allocate(null);
+ }
+
+ /**
+ * allocate closed part value pointable
+ *
+ * @param type
+ * @return the pointable object
+ */
+ public IVisitablePointable allocateFieldValue(IAType type) {
+ if (type == null)
+ return flatValueAllocator.allocate(null);
+ else if (type.getTypeTag().equals(ATypeTag.RECORD))
+ return recordValueAllocator.allocate(type);
+ else if (type.getTypeTag().equals(ATypeTag.UNORDEREDLIST) || type.getTypeTag().equals(ATypeTag.ORDEREDLIST))
+ return listValueAllocator.allocate(type);
+ else
+ return flatValueAllocator.allocate(null);
+ }
+
+ /**
+ * allocate open part value pointable
+ *
+ * @param typeTag
+ * @return the pointable object
+ */
+ public IVisitablePointable allocateFieldValue(ATypeTag typeTag) {
+ if (typeTag == null)
+ return flatValueAllocator.allocate(null);
+ else if (typeTag.equals(ATypeTag.RECORD))
+ return recordValueAllocator.allocate(DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE);
+ else if (typeTag.equals(ATypeTag.UNORDEREDLIST))
+ return listValueAllocator.allocate(DefaultOpenFieldType.NESTED_OPEN_AUNORDERED_LIST_TYPE);
+ else if (typeTag.equals(ATypeTag.ORDEREDLIST))
+ return listValueAllocator.allocate(DefaultOpenFieldType.NESTED_OPEN_AORDERED_LIST_TYPE);
+ else
+ return flatValueAllocator.allocate(null);
+ }
+
+ public IVisitablePointable allocateListValue(IAType type) {
+ return listValueAllocator.allocate(type);
+ }
+
+ public IVisitablePointable allocateRecordValue(IAType type) {
+ return recordValueAllocator.allocate(type);
+ }
+
+ public void reset() {
+ flatValueAllocator.reset();
+ recordValueAllocator.reset();
+ listValueAllocator.reset();
+ }
+}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/base/DefaultOpenFieldType.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/base/DefaultOpenFieldType.java
new file mode 100644
index 0000000..9184616
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/base/DefaultOpenFieldType.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2009-2010 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.uci.ics.asterix.om.pointables.base;
+
+import edu.uci.ics.asterix.om.types.AOrderedListType;
+import edu.uci.ics.asterix.om.types.ARecordType;
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.AUnorderedListType;
+import edu.uci.ics.asterix.om.types.BuiltinType;
+import edu.uci.ics.asterix.om.types.IAType;
+
+/**
+ * This class serves as the repository for the default record type and list type
+ * fields in the open part, e.g., a "record" (nested) field in the open part is
+ * always a fully open one, and a "list" field in the open part is always a list
+ * of "ANY".
+ *
+ */
+public class DefaultOpenFieldType {
+
+ // nested open field rec type
+ public static ARecordType NESTED_OPEN_RECORD_TYPE = new ARecordType("nested-open", new String[] {},
+ new IAType[] {}, true);
+
+ // nested open list type
+ public static AOrderedListType NESTED_OPEN_AORDERED_LIST_TYPE = new AOrderedListType(BuiltinType.ANY,
+ "nested-ordered-list");
+
+ // nested open list type
+ public static AUnorderedListType NESTED_OPEN_AUNORDERED_LIST_TYPE = new AUnorderedListType(BuiltinType.ANY,
+ "nested-unordered-list");
+
+ public static IAType getDefaultOpenFieldType(ATypeTag tag) {
+ if (tag.equals(ATypeTag.RECORD))
+ return NESTED_OPEN_RECORD_TYPE;
+ if (tag.equals(ATypeTag.ORDEREDLIST))
+ return NESTED_OPEN_AORDERED_LIST_TYPE;
+ if (tag.equals(ATypeTag.UNORDEREDLIST))
+ return NESTED_OPEN_AUNORDERED_LIST_TYPE;
+ else
+ return null;
+ }
+
+}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/base/IVisitablePointable.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/base/IVisitablePointable.java
new file mode 100644
index 0000000..7456ee8
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/base/IVisitablePointable.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2009-2010 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.uci.ics.asterix.om.pointables.base;
+
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.om.pointables.visitor.IVisitablePointableVisitor;
+import edu.uci.ics.hyracks.data.std.api.IPointable;
+
+/**
+ * This interface extends IPointable with a visitor interface in order to ease
+ * programming for recursive record structures.
+ */
+public interface IVisitablePointable extends IPointable {
+
+ public <R, T> R accept(IVisitablePointableVisitor<R, T> vistor, T tag) throws AsterixException;
+}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/cast/ACastVisitor.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/cast/ACastVisitor.java
new file mode 100644
index 0000000..9fccf4a
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/cast/ACastVisitor.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2009-2010 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.uci.ics.asterix.om.pointables.cast;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.om.pointables.AFlatValuePointable;
+import edu.uci.ics.asterix.om.pointables.AListPointable;
+import edu.uci.ics.asterix.om.pointables.ARecordPointable;
+import edu.uci.ics.asterix.om.pointables.base.DefaultOpenFieldType;
+import edu.uci.ics.asterix.om.pointables.base.IVisitablePointable;
+import edu.uci.ics.asterix.om.pointables.visitor.IVisitablePointableVisitor;
+import edu.uci.ics.asterix.om.types.ARecordType;
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.AbstractCollectionType;
+import edu.uci.ics.asterix.om.types.IAType;
+import edu.uci.ics.hyracks.algebricks.common.utils.Triple;
+
+/**
+ * This class is a IVisitablePointableVisitor implementation which recursively
+ * visit a given record, list or flat value of a given type, and cast it to a
+ * specified type. For example:
+ * A record { "hobby": {{"music", "coding"}}, "id": "001", "name":
+ * "Person Three"} which confirms to closed type ( id: string, name: string,
+ * hobby: {{string}}? ) can be casted to a open type (id: string )
+ * Since the open/closed part of a record has a completely different underlying
+ * memory/storage layout, the visitor will change the layout as specified at
+ * runtime.
+ */
+public class ACastVisitor implements IVisitablePointableVisitor<Void, Triple<IVisitablePointable, IAType, Boolean>> {
+
+ private final Map<IVisitablePointable, ARecordCaster> raccessorToCaster = new HashMap<IVisitablePointable, ARecordCaster>();
+ private final Map<IVisitablePointable, AListCaster> laccessorToCaster = new HashMap<IVisitablePointable, AListCaster>();
+
+ @Override
+ public Void visit(AListPointable accessor, Triple<IVisitablePointable, IAType, Boolean> arg)
+ throws AsterixException {
+ AListCaster caster = laccessorToCaster.get(accessor);
+ if (caster == null) {
+ caster = new AListCaster();
+ laccessorToCaster.put(accessor, caster);
+ }
+ try {
+ if (arg.second.getTypeTag().equals(ATypeTag.ANY)) {
+ arg.second = DefaultOpenFieldType.NESTED_OPEN_AUNORDERED_LIST_TYPE;
+ }
+ caster.castList(accessor, arg.first, (AbstractCollectionType) arg.second, this);
+ } catch (Exception e) {
+ throw new AsterixException(e);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(ARecordPointable accessor, Triple<IVisitablePointable, IAType, Boolean> arg)
+ throws AsterixException {
+ ARecordCaster caster = raccessorToCaster.get(accessor);
+ if (caster == null) {
+ caster = new ARecordCaster();
+ raccessorToCaster.put(accessor, caster);
+ }
+ try {
+ if (arg.second.getTypeTag().equals(ATypeTag.ANY)) {
+ arg.second = DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE;
+ }
+ caster.castRecord(accessor, arg.first, (ARecordType) arg.second, this);
+ } catch (Exception e) {
+ throw new AsterixException(e);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(AFlatValuePointable accessor, Triple<IVisitablePointable, IAType, Boolean> arg) {
+ // set the pointer for result
+ arg.first.set(accessor);
+ return null;
+ }
+
+}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/cast/AListCaster.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/cast/AListCaster.java
new file mode 100644
index 0000000..c65b3eb
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/cast/AListCaster.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2009-2010 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.uci.ics.asterix.om.pointables.cast;
+
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.List;
+
+import edu.uci.ics.asterix.builders.OrderedListBuilder;
+import edu.uci.ics.asterix.builders.UnorderedListBuilder;
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.om.pointables.AListPointable;
+import edu.uci.ics.asterix.om.pointables.PointableAllocator;
+import edu.uci.ics.asterix.om.pointables.base.DefaultOpenFieldType;
+import edu.uci.ics.asterix.om.pointables.base.IVisitablePointable;
+import edu.uci.ics.asterix.om.types.AOrderedListType;
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.AUnorderedListType;
+import edu.uci.ics.asterix.om.types.AbstractCollectionType;
+import edu.uci.ics.asterix.om.types.EnumDeserializer;
+import edu.uci.ics.asterix.om.types.IAType;
+import edu.uci.ics.asterix.om.util.ResettableByteArrayOutputStream;
+import edu.uci.ics.hyracks.algebricks.common.utils.Triple;
+
+/**
+ * This class is to do the runtime type cast for a list. It is ONLY visible to
+ * ACastVisitor.
+ */
+class AListCaster {
+ // pointable allocator
+ private final PointableAllocator allocator = new PointableAllocator();
+
+ // for storing the cast result
+ private final IVisitablePointable itemTempReference = allocator.allocateEmpty();
+ private final Triple<IVisitablePointable, IAType, Boolean> itemVisitorArg = new Triple<IVisitablePointable, IAType, Boolean>(
+ itemTempReference, null, null);
+
+ private final UnorderedListBuilder unOrderedListBuilder = new UnorderedListBuilder();
+ private final OrderedListBuilder orderedListBuilder = new OrderedListBuilder();
+
+ private final ResettableByteArrayOutputStream dataBos = new ResettableByteArrayOutputStream();
+ private final DataOutput dataDos = new DataOutputStream(dataBos);
+ private IAType reqItemType;
+
+ public AListCaster() {
+
+ }
+
+ public void castList(AListPointable listAccessor, IVisitablePointable resultAccessor,
+ AbstractCollectionType reqType, ACastVisitor visitor) throws IOException, AsterixException {
+ if (reqType.getTypeTag().equals(ATypeTag.UNORDEREDLIST)) {
+ unOrderedListBuilder.reset((AUnorderedListType) reqType);
+ reqItemType = reqType.getItemType();
+ }
+ if (reqType.getTypeTag().equals(ATypeTag.ORDEREDLIST)) {
+ orderedListBuilder.reset((AOrderedListType) reqType);
+ reqItemType = reqType.getItemType();
+ }
+ dataBos.reset();
+
+ List<IVisitablePointable> itemTags = listAccessor.getItemTags();
+ List<IVisitablePointable> items = listAccessor.getItems();
+
+ int start = dataBos.size();
+ for (int i = 0; i < items.size(); i++) {
+ IVisitablePointable itemTypeTag = itemTags.get(i);
+ IVisitablePointable item = items.get(i);
+ ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(itemTypeTag.getByteArray()[itemTypeTag
+ .getStartOffset()]);
+ if (reqItemType == null || reqItemType.getTypeTag().equals(ATypeTag.ANY)) {
+ itemVisitorArg.second = DefaultOpenFieldType.getDefaultOpenFieldType(typeTag);
+ item.accept(visitor, itemVisitorArg);
+ } else {
+ if (typeTag != reqItemType.getTypeTag())
+ throw new AsterixException("mismatched item type");
+ itemVisitorArg.second = reqItemType;
+ item.accept(visitor, itemVisitorArg);
+ }
+ if (reqType.getTypeTag().equals(ATypeTag.ORDEREDLIST)) {
+ orderedListBuilder.addItem(itemVisitorArg.first);
+ }
+ if (reqType.getTypeTag().equals(ATypeTag.UNORDEREDLIST)) {
+ unOrderedListBuilder.addItem(itemVisitorArg.first);
+ }
+ }
+ if (reqType.getTypeTag().equals(ATypeTag.ORDEREDLIST)) {
+ orderedListBuilder.write(dataDos, true);
+ }
+ if (reqType.getTypeTag().equals(ATypeTag.UNORDEREDLIST)) {
+ unOrderedListBuilder.write(dataDos, true);
+ }
+ int end = dataBos.size();
+ resultAccessor.set(dataBos.getByteArray(), start, end - start);
+ }
+}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/cast/ARecordCaster.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/cast/ARecordCaster.java
new file mode 100644
index 0000000..fbad7a7
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/cast/ARecordCaster.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright 2009-2010 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.uci.ics.asterix.om.pointables.cast;
+
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import edu.uci.ics.asterix.builders.RecordBuilder;
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.dataflow.data.nontagged.AqlNullWriterFactory;
+import edu.uci.ics.asterix.om.pointables.ARecordPointable;
+import edu.uci.ics.asterix.om.pointables.PointableAllocator;
+import edu.uci.ics.asterix.om.pointables.base.DefaultOpenFieldType;
+import edu.uci.ics.asterix.om.pointables.base.IVisitablePointable;
+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.asterix.om.util.ResettableByteArrayOutputStream;
+import edu.uci.ics.hyracks.algebricks.common.utils.Triple;
+import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparator;
+import edu.uci.ics.hyracks.api.dataflow.value.INullWriter;
+import edu.uci.ics.hyracks.data.std.accessors.PointableBinaryComparatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IValueReference;
+import edu.uci.ics.hyracks.data.std.primitive.UTF8StringPointable;
+import edu.uci.ics.hyracks.data.std.util.ByteArrayAccessibleOutputStream;
+
+/**
+ * This class is to do the runtime type cast for a record. It is ONLY visible to
+ * ACastVisitor.
+ */
+class ARecordCaster {
+
+ // pointable allocator
+ private final PointableAllocator allocator = new PointableAllocator();
+
+ private final List<IVisitablePointable> reqFieldNames = new ArrayList<IVisitablePointable>();
+ private final List<IVisitablePointable> reqFieldTypeTags = new ArrayList<IVisitablePointable>();
+ private ARecordType cachedReqType = null;
+
+ private final ResettableByteArrayOutputStream bos = new ResettableByteArrayOutputStream();
+ private final DataOutputStream dos = new DataOutputStream(bos);
+
+ private final RecordBuilder recBuilder = new RecordBuilder();
+ private final IVisitablePointable nullReference = allocator.allocateEmpty();
+ private final IVisitablePointable nullTypeTag = allocator.allocateEmpty();
+
+ private final IBinaryComparator fieldNameComparator = PointableBinaryComparatorFactory.of(
+ UTF8StringPointable.FACTORY).createBinaryComparator();
+
+ private final ByteArrayAccessibleOutputStream outputBos = new ByteArrayAccessibleOutputStream();
+ private final DataOutputStream outputDos = new DataOutputStream(outputBos);
+
+ private final IVisitablePointable fieldTempReference = allocator.allocateEmpty();
+ private final Triple<IVisitablePointable, IAType, Boolean> nestedVisitorArg = new Triple<IVisitablePointable, IAType, Boolean>(
+ fieldTempReference, null, null);
+
+ private int numInputFields = 0;
+
+ // describe closed fields in the required type
+ private int[] fieldPermutation;
+ private boolean[] optionalFields;
+
+ // describe fields (open or not) in the input records
+ private boolean[] openFields;
+ private int[] fieldNamesSortedIndex;
+ private int[] reqFieldNamesSortedIndex;
+
+ public ARecordCaster() {
+ try {
+ bos.reset();
+ int start = bos.size();
+ INullWriter nullWriter = AqlNullWriterFactory.INSTANCE.createNullWriter();
+ nullWriter.writeNull(dos);
+ int end = bos.size();
+ nullReference.set(bos.getByteArray(), start, end - start);
+ start = bos.size();
+ dos.write(ATypeTag.NULL.serialize());
+ end = bos.size();
+ nullTypeTag.set(bos.getByteArray(), start, end);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public void castRecord(ARecordPointable recordAccessor, IVisitablePointable resultAccessor, ARecordType reqType,
+ ACastVisitor visitor) throws IOException, AsterixException {
+ List<IVisitablePointable> fieldNames = recordAccessor.getFieldNames();
+ List<IVisitablePointable> fieldTypeTags = recordAccessor.getFieldTypeTags();
+ List<IVisitablePointable> fieldValues = recordAccessor.getFieldValues();
+ numInputFields = fieldNames.size();
+
+ if (openFields == null || numInputFields > openFields.length) {
+ openFields = new boolean[numInputFields];
+ fieldNamesSortedIndex = new int[numInputFields];
+ }
+ if (cachedReqType == null || !reqType.equals(cachedReqType)) {
+ loadRequiredType(reqType);
+ }
+
+ // clear the previous states
+ reset();
+ matchClosedPart(fieldNames, fieldTypeTags, fieldValues);
+ writeOutput(fieldNames, fieldTypeTags, fieldValues, outputDos, visitor);
+ resultAccessor.set(outputBos.getByteArray(), 0, outputBos.size());
+ }
+
+ private void reset() {
+ for (int i = 0; i < numInputFields; i++)
+ openFields[i] = true;
+ for (int i = 0; i < fieldPermutation.length; i++)
+ fieldPermutation[i] = -1;
+ for (int i = 0; i < numInputFields; i++)
+ fieldNamesSortedIndex[i] = i;
+ outputBos.reset();
+ }
+
+ private void loadRequiredType(ARecordType reqType) throws IOException {
+ reqFieldNames.clear();
+ reqFieldTypeTags.clear();
+
+ cachedReqType = reqType;
+ int numSchemaFields = reqType.getFieldTypes().length;
+ IAType[] fieldTypes = reqType.getFieldTypes();
+ String[] fieldNames = reqType.getFieldNames();
+ fieldPermutation = new int[numSchemaFields];
+ optionalFields = new boolean[numSchemaFields];
+ for (int i = 0; i < optionalFields.length; i++)
+ optionalFields[i] = false;
+
+ bos.reset(nullReference.getStartOffset() + nullReference.getLength());
+ for (int i = 0; i < numSchemaFields; i++) {
+ ATypeTag ftypeTag = fieldTypes[i].getTypeTag();
+ String fname = fieldNames[i];
+
+ // add type tag pointable
+ if (fieldTypes[i].getTypeTag() == ATypeTag.UNION
+ && NonTaggedFormatUtil.isOptionalField((AUnionType) fieldTypes[i])) {
+ // optional field: add the embedded non-null type tag
+ ftypeTag = ((AUnionType) fieldTypes[i]).getUnionList()
+ .get(NonTaggedFormatUtil.OPTIONAL_TYPE_INDEX_IN_UNION_LIST).getTypeTag();
+ optionalFields[i] = true;
+ }
+ int tagStart = bos.size();
+ dos.writeByte(ftypeTag.serialize());
+ int tagEnd = bos.size();
+ IVisitablePointable typeTagPointable = allocator.allocateEmpty();
+ typeTagPointable.set(bos.getByteArray(), tagStart, tagEnd - tagStart);
+ reqFieldTypeTags.add(typeTagPointable);
+
+ // add type name pointable (including a string type tag)
+ int nameStart = bos.size();
+ dos.write(ATypeTag.STRING.serialize());
+ dos.writeUTF(fname);
+ int nameEnd = bos.size();
+ IVisitablePointable typeNamePointable = allocator.allocateEmpty();
+ typeNamePointable.set(bos.getByteArray(), nameStart, nameEnd - nameStart);
+ reqFieldNames.add(typeNamePointable);
+ }
+
+ reqFieldNamesSortedIndex = new int[reqFieldNames.size()];
+ for (int i = 0; i < reqFieldNamesSortedIndex.length; i++)
+ reqFieldNamesSortedIndex[i] = i;
+ // sort the field name index
+ quickSort(reqFieldNamesSortedIndex, reqFieldNames, 0, reqFieldNamesSortedIndex.length - 1);
+ }
+
+ private void matchClosedPart(List<IVisitablePointable> fieldNames, List<IVisitablePointable> fieldTypeTags,
+ List<IVisitablePointable> fieldValues) {
+ // sort-merge based match
+ quickSort(fieldNamesSortedIndex, fieldNames, 0, numInputFields - 1);
+ int fnStart = 0;
+ int reqFnStart = 0;
+ while (fnStart < numInputFields && reqFnStart < reqFieldNames.size()) {
+ int fnPos = fieldNamesSortedIndex[fnStart];
+ int reqFnPos = reqFieldNamesSortedIndex[reqFnStart];
+ int c = compare(fieldNames.get(fnPos), reqFieldNames.get(reqFnPos));
+ if (c == 0) {
+ IVisitablePointable fieldTypeTag = fieldTypeTags.get(fnPos);
+ IVisitablePointable reqFieldTypeTag = reqFieldTypeTags.get(reqFnPos);
+ if (fieldTypeTag.equals(reqFieldTypeTag) || (
+ // match the null type of optional field
+ optionalFields[reqFnPos] && fieldTypeTag.equals(nullTypeTag))) {
+ fieldPermutation[reqFnPos] = fnPos;
+ openFields[fnPos] = false;
+ }
+ fnStart++;
+ reqFnStart++;
+ }
+ if (c > 0)
+ reqFnStart++;
+ if (c < 0)
+ fnStart++;
+ }
+
+ // check unmatched fields in the input type
+ for (int i = 0; i < openFields.length; i++) {
+ if (openFields[i] == true && !cachedReqType.isOpen())
+ throw new IllegalStateException("type mismatch: including extra closed fields");
+ }
+
+ // check unmatched fields in the required type
+ for (int i = 0; i < fieldPermutation.length; i++) {
+ if (fieldPermutation[i] < 0) {
+ IAType t = cachedReqType.getFieldTypes()[i];
+ if (!(t.getTypeTag() == ATypeTag.UNION && NonTaggedFormatUtil.isOptionalField((AUnionType) t))) {
+ // no matched field in the input for a required closed field
+ throw new IllegalStateException("type mismatch: miss a required closed field");
+ }
+ }
+ }
+ }
+
+ private void writeOutput(List<IVisitablePointable> fieldNames, List<IVisitablePointable> fieldTypeTags,
+ List<IVisitablePointable> fieldValues, DataOutput output, ACastVisitor visitor) throws IOException,
+ AsterixException {
+ // reset the states of the record builder
+ recBuilder.reset(cachedReqType);
+ recBuilder.init();
+
+ // write the closed part
+ for (int i = 0; i < fieldPermutation.length; i++) {
+ int pos = fieldPermutation[i];
+ IVisitablePointable field;
+ if (pos >= 0) {
+ field = fieldValues.get(pos);
+ } else {
+ field = nullReference;
+ }
+ IAType fType = cachedReqType.getFieldTypes()[i];
+ nestedVisitorArg.second = fType;
+
+ // recursively casting, the result of casting can always be thought
+ // as flat
+ if (optionalFields[i]) {
+ nestedVisitorArg.second = ((AUnionType) fType).getUnionList().get(
+ NonTaggedFormatUtil.OPTIONAL_TYPE_INDEX_IN_UNION_LIST);
+ }
+ field.accept(visitor, nestedVisitorArg);
+ recBuilder.addField(i, nestedVisitorArg.first);
+ }
+
+ // write the open part
+ for (int i = 0; i < numInputFields; i++) {
+ if (openFields[i]) {
+ IVisitablePointable name = fieldNames.get(i);
+ IVisitablePointable field = fieldValues.get(i);
+ IVisitablePointable fieldTypeTag = fieldTypeTags.get(i);
+
+ ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER
+ .deserialize(fieldTypeTag.getByteArray()[fieldTypeTag.getStartOffset()]);
+ nestedVisitorArg.second = DefaultOpenFieldType.getDefaultOpenFieldType(typeTag);
+ field.accept(visitor, nestedVisitorArg);
+ recBuilder.addField(name, nestedVisitorArg.first);
+ }
+ }
+ recBuilder.write(output, true);
+ }
+
+ private void quickSort(int[] index, List<IVisitablePointable> names, int start, int end) {
+ if (end <= start)
+ return;
+ int i = partition(index, names, start, end);
+ quickSort(index, names, start, i - 1);
+ quickSort(index, names, i + 1, end);
+ }
+
+ private int partition(int[] index, List<IVisitablePointable> names, int left, int right) {
+ int i = left - 1;
+ int j = right;
+ while (true) {
+ // grow from the left
+ while (compare(names.get(index[++i]), names.get(index[right])) < 0)
+ ;
+ // lower from the right
+ while (compare(names.get(index[right]), names.get(index[--j])) < 0)
+ if (j == left)
+ break;
+ if (i >= j)
+ break;
+ // swap i and j
+ swap(index, i, j);
+ }
+ // swap i and right
+ swap(index, i, right); // swap with partition element
+ return i;
+ }
+
+ private void swap(int[] array, int i, int j) {
+ int temp = array[i];
+ array[i] = array[j];
+ array[j] = temp;
+ }
+
+ private int compare(IValueReference a, IValueReference b) {
+ // start+1 and len-1 due to the type tag
+ return fieldNameComparator.compare(a.getByteArray(), a.getStartOffset() + 1, a.getLength() - 1,
+ b.getByteArray(), b.getStartOffset() + 1, b.getLength() - 1);
+ }
+}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/printer/AListPrinter.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/printer/AListPrinter.java
new file mode 100644
index 0000000..5f47f4f
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/printer/AListPrinter.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2009-2010 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.uci.ics.asterix.om.pointables.printer;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.List;
+
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.om.pointables.AListPointable;
+import edu.uci.ics.asterix.om.pointables.base.IVisitablePointable;
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.EnumDeserializer;
+import edu.uci.ics.hyracks.algebricks.common.utils.Pair;
+
+/**
+ * This class is to print the content of a list. It is ONLY visible to
+ * APrintVisitor.
+ */
+class AListPrinter {
+ private static String LEFT_PAREN = "{{ ";
+ private static String RIGHT_PAREN = " }}";
+ private static String LEFT_PAREN_ORDERED = "[ ";
+ private static String RIGHT_PAREN_ORDERED = " ]";
+ private static String COMMA = ", ";
+
+ private final Pair<PrintStream, ATypeTag> itemVisitorArg = new Pair<PrintStream, ATypeTag>(null, null);
+ private String leftParen = LEFT_PAREN;
+ private String rightParen = RIGHT_PAREN;
+
+ public AListPrinter(boolean ordered) {
+ if (ordered) {
+ leftParen = LEFT_PAREN_ORDERED;
+ rightParen = RIGHT_PAREN_ORDERED;
+ }
+ }
+
+ public void printList(AListPointable listAccessor, PrintStream ps, APrintVisitor visitor) throws IOException,
+ AsterixException {
+ List<IVisitablePointable> itemTags = listAccessor.getItemTags();
+ List<IVisitablePointable> items = listAccessor.getItems();
+ itemVisitorArg.first = ps;
+
+ //print the beginning part
+ ps.print(leftParen);
+
+ // print item 0 to n-2
+ for (int i = 0; i < items.size() - 1; i++) {
+ IVisitablePointable itemTypeTag = itemTags.get(i);
+ IVisitablePointable item = items.get(i);
+ ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(itemTypeTag.getByteArray()[itemTypeTag
+ .getStartOffset()]);
+ itemVisitorArg.second = item.getLength() <= 1 ? ATypeTag.NULL : typeTag;
+ item.accept(visitor, itemVisitorArg);
+ //print the comma
+ ps.print(COMMA);
+ }
+
+ // print item n-1
+ if (items.size() > 0) {
+ IVisitablePointable itemTypeTag = itemTags.get(itemTags.size() - 1);
+ IVisitablePointable item = items.get(items.size() - 1);
+ ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(itemTypeTag.getByteArray()[itemTypeTag
+ .getStartOffset()]);
+ itemVisitorArg.second = item.getLength() <= 1 ? ATypeTag.NULL : typeTag;
+ item.accept(visitor, itemVisitorArg);
+ }
+
+ //print the end part
+ ps.print(rightParen);
+ }
+}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/printer/APrintVisitor.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/printer/APrintVisitor.java
new file mode 100644
index 0000000..3664804
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/printer/APrintVisitor.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2009-2010 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.uci.ics.asterix.om.pointables.printer;
+
+import java.io.PrintStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.dataflow.data.nontagged.printers.ABooleanPrinter;
+import edu.uci.ics.asterix.dataflow.data.nontagged.printers.ACirclePrinter;
+import edu.uci.ics.asterix.dataflow.data.nontagged.printers.ADatePrinter;
+import edu.uci.ics.asterix.dataflow.data.nontagged.printers.ADateTimePrinter;
+import edu.uci.ics.asterix.dataflow.data.nontagged.printers.ADoublePrinter;
+import edu.uci.ics.asterix.dataflow.data.nontagged.printers.ADurationPrinter;
+import edu.uci.ics.asterix.dataflow.data.nontagged.printers.AFloatPrinter;
+import edu.uci.ics.asterix.dataflow.data.nontagged.printers.AInt16Printer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.printers.AInt32Printer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.printers.AInt64Printer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.printers.AInt8Printer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.printers.ALinePrinter;
+import edu.uci.ics.asterix.dataflow.data.nontagged.printers.ANullPrinter;
+import edu.uci.ics.asterix.dataflow.data.nontagged.printers.APoint3DPrinter;
+import edu.uci.ics.asterix.dataflow.data.nontagged.printers.APointPrinter;
+import edu.uci.ics.asterix.dataflow.data.nontagged.printers.APolygonPrinter;
+import edu.uci.ics.asterix.dataflow.data.nontagged.printers.ARectanglePrinter;
+import edu.uci.ics.asterix.dataflow.data.nontagged.printers.AStringPrinter;
+import edu.uci.ics.asterix.dataflow.data.nontagged.printers.ATimePrinter;
+import edu.uci.ics.asterix.om.pointables.AFlatValuePointable;
+import edu.uci.ics.asterix.om.pointables.AListPointable;
+import edu.uci.ics.asterix.om.pointables.ARecordPointable;
+import edu.uci.ics.asterix.om.pointables.base.IVisitablePointable;
+import edu.uci.ics.asterix.om.pointables.visitor.IVisitablePointableVisitor;
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.NotImplementedException;
+import edu.uci.ics.hyracks.algebricks.common.utils.Pair;
+
+/**
+ * This class is a IVisitablePointableVisitor implementation which recursively
+ * visit a given record, list or flat value of a given type, and print it to a
+ * PrintStream in adm format.
+ */
+public class APrintVisitor implements IVisitablePointableVisitor<Void, Pair<PrintStream, ATypeTag>> {
+
+ private final Map<IVisitablePointable, ARecordPrinter> raccessorToPrinter = new HashMap<IVisitablePointable, ARecordPrinter>();
+ private final Map<IVisitablePointable, AListPrinter> laccessorToPrinter = new HashMap<IVisitablePointable, AListPrinter>();
+
+ @Override
+ public Void visit(AListPointable accessor, Pair<PrintStream, ATypeTag> arg) throws AsterixException {
+ AListPrinter printer = laccessorToPrinter.get(accessor);
+ if (printer == null) {
+ printer = new AListPrinter(accessor.ordered());
+ laccessorToPrinter.put(accessor, printer);
+ }
+ try {
+ printer.printList(accessor, arg.first, this);
+ } catch (Exception e) {
+ throw new AsterixException(e);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(ARecordPointable accessor, Pair<PrintStream, ATypeTag> arg) throws AsterixException {
+ ARecordPrinter printer = raccessorToPrinter.get(accessor);
+ if (printer == null) {
+ printer = new ARecordPrinter();
+ raccessorToPrinter.put(accessor, printer);
+ }
+ try {
+ printer.printRecord(accessor, arg.first, this);
+ } catch (Exception e) {
+ throw new AsterixException(e);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(AFlatValuePointable accessor, Pair<PrintStream, ATypeTag> arg) {
+ try {
+ byte[] b = accessor.getByteArray();
+ int s = accessor.getStartOffset();
+ int l = accessor.getLength();
+ PrintStream ps = arg.first;
+ ATypeTag typeTag = arg.second;
+ switch (typeTag) {
+ case INT8: {
+ AInt8Printer.INSTANCE.print(b, s, l, ps);
+ break;
+ }
+ case INT16: {
+ AInt16Printer.INSTANCE.print(b, s, l, ps);
+ break;
+ }
+ case INT32: {
+ AInt32Printer.INSTANCE.print(b, s, l, ps);
+ break;
+ }
+ case INT64: {
+ AInt64Printer.INSTANCE.print(b, s, l, ps);
+ break;
+ }
+ case NULL: {
+ ANullPrinter.INSTANCE.print(b, s, l, ps);
+ break;
+ }
+ case BOOLEAN: {
+ ABooleanPrinter.INSTANCE.print(b, s, l, ps);
+ break;
+ }
+ case FLOAT: {
+ AFloatPrinter.INSTANCE.print(b, s, l, ps);
+ break;
+ }
+ case DOUBLE: {
+ ADoublePrinter.INSTANCE.print(b, s, l, ps);
+ break;
+ }
+ case DATE: {
+ ADatePrinter.INSTANCE.print(b, s, l, ps);
+ break;
+ }
+ case TIME: {
+ ATimePrinter.INSTANCE.print(b, s, l, ps);
+ break;
+ }
+ case DATETIME: {
+ ADateTimePrinter.INSTANCE.print(b, s, l, ps);
+ break;
+ }
+ case DURATION: {
+ ADurationPrinter.INSTANCE.print(b, s, l, ps);
+ break;
+ }
+ case POINT: {
+ APointPrinter.INSTANCE.print(b, s, l, ps);
+ break;
+ }
+ case POINT3D: {
+ APoint3DPrinter.INSTANCE.print(b, s, l, ps);
+ break;
+ }
+ case LINE: {
+ ALinePrinter.INSTANCE.print(b, s, l, ps);
+ break;
+ }
+ case POLYGON: {
+ APolygonPrinter.INSTANCE.print(b, s, l, ps);
+ break;
+ }
+ case CIRCLE: {
+ ACirclePrinter.INSTANCE.print(b, s, l, ps);
+ break;
+ }
+ case RECTANGLE: {
+ ARectanglePrinter.INSTANCE.print(b, s, l, ps);
+ break;
+ }
+ case STRING: {
+ AStringPrinter.INSTANCE.print(b, s, l, ps);
+ break;
+ }
+ default: {
+ throw new NotImplementedException("No printer for type " + typeTag);
+ }
+ }
+ return null;
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/printer/ARecordPrinter.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/printer/ARecordPrinter.java
new file mode 100644
index 0000000..391d2c9
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/printer/ARecordPrinter.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2009-2010 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.uci.ics.asterix.om.pointables.printer;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.List;
+
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.om.pointables.ARecordPointable;
+import edu.uci.ics.asterix.om.pointables.base.IVisitablePointable;
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.EnumDeserializer;
+import edu.uci.ics.hyracks.algebricks.common.utils.Pair;
+
+/**
+ * This class is to print the content of a record. It is ONLY visible to
+ * APrintVisitor.
+ */
+class ARecordPrinter {
+ private static String LEFT_PAREN = "{ ";
+ private static String RIGHT_PAREN = " }";
+ private static String COMMA = ", ";
+ private static String COLON = ": ";
+
+ private final Pair<PrintStream, ATypeTag> nameVisitorArg = new Pair<PrintStream, ATypeTag>(null, ATypeTag.STRING);
+ private final Pair<PrintStream, ATypeTag> itemVisitorArg = new Pair<PrintStream, ATypeTag>(null, null);
+
+ public ARecordPrinter() {
+
+ }
+
+ public void printRecord(ARecordPointable recordAccessor, PrintStream ps, APrintVisitor visitor) throws IOException,
+ AsterixException {
+ List<IVisitablePointable> fieldNames = recordAccessor.getFieldNames();
+ List<IVisitablePointable> fieldTags = recordAccessor.getFieldTypeTags();
+ List<IVisitablePointable> fieldValues = recordAccessor.getFieldValues();
+
+ nameVisitorArg.first = ps;
+ itemVisitorArg.first = ps;
+
+ // print the beginning part
+ ps.print(LEFT_PAREN);
+
+ // print field 0 to n-2
+ for (int i = 0; i < fieldNames.size() - 1; i++) {
+ IVisitablePointable itemTypeTag = fieldTags.get(i);
+ IVisitablePointable item = fieldValues.get(i);
+ ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(itemTypeTag.getByteArray()[itemTypeTag
+ .getStartOffset()]);
+ itemVisitorArg.second = item.getLength() <= 1 ? ATypeTag.NULL : typeTag;
+
+ // print field name
+ fieldNames.get(i).accept(visitor, nameVisitorArg);
+ ps.print(COLON);
+ // print field value
+ item.accept(visitor, itemVisitorArg);
+
+ // print the comma
+ ps.print(COMMA);
+ }
+
+ // print field n-1
+ if (fieldValues.size() > 0) {
+ IVisitablePointable itemTypeTag = fieldTags.get(fieldTags.size() - 1);
+ IVisitablePointable item = fieldValues.get(fieldValues.size() - 1);
+ ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(itemTypeTag.getByteArray()[itemTypeTag
+ .getStartOffset()]);
+ itemVisitorArg.second = item.getLength() <= 1 ? ATypeTag.NULL : typeTag;
+
+ // print field name
+ fieldNames.get(fieldNames.size() - 1).accept(visitor, nameVisitorArg);
+ ps.print(COLON);
+ // print field value
+ item.accept(visitor, itemVisitorArg);
+ }
+
+ // print the end part
+ ps.print(RIGHT_PAREN);
+ }
+}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/visitor/IVisitablePointableVisitor.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/visitor/IVisitablePointableVisitor.java
new file mode 100644
index 0000000..bcb4b34
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/visitor/IVisitablePointableVisitor.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2009-2010 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.uci.ics.asterix.om.pointables.visitor;
+
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.om.pointables.AFlatValuePointable;
+import edu.uci.ics.asterix.om.pointables.AListPointable;
+import edu.uci.ics.asterix.om.pointables.ARecordPointable;
+
+/**
+ * This interface is a visitor for all the three different IVisitablePointable
+ * (Note that right now we have three pointable implementations for type
+ * casting) implementations.
+ */
+public interface IVisitablePointableVisitor<R, T> {
+
+ public R visit(AListPointable accessor, T arg) throws AsterixException;
+
+ public R visit(ARecordPointable accessor, T arg) throws AsterixException;
+
+ public R visit(AFlatValuePointable accessor, T arg) throws AsterixException;
+}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/typecomputer/impl/NonTaggedFieldAccessByNameResultType.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/typecomputer/impl/NonTaggedFieldAccessByNameResultType.java
index 4b8b32a9..d9420cf 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/om/typecomputer/impl/NonTaggedFieldAccessByNameResultType.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/typecomputer/impl/NonTaggedFieldAccessByNameResultType.java
@@ -2,6 +2,7 @@
import edu.uci.ics.asterix.om.base.AString;
import edu.uci.ics.asterix.om.constants.AsterixConstantValue;
+import edu.uci.ics.asterix.om.pointables.base.DefaultOpenFieldType;
import edu.uci.ics.asterix.om.typecomputer.base.IResultTypeComputer;
import edu.uci.ics.asterix.om.types.ARecordType;
import edu.uci.ics.asterix.om.types.ATypeTag;
@@ -9,7 +10,6 @@
import edu.uci.ics.asterix.om.types.BuiltinType;
import edu.uci.ics.asterix.om.types.IAType;
import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
-import edu.uci.ics.hyracks.algebricks.common.exceptions.NotImplementedException;
import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression;
import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
@@ -58,7 +58,7 @@
return (ARecordType) type0;
}
case ANY: {
- throw new NotImplementedException();
+ return DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE;
}
case UNION: {
AUnionType u = (AUnionType) type0;
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/util/AsterixRuntimeUtil.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/util/AsterixRuntimeUtil.java
new file mode 100644
index 0000000..624d7eb
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/util/AsterixRuntimeUtil.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2009-2011 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.om.util;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import edu.uci.ics.asterix.common.api.AsterixAppContextInfoImpl;
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+
+public class AsterixRuntimeUtil {
+
+ public static Set<String> getNodeControllersOnIP(String ipAddress) throws AsterixException {
+ Map<String, Set<String>> nodeControllerInfo = AsterixAppContextInfoImpl.getNodeControllerMap();
+ Set<String> nodeControllersAtLocation = nodeControllerInfo.get(ipAddress);
+ return nodeControllersAtLocation;
+ }
+
+ public static Set<String> getNodeControllersOnHostName(String hostName) throws UnknownHostException {
+ Map<String, Set<String>> nodeControllerInfo = AsterixAppContextInfoImpl.getNodeControllerMap();
+ String address;
+ address = InetAddress.getByName(hostName).getHostAddress();
+ if (address.equals("127.0.1.1")) {
+ address = "127.0.0.1";
+ }
+ Set<String> nodeControllersAtLocation = nodeControllerInfo.get(address);
+ return nodeControllersAtLocation;
+ }
+
+ public static List<String> getAllNodeControllers() {
+
+ Collection<Set<String>> nodeControllersCollection = AsterixAppContextInfoImpl.getNodeControllerMap().values();
+ List<String> nodeControllers = new ArrayList<String>();
+ for (Set<String> ncCollection : nodeControllersCollection) {
+ nodeControllers.addAll(ncCollection);
+ }
+ return nodeControllers;
+ }
+}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/util/ResettableByteArrayOutputStream.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/util/ResettableByteArrayOutputStream.java
new file mode 100644
index 0000000..e47d417
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/util/ResettableByteArrayOutputStream.java
@@ -0,0 +1,15 @@
+package edu.uci.ics.asterix.om.util;
+
+import edu.uci.ics.hyracks.data.std.util.ByteArrayAccessibleOutputStream;
+
+/**
+ * This class extends ByteArrayAccessibleOutputStream to allow reset to a given
+ * size.
+ *
+ */
+public class ResettableByteArrayOutputStream extends ByteArrayAccessibleOutputStream {
+
+ public void reset(int size) {
+ count = size;
+ }
+}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/util/container/IObjectFactory.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/util/container/IObjectFactory.java
new file mode 100644
index 0000000..bf11b76
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/util/container/IObjectFactory.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2009-2010 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.uci.ics.asterix.om.util.container;
+
+/**
+ * A factory interface to create objects.
+ */
+public interface IObjectFactory<E, T> {
+
+ /**
+ * create an element of type E
+ *
+ * @param arg
+ * @return an E element
+ */
+ public E create(T arg);
+}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/util/container/IObjectPool.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/util/container/IObjectPool.java
new file mode 100644
index 0000000..4969cd5
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/util/container/IObjectPool.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2009-2010 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.uci.ics.asterix.om.util.container;
+
+/**
+ * A reusable object pool interface.
+ */
+public interface IObjectPool<E, T> {
+
+ /**
+ * Give client an E instance
+ *
+ * @param arg
+ * the argument to create E
+ * @return an E instance
+ */
+ public E allocate(T arg);
+
+ /**
+ * Mark all instances in the pool as unused
+ */
+ public void reset();
+}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/util/container/ListObjectPool.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/util/container/ListObjectPool.java
new file mode 100644
index 0000000..8d9057c
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/util/container/ListObjectPool.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2009-2010 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.uci.ics.asterix.om.util.container;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.List;
+
+/**
+ * Object pool backed by a list.
+ *
+ * The argument for creating E instances could be different. This class also
+ * considers arguments in object reusing, e.g., it reuses an E instances ONLY
+ * when the construction argument is "equal".
+ */
+public class ListObjectPool<E, T> implements IObjectPool<E, T> {
+
+ private IObjectFactory<E, T> factory;
+
+ /**
+ * cache of objects
+ */
+ private List<E> pool = new ArrayList<E>();
+
+ /**
+ * args that are used to create each element in the pool
+ */
+ private List<T> args = new ArrayList<T>();
+
+ /**
+ * bits indicating which element is in use
+ */
+ private BitSet usedBits = new BitSet();
+
+ public ListObjectPool(IObjectFactory<E, T> factory) {
+ this.factory = factory;
+ }
+
+ @Override
+ public E allocate(T arg) {
+ int freeSlot = -1;
+ while (freeSlot + 1 < pool.size()) {
+ freeSlot = usedBits.nextClearBit(freeSlot + 1);
+ if (freeSlot >= pool.size())
+ break;
+
+ // the two cases where an element in the pool is a match
+ if ((arg == null && args.get(freeSlot) == null)
+ || (arg != null && args.get(freeSlot) != null && arg.equals(args.get(freeSlot)))) {
+ // the element is not used and the arg is the same as
+ // input arg
+ usedBits.set(freeSlot);
+ return pool.get(freeSlot);
+ }
+ }
+
+ // if we do not find a reusable object, allocate a new one
+ E element = factory.create(arg);
+ pool.add(element);
+ args.add(arg);
+ usedBits.set(pool.size() - 1);
+ return element;
+ }
+
+ @Override
+ public void reset() {
+ usedBits.clear();
+ }
+}