You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by im...@apache.org on 2016/04/07 16:59:48 UTC
[13/50] [abbrv] incubator-asterixdb git commit: Merge branch 'master'
into hyracks-merge2
http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/8516517e/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/ClassAdParser.java
----------------------------------------------------------------------
diff --cc asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/ClassAdParser.java
index 5fd6f21,0000000..93b31ca
mode 100644,000000..100644
--- a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/ClassAdParser.java
+++ b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/ClassAdParser.java
@@@ -1,1728 -1,0 +1,1778 @@@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 at
+ *
+ * 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 org.apache.asterix.external.library;
+
+import java.io.DataOutput;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.BitSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.asterix.builders.AbvsBuilderFactory;
+import org.apache.asterix.builders.IARecordBuilder;
+import org.apache.asterix.builders.IAsterixListBuilder;
+import org.apache.asterix.builders.ListBuilderFactory;
+import org.apache.asterix.builders.OrderedListBuilder;
+import org.apache.asterix.builders.RecordBuilderFactory;
+import org.apache.asterix.builders.UnorderedListBuilder;
+import org.apache.asterix.common.exceptions.AsterixException;
+import org.apache.asterix.external.api.IRawRecord;
+import org.apache.asterix.external.api.IRecordDataParser;
+import org.apache.asterix.external.classad.AMutableCharArrayString;
+import org.apache.asterix.external.classad.AMutableNumberFactor;
+import org.apache.asterix.external.classad.AttributeReference;
+import org.apache.asterix.external.classad.CaseInsensitiveString;
+import org.apache.asterix.external.classad.CharArrayLexerSource;
+import org.apache.asterix.external.classad.ClassAd;
+import org.apache.asterix.external.classad.ExprList;
+import org.apache.asterix.external.classad.ExprTree;
+import org.apache.asterix.external.classad.ExprTree.NodeKind;
+import org.apache.asterix.external.classad.ExprTreeHolder;
+import org.apache.asterix.external.classad.FileLexerSource;
+import org.apache.asterix.external.classad.FunctionCall;
+import org.apache.asterix.external.classad.InputStreamLexerSource;
+import org.apache.asterix.external.classad.Lexer;
+import org.apache.asterix.external.classad.Lexer.TokenType;
+import org.apache.asterix.external.classad.LexerSource;
+import org.apache.asterix.external.classad.Literal;
+import org.apache.asterix.external.classad.Operation;
+import org.apache.asterix.external.classad.StringLexerSource;
+import org.apache.asterix.external.classad.TokenValue;
+import org.apache.asterix.external.classad.Value;
+import org.apache.asterix.external.classad.Value.NumberFactor;
+import org.apache.asterix.external.classad.object.pool.ClassAdObjectPool;
+import org.apache.asterix.external.parser.AbstractDataParser;
+import org.apache.asterix.om.base.ABoolean;
+import org.apache.asterix.om.base.AMutableInt32;
+import org.apache.asterix.om.types.AOrderedListType;
+import org.apache.asterix.om.types.ARecordType;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.AUnionType;
+import org.apache.asterix.om.types.AUnorderedListType;
+import org.apache.asterix.om.types.IAType;
+import org.apache.asterix.om.types.hierachy.ATypeHierarchy;
+import org.apache.asterix.om.util.NonTaggedFormatUtil;
+import org.apache.asterix.om.util.container.IObjectPool;
+import org.apache.asterix.om.util.container.ListObjectPool;
+import org.apache.commons.lang3.mutable.MutableBoolean;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.data.std.api.IMutableValueStorage;
+import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
+
+/// This reads ClassAd strings from various sources and converts them into a ClassAd.
+/// It can read from Strings, Files, and InputStreams.
+public class ClassAdParser extends AbstractDataParser implements IRecordDataParser<char[]> {
+
+ // reusable components
+ private Lexer lexer = new Lexer();
+ private LexerSource currentSource = null;
+ private boolean isExpr = false;
+ private final ClassAdObjectPool objectPool;
+ // asterix objects
+ private ARecordType recordType;
+ private IObjectPool<IARecordBuilder, ATypeTag> recordBuilderPool = new ListObjectPool<IARecordBuilder, ATypeTag>(
+ new RecordBuilderFactory());
+ private IObjectPool<IAsterixListBuilder, ATypeTag> listBuilderPool = new ListObjectPool<IAsterixListBuilder, ATypeTag>(
+ new ListBuilderFactory());
+ private IObjectPool<IMutableValueStorage, ATypeTag> abvsBuilderPool = new ListObjectPool<IMutableValueStorage, ATypeTag>(
+ new AbvsBuilderFactory());
+ private final ClassAd rootAd;
+ private String exprPrefix = "expr=";
+ private String exprSuffix = "";
+ private boolean evaluateExpr = true;
+ private String exprFieldNameSuffix = "Expr";
+ private boolean keepBoth = true;
+ private boolean oldFormat = true;
+ private StringLexerSource stringLexerSource = new StringLexerSource("");
+
+ public ClassAdParser(ARecordType recordType, boolean oldFormat, boolean evaluateExpr, boolean keepBoth,
+ String exprPrefix, String exprSuffix, String exprFieldNameSuffix, ClassAdObjectPool objectPool) {
+ if (objectPool == null) {
+ System.out.println();
+ }
+ this.objectPool = objectPool;
+ this.rootAd = new ClassAd(objectPool);
+ this.recordType = recordType;
+ this.currentSource = new CharArrayLexerSource();
+ this.recordType = recordType;
+ this.oldFormat = oldFormat;
+ if (oldFormat) {
+ rootAd.createParser();
+ }
+ this.keepBoth = keepBoth;
+ this.evaluateExpr = evaluateExpr;
+ this.exprPrefix = exprPrefix;
+ this.exprSuffix = exprSuffix;
+ this.exprFieldNameSuffix = exprFieldNameSuffix;
+ }
+
+ public ClassAdParser(ClassAdObjectPool objectPool) {
+ if (objectPool == null) {
+ System.out.println();
+ }
+ this.objectPool = objectPool;
+ this.currentSource = new CharArrayLexerSource();
+ rootAd = null;
+ }
+
+ /***********************************
+ * AsterixDB Specific begin
+ *
+ * @throws AsterixException
+ ***********************************/
+ public void asterixParse(ClassAd classad, DataOutput out) throws IOException, AsterixException {
+ // we assume the lexer source used here is a char array
+ parseClassAd(currentSource, classad, false);
+ parseRecord(null, classad, out);
+ }
+
+ public void handleErrorParsing() throws IOException {
+ }
+
+ private boolean asterixParseClassAd(ClassAd ad) throws IOException {
+ TokenType tt;
+ ad.clear();
+ lexer.initialize(currentSource);
+ if ((tt = lexer.consumeToken()) != TokenType.LEX_OPEN_BOX) {
+ handleErrorParsing();
+ return false;
+ }
+ tt = lexer.peekToken();
+ TokenValue tv = objectPool.tokenValuePool.get();
+ ExprTreeHolder tree = objectPool.mutableExprPool.get();
+ while (tt != TokenType.LEX_CLOSE_BOX) {
+ // Get the name of the expression
+ tv.reset();
+ tree.reset();
+ tt = lexer.consumeToken(tv);
+ if (tt == TokenType.LEX_SEMICOLON) {
+ // We allow empty expressions, so if someone give a double
+ // semicolon, it doesn't
+ // hurt. Technically it's not right, but we shouldn't make users
+ // pay the price for
+ // a meaningless mistake. See condor-support #1881 for a user
+ // that was bitten by this.
+ continue;
+ }
+ if (tt != TokenType.LEX_IDENTIFIER) {
+ throw new HyracksDataException(
+ "while parsing classad: expected LEX_IDENTIFIER " + " but got " + Lexer.strLexToken(tt));
+ }
+
+ // consume the intermediate '='
+ if ((tt = lexer.consumeToken()) != TokenType.LEX_BOUND_TO) {
+ throw new HyracksDataException(
+ "while parsing classad: expected LEX_BOUND_TO " + " but got " + Lexer.strLexToken(tt));
+ }
+
+ int positionBefore = lexer.getLexSource().getPosition();
+ isExpr = false;
+ // parse the expression
+ parseExpression(tree);
+ if (tree.getInnerTree() == null) {
+ handleErrorParsing();
+ throw new HyracksDataException("parse expression returned empty tree");
+ }
+
+ if ((!evaluateExpr || keepBoth) && isExpr && positionBefore >= 0) {
+ // we will store a string representation of the expression
- int len = lexer.getLexSource().getPosition() - positionBefore;
++ int len = lexer.getLexSource().getPosition() - positionBefore - 2;
+ // add it as it is to the classAd
+ Literal lit = objectPool.literalPool.get();
+ Value exprVal = objectPool.valuePool.get();
- exprVal.setStringValue(exprPrefix
- + String.valueOf(lexer.getLexSource().getBuffer(), positionBefore, len) + exprSuffix);
++
++ exprVal.setStringValue((exprPrefix == null ? "" : exprPrefix)
++ + String.valueOf(lexer.getLexSource().getBuffer(), positionBefore, len)
++ + (exprSuffix == null ? "" : exprSuffix));
+ Literal.createLiteral(lit, exprVal, NumberFactor.NO_FACTOR);
+ if (!evaluateExpr) {
+ ad.insert(tv.getStrValue().toString(), lit);
+ } else {
+ ad.insert(tv.getStrValue().toString() + exprFieldNameSuffix, lit);
+ }
+ }
+ if (!isExpr || (evaluateExpr)) {
+ // insert the attribute into the classad
+ if (!ad.insert(tv.getStrValue().toString(), tree)) {
+ handleErrorParsing();
+ throw new HyracksDataException("Couldn't insert value to classad");
+ }
+ }
+ // the next token must be a ';' or a ']'
+ tt = lexer.peekToken();
+ if (tt != TokenType.LEX_SEMICOLON && tt != TokenType.LEX_CLOSE_BOX) {
+ handleErrorParsing();
+ throw new HyracksDataException("while parsing classad: expected LEX_SEMICOLON or "
+ + "LEX_CLOSE_BOX but got " + Lexer.strLexToken(tt));
+ }
+
+ // Slurp up any extra semicolons. This does not duplicate the work
+ // at the top of the loop
+ // because it accounts for the case where the last expression has
+ // extra semicolons,
+ // while the first case accounts for optional beginning semicolons.
+ while (tt == TokenType.LEX_SEMICOLON) {
+ lexer.consumeToken();
+ tt = lexer.peekToken();
+ }
+ }
+ return true;
+ }
+
+ public static String readLine(char[] buffer, AMutableInt32 offset, int maxOffset) {
+ int position = offset.getIntegerValue();
+ while (buffer[position] != '\n' && position < maxOffset) {
+ position++;
+ }
+ if (offset.getIntegerValue() == position) {
+ return null;
+ }
+ String line = String.valueOf(buffer, offset.getIntegerValue(), position - offset.getIntegerValue());
+ position++;
+ offset.setValue(position);
+ return line;
+ }
+
+ private AMutableInt32 aInt32 = new AMutableInt32(0);
+
+ /**
+ * Resets the pools before parsing a top-level record. In this way the
+ * elements in those pools can be re-used.
+ */
+ private void resetPools() {
+ listBuilderPool.reset();
+ recordBuilderPool.reset();
+ abvsBuilderPool.reset();
+ objectPool.reset();
+ }
+
+ private ATypeTag getTargetTypeTag(ATypeTag expectedTypeTag, IAType aObjectType) throws IOException {
+ if (aObjectType == null) {
+ return expectedTypeTag;
+ }
+ if (aObjectType.getTypeTag() != ATypeTag.UNION) {
+ final ATypeTag typeTag = aObjectType.getTypeTag();
+ if (ATypeHierarchy.canPromote(expectedTypeTag, typeTag)
+ || ATypeHierarchy.canDemote(expectedTypeTag, typeTag)) {
+ return typeTag;
+ } else {
+ return null;
+ }
+ } else { // union
+ List<IAType> unionList = ((AUnionType) aObjectType).getUnionList();
+ for (IAType t : unionList) {
+ final ATypeTag typeTag = t.getTypeTag();
+ if (ATypeHierarchy.canPromote(expectedTypeTag, typeTag)
+ || ATypeHierarchy.canDemote(expectedTypeTag, typeTag)) {
+ return typeTag;
+ }
+ }
+ }
+ return null;
+ }
+
+ private void parseRecord(ARecordType recType, ClassAd pAd, DataOutput out) throws IOException, AsterixException {
+ ArrayBackedValueStorage fieldValueBuffer = getTempBuffer();
+ ArrayBackedValueStorage fieldNameBuffer = getTempBuffer();
+ IARecordBuilder recBuilder = getRecordBuilder();
+ BitSet nulls = null;
+ if (recType != null) {
+ nulls = getBitSet();
+ recBuilder.reset(recType);
+ } else {
+ recBuilder.reset(null);
+ }
+ recBuilder.init();
+ Boolean openRecordField = false;
+ int fieldId = 0;
+ IAType fieldType = null;
+
+ // new stuff
+ Map<CaseInsensitiveString, ExprTree> attrs = pAd.getAttrList();
+ for (Entry<CaseInsensitiveString, ExprTree> entry : attrs.entrySet()) {
+ // reset buffers
+ fieldNameBuffer.reset();
+ fieldValueBuffer.reset();
+ // take care of field name
+ String fldName = entry.getKey().get();
+ if (recType != null) {
+ fieldId = recBuilder.getFieldId(fldName);
+ if (fieldId < 0 && !recType.isOpen()) {
+ throw new HyracksDataException("This record is closed, you can not add extra fields !!");
+ } else if (fieldId < 0 && recType.isOpen()) {
+ aStringFieldName.setValue(fldName);
- if (aStringFieldName.getStringValue().contains("org.apache.asterix.external.classad.TokenValue")) {
- System.err.println("we have a problem");
- }
+ stringSerde.serialize(aStringFieldName, fieldNameBuffer.getDataOutput());
+ openRecordField = true;
+ fieldType = null;
+ } else {
+ // a closed field
+ nulls.set(fieldId);
+ fieldType = recType.getFieldTypes()[fieldId];
+ openRecordField = false;
+ }
+ } else {
+ aStringFieldName.setValue(fldName);
+ stringSerde.serialize(aStringFieldName, fieldNameBuffer.getDataOutput());
+ openRecordField = true;
+ fieldType = null;
+ }
+
+ // add field value to value buffer
+ writeFieldValueToBuffer(fieldType, fieldValueBuffer.getDataOutput(), fldName, entry.getValue(), pAd);
+ if (openRecordField) {
+ if (fieldValueBuffer.getByteArray()[0] != ATypeTag.NULL.serialize()) {
+ recBuilder.addField(fieldNameBuffer, fieldValueBuffer);
+ }
+ } else if (NonTaggedFormatUtil.isOptional(fieldType)) {
+ if (fieldValueBuffer.getByteArray()[0] != ATypeTag.NULL.serialize()) {
+ recBuilder.addField(fieldId, fieldValueBuffer);
+ }
+ } else {
+ recBuilder.addField(fieldId, fieldValueBuffer);
+ }
+ }
+
+ if (recType != null) {
+ int nullableFieldId = checkNullConstraints(recType, nulls);
+ if (nullableFieldId != -1) {
+ throw new HyracksDataException(
+ "Field: " + recType.getFieldNames()[nullableFieldId] + " can not be null");
+ }
+ }
+ recBuilder.write(out, true);
+ }
+
- // The only method left
+ private void writeFieldValueToBuffer(IAType fieldType, DataOutput out, String name, ExprTree tree, ClassAd pAd)
+ throws IOException, AsterixException {
+ Value val;
+ switch (tree.getKind()) {
+ case ATTRREF_NODE:
+ case CLASSAD_NODE:
+ case EXPR_ENVELOPE:
+ case EXPR_LIST_NODE:
+ case FN_CALL_NODE:
+ case OP_NODE:
+ val = objectPool.valuePool.get();
+ if (pAd.evaluateAttr(name, val)) {
-
+ } else {
+ // just write the expr
+ val = ((Literal) pAd.getAttrList().get(name + "Expr")).getValue();
+ }
+ break;
+ case LITERAL_NODE:
+ val = ((Literal) tree.getTree()).getValue();
+ break;
+ default:
+ throw new HyracksDataException("Unknown Expression type detected: " + tree.getKind());
+ }
+
+ switch (val.getValueType()) {
+ case ABSOLUTE_TIME_VALUE:
+ if (checkType(ATypeTag.DATETIME, fieldType)) {
+ parseDateTime(val, out);
+ } else {
+ throw new HyracksDataException(mismatchErrorMessage + fieldType.getTypeTag());
+ }
+ break;
+ case BOOLEAN_VALUE:
+ if (checkType(ATypeTag.BOOLEAN, fieldType)) {
+ booleanSerde.serialize(val.getBoolVal() ? ABoolean.TRUE : ABoolean.FALSE, out);
+ } else {
+ throw new HyracksDataException(mismatchErrorMessage + fieldType.getTypeTag());
+ }
+ break;
+ case CLASSAD_VALUE:
+ if (checkType(ATypeTag.RECORD, fieldType)) {
+ IAType objectType = getComplexType(fieldType, ATypeTag.RECORD);
+ ClassAd classad = val.getClassadVal();
+ parseRecord((ARecordType) objectType, classad, out);
+ } else {
+ throw new HyracksDataException(mismatchErrorMessage + fieldType.getTypeTag());
+ }
+ break;
+ case ERROR_VALUE:
+ case STRING_VALUE:
+ case UNDEFINED_VALUE:
+ if (checkType(ATypeTag.STRING, fieldType)) {
+ parseString(val, out);
+ } else {
+ throw new HyracksDataException(mismatchErrorMessage + fieldType.getTypeTag());
+ }
+ break;
+ case INTEGER_VALUE:
+ if (checkType(ATypeTag.INT64, fieldType)) {
- aInt64.setValue(val.getLongVal());
- int64Serde.serialize(aInt64, out);
++ if (fieldType == null || fieldType.getTypeTag() == ATypeTag.INT64) {
++ aInt64.setValue(val.getLongVal());
++ int64Serde.serialize(aInt64, out);
++ } else if (fieldType.getTypeTag() == ATypeTag.INT32) {
++ aInt32.setValue((int) val.getLongVal());
++ int32Serde.serialize(aInt32, out);
++ } else if (fieldType.getTypeTag() == ATypeTag.DOUBLE) {
++ aDouble.setValue(val.getLongVal());
++ doubleSerde.serialize(aDouble, out);
++ } else if (fieldType.getTypeTag() == ATypeTag.INT16) {
++ aInt16.setValue((short) val.getLongVal());
++ int16Serde.serialize(aInt16, out);
++ } else if (fieldType.getTypeTag() == ATypeTag.INT8) {
++ aInt8.setValue((byte) val.getLongVal());
++ int8Serde.serialize(aInt8, out);
++ } else if (fieldType.getTypeTag() == ATypeTag.FLOAT) {
++ aFloat.setValue(val.getLongVal());
++ floatSerde.serialize(aFloat, out);
++ }
++ } else if (checkType(ATypeTag.DATETIME, fieldType)) {
++ // Classad uses Linux Timestamps (s instead of ms)
++ aDateTime.setValue(val.getLongVal() * 1000);
++ datetimeSerde.serialize(aDateTime, out);
++ } else if (checkType(ATypeTag.DURATION, fieldType)) {
++ // Classad uses Linux Timestamps (s instead of ms)
++ aDuration.setValue(0, val.getLongVal() * 1000);
++ durationSerde.serialize(aDuration, out);
++ } else if (checkType(ATypeTag.INT32, fieldType)) {
++ aInt32.setValue((int) val.getLongVal());
++ int32Serde.serialize(aInt32, out);
+ } else if (checkType(ATypeTag.DOUBLE, fieldType)) {
+ aDouble.setValue(val.getLongVal());
+ doubleSerde.serialize(aDouble, out);
+ } else {
+ throw new HyracksDataException(mismatchErrorMessage + fieldType.getTypeTag());
+ }
+ break;
+ case LIST_VALUE:
+ case SLIST_VALUE:
+ IAType objectType;
+ if (checkType(ATypeTag.UNORDEREDLIST, fieldType)) {
+ objectType = getComplexType(fieldType, ATypeTag.UNORDEREDLIST);
+ parseUnorderedList((AUnorderedListType) objectType, val, out);
+ } else if (checkType(ATypeTag.ORDEREDLIST, fieldType)) {
+ objectType = getComplexType(fieldType, ATypeTag.ORDEREDLIST);
+ parseOrderedList((AOrderedListType) objectType, val, out);
+ } else {
+ throw new HyracksDataException(mismatchErrorMessage + fieldType.getTypeTag());
+ }
+ break;
+ case REAL_VALUE:
+ if (checkType(ATypeTag.DOUBLE, fieldType)) {
- aDouble.setValue(val.getDoubleVal());
- doubleSerde.serialize(aDouble, out);
++ if (fieldType == null || fieldType.getTypeTag() == ATypeTag.DOUBLE) {
++ aDouble.setValue(val.getDoubleVal());
++ doubleSerde.serialize(aDouble, out);
++ } else if (fieldType.getTypeTag() == ATypeTag.INT32) {
++ aInt32.setValue((int) val.getDoubleVal());
++ int32Serde.serialize(aInt32, out);
++ } else if (fieldType.getTypeTag() == ATypeTag.INT64) {
++ aInt64.setValue((long) val.getDoubleVal());
++ int64Serde.serialize(aInt64, out);
++ } else if (fieldType.getTypeTag() == ATypeTag.INT16) {
++ aInt16.setValue((short) val.getDoubleVal());
++ int16Serde.serialize(aInt16, out);
++ } else if (fieldType.getTypeTag() == ATypeTag.INT8) {
++ aInt8.setValue((byte) val.getDoubleVal());
++ int8Serde.serialize(aInt8, out);
++ } else if (fieldType.getTypeTag() == ATypeTag.FLOAT) {
++ aFloat.setValue((float) val.getDoubleVal());
++ floatSerde.serialize(aFloat, out);
++ }
+ } else if (checkType(ATypeTag.INT32, fieldType)) {
+ aInt32.setValue((int) val.getDoubleVal());
+ int32Serde.serialize(aInt32, out);
+ } else if (checkType(ATypeTag.INT64, fieldType)) {
+ aInt64.setValue((long) val.getDoubleVal());
+ int64Serde.serialize(aInt64, out);
++ } else if (checkType(ATypeTag.DATETIME, fieldType)) {
++ // Classad uses Linux Timestamps (s instead of ms)
++ aDateTime.setValue(val.getLongVal() * 1000);
++ datetimeSerde.serialize(aDateTime, out);
++ } else if (checkType(ATypeTag.DURATION, fieldType)) {
++ // Classad uses Linux Timestamps (s instead of ms)
++ aDuration.setValue(0, (long) (val.getDoubleVal() * 1000.0));
++ durationSerde.serialize(aDuration, out);
+ } else {
+ throw new HyracksDataException(mismatchErrorMessage + fieldType.getTypeTag());
+ }
+ break;
+ case RELATIVE_TIME_VALUE:
+ if (checkType(ATypeTag.DURATION, fieldType)) {
+ parseDuration(val, out);
+ } else {
+ throw new HyracksDataException(mismatchErrorMessage + fieldType.getTypeTag());
+ }
+ break;
+ default:
+ throw new HyracksDataException("unknown data type " + val.getValueType());
+ }
+ }
+
+ private void parseOrderedList(AOrderedListType oltype, Value listVal, DataOutput out)
+ throws IOException, AsterixException {
+ ArrayBackedValueStorage itemBuffer = getTempBuffer();
+ OrderedListBuilder orderedListBuilder = (OrderedListBuilder) getOrderedListBuilder();
+ IAType itemType = null;
+ if (oltype != null) {
+ itemType = oltype.getItemType();
+ }
+ orderedListBuilder.reset(oltype);
+ for (ExprTree tree : listVal.getListVal().getExprList()) {
+ itemBuffer.reset();
+ writeFieldValueToBuffer(itemType, itemBuffer.getDataOutput(), null, tree, null);
+ orderedListBuilder.addItem(itemBuffer);
+ }
+ orderedListBuilder.write(out, true);
+ }
+
+ private void parseUnorderedList(AUnorderedListType uoltype, Value listVal, DataOutput out)
+ throws IOException, AsterixException {
+ ArrayBackedValueStorage itemBuffer = getTempBuffer();
+ UnorderedListBuilder unorderedListBuilder = (UnorderedListBuilder) getUnorderedListBuilder();
+ IAType itemType = null;
+ if (uoltype != null) {
+ itemType = uoltype.getItemType();
+ }
+ unorderedListBuilder.reset(uoltype);
+ for (ExprTree tree : listVal.getListVal().getExprList()) {
+ itemBuffer.reset();
+ writeFieldValueToBuffer(itemType, itemBuffer.getDataOutput(), null, tree, null);
+ unorderedListBuilder.addItem(itemBuffer);
+ }
+ unorderedListBuilder.write(out, true);
+ }
+
+ private void parseString(Value val, DataOutput out) throws HyracksDataException {
+ switch (val.getValueType()) {
+ case ERROR_VALUE:
+ aString.setValue("error");
+ break;
+ case STRING_VALUE:
+ aString.setValue(val.getStringVal());
+ break;
+ case UNDEFINED_VALUE:
+ aString.setValue("undefined");
+ break;
+ default:
+ throw new HyracksDataException("Unknown String type " + val.getValueType());
+ }
+ stringSerde.serialize(aString, out);
+ }
+
+ protected void parseDuration(Value duration, DataOutput out) throws HyracksDataException {
+ try {
+ aDuration.setValue(0, duration.getTimeVal().getRelativeTime());
+ durationSerde.serialize(aDuration, out);
+ } catch (Exception e) {
+ throw new HyracksDataException(e);
+ }
+ }
+
+ protected void parseDateTime(Value datetime, DataOutput out) throws HyracksDataException {
+ aDateTime.setValue(datetime.getTimeVal().getTimeInMillis());
+ datetimeSerde.serialize(aDateTime, out);
+ }
+
+ public static IAType getComplexType(IAType aObjectType, ATypeTag tag) {
+ if (aObjectType == null) {
+ return null;
+ }
+
+ if (aObjectType.getTypeTag() == tag) {
+ return aObjectType;
+ }
+
+ if (aObjectType.getTypeTag() == ATypeTag.UNION) {
+ List<IAType> unionList = ((AUnionType) aObjectType).getUnionList();
+ for (int i = 0; i < unionList.size(); i++) {
+ if (unionList.get(i).getTypeTag() == tag) {
+ return unionList.get(i);
+ }
+ }
+ }
+ return null; // wont get here
+ }
+
+ private String mismatchErrorMessage = "Mismatch Type, expecting a value of type ";
+
+ private boolean checkType(ATypeTag expectedTypeTag, IAType aObjectType) throws IOException {
+ return getTargetTypeTag(expectedTypeTag, aObjectType) != null;
+ }
+
+ private BitSet getBitSet() {
+ return objectPool.bitSetPool.get();
+ }
+
+ public static int checkNullConstraints(ARecordType recType, BitSet nulls) {
+ boolean isNull = false;
+ for (int i = 0; i < recType.getFieldTypes().length; i++) {
+ if (nulls.get(i) == false) {
+ IAType type = recType.getFieldTypes()[i];
+ if (type.getTypeTag() != ATypeTag.NULL && type.getTypeTag() != ATypeTag.UNION) {
+ return i;
+ }
+
+ if (type.getTypeTag() == ATypeTag.UNION) { // union
+ List<IAType> unionList = ((AUnionType) type).getUnionList();
+ for (int j = 0; j < unionList.size(); j++) {
+ if (unionList.get(j).getTypeTag() == ATypeTag.NULL) {
+ isNull = true;
+ break;
+ }
+ }
+ if (!isNull) {
+ return i;
+ }
+ }
+ }
+ }
+ return -1;
+ }
+
+ private IARecordBuilder getRecordBuilder() {
+ return recordBuilderPool.allocate(ATypeTag.RECORD);
+ }
+
+ private IAsterixListBuilder getOrderedListBuilder() {
+ return listBuilderPool.allocate(ATypeTag.ORDEREDLIST);
+ }
+
+ private IAsterixListBuilder getUnorderedListBuilder() {
+ return listBuilderPool.allocate(ATypeTag.UNORDEREDLIST);
+ }
+
+ private ArrayBackedValueStorage getTempBuffer() {
+ return (ArrayBackedValueStorage) abvsBuilderPool.allocate(ATypeTag.BINARY);
+ }
+
+ public static ATypeTag getMatchingType(Literal lit) throws HyracksDataException {
+ return getMatchingType(lit.getValue());
+ }
+
+ public static ATypeTag getMatchingType(Value val) throws HyracksDataException {
+ switch (val.getValueType()) {
+ case ABSOLUTE_TIME_VALUE:
+ return ATypeTag.DATETIME;
+ case BOOLEAN_VALUE:
+ return ATypeTag.BOOLEAN;
+ case CLASSAD_VALUE:
+ return ATypeTag.RECORD;
+ case ERROR_VALUE:
+ case STRING_VALUE:
+ case UNDEFINED_VALUE:
+ return ATypeTag.STRING;
+ case INTEGER_VALUE:
+ return ATypeTag.INT64;
+ case LIST_VALUE:
+ case SLIST_VALUE:
+ return ATypeTag.UNORDEREDLIST;
+ case NULL_VALUE:
+ return ATypeTag.NULL;
+ case REAL_VALUE:
+ return ATypeTag.DOUBLE;
+ case RELATIVE_TIME_VALUE:
+ return ATypeTag.DURATION;
+ default:
+ throw new HyracksDataException("Unknown data type");
+ }
+ }
+
+ /********************************
+ * End of AsterixDB specifics
+ ********************************/
+
+ /**
+ * Parse a ClassAd
+ *
+ * @param buffer
+ * Buffer containing the string representation of the classad.
+ * @param full
+ * If this parameter is true, the parse is considered to succeed
+ * only if the ClassAd was parsed successfully and no other
+ * tokens follow the ClassAd.
+ * @return pointer to the ClassAd object if successful, or null otherwise
+ * @throws IOException
+ */
+ public ClassAd parseClassAd(String buffer, boolean full) throws IOException {
+ currentSource = new StringLexerSource(buffer);
+ return parseClassAd(currentSource, full);
+ }
+
+ public ClassAd parseClassAd(String buffer, AMutableInt32 offset) throws IOException {
+ currentSource = new StringLexerSource(buffer);
+ ClassAd ad = parseClassAd((StringLexerSource) currentSource);
+ offset.setValue(((StringLexerSource) currentSource).getCurrentLocation());
+ return ad;
+ }
+
+ public ClassAd parseClassAd(StringLexerSource lexer_source) throws IOException {
+ return parseClassAd(lexer_source, false);
+ }
+
+ public ClassAd parseClassAd(File file, boolean full) throws IOException {
+ FileLexerSource fileLexerSource = new FileLexerSource(file);
+ return parseClassAd(fileLexerSource, full);
+ }
+
+ public ClassAd parseClassAd(InputStream in, boolean full) throws IOException {
+ InputStreamLexerSource lexer_source = new InputStreamLexerSource(in);
+ return parseClassAd(lexer_source, full);
+ }
+
+ // preferred method since the parser doesn't need to create an object
+ public void parseClassAd(ClassAd ad, LexerSource lexer_source, boolean full) throws IOException {
+ ad.reset();
+ if (lexer.initialize(lexer_source)) {
+ if (!parseClassAd(ad, full)) {
+ return;
+ } else if (lexer_source.readPreviousCharacter() != '\0') {
+ // The lexer swallows one extra character, so if we have
+ // two classads back to back we need to make sure to unread
+ // one of the characters.
+ lexer_source.unreadCharacter();
+ }
+ }
+ }
+
+ public ClassAd parseClassAd(LexerSource lexer_source, boolean full) throws IOException {
+ System.out.println("Don't use this call. instead, pass a mutable classad instance");
+ ClassAd ad = objectPool.classAdPool.get();
+ if (lexer.initialize(lexer_source)) {
+ if (!parseClassAd(ad, full)) {
+ return null;
+ } else if (lexer_source.readPreviousCharacter() != '\0') {
+ // The lexer swallows one extra character, so if we have
+ // two classads back to back we need to make sure to unread
+ // one of the characters.
+ lexer_source.unreadCharacter();
+ }
+ }
+ return ad;
+ }
+
+ /**
+ * Parse a ClassAd
+ *
+ * @param buffer
+ * Buffer containing the string representation of the classad.
+ * @param ad
+ * The classad to be populated
+ * @param full
+ * If this parameter is true, the parse is considered to succeed
+ * only if the ClassAd was parsed successfully and no other
+ * tokens follow the ClassAd.
+ * @return true on success, false on failure
+ * @throws IOException
+ */
+ public boolean parseClassAd(String buffer, ClassAd classad, boolean full) throws IOException {
+ StringLexerSource stringLexerSource = new StringLexerSource(buffer);
+ return parseClassAd(stringLexerSource, classad, full);
+ }
+
+ public boolean parseClassAd(String buffer, ClassAd classad, AMutableInt32 offset) throws IOException {
+ boolean success = false;
+ StringLexerSource stringLexerSource = new StringLexerSource(buffer, offset.getIntegerValue().intValue());
+ success = parseClassAd(stringLexerSource, classad);
+ offset.setValue(stringLexerSource.getCurrentLocation());
+ return success;
+ }
+
+ public boolean parseNext(ClassAd classad) throws IOException {
+ return parseClassAd(currentSource, classad, false);
+ }
+
+ public boolean parseNext(ClassAd classad, boolean full) throws IOException {
+ return parseClassAd(currentSource, classad, full);
+ }
+
+ private boolean parseClassAd(StringLexerSource lexer_source, ClassAd classad) throws IOException {
+ return parseClassAd(lexer_source, classad, false);
+ }
+
+ public boolean parseClassAd(File file, ClassAd classad, boolean full) throws IOException {
+ FileLexerSource fileLexerSource = new FileLexerSource(file);
+ return parseClassAd(fileLexerSource, classad, full);
+ }
+
+ public boolean parseClassAd(InputStream stream, ClassAd classad, boolean full) throws IOException {
+ InputStreamLexerSource inputStreamLexerSource = new InputStreamLexerSource(stream);
+ return parseClassAd(inputStreamLexerSource, classad, full);
+ }
+
+ public boolean parseClassAd(LexerSource lexer_source, ClassAd classad, boolean full) throws IOException {
+ boolean success = false;
+ if (lexer.initialize(lexer_source)) {
+ success = parseClassAd(classad, full);
+ }
+ if (success) {
+ // The lexer swallows one extra character, so if we have
+ // two classads back to back we need to make sure to unread
+ // one of the characters.
+ if (lexer_source.readPreviousCharacter() != Lexer.EOF) {
+ lexer_source.unreadCharacter();
+ }
+ } else {
+ classad.clear();
+ }
+ return success;
+ }
+
+ /**
+ * Parse an expression
+ *
+ * @param buffer
+ * Buffer containing the string representation of the expression.
+ * @param full
+ * If this parameter is true, the parse is considered to succeed
+ * only if the expression was parsed successfully and no other
+ * tokens are left.
+ * @return pointer to the expression object if successful, or null otherwise
+ */
+ public ExprTree parseExpression(String buffer, boolean full) throws IOException {
+ stringLexerSource.setNewSource(buffer);
+ ExprTreeHolder mutableExpr = objectPool.mutableExprPool.get();
+ if (lexer.initialize(stringLexerSource)) {
+ parseExpression(mutableExpr, full);
+ }
+ return mutableExpr.getInnerTree();
+ }
+
+ public ExprTree ParseExpression(String buffer) throws IOException {
+ return parseExpression(buffer, false);
+ }
+
+ public ExprTree parseExpression(LexerSource lexer_source, boolean full) throws IOException {
+ ExprTreeHolder mutableExpr = objectPool.mutableExprPool.get();
+ if (lexer.initialize(lexer_source)) {
+ parseExpression(mutableExpr, full);
+ }
+ return mutableExpr.getInnerTree();
+ }
+
+ public ExprTree parseNextExpression() throws IOException {
+ if (!lexer.wasInitialized()) {
+ return null;
+ } else {
+ ExprTreeHolder expr = objectPool.mutableExprPool.get();
+ parseExpression(expr, false);
+ ExprTree innerTree = expr.getInnerTree();
+ return innerTree;
+ }
+ }
+
+ /*--------------------------------------------------------------------
+ *
+ * Private Functions
+ *
+ *-------------------------------------------------------------------*/
+
+ // Expression .= LogicalORExpression
+ // | LogicalORExpression '?' Expression ':' Expression
+
+ private boolean parseExpression(ExprTreeHolder tree) throws IOException {
+ return parseExpression(tree, false);
+ }
+
+ private boolean parseExpression(ExprTreeHolder tree, boolean full) throws IOException {
+ TokenType tt;
+ if (!parseLogicalORExpression(tree)) {
+ return false;
+ }
+ if ((tt = lexer.peekToken()) == TokenType.LEX_QMARK) {
+ lexer.consumeToken();
+ ExprTreeHolder treeL = tree;
+ ExprTreeHolder treeM = objectPool.mutableExprPool.get();
+ ExprTreeHolder treeR = objectPool.mutableExprPool.get();
+ parseExpression(treeM);
+ if ((tt = lexer.consumeToken()) != TokenType.LEX_COLON) {
+ throw new HyracksDataException("expected LEX_COLON, but got " + Lexer.strLexToken(tt));
+ }
+ parseExpression(treeR);
+ if (treeL.getInnerTree() != null && treeM.getInnerTree() != null && treeR.getInnerTree() != null) {
+ Operation newTree = objectPool.operationPool.get();
+ Operation.createOperation(Operation.OpKind_TERNARY_OP, treeL, treeM, treeR, newTree);
+ tree.setInnerTree(newTree);
+ return (true);
+ }
+ tree.setInnerTree(null);
+ return false;
+ }
+ // if a full parse was requested, ensure that input is exhausted
+ if (full && (lexer.consumeToken() != TokenType.LEX_END_OF_INPUT)) {
+ throw new HyracksDataException(
+ "expected LEX_END_OF_INPUT on full parse, but got " + String.valueOf(Lexer.strLexToken(tt)));
+ }
+ return true;
+ }
+
+ // LogicalORExpression .= LogicalANDExpression
+ // | LogicalORExpression '||' LogicalANDExpression
+
+ private boolean parseLogicalORExpression(ExprTreeHolder tree) throws IOException {
+ if (!parseLogicalANDExpression(tree)) {
+ return false;
+ }
+ while ((lexer.peekToken()) == TokenType.LEX_LOGICAL_OR) {
+ ExprTreeHolder treeL = tree;
+ ExprTreeHolder treeR = objectPool.mutableExprPool.get();
+ lexer.consumeToken();
+ parseLogicalANDExpression(treeR);
+ if (treeL.getInnerTree() != null && treeR.getInnerTree() != null) {
+ Operation newTree = objectPool.operationPool.get();
+ Operation.createOperation(Operation.OpKind_LOGICAL_OR_OP, treeL, treeR, null, newTree);
+ tree.setInnerTree(newTree);
+ } else {
+ tree.setInnerTree(null);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // LogicalANDExpression .= InclusiveORExpression
+ // | LogicalANDExpression '&&' InclusiveORExpression
+ private boolean parseLogicalANDExpression(ExprTreeHolder tree) throws IOException {
+ if (!parseInclusiveORExpression(tree)) {
+ return false;
+ }
+ while ((lexer.peekToken()) == TokenType.LEX_LOGICAL_AND) {
+ ExprTreeHolder treeL = tree;
+ ExprTreeHolder treeR = objectPool.mutableExprPool.get();
+ lexer.consumeToken();
+ parseInclusiveORExpression(treeR);
+ if (treeL.getInnerTree() != null && treeR.getInnerTree() != null) {
+ Operation newTree = objectPool.operationPool.get();
+ Operation.createOperation(Operation.OpKind_LOGICAL_AND_OP, treeL, treeR, null, newTree);
+ tree.setInnerTree(newTree);
+ } else {
+ tree.setInnerTree(null);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // InclusiveORExpression .= ExclusiveORExpression
+ // | InclusiveORExpression '|' ExclusiveORExpression
+ public boolean parseInclusiveORExpression(ExprTreeHolder tree) throws IOException {
+ if (!parseExclusiveORExpression(tree)) {
+ return false;
+ }
+ while ((lexer.peekToken()) == TokenType.LEX_BITWISE_OR) {
+ ExprTreeHolder treeL = tree;
+ ExprTreeHolder treeR = objectPool.mutableExprPool.get();
+ lexer.consumeToken();
+ parseExclusiveORExpression(treeR);
+ if (treeL.getInnerTree() != null && treeR.getInnerTree() != null) {
+ Operation newTree = objectPool.operationPool.get();
+ Operation.createOperation(Operation.OpKind_BITWISE_OR_OP, treeL, treeR, null, newTree);
+ tree.setInnerTree(newTree);
+ } else {
+ tree.setInnerTree(null);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // ExclusiveORExpression .= ANDExpression
+ // | ExclusiveORExpression '^' ANDExpression
+ private boolean parseExclusiveORExpression(ExprTreeHolder tree) throws IOException {
+ if (!parseANDExpression(tree)) {
+ return false;
+ }
+ while ((lexer.peekToken()) == TokenType.LEX_BITWISE_XOR) {
+ lexer.consumeToken();
+ ExprTreeHolder treeL = tree;
+ ExprTreeHolder treeR = objectPool.mutableExprPool.get();
+ parseANDExpression(treeR);
+ if (treeL.getInnerTree() != null && treeR.getInnerTree() != null) {
+ Operation newTree = objectPool.operationPool.get();
+ Operation.createOperation(Operation.OpKind_BITWISE_XOR_OP, treeL, treeR, null, newTree);
+ tree.setInnerTree(newTree);
+ } else {
+ tree.setInnerTree(null);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // ANDExpression .= EqualityExpression
+ // | ANDExpression '&' EqualityExpression
+ private boolean parseANDExpression(ExprTreeHolder tree) throws IOException {
+ if (!parseEqualityExpression(tree)) {
+ return false;
+ }
+ while ((lexer.peekToken()) == TokenType.LEX_BITWISE_AND) {
+ ExprTreeHolder treeL = tree;
+ ExprTreeHolder treeR = objectPool.mutableExprPool.get();
+ lexer.consumeToken();
+ parseEqualityExpression(treeR);
+ if (treeL.getInnerTree() != null && treeR.getInnerTree() != null) {
+ Operation newTree = objectPool.operationPool.get();
+ Operation.createOperation(Operation.OpKind_BITWISE_AND_OP, treeL, treeR, null, newTree);
+ tree.setInnerTree(newTree);
+ } else {
+ tree.setInnerTree(null);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // EqualityExpression .= RelationalExpression
+ // | EqualityExpression '==' RelationalExpression
+ // | EqualityExpression '!=' RelationalExpression
+ // | EqualityExpression '=?=' RelationalExpression
+ // | EqualityExpression '=!=' RelationalExpression
+ private boolean parseEqualityExpression(ExprTreeHolder tree) throws IOException {
+ TokenType tt;
+ int op = Operation.OpKind_NO_OP;
+ if (!parseRelationalExpression(tree)) {
+ return false;
+ }
+ tt = lexer.peekToken();
+ while (tt == TokenType.LEX_EQUAL || tt == TokenType.LEX_NOT_EQUAL || tt == TokenType.LEX_META_EQUAL
+ || tt == TokenType.LEX_META_NOT_EQUAL) {
+ ExprTreeHolder treeL = tree;
+ ExprTreeHolder treeR = objectPool.mutableExprPool.get();
+ lexer.consumeToken();
+ parseRelationalExpression(treeR);
+ switch (tt) {
+ case LEX_EQUAL:
+ op = Operation.OpKind_EQUAL_OP;
+ break;
+ case LEX_NOT_EQUAL:
+ op = Operation.OpKind_NOT_EQUAL_OP;
+ break;
+ case LEX_META_EQUAL:
+ op = Operation.OpKind_META_EQUAL_OP;
+ break;
+ case LEX_META_NOT_EQUAL:
+ op = Operation.OpKind_META_NOT_EQUAL_OP;
+ break;
+ default:
+ throw new HyracksDataException("ClassAd: Should not reach here");
+ }
+ if (treeL.getInnerTree() != null && treeR.getInnerTree() != null) {
+ Operation newTree = objectPool.operationPool.get();
+ Operation.createOperation(op, treeL, treeR, null, newTree);
+ tree.setInnerTree(newTree);
+ } else {
+ tree.setInnerTree(null);
+ return false;
+ }
+ tt = lexer.peekToken();
+ }
+ return true;
+ }
+
+ // RelationalExpression .= ShiftExpression
+ // | RelationalExpression '<' ShiftExpression
+ // | RelationalExpression '>' ShiftExpression
+ // | RelationalExpression '<=' ShiftExpression
+ // | RelationalExpression '>=' ShiftExpression
+ private boolean parseRelationalExpression(ExprTreeHolder tree) throws IOException {
+ TokenType tt;
+ if (!parseShiftExpression(tree)) {
+ return false;
+ }
+ tt = lexer.peekToken();
+ while (tt == TokenType.LEX_LESS_THAN || tt == TokenType.LEX_GREATER_THAN || tt == TokenType.LEX_LESS_OR_EQUAL
+ || tt == TokenType.LEX_GREATER_OR_EQUAL) {
+ int op = Operation.OpKind_NO_OP;
+ ExprTreeHolder treeL = tree;
+ ExprTreeHolder treeR = objectPool.mutableExprPool.get();
+ lexer.consumeToken();
+ parseShiftExpression(treeR);
+ switch (tt) {
+ case LEX_LESS_THAN:
+ op = Operation.OpKind_LESS_THAN_OP;
+ break;
+ case LEX_LESS_OR_EQUAL:
+ op = Operation.OpKind_LESS_OR_EQUAL_OP;
+ break;
+ case LEX_GREATER_THAN:
+ op = Operation.OpKind_GREATER_THAN_OP;
+ break;
+ case LEX_GREATER_OR_EQUAL:
+ op = Operation.OpKind_GREATER_OR_EQUAL_OP;
+ break;
+ default:
+ throw new HyracksDataException("ClassAd: Should not reach here");
+ }
+ if (treeL.getInnerTree() != null && treeR.getInnerTree() != null) {
+ Operation newTree = objectPool.operationPool.get();
+ Operation.createOperation(op, treeL, treeR, null, newTree);
+ tree.setInnerTree(newTree);
+ } else {
+ tree.setInnerTree(null);
+ return false;
+ }
+ tt = lexer.peekToken();
+ }
+ return true;
+ }
+
+ // ShiftExpression .= AdditiveExpression
+ // | ShiftExpression '<<' AdditiveExpression
+ // | ShiftExpression '>>' AdditiveExpression
+ // | ShiftExpression '>>>' AditiveExpression
+ private boolean parseShiftExpression(ExprTreeHolder tree) throws IOException {
+ if (!parseAdditiveExpression(tree)) {
+ return false;
+ }
+
+ TokenType tt = lexer.peekToken();
+ while (tt == TokenType.LEX_LEFT_SHIFT || tt == TokenType.LEX_RIGHT_SHIFT || tt == TokenType.LEX_URIGHT_SHIFT) {
+ ExprTreeHolder treeL = tree;
+ ExprTreeHolder treeR = objectPool.mutableExprPool.get();
+ int op;
+ lexer.consumeToken();
+ parseAdditiveExpression(treeR);
+ switch (tt) {
+ case LEX_LEFT_SHIFT:
+ op = Operation.OpKind_LEFT_SHIFT_OP;
+ break;
+ case LEX_RIGHT_SHIFT:
+ op = Operation.OpKind_RIGHT_SHIFT_OP;
+ break;
+ case LEX_URIGHT_SHIFT:
+ op = Operation.OpKind_URIGHT_SHIFT_OP;
+ break;
+ default:
+ op = Operation.OpKind_NO_OP; // Make gcc's -wuninitalized happy
+ throw new HyracksDataException("ClassAd: Should not reach here");
+ }
+
+ if (treeL.getInnerTree() != null && treeR.getInnerTree() != null) {
+ Operation newTree = objectPool.operationPool.get();
+ Operation.createOperation(op, treeL, treeR, null, newTree);
+ tree.setInnerTree(newTree);
+ } else {
+ tree.setInnerTree(null);
+ return false;
+ }
+ tt = lexer.peekToken();
+ }
+ return true;
+ }
+
+ // AdditiveExpression .= MultiplicativeExpression
+ // | AdditiveExpression '+' MultiplicativeExpression
+ // | AdditiveExpression '-' MultiplicativeExpression
+ private boolean parseAdditiveExpression(ExprTreeHolder tree) throws IOException {
+ if (!parseMultiplicativeExpression(tree)) {
+ return false;
+ }
+
+ TokenType tt = lexer.peekToken();
+ while (tt == TokenType.LEX_PLUS || tt == TokenType.LEX_MINUS) {
+ ExprTreeHolder treeL = tree;
+ ExprTreeHolder treeR = objectPool.mutableExprPool.get();
+ lexer.consumeToken();
+ parseMultiplicativeExpression(treeR);
+ if (treeL.getInnerTree() != null && treeR.getInnerTree() != null) {
+ Operation newTree = objectPool.operationPool.get();
+ Operation.createOperation(
+ (tt == TokenType.LEX_PLUS) ? Operation.OpKind_ADDITION_OP : Operation.OpKind_SUBTRACTION_OP,
+ treeL, treeR, null, newTree);
+ tree.setInnerTree(newTree);
+ } else {
+ tree.setInnerTree(null);
+ return false;
+ }
+ tt = lexer.peekToken();
+ }
+ return true;
+ }
+
+ // MultiplicativeExpression .= UnaryExpression
+ // | MultiplicativeExpression '*' UnaryExpression
+ // | MultiplicativeExpression '/' UnaryExpression
+ // | MultiplicativeExpression '%' UnaryExpression
+ private boolean parseMultiplicativeExpression(ExprTreeHolder tree) throws IOException {
+ if (!parseUnaryExpression(tree)) {
+ return false;
+ }
+
+ TokenType tt = lexer.peekToken();
+ while (tt == TokenType.LEX_MULTIPLY || tt == TokenType.LEX_DIVIDE || tt == TokenType.LEX_MODULUS) {
+ ExprTreeHolder treeL = tree;
+ ExprTreeHolder treeR = objectPool.mutableExprPool.get();
+ int op;
+ lexer.consumeToken();
+ parseUnaryExpression(treeR);
+ switch (tt) {
+ case LEX_MULTIPLY:
+ op = Operation.OpKind_MULTIPLICATION_OP;
+ break;
+ case LEX_DIVIDE:
+ op = Operation.OpKind_DIVISION_OP;
+ break;
+ case LEX_MODULUS:
+ op = Operation.OpKind_MODULUS_OP;
+ break;
+ default:
+ op = Operation.OpKind_NO_OP; // Make gcc's -wuninitalized happy
+ throw new HyracksDataException("ClassAd: Should not reach here");
+ }
+ if (treeL.getInnerTree() != null && treeR.getInnerTree() != null) {
+ Operation newTree = objectPool.operationPool.get();
+ Operation.createOperation(op, treeL, treeR, null, newTree);
+ tree.setInnerTree(newTree);
+ } else {
+ tree.setInnerTree(null);
+ return false;
+ }
+ tt = lexer.peekToken();
+ }
+ return true;
+ }
+
+ // UnaryExpression .= PostfixExpression
+ // | UnaryOperator UnaryExpression
+ // ( where UnaryOperator is one of { -, +, ~, ! } )
+ private boolean parseUnaryExpression(ExprTreeHolder tree) throws IOException {
+ TokenType tt = lexer.peekToken();
+ if (tt == TokenType.LEX_MINUS || tt == TokenType.LEX_PLUS || tt == TokenType.LEX_BITWISE_NOT
+ || tt == TokenType.LEX_LOGICAL_NOT) {
+ lexer.consumeToken();
+ ExprTreeHolder treeM = objectPool.mutableExprPool.get();
+ int op = Operation.OpKind_NO_OP;
+ parseUnaryExpression(treeM);
+ switch (tt) {
+ case LEX_MINUS:
+ op = Operation.OpKind_UNARY_MINUS_OP;
+ break;
+ case LEX_PLUS:
+ op = Operation.OpKind_UNARY_PLUS_OP;
+ break;
+ case LEX_BITWISE_NOT:
+ op = Operation.OpKind_BITWISE_NOT_OP;
+ break;
+ case LEX_LOGICAL_NOT:
+ op = Operation.OpKind_LOGICAL_NOT_OP;
+ break;
+ default:
+ throw new HyracksDataException("ClassAd: Shouldn't Get here");
+ }
+ if (treeM.getInnerTree() != null) {
+ Operation newTree = objectPool.operationPool.get();
+ Operation.createOperation(op, treeM, null, null, newTree);
+ tree.setInnerTree(newTree);
+ } else {
+ tree.setInnerTree(null);
+ return (false);
+ }
+ return true;
+ } else {
+ return parsePostfixExpression(tree);
+ }
+ }
+
+ // PostfixExpression .= PrimaryExpression
+ // | PostfixExpression '.' Identifier
+ // | PostfixExpression '[' Expression ']'
+ private boolean parsePostfixExpression(ExprTreeHolder tree) throws IOException {
+ TokenType tt;
+ if (!parsePrimaryExpression(tree)) {
+ return false;
+ }
+ while ((tt = lexer.peekToken()) == TokenType.LEX_OPEN_BOX || tt == TokenType.LEX_SELECTION) {
+ ExprTreeHolder treeL = tree;
+ ExprTreeHolder treeR = objectPool.mutableExprPool.get();
+ TokenValue tv = objectPool.tokenValuePool.get();
+ lexer.consumeToken();
+ if (tt == TokenType.LEX_OPEN_BOX) {
+ // subscript operation
+ parseExpression(treeR);
+ if (treeL.getInnerTree() != null && treeR.getInnerTree() != null) {
+ Operation newTree = objectPool.operationPool.get();
+ Operation.createOperation(Operation.OpKind_SUBSCRIPT_OP, treeL, treeR, null, newTree);
+ if (lexer.consumeToken() == TokenType.LEX_CLOSE_BOX) {
+ tree.setInnerTree(newTree);
+ continue;
+ }
+ }
+ tree.setInnerTree(null);
+ return false;
+ } else if (tt == TokenType.LEX_SELECTION) {
+ // field selection operation
+ if ((tt = lexer.consumeToken(tv)) != TokenType.LEX_IDENTIFIER) {
+ throw new HyracksDataException("second argument of selector must be an " + "identifier (got"
+ + String.valueOf(Lexer.strLexToken(tt)) + ")");
+ }
+ AttributeReference newTree = objectPool.attrRefPool.get();
+ AttributeReference.createAttributeReference(treeL, tv.getStrValue(), false, newTree);
+ tree.setInnerTree(newTree);
+ }
+ }
+ return true;
+ }
+
+ // PrimaryExpression .= Identifier
+ // | FunctionCall
+ // | '.' Identifier
+ // | '(' Expression ')'
+ // | Literal
+ // FunctionCall .= Identifier ArgumentList
+ // ( Constant may be
+ // boolean,undefined,error,string,integer,real,classad,list )
+ // ( ArgumentList non-terminal includes parentheses )
+ private boolean parsePrimaryExpression(ExprTreeHolder tree) throws IOException {
+ ExprTreeHolder treeL;
+ TokenValue tv = objectPool.tokenValuePool.get();
+ TokenType tt;
+ tree.setInnerTree(null);
+ switch ((tt = lexer.peekToken(tv))) {
+ // identifiers
+ case LEX_IDENTIFIER:
+ isExpr = true;
+ lexer.consumeToken();
+ // check for funcion call
+ if ((tt = lexer.peekToken()) == TokenType.LEX_OPEN_PAREN) {
+ ExprList argList = objectPool.exprListPool.get();
+ if (!parseArgumentList(argList)) {
+ tree.setInnerTree(null);
+ return false;
+ } ;
+ // special case function-calls should be converted
+ // into a literal expression if the argument is a
+ // string literal
+ if (shouldEvaluateAtParseTime(tv.getStrValue().toString(), argList)) {
+ tree.setInnerTree(evaluateFunction(tv.getStrValue().toString(), argList));
+ } else {
+ tree.setInnerTree(
+ FunctionCall.createFunctionCall(tv.getStrValue().toString(), argList, objectPool));
+ }
+ } else {
+ // I don't think this is ever hit
+ tree.setInnerTree(
+ AttributeReference.createAttributeReference(null, tv.getStrValue(), false, objectPool));
+ }
+ return (tree.getInnerTree() != null);
+ case LEX_SELECTION:
+ isExpr = true;
+ lexer.consumeToken();
+ if ((tt = lexer.consumeToken(tv)) == TokenType.LEX_IDENTIFIER) {
+ // the boolean final arg signifies that reference is absolute
+ tree.setInnerTree(
+ AttributeReference.createAttributeReference(null, tv.getStrValue(), true, objectPool));
+ return (tree.size() != 0);
+ }
+ // not an identifier following the '.'
+ throw new HyracksDataException(
+ "need identifier in selection expression (got" + Lexer.strLexToken(tt) + ")");
+ // parenthesized expression
+ case LEX_OPEN_PAREN: {
+ isExpr = true;
+ lexer.consumeToken();
+ treeL = objectPool.mutableExprPool.get();
+ parseExpression(treeL);
+ if (treeL.getInnerTree() == null) {
+ tree.resetExprTree(null);
+ return false;
+ }
+
+ if ((tt = lexer.consumeToken()) != TokenType.LEX_CLOSE_PAREN) {
+ throw new HyracksDataException("exptected LEX_CLOSE_PAREN, but got " + Lexer.strLexToken(tt));
+ // tree.resetExprTree(null);
+ // return false;
+ }
+ // assume make operation will return a new tree
+ tree.setInnerTree(Operation.createOperation(Operation.OpKind_PARENTHESES_OP, treeL, objectPool));
+ return (tree.size() != 0);
+ }
+ // constants
+ case LEX_OPEN_BOX: {
+ isExpr = true;
+ ClassAd newAd = objectPool.classAdPool.get();
+ if (!parseClassAd(newAd)) {
+ tree.resetExprTree(null);
+ return false;
+ }
+ tree.setInnerTree(newAd);
+ }
+ return true;
+
+ case LEX_OPEN_BRACE: {
+ isExpr = true;
+ ExprList newList = objectPool.exprListPool.get();
+ if (!parseExprList(newList)) {
+ tree.setInnerTree(null);
+ return false;
+ }
+ tree.setInnerTree(newList);
+ }
+ return true;
+
+ case LEX_UNDEFINED_VALUE: {
+ Value val = objectPool.valuePool.get();
+ lexer.consumeToken();
+ val.setUndefinedValue();
+ tree.setInnerTree(Literal.createLiteral(val, objectPool));
+ return (tree.getInnerTree() != null);
+ }
+ case LEX_ERROR_VALUE: {
+ Value val = objectPool.valuePool.get();
+ lexer.consumeToken();
+ val.setErrorValue();
+ tree.setInnerTree(Literal.createLiteral(val, objectPool));
+ return (tree.getInnerTree() != null);
+ }
+ case LEX_BOOLEAN_VALUE: {
+ Value val = objectPool.valuePool.get();
+ MutableBoolean b = new MutableBoolean();
+ tv.getBoolValue(b);
+ lexer.consumeToken();
+ val.setBooleanValue(b);
+ tree.setInnerTree(Literal.createLiteral(val, objectPool));
+ return (tree.getInnerTree() != null);
+ }
+
+ case LEX_INTEGER_VALUE: {
+ Value val = objectPool.valuePool.get();
+ lexer.consumeToken();
+ val.setIntegerValue(tv.getIntValue());
+ tree.setInnerTree(Literal.createLiteral(val, tv.getFactor(), objectPool));
+ return (tree.getInnerTree() != null);
+ }
+
+ case LEX_REAL_VALUE: {
+ Value val = objectPool.valuePool.get();
+ lexer.consumeToken();
+ val.setRealValue(tv.getRealValue());
+ tree.setInnerTree(Literal.createLiteral(val, tv.getFactor(), objectPool));
+ return (tree.getInnerTree() != null);
+ }
+
+ case LEX_STRING_VALUE: {
+ Value val = objectPool.valuePool.get();
+ lexer.consumeToken();
+ val.setStringValue(tv.getStrValue());
+ tree.setInnerTree(Literal.createLiteral(val, objectPool));
+ return (tree.getInnerTree() != null);
+ }
+
+ case LEX_ABSOLUTE_TIME_VALUE: {
+ Value val = objectPool.valuePool.get();
+ lexer.consumeToken();
+ val.setAbsoluteTimeValue(tv.getTimeValue());
+ tree.setInnerTree(Literal.createLiteral(val, objectPool));
+ return (tree.getInnerTree() != null);
+ }
+
+ case LEX_RELATIVE_TIME_VALUE: {
+ Value val = objectPool.valuePool.get();
+ lexer.consumeToken();
+ val.setRelativeTimeValue(tv.getTimeValue().getRelativeTime());
+ tree.setInnerTree(Literal.createLiteral(val, objectPool));
+ return (tree.getInnerTree() != null);
+ }
+
+ default:
+ tree.setInnerTree(null);
+ return false;
+ }
+ }
+
+ // ArgumentList .= '(' ListOfArguments ')'
+ // ListOfArguments .= (epsilon)
+ // | ListOfArguments ',' Expression
+ public boolean parseArgumentList(ExprList argList) throws IOException {
+ TokenType tt;
+ argList.clear();
+ if ((tt = lexer.consumeToken()) != TokenType.LEX_OPEN_PAREN) {
+ throw new HyracksDataException("expected LEX_OPEN_PAREN but got " + String.valueOf(Lexer.strLexToken(tt)));
+ // return false;
+ }
+ tt = lexer.peekToken();
+ ExprTreeHolder tree = objectPool.mutableExprPool.get();
+ while (tt != TokenType.LEX_CLOSE_PAREN) {
+ // parse the expression
+ tree.reset();
+ parseExpression(tree);
+ if (tree.getInnerTree() == null) {
+ argList.clear();
+ return false;
+ }
+ // insert the expression into the argument list
+ argList.add(tree.getInnerTree());
+ // the next token must be a ',' or a ')'
+ // or it can be a ';' if using old ClassAd semantics
+ tt = lexer.peekToken();
+ if (tt == TokenType.LEX_COMMA || (tt == TokenType.LEX_SEMICOLON && false)) {
+ lexer.consumeToken();
+ } else if (tt != TokenType.LEX_CLOSE_PAREN) {
+ argList.clear();
+ throw new HyracksDataException(
+ "expected LEX_COMMA or LEX_CLOSE_PAREN but got " + String.valueOf(Lexer.strLexToken(tt)));
+ // return false;
+ }
+ }
+ lexer.consumeToken();
+ return true;
+ }
+
+ // ClassAd .= '[' AttributeList ']'
+ // AttributeList .= (epsilon)
+ // | Attribute ';' AttributeList
+ // Attribute .= Identifier '=' Expression
+ public boolean parseClassAd(ClassAd ad) throws IOException {
+ return parseClassAd(ad, false);
+ }
+
+ public boolean parseClassAdOld(ClassAd ad, boolean full) throws IOException {
+ return false;
+ }
+
+ public boolean parseClassAd(ClassAd ad, boolean full) throws IOException {
+ TokenType tt;
+ ad.clear();
+ if ((tt = lexer.consumeToken()) != TokenType.LEX_OPEN_BOX) {
+ return false;
+ }
+ tt = lexer.peekToken();
+ TokenValue tv = objectPool.tokenValuePool.get();
+ ExprTreeHolder tree = objectPool.mutableExprPool.get();
+ while (tt != TokenType.LEX_CLOSE_BOX) {
+ // Get the name of the expression
+ tv.reset();
+ tree.reset();
+ tt = lexer.consumeToken(tv);
+ if (tt == TokenType.LEX_SEMICOLON) {
+ // We allow empty expressions, so if someone give a double
+ // semicolon, it doesn't
+ // hurt. Technically it's not right, but we shouldn't make users
+ // pay the price for
+ // a meaningless mistake. See condor-support #1881 for a user
+ // that was bitten by this.
+ continue;
+ }
+ if (tt != TokenType.LEX_IDENTIFIER) {
+ throw new HyracksDataException(
+ "while parsing classad: expected LEX_IDENTIFIER " + " but got " + Lexer.strLexToken(tt));
+ }
+
+ // consume the intermediate '='
+ if ((tt = lexer.consumeToken()) != TokenType.LEX_BOUND_TO) {
+ throw new HyracksDataException(
+ "while parsing classad: expected LEX_BOUND_TO " + " but got " + Lexer.strLexToken(tt));
+ }
+
+ isExpr = false;
+ // parse the expression
+ parseExpression(tree);
+ if (tree.getInnerTree() == null) {
+ throw new HyracksDataException("parse expression returned empty tree");
+ }
+
+ // insert the attribute into the classad
+ if (!ad.insert(tv.getStrValue().toString(), tree)) {
+ throw new HyracksDataException("Couldn't insert value to classad");
+ }
+
+ // the next token must be a ';' or a ']'
+ tt = lexer.peekToken();
+ if (tt != TokenType.LEX_SEMICOLON && tt != TokenType.LEX_CLOSE_BOX) {
+ throw new HyracksDataException("while parsing classad: expected LEX_SEMICOLON or "
+ + "LEX_CLOSE_BOX but got " + Lexer.strLexToken(tt));
+ }
+
+ // Slurp up any extra semicolons. This does not duplicate the work
+ // at the top of the loop
+ // because it accounts for the case where the last expression has
+ // extra semicolons,
+ // while the first case accounts for optional beginning semicolons.
+ while (tt == TokenType.LEX_SEMICOLON) {
+ lexer.consumeToken();
+ tt = lexer.peekToken();
+ }
+ }
+ lexer.consumeToken();
+ // if a full parse was requested, ensure that input is exhausted
+ if (full && (lexer.consumeToken() != TokenType.LEX_END_OF_INPUT)) {
+ throw new HyracksDataException("while parsing classad: expected LEX_END_OF_INPUT for "
+ + "full parse but got " + Lexer.strLexToken(tt));
+ }
+ return true;
+ }
+
+ // ExprList .= '{' ListOfExpressions '}'
+ // ListOfExpressions .= (epsilon)
+ // | Expression ',' ListOfExpressions
+ public boolean parseExprList(ExprList list) throws IOException {
+ return parseExprList(list, false);
+ }
+
+ public boolean parseExprList(ExprList list, boolean full) throws IOException {
+ TokenType tt;
+ ExprTreeHolder tree = objectPool.mutableExprPool.get();
+ ExprList loe = objectPool.exprListPool.get();
+
+ if ((tt = lexer.consumeToken()) != TokenType.LEX_OPEN_BRACE) {
+ throw new HyracksDataException(
+ "while parsing expression list: expected LEX_OPEN_BRACE" + " but got " + Lexer.strLexToken(tt));
+ // return false;
+ }
+ tt = lexer.peekToken();
+ while (tt != TokenType.LEX_CLOSE_BRACE) {
+ // parse the expression
+ parseExpression(tree);
+ if (tree.getInnerTree() == null) {
+ throw new HyracksDataException("while parsing expression list: expected "
+ + "LEX_CLOSE_BRACE or LEX_COMMA but got " + Lexer.strLexToken(tt));
+ }
+
+ // insert the expression into the list
+ loe.add(tree);
+
+ // the next token must be a ',' or a '}'
+ tt = lexer.peekToken();
+ if (tt == TokenType.LEX_COMMA) {
+ lexer.consumeToken();
+ } else if (tt != TokenType.LEX_CLOSE_BRACE) {
+ throw new HyracksDataException("while parsing expression list: expected "
+ + "LEX_CLOSE_BRACE or LEX_COMMA but got " + Lexer.strLexToken(tt));
+ }
+ }
+
+ lexer.consumeToken();
+ list.setValue(ExprList.createExprList(loe, objectPool));
+
+ // if a full parse was requested, ensure that input is exhausted
+ if (full && (lexer.consumeToken() != TokenType.LEX_END_OF_INPUT)) {
+ list.clear();
+ throw new HyracksDataException("while parsing expression list: expected "
+ + "LEX_END_OF_INPUT for full parse but got " + Lexer.strLexToken(tt));
+ }
+ return true;
+ }
+
+ public boolean shouldEvaluateAtParseTime(String functionName, ExprList argList) throws HyracksDataException {
+ boolean should_eval = false;
+ if (functionName.equalsIgnoreCase("absTime") || functionName.equalsIgnoreCase("relTime")) {
+ if (argList.size() == 1 && argList.get(0).getKind() == NodeKind.LITERAL_NODE) {
+ Value val = objectPool.valuePool.get();
+ AMutableNumberFactor factor = objectPool.numFactorPool.get();
+ ((Literal) argList.get(0)).getComponents(val, factor);
+ if (val.isStringValue()) {
+ should_eval = true;
+ }
+ }
+ }
+ return should_eval;
+ }
+
+ public ExprTree evaluateFunction(String functionName, ExprList argList) throws HyracksDataException {
+ Value val = objectPool.valuePool.get();
+ AMutableNumberFactor factor = objectPool.numFactorPool.get();
+ ExprTreeHolder tree = objectPool.mutableExprPool.get();
+ ((Literal) argList.get(0)).getComponents(val, factor);
+
+ AMutableCharArrayString string_value = objectPool.strPool.get();
+ if (val.isStringValue(string_value)) {
+ if (functionName.equalsIgnoreCase("absTime")) {
+ tree.setInnerTree(Literal.createAbsTime(string_value, objectPool));
+ } else if (functionName.equalsIgnoreCase("relTime")) {
+ tree.setInnerTree(Literal.createRelTime(string_value, objectPool));
+ } else {
+ tree.setInnerTree(FunctionCall.createFunctionCall(functionName, argList, objectPool));
+ }
+ } else {
+ tree.setInnerTree(FunctionCall.createFunctionCall(functionName, argList, objectPool));
+ }
+ return tree;
+ }
+
+ public TokenType peekToken() throws IOException {
+ if (lexer.wasInitialized()) {
+ return lexer.peekToken();
+ } else {
+ return TokenType.LEX_TOKEN_ERROR;
+ }
+ }
+
+ public TokenType consumeToken() throws IOException {
+ if (lexer.wasInitialized()) {
+ return lexer.consumeToken();
+ } else {
+ return TokenType.LEX_TOKEN_ERROR;
+ }
+ }
+
+ public boolean parseExpression(String buf, ExprTreeHolder tree) throws IOException {
+ return parseExpression(buf, tree, false);
+ }
+
+ public boolean parseExpression(String buf, ExprTreeHolder tree, boolean full) throws IOException {
+ boolean success;
+ StringLexerSource lexer_source = new StringLexerSource(buf);
+
+ success = false;
+ if (lexer.initialize(lexer_source)) {
+ success = parseExpression(tree, full);
+ }
+ return success;
+ }
+
+ public ClassAd parseClassAd(String input_basic) throws IOException {
+ return parseClassAd(input_basic, false);
+ }
+
+ public LexerSource getLexerSource() {
+ return currentSource;
+ }
+
+ public void setLexerSource(LexerSource lexerSource) {
+ this.currentSource = lexerSource;
+ }
+
+ @Override
+ public void parse(IRawRecord<? extends char[]> record, DataOutput out) throws IOException {
+ try {
+ resetPools();
+ if (oldFormat) {
+ int maxOffset = record.size();
+ rootAd.clear();
+ char[] buffer = record.get();
+ aInt32.setValue(0);
+ String line = readLine(buffer, aInt32, maxOffset);
+ while (line != null) {
+ if (line.trim().length() == 0) {
+ if (rootAd.size() == 0) {
+ line = readLine(buffer, aInt32, maxOffset);
+ continue;
+ }
+ break;
+ } else if (!rootAd.insert(line)) {
+ throw new HyracksDataException("Couldn't parse expression in line: " + line);
+ }
+ line = readLine(buffer, aInt32, maxOffset);
+ }
+ } else {
+ currentSource.setNewSource(record.get());
+ rootAd.reset();
+ asterixParseClassAd(rootAd);
+ }
+ parseRecord(recordType, rootAd, out);
+ } catch (Exception e) {
+ throw new HyracksDataException(e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/8516517e/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/adapter/TestTypedAdapterFactory.java
----------------------------------------------------------------------
diff --cc asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/adapter/TestTypedAdapterFactory.java
index 7da6389,0000000..d1a4532
mode 100644,000000..100644
--- a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/adapter/TestTypedAdapterFactory.java
+++ b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/adapter/TestTypedAdapterFactory.java
@@@ -1,137 -1,0 +1,137 @@@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 at
+ *
+ * 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 org.apache.asterix.external.library.adapter;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+
+import org.apache.asterix.common.cluster.ClusterPartition;
+import org.apache.asterix.common.config.IAsterixPropertiesProvider;
+import org.apache.asterix.common.exceptions.AsterixException;
+import org.apache.asterix.external.api.IAdapterFactory;
+import org.apache.asterix.external.api.IDataSourceAdapter;
+import org.apache.asterix.external.api.IExternalDataSourceFactory;
+import org.apache.asterix.external.api.ITupleForwarder;
+import org.apache.asterix.external.parser.ADMDataParser;
+import org.apache.asterix.external.util.DataflowUtils;
+import org.apache.asterix.external.util.ExternalDataUtils;
+import org.apache.asterix.external.util.FeedUtils;
+import org.apache.asterix.om.types.ARecordType;
+import org.apache.hyracks.algebricks.common.constraints.AlgebricksAbsolutePartitionConstraint;
+import org.apache.hyracks.api.comm.IFrameWriter;
+import org.apache.hyracks.api.context.IHyracksTaskContext;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.control.nc.NodeControllerService;
+import org.apache.hyracks.dataflow.common.comm.io.ArrayTupleBuilder;
+import org.apache.hyracks.dataflow.std.file.ITupleParser;
+import org.apache.hyracks.dataflow.std.file.ITupleParserFactory;
+
+public class TestTypedAdapterFactory implements IAdapterFactory {
+
+ private static final long serialVersionUID = 1L;
+
+ private ARecordType outputType;
+
+ public static final String KEY_NUM_OUTPUT_RECORDS = "num_output_records";
+
+ private Map<String, String> configuration;
+
+ private transient AlgebricksAbsolutePartitionConstraint clusterLocations;
+
+ @Override
+ public String getAlias() {
+ return "test_typed";
+ }
+
+ @Override
+ public AlgebricksAbsolutePartitionConstraint getPartitionConstraint() throws AsterixException {
+ clusterLocations = IExternalDataSourceFactory.getPartitionConstraints(clusterLocations, 1);
+ return clusterLocations;
+ }
+
+ @Override
+ public IDataSourceAdapter createAdapter(IHyracksTaskContext ctx, int partition) throws HyracksDataException {
+ final String nodeId = ctx.getJobletContext().getApplicationContext().getNodeId();
+ final ITupleParserFactory tupleParserFactory = new ITupleParserFactory() {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public ITupleParser createTupleParser(IHyracksTaskContext ctx) throws HyracksDataException {
+ ADMDataParser parser;
+ ITupleForwarder forwarder;
+ ArrayTupleBuilder tb;
+ IAsterixPropertiesProvider propertiesProvider = (IAsterixPropertiesProvider) ((NodeControllerService) ctx
+ .getJobletContext().getApplicationContext().getControllerService()).getApplicationContext()
+ .getApplicationObject();
- ClusterPartition[] nodePartitions = propertiesProvider.getMetadataProperties().getNodePartitions()
- .get(nodeId);
++ ClusterPartition nodePartition = propertiesProvider.getMetadataProperties().getNodePartitions()
++ .get(nodeId)[0];
+ try {
+ parser = new ADMDataParser(outputType, true);
+ forwarder = DataflowUtils
+ .getTupleForwarder(configuration,
+ FeedUtils.getFeedLogManager(ctx,
+ FeedUtils.splitsForAdapter(ExternalDataUtils.getDataverse(configuration),
- ExternalDataUtils.getFeedName(configuration), partition,
- nodePartitions)));
++ ExternalDataUtils.getFeedName(configuration), nodeId,
++ nodePartition)));
+ tb = new ArrayTupleBuilder(1);
+ } catch (Exception e) {
+ throw new HyracksDataException(e);
+ }
+ return new ITupleParser() {
+
+ @Override
+ public void parse(InputStream in, IFrameWriter writer) throws HyracksDataException {
+ try {
+ parser.setInputStream(in);
+ forwarder.initialize(ctx, writer);
+ while (true) {
+ tb.reset();
+ if (!parser.parse(tb.getDataOutput())) {
+ break;
+ }
+ tb.addFieldEndOffset();
+ forwarder.addTuple(tb);
+ }
+ forwarder.close();
+ } catch (Exception e) {
+ throw new HyracksDataException(e);
+ }
+ }
+ };
+ }
+ };
+ try {
+ return new TestTypedAdapter(tupleParserFactory, outputType, ctx, configuration, partition);
+ } catch (IOException e) {
+ throw new HyracksDataException(e);
+ }
+ }
+
+ @Override
+ public ARecordType getAdapterOutputType() {
+ return outputType;
+ }
+
+ @Override
+ public void configure(Map<String, String> configuration, ARecordType outputType, ARecordType metaType) {
+ this.configuration = configuration;
+ this.outputType = outputType;
+ }
+}