Java tutorial
/* * 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 = ""; } }