You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2023/01/04 22:44:05 UTC

[groovy] branch master updated: GROOVY-10891: We should have variants of findResult/s with no Closure which use Closure.IDENTITY in that case

This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/master by this push:
     new 3a5569172b GROOVY-10891: We should have variants of findResult/s with no Closure which use Closure.IDENTITY in that case
3a5569172b is described below

commit 3a5569172b2d4b48e8a9ceb0e404075672014247
Author: Paul King <pa...@asert.com.au>
AuthorDate: Sat Dec 31 22:32:14 2022 +1000

    GROOVY-10891: We should have variants of findResult/s with no Closure which use Closure.IDENTITY in that case
---
 .../groovy/runtime/DefaultGroovyMethods.java       | 175 +++++++++++++++++++++
 src/test/groovy/inspect/InspectorTest.java         |   6 +-
 2 files changed, 178 insertions(+), 3 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java b/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
index 6847865189..df75a6b37b 100644
--- a/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
+++ b/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
@@ -4714,6 +4714,28 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
         return null;
     }
 
+    /**
+     * Treats the object as iterable, iterating through the values it represents and returns the first non-null value, otherwise returns null.
+     * <p>
+     * <pre class="groovyTestCase">
+     * class Foo {
+     *     List items
+     *     Iterator iterator() {
+     *         items.iterator()
+     *     }
+     * }
+     * assert new Foo(items: [null, 2, 4]).findResult() == 2
+     * assert new Foo(items: [null, null]).findResult() == null
+     * </pre>
+     *
+     * @param self      an Object with an iterator returning its values
+     * @return the first non-null result of the closure
+     * @since 4.0.8
+     */
+    public static Object findResult(Object self) {
+        return findResult(self, Closure.IDENTITY);
+    }
+
     /**
      * Treats the object as iterable, iterating through the values it represents and returns the first non-null result obtained from calling the closure, otherwise returns the defaultResult.
      * <p>
@@ -4735,6 +4757,31 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
         return result;
     }
 
+    /**
+     * Treats the object as iterable, iterating through the values it represents and returns the first non-null result, otherwise returns the defaultResult.
+     * <p>
+     * <pre class="groovyTestCase">
+     * class Foo {
+     *     List items
+     *     Iterator iterator() {
+     *         items.iterator()
+     *     }
+     * }
+     * assert new Foo(items: [null, 2, 4]).findResult(5) == 2
+     * assert new Foo(items: [null, null]).findResult(5) == 5
+     * </pre>
+     *
+     * @param self          an Object with an iterator returning its values
+     * @param defaultResult an Object that should be returned if all elements are null
+     * @return the first non-null element, otherwise the default value
+     * @since 4.0.8
+     */
+    public static Object findResult(Object self, Object defaultResult) {
+        Object result = findResult(self, Closure.IDENTITY);
+        if (result == null) return defaultResult;
+        return result;
+    }
+
     /**
      * Iterates through the Iterator calling the given closure condition for each item but stopping once the first non-null
      * result is found and returning that result. If all are null, the defaultResult is returned.
@@ -4758,6 +4805,26 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
         return result;
     }
 
+    /**
+     * Iterates through the Iterator stopping once the first non-null
+     * result is found and returning that result. If all are null, the defaultResult is returned.
+     * <p>
+     * Examples:
+     * <pre class="groovyTestCase">
+     * assert [null, 1, 2].iterator().findResult('default') == 1
+     * assert [null, null].findResult('default') == 'default'
+     * </pre>
+     *
+     * @param self          an Iterator
+     * @param defaultResult an Object that should be returned if all elements are null
+     * @return the first non-null result from the iterator, or the defaultValue
+     * @since 4.0.8
+     */
+    public static <T, U extends T, V extends T> T findResult(Iterator<U> self, V defaultResult) {
+        T result = (T) findResult(self, Closure.IDENTITY);
+        return result == null ? defaultResult : result;
+    }
+
     /**
      * Iterates through the Iterator calling the given closure condition for each item but stopping once the first non-null
      * result is found and returning that result. If all results are null, null is returned.
@@ -4778,6 +4845,18 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
         return null;
     }
 
+    /**
+     * Iterates through the Iterator stopping once the first non-null
+     * result is found and returning that result. If all results are null, null is returned.
+     *
+     * @param self      an Iterator
+     * @return the first non-null result from the iterator, or null
+     * @since 4.0.8
+     */
+    public static <T> T findResult(Iterator<T> self) {
+        return (T) findResult(self, Closure.IDENTITY);
+    }
+
     /**
      * Iterates through the Iterable calling the given closure condition for each item but stopping once the first non-null
      * result is found and returning that result. If all are null, the defaultResult is returned.
@@ -4801,6 +4880,27 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
         return result;
     }
 
+    /**
+     * Iterates through the Iterable calling the given closure condition for each item but stopping once the first non-null
+     * result is found and returning that result. If all are null, the defaultResult is returned.
+     * <p>
+     * Examples:
+     * <pre class="groovyTestCase">
+     * assert [null, 1, 2].findResult('default') == 1
+     * assert [null, null].findResult('default') == 'default'
+     * </pre>
+     *
+     * @param self          an Iterable
+     * @param defaultResult an Object that should be returned if all elements in the iterable are null
+     * @return the first non-null element from the iterable, or the defaultValue
+     * @since 4.0.8
+     */
+    public static <T, U extends T, V extends T> T findResult(Iterable<U> self, V defaultResult) {
+        T result = (T) findResult(self, Closure.IDENTITY);
+        if (result == null) return defaultResult;
+        return result;
+    }
+
     /**
      * Iterates through the Iterable calling the given closure condition for each item but stopping once the first non-null
      * result is found and returning that result. If all results are null, null is returned.
@@ -4814,6 +4914,18 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
         return findResult(self.iterator(), condition);
     }
 
+    /**
+     * Iterates through the Iterable stopping once the first non-null
+     * result is found and returning that result. If all results are null, null is returned.
+     *
+     * @param self      an Iterable
+     * @return the first non-null element from the iterable, or null
+     * @since 4.0.8
+     */
+    public static <T> T findResult(Iterable<T> self) {
+        return (T) findResult(self.iterator(), Closure.IDENTITY);
+    }
+
     /**
      * Iterates through the Array calling the given closure condition for each item but stopping once the first non-null
      * result is found and returning that result. If all are null, the defaultResult is returned.
@@ -4828,6 +4940,19 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
         return findResult(new ArrayIterator<>(self), defaultResult, condition);
     }
 
+    /**
+     * Iterates through the Array stopping once the first non-null
+     * result is found and returning that result. If all are null, the defaultResult is returned.
+     *
+     * @param self          an Array
+     * @param defaultResult an Object that should be returned if all elements are null
+     * @return the first non-null result from calling the closure, or the defaultValue
+     * @since 4.0.8
+     */
+    public static <T, U extends T, V extends T> T findResult(U[] self, V defaultResult) {
+        return (T) findResult(new ArrayIterator<>(self), defaultResult, Closure.IDENTITY);
+    }
+
     /**
      * Iterates through the Array calling the given closure condition for each item but stopping once the first non-null
      * result is found and returning that result. If all results are null, null is returned.
@@ -4841,6 +4966,18 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
         return findResult(new ArrayIterator<>(self), condition);
     }
 
+    /**
+     * Iterates through the Array stopping once the first non-null
+     * result is found and returning that result. If all results are null, null is returned.
+     *
+     * @param self      an Array
+     * @return the first non-null result from calling the closure, or null
+     * @since 4.0.8
+     */
+    public static <T> T findResult(T[] self) {
+        return (T) findResult(new ArrayIterator<>(self), Closure.IDENTITY);
+    }
+
     /**
      * Returns the first non-null closure result found by passing each map entry to the closure, otherwise null is returned.
      * If the closure takes two parameters, the entry key and value are passed.
@@ -4908,6 +5045,22 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
         return findResults(self.iterator(), filteringTransform);
     }
 
+    /**
+     * Iterates through the Iterable collecting any non-null results.
+     * <p>
+     * Example:
+     * <pre class="groovyTestCase">
+     * assert [1, null, 2, null, 3].findResults() == [1, 2, 3]
+     * </pre>
+     *
+     * @param self an Iterable
+     * @return the list of non-null values
+     * @since 4.0.8
+     */
+    public static <T> Collection<T> findResults(Iterable<T> self) {
+        return findResults(self.iterator(), Closure.IDENTITY);
+    }
+
     /**
      * Iterates through the Iterator transforming items using the supplied closure
      * and collecting any non-null results.
@@ -4929,6 +5082,17 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
         return result;
     }
 
+    /**
+     * Iterates through the Iterator collecting any non-null results.
+     *
+     * @param self an Iterator
+     * @return the list of non-null values
+     * @since 4.0.8
+     */
+    public static <T> Collection<T> findResults(Iterator<T> self) {
+        return findResults(self, Closure.IDENTITY);
+    }
+
     /**
      * Iterates through the Array transforming items using the supplied closure
      * and collecting any non-null results.
@@ -4942,6 +5106,17 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
         return findResults(new ArrayIterator<>(self), filteringTransform);
     }
 
+    /**
+     * Iterates through the Array collecting any non-null results.
+     *
+     * @param self               an Array
+     * @return the list of non-null values
+     * @since 4.0.8
+     */
+    public static <T> Collection<T> findResults(T[] self) {
+        return findResults(self, Closure.IDENTITY);
+    }
+
     /**
      * Iterates through the map transforming items using the supplied closure
      * and collecting any non-null results.
diff --git a/src/test/groovy/inspect/InspectorTest.java b/src/test/groovy/inspect/InspectorTest.java
index cc789e2117..e6fe5679f3 100644
--- a/src/test/groovy/inspect/InspectorTest.java
+++ b/src/test/groovy/inspect/InspectorTest.java
@@ -117,9 +117,9 @@ public class InspectorTest extends MockObjectTestCase implements Serializable {
             "addShutdownHook", "any", "any", "asBoolean", "asType", "collect", "collect", "collect",
             "dump", "each", "eachWithIndex", "every", "every", "find", "find", "findAll", "findAll",
             "findIndexOf", "findIndexOf", "findIndexValues", "findIndexValues", "findLastIndexOf",
-            "findLastIndexOf", "findResult", "findResult", "getAt", "getMetaClass", "getMetaPropertyValues",
-            "getProperties", "grep", "grep", "hasProperty", "identity", "inject", "inject", "inspect",
-            "invokeMethod", "is", "isCase", "isNotCase", "iterator", "metaClass", "print", "print",
+            "findLastIndexOf", "findResult", "findResult", "findResult", "findResult", "getAt", "getMetaClass",
+            "getMetaPropertyValues", "getProperties", "grep", "grep", "hasProperty", "identity", "inject", "inject",
+            "inspect", "invokeMethod", "is", "isCase", "isNotCase", "iterator", "metaClass", "print", "print",
             "printf", "printf", "println", "println", "println", "putAt", "respondsTo", "respondsTo",
             "setMetaClass", "split", "sprintf", "sprintf", "tap", "toString", "use", "use", "use", "with",
             "with", "withTraits", "stream", "sleep", "sleep", "macro", "macro", "macro", "macro"