protected Object doTaskBody()

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;
        }
    }