Repository: groovy Updated Branches: refs/heads/master 82e161561 -> dfefeefa6
GROOVY-8519: Groovy should provide collect DGM variants for Optional and Future Project: http://git-wip-us.apache.org/repos/asf/groovy/repo Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/dfefeefa Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/dfefeefa Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/dfefeefa Branch: refs/heads/master Commit: dfefeefa6fdae3701697d95f32572b7ed3c25aec Parents: 82e1615 Author: paulk <[email protected]> Authored: Mon Mar 26 10:26:33 2018 +1000 Committer: paulk <[email protected]> Committed: Mon Mar 26 10:26:33 2018 +1000 ---------------------------------------------------------------------- .../vmplugin/v8/PluginDefaultGroovyMethods.java | 86 ++++++++++++++++++++ 1 file changed, 86 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/groovy/blob/dfefeefa/src/main/java/org/codehaus/groovy/vmplugin/v8/PluginDefaultGroovyMethods.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v8/PluginDefaultGroovyMethods.java b/src/main/java/org/codehaus/groovy/vmplugin/v8/PluginDefaultGroovyMethods.java index 973d856..7a27293 100644 --- a/src/main/java/org/codehaus/groovy/vmplugin/v8/PluginDefaultGroovyMethods.java +++ b/src/main/java/org/codehaus/groovy/vmplugin/v8/PluginDefaultGroovyMethods.java @@ -18,12 +18,21 @@ */ package org.codehaus.groovy.vmplugin.v8; +import groovy.lang.Closure; +import groovy.transform.stc.ClosureParams; +import groovy.transform.stc.FirstParam; + import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.Spliterator; import java.util.Spliterators; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.stream.BaseStream; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -53,6 +62,83 @@ public class PluginDefaultGroovyMethods { } /** + * If the optional contains a value, returns an optional containing the transformed value obtained using the <code>transform</code> closure + * or otherwise an empty optional. + * <pre class="groovyTestCase"> + * assert Optional.of("foobar").collect{ it.size() }.get() == 6 + * assert !Optional.empty().collect{ it.size() }.isPresent() + * </pre> + * + * @param self an Optional + * @param transform the closure used to transform the optional value if present + * @return an Optional containing the transformed value or empty if the optional is empty or the transform returns null + */ + public static <S,T> Optional<T> collect(Optional<S> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure<T> transform) { + Objects.requireNonNull(self); + Objects.requireNonNull(transform); + if (!self.isPresent()) { + return self.empty(); + } + return Optional.ofNullable(transform.call(self.get())); + } + + /** + * Returns a Future asynchronously returning a transformed result. + * <pre class="groovyTestCase"> + * import java.util.concurrent.* + * def executor = Executors.newSingleThreadExecutor() + * Future<String> foobar = executor.submit{ "foobar" } + * Future<Integer> foobarSize = foobar.collect{ it.size() } + * assert foobarSize.get() == 6 + * executor.shutdown() + * </pre> + * + * @param self a Future + * @param transform the closure used to transform the Future value + * @return a Future allowing the transformed value to be obtained asynchronously + */ + public static <S,T> Future<T> collect(Future<S> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure<T> transform) { + Objects.requireNonNull(self); + Objects.requireNonNull(transform); + return new TransformedFuture<T>(self, transform); + } + + private static class TransformedFuture<E> implements Future<E> { + private Future delegate; + private Closure<E> transform; + + private TransformedFuture(Future delegate, Closure<E> transform) { + this.delegate = delegate; + this.transform = transform; + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + return delegate.cancel(mayInterruptIfRunning); + } + + @Override + public boolean isCancelled() { + return delegate.isCancelled(); + } + + @Override + public boolean isDone() { + return delegate.isDone(); + } + + @Override + public E get() throws InterruptedException, ExecutionException { + return transform.call(delegate.get()); + } + + @Override + public E get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + return transform.call(delegate.get(timeout, unit)); + } + } + + /** * Accumulates the elements of stream into a new List. * @param stream the Stream * @param <T> the type of element
