asterixdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From amo...@apache.org
Subject [15/34] incubator-asterixdb git commit: Enabled Feed Tests and Added External Library tests
Date Mon, 22 Feb 2016 22:35:03 GMT
http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/ac683db0/asterix-external-data/src/test/java/org/apache/asterix/external/classad/BuiltinClassAdFunctions.java
----------------------------------------------------------------------
diff --git a/asterix-external-data/src/test/java/org/apache/asterix/external/classad/BuiltinClassAdFunctions.java b/asterix-external-data/src/test/java/org/apache/asterix/external/classad/BuiltinClassAdFunctions.java
new file mode 100644
index 0000000..97ebd6c
--- /dev/null
+++ b/asterix-external-data/src/test/java/org/apache/asterix/external/classad/BuiltinClassAdFunctions.java
@@ -0,0 +1,1927 @@
+/*
+ * 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.ArrayList;
+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.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) 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) throws HyracksDataException {
+            Value arg0 = new Value();
+            Value arg1 = new Value();
+            Value cArg = new Value();
+
+            ExprList el = new ExprList();
+            MutableBoolean b = new MutableBoolean();
+            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 = new Value();
+                swap.copyFrom(arg0);
+                arg0.copyFrom(arg1);
+                arg1.copyFrom(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);
+                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) throws HyracksDataException {
+            Value arg = new Value();
+            ExprList listToSize = new ExprList();
+            ClassAd classadToSize = new ClassAd();
+            AMutableInt32 length = new AMutableInt32(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) throws HyracksDataException {
+
+            Value listElementValue = new Value();
+            Value listVal = new Value();
+            Value numElements = new Value();
+            Value result = new Value();
+            ExprList listToSum = new ExprList();
+            MutableBoolean first = new MutableBoolean();
+            AMutableInt64 len = new AMutableInt64(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.copyFrom(listElementValue);
+                    first.setValue(false);
+                } else {
+                    Operation.operate(Operation.OpKind_ADDITION_OP, result, listElementValue, result);
+                }
+
+            }
+
+            // if the sum() function was called, we don't need to find the average
+            if (onlySum) {
+                val.copyFrom(result);
+                return true;
+            }
+
+            if (len.getLongValue() > 0) {
+                numElements.setRealValue(len.getLongValue());
+                Operation.operate(Operation.OpKind_DIVISION_OP, result, numElements, result);
+            } else {
+                val.setUndefinedValue();
+            }
+
+            val.copyFrom(result);
+            return true;
+        }
+
+    };
+    public static final ClassAdFunc MinMax = new ClassAdFunc() {
+
+        @Override
+        public boolean call(String fn, ExprList argList, EvalState state, Value val) throws HyracksDataException {
+            Value listElementValue = new Value();
+            Value listVal = new Value();
+            Value cmp = new Value();
+            Value result = new Value();
+            ExprList listToBound = new ExprList();
+            boolean first = true;
+            MutableBoolean b = new MutableBoolean(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.copyFrom(listElementValue);
+                    first = false;
+                } else {
+                    Operation.operate(comparisonOperator, listElementValue, result, cmp);
+                    if (cmp.isBooleanValue(b) && b.booleanValue()) {
+                        result.copyFrom(listElementValue);
+                    }
+                }
+            }
+
+            val.copyFrom(result);
+            return true;
+        }
+
+    };
+    public static final ClassAdFunc ListCompare = new ClassAdFunc() {
+
+        @Override
+        public boolean call(String fn, ExprList argList, EvalState state, Value val) throws HyracksDataException {
+
+            Value listElementValue = new Value();
+            Value listVal = new Value();
+            Value compareVal = new Value();
+            Value stringValue = new Value();
+            ExprList listToCompare = new ExprList();
+            boolean needAllMatch;
+            AMutableCharArrayString comparison_string = new AMutableCharArrayString();
+            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 = new Value();
+                    MutableBoolean b = new MutableBoolean();
+
+                    Operation.operate(comparisonOperator, listElementValue, compareVal, compareResult);
+                    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) throws HyracksDataException {
+            // no arguments
+            if (argList.size() > 0) {
+                val.setErrorValue();
+                return (true);
+            }
+            val.setRelativeTimeValue(new ClassAdTime());
+            return (true);
+        }
+    };
+    public static final ClassAdFunc debug = new ClassAdFunc() {
+        @Override
+        public boolean call(String name, ExprList argList, EvalState state, Value result) throws HyracksDataException {
+            return false;
+        }
+    };
+    public static final ClassAdFunc formatTime = new ClassAdFunc() {
+
+        @Override
+        public boolean call(String name, ExprList argList, EvalState state, Value result) throws HyracksDataException {
+            Value time_arg = new Value();
+            Value format_arg = new Value();
+            AMutableInt64 int64 = new AMutableInt64(0);
+            ClassAdTime epoch_time = new ClassAdTime();
+            ClassAdTime time_components = new ClassAdTime("GMT");
+            ClassAd splitClassAd = new ClassAd();
+            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 = new AMutableCharArrayString();
+                        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) throws HyracksDataException {
+            Value arg = new Value();
+            ClassAdTime asecs = new ClassAdTime();
+            ClassAdTime rsecs = new ClassAdTime();
+            ClassAdTime clock = new ClassAdTime();
+            ClassAdTime tms = new ClassAdTime();
+
+            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) throws HyracksDataException {
+            // no arguments
+            if (argList.size() > 0) {
+                val.setErrorValue();
+                return (true);
+            }
+            Literal time_literal = Literal.createAbsTime(new ClassAdTime());
+            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) throws HyracksDataException {
+            Value arg = new Value();
+            ClassAd split = new ClassAd();
+
+            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)) {
+                result.setClassAdValue(split);
+            } else {
+                result.setErrorValue();
+            }
+            return true;
+        }
+
+    };
+
+    public static boolean doSplitTime(Value time, ClassAd splitClassAd) throws HyracksDataException {
+        boolean did_conversion;
+        AMutableInt64 integer = new AMutableInt64(0);
+        AMutableDouble real = new AMutableDouble(0);
+        ClassAdTime asecs = new ClassAdTime();
+        ClassAdTime rsecs = new ClassAdTime();
+        ClassAd classad = new ClassAd();
+        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 = new ClassAd();
+            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) throws HyracksDataException {
+            val.setRelativeTimeValue(new ClassAdTime());
+            return (true);
+        }
+    };
+    public static final ClassAdFunc epochTime = new ClassAdFunc() {
+        @Override
+        public boolean call(String name, ExprList argList, EvalState state, Value val) 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) throws HyracksDataException {
+            AMutableCharArrayString buf = new AMutableCharArrayString();
+            AMutableCharArrayString s = new AMutableCharArrayString();
+            boolean errorFlag = false;
+            boolean undefFlag = false;
+            boolean rval = false;
+
+            Value val = new Value();
+            Value stringVal = new Value();
+
+            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);
+                    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) throws HyracksDataException {
+            Value val = new Value();
+            Value stringVal = new Value();
+            AMutableCharArrayString str = new AMutableCharArrayString();
+            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);
+                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) throws HyracksDataException {
+            Value arg0 = new Value();
+            Value arg1 = new Value();
+            Value arg2 = new Value();
+            AMutableCharArrayString buf = new AMutableCharArrayString();
+            AMutableInt64 offset = new AMutableInt64(0);
+            AMutableInt64 len = new AMutableInt64(0);
+            AMutableInt64 alen = new AMutableInt64(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 = new AMutableInt64(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) throws HyracksDataException {
+            Value arg = new Value();
+            // 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);
+            return true;
+        }
+    };
+    public static final ClassAdFunc compareString = new ClassAdFunc() {
+
+        @Override
+        public boolean call(String name, ExprList argList, EvalState state, Value result) throws HyracksDataException {
+            Value arg0 = new Value();
+            Value arg1 = new Value();
+            Value arg0_s = new Value();
+            Value arg1_s = new Value();
+
+            // 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 = new AMutableCharArrayString();
+            AMutableCharArrayString s1 = new AMutableCharArrayString();
+            if (Value.convertValueToStringValue(arg0, arg0_s) && Value.convertValueToStringValue(arg1, arg1_s)
+                    && 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) throws HyracksDataException {
+            boolean have_options;
+            Value arg0 = new Value();
+            Value arg1 = new Value();
+            Value arg2 = new Value();
+
+            AMutableCharArrayString pattern = new AMutableCharArrayString();
+            AMutableCharArrayString target = new AMutableCharArrayString();
+            AMutableCharArrayString options_string = new AMutableCharArrayString();
+
+            // 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) throws HyracksDataException {
+            Value arg = new Value();
+
+            // 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);
+            return true;
+        }
+    };
+    public static final ClassAdFunc convString = new ClassAdFunc() {
+
+        @Override
+        public boolean call(String name, ExprList argList, EvalState state, Value result) throws HyracksDataException {
+            Value arg = new Value();
+
+            // 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);
+            return true;
+        }
+    };
+    public static final ClassAdFunc unparse = new ClassAdFunc() {
+        @Override
+        public boolean call(String name, ExprList argList, EvalState state, Value result) 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 = new PrettyPrint();
+                AMutableCharArrayString szAttribute = new AMutableCharArrayString();
+                AMutableCharArrayString szValue = new AMutableCharArrayString();
+                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) throws HyracksDataException {
+            Value arg = new Value();
+            // 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.copyFrom(arg);
+                    return (true);
+
+                case INTEGER_VALUE: {
+                    AMutableInt64 ival = new AMutableInt64(0);
+                    arg.isIntegerValue(ival);
+                    result.setBooleanValue(ival.getLongValue() != 0);
+                    return (true);
+                }
+
+                case REAL_VALUE: {
+                    AMutableDouble rval = new AMutableDouble(0);
+                    arg.isRealValue(rval);
+                    result.setBooleanValue(rval.getDoubleValue() != 0.0);
+                    return (true);
+                }
+
+                case STRING_VALUE: {
+                    AMutableCharArrayString buf = new AMutableCharArrayString();
+                    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 = new ClassAdTime();
+                    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) throws HyracksDataException {
+            Value arg = new Value();
+            Value arg2 = new Value();
+            boolean relative = name.equalsIgnoreCase("reltime");
+            boolean secondarg = false; // says whether a 2nd argument exists
+            AMutableInt64 arg2num = new AMutableInt64(0);
+
+            if (argList.size() == 0 && !relative) {
+                // absTime with no arguments returns the current time.
+                return currentTime.call(name, argList, state, result);
+            }
+            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 = new AMutableInt64(0);
+                AMutableDouble rvalue2 = new AMutableDouble(0);
+                ClassAdTime rsecs = new ClassAdTime();
+                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 = new AMutableInt64(0);
+                    arg.isIntegerValue(ivalue);
+                    if (relative) {
+                        result.setRelativeTimeValue(new ClassAdTime(ivalue.getLongValue(), false));
+                    } else {
+                        ClassAdTime atvalue = new ClassAdTime(true);
+                        atvalue.setValue(ivalue.getLongValue());
+                        if (secondarg) //2nd arg is the offset in secs
+                            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 = new AMutableDouble(0);
+                    arg.isRealValue(rvalue);
+                    if (relative) {
+                        result.setRelativeTimeValue(new ClassAdTime((long) (1000 * rvalue.getDoubleValue()), false));
+                    } else {
+                        ClassAdTime atvalue = new ClassAdTime();
+                        atvalue.setValue((long) rvalue.getDoubleValue());
+                        if (secondarg) //2nd arg is the offset in secs
+                            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 = new ClassAdTime();
+                    arg.isAbsoluteTimeValue(secs);
+                    if (relative) {
+                        result.setRelativeTimeValue(secs);
+                    } else {
+                        result.copyFrom(arg);
+                    }
+                    return (true);
+                }
+                case RELATIVE_TIME_VALUE: {
+                    if (relative) {
+                        result.copyFrom(arg);
+                    } else {
+                        ClassAdTime secs = new ClassAdTime();
+                        arg.isRelativeTimeValue(secs);
+                        ClassAdTime atvalue = new ClassAdTime();
+                        atvalue.setValue(secs);
+                        if (secondarg) //2nd arg is the offset in secs
+                            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) throws HyracksDataException {
+            Value arg = new Value();
+            Value realValue = new Value();
+            // 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.copyFrom(arg);
+            } else {
+                if (!Value.convertValueToRealValue(arg, realValue)) {
+                    result.setErrorValue();
+                } else {
+                    AMutableDouble rvalue = new AMutableDouble(0);
+                    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) throws HyracksDataException {
+            Value arg = new Value();
+            Value arg2 = new Value();
+
+            // 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 = new AMutableInt64(0);
+                AMutableInt64 ibase = new AMutableInt64(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 = new Value();
+                    Value realBase = new Value();
+                    if (!Value.convertValueToRealValue(arg, realValue)
+                            || !Value.convertValueToRealValue(arg2, realBase)) {
+                        result.setErrorValue();
+                    } else {
+                        AMutableDouble rvalue = new AMutableDouble(0);
+                        AMutableDouble rbase = new AMutableDouble(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 = new Value();
+                Value base = new Value();
+                if (!Value.convertValueToRealValue(arg, val)) {
+                    result.setErrorValue();
+                } else {
+                    // get the value to quantize into rval.
+                    AMutableDouble rval = new AMutableDouble(0);
+                    AMutableDouble rbase = new AMutableDouble(0);
+                    val.isRealValue(rval);
+                    if (arg2.isListValue()) {
+                        ExprList list = new ExprList();
+                        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)) {
+                                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)) {
+                            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 = new AMutableInt64(0);
+                    AMutableInt64 ibase = new AMutableInt64(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() {
+
+        @Override
+        public boolean call(String name, ExprList argList, EvalState state, Value result) throws HyracksDataException {
+            Value arg = new Value();;
+            // 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 = new AMutableInt64(0);
+            AMutableDouble double_max = new AMutableDouble(0);
+            Random randomGenerator = new Random(System.currentTimeMillis());
+            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) throws HyracksDataException {
+            Value arg1 = new Value();
+            MutableBoolean arg1_bool = new MutableBoolean();
+            // 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 = new AMutableInt64(0);
+                    if (!arg1.isIntegerValue(intval)) {
+                        result.setErrorValue();
+                        return (false);
+                    }
+                    arg1_bool.setValue(intval.getLongValue() != 0L);
+                    break;
+                }
+                case REAL_VALUE: {
+                    AMutableDouble realval = new AMutableDouble(0);
+                    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) throws HyracksDataException {
+            Value arg0 = new Value();
+            Value arg1 = new Value();
+            Value arg2 = new Value();
+            boolean have_delimiter;
+            AMutableCharArrayString str0 = new AMutableCharArrayString();
+            AMutableCharArrayString str1 = new AMutableCharArrayString();
+            AMutableCharArrayString delimiter_string = new AMutableCharArrayString();
+
+            // 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 = new ArrayList<String>();
+            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) throws HyracksDataException {
+            Value arg = new Value();
+            Value intarg = new Value();
+            AMutableInt64 tot_secs = new AMutableInt64(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)) {
+                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) throws HyracksDataException {
+            Value arg = new Value();
+            Value strarg = new Value();
+            // takes exactly one argument
+            if (argList.size() != 1) {
+                result.setErrorValue();
+                return true;
+            }
+            if (!argList.get(0).publicEvaluate(state, arg)) {
+                result.setErrorValue();
+                return false;
+            }
+            AMutableCharArrayString s = new AMutableCharArrayString();
+            if (!Value.convertValueToStringValue(arg, strarg) || !strarg.isStringValue(s)) {
+                result.setErrorValue();
+                return true;
+            }
+            if (state.getDepthRemaining() <= 0) {
+                result.setErrorValue();
+                return false;
+            }
+            ClassAdParser parser = new ClassAdParser();
+            ExprTreeHolder expr = new ExprTreeHolder();
+            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;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/ac683db0/asterix-external-data/src/test/java/org/apache/asterix/external/classad/CaseInsensitiveString.java
----------------------------------------------------------------------
diff --git a/asterix-external-data/src/test/java/org/apache/asterix/external/classad/CaseInsensitiveString.java b/asterix-external-data/src/test/java/org/apache/asterix/external/classad/CaseInsensitiveString.java
new file mode 100644
index 0000000..ecc69f8
--- /dev/null
+++ b/asterix-external-data/src/test/java/org/apache/asterix/external/classad/CaseInsensitiveString.java
@@ -0,0 +1,61 @@
+/*
+ * 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;
+
+public class CaseInsensitiveString implements Comparable<CaseInsensitiveString> {
+    private String aString;
+
+    public String get() {
+        return aString;
+    }
+
+    @Override
+    public String toString() {
+        return aString;
+    }
+
+    public void set(String aString) {
+        this.aString = aString;
+    }
+
+    public CaseInsensitiveString(String aString) {
+        this.aString = aString;
+    }
+
+    public CaseInsensitiveString() {
+        this.aString = null;
+    }
+
+    @Override
+    public int compareTo(CaseInsensitiveString o) {
+        return aString.compareToIgnoreCase(o.aString);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return (o instanceof CaseInsensitiveString) ? aString.equalsIgnoreCase(((CaseInsensitiveString) o).aString)
+                : false;
+    }
+
+    @Override
+    public int hashCode() {
+        return aString.toLowerCase().hashCode();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/ac683db0/asterix-external-data/src/test/java/org/apache/asterix/external/classad/CharArrayLexerSource.java
----------------------------------------------------------------------
diff --git a/asterix-external-data/src/test/java/org/apache/asterix/external/classad/CharArrayLexerSource.java b/asterix-external-data/src/test/java/org/apache/asterix/external/classad/CharArrayLexerSource.java
new file mode 100644
index 0000000..3501953
--- /dev/null
+++ b/asterix-external-data/src/test/java/org/apache/asterix/external/classad/CharArrayLexerSource.java
@@ -0,0 +1,86 @@
+/*
+ * 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;
+
+public class CharArrayLexerSource extends LexerSource {
+
+    private char[] input;
+    private int offset;
+
+    @Override
+    public int getPosition() {
+        return offset;
+    }
+
+    public CharArrayLexerSource() {
+        offset = 0;
+        input = null;
+    }
+
+    public CharArrayLexerSource(char[] input, int offset) {
+        SetNewSource(input, offset);
+    }
+
+    private void SetNewSource(char[] input, int offset2) {
+        this.input = input;
+        this.offset = offset2;
+    }
+
+    @Override
+    public char readCharacter() throws IOException {
+        if (offset == input.length) {
+            previousCharacter = Lexer.EOF;
+            return previousCharacter;
+        } else {
+            previousCharacter = input[offset];
+            offset++;
+            return previousCharacter;
+        }
+    }
+
+    @Override
+    public void unreadCharacter() {
+        if (offset > 0) {
+            if (previousCharacter != Lexer.EOF) {
+                offset--;
+            }
+        }
+    }
+
+    @Override
+    public boolean atEnd() {
+        return offset == input.length;
+    }
+
+    public int GetCurrentLocation() {
+        return offset;
+    }
+
+    @Override
+    public void setNewSource(char[] buffer) {
+        SetNewSource(buffer, 0);
+    }
+
+    @Override
+    public char[] getBuffer() {
+        return input;
+    }
+}


Mime
View raw message