asterix.parser.classad.FunctionCall.java Source code

Java tutorial

Introduction

Here is the source code for asterix.parser.classad.FunctionCall.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 asterix.parser.classad;

import java.util.HashMap;
import org.apache.commons.lang3.mutable.MutableBoolean;
import asterix.parser.classad.AMutableCharArrayString;
import asterix.parser.classad.BuiltinClassAdFunctions;
import asterix.parser.classad.ClassAd;
import asterix.parser.classad.ClassAdFunc;
import asterix.parser.classad.EvalState;
import asterix.parser.classad.ExprList;
import asterix.parser.classad.ExprTree;
import asterix.parser.classad.ExprTreeHolder;
import asterix.parser.classad.FunctionCall;
import asterix.parser.classad.Literal;
import asterix.parser.classad.Value;
import org.apache.asterix.om.base.AMutableInt32;
import org.apache.asterix.om.base.AMutableString;
import org.apache.hyracks.api.exceptions.HyracksDataException;

public class FunctionCall extends ExprTree {

    public static boolean initialized = false;

    public static final ClassAdFunc[] ClassAdBuiltinFunc = { BuiltinClassAdFunctions.IsType,
            BuiltinClassAdFunctions.TestMember, BuiltinClassAdFunctions.Size, BuiltinClassAdFunctions.SumAvg,
            BuiltinClassAdFunctions.MinMax, BuiltinClassAdFunctions.ListCompare, BuiltinClassAdFunctions.debug,
            BuiltinClassAdFunctions.formatTime, BuiltinClassAdFunctions.getField,
            BuiltinClassAdFunctions.currentTime, BuiltinClassAdFunctions.timeZoneOffset,
            BuiltinClassAdFunctions.splitTime, BuiltinClassAdFunctions.dayTime, BuiltinClassAdFunctions.epochTime,
            BuiltinClassAdFunctions.strCat, BuiltinClassAdFunctions.changeCase, BuiltinClassAdFunctions.subString,
            BuiltinClassAdFunctions.convInt, BuiltinClassAdFunctions.compareString,
            BuiltinClassAdFunctions.matchPattern, BuiltinClassAdFunctions.matchPatternMember,
            BuiltinClassAdFunctions.substPattern, BuiltinClassAdFunctions.convReal,
            BuiltinClassAdFunctions.convString, BuiltinClassAdFunctions.unparse, BuiltinClassAdFunctions.convBool,
            BuiltinClassAdFunctions.convTime, BuiltinClassAdFunctions.doRound, BuiltinClassAdFunctions.doMath2,
            BuiltinClassAdFunctions.random, BuiltinClassAdFunctions.ifThenElse,
            BuiltinClassAdFunctions.stringListsIntersect, BuiltinClassAdFunctions.interval,
            BuiltinClassAdFunctions.eval };

    // function call specific information
    private String functionName;
    private ClassAdFunc function;
    private ExprList arguments;
    public static final HashMap<String, ClassAdFunc> funcTable = new HashMap<String, ClassAdFunc>();
    static {
        // load up the function dispatch table
        // type predicates
        funcTable.put("isundefined", BuiltinClassAdFunctions.IsType);
        funcTable.put("iserror", BuiltinClassAdFunctions.IsType);
        funcTable.put("isstring", BuiltinClassAdFunctions.IsType);
        funcTable.put("isinteger", BuiltinClassAdFunctions.IsType);
        funcTable.put("isreal", BuiltinClassAdFunctions.IsType);
        funcTable.put("islist", BuiltinClassAdFunctions.IsType);
        funcTable.put("isclassad", BuiltinClassAdFunctions.IsType);
        funcTable.put("isboolean", BuiltinClassAdFunctions.IsType);
        funcTable.put("isabstime", BuiltinClassAdFunctions.IsType);
        funcTable.put("isreltime", BuiltinClassAdFunctions.IsType);
        funcTable.put("isundefined", BuiltinClassAdFunctions.IsType);
        funcTable.put("isundefined", BuiltinClassAdFunctions.IsType);
        // list membership
        funcTable.put("member", BuiltinClassAdFunctions.TestMember);
        funcTable.put("identicalmember", BuiltinClassAdFunctions.TestMember);
        // Some list functions, useful for lists as sets
        funcTable.put("size", BuiltinClassAdFunctions.Size);
        funcTable.put("sum", BuiltinClassAdFunctions.SumAvg);
        funcTable.put("avg", BuiltinClassAdFunctions.SumAvg);
        funcTable.put("min", BuiltinClassAdFunctions.MinMax);
        funcTable.put("max", BuiltinClassAdFunctions.MinMax);
        funcTable.put("anycompare", BuiltinClassAdFunctions.ListCompare);
        funcTable.put("allcompare", BuiltinClassAdFunctions.ListCompare);
        //basic functions
        /*
        funcTable.put("sumfrom", BuiltinFunctions.SumAvgFrom);
        funcTable.put("avgfrom", BuiltinFunctions.SumAvgFrom);
        funcTable.put("maxfrom", BuiltinFunctions.BoundFrom);
        funcTable.put("minfrom", BuiltinFunctions.BoundFrom);
        */
        // time management
        funcTable.put("time", BuiltinClassAdFunctions.epochTime);
        funcTable.put("currenttime", BuiltinClassAdFunctions.currentTime);
        funcTable.put("timezoneoffset", BuiltinClassAdFunctions.timeZoneOffset);
        funcTable.put("daytime", BuiltinClassAdFunctions.dayTime);
        funcTable.put("getyear", BuiltinClassAdFunctions.getField);
        funcTable.put("getmonth", BuiltinClassAdFunctions.getField);
        funcTable.put("getdayofyear", BuiltinClassAdFunctions.getField);
        funcTable.put("getdayofmonth", BuiltinClassAdFunctions.getField);
        funcTable.put("getdayofweek", BuiltinClassAdFunctions.getField);
        funcTable.put("getdays", BuiltinClassAdFunctions.getField);
        funcTable.put("gethours", BuiltinClassAdFunctions.getField);
        funcTable.put("getminutes", BuiltinClassAdFunctions.getField);
        funcTable.put("getseconds", BuiltinClassAdFunctions.getField);
        funcTable.put("splittime", BuiltinClassAdFunctions.splitTime);
        funcTable.put("formattime", BuiltinClassAdFunctions.formatTime);
        // string manipulation
        funcTable.put("strcat", BuiltinClassAdFunctions.strCat);
        funcTable.put("toupper", BuiltinClassAdFunctions.changeCase);
        funcTable.put("tolower", BuiltinClassAdFunctions.changeCase);
        funcTable.put("substr", BuiltinClassAdFunctions.subString);
        funcTable.put("strcmp", BuiltinClassAdFunctions.compareString);
        funcTable.put("stricmp", BuiltinClassAdFunctions.compareString);
        // pattern matching (regular expressions) 
        funcTable.put("regexp", BuiltinClassAdFunctions.matchPattern);
        funcTable.put("regexpmember", BuiltinClassAdFunctions.matchPatternMember);
        funcTable.put("regexps", BuiltinClassAdFunctions.substPattern);
        // conversion functions
        funcTable.put("int", BuiltinClassAdFunctions.convInt);
        funcTable.put("real", BuiltinClassAdFunctions.convReal);
        funcTable.put("string", BuiltinClassAdFunctions.convString);
        funcTable.put("bool", BuiltinClassAdFunctions.convBool);
        funcTable.put("abstime", BuiltinClassAdFunctions.convTime);
        funcTable.put("reltime", BuiltinClassAdFunctions.convTime);

        // turn the contents of an expression into a string 
        // but *do not* evaluate it

        funcTable.put("unparse", BuiltinClassAdFunctions.unparse);
        // mathematical functions
        funcTable.put("floor", BuiltinClassAdFunctions.doRound);
        funcTable.put("ceil", BuiltinClassAdFunctions.doRound);
        funcTable.put("ceiling", BuiltinClassAdFunctions.doRound);
        funcTable.put("round", BuiltinClassAdFunctions.doRound);
        funcTable.put("pow", BuiltinClassAdFunctions.doMath2);
        funcTable.put("quantize", BuiltinClassAdFunctions.doMath2);
        funcTable.put("random", BuiltinClassAdFunctions.random);

        // for compatibility with old classads:
        funcTable.put("ifthenelse", BuiltinClassAdFunctions.ifThenElse);
        funcTable.put("interval", BuiltinClassAdFunctions.interval);
        funcTable.put("eval", BuiltinClassAdFunctions.eval);

        // string list functions:
        // Note that many other string list functions are defined
        // externally in the Condor classad compatibility layer.

        funcTable.put("stringlistsintersect", BuiltinClassAdFunctions.stringListsIntersect);
        funcTable.put("debug", BuiltinClassAdFunctions.debug);
        initialized = true;
    }

    /**
     * Returns true if the function expression points to a valid
     * function in the ClassAd library.
     */
    public boolean functionIsDefined() {
        return function != null;
    }

    public void copyFrom(FunctionCall copiedFrom) throws HyracksDataException {
        this.function = copiedFrom.function;
        this.functionName = copiedFrom.functionName;
        if (this.arguments == null) {
            this.arguments = (ExprList) copiedFrom.arguments.copy();
        } else {
            this.arguments.copyFrom(copiedFrom.arguments);
        }
    }

    public FunctionCall() {
        functionName = null;
        function = null;
        arguments = null;
    }

    public static FunctionCall createFunctionCall(String functionName, ExprList args) {
        FunctionCall fc = new FunctionCall();
        fc.function = funcTable.get(functionName.toLowerCase());
        fc.functionName = functionName;
        fc.arguments = args;
        return fc;
    }

    // start up with an argument list of size 4

    public FunctionCall(FunctionCall functioncall) throws HyracksDataException {
        copyFrom(functioncall);
    }

    public ExprTree copy() throws HyracksDataException {
        FunctionCall newTree = new FunctionCall();
        newTree.copyFrom(this);
        return newTree;
    }

    public void copyFrom(ExprTree tree) throws HyracksDataException {
        FunctionCall functioncall = (FunctionCall) tree;
        functionName = functioncall.functionName;
        function = functioncall.function;
        arguments.copyFrom(arguments);
        super.copyFrom(functioncall);
    }

    public boolean sameAs(ExprTree tree) {
        boolean is_same = false;
        FunctionCall other_fn;
        ExprTree pSelfTree = tree.self();

        if (this == pSelfTree) {
            is_same = true;
        } else if (pSelfTree.getKind() != NodeKind.FN_CALL_NODE) {
            is_same = false;
        } else {
            other_fn = (FunctionCall) pSelfTree;
            if (functionName == other_fn.functionName && function.equals(other_fn.function)
                    && arguments.equals(other_fn.arguments)) {
                is_same = true;

            } else {
                is_same = false;
            }
        }
        return is_same;
    }

    public boolean equals(FunctionCall fn) {
        return sameAs(fn);
    }

    public static HashMap<String, ClassAdFunc> getFunctionTable() {
        return funcTable;
    }

    public static synchronized void registerFunction(String functionName, ClassAdFunc function) {
        if (!funcTable.containsKey(functionName)) {
            funcTable.put(functionName, function);
        }
    }

    public void privateSetParentScope(ClassAd parent) {
        arguments.privateSetParentScope(parent);
    }

    //This will move pointers to objects (not create clones)
    public void getComponents(AMutableString fn, ExprList exprList) {
        fn.setValue(functionName);
        for (ExprTree tree : arguments.getExprList()) {
            exprList.add(tree);
        }
    }

    public void getComponents(AMutableCharArrayString fn, ExprList exprList) {
        fn.setValue(functionName);
        for (ExprTree tree : arguments.getExprList()) {
            exprList.add(tree);
        }
    }

    public boolean privateEvaluate(EvalState state, Value value) throws HyracksDataException {
        if (function != null) {
            return function.call(functionName, arguments, state, value);
        } else {
            value.setErrorValue();
            return (true);
        }
    }

    public boolean privateEvaluate(EvalState state, Value value, ExprTreeHolder tree) throws HyracksDataException {
        FunctionCall tmpSig = new FunctionCall();
        Value tmpVal = new Value();
        ExprTreeHolder argSig = new ExprTreeHolder();
        MutableBoolean rval = new MutableBoolean();
        if (!privateEvaluate(state, value)) {
            return false;
        }
        tmpSig.functionName = functionName;
        rval.setValue(true);
        for (ExprTree i : arguments.getExprList()) {
            rval.setValue(i.publicEvaluate(state, tmpVal, argSig));
            if (rval.booleanValue())
                tmpSig.arguments.add(argSig.getInnerTree());
        }
        tree.setInnerTree(tmpSig);
        return rval.booleanValue();
    }

    public boolean privateFlatten(EvalState state, Value value, ExprTreeHolder tree, AMutableInt32 i)
            throws HyracksDataException {
        FunctionCall newCall = new FunctionCall();
        ExprTreeHolder argTree = new ExprTreeHolder();
        Value argValue = new Value();
        boolean fold = true;

        tree.setInnerTree(null); // Just to be safe...  wenger 2003-12-11.

        // if the function cannot be resolved, the value is "error"
        if (function == null) {
            value.setErrorValue();
            return true;
        }

        newCall.functionName = functionName;
        newCall.function = function;

        // flatten the arguments
        for (ExprTree exp : arguments.getExprList()) {
            if (exp.publicFlatten(state, argValue, argTree)) {
                if (argTree.getInnerTree() != null) {
                    newCall.arguments.add(argTree.getInnerTree());
                    fold = false;
                    continue;
                } else {
                    // Assert: argTree == NULL
                    argTree.setInnerTree(Literal.createLiteral(argValue));
                    if (argTree.getInnerTree() != null) {
                        newCall.arguments.add(argTree.getInnerTree());
                        continue;
                    }
                }
            }

            // we get here only when something bad happens
            value.setErrorValue();
            tree.setInnerTree(null);
            return false;
        }

        // assume all functions are "pure" (i.e., side-affect free)
        if (fold) {
            // flattened to a value
            if (!function.call(functionName, arguments, state, value)) {
                return false;
            }
            tree.setInnerTree(null);
        } else {
            tree.setInnerTree(newCall);
        }
        return true;
    }

    @Override
    public NodeKind getKind() {
        return NodeKind.FN_CALL_NODE;
    }

    @Override
    public void reset() {
        this.arguments.clear();
        this.function = null;
        this.functionName = "";
    }
}