Reimplement GroovyJavaMethods in Java

Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/0d0214cc
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/0d0214cc
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/0d0214cc

Branch: refs/heads/master
Commit: 0d0214ccecc6222ffa7c712b1b9077c9356f6f46
Parents: 18c28d2
Author: Svetoslav Neykov <[email protected]>
Authored: Thu Oct 22 09:49:22 2015 +0300
Committer: Svetoslav Neykov <[email protected]>
Committed: Thu Oct 22 16:33:44 2015 +0300

----------------------------------------------------------------------
 .../util/groovy/FromCallableClosure.java        |  38 ++++
 .../util/groovy/FromFunctionClosure.java        |  39 ++++
 .../util/groovy/FromRunnableClosure.java        |  46 +++++
 .../util/groovy/GroovyJavaMethods.groovy        | 146 --------------
 .../brooklyn/util/groovy/GroovyJavaMethods.java | 200 +++++++++++++++++++
 .../brooklyn/util/groovy/JavadocDummy.java      |  30 ---
 6 files changed, 323 insertions(+), 176 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0d0214cc/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/FromCallableClosure.java
----------------------------------------------------------------------
diff --git 
a/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/FromCallableClosure.java
 
b/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/FromCallableClosure.java
new file mode 100644
index 0000000..0ad414f
--- /dev/null
+++ 
b/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/FromCallableClosure.java
@@ -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.brooklyn.util.groovy;
+
+import java.util.concurrent.Callable;
+
+import groovy.lang.Closure;
+
+public class FromCallableClosure<T> extends Closure<T> {
+    private static final long serialVersionUID = 1L;
+    private Callable<T> job;
+
+    public FromCallableClosure(Class<GroovyJavaMethods> owner, Callable<T> 
job) {
+        super(owner, owner);
+        this.job = job;
+    }
+
+    public T doCall() throws Exception {
+        return job.call();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0d0214cc/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/FromFunctionClosure.java
----------------------------------------------------------------------
diff --git 
a/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/FromFunctionClosure.java
 
b/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/FromFunctionClosure.java
new file mode 100644
index 0000000..80203fb
--- /dev/null
+++ 
b/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/FromFunctionClosure.java
@@ -0,0 +1,39 @@
+/*
+ * 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.brooklyn.util.groovy;
+
+import groovy.lang.Closure;
+
+import com.google.common.base.Function;
+
+public class FromFunctionClosure<T> extends Closure<T> {
+    private static final long serialVersionUID = 1L;
+    private Function<Object, T> job;
+
+    @SuppressWarnings("unchecked")
+    public FromFunctionClosure(Class<GroovyJavaMethods> owner, Function<?, T> 
job) {
+        super(owner, owner);
+        this.job = (Function<Object, T>) job;
+    }
+
+    public T doCall(Object it) throws Exception {
+        return job.apply(it);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0d0214cc/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/FromRunnableClosure.java
----------------------------------------------------------------------
diff --git 
a/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/FromRunnableClosure.java
 
b/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/FromRunnableClosure.java
new file mode 100644
index 0000000..37fad87
--- /dev/null
+++ 
b/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/FromRunnableClosure.java
@@ -0,0 +1,46 @@
+/*
+ * 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.brooklyn.util.groovy;
+
+import groovy.lang.Closure;
+
+import java.util.concurrent.Callable;
+
+import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
+
+public class FromRunnableClosure<T> extends Closure<T> {
+    private static final long serialVersionUID = 1L;
+    private Runnable job;
+
+    public FromRunnableClosure(Class<GroovyJavaMethods> owner, Runnable job) {
+        super(owner, owner);
+        this.job = job;
+    }
+
+    @SuppressWarnings("unchecked")
+    public T doCall() throws Throwable {
+        if (ScriptBytecodeAdapter.isCase(job, Callable.class)) {
+            return ((Callable<T>)job).call();
+        } else {
+            job.run();
+            return null;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0d0214cc/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/GroovyJavaMethods.groovy
----------------------------------------------------------------------
diff --git 
a/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/GroovyJavaMethods.groovy
 
b/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/GroovyJavaMethods.groovy
deleted file mode 100644
index ff0def2..0000000
--- 
a/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/GroovyJavaMethods.groovy
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * 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.brooklyn.util.groovy;
-
-import static org.apache.brooklyn.util.groovy.GroovyJavaMethods.truth;
-
-import java.util.concurrent.Callable
-
-import org.apache.brooklyn.util.concurrent.CallableFromRunnable;
-
-import com.google.common.base.Function
-import com.google.common.base.Predicate
-
-/** handy methods available in groovy packaged so they can be consumed from 
java,
- *  and other conversion/conveniences; but see JavaGroovyEquivalents for 
faster alternatives */
-public class GroovyJavaMethods {
-
-    //TODO use named subclasses, would that be more efficient?
-
-    // TODO xFromY methods not in correct class: they are not "handy method 
available in groovy"?
-    public static Closure closureFromRunnable(final Runnable job) {
-        return {
-            if (job in Callable) { return job.call() }
-            else { job.run(); null; }
-        };
-    }
-    
-    public static Closure closureFromCallable(final Callable job) {
-        return { job.call(); };
-    }
-
-    public static <T> Closure<T> closureFromFunction(final Function<?,T> job) {
-        return { it -> return job.apply(it); };
-    }
-
-    public static <T> Callable<T> callableFromClosure(final Closure<T> job) {
-        return job as Callable;
-    }
-
-    public static <T> Callable<T> callableFromRunnable(final Runnable job) {
-        return (job in Callable) ? callableFromClosure(job) : 
CallableFromRunnable.newInstance(job, null);
-    }
-
-    public static <T> Predicate<T> predicateFromClosure(final Closure<Boolean> 
job) {
-        // TODO using `Predicate<T>` on the line below gives "unable to 
resolve class T"
-        return new Predicate<Object>() {
-            public boolean apply(Object input) {
-                return job.call(input);
-            }
-        };
-    }
-
-    public static <F,T> Function<F,T> functionFromClosure(final Closure<T> 
job) {
-        // TODO using `Function<F,T>` on the line below gives "unable to 
resolve class T"
-        return new Function<Object,Object>() {
-            public Object apply(Object input) {
-                return job.call(input);
-            }
-        };
-    }
-
-    public static <T> Predicate<T> castToPredicate(Object o) {
-        if (o in Closure) {
-            return predicateFromClosure(o);
-        } else {
-            return (Predicate<T>) o;
-        }
-    }
-
-    public static <T> Closure castToClosure(Object o) {
-        if (o == null) {
-            return o;
-        } else if (o in Closure) {
-            return o;
-        } else if (o instanceof Runnable) {
-            return closureFromRunnable((Runnable)o);
-        } else if (o instanceof Callable) {
-            return closureFromCallable((Callable)o); 
-        } else if (o instanceof Function) {
-            return closureFromFunction((Function)o); 
-        } else {
-            throw new IllegalArgumentException("Cannot convert to closure: 
o="+o+"; type="+(o != null ? o.getClass() : null));
-        }
-    }
-
-/* alternatives to above; but I think the above is more efficient?  (even more 
efficient if moved from java to groovy)  --alex jun 2012
-    public static <K,T> Function<K,T> functionFromClosure(final Closure<T> 
job) {
-        return job as Function;
-    }
-
-    public static <T> Predicate<T> predicateFromClosure(final Closure<Boolean> 
job) {
-        return job as Predicate;
-    }
-*/
-    
-    public static Predicate<Object> truthPredicate() {
-        return new Predicate<Object>() {
-           @Override public boolean apply(Object input) {
-               return truth(input);
-           }
-        };
-    }
-    
-    public static boolean truth(Object o) {
-        if (o) return true;
-        return false;
-    }
-
-    public static <T> T elvis(Object preferred, Object fallback) {
-        return fix(preferred ?: fallback);
-    }
-    
-    public static <T> T elvis(Object... preferences) {
-        if (preferences.length == 0) throw new 
IllegalArgumentException("preferences must not be empty for elvis");
-        for (Object contender : preferences) {
-            if (contender) return fix(contender);
-        }
-        return fix(preferences[preferences.size()-1]);
-    }
-    
-    public static <T> T fix(Object o) {
-        if (o in GString) return (o as String);
-        return o;
-    }
-    
-    // args is expected to be an array, but for groovy compilation reasons 
it's not declared as such in the signature :-(
-    public static <T> T invokeMethodOnMetaClass(Object target, String 
methodName, Object args) {
-        return target.metaClass.invokeMethod(target, methodName, args);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0d0214cc/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/GroovyJavaMethods.java
----------------------------------------------------------------------
diff --git 
a/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/GroovyJavaMethods.java
 
b/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/GroovyJavaMethods.java
new file mode 100644
index 0000000..7f019a9
--- /dev/null
+++ 
b/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/GroovyJavaMethods.java
@@ -0,0 +1,200 @@
+/*
+ * 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.brooklyn.util.groovy;
+
+import java.util.concurrent.Callable;
+
+import org.apache.brooklyn.util.concurrent.CallableFromRunnable;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
+import org.codehaus.groovy.runtime.callsite.CallSite;
+import org.codehaus.groovy.runtime.callsite.CallSiteArray;
+import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+
+import groovy.lang.Closure;
+import groovy.lang.GString;
+
+/** handy methods available in groovy packaged so they can be consumed from 
java,
+ *  and other conversion/conveniences; but see JavaGroovyEquivalents for 
faster alternatives */
+public class GroovyJavaMethods {
+    private static final CallSiteArray CALL_SITE_ARRAY = new 
CallSiteArray(GroovyJavaMethods.class, new String[] {"metaClass", 
"invokeMethod"});
+
+    //TODO use named subclasses, would that be more efficient?
+
+    // TODO xFromY methods not in correct class: they are not "handy method 
available in groovy"?
+    public static <T> Closure<T> closureFromRunnable(final Runnable job) {
+        return new FromRunnableClosure<T>(GroovyJavaMethods.class, job);
+    }
+    
+    public static <T> Closure<T> closureFromCallable(final Callable<T> job) {
+        return new FromCallableClosure<T>(GroovyJavaMethods.class, job);
+    }
+
+    public static <T> Closure<T> closureFromFunction(final Function<?,T> job) {
+        return new FromFunctionClosure<T>(GroovyJavaMethods.class, job);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> Callable<T> callableFromClosure(final Closure<T> job) {
+        try {
+            return (Callable<T>)ScriptBytecodeAdapter.asType(job, 
Callable.class);
+        } catch (Throwable e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> Callable<T> callableFromRunnable(final Runnable job) {
+        try {
+            if (ScriptBytecodeAdapter.isCase(job, Callable.class)) {
+                return (Callable<T>)ScriptBytecodeAdapter.asType(job, 
Callable.class);
+            } else {
+                return CallableFromRunnable.newInstance(job, null);
+            }
+        } catch (Throwable e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+
+    public static <T> Predicate<T> predicateFromClosure(final Closure<Boolean> 
job) {
+        return new Predicate<T>() {
+            @Override
+            public boolean apply(Object input) {
+                return job.call(input);
+            }
+        };
+    }
+
+    public static <F,T> Function<F,T> functionFromClosure(final Closure<T> 
job) {
+        return new Function<F,T>() {
+            @Override
+            public T apply(F input) {
+                return job.call(input);
+            }
+        };
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> Predicate<T> castToPredicate(Object o) {
+        try {
+            if (ScriptBytecodeAdapter.isCase(o, Closure.class)) {
+                return predicateFromClosure((Closure<Boolean>)o);
+            } else {
+                return (Predicate<T>) o;
+            }
+        } catch (Throwable e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> Closure<T> castToClosure(Object o) {
+        try {
+            if (ScriptBytecodeAdapter.compareEqual(o, null)) {
+                return (Closure<T>)ScriptBytecodeAdapter.castToType(o, 
Closure.class);
+            } else if (ScriptBytecodeAdapter.isCase(o, Closure.class)) {
+                return (Closure<T>)ScriptBytecodeAdapter.castToType(o, 
Closure.class);
+            } else if (o instanceof Runnable) {
+                return 
closureFromRunnable((Runnable)ScriptBytecodeAdapter.createPojoWrapper(ScriptBytecodeAdapter.castToType(o,
 Runnable.class), Runnable.class));
+            } else if (o instanceof Callable) {
+                return 
closureFromCallable((Callable<T>)ScriptBytecodeAdapter.createPojoWrapper(ScriptBytecodeAdapter.castToType(o,
 Callable.class), Callable.class));
+            } else if (o instanceof Function) {
+                return closureFromFunction((Function<Object, 
T>)ScriptBytecodeAdapter.createPojoWrapper(ScriptBytecodeAdapter.castToType(o, 
Function.class), Function.class));
+            } else {
+                throw new IllegalArgumentException("Cannot convert to closure: 
o="+o+"; type="+(o != null ? o.getClass() : null));
+            }
+        } catch (Throwable e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+
+/* alternatives to above; but I think the above is more efficient?  (even more 
efficient if moved from java to groovy)  --alex jun 2012
+    public static <K,T> Function<K,T> functionFromClosure(final Closure<T> 
job) {
+        return job as Function;
+    }
+
+    public static <T> Predicate<T> predicateFromClosure(final Closure<Boolean> 
job) {
+        return job as Predicate;
+    }
+*/
+    
+    public static Predicate<Object> truthPredicate() {
+        return new Predicate<Object>() {
+           @Override public boolean apply(Object input) {
+               return truth(input);
+           }
+        };
+    }
+    
+    public static boolean truth(Object o) {
+        if (DefaultTypeTransformation.booleanUnbox(o)) return true;
+        return false;
+    }
+
+    public static <T> T elvis(Object preferred, Object fallback) {
+        try {
+            return fix(truth(preferred) ? preferred : fallback);
+        } catch (Throwable e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+    
+    public static <T> T elvis(Object... preferences) {
+        try {
+            if (preferences.length == 0) throw new 
IllegalArgumentException("preferences must not be empty for elvis");
+            for (Object contender : preferences) {
+                if (truth(contender)) return fix(contender);
+            }
+            return fix(preferences[preferences.length-1]);
+        } catch (Throwable e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+    
+    @SuppressWarnings("unchecked")
+    public static <T> T fix(Object o) {
+        try {
+            if (ScriptBytecodeAdapter.isCase(o, GString.class)) {
+                return (T)ScriptBytecodeAdapter.asType(o, String.class);
+            } else {
+                return (T)o;
+            }
+        } catch (Throwable e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+    
+    @SuppressWarnings("unchecked")
+    public static <T> T invokeMethodOnMetaClass(Object target, String 
methodName, Object args) {
+        try {
+            CallSite[] callSiteArray = getCallSiteArray();
+            Object metaClass = callSiteArray[0].callGetProperty(target);
+            return (T) callSiteArray[1].call(metaClass, target, methodName, 
args);
+        } catch (Throwable e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+
+    private static CallSite[] getCallSiteArray() {
+        return CALL_SITE_ARRAY.array;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0d0214cc/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/JavadocDummy.java
----------------------------------------------------------------------
diff --git 
a/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/JavadocDummy.java 
b/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/JavadocDummy.java
deleted file mode 100644
index c9a51b5..0000000
--- 
a/utils/groovy/src/main/java/org/apache/brooklyn/util/groovy/JavadocDummy.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.brooklyn.util.groovy;
-
-/** Maven Central requires javadoc to promote as a release. This seemed to 
happen when this was built by maven as a bundle,
- * but now that it is built as a jar it does not. This class exists only to 
provide that javadoc.
- * <p>
- * Note the groovy code does javadoc but the maven build is not picking it up. 
It *is* generated as part of the site build.
- */
-public class JavadocDummy {
-
-    private JavadocDummy() {}
-    
-}

Reply via email to