allow if workflow step to take condition objects
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/flow/IfWorkflowStep.java b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/flow/IfWorkflowStep.java
index 0fcdfdd..c269616 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/flow/IfWorkflowStep.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/flow/IfWorkflowStep.java
@@ -22,14 +22,18 @@
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.reflect.TypeToken;
+import org.apache.brooklyn.core.resolve.jackson.WrappedValue;
import org.apache.brooklyn.core.workflow.WorkflowExpressionResolution.WorkflowExpressionStage;
import org.apache.brooklyn.core.workflow.WorkflowExpressionResolution.WrappedResolvedExpression;
import org.apache.brooklyn.core.workflow.WorkflowExpressionResolution.WrappingMode;
import org.apache.brooklyn.core.workflow.WorkflowStepInstanceExecutionContext;
import org.apache.brooklyn.util.collections.MutableList;
import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.core.predicates.DslPredicates.DslEntityPredicateDefault;
import org.apache.brooklyn.util.core.predicates.DslPredicates.DslPredicate;
+import org.apache.brooklyn.util.core.predicates.DslPredicates.DslPredicateDefault;
import org.apache.brooklyn.util.core.predicates.DslPredicates.WhenPresencePredicate;
+import org.apache.brooklyn.util.core.task.DeferredSupplier;
public class IfWorkflowStep extends SubWorkflowStep {
@@ -77,21 +81,51 @@
Map<String, Object> raw = MutableMap.of("target", getConditionRaw());
Object conditionConstructed = this.condition;
if (conditionConstructed==null) {
- Object k = context.getWorkflowExectionContext().resolveWrapped(
- WorkflowExpressionStage.STEP_RUNNING, condition_target, TypeToken.of(Object.class),
- WrappingMode.WRAPPED_RESULT_DEFER_THROWING_ERROR_BUT_NO_RETRY);
- Map c = MutableMap.of("target", WrappedResolvedExpression.ifNonDeferred(condition_target, k));
-
- if (condition_equals !=null) {
- Object v = context.getWorkflowExectionContext().resolveWrapped(
- WorkflowExpressionStage.STEP_RUNNING, condition_equals, TypeToken.of(Object.class),
- WrappingMode.WRAPPED_RESULT_DEFER_THROWING_ERROR_BUT_NO_RETRY);
- c.put("check", WrappedResolvedExpression.ifNonDeferred(condition_equals, v));
- c.put("assert", MutableMap.of("when", WhenPresencePredicate.PRESENT)); // when doing equals we need LHS and RHS to be present
- } else {
- c.put("when", WhenPresencePredicate.TRUTHY);
+ boolean isCondition = false;
+ boolean seemsStatic = false;
+ Object k = condition_target;
+ if (condition_equals==null) {
+ if (condition_target instanceof Map) isCondition = true;
+ else if (condition_target instanceof String) {
+ if (((String) condition_target).trim().startsWith("$")) isCondition = false;
+ if (((String) condition_target).trim().startsWith("{")) {
+ isCondition = true;
+ k = context.getWorkflowExectionContext().resolveWrapped(
+ WorkflowExpressionStage.STEP_RUNNING, condition_target, TypeToken.of(Map.class),
+ WrappingMode.WRAPPED_RESULT_DEFER_THROWING_ERROR_BUT_NO_RETRY);
+ } else seemsStatic = true;
+ } else seemsStatic = true;
}
- conditionConstructed = c;
+ k = context.getWorkflowExectionContext().resolveWrapped(
+ WorkflowExpressionStage.STEP_RUNNING, k, TypeToken.of(isCondition ? DslEntityPredicateDefault.class : Object.class),
+ WrappingMode.WRAPPED_RESULT_DEFER_THROWING_ERROR_BUT_NO_RETRY);
+
+ if (seemsStatic && !(k instanceof DslPredicate || k instanceof Boolean || k instanceof DeferredSupplier)) {
+ throw new IllegalArgumentException("Argument supplied as condition target will always evaluate as true.");
+ }
+
+ if (isCondition) {
+ if (WrappedValue.getMaybe( ((DslPredicateDefault<?>)k).implicitEquals ).map(
+ impEq -> condition_target.equals(impEq)).or(false)) {
+ // will probably have thrown error when coercing from map, so probably not needed, but for good measure
+ throw new IllegalArgumentException("Argument supplied as condition target could not be evaluated as condition.");
+ }
+ conditionConstructed = k;
+
+ } else {
+ Map c = MutableMap.of("target", WrappedResolvedExpression.ifNonDeferred(condition_target, k));
+
+ if (condition_equals != null) {
+ Object v = context.getWorkflowExectionContext().resolveWrapped(
+ WorkflowExpressionStage.STEP_RUNNING, condition_equals, TypeToken.of(Object.class),
+ WrappingMode.WRAPPED_RESULT_DEFER_THROWING_ERROR_BUT_NO_RETRY);
+ c.put("check", WrappedResolvedExpression.ifNonDeferred(condition_equals, v));
+ c.put("assert", MutableMap.of("when", WhenPresencePredicate.PRESENT)); // when doing equals we need LHS and RHS to be present
+ } else {
+ c.put("when", WhenPresencePredicate.TRUTHY);
+ }
+ conditionConstructed = c;
+ }
}
DslPredicate result = getConditionResolved(context, conditionConstructed);
diff --git a/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowSubIfAndCustomExtensionEdgeTest.java b/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowSubIfAndCustomExtensionEdgeTest.java
index 4505bd8..e411031 100644
--- a/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowSubIfAndCustomExtensionEdgeTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowSubIfAndCustomExtensionEdgeTest.java
@@ -199,6 +199,11 @@
Asserts.assertEquals(run.apply(null, "${x} == ${x}"), "yes");
Asserts.assertEquals(run.apply("let boolean x = true", "${x} == true"), "yes");
+ Asserts.assertEquals(run.apply("set-sensor xy = yes", "{ sensor: xy, equals: yes }"), "yes");
+ Asserts.assertEquals(run.apply(null, "{ sensor: xn, equals: yes }"), "no");
+ Asserts.assertFailsWith(() -> run.apply(null, "{ unknown_field: xn }"),
+ Asserts.expectedFailureContainsIgnoreCase("unknown_field", "predicate"));
+
// unresolvable things -- allowed iff no == block
Asserts.assertEquals(run.apply(null, "${unresolvable_without_equals}"), "no");
Asserts.assertFailsWith(() -> run.apply(null, "${x} == ${unresolvable_on_rhs}"),
@@ -210,11 +215,22 @@
Asserts.assertEquals(runWorkflow(MutableList.of("let boolean x = true",
"if ${x} then return yes",
"return no")), "yes");
-
Asserts.assertEquals(runWorkflow(MutableList.of("let integer x = 1",
MutableMap.of("id", "loop", "step", "let x = ${x} + 1"),
"if ${x} == 2 then goto loop",
"return ${x}")), 3);
}
+ @Test
+ public void testIfWorkflowWithSteps() throws Exception {
+ BiFunction<String, String, Object> run = (preface, cond) ->
+ runWorkflow(MutableList.<Object>of(preface==null ? "let x = hi" : preface,
+ MutableMap.of("step", "if "+(cond==null ? "${x}" : cond),
+ "steps", MutableList.of("let y = yes", "return ${y}")),
+ "return no"));
+
+ Asserts.assertEquals(run.apply(null, null), "yes");
+ Asserts.assertEquals(run.apply("let boolean x = false", null), "no");
+ }
+
}