org.apache.asterix.external.classad.ClassAdUnParser.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.asterix.external.classad.ClassAdUnParser.java

Source

/*
 * 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.classad;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.asterix.external.classad.Value.NumberFactor;
import org.apache.asterix.external.classad.object.pool.ClassAdObjectPool;
import org.apache.asterix.om.base.AMutableDouble;
import org.apache.asterix.om.base.AMutableInt32;
import org.apache.asterix.om.base.AMutableInt64;
import org.apache.commons.lang3.mutable.MutableBoolean;
import org.apache.hyracks.api.exceptions.HyracksDataException;

public class ClassAdUnParser {

    // table of string representation of operators
    public static final String[] opString = { "", " < ", " <= ", " != ", " == ", " >= ", " > ", " is ", " isnt ",
            " +", " -", " + ", " - ", " * ", " / ", " % ", " !", " || ", " && ", " ~", " | ", " ^ ", " & ", " << ",
            " >> ", " >>> ", " () ", " [] ", " ?: " };
    protected static char delimiter = '\"';

    protected final ClassAdObjectPool objectPool;

    /// Constructor
    public ClassAdUnParser(ClassAdObjectPool objectPool) {
        this.objectPool = objectPool;
    }

    // The default delimiter for strings is '\"'
    // This can be changed to '\'' to unparse quoted attributes, with this function
    public void setDelimiter(char delim) {
        delimiter = delim;
    }

    /**
     * Unparse a value
     *
     * @param buffer
     *            The string to unparse to
     * @param val
     *            The value to unparse
     * @throws HyracksDataException
     */
    public void unparse(AMutableCharArrayString buffer, Value val) throws HyracksDataException {
        switch (val.getType()) {
        case NULL_VALUE:
            buffer.appendString("(null-value)");
            break;

        case STRING_VALUE: {
            AMutableCharArrayString s = objectPool.strPool.get();
            val.isStringValue(s);
            buffer.appendChar('"');
            for (int i = 0; i < s.getLength(); i++) {
                char ch = s.charAt(i);
                if (ch == delimiter) {
                    if (delimiter == '\"') {
                        buffer.appendString("\\\"");
                        continue;
                    } else {
                        buffer.appendString("\\\'");
                        continue;
                    }
                }
                switch (ch) {
                case '\b':
                    buffer.appendString("\\b");
                    continue;
                case '\f':
                    buffer.appendString("\\f");
                    continue;
                case '\n':
                    buffer.appendString("\\n");
                    continue;
                case '\r':
                    buffer.appendString("\\r");
                    continue;
                case '\t':
                    buffer.appendString("\\t");
                    continue;
                case '\\':
                    buffer.appendString("\\\\");
                    continue;
                case '\'':
                    buffer.appendString("\'");
                    continue;
                case '\"':
                    buffer.appendString("\"");
                    continue;
                default:
                    if (Character.isISOControl(ch)) {
                        // print octal representation
                        buffer.appendString(String.format("\\%03o", ch));
                        continue;
                    }
                    break;
                }

                buffer.appendChar(ch);
            }
            buffer.appendChar('"');
            return;
        }
        case INTEGER_VALUE: {
            AMutableInt64 i = objectPool.int64Pool.get();
            val.isIntegerValue(i);
            buffer.appendString(String.valueOf(i.getLongValue()));
            return;
        }
        case REAL_VALUE: {
            AMutableDouble real = objectPool.doublePool.get();
            val.isRealValue(real);
            if (real.getDoubleValue() == 0.0) {
                // It might be positive or negative and it's
                // hard to tell. printf is good at telling though.
                // We also want to print it with as few
                // digits as possible, which is why we don't use the
                // case below.
                buffer.appendString(String.valueOf(real.getDoubleValue()));
            } else if (Util.isNan(real.getDoubleValue())) {
                buffer.appendString("real(\"NaN\")");
            } else if (Util.isInf(real.getDoubleValue()) == -1) {
                buffer.appendString("real(\"-INF\")");
            } else if (Util.isInf(real.getDoubleValue()) == 1) {
                buffer.appendString("real(\"INF\")");
            } else {
                buffer.appendString(String.format("%1.15E", real.getDoubleValue()));
            }
            return;
        }
        case BOOLEAN_VALUE: {
            MutableBoolean b = objectPool.boolPool.get();
            val.isBooleanValue(b);
            buffer.appendString(b.booleanValue() ? "true" : "false");
            return;
        }
        case UNDEFINED_VALUE: {
            buffer.appendString("undefined");
            return;
        }
        case ERROR_VALUE: {
            buffer.appendString("error");
            return;
        }
        case ABSOLUTE_TIME_VALUE: {
            ClassAdTime asecs = objectPool.classAdTimePool.get();
            val.isAbsoluteTimeValue(asecs);

            buffer.appendString("absTime(\"");
            Util.absTimeToString(asecs, buffer);
            buffer.appendString("\")");
            return;
        }
        case RELATIVE_TIME_VALUE: {
            ClassAdTime rsecs = objectPool.classAdTimePool.get();
            val.isRelativeTimeValue(rsecs);
            buffer.appendString("relTime(\"");
            Util.relTimeToString(rsecs.getRelativeTime(), buffer);
            buffer.appendString("\")");

            return;
        }
        case CLASSAD_VALUE: {
            ClassAd ad = objectPool.classAdPool.get();
            Map<CaseInsensitiveString, ExprTree> attrs = objectPool.strToExprPool.get();
            val.isClassAdValue(ad);
            ad.getComponents(attrs, objectPool);
            unparseAux(buffer, attrs);
            return;
        }
        case SLIST_VALUE:
        case LIST_VALUE: {
            ExprList el = objectPool.exprListPool.get();
            val.isListValue(el);
            unparseAux(buffer, el);
            return;
        }
        }
    }

    /**
     * Unparse an expression
     *
     * @param buffer
     *            The string to unparse to
     * @param expr
     *            The expression to unparse
     * @throws HyracksDataException
     */
    public void unparse(AMutableCharArrayString buffer, ExprTree tree) throws HyracksDataException {
        if (tree == null) {
            buffer.appendString("<error:null expr>");
            return;
        }

        switch (tree.getKind()) {
        case LITERAL_NODE: { // value
            Value val = objectPool.valuePool.get();
            AMutableNumberFactor factor = objectPool.numFactorPool.get();
            ((Literal) tree.getTree()).getComponents(val, factor);
            unparseAux(buffer, val, factor.getFactor());
            return;
        }

        case ATTRREF_NODE: { // string
            ExprTreeHolder expr = objectPool.mutableExprPool.get(); //needs initialization
            AMutableCharArrayString ref = objectPool.strPool.get();
            MutableBoolean absolute = objectPool.boolPool.get();
            ((AttributeReference) tree.getTree()).getComponents(expr, ref, absolute);
            unparseAux(buffer, expr, ref, absolute.booleanValue());
            return;
        }

        case OP_NODE: { //string
            AMutableInt32 op = objectPool.int32Pool.get();
            ExprTreeHolder t1 = objectPool.mutableExprPool.get();
            ExprTreeHolder t2 = objectPool.mutableExprPool.get();
            ExprTreeHolder t3 = objectPool.mutableExprPool.get();
            ((Operation) tree.getTree()).getComponents(op, t1, t2, t3);
            unparseAux(buffer, op.getIntegerValue().intValue(), t1, t2, t3);
            return;
        }

        case FN_CALL_NODE: { // string
            AMutableCharArrayString fnName = objectPool.strPool.get();
            ExprList args = objectPool.exprListPool.get();
            ((FunctionCall) tree.getTree()).getComponents(fnName, args);
            unparseAux(buffer, fnName, args);
            return;
        }

        case CLASSAD_NODE: { // nested record
            Map<CaseInsensitiveString, ExprTree> attrs = objectPool.strToExprPool.get();
            ((ClassAd) tree.getTree()).getComponents(attrs, objectPool);
            unparseAux(buffer, attrs);
            return;
        }
        case EXPR_LIST_NODE: { // list
            ExprList exprs = objectPool.exprListPool.get();
            ((ExprList) tree.getTree()).getComponents(exprs);
            unparseAux(buffer, exprs);
            return;
        }

        default:
            // I really wonder whether we should except here, but I
            // don't want to do that without further consultation.
            // wenger 2003-12-11.
            buffer.setValue("");
            throw new HyracksDataException("unknown expression type");
        }
    }

    private void unparseAux(AMutableCharArrayString buffer, AMutableCharArrayString fnName, ExprList args)
            throws HyracksDataException {
        buffer.appendString(fnName);
        buffer.appendChar('(');
        for (ExprTree tree : args.getExprList()) {
            unparse(buffer, tree);
            buffer.appendChar(',');
        }
        if (args.size() > 0) {
            buffer.decrementLength();
        }
        buffer.appendChar(')');

    }

    public void unparseAux(AMutableCharArrayString buffer, final Value value, NumberFactor numFactor)
            throws HyracksDataException {
        unparse(buffer, value);
        if ((value.isIntegerValue() || value.isRealValue()) && numFactor != NumberFactor.NO_FACTOR) {
            buffer.appendChar((numFactor == NumberFactor.B_FACTOR) ? 'B'
                    : (numFactor == NumberFactor.K_FACTOR) ? 'K'
                            : (numFactor == NumberFactor.M_FACTOR) ? 'M'
                                    : (numFactor == NumberFactor.G_FACTOR) ? 'G'
                                            : (numFactor == NumberFactor.T_FACTOR) ? 'T' : '?');
            if (buffer.charAt(buffer.getLength() - 1) == '?') {
                buffer.reset();
                throw new HyracksDataException("bad number factor");
            }
        }
        return;
    }

    /**
     * @param buffer
     * @param tree
     * @param ref
     * @param absolute
     *            = false if ommitted
     * @throws HyracksDataException
     */
    public void unparseAux(AMutableCharArrayString buffer, final ExprTree tree, AMutableCharArrayString ref,
            boolean absolute) throws HyracksDataException {

        if (tree != null && tree.self() != null) {
            unparse(buffer, tree);
            buffer.appendChar('.');
            buffer.appendString(ref);
            return;
        }
        if (absolute) {
            buffer.appendChar('.');
        }
        unparseAux(buffer, ref);
    };

    public void unparseAux(AMutableCharArrayString buffer, final ExprTree tree, AMutableCharArrayString ref)
            throws HyracksDataException {
        unparseAux(buffer, tree, ref, false);
    };

    public void unparseAuxPairs(AMutableCharArrayString buffer,
            List<Entry<AMutableCharArrayString, ExprTree>> attrlist) throws HyracksDataException {
        String delim = "; "; // NAC
        buffer.appendString("[ ");
        for (Entry<AMutableCharArrayString, ExprTree> entry : attrlist) {
            unparseAux(buffer, entry.getKey());
            buffer.appendString(" = ");
            unparse(buffer, entry.getValue());
            buffer.appendString(delim);
        }
        //get rid of last delimiter
        buffer.setLength(buffer.getLength() - delim.length());
        buffer.appendString(" ]");
    }

    // to unparse attribute names (quoted & unquoted attributes)
    public void unparseAux(AMutableCharArrayString buffer, AMutableCharArrayString identifier)
            throws HyracksDataException {
        Value val = objectPool.valuePool.get();
        AMutableCharArrayString idstr = objectPool.strPool.get();

        val.setStringValue(identifier);
        setDelimiter('\''); // change the delimiter from string-literal mode to quoted attribute mode
        unparse(idstr, val);
        setDelimiter('\"'); // set delimiter back to default setting
        idstr.erase(0, 1);
        idstr.erase(idstr.length() - 1, 1);
        if (identifierNeedsQuoting(idstr)) {
            idstr.insert(0, "'");
            idstr.appendString("'");
        }
        buffer.appendString(idstr);
    }

    static boolean identifierNeedsQuoting(AMutableCharArrayString aString) {
        return false;
    }

    public void unparseAux(AMutableCharArrayString buffer, Value val, AMutableNumberFactor factor)
            throws HyracksDataException {
        unparse(buffer, val);
        if ((val.isIntegerValue() || val.isRealValue()) && factor.getFactor() != NumberFactor.NO_FACTOR) {
            buffer.appendString((factor.getFactor() == NumberFactor.B_FACTOR) ? "B"
                    : (factor.getFactor() == NumberFactor.K_FACTOR) ? "K"
                            : (factor.getFactor() == NumberFactor.M_FACTOR) ? "M"
                                    : (factor.getFactor() == NumberFactor.G_FACTOR) ? "G"
                                            : (factor.getFactor() == NumberFactor.T_FACTOR) ? "T"
                                                    : "<error:bad factor>");
        }
        return;
    }

    public void unparseAux(AMutableCharArrayString buffer, ExprTree expr, String attrName, boolean absolute)
            throws HyracksDataException {
        if (expr != null) {
            unparse(buffer, expr);
            buffer.appendString("." + attrName);
            return;
        }
        if (absolute) {
            buffer.appendChar('.');
        }
        unparseAux(buffer, attrName);
    }

    public void unparseAux(AMutableCharArrayString buffer, int op, ExprTreeHolder t1, ExprTreeHolder t2,
            ExprTreeHolder t3) throws HyracksDataException {
        // case 0: parentheses op
        if (op == Operation.OpKind_PARENTHESES_OP) {
            buffer.appendString("( ");
            unparse(buffer, t1);
            buffer.appendString(" )");
            return;
        }
        // case 1: check for unary ops
        if (op == Operation.OpKind_UNARY_PLUS_OP || op == Operation.OpKind_UNARY_MINUS_OP
                || op == Operation.OpKind_LOGICAL_NOT_OP || op == Operation.OpKind_BITWISE_NOT_OP) {
            buffer.appendString(opString[op]);
            unparse(buffer, t1);
            return;
        }
        // case 2: check for ternary op
        if (op == Operation.OpKind_TERNARY_OP) {
            unparse(buffer, t1);
            buffer.appendString(" ? ");
            unparse(buffer, t2);
            buffer.appendString(" : ");
            unparse(buffer, t3);
            return;
        }
        // case 3: check for subscript op
        if (op == Operation.OpKind_SUBSCRIPT_OP) {
            unparse(buffer, t1);
            buffer.appendChar('[');
            unparse(buffer, t2);
            buffer.appendChar(']');
            return;
        }

        // all others are binary ops
        unparse(buffer, t1);
        buffer.appendString(opString[op]);
        unparse(buffer, t2);
    }

    public void UnparseAux(AMutableCharArrayString buffer, String fnName, ExprList args)
            throws HyracksDataException {
        buffer.appendString(fnName + "(");
        for (ExprTree tree : args.getExprList()) {
            unparse(buffer, tree);
            buffer.appendChar(',');
        }
        buffer.setChar(buffer.getLength() - 1, ')');
    }

    public void unparseAux(AMutableCharArrayString buffer, Map<CaseInsensitiveString, ExprTree> attrs)
            throws HyracksDataException {

        String delim = "; "; // NAC

        buffer.appendString("[ ");

        for (Entry<CaseInsensitiveString, ExprTree> entry : attrs.entrySet()) {
            unparseAux(buffer, entry.getKey().get());
            buffer.appendString(" = ");
            unparse(buffer, entry.getValue());
            buffer.appendString(delim); // NAC
        }
        buffer.setLength(buffer.getLength() - delim.length());
        buffer.appendString(" ]");

    }

    public void unparseAux(AMutableCharArrayString buffer, ExprList exprs) throws HyracksDataException {

        buffer.appendString("{ ");
        for (ExprTree expr : exprs.getExprList()) {
            unparse(buffer, expr);
            buffer.appendChar(',');
        }
        buffer.decrementLength();
        buffer.appendString(" }");
    }

    /* To unparse the identifier strings
     * based on the character content,
     * it's unparsed either as a quoted attribute or non-quoted attribute
     */
    public void unparseAux(AMutableCharArrayString buffer, String identifier) throws HyracksDataException {
        Value val = objectPool.valuePool.get();
        AMutableCharArrayString idstr = objectPool.strPool.get();

        val.setStringValue(identifier);
        setDelimiter('\''); // change the delimiter from string-literal mode to quoted attribute mode
        unparse(idstr, val);
        setDelimiter('\"'); // set delimiter back to default setting
        idstr.erase(0, 1);
        idstr.erase(idstr.length() - 1, 1);
        if (identifierNeedsQuoting(idstr)) {
            idstr.prependChar('\'');
            idstr.appendChar('\'');
        }
        buffer.appendString(idstr);
    }
}