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 org.apache.asterix.external.classad; import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.HashSet; import java.util.List; import java.util.Random; import java.util.Set; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.asterix.external.classad.ExprTree.NodeKind; import org.apache.asterix.external.classad.Value.ValueType; import org.apache.asterix.external.classad.object.pool.ClassAdObjectPool; import org.apache.asterix.external.library.ClassAdParser; 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 BuiltinClassAdFunctions { public static final ClassAdFunc IsType = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value val, ClassAdObjectPool objectPool) throws HyracksDataException { // need a single argument if (argList.size() != 1) { val.setErrorValue(); return true; } // Evaluate the argument if (!argList.getExprList().get(0).publicEvaluate(state, val)) { val.setErrorValue(); return false; } // check if the value was of the required type switch (name.toLowerCase()) { case "isundefined": val.setBooleanValue(val.isUndefinedValue()); break; case "iserror": val.setBooleanValue(val.isErrorValue()); break; case "isinteger": val.setBooleanValue(val.isIntegerValue()); break; case "isstring": val.setBooleanValue(val.isStringValue()); break; case "isreal": val.setBooleanValue(val.isRealValue()); break; case "isboolean": val.setBooleanValue(val.isBooleanValue()); break; case "isclassad": val.setBooleanValue(val.isClassAdValue()); break; case "islist": val.setBooleanValue(val.isListValue()); break; case "isabstime": val.setBooleanValue(val.isAbsoluteTimeValue()); break; case "isreltime": val.setBooleanValue(val.isRelativeTimeValue()); break; default: val.setErrorValue(); } return (true); } }; public static final ClassAdFunc TestMember = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value val, ClassAdObjectPool objectPool) throws HyracksDataException { Value arg0 = objectPool.valuePool.get(); Value arg1 = objectPool.valuePool.get(); Value cArg = objectPool.valuePool.get(); ExprList el = objectPool.exprListPool.get(); MutableBoolean b = objectPool.boolPool.get(); boolean useIS = name.equalsIgnoreCase("identicalmember"); // need two arguments if (argList.size() != 2) { val.setErrorValue(); return (true); } // Evaluate the arg list if (!argList.get(0).publicEvaluate(state, arg0) || !argList.get(1).publicEvaluate(state, arg1)) { val.setErrorValue(); return false; } // if the second arg (a list) is undefined, or the first arg is // undefined and we're supposed to test for strict comparison, the // result is 'undefined' if (arg1.isUndefinedValue() || (!useIS && arg0.isUndefinedValue())) { val.setUndefinedValue(); return true; } // Swap if (arg0.isListValue() && !arg1.isListValue()) { Value swap = objectPool.valuePool.get(); swap.setValue(arg0); arg0.setValue(arg1); arg1.setValue(swap); } // arg1 must be a list; arg0 must be comparable if (!arg1.isListValue() || arg0.isListValue() || arg0.isClassAdValue()) { val.setErrorValue(); return true; } // if we're using strict comparison, arg0 can't be 'error' if (!useIS && arg0.isErrorValue()) { val.setErrorValue(); return (true); } // check for membership arg1.isListValue(el); for (ExprTree tree : el.getExprList()) { if (!tree.publicEvaluate(state, cArg)) { val.setErrorValue(); return (false); } Operation.operate(useIS ? Operation.OpKind_IS_OP : Operation.OpKind_EQUAL_OP, cArg, arg0, val, objectPool); if (val.isBooleanValue(b) && b.booleanValue()) { return true; } } val.setBooleanValue(false); return true; } }; public static final ClassAdFunc Size = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value val, ClassAdObjectPool objectPool) throws HyracksDataException { Value arg = objectPool.valuePool.get(); ExprList listToSize = objectPool.exprListPool.get(); ClassAd classadToSize = objectPool.classAdPool.get(); AMutableInt32 length = objectPool.int32Pool.get(); length.setValue(0); // we accept only one argument if (argList.size() != 1) { val.setErrorValue(); return (true); } if (!argList.get(0).publicEvaluate(state, arg)) { val.setErrorValue(); return false; } else if (arg.isUndefinedValue()) { val.setUndefinedValue(); return true; } else if (arg.isListValue(listToSize)) { val.setIntegerValue(listToSize.size()); return true; } else if (arg.isClassAdValue(classadToSize)) { val.setIntegerValue(classadToSize.size()); return true; } else if (arg.isStringValue(length)) { val.setIntegerValue(length.getIntegerValue().intValue()); return true; } else { val.setErrorValue(); return true; } } }; public static final ClassAdFunc SumAvg = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value val, ClassAdObjectPool objectPool) throws HyracksDataException { Value listElementValue = objectPool.valuePool.get(); Value listVal = objectPool.valuePool.get(); Value numElements = objectPool.valuePool.get(); Value result = objectPool.valuePool.get(); ExprList listToSum = objectPool.exprListPool.get(); MutableBoolean first = objectPool.boolPool.get(); AMutableInt64 len = objectPool.int64Pool.get(); len.setValue(0); boolean onlySum = name.equalsIgnoreCase("sum"); // we accept only one argument if (argList.size() != 1) { val.setErrorValue(); return (true); } // argument must Evaluate to a list if (!argList.get(0).publicEvaluate(state, listVal)) { val.setErrorValue(); return false; } else if (listVal.isUndefinedValue()) { val.setUndefinedValue(); return true; } else if (!listVal.isListValue(listToSum)) { val.setErrorValue(); return (true); } result.setUndefinedValue(); len.setValue(0); first.setValue(true); // Walk over each element in the list, and sum. for (ExprTree listElement : listToSum.getExprList()) { len.setValue(len.getLongValue() + 1); ; // Make sure this element is a number. if (!listElement.publicEvaluate(state, listElementValue)) { val.setErrorValue(); return false; } else if (!listElementValue.isRealValue() && !listElementValue.isIntegerValue()) { val.setErrorValue(); return true; } // Either take the number if it's the first, // or add to the running sum. if (first.booleanValue()) { result.setValue(listElementValue); first.setValue(false); } else { Operation.operate(Operation.OpKind_ADDITION_OP, result, listElementValue, result, objectPool); } } // if the sum() function was called, we don't need to find the average if (onlySum) { val.setValue(result); return true; } if (len.getLongValue() > 0) { numElements.setRealValue(len.getLongValue()); Operation.operate(Operation.OpKind_DIVISION_OP, result, numElements, result, objectPool); } else { val.setUndefinedValue(); } val.setValue(result); return true; } }; public static final ClassAdFunc MinMax = new ClassAdFunc() { @Override public boolean call(String fn, ExprList argList, EvalState state, Value val, ClassAdObjectPool objectPool) throws HyracksDataException { Value listElementValue = objectPool.valuePool.get(); Value listVal = objectPool.valuePool.get(); Value cmp = objectPool.valuePool.get(); Value result = objectPool.valuePool.get(); ExprList listToBound = objectPool.exprListPool.get(); boolean first = true; MutableBoolean b = objectPool.boolPool.get(); b.setValue(false); int comparisonOperator; // we accept only one argument if (argList.size() != 1) { val.setErrorValue(); return true; } // first argument must Evaluate to a list if (!argList.get(0).publicEvaluate(state, listVal)) { val.setErrorValue(); return false; } else if (listVal.isUndefinedValue()) { val.setUndefinedValue(); return true; } else if (!listVal.isListValue(listToBound)) { val.setErrorValue(); return true; } // fn is either "min..." or "max..." if (Character.toLowerCase(fn.charAt(1)) == 'i') { comparisonOperator = Operation.OpKind_LESS_THAN_OP; } else { comparisonOperator = Operation.OpKind_GREATER_THAN_OP; } result.setUndefinedValue(); // Walk over the list, calculating the bound the whole way. for (ExprTree listElement : listToBound.getExprList()) { // For this element of the list, make sure it is // acceptable. if (!listElement.publicEvaluate(state, listElementValue)) { val.setErrorValue(); return false; } else if (!listElementValue.isRealValue() && !listElementValue.isIntegerValue()) { val.setErrorValue(); return true; } // If it's the first element, copy it to the bound, // otherwise compare to decide what to do. if (first) { result.setValue(listElementValue); first = false; } else { Operation.operate(comparisonOperator, listElementValue, result, cmp, objectPool); if (cmp.isBooleanValue(b) && b.booleanValue()) { result.setValue(listElementValue); } } } val.setValue(result); return true; } }; public static final ClassAdFunc ListCompare = new ClassAdFunc() { @Override public boolean call(String fn, ExprList argList, EvalState state, Value val, ClassAdObjectPool objectPool) throws HyracksDataException { Value listElementValue = objectPool.valuePool.get(); Value listVal = objectPool.valuePool.get(); Value compareVal = objectPool.valuePool.get(); Value stringValue = objectPool.valuePool.get(); ExprList listToCompare = objectPool.exprListPool.get(); boolean needAllMatch; AMutableCharArrayString comparison_string = objectPool.strPool.get(); int comparisonOperator; // We take three arguments: // The operator to use, as a string. // The list // The thing we are comparing against. if (argList.size() != 3) { val.setErrorValue(); return true; } // The first argument must be a string if (!argList.get(0).publicEvaluate(state, stringValue)) { val.setErrorValue(); return false; } else if (stringValue.isUndefinedValue()) { val.setUndefinedValue(); return true; } else if (!stringValue.isStringValue(comparison_string)) { val.setErrorValue(); return true; } // Decide which comparison to do, or give an error switch (comparison_string.toString()) { case "<": comparisonOperator = Operation.OpKind_LESS_THAN_OP; break; case "<=": comparisonOperator = Operation.OpKind_LESS_OR_EQUAL_OP; break; case "!=": comparisonOperator = Operation.OpKind_NOT_EQUAL_OP; break; case "==": comparisonOperator = Operation.OpKind_EQUAL_OP; break; case ">": comparisonOperator = Operation.OpKind_GREATER_THAN_OP; break; case ">=": comparisonOperator = Operation.OpKind_GREATER_OR_EQUAL_OP; break; case "is": comparisonOperator = Operation.OpKind_META_EQUAL_OP; break; case "isnt": comparisonOperator = Operation.OpKind_META_NOT_EQUAL_OP; break; default: val.setErrorValue(); return true; } // The second argument must Evaluate to a list if (!argList.get(1).publicEvaluate(state, listVal)) { val.setErrorValue(); return false; } else if (listVal.isUndefinedValue()) { val.setUndefinedValue(); return true; } else if (!listVal.isListValue(listToCompare)) { val.setErrorValue(); return true; } // The third argument is something to compare against. if (!argList.get(2).publicEvaluate(state, compareVal)) { val.setErrorValue(); return false; } else if (listVal.isUndefinedValue()) { val.setUndefinedValue(); return true; } // Finally, we decide what to do exactly, based on our name. if (fn.equalsIgnoreCase("anycompare")) { needAllMatch = false; val.setBooleanValue(false); } else { needAllMatch = true; val.setBooleanValue(true); } // Walk over the list for (ExprTree listElement : listToCompare.getExprList()) { // For this element of the list, make sure it is // acceptable. if (!listElement.publicEvaluate(state, listElementValue)) { val.setErrorValue(); return false; } else { Value compareResult = objectPool.valuePool.get(); MutableBoolean b = objectPool.boolPool.get(); Operation.operate(comparisonOperator, listElementValue, compareVal, compareResult, objectPool); if (!compareResult.isBooleanValue(b)) { if (compareResult.isUndefinedValue()) { if (needAllMatch) { val.setBooleanValue(false); return true; } } else { val.setErrorValue(); return true; } return true; } else if (b.booleanValue()) { if (!needAllMatch) { val.setBooleanValue(true); return true; } } else { if (needAllMatch) { // we failed, because it didn't match val.setBooleanValue(false); return true; } } } } if (needAllMatch) { // They must have all matched, because nothing failed, // which would have returned. val.setBooleanValue(true); } else { // Nothing must have matched, since we would have already // returned. val.setBooleanValue(false); } return true; } }; public static final ClassAdFunc timeZoneOffset = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value val, ClassAdObjectPool objectPool) throws HyracksDataException { // no arguments if (argList.size() > 0) { val.setErrorValue(); return (true); } val.setRelativeTimeValue(objectPool.classAdTimePool.get()); return (true); } }; public static final ClassAdFunc debug = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value result, ClassAdObjectPool objectPool) throws HyracksDataException { return false; } }; public static final ClassAdFunc formatTime = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value result, ClassAdObjectPool objectPool) throws HyracksDataException { Value time_arg = objectPool.valuePool.get(); Value format_arg = objectPool.valuePool.get(); AMutableInt64 int64 = objectPool.int64Pool.get(); int64.setValue(0); ClassAdTime epoch_time = objectPool.classAdTimePool.get(); ClassAdTime time_components = objectPool.classAdTimePool.get(); time_components.setTimeZone("GMT"); ClassAd splitClassAd = objectPool.classAdPool.get(); String format; int number_of_args; boolean did_eval; did_eval = true; number_of_args = argList.size(); if (number_of_args == 0) { epoch_time.setEpochTime(); Util.getLocalTime(epoch_time, time_components); format = "%c"; make_formatted_time(time_components, format, result); } else if (number_of_args < 3) { // The first argument should be our time and should // not be a relative time. if (!argList.get(0).publicEvaluate(state, time_arg)) { did_eval = false; } else if (time_arg.isRelativeTimeValue()) { result.setErrorValue(); } else if (time_arg.isAbsoluteTimeValue(time_components)) { } else if (!time_arg.isClassAdValue(splitClassAd) /* doSplitTime(time_arg, splitClassAd) */) { result.setErrorValue(); } else { if (!splitClassAd.evaluateAttrInt("Seconds", int64)) { time_components.setSeconds(0); } else { time_components.setSeconds((int) int64.getLongValue()); } if (!splitClassAd.evaluateAttrInt("Minutes", int64)) { time_components.setMinutes(0); } else { time_components.setMinutes((int) int64.getLongValue()); } if (!splitClassAd.evaluateAttrInt("Hours", int64)) { time_components.setHours(0); } else { time_components.setHours((int) int64.getLongValue()); } if (!splitClassAd.evaluateAttrInt("Day", int64)) { time_components.setDayOfMonth(0); } else { time_components.setDayOfMonth((int) int64.getLongValue()); } if (!splitClassAd.evaluateAttrInt("Month", int64)) { time_components.setMonth(0); } else { time_components.setMonth((int) int64.getLongValue() - 1); } if (!splitClassAd.evaluateAttrInt("Year", int64)) { time_components.setYear(0); } else { time_components.setYear((int) int64.getLongValue()); } } // The second argument, if provided, must be a string if (number_of_args == 1) { format = "EEE MMM dd HH:mm:ss yyyy"; make_formatted_time(time_components, format, result); } else { if (!argList.get(1).publicEvaluate(state, format_arg)) { did_eval = false; } else { AMutableCharArrayString formatString = objectPool.strPool.get(); if (!format_arg.isStringValue(formatString)) { result.setErrorValue(); } else { make_formatted_time(time_components, formatString.toString(), result); } } } } else { result.setErrorValue(); } if (!did_eval) { result.setErrorValue(); } return did_eval; } }; public static void make_formatted_time(ClassAdTime time_components, String format, Value result) { //replace c++ format elements with java elements format = format.replace("%m", "MM"); format = format.replace("%d", "dd"); format = format.replace("%Y", "yyyy"); format = format.replace("%M", "mm"); format = format.replace("%S", "ss"); format = format.replace("%A", "EEEE"); format = format.replace("%a", "EEE"); format = format.replace("%B", "MMMM"); format = format.replace("%b", "MMM"); format = format.replace("%H", "HH"); format = format.replace("%Y", "y"); format = format.replace("%", ""); DateFormat df = new SimpleDateFormat(format); df.setTimeZone(TimeZone.getTimeZone("GMT")); result.setStringValue(df.format(time_components.getCalendar().getTime())); } public static final ClassAdFunc getField = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value val, ClassAdObjectPool objectPool) throws HyracksDataException { Value arg = objectPool.valuePool.get(); ClassAdTime asecs = objectPool.classAdTimePool.get(); ClassAdTime rsecs = objectPool.classAdTimePool.get(); ClassAdTime clock = objectPool.classAdTimePool.get(); ClassAdTime tms = objectPool.classAdTimePool.get(); if (argList.size() != 1) { val.setErrorValue(); return (true); } if (!argList.get(0).publicEvaluate(state, arg)) { val.setErrorValue(); return false; } if (arg.isAbsoluteTimeValue(asecs)) { clock.setValue(asecs); Util.getLocalTime(clock, tms); switch (name) { case "getyear": // tm_year is years since 1900 --- make it y2k compliant :-) val.setIntegerValue(tms.getYear()); break; case "getmonth": val.setIntegerValue(tms.getMonth() + 1); break; case "getdayofyear": val.setIntegerValue(tms.getDayOfYear()); break; case "getdayofmonth": val.setIntegerValue(tms.getDayOfMonth()); break; case "getdayofweek": val.setIntegerValue(tms.getDayOfWeek()); break; case "gethours": val.setIntegerValue(tms.getHours()); break; case "getminutes": val.setIntegerValue(tms.getMinutes()); break; case "getseconds": val.setIntegerValue(tms.getSeconds()); break; case "getdays": case "getuseconds": // not meaningful for abstimes val.setErrorValue(); return true; default: throw new HyracksDataException("Should not reach here"); } return (true); } else if (arg.isRelativeTimeValue(rsecs)) { switch (name.toLowerCase()) { case "getyear": case "getmonth": case "getdayofmonth": case "getdayofweek": case "getdayofyear": // not meaningful for reltimes val.setErrorValue(); return true; case "getdays": val.setIntegerValue(rsecs.getRelativeTime() / 86400); break; case "gethours": val.setIntegerValue((rsecs.getRelativeTime() % 86400) / 3600); break; case "getminutes": val.setIntegerValue((rsecs.getRelativeTime() % 3600) / 60); break; case "getseconds": val.setIntegerValue(rsecs.getRelativeTime() % 60); break; default: throw new HyracksDataException("Should not reach here"); } return true; } val.setErrorValue(); return (true); } }; public static final ClassAdFunc currentTime = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value val, ClassAdObjectPool objectPool) throws HyracksDataException { // no arguments if (argList.size() > 0) { val.setErrorValue(); return (true); } Literal time_literal = Literal.createAbsTime(objectPool.classAdTimePool.get(), objectPool); time_literal.GetValue(val); return true; } }; public static final ClassAdFunc splitTime = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value result, ClassAdObjectPool objectPool) throws HyracksDataException { Value arg = objectPool.valuePool.get(); ClassAd split = objectPool.classAdPool.get(); if (argList.size() != 1) { result.setErrorValue(); return true; } if (!argList.get(0).publicEvaluate(state, arg)) { result.setErrorValue(); return false; } if (!arg.isClassAdValue() && doSplitTime(arg, split, objectPool)) { result.setClassAdValue(split); } else { result.setErrorValue(); } return true; } }; public static boolean doSplitTime(Value time, ClassAd splitClassAd, ClassAdObjectPool objectPool) throws HyracksDataException { boolean did_conversion; AMutableInt64 integer = objectPool.int64Pool.get(); integer.setValue(0); AMutableDouble real = objectPool.doublePool.get(); real.setValue(0); ClassAdTime asecs = objectPool.classAdTimePool.get(); ClassAdTime rsecs = objectPool.classAdTimePool.get(); ClassAd classad = objectPool.classAdPool.get(); did_conversion = true; if (time.isIntegerValue(integer)) { asecs.setValue(integer.getLongValue()); asecs.makeLocalAbsolute(); absTimeToClassAd(asecs, splitClassAd); } else if (time.isRealValue(real)) { asecs.setValue((long) real.getDoubleValue()); asecs.makeAbsolute(true); absTimeToClassAd(asecs, splitClassAd); } else if (time.isAbsoluteTimeValue(asecs)) { absTimeToClassAd(asecs, splitClassAd); } else if (time.isRelativeTimeValue(rsecs)) { relTimeToClassAd((rsecs.getRelativeTime() / 1000.0), splitClassAd); } else if (time.isClassAdValue(classad)) { splitClassAd = objectPool.classAdPool.get(); splitClassAd.copyFrom(classad); } else { did_conversion = false; } return did_conversion; } public static void relTimeToClassAd(double rsecs, ClassAd splitClassAd) throws HyracksDataException { int days, hrs, mins; double secs; boolean is_negative; if (rsecs < 0) { rsecs = -rsecs; is_negative = true; } else { is_negative = false; } days = (int) rsecs; hrs = days % 86400; mins = hrs % 3600; secs = (mins % 60) + (rsecs - Math.floor(rsecs)); days = days / 86400; hrs = hrs / 3600; mins = mins / 60; if (is_negative) { if (days > 0) { days = -days; } else if (hrs > 0) { hrs = -hrs; } else if (mins > 0) { mins = -mins; } else { secs = -secs; } } splitClassAd.insertAttr("Type", "RelativeTime"); splitClassAd.insertAttr("Days", days); splitClassAd.insertAttr("Hours", hrs); splitClassAd.insertAttr("Minutes", mins); splitClassAd.insertAttr("Seconds", secs); return; } public static void absTimeToClassAd(ClassAdTime asecs, ClassAd splitClassAd) throws HyracksDataException { ClassAdTime tms = asecs.getGMTCopy(); splitClassAd.insertAttr("Type", "AbsoluteTime"); splitClassAd.insertAttr("Year", tms.getYear()); splitClassAd.insertAttr("Month", tms.getMonth() + 1); splitClassAd.insertAttr("Day", tms.getDayOfMonth()); splitClassAd.insertAttr("Hours", tms.getHours()); splitClassAd.insertAttr("Minutes", tms.getMinutes()); splitClassAd.insertAttr("Seconds", tms.getSeconds()); // Note that we convert the timezone from seconds to minutes. splitClassAd.insertAttr("Offset", asecs.getOffset() / 1000); return; } public static final ClassAdFunc dayTime = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value val, ClassAdObjectPool objectPool) throws HyracksDataException { val.setRelativeTimeValue(objectPool.classAdTimePool.get()); return (true); } }; public static final ClassAdFunc epochTime = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value val, ClassAdObjectPool objectPool) throws HyracksDataException { // no arguments if (argList.size() > 0) { val.setErrorValue(); return (true); } val.setIntegerValue(0); return (true); } }; public static final ClassAdFunc strCat = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value result, ClassAdObjectPool objectPool) throws HyracksDataException { AMutableCharArrayString buf = objectPool.strPool.get(); AMutableCharArrayString s = objectPool.strPool.get(); boolean errorFlag = false; boolean undefFlag = false; boolean rval = false; Value val = objectPool.valuePool.get(); Value stringVal = objectPool.valuePool.get(); for (int i = 0; i < argList.size(); i++) { s.reset(); if (!(rval = argList.get(i).publicEvaluate(state, val))) { break; } if (val.isStringValue(s)) { buf.appendString(s); } else { Value.convertValueToStringValue(val, stringVal, objectPool); if (stringVal.isUndefinedValue()) { undefFlag = true; break; } else if (stringVal.isErrorValue()) { errorFlag = true; result.setErrorValue(); break; } else if (stringVal.isStringValue(s)) { buf.appendString(s); } else { errorFlag = true; break; } } } // failed evaluating some argument if (!rval) { result.setErrorValue(); return (false); } // type error if (errorFlag) { result.setErrorValue(); return (true); } // some argument was undefined if (undefFlag) { result.setUndefinedValue(); return (true); } result.setStringValue(buf); return (true); } }; public static final ClassAdFunc changeCase = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value result, ClassAdObjectPool objectPool) throws HyracksDataException { Value val = objectPool.valuePool.get(); Value stringVal = objectPool.valuePool.get(); AMutableCharArrayString str = objectPool.strPool.get(); boolean lower = name.equalsIgnoreCase("tolower"); int len; // only one argument if (argList.size() != 1) { result.setErrorValue(); return true; } // check for evaluation failure if (!argList.get(0).publicEvaluate(state, val)) { result.setErrorValue(); return false; } if (!val.isStringValue(str)) { Value.convertValueToStringValue(val, stringVal, objectPool); if (stringVal.isUndefinedValue()) { result.setUndefinedValue(); return true; } else if (stringVal.isErrorValue()) { result.setErrorValue(); return true; } else if (!stringVal.isStringValue(str)) { result.setErrorValue(); return true; } } len = str.size(); for (int i = 0; i <= len; i++) { str.setChar(i, lower ? Character.toLowerCase(str.charAt(i)) : Character.toUpperCase(str.charAt(i))); } result.setStringValue(str); return (true); } }; public static final ClassAdFunc subString = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value result, ClassAdObjectPool objectPool) throws HyracksDataException { Value arg0 = objectPool.valuePool.get(); Value arg1 = objectPool.valuePool.get(); Value arg2 = objectPool.valuePool.get(); AMutableCharArrayString buf = objectPool.strPool.get(); AMutableInt64 offset = objectPool.int64Pool.get(); offset.setValue(0); AMutableInt64 len = objectPool.int64Pool.get(); len.setValue(0); AMutableInt64 alen = objectPool.int64Pool.get(); len.setValue(0); // two or three arguments if (argList.size() < 2 || argList.size() > 3) { result.setErrorValue(); return (true); } // Evaluate all arguments if (!argList.get(0).publicEvaluate(state, arg0) || !argList.get(1).publicEvaluate(state, arg1) || (argList.size() > 2 && !argList.get(2).publicEvaluate(state, arg2))) { result.setErrorValue(); return (false); } // strict on undefined if (arg0.isUndefinedValue() || arg1.isUndefinedValue() || (argList.size() > 2 && arg2.isUndefinedValue())) { result.setUndefinedValue(); return (true); } // arg0 must be string, arg1 must be int, arg2 (if given) must be int if (!arg0.isStringValue(buf) || !arg1.isIntegerValue(offset) || (argList.size() > 2 && !arg2.isIntegerValue(len))) { result.setErrorValue(); return (true); } // perl-like substr; negative offsets and lengths count from the end // of the string alen.setValue(buf.size()); if (offset.getLongValue() < 0) { offset.setValue(alen.getLongValue() + offset.getLongValue()); } else if (offset.getLongValue() >= alen.getLongValue()) { offset.setValue(alen.getLongValue()); } if (len.getLongValue() <= 0) { len.setValue(alen.getLongValue() - offset.getLongValue() + len.getLongValue()); if (len.getLongValue() < 0) { len.setValue(0); } } else if (len.getLongValue() > alen.getLongValue() - offset.getLongValue()) { len.setValue(alen.getLongValue() - offset.getLongValue()); } // to make sure that if length is specified as 0 explicitly // then, len is set to 0 if (argList.size() == 3) { AMutableInt64 templen = objectPool.int64Pool.get(); templen.setValue(0); arg2.isIntegerValue(templen); if (templen.getLongValue() == 0) { len.setValue(0); } } result.setStringValue(buf.substr((int) offset.getLongValue(), (int) len.getLongValue())); return (true); } }; public static final ClassAdFunc convInt = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value result, ClassAdObjectPool objectPool) throws HyracksDataException { Value arg = objectPool.valuePool.get(); // takes exactly one argument if (argList.size() != 1) { result.setErrorValue(); return (true); } if (!argList.get(0).publicEvaluate(state, arg)) { result.setErrorValue(); return (false); } Value.convertValueToIntegerValue(arg, result, objectPool); return true; } }; public static final ClassAdFunc compareString = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value result, ClassAdObjectPool objectPool) throws HyracksDataException { Value arg0 = objectPool.valuePool.get(); Value arg1 = objectPool.valuePool.get(); Value arg0_s = objectPool.valuePool.get(); Value arg1_s = objectPool.valuePool.get(); // Must have two arguments if (argList.size() != 2) { result.setErrorValue(); return (true); } // Evaluate both arguments if (!argList.get(0).publicEvaluate(state, arg0) || !argList.get(1).publicEvaluate(state, arg1)) { result.setErrorValue(); return false; } // If either argument is undefined, then the result is // undefined. if (arg0.isUndefinedValue() || arg1.isUndefinedValue()) { result.setUndefinedValue(); return true; } AMutableCharArrayString s0 = objectPool.strPool.get(); AMutableCharArrayString s1 = objectPool.strPool.get(); if (Value.convertValueToStringValue(arg0, arg0_s, objectPool) && Value.convertValueToStringValue(arg1, arg1_s, objectPool) && arg0_s.isStringValue(s0) && arg1_s.isStringValue(s1)) { int order; if (name.equalsIgnoreCase("strcmp")) { order = s0.compareTo(s1); if (order < 0) { order = -1; } else if (order > 0) { order = 1; } } else { order = s0.compareToIgnoreCase(s1); if (order < 0) { order = -1; } else if (order > 0) { order = 1; } } result.setIntegerValue(order); } else { result.setErrorValue(); } return (true); } }; public static final ClassAdFunc matchPattern = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value result, ClassAdObjectPool objectPool) throws HyracksDataException { boolean have_options; Value arg0 = objectPool.valuePool.get(); Value arg1 = objectPool.valuePool.get(); Value arg2 = objectPool.valuePool.get(); AMutableCharArrayString pattern = objectPool.strPool.get(); AMutableCharArrayString target = objectPool.strPool.get(); AMutableCharArrayString options_string = objectPool.strPool.get(); // need two or three arguments: pattern, string, optional settings if (argList.size() != 2 && argList.size() != 3) { result.setErrorValue(); return (true); } if (argList.size() == 2) { have_options = false; } else { have_options = true; } // Evaluate args if (!argList.get(0).publicEvaluate(state, arg0) || !argList.get(1).publicEvaluate(state, arg1)) { result.setErrorValue(); return (false); } if (have_options && !argList.get(2).publicEvaluate(state, arg2)) { result.setErrorValue(); return (false); } // if either arg is error, the result is error if (arg0.isErrorValue() || arg1.isErrorValue()) { result.setErrorValue(); return (true); } if (have_options && arg2.isErrorValue()) { result.setErrorValue(); return (true); } // if either arg is undefined, the result is undefined if (arg0.isUndefinedValue() || arg1.isUndefinedValue()) { result.setUndefinedValue(); return (true); } if (have_options && arg2.isUndefinedValue()) { result.setUndefinedValue(); return (true); } else if (have_options && !arg2.isStringValue(options_string)) { result.setErrorValue(); return (true); } // if either argument is not a string, the result is an error if (!arg0.isStringValue(pattern) || !arg1.isStringValue(target)) { result.setErrorValue(); return (true); } return regexp_helper(pattern.toString(), target, null, have_options, options_string.toString(), result); } }; private static boolean regexp_helper(String pattern, AMutableCharArrayString target, String replace, boolean have_options, String options_string, Value result) { int options = 0; //pattern = pattern.replaceAll(""); //pattern = pattern.replaceAll("?", "."); Pattern re; if (have_options) { // We look for the options we understand, and ignore // any others that we might find, hopefully allowing // forwards compatibility. if (options_string.contains("i")) { options |= Pattern.CASE_INSENSITIVE; } } // compile the patern re = Pattern.compile(pattern, options); Matcher matcher = re.matcher(target.toString()); if (matcher.matches()) { result.setBooleanValue(true); return (true); } else { result.setBooleanValue(false); return (true); } } public static final ClassAdFunc matchPatternMember = null; public static final ClassAdFunc substPattern = null; public static final ClassAdFunc convReal = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value result, ClassAdObjectPool objectPool) throws HyracksDataException { Value arg = objectPool.valuePool.get(); // takes exactly one argument if (argList.size() != 1) { result.setErrorValue(); return (true); } if (!argList.get(0).publicEvaluate(state, arg)) { result.setErrorValue(); return (false); } Value.convertValueToRealValue(arg, result, objectPool); return true; } }; public static final ClassAdFunc convString = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value result, ClassAdObjectPool objectPool) throws HyracksDataException { Value arg = objectPool.valuePool.get(); // takes exactly one argument if (argList.size() != 1) { result.setErrorValue(); return (true); } if (!argList.get(0).publicEvaluate(state, arg)) { result.setErrorValue(); return (false); } Value.convertValueToStringValue(arg, result, objectPool); return true; } }; public static final ClassAdFunc unparse = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value result, ClassAdObjectPool objectPool) throws HyracksDataException { if (argList.size() != 1 || argList.get(0).getKind() != NodeKind.ATTRREF_NODE) { result.setErrorValue(); } else { // use the printpretty on arg0 to spew out PrettyPrint unp = objectPool.prettyPrintPool.get(); AMutableCharArrayString szAttribute = objectPool.strPool.get(); AMutableCharArrayString szValue = objectPool.strPool.get(); ExprTree pTree; unp.unparse(szAttribute, argList.get(0)); // look them up argument within context of the ad. if (state.getCurAd() != null && (pTree = state.getCurAd().lookup(szAttribute.toString())) != null) { unp.unparse(szValue, pTree); } result.setStringValue(szValue); } return (true); } }; public static final ClassAdFunc convBool = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value result, ClassAdObjectPool objectPool) throws HyracksDataException { Value arg = objectPool.valuePool.get(); // takes exactly one argument if (argList.size() != 1) { result.setErrorValue(); return (true); } if (!argList.get(0).publicEvaluate(state, arg)) { result.setErrorValue(); return (false); } switch (arg.getType()) { case UNDEFINED_VALUE: result.setUndefinedValue(); return (true); case ERROR_VALUE: case CLASSAD_VALUE: case LIST_VALUE: case SLIST_VALUE: case ABSOLUTE_TIME_VALUE: result.setErrorValue(); return (true); case BOOLEAN_VALUE: result.setValue(arg); return (true); case INTEGER_VALUE: { AMutableInt64 ival = objectPool.int64Pool.get(); ival.setValue(0); arg.isIntegerValue(ival); result.setBooleanValue(ival.getLongValue() != 0); return (true); } case REAL_VALUE: { AMutableDouble rval = objectPool.doublePool.get(); arg.isRealValue(rval); result.setBooleanValue(rval.getDoubleValue() != 0.0); return (true); } case STRING_VALUE: { AMutableCharArrayString buf = objectPool.strPool.get(); arg.isStringValue(buf); if (buf.equalsIgnoreCase("false") || buf.size() == 0) { result.setBooleanValue(false); } else { result.setBooleanValue(true); } return (true); } case RELATIVE_TIME_VALUE: { ClassAdTime rsecs = objectPool.classAdTimePool.get(); arg.isRelativeTimeValue(rsecs); result.setBooleanValue(rsecs.getTimeInMillis() != 0); return (true); } default: throw new HyracksDataException("Should not reach here"); } } }; public static final ClassAdFunc convTime = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value result, ClassAdObjectPool objectPool) throws HyracksDataException { Value arg = objectPool.valuePool.get(); Value arg2 = objectPool.valuePool.get(); boolean relative = name.equalsIgnoreCase("reltime"); boolean secondarg = false; // says whether a 2nd argument exists AMutableInt64 arg2num = objectPool.int64Pool.get(); arg2num.setValue(0); if (argList.size() == 0 && !relative) { // absTime with no arguments returns the current time. return currentTime.call(name, argList, state, result, objectPool); } if ((argList.size() < 1) || (argList.size() > 2)) { result.setErrorValue(); return (true); } if (!argList.get(0).publicEvaluate(state, arg)) { result.setErrorValue(); return (false); } if (argList.size() == 2) { // we have a 2nd argument secondarg = true; if (!argList.get(1).publicEvaluate(state, arg2)) { result.setErrorValue(); return (false); } AMutableInt64 ivalue2 = objectPool.int64Pool.get(); ivalue2.setValue(0); AMutableDouble rvalue2 = objectPool.doublePool.get(); ClassAdTime rsecs = objectPool.classAdTimePool.get(); if (relative) {// 2nd argument is N/A for reltime result.setErrorValue(); return (true); } // 2nd arg should be integer, real or reltime else if (arg2.isIntegerValue(ivalue2)) { arg2num.setValue(ivalue2.getLongValue()); } else if (arg2.isRealValue(rvalue2)) { arg2num.setValue((long) rvalue2.getDoubleValue()); } else if (arg2.isRelativeTimeValue(rsecs)) { arg2num.setValue(rsecs.getTimeInMillis()); } else { result.setErrorValue(); return (true); } } else { secondarg = false; arg2num.setValue(0); } switch (arg.getType()) { case UNDEFINED_VALUE: result.setUndefinedValue(); return (true); case ERROR_VALUE: case CLASSAD_VALUE: case LIST_VALUE: case SLIST_VALUE: case BOOLEAN_VALUE: result.setErrorValue(); return (true); case INTEGER_VALUE: { AMutableInt64 ivalue = objectPool.int64Pool.get(); ivalue.setValue(0); arg.isIntegerValue(ivalue); if (relative) { ClassAdTime time = objectPool.classAdTimePool.get(); time.setRelativeTime(ivalue.getLongValue()); result.setRelativeTimeValue(time); } else { ClassAdTime atvalue = objectPool.classAdTimePool.get(); atvalue.setValue(ivalue.getLongValue()); if (secondarg) { atvalue.setTimeZone((int) arg2num.getLongValue()); } else { // the default offset is the current timezone atvalue.setTimeZone(Literal.findOffset(atvalue)); } if (atvalue.getOffset() == -1) { result.setErrorValue(); return (false); } else { result.setAbsoluteTimeValue(atvalue); } } return (true); } case REAL_VALUE: { AMutableDouble rvalue = objectPool.doublePool.get(); arg.isRealValue(rvalue); if (relative) { ClassAdTime time = objectPool.classAdTimePool.get(); time.setRelativeTime((long) (1000 * rvalue.getDoubleValue())); result.setRelativeTimeValue(time); } else { ClassAdTime atvalue = objectPool.classAdTimePool.get(); atvalue.setValue((long) rvalue.getDoubleValue()); if (secondarg) { atvalue.setTimeZone((int) arg2num.getLongValue()); } else { // the default offset is the current timezone atvalue.setTimeZone(Literal.findOffset(atvalue)); } result.setAbsoluteTimeValue(atvalue); } return (true); } case STRING_VALUE: { //should'nt come here // a string argument to this function is transformed to a literal directly } case ABSOLUTE_TIME_VALUE: { ClassAdTime secs = objectPool.classAdTimePool.get(); arg.isAbsoluteTimeValue(secs); if (relative) { result.setRelativeTimeValue(secs); } else { result.setValue(arg); } return (true); } case RELATIVE_TIME_VALUE: { if (relative) { result.setValue(arg); } else { ClassAdTime secs = objectPool.classAdTimePool.get(); arg.isRelativeTimeValue(secs); ClassAdTime atvalue = objectPool.classAdTimePool.get(); atvalue.setValue(secs); if (secondarg) { atvalue.setTimeZone((int) arg2num.getLongValue()); } else { // the default offset is the current timezone atvalue.setTimeZone(Literal.findOffset(atvalue)); } result.setAbsoluteTimeValue(atvalue); } return (true); } default: throw new HyracksDataException("Should not reach here"); } } }; public static final ClassAdFunc doRound = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value result, ClassAdObjectPool objectPool) throws HyracksDataException { Value arg = objectPool.valuePool.get(); Value realValue = objectPool.valuePool.get(); // takes exactly one argument if (argList.size() != 1) { result.setErrorValue(); return (true); } if (!argList.get(0).publicEvaluate(state, arg)) { result.setErrorValue(); return (false); } if (arg.getType() == ValueType.INTEGER_VALUE) { result.setValue(arg); } else { if (!Value.convertValueToRealValue(arg, realValue, objectPool)) { result.setErrorValue(); } else { AMutableDouble rvalue = objectPool.doublePool.get(); realValue.isRealValue(rvalue); if (name.equalsIgnoreCase("floor")) { result.setIntegerValue((long) Math.floor(rvalue.getDoubleValue())); } else if (name.equalsIgnoreCase("ceil") || name.equalsIgnoreCase("ceiling")) { result.setIntegerValue((long) Math.ceil(rvalue.getDoubleValue())); } else if (name.equalsIgnoreCase("round")) { result.setIntegerValue(Math.round(rvalue.getDoubleValue())); } else { result.setErrorValue(); } } } return true; } }; public static final ClassAdFunc doMath2 = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value result, ClassAdObjectPool objectPool) throws HyracksDataException { Value arg = objectPool.valuePool.get(); Value arg2 = objectPool.valuePool.get(); // takes 2 arguments pow(val,base) if (argList.size() != 2) { result.setErrorValue(); return (true); } if (!argList.get(0).publicEvaluate(state, arg) || !argList.get(1).publicEvaluate(state, arg2)) { result.setErrorValue(); return (false); } if (name.equalsIgnoreCase("pow")) { // take arg2 to the power of arg2 AMutableInt64 ival = objectPool.int64Pool.get(); ival.setValue(0); AMutableInt64 ibase = objectPool.int64Pool.get(); ibase.setValue(0); if (arg.isIntegerValue(ival) && arg2.isIntegerValue(ibase) && ibase.getLongValue() >= 0) { ival.setValue((long) (Math.pow(ival.getLongValue(), ibase.getLongValue()))); result.setIntegerValue(ival.getLongValue()); } else { Value realValue = objectPool.valuePool.get(); Value realBase = objectPool.valuePool.get(); if (!Value.convertValueToRealValue(arg, realValue, objectPool) || !Value.convertValueToRealValue(arg2, realBase, objectPool)) { result.setErrorValue(); } else { AMutableDouble rvalue = objectPool.doublePool.get(); rvalue.setValue(0); AMutableDouble rbase = objectPool.doublePool.get(); rbase.setValue(1); realValue.isRealValue(rvalue); realBase.isRealValue(rbase); result.setRealValue(Math.pow(rvalue.getDoubleValue(), rbase.getDoubleValue())); } } } else if (name.equalsIgnoreCase("quantize")) { // quantize arg1 to the next integral multiple of arg2 // if arg2 is a list, choose the first item from the list that is larger than arg1 // if arg1 is larger than all of the items in the list, the result is an error. Value val = objectPool.valuePool.get(); Value base = objectPool.valuePool.get(); if (!Value.convertValueToRealValue(arg, val, objectPool)) { result.setErrorValue(); } else { // get the value to quantize into rval. AMutableDouble rval = objectPool.doublePool.get(); AMutableDouble rbase = objectPool.doublePool.get(); val.isRealValue(rval); if (arg2.isListValue()) { ExprList list = objectPool.exprListPool.get(); arg2.isListValue(list); base.setRealValue(0.0); rbase.setValue(0.0); // treat an empty list as 'don't quantize' for (ExprTree expr : list.getExprList()) { if (!expr.publicEvaluate(state, base)) { result.setErrorValue(); return false; // eval should not fail } if (Value.convertValueToRealValue(base, val, objectPool)) { val.isRealValue(rbase); if (rbase.getDoubleValue() >= rval.getDoubleValue()) { result.setValue(base); return true; } } else { //TJ: should we ignore values that can't be converted? result.setErrorValue(); return true; } } // at this point base is the value of the last expression in the list. // and rbase is the real value of it and rval > rbase. // when this happens we want to quantize on multiples of the last // list value, as if on a single value were passed rather than a list. arg2.setValue(base); } else { // if arg2 is not a list, then it must evaluate to a real value // or we can't use it. (note that if it's an int, we still want // to return an int, but we assume that all ints can be converted to real) if (!Value.convertValueToRealValue(arg2, base, objectPool)) { result.setErrorValue(); return true; } base.isRealValue(rbase); } // at this point rbase should contain the real value of either arg2 or the // last entry in the list. and rval should contain the value to be quantized. AMutableInt64 ival = objectPool.int64Pool.get(); ival.setValue(0); AMutableInt64 ibase = objectPool.int64Pool.get(); ibase.setValue(0); if (arg2.isIntegerValue(ibase)) { // quantize to an integer base, if (ibase.getLongValue() == 0L) { result.setValue(arg); } else if (arg.isIntegerValue(ival)) { ival.setValue(((ival.getLongValue() + ibase.getLongValue() - 1) / ibase.getLongValue()) * ibase.getLongValue()); result.setIntegerValue(ival.getLongValue()); } else { rval.setValue( Math.ceil(rval.getDoubleValue() / ibase.getLongValue()) * ibase.getLongValue()); result.setRealValue(rval); } } else { double epsilon = 1e-8; if (rbase.getDoubleValue() >= -epsilon && rbase.getDoubleValue() <= epsilon) { result.setValue(arg); } else { // we already have the real-valued base in rbase so just use it here. rval.setValue(Math.ceil(rval.getDoubleValue() / rbase.getDoubleValue()) * rbase.getDoubleValue()); result.setRealValue(rval); } } } } else { // unknown 2 argument math function result.setErrorValue(); } return true; } }; public static final ClassAdFunc random = new ClassAdFunc() { private Random randomGenerator = new Random(System.currentTimeMillis()); @Override public boolean call(String name, ExprList argList, EvalState state, Value result, ClassAdObjectPool objectPool) throws HyracksDataException { Value arg = objectPool.valuePool.get(); ; // takes exactly one argument if (argList.size() > 1) { result.setErrorValue(); return (true); } else if (argList.size() == 0) { arg.setRealValue(1.0); } else if (!argList.get(0).publicEvaluate(state, arg)) { result.setErrorValue(); return (false); } AMutableInt64 int_max = objectPool.int64Pool.get(); int_max.setValue(0); AMutableDouble double_max = objectPool.doublePool.get(); if (arg.isIntegerValue(int_max)) { int random_int = randomGenerator.nextInt((int) int_max.getLongValue()); result.setIntegerValue(random_int); } else if (arg.isRealValue(double_max)) { double random_double = double_max.getDoubleValue() * randomGenerator.nextDouble(); result.setRealValue(random_double); } else { result.setErrorValue(); } return true; } }; public static final ClassAdFunc ifThenElse = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value result, ClassAdObjectPool objectPool) throws HyracksDataException { Value arg1 = objectPool.valuePool.get(); MutableBoolean arg1_bool = objectPool.boolPool.get(); // takes exactly three arguments if (argList.size() != 3) { result.setErrorValue(); return (true); } if (!argList.get(0).publicEvaluate(state, arg1)) { result.setErrorValue(); return (false); } switch (arg1.getType()) { case BOOLEAN_VALUE: if (!arg1.isBooleanValue(arg1_bool)) { result.setErrorValue(); return (false); } break; case INTEGER_VALUE: { AMutableInt64 intval = objectPool.int64Pool.get(); intval.setValue(0); if (!arg1.isIntegerValue(intval)) { result.setErrorValue(); return (false); } arg1_bool.setValue(intval.getLongValue() != 0L); break; } case REAL_VALUE: { AMutableDouble realval = objectPool.doublePool.get(); if (!arg1.isRealValue(realval)) { result.setErrorValue(); return (false); } arg1_bool.setValue(realval.getDoubleValue() != 0.0); break; } case UNDEFINED_VALUE: result.setUndefinedValue(); return (true); case ERROR_VALUE: case CLASSAD_VALUE: case LIST_VALUE: case SLIST_VALUE: case STRING_VALUE: case ABSOLUTE_TIME_VALUE: case RELATIVE_TIME_VALUE: case NULL_VALUE: result.setErrorValue(); return (true); } if (arg1_bool.booleanValue()) { if (!argList.get(1).publicEvaluate(state, result)) { result.setErrorValue(); return (false); } } else { if (!argList.get(2).publicEvaluate(state, result)) { result.setErrorValue(); return (false); } } return true; } }; public static final ClassAdFunc stringListsIntersect = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value result, ClassAdObjectPool objectPool) throws HyracksDataException { Value arg0 = objectPool.valuePool.get(); Value arg1 = objectPool.valuePool.get(); Value arg2 = objectPool.valuePool.get(); boolean have_delimiter; AMutableCharArrayString str0 = objectPool.strPool.get(); AMutableCharArrayString str1 = objectPool.strPool.get(); AMutableCharArrayString delimiter_string = objectPool.strPool.get(); // need two or three arguments: pattern, list, optional settings if (argList.size() != 2 && argList.size() != 3) { result.setErrorValue(); return true; } if (argList.size() == 2) { have_delimiter = false; } else { have_delimiter = true; } // Evaluate args if (!argList.get(0).publicEvaluate(state, arg0) || !argList.get(1).publicEvaluate(state, arg1)) { result.setErrorValue(); return true; } if (have_delimiter && !argList.get(2).publicEvaluate(state, arg2)) { result.setErrorValue(); return true; } // if either arg is error, the result is error if (arg0.isErrorValue() || arg1.isErrorValue()) { result.setErrorValue(); return true; } if (have_delimiter && arg2.isErrorValue()) { result.setErrorValue(); return true; } // if either arg is undefined, the result is undefined if (arg0.isUndefinedValue() || arg1.isUndefinedValue()) { result.setUndefinedValue(); return true; } if (have_delimiter && arg2.isUndefinedValue()) { result.setUndefinedValue(); return true; } else if (have_delimiter && !arg2.isStringValue(delimiter_string)) { result.setErrorValue(); return true; } // if the arguments are not of the correct types, the result // is an error if (!arg0.isStringValue(str0) || !arg1.isStringValue(str1)) { result.setErrorValue(); return true; } result.setBooleanValue(false); List<String> list0 = objectPool.stringArrayListPool.get(); Set<String> set1 = new HashSet<String>(); split_string_list(str0, have_delimiter ? delimiter_string.charAt(0) : ',', list0); split_string_set(str1, have_delimiter ? delimiter_string.charAt(0) : ',', set1); for (String str : list0) { if (set1.contains(str)) { result.setBooleanValue(true); break; } } return true; } }; public static final ClassAdFunc interval = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value result, ClassAdObjectPool objectPool) throws HyracksDataException { Value arg = objectPool.valuePool.get(); Value intarg = objectPool.valuePool.get(); AMutableInt64 tot_secs = objectPool.int64Pool.get(); tot_secs.setValue(0); // takes exactly one argument if (argList.size() != 1) { result.setErrorValue(); return (true); } if (!argList.get(0).publicEvaluate(state, arg)) { result.setErrorValue(); return (false); } if (!Value.convertValueToIntegerValue(arg, intarg, objectPool)) { result.setErrorValue(); return (true); } if (!intarg.isIntegerValue(tot_secs)) { result.setErrorValue(); return (true); } long days = tot_secs.getLongValue() / (3600 * 24); tot_secs.setValue(tot_secs.getLongValue() % (3600 * 24)); long hours = tot_secs.getLongValue() / 3600; tot_secs.setValue(tot_secs.getLongValue() % 3600); long min = tot_secs.getLongValue() / 60; long secs = tot_secs.getLongValue() % 60; String strval; if (days != 0) { strval = String.format("%d+%02d:%02d:%02d", days, Math.abs(hours), Math.abs(min), Math.abs(secs)); } else if (hours != 0) { strval = String.format("%d:%02d:%02d", hours, Math.abs(min), Math.abs(secs)); } else if (min != 0) { strval = String.format("%d:%02d", min, Math.abs(secs)); } else { strval = String.format("%d", secs); } result.setStringValue(strval); return true; } }; public static final ClassAdFunc eval = new ClassAdFunc() { @Override public boolean call(String name, ExprList argList, EvalState state, Value result, ClassAdObjectPool objectPool) throws HyracksDataException { Value arg = objectPool.valuePool.get(); Value strarg = objectPool.valuePool.get(); // takes exactly one argument if (argList.size() != 1) { result.setErrorValue(); return true; } if (!argList.get(0).publicEvaluate(state, arg)) { result.setErrorValue(); return false; } ClassAdParser parser = objectPool.classAdParserPool.get(); ExprTreeHolder expr = objectPool.mutableExprPool.get(); AMutableCharArrayString s = objectPool.strPool.get(); if (!Value.convertValueToStringValue(arg, strarg, objectPool) || !strarg.isStringValue(s)) { result.setErrorValue(); return true; } if (state.getDepthRemaining() <= 0) { result.setErrorValue(); return false; } expr.reset(); try { if (!parser.parseExpression(s.toString(), expr, true) || (expr.getInnerTree() == null)) { result.setErrorValue(); return true; } } catch (IOException e) { throw new HyracksDataException(e); } state.decrementDepth(); expr.setParentScope(state.getCurAd()); boolean eval_ok = expr.publicEvaluate(state, result); state.incrementDepth(); if (!eval_ok) { result.setErrorValue(); return false; } return true; } }; public static void split_string_list(AMutableCharArrayString amutableString, char delim, List<String> list) { if (amutableString.getLength() == 0) { return; } int index = 0; int lastIndex = 0; while (index < amutableString.getLength()) { index = amutableString.firstIndexOf(delim, lastIndex); if (index > 0) { list.add(amutableString.substr(lastIndex, index - lastIndex).trim()); lastIndex = index + 1; } else { if (amutableString.getLength() > lastIndex) { list.add(amutableString.substr(lastIndex).trim()); } break; } } } public static void split_string_set(AMutableCharArrayString amutableString, char delim, Set<String> set) { if (amutableString.getLength() == 0) { return; } int index = 0; int lastIndex = 0; while (index < amutableString.getLength()) { index = amutableString.firstIndexOf(delim, lastIndex); if (index > 0) { set.add(amutableString.substr(lastIndex, index - lastIndex).trim()); lastIndex = index + 1; } else { if (amutableString.getLength() > lastIndex) { set.add(amutableString.substr(lastIndex).trim()); } break; } } } }