You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by ge...@apache.org on 2016/12/20 11:10:22 UTC
[04/13] brooklyn-server git commit: Non-recursive ValueResolver
Non-recursive ValueResolver
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/42bc7c13
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/42bc7c13
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/42bc7c13
Branch: refs/heads/master
Commit: 42bc7c136ec885cc43125edfee86a741793aa64b
Parents: ddfe733
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Mon Dec 12 18:02:16 2016 +0200
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Tue Dec 13 09:15:36 2016 +0200
----------------------------------------------------------------------
.../brooklyn/util/core/task/ValueResolver.java | 37 ++++++++-
.../util/core/task/ValueResolverTest.java | 83 +++++++++++++++++++-
2 files changed, 116 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/42bc7c13/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolver.java b/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolver.java
index 6775a44..4dcf5be 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolver.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolver.java
@@ -31,6 +31,7 @@ import org.apache.brooklyn.api.mgmt.Task;
import org.apache.brooklyn.api.mgmt.TaskAdaptable;
import org.apache.brooklyn.core.entity.EntityInternal;
import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
+import org.apache.brooklyn.core.mgmt.rebind.ImmediateDeltaChangeListener;
import org.apache.brooklyn.util.core.flags.TypeCoercions;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.guava.Maybe;
@@ -110,6 +111,7 @@ public class ValueResolver<T> implements DeferredSupplier<T> {
/** timeout on execution, if possible, or if embedResolutionInTask is true */
Duration timeout;
boolean immediately;
+ boolean recursive = true;
boolean isTransientTask = true;
T defaultValue = null;
@@ -144,6 +146,7 @@ public class ValueResolver<T> implements DeferredSupplier<T> {
timeout = parent.timeout;
immediately = parent.immediately;
+ // not copying recursive as we want deep resolving to be recursive, only top-level values should be non-recursive
parentTimer = parent.parentTimer;
if (parentTimer!=null && parentTimer.isExpired())
expired = true;
@@ -167,7 +170,9 @@ public class ValueResolver<T> implements DeferredSupplier<T> {
.context(exec).description(description)
.embedResolutionInTask(embedResolutionInTask)
.deep(forceDeep)
- .timeout(timeout);
+ .timeout(timeout)
+ .immediately(immediately)
+ .recursive(recursive);
if (returnDefaultOnGet) result.defaultValue(defaultValue);
if (swallowExceptions) result.swallowExceptions();
return result;
@@ -264,6 +269,18 @@ public class ValueResolver<T> implements DeferredSupplier<T> {
return this;
}
+ /**
+ * Whether the value should be resolved recursively. When true the result of
+ * the resolving will be resolved again recursively until the value is an immediate object.
+ * When false will try to resolve the value a single time and return the result even if it
+ * can be resolved further (e.x. it is DeferredSupplier).
+ */
+ @Beta
+ public ValueResolver<T> recursive(boolean val) {
+ this.recursive = val;
+ return this;
+ }
+
protected void checkTypeNotNull() {
if (type==null)
throw new NullPointerException("type must be set to resolve, for '"+value+"'"+(description!=null ? ", "+description : ""));
@@ -297,6 +314,11 @@ public class ValueResolver<T> implements DeferredSupplier<T> {
exec = BasicExecutionContext.getCurrentExecutionContext();
}
+ if (!recursive && type != Object.class) {
+ throw new IllegalStateException("When non-recursive resolver requested the return type must be Object " +
+ "as the immediately resolved value could be a number of (deferred) types.");
+ }
+
CountdownTimer timerU = parentTimer;
if (timerU==null && timeout!=null)
timerU = timeout.countdownTimer();
@@ -319,7 +341,11 @@ public class ValueResolver<T> implements DeferredSupplier<T> {
Maybe<?> result = supplier.getImmediately();
// Recurse: need to ensure returned value is cast, etc
- return (result.isPresent()) ? new ValueResolver(result.get(), type, this).getMaybe() : Maybe.<T>absent();
+ return (result.isPresent())
+ ? recursive
+ ? new ValueResolver(result.get(), type, this).getMaybe()
+ : result
+ : Maybe.<T>absent();
} catch (ImmediateSupplier.ImmediateUnsupportedException e) {
log.debug("Unable to resolve-immediately for "+description+" ("+v+"); falling back to executing with timeout", e);
}
@@ -455,7 +481,12 @@ public class ValueResolver<T> implements DeferredSupplier<T> {
throw problem;
}
- return new ValueResolver(v, type, this).getMaybe();
+ if (recursive) {
+ return new ValueResolver(v, type, this).getMaybe();
+ } else {
+ // T expected to be Object.class
+ return (Maybe<T>) Maybe.of(v);
+ }
}
protected String getDescription() {
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/42bc7c13/core/src/test/java/org/apache/brooklyn/util/core/task/ValueResolverTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/util/core/task/ValueResolverTest.java b/core/src/test/java/org/apache/brooklyn/util/core/task/ValueResolverTest.java
index b7e9085..ffe6762 100644
--- a/core/src/test/java/org/apache/brooklyn/util/core/task/ValueResolverTest.java
+++ b/core/src/test/java/org/apache/brooklyn/util/core/task/ValueResolverTest.java
@@ -172,7 +172,55 @@ public class ValueResolverTest extends BrooklynAppUnitTestSupport {
assertEquals(BrooklynTaskTags.getContextEntity(callInfo.task), app);
assertNotContainsCallingMethod(callInfo.stackTrace, "testGetImmediatelyFallsBackToDeferredCallInTask");
}
-
+
+ public void testNonRecursiveBlockingFailsOnNonObjectType() throws Exception {
+ try {
+ Tasks.resolving(new WrappingImmediateAndDeferredSupplier(new FailingImmediateAndDeferredSupplier()))
+ .as(FailingImmediateAndDeferredSupplier.class)
+ .context(app)
+ .immediately(false)
+ .recursive(false)
+ .get();
+ Asserts.shouldHaveFailedPreviously("recursive(true) accepts only as(Object.class)");
+ } catch (IllegalStateException e) {
+ Asserts.expectedFailureContains(e, "must be Object");
+ }
+ }
+
+ public void testNonRecursiveBlocking() throws Exception {
+ Object result = Tasks.resolving(new WrappingImmediateAndDeferredSupplier(new FailingImmediateAndDeferredSupplier()))
+ .as(Object.class)
+ .context(app)
+ .immediately(false)
+ .recursive(false)
+ .get();
+ assertEquals(result.getClass(), FailingImmediateAndDeferredSupplier.class);
+ }
+
+ public void testNonRecursiveImmediateFailsOnNonObjectType() throws Exception {
+ try {
+ Tasks.resolving(new WrappingImmediateAndDeferredSupplier(new FailingImmediateAndDeferredSupplier()))
+ .as(FailingImmediateAndDeferredSupplier.class)
+ .context(app)
+ .immediately(true)
+ .recursive(false)
+ .get();
+ Asserts.shouldHaveFailedPreviously("recursive(true) accepts only as(Object.class)");
+ } catch (IllegalStateException e) {
+ Asserts.expectedFailureContains(e, "must be Object");
+ }
+ }
+
+ public void testNonRecursiveImmediately() throws Exception {
+ Object result = Tasks.resolving(new WrappingImmediateAndDeferredSupplier(new FailingImmediateAndDeferredSupplier()))
+ .as(Object.class)
+ .context(app)
+ .immediately(true)
+ .recursive(false)
+ .get();
+ assertEquals(result.getClass(), FailingImmediateAndDeferredSupplier.class);
+ }
+
private static class MyImmediateAndDeferredSupplier implements ImmediateSupplier<CallInfo>, DeferredSupplier<CallInfo> {
private final boolean failImmediately;
@@ -198,6 +246,39 @@ public class ValueResolverTest extends BrooklynAppUnitTestSupport {
}
}
+ private static class WrappingImmediateAndDeferredSupplier implements ImmediateSupplier<Object>, DeferredSupplier<Object> {
+ private Object value;
+
+ public WrappingImmediateAndDeferredSupplier(Object value) {
+ this.value = value;
+ }
+
+ @Override
+ public Object get() {
+ return getImmediately().get();
+ }
+
+ @Override
+ public Maybe<Object> getImmediately() {
+ return Maybe.of(value);
+ }
+
+ }
+
+ private static class FailingImmediateAndDeferredSupplier implements ImmediateSupplier<Object>, DeferredSupplier<Object> {
+
+ @Override
+ public Object get() {
+ throw new IllegalStateException("Not to be called");
+ }
+
+ @Override
+ public Maybe<Object> getImmediately() {
+ throw new IllegalStateException("Not to be called");
+ }
+
+ }
+
private static class CallInfo {
final StackTraceElement[] stackTrace;
final Task<?> task;