diff --git a/jq/build.gradle b/jq/build.gradle index 0272443..99a45d7 100644 --- a/jq/build.gradle +++ b/jq/build.gradle @@ -9,8 +9,8 @@ android { defaultConfig { minSdkVersion 3 targetSdkVersion 23 - versionCode 15 - versionName "1.1.4" + versionCode 16 + versionName "1.1.5" } buildTypes { } diff --git a/jq/src/main/java/se/code77/jq/Value.java b/jq/src/main/java/se/code77/jq/Value.java index 6e69064..b0ab985 100644 --- a/jq/src/main/java/se/code77/jq/Value.java +++ b/jq/src/main/java/se/code77/jq/Value.java @@ -14,6 +14,17 @@ * @param Type of the value being wrapped */ public final class Value implements Future { + /** + * A wrapper for calling void methods and returning Value.VOID. + */ + public interface VoidCallable { + /** + * This callback should call the void method. + * @throws Exception Any exception thrown by the callback. + */ + void call() throws Exception; + } + /** * Return value for Void callbacks */ @@ -36,6 +47,26 @@ public static Value wrap(V value) { return new Value(value); } + /** + * Convenience for calling a void method and returning a Future<Void>. + * Examples: + * + *
+     *     return Value.wrap(this::doSomething);
+
+     *     return Value.wrap(() -> doSomethingWithArgs(42));
+     * 
+ * + * @param callable The callback making the call to a void method + * @return Value.VOID + * @throws Exception if the invoked void method threw an exception + */ + public static Value wrap(VoidCallable callable) throws Exception { + callable.call(); + + return Value.VOID; + } + /** * Not applicable, since the value is already available upon construction * diff --git a/jq/src/test/java/se/code77/jq/ValueTests.java b/jq/src/test/java/se/code77/jq/ValueTests.java index d315a4f..63e9447 100644 --- a/jq/src/test/java/se/code77/jq/ValueTests.java +++ b/jq/src/test/java/se/code77/jq/ValueTests.java @@ -15,6 +15,7 @@ import se.code77.jq.Promise.UnhandledRejectionException; import se.code77.jq.util.AsyncTests; import se.code77.jq.util.BlockingDataHolder; +import se.code77.jq.util.DataCallback; import se.code77.jq.util.DataFulfilledCallback; import se.code77.jq.util.DataRejectedCallback; import se.code77.jq.util.SlowTask; @@ -73,4 +74,51 @@ public void value_isDone() { assertEquals(false, value.cancel(true)); assertEquals(true, value.isDone()); } + + private void setFlag(BlockingDataHolder holder, T data) { + if (holder != null) { + holder.set(data); + } else { + throw new IllegalArgumentException(); + } + } + + @Test + public void value_wrapVoid() { + try { + final BlockingDataHolder holder = new BlockingDataHolder<>(); + + Value v = Value.wrap(new Value.VoidCallable() { + @Override + public void call() throws Exception { + setFlag(holder, TEST_VALUE1); + } + }); + + assertEquals(Value.VOID, v); + assertData(holder, 100, TEST_VALUE1); + } catch (Exception e) { + assertTrue(false); + } + } + + @Test + public void value_wrapVoidThrows() { + final BlockingDataHolder holder = new BlockingDataHolder<>(); + + try { + Value v = Value.wrap(new Value.VoidCallable() { + @Override + public void call() throws Exception { + setFlag(null, null); + } + }); + + assertTrue(false); + } catch (Exception e) { + holder.set(e); + } + + assertData(holder, 100); + } }