io.cloudslang.lang.compiler.scorecompiler.ExecutionPlanBuilder.java Source code

Java tutorial

Introduction

Here is the source code for io.cloudslang.lang.compiler.scorecompiler.ExecutionPlanBuilder.java

Source

/*******************************************************************************
 * (c) Copyright 2016 Hewlett-Packard Development Company, L.P.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Apache License v2.0 which accompany this distribution.
 *
 * The Apache License is available at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 *******************************************************************************/
package io.cloudslang.lang.compiler.scorecompiler;

import ch.lambdaj.Lambda;
import io.cloudslang.lang.compiler.modeller.model.Decision;
import io.cloudslang.lang.compiler.modeller.model.ExternalStep;
import io.cloudslang.lang.compiler.modeller.model.Flow;
import io.cloudslang.lang.compiler.modeller.model.Operation;
import io.cloudslang.lang.compiler.modeller.model.Step;
import io.cloudslang.lang.entities.ExecutableType;
import io.cloudslang.lang.entities.ResultNavigation;
import io.cloudslang.lang.entities.bindings.Result;
import io.cloudslang.score.api.ExecutionPlan;
import io.cloudslang.score.api.ExecutionStep;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections4.CollectionUtils;

import static ch.lambdaj.Lambda.having;
import static ch.lambdaj.Lambda.on;
import static ch.lambdaj.Lambda.selectFirst;
import static org.hamcrest.Matchers.equalTo;

/*
 * Created by orius123 on 11/11/14.
 */
public class ExecutionPlanBuilder {

    private ExecutionStepFactory stepFactory;

    private ExternalExecutionStepFactory externalStepFactory;

    private static final String CLOUDSLANG_NAME = "CloudSlang";
    private static final int NUMBER_OF_STEP_EXECUTION_STEPS = 2;
    private static final int NUMBER_OF_PARALLEL_LOOP_EXECUTION_STEPS = 2;
    private static final long FLOW_END_STEP_ID = 0L;
    private static final long FLOW_START_STEP_ID = 1L;

    public ExecutionPlan createOperationExecutionPlan(Operation compiledOp) {
        ExecutionPlan executionPlan = new ExecutionPlan();
        executionPlan.setName(compiledOp.getName());
        executionPlan.setLanguage(CLOUDSLANG_NAME);
        executionPlan.setFlowUuid(compiledOp.getId());

        executionPlan.setBeginStep(1L);

        executionPlan.addStep(stepFactory.createStartStep(1L, compiledOp.getPreExecActionData(),
                compiledOp.getInputs(), compiledOp.getName(), ExecutableType.OPERATION));
        executionPlan.addStep(stepFactory.createActionStep(2L, compiledOp.getAction().getActionData()));
        executionPlan.addStep(stepFactory.createEndStep(3L, compiledOp.getPostExecActionData(),
                compiledOp.getOutputs(), compiledOp.getResults(), compiledOp.getName(), ExecutableType.OPERATION));
        return executionPlan;
    }

    public ExecutionPlan createDecisionExecutionPlan(Decision compiledDecision) {
        ExecutionPlan executionPlan = new ExecutionPlan();
        executionPlan.setName(compiledDecision.getName());
        executionPlan.setLanguage(CLOUDSLANG_NAME);
        executionPlan.setFlowUuid(compiledDecision.getId());

        executionPlan.setBeginStep(1L);

        executionPlan.addStep(stepFactory.createStartStep(1L, compiledDecision.getPreExecActionData(),
                compiledDecision.getInputs(), compiledDecision.getName(), ExecutableType.DECISION));
        executionPlan.addStep(stepFactory.createEndStep(2L, compiledDecision.getPostExecActionData(),
                compiledDecision.getOutputs(), compiledDecision.getResults(), compiledDecision.getName(),
                ExecutableType.DECISION));
        return executionPlan;
    }

    public ExecutionPlan createFlowExecutionPlan(Flow compiledFlow) {
        ExecutionPlan executionPlan = new ExecutionPlan();
        executionPlan.setName(compiledFlow.getName());
        executionPlan.setLanguage(CLOUDSLANG_NAME);
        executionPlan.setFlowUuid(compiledFlow.getId());
        executionPlan.setWorkerGroup(compiledFlow.getWorkerGroup());

        executionPlan.setBeginStep(FLOW_START_STEP_ID);
        //flow start step
        executionPlan.addStep(stepFactory.createStartStep(FLOW_START_STEP_ID, compiledFlow.getPreExecActionData(),
                compiledFlow.getInputs(), compiledFlow.getName(), ExecutableType.FLOW));
        //flow end step
        executionPlan.addStep(stepFactory.createEndStep(FLOW_END_STEP_ID, compiledFlow.getPostExecActionData(),
                compiledFlow.getOutputs(), compiledFlow.getResults(), compiledFlow.getName(), ExecutableType.FLOW));

        Map<String, Long> stepReferences = getStepReferences(compiledFlow);

        Deque<Step> steps = compiledFlow.getWorkflow().getSteps();

        if (CollectionUtils.isEmpty(steps)) {
            throw new RuntimeException("Flow: " + compiledFlow.getName() + " has no steps");
        }

        List<ExecutionStep> stepExecutionSteps = buildStepExecutionSteps(steps.getFirst(), stepReferences, steps,
                compiledFlow);
        executionPlan.addSteps(stepExecutionSteps);

        return executionPlan;
    }

    private Map<String, Long> getStepReferences(Flow compiledFlow) {
        Map<String, Long> stepReferences = new HashMap<>();
        for (Result result : compiledFlow.getResults()) {
            stepReferences.put(result.getName(), FLOW_END_STEP_ID);
        }
        return stepReferences;
    }

    private List<ExecutionStep> buildStepExecutionSteps(Step step, Map<String, Long> stepReferences,
            Deque<Step> steps, Flow compiledFlow) {

        List<ExecutionStep> stepExecutionSteps = new ArrayList<>();

        String stepName = step.getName();
        long currentId = getCurrentId(stepReferences, steps);
        boolean parallelLoop = step.isParallelLoop();

        //Begin Step
        stepReferences.put(stepName, currentId);
        if (parallelLoop) {
            Long joinStepId = currentId + NUMBER_OF_PARALLEL_LOOP_EXECUTION_STEPS + 1;
            stepExecutionSteps.add(stepFactory.createAddBranchesStep(currentId++, joinStepId, currentId,
                    step.getPreStepActionData(), compiledFlow.getId(), stepName));
        }

        stepExecutionSteps.add(createBeginStep(currentId++, step, inheritWorkerGroupFromFlow(step, compiledFlow)));

        //End Step
        Map<String, ResultNavigation> navigationValues = new HashMap<>();
        for (Map<String, String> map : step.getNavigationStrings()) {
            Map.Entry<String, String> entry = map.entrySet().iterator().next();
            String nextStepName = entry.getValue();
            if (stepReferences.get(nextStepName) == null) {
                Step nextStepToCompile = selectFirst(steps,
                        having(on(Step.class).getName(), equalTo(nextStepName)));
                stepExecutionSteps
                        .addAll(buildStepExecutionSteps(nextStepToCompile, stepReferences, steps, compiledFlow));
            }
            long nextStepId = stepReferences.get(nextStepName);
            String presetResult = (FLOW_END_STEP_ID == nextStepId) ? nextStepName : null;
            String navigationKey = entry.getKey();
            if (!navigationValues.containsKey(navigationKey)) {
                navigationValues.put(navigationKey, new ResultNavigation(nextStepId, presetResult));
            }
        }
        if (parallelLoop) {
            stepExecutionSteps.add(createFinishStepStep(currentId++, step, new HashMap<>(),
                    inheritWorkerGroupFromFlow(step, compiledFlow), true));
            stepExecutionSteps.add(stepFactory.createJoinBranchesStep(currentId, step.getPostStepActionData(),
                    navigationValues, stepName));
        } else {
            stepExecutionSteps.add(createFinishStepStep(currentId, step, navigationValues,
                    inheritWorkerGroupFromFlow(step, compiledFlow), false));
        }
        return stepExecutionSteps;
    }

    private String inheritWorkerGroupFromFlow(Step step, Flow flow) {
        if (step.getWorkerGroup() != null) {
            return step.getWorkerGroup();
        } else if (flow.getWorkerGroup() != null) {
            return flow.getWorkerGroup();
        } else {
            return null;
        }
    }

    private long getCurrentId(Map<String, Long> stepReferences, Deque<Step> steps) {
        Long currentId;

        long max = Lambda.max(stepReferences);
        Map.Entry maxEntry = selectFirst(stepReferences.entrySet(),
                having(on(Map.Entry.class).getValue(), equalTo(max)));
        String referenceKey = (String) (maxEntry).getKey();
        Step step = null;
        for (Step stepItem : steps) {
            if (stepItem.getName().equals(referenceKey)) {
                step = stepItem;
                break;
            }
        }

        if (step == null || !step.isParallelLoop()) {
            // the reference is not a step or is not a parallel loop step
            currentId = max + NUMBER_OF_STEP_EXECUTION_STEPS;
        } else {
            //async step
            currentId = max + NUMBER_OF_STEP_EXECUTION_STEPS + NUMBER_OF_PARALLEL_LOOP_EXECUTION_STEPS;
        }

        return currentId;
    }

    private ExecutionStep createFinishStepStep(long currentId, Step step,
            Map<String, ResultNavigation> navigationValues, String workerGroup, boolean parallelLoop) {
        if (step instanceof ExternalStep) {
            return externalStepFactory.createFinishExternalFlowStep(currentId, step.getPostStepActionData(),
                    navigationValues, step.getName(), parallelLoop);
        }
        return stepFactory.createFinishStepStep(currentId, step.getPostStepActionData(), navigationValues,
                step.getName(), workerGroup, parallelLoop);
    }

    private ExecutionStep createBeginStep(Long id, Step step, String workerGroup) {
        if (step instanceof ExternalStep) {
            return externalStepFactory.createBeginExternalFlowStep(id, step.getArguments(),
                    step.getPreStepActionData(), step.getRefId(), step.getName());
        }
        return stepFactory.createBeginStepStep(id, step.getArguments(), step.getPreStepActionData(),
                step.getRefId(), step.getName(), workerGroup);
    }

    public void setStepFactory(ExecutionStepFactory stepFactory) {
        this.stepFactory = stepFactory;
    }

    public void setExternalStepFactory(ExternalExecutionStepFactory externalStepFactory) {
        this.externalStepFactory = externalStepFactory;
    }
}