Author: dvryaboy
Date: Wed Apr  7 13:15:51 2010
New Revision: 931531

URL: http://svn.apache.org/viewvc?rev=931531&view=rev
Log:
PIG-1354: UDFs for dynamic invocation of simple Java methods

Added:
    hadoop/pig/trunk/src/org/apache/pig/builtin/GenericInvoker.java
    hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForDouble.java
    hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForFloat.java
    hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForInt.java
    hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForLong.java
    hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForString.java
    hadoop/pig/trunk/src/org/apache/pig/builtin/Invoker.java
    hadoop/pig/trunk/test/org/apache/pig/test/TestInvoker.java
Modified:
    hadoop/pig/trunk/CHANGES.txt

Modified: hadoop/pig/trunk/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/hadoop/pig/trunk/CHANGES.txt?rev=931531&r1=931530&r2=931531&view=diff
==============================================================================
--- hadoop/pig/trunk/CHANGES.txt (original)
+++ hadoop/pig/trunk/CHANGES.txt Wed Apr  7 13:15:51 2010
@@ -24,6 +24,8 @@ INCOMPATIBLE CHANGES
 
 IMPROVEMENTS
 
+PIG-1354: UDFs for dynamic invocation of simple Java methods (dvryaboy)
+
 PIG-1316: TextLoader should use Bzip2TextInputFormat for bzip files so that
 bzip files can be efficiently processed by splitting the files (pradeepkth)
 

Added: hadoop/pig/trunk/src/org/apache/pig/builtin/GenericInvoker.java
URL: 
http://svn.apache.org/viewvc/hadoop/pig/trunk/src/org/apache/pig/builtin/GenericInvoker.java?rev=931531&view=auto
==============================================================================
--- hadoop/pig/trunk/src/org/apache/pig/builtin/GenericInvoker.java (added)
+++ hadoop/pig/trunk/src/org/apache/pig/builtin/GenericInvoker.java Wed Apr  7 
13:15:51 2010
@@ -0,0 +1,93 @@
+/*
+ * 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.pig.builtin;
+
+import java.io.IOException;
+
+import org.apache.pig.EvalFunc;
+import org.apache.pig.backend.executionengine.ExecException;
+import org.apache.pig.data.DataType;
+import org.apache.pig.data.Tuple;
+import org.apache.pig.impl.logicalLayer.FrontendException;
+import org.apache.pig.impl.logicalLayer.schema.Schema;
+import org.apache.pig.impl.logicalLayer.schema.Schema.FieldSchema;
+/**
+ * The generic Invoker class does all the common grunt work of setting up an 
invoker.
+ * Class-specific non-generic extensions of this class are needed for Pig to 
know what type
+ * of return to expect from exec, and to find the appropriate classes through 
reflection.
+ * All they have to do is implement the constructors that call into super(). 
Note that the 
+ * no-parameter constructor is <b>required</b>, if nonsensical, for Pig to do 
its work.
+ * <p>
+ * 
+ * This UDF allows one to dynamically invoke Java methods that return a 
<code>T</code>
+ * <p>
+ * Usage of the Invoker family of UDFs (adjust as appropriate):
+ * <p>
+ *<pre>
+ * {...@code
+ * -- invoking a static method
+ * DEFINE StringToLong InvokeForLong('java.lang.Long.valueOf', 'String')
+ * longs = FOREACH strings GENERATE StringToLong(some_chararray);
+ *
+ * -- invoking a method on an object
+ * DEFINE StringConcat InvokeForString('java.lang.String.concat', 'String 
String', 'false')
+ * concatenations = FOREACH strings GENERATE StringConcat(str1, str2); 
+ * }
+ * </pre>
+ * <p>
+ * The first argument to the constructor is the full path to desired 
method.<br>
+ * The second argument is a list of classes of the method parameters.<br>
+ * If the method is not static, the first element in this list is the object 
to invoke the method on.<br>
+ * The third argument is the keyword "static" (or "true") to signify that the 
method is static. <br>
+ * The third argument is optional, and true by default.<br>
+ * <p>
+ * @param <T>
+ */
+public abstract class GenericInvoker<T> extends EvalFunc<T> {
+
+    private Invoker<T> invoker_;
+
+    public GenericInvoker() {}
+
+    public GenericInvoker(String fullName, String paramSpecsStr)
+    throws ClassNotFoundException, FrontendException, SecurityException, 
NoSuchMethodException {
+        invoker_ = new Invoker<T>(fullName, paramSpecsStr);
+    }
+
+    public GenericInvoker(String fullName, String paramSpecsStr, String 
isStatic)
+    throws ClassNotFoundException, FrontendException, SecurityException, 
NoSuchMethodException {
+        invoker_ = new Invoker<T>(fullName, paramSpecsStr, isStatic);
+    }
+
+    @Override
+    public T exec(Tuple input) throws IOException {
+        if (invoker_ == null) {
+            throw new ExecException("exec() attempted on an unitialized 
invoker. " +
+            "Invokers must be constructed with the method to invoke, and 
parameter signature to same.");
+        }
+        return invoker_.invoke(input);
+    }
+
+    @Override
+    public Schema outputSchema(Schema input) {
+        if (invoker_ == null) return null;
+        FieldSchema fs = new FieldSchema(null, 
DataType.findType(invoker_.getReturnType()));
+        return new Schema(fs);
+    }
+}

Added: hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForDouble.java
URL: 
http://svn.apache.org/viewvc/hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForDouble.java?rev=931531&view=auto
==============================================================================
--- hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForDouble.java (added)
+++ hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForDouble.java Wed Apr  7 
13:15:51 2010
@@ -0,0 +1,37 @@
+/*
+ * 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.pig.builtin;
+
+import org.apache.pig.impl.logicalLayer.FrontendException;
+
+/**
+ * @see GenericInvoker
+ */
+public class InvokeForDouble extends GenericInvoker<Double> {
+
+     public InvokeForDouble() {}
+
+     public InvokeForDouble(String fullName, String paramSpecsStr) throws 
FrontendException, SecurityException, ClassNotFoundException, 
NoSuchMethodException {
+         super(fullName, paramSpecsStr);
+     }
+
+     public InvokeForDouble(String fullName, String paramSpecsStr, String 
isStatic)
+     throws ClassNotFoundException, FrontendException, SecurityException, 
NoSuchMethodException {
+         super(fullName, paramSpecsStr, isStatic);
+     }
+ }

Added: hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForFloat.java
URL: 
http://svn.apache.org/viewvc/hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForFloat.java?rev=931531&view=auto
==============================================================================
--- hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForFloat.java (added)
+++ hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForFloat.java Wed Apr  7 
13:15:51 2010
@@ -0,0 +1,38 @@
+/*
+ * 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.pig.builtin;
+
+import org.apache.pig.impl.logicalLayer.FrontendException;
+
+/**
+ * @see GenericInvoker
+ */
+
+public class InvokeForFloat extends GenericInvoker<Float> {
+
+     public InvokeForFloat() {}
+
+     public InvokeForFloat(String fullName, String paramSpecsStr) throws 
FrontendException, SecurityException, ClassNotFoundException, 
NoSuchMethodException {
+         super(fullName, paramSpecsStr);
+     }
+
+     public InvokeForFloat(String fullName, String paramSpecsStr, String 
isStatic)
+     throws ClassNotFoundException, FrontendException, SecurityException, 
NoSuchMethodException {
+         super(fullName, paramSpecsStr, isStatic);
+     }
+ }
\ No newline at end of file

Added: hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForInt.java
URL: 
http://svn.apache.org/viewvc/hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForInt.java?rev=931531&view=auto
==============================================================================
--- hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForInt.java (added)
+++ hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForInt.java Wed Apr  7 
13:15:51 2010
@@ -0,0 +1,37 @@
+/*
+ * 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.pig.builtin;
+
+import org.apache.pig.impl.logicalLayer.FrontendException;
+
+/**
+ * @see GenericInvoker
+ */
+public class InvokeForInt extends GenericInvoker<Integer> {
+
+    public InvokeForInt() {}
+
+    public InvokeForInt(String fullName, String paramSpecsStr) throws 
FrontendException, SecurityException, ClassNotFoundException, 
NoSuchMethodException {
+        super(fullName, paramSpecsStr);
+    }
+
+    public InvokeForInt(String fullName, String paramSpecsStr, String isStatic)
+    throws ClassNotFoundException, FrontendException, SecurityException, 
NoSuchMethodException {
+        super(fullName, paramSpecsStr, isStatic);
+    }
+}

Added: hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForLong.java
URL: 
http://svn.apache.org/viewvc/hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForLong.java?rev=931531&view=auto
==============================================================================
--- hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForLong.java (added)
+++ hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForLong.java Wed Apr  7 
13:15:51 2010
@@ -0,0 +1,37 @@
+/*
+ * 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.pig.builtin;
+
+import org.apache.pig.impl.logicalLayer.FrontendException;
+
+/**
+ * @see GenericInvoker
+ */
+public class InvokeForLong extends GenericInvoker<Long> {
+
+    public InvokeForLong() {}
+
+    public InvokeForLong(String fullName, String paramSpecsStr) throws 
FrontendException, SecurityException, ClassNotFoundException, 
NoSuchMethodException {
+        super(fullName, paramSpecsStr);
+    }
+
+    public InvokeForLong(String fullName, String paramSpecsStr, String 
isStatic)
+    throws ClassNotFoundException, FrontendException, SecurityException, 
NoSuchMethodException {
+        super(fullName, paramSpecsStr, isStatic);
+    }
+}

Added: hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForString.java
URL: 
http://svn.apache.org/viewvc/hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForString.java?rev=931531&view=auto
==============================================================================
--- hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForString.java (added)
+++ hadoop/pig/trunk/src/org/apache/pig/builtin/InvokeForString.java Wed Apr  7 
13:15:51 2010
@@ -0,0 +1,38 @@
+/*
+ * 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.pig.builtin;
+
+import org.apache.pig.impl.logicalLayer.FrontendException;
+
+/**
+ * @see GenericInvoker
+ */
+public class InvokeForString extends GenericInvoker<String> {
+
+    public InvokeForString() {}
+
+    public InvokeForString(String fullName, String paramSpecsStr) throws 
FrontendException, SecurityException, ClassNotFoundException, 
NoSuchMethodException {
+        super(fullName, paramSpecsStr);
+    }
+
+    public InvokeForString(String fullName, String paramSpecsStr, String 
isStatic)
+    throws ClassNotFoundException, FrontendException, SecurityException, 
NoSuchMethodException {
+        super(fullName, paramSpecsStr, isStatic);
+    }
+}

Added: hadoop/pig/trunk/src/org/apache/pig/builtin/Invoker.java
URL: 
http://svn.apache.org/viewvc/hadoop/pig/trunk/src/org/apache/pig/builtin/Invoker.java?rev=931531&view=auto
==============================================================================
--- hadoop/pig/trunk/src/org/apache/pig/builtin/Invoker.java (added)
+++ hadoop/pig/trunk/src/org/apache/pig/builtin/Invoker.java Wed Apr  7 
13:15:51 2010
@@ -0,0 +1,150 @@
+/*
+ * 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.pig.builtin;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+
+import org.apache.pig.backend.executionengine.ExecException;
+import org.apache.pig.data.Tuple;
+import org.apache.pig.impl.logicalLayer.FrontendException;
+
+public class Invoker<T>  {
+
+    private Method method_;
+    private Class<?>[] paramClasses_;
+
+    private boolean isStatic_;
+    private Class<?> selfClass_;
+    private Type returnType_;
+
+    public Invoker(String fullName, String paramSpecsStr) throws 
ClassNotFoundException, FrontendException, SecurityException, 
NoSuchMethodException {
+        this(fullName, paramSpecsStr, "true");
+    }
+
+    public Invoker(String fullName, String paramSpecsStr, String isStatic) 
throws ClassNotFoundException, FrontendException, SecurityException, 
NoSuchMethodException {
+        String className = fullName.substring(0, fullName.lastIndexOf('.'));
+        String methodName = fullName.substring(fullName.lastIndexOf('.')+1);
+        Class<?> klazz = Class.forName(className);
+        String[] paramSpecs = paramSpecsStr.split(" ");
+        isStatic_ = "static".equalsIgnoreCase(isStatic) || 
"true".equals(isStatic);
+        paramClasses_ = new Class<?>[paramSpecs.length];
+        for (int i = 0; i < paramSpecs.length; i++) {
+            paramClasses_[i] = stringToClass(paramSpecs[i]);
+        }
+        if (!isStatic_) {
+            selfClass_ = paramClasses_[0];
+        }
+        method_ = klazz.getMethod(methodName, (isStatic_ ? paramClasses_ : 
dropFirstClass(paramClasses_)));
+        returnType_ = method_.getGenericReturnType();
+    }
+
+    public Type getReturnType() {
+        return returnType_;
+    }
+
+    private static Class<?>[] dropFirstClass(Class<?>[] original) {
+        if (original.length < 2) {
+            return new Class[0];
+        } else {
+            return Arrays.copyOfRange(original, 1, original.length-1);
+        }
+    }
+
+    private static Object[] dropFirstObject(Object[] original) {
+        if (original.length < 2) {
+            return new Object[0];
+        } else {
+            return Arrays.copyOfRange(original, 1, original.length-1);
+        } 
+    }
+
+    private static Class<?> stringToClass(String klass) throws 
FrontendException {
+        if ("string".equalsIgnoreCase(klass)) {
+            return String.class;
+        } else if ("int".equalsIgnoreCase(klass)) {
+            return Integer.TYPE;
+        } else if ("double".equalsIgnoreCase(klass)) {
+            return Double.TYPE;
+        } else if ("float".equalsIgnoreCase(klass)){
+            return Float.TYPE;
+        } else if ("long".equalsIgnoreCase(klass)) {
+            return Long.TYPE;
+        } else { 
+            throw new FrontendException("unable to find mathing class for " + 
klass);
+        }
+
+    }
+
+    private static Class<?> unPrimitivize(Class<?> klass) {
+        if (klass.equals(Integer.TYPE)) {
+            return Integer.class;
+        } if (klass.equals(Long.TYPE)) {
+            return Long.class;
+        } else if (klass.equals(Float.TYPE)) {
+            return Float.class;
+        } else if (klass.equals(Double.TYPE)) {
+            return Double.class;
+        } else {
+            return klass;
+        }
+    }
+
+    private Object[] tupleToArgs(Tuple t) throws ExecException {
+        if ( (t == null && paramClasses_ != null) || (t != null && t.size() != 
paramClasses_.length)) {
+            throw new ExecException("unable to match function arguments to 
declared signature.");
+        }
+        if (t == null) {
+            return null;
+        }
+        Object[] args = new Object[t.size()];
+        for (int i = 0; i < t.size(); i++) {
+            args[i] =  unPrimitivize(paramClasses_[i]).cast(t.get(i));
+        }
+        return args;
+    }
+
+    @SuppressWarnings("unchecked")
+    public T invoke(Tuple input) throws IOException {
+        Object[] args = tupleToArgs(input);
+        try {
+            if (!isStatic_) {
+                return (T) method_.invoke(selfClass_.cast(args[0]), 
dropFirstObject(args));
+            } else {
+                return (T) method_.invoke(null, args);
+            }
+        } catch (IllegalArgumentException e) {
+            throw new ExecException(e);
+        } catch (IllegalAccessException e) {
+            throw new ExecException(e);
+        } catch (InvocationTargetException e) {
+            throw new ExecException(e);
+        }
+    }
+
+}
+
+
+
+
+
+

Added: hadoop/pig/trunk/test/org/apache/pig/test/TestInvoker.java
URL: 
http://svn.apache.org/viewvc/hadoop/pig/trunk/test/org/apache/pig/test/TestInvoker.java?rev=931531&view=auto
==============================================================================
--- hadoop/pig/trunk/test/org/apache/pig/test/TestInvoker.java (added)
+++ hadoop/pig/trunk/test/org/apache/pig/test/TestInvoker.java Wed Apr  7 
13:15:51 2010
@@ -0,0 +1,139 @@
+/*
+ * 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.pig.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.apache.pig.EvalFunc;
+import org.apache.pig.builtin.InvokeForDouble;
+import org.apache.pig.builtin.InvokeForFloat;
+import org.apache.pig.builtin.InvokeForInt;
+import org.apache.pig.builtin.InvokeForLong;
+import org.apache.pig.builtin.InvokeForString;
+import org.apache.pig.data.Tuple;
+import org.apache.pig.data.TupleFactory;
+import org.junit.Test;
+
+/** need more tests -- non-String funcs and especially the full path through 
the pig interpreter. 
+ * I tested manually, seems to work, but
+ * should really add more here.
+ */
+public class TestInvoker {
+
+    private final TupleFactory tf_ = TupleFactory.getInstance();
+    @Test
+    public void testStringInvoker() throws SecurityException, 
ClassNotFoundException, NoSuchMethodException, IOException {
+
+        // Test non-static method
+        InvokeForString is = new 
InvokeForString("java.lang.String.toUpperCase", "String", "false");
+        assertEquals("FOO", is.exec(tf_.newTuple("foo")));
+
+        // both "static" and "true" should work
+        // Test static method
+        is = new InvokeForString("java.lang.String.valueOf", "int", "true");
+        Tuple t = tf_.newTuple(1);
+        t.set(0,231);
+        assertEquals("231", is.exec(t));
+
+        // test default (should be static)
+        is = new InvokeForString("java.lang.String.valueOf", "int");
+        assertEquals("231", is.exec(t));
+
+        // Test method with multiple args
+        is = new InvokeForString(TestInvoker.class.getName()+".concatStrings", 
"String String");
+        t = tf_.newTuple(2);
+        t.set(0, "foo");
+        t.set(1, "bar");
+        assertEquals("foobar", is.exec(t));
+    }
+
+    @Test
+    public void testLongInvoker() throws SecurityException, 
ClassNotFoundException, NoSuchMethodException, NumberFormatException, 
IOException {
+        InvokeForLong il = new InvokeForLong("java.lang.Long.valueOf", 
"String");
+        Tuple t = tf_.newTuple(1);
+        String arg = "245";
+        t.set(0, arg);
+        assertEquals(Long.valueOf(arg), il.exec(t));
+    }
+
+    @Test
+    public void testIntInvoker() throws SecurityException, 
ClassNotFoundException, NoSuchMethodException, NumberFormatException, 
IOException {
+        InvokeForInt il = new InvokeForInt("java.lang.Integer.valueOf", 
"String");
+        Tuple t = tf_.newTuple(1);
+        String arg = "245";
+        t.set(0, arg);
+        assertEquals(Integer.valueOf(arg), il.exec(t));
+    }
+
+    @Test
+    public void testDoubleInvoker() throws SecurityException, 
ClassNotFoundException, NoSuchMethodException, NumberFormatException, 
IOException {
+        InvokeForDouble il = new InvokeForDouble("java.lang.Double.valueOf", 
"String");
+        Tuple t = tf_.newTuple(1);
+        String arg = "245";
+        t.set(0, arg);
+        assertEquals(Double.valueOf(arg), il.exec(t));
+    }
+
+    @Test
+    public void testFloatInvoker() throws SecurityException, 
ClassNotFoundException, NoSuchMethodException, NumberFormatException, 
IOException {
+        InvokeForFloat il = new InvokeForFloat("java.lang.Float.valueOf", 
"String");
+        Tuple t = tf_.newTuple(1);
+        String arg = "245.3";
+        t.set(0, arg);
+        assertEquals(Float.valueOf(arg), il.exec(t));
+    }
+
+    public static String concatStrings(String str1, String str2) {
+        return str1.concat(str2);
+    }
+
+    @Test
+    public void testSpeed() throws IOException, SecurityException, 
ClassNotFoundException, NoSuchMethodException {
+        EvalFunc<Double> log = new Log();
+        Tuple tup = tf_.newTuple(1);
+        long start = System.currentTimeMillis();
+        for (int i=0; i < 1000000; i++) {
+            tup.set(0, (double) i);
+            log.exec(tup);
+        }
+        long staticSpeed = (System.currentTimeMillis()-start);
+        start = System.currentTimeMillis();
+        log = new InvokeForDouble("java.lang.Math.log", "Double", "static");
+        for (int i=0; i < 1000000; i++) {
+            tup.set(0, (double) i);
+            log.exec(tup);
+        }
+        long dynamicSpeed = System.currentTimeMillis()-start;
+        System.err.println("Dynamic to static ratio: "+((float) 
dynamicSpeed)/staticSpeed);
+        assertTrue( ((float) dynamicSpeed)/staticSpeed < 5);
+    }
+    
+    private class Log extends EvalFunc<Double> {
+
+        @Override
+        public Double exec(Tuple input) throws IOException {
+            Double d = (Double) input.get(0);
+            return Math.log(d);
+        }
+        
+    }
+}


Reply via email to