in core/src/main/java/org/apache/brooklyn/core/workflow/steps/variables/TransformVariableWorkflowStep.java [105:235]
protected Object doTaskBody(WorkflowStepInstanceExecutionContext context) {
TypedValueToSet variable = context.getInput(VARIABLE);
Object transformO = context.getInputRaw(TRANSFORM.getName());
if (!(transformO instanceof Iterable)) transformO = MutableList.of(transformO);
List<String> transforms = MutableList.of();
for (Object t: (Iterable)transformO) {
if (t instanceof String) transforms.addAll(MutableList.copyOf(Arrays.stream( ((String)t).split("\\|") ).map(String::trim).collect(Collectors.toList())));
else throw new IllegalArgumentException("Argument to transform should be a string or list of strings, not: "+t);
}
String varName = null;
Object vv_auto = input.get(VV_AUTO.getName());
boolean variableNameSpecified = variable != null && Strings.isNonBlank(variable.name);
Object valueExpressionToTransform = null;
boolean setVariableAtEnd = variableNameSpecified;
Boolean typeCoercionAtStart = null;
if (Strings.isNonBlank((String)vv_auto)) {
boolean isVariable = input.containsKey(VALUE.getName());
boolean isValue = variableNameSpecified;
if (!isVariable && !isValue) {
isValue = true;
// in future, just do the line above
// ...
// but for now we need to exclude it if it matches a workflow variable because that could be legacy syntax
boolean isDisallowedUndecoratedVariable = false;
try {
Object vvAutoResolved = context.resolve(WorkflowExpressionResolution.WorkflowExpressionStage.STEP_INPUT, "${" + vv_auto + "}", Object.class);
isDisallowedUndecoratedVariable = true;
} catch (Exception e) {
Exceptions.propagateIfFatal(e);
// otherwise normal, it does not match a variable name, so treat it as the value
}
if (isDisallowedUndecoratedVariable)
throw new IllegalArgumentException("Legacy transform syntax `transform var_name | ...` disallowed (" + vv_auto + "); use '${"+vv_auto+"'}' if you don't want to update it or insert the keyword 'variable' if you do");
}
if (isVariable) {
if (isValue) throw new IllegalArgumentException("Legacy transform identified as both value and variable");
varName = (String) vv_auto;
setVariableAtEnd = true;
typeCoercionAtStart = false;
} else {
if (!isValue) throw new IllegalArgumentException("Legacy transform cannot identify as value or variable");
valueExpressionToTransform = vv_auto;
typeCoercionAtStart = !variableNameSpecified;
}
}
if (variableNameSpecified) {
if (varName!=null) throw new IllegalStateException("Variable name specified twice"); //shouldn't happen
varName = variable.name;
setVariableAtEnd = true;
}
if (valueExpressionToTransform==null) {
// value not set from auto; check if specified elsewhere
valueExpressionToTransform = input.get(VALUE.getName());
if (typeCoercionAtStart==null && valueExpressionToTransform!=null) typeCoercionAtStart = !variableNameSpecified;
}
if (valueExpressionToTransform==null) {
if (!variableNameSpecified) throw new IllegalArgumentException("Transform needs a variable or value to transform");
valueExpressionToTransform = "${"+variable.name+"}";
if (typeCoercionAtStart!=null) throw new IllegalStateException("Unclear whether to do type coercion; should be unset"); // shouldn't come here
typeCoercionAtStart = true;
}
if (typeCoercionAtStart==null) {
throw new IllegalStateException("Unclear whether to do type coercion; should be set"); // shouldn't come here
}
if (variable!=null && Strings.isNonBlank(variable.type)) {
// if type is specified with a variable used to start the transform, we coerce to that type at the start and at the end
if (typeCoercionAtStart) transforms.add(0, "type " + variable.type);
if (setVariableAtEnd) transforms.add("type " + variable.type);
}
boolean isResolved = false;
Object v = valueExpressionToTransform;
for (String t: transforms) {
WorkflowTransformWithContext tt = getTransform(context, t);
Boolean req = tt.resolvedValueRequirement();
if (req==null) { /* no requirement */ }
else if (req && !isResolved) {
v = context.resolve(WorkflowExpressionResolution.WorkflowExpressionStage.STEP_RUNNING, v, TypeToken.of(Object.class));
isResolved = true;
} else if (!req && isResolved) {
throw new IllegalArgumentException("Transform '" + t + "' must be first or follow a resolve_expression transform as it requires unresolved input");
} else {
// requirement matches resolution status, both done, or both not
}
v = tt.apply(v);
Boolean ret = tt.resolvedValueReturned();
if (ret!=null) isResolved = ret;
}
if (!isResolved) {
// in case "resolve" was supplied at the end
v = context.resolve(WorkflowExpressionResolution.WorkflowExpressionStage.STEP_RUNNING, v, TypeToken.of(Object.class));
isResolved = true;
}
if (setVariableAtEnd) {
if (varName==null) throw new IllegalStateException("Variable name not specified when setting variable"); // shouldn't happen
setWorkflowScratchVariableDotSeparated(context, varName, v);
// easily inferred from workflow vars, now that updates are stored separately
// Object oldValue =
// <above> setWorkflowScratchVariableDotSeparated(context, varName, v);
// context.noteOtherMetadata("Value set", v);
// if (oldValue != null) context.noteOtherMetadata("Previous value", oldValue);
if (context.getOutput()!=null) throw new IllegalStateException("Transform that produces output results cannot be used when setting a variable");
if (STEP_TARGET_NAME_FOR_END.equals(context.next)) throw new IllegalStateException("Return transform cannot be used when setting a variable");
return context.getPreviousStepOutput();
} else {
return v;
}
}