Search in sources :

Example 26 with WorkflowStep

use of org.alien4cloud.tosca.model.workflow.WorkflowStep in project alien4cloud by alien4cloud.

the class WorkflowSimplifyService method removeUnnecessarySteps.

private void removeUnnecessarySteps(TopologyContext topologyContext, Workflow workflow, SubGraph subGraph) {
    LastPathGraphConsumer consumer = new LastPathGraphConsumer();
    subGraph.browse(consumer);
    if (consumer.getAllNodes().isEmpty()) {
        // This is really strange as we have a node template without any workflow step
        return;
    }
    Set<String> allStepIds = consumer.getAllNodes().keySet();
    List<WorkflowStep> sortedByWeightsSteps = consumer.getLastPath();
    List<Integer> nonEmptyIndexes = new ArrayList<>();
    LinkedHashSet<Integer> emptyIndexes = new LinkedHashSet<>();
    int lastIndexWithOutgoingLinks = -1;
    int firstIndexWithOutgoingLinks = -1;
    for (int i = 0; i < sortedByWeightsSteps.size(); i++) {
        WorkflowStep step = sortedByWeightsSteps.get(i);
        if (!allStepIds.containsAll(step.getOnSuccess())) {
            lastIndexWithOutgoingLinks = i;
            if (firstIndexWithOutgoingLinks == -1) {
                firstIndexWithOutgoingLinks = i;
            }
        }
        if (!WorkflowGraphUtils.isStepEmpty(step, topologyContext)) {
            nonEmptyIndexes.add(i);
        } else {
            emptyIndexes.add(i);
        }
    }
    Map<Integer, Integer> emptyIndexToFollowingSubstituteMap = new HashMap<>();
    Map<Integer, Integer> emptyIndexToPrecedingSubstituteMap = new HashMap<>();
    for (Integer emptyIndex : emptyIndexes) {
        Optional<Integer> substitutePrecedingIndex = nonEmptyIndexes.stream().filter(nonEmptyIndex -> nonEmptyIndex > emptyIndex).findFirst();
        Optional<Integer> substituteFollowingIndex = nonEmptyIndexes.stream().filter(nonEmptyIndex -> nonEmptyIndex < emptyIndex).reduce((first, second) -> second);
        substitutePrecedingIndex.ifPresent(index -> emptyIndexToPrecedingSubstituteMap.put(emptyIndex, index));
        substituteFollowingIndex.ifPresent(index -> emptyIndexToFollowingSubstituteMap.put(emptyIndex, index));
    }
    for (int index = 0; index < sortedByWeightsSteps.size(); index++) {
        WorkflowStep step = sortedByWeightsSteps.get(index);
        boolean stepIsEmpty = emptyIndexes.contains(index);
        Integer followingSubstitutedIndex = emptyIndexToFollowingSubstituteMap.get(index);
        Integer precedingSubstitutedIndex = emptyIndexToPrecedingSubstituteMap.get(index);
        if (stepIsEmpty) {
            if (followingSubstitutedIndex == null && !allStepIds.containsAll(step.getOnSuccess())) {
                // the step is empty but no substitute for following links, it means that before the step there are no non empty steps
                if (firstIndexWithOutgoingLinks >= 0 && firstIndexWithOutgoingLinks <= index) {
                    // the step or before the step, outgoing links exist out of the sub graph so we should not remove it, because it will impact the
                    // structure of the graph
                    emptyIndexes.remove(index);
                    continue;
                }
            }
            if (precedingSubstitutedIndex == null && !allStepIds.containsAll(step.getPrecedingSteps())) {
                // the step is empty but no substitute for preceding links, it means that after the step there are no non empty steps
                if (lastIndexWithOutgoingLinks >= index) {
                    // the step or after the step, outgoing links exist out of the sub graph so we should not remove it, because it will impact the
                    // structure of the graph
                    emptyIndexes.remove(index);
                    continue;
                }
            }
            // Empty so the step will be removed, so unlink all
            for (String following : step.getOnSuccess()) {
                workflow.getSteps().get(following).removePreceding(step.getName());
            }
            for (String preceding : step.getPrecedingSteps()) {
                workflow.getSteps().get(preceding).removeFollowing(step.getName());
            }
            if (followingSubstitutedIndex != null) {
                WorkflowStep substitutedFollowingStep = sortedByWeightsSteps.get(followingSubstitutedIndex);
                for (String following : step.getOnSuccess()) {
                    workflow.getSteps().get(following).addPreceding(substitutedFollowingStep.getName());
                }
                // Copy all links to the substituted node
                substitutedFollowingStep.addAllFollowings(step.getOnSuccess());
            }
            if (precedingSubstitutedIndex != null) {
                WorkflowStep substitutedPrecedingStep = sortedByWeightsSteps.get(precedingSubstitutedIndex);
                for (String preceding : step.getPrecedingSteps()) {
                    workflow.getSteps().get(preceding).addFollowing(substitutedPrecedingStep.getName());
                }
                substitutedPrecedingStep.addAllPrecedings(step.getPrecedingSteps());
            }
        }
    }
    int index = 0;
    Iterator<WorkflowStep> stepIterator = sortedByWeightsSteps.iterator();
    while (stepIterator.hasNext()) {
        WorkflowStep step = stepIterator.next();
        if (emptyIndexes.contains(index)) {
            stepIterator.remove();
            workflow.getSteps().remove(step.getName());
        }
        index++;
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Iterator(java.util.Iterator) Getter(lombok.Getter) AlienUtils(alien4cloud.utils.AlienUtils) Workflow(org.alien4cloud.tosca.model.workflow.Workflow) WorkflowStepWeightComparator(alien4cloud.paas.wf.util.WorkflowStepWeightComparator) Set(java.util.Set) HashMap(java.util.HashMap) SubGraph(alien4cloud.paas.wf.util.SubGraph) SubGraphFilter(alien4cloud.paas.wf.util.SubGraphFilter) ArrayList(java.util.ArrayList) List(java.util.List) Component(org.springframework.stereotype.Component) WorkflowGraphUtils(alien4cloud.paas.wf.util.WorkflowGraphUtils) Slf4j(lombok.extern.slf4j.Slf4j) SimpleGraphConsumer(alien4cloud.paas.wf.util.SimpleGraphConsumer) Map(java.util.Map) Optional(java.util.Optional) NodeSubGraphFilter(alien4cloud.paas.wf.util.NodeSubGraphFilter) LinkedList(java.util.LinkedList) WorkflowStep(org.alien4cloud.tosca.model.workflow.WorkflowStep) LinkedHashSet(java.util.LinkedHashSet) WorkflowStep(org.alien4cloud.tosca.model.workflow.WorkflowStep) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList)

Example 27 with WorkflowStep

use of org.alien4cloud.tosca.model.workflow.WorkflowStep in project alien4cloud by alien4cloud.

the class SemanticValidation method validate.

@Override
public List<AbstractWorkflowError> validate(TopologyContext topologyContext, Workflow workflow) throws WorkflowException {
    if (workflow.getSteps() == null || workflow.getSteps().isEmpty()) {
        return null;
    }
    List<AbstractWorkflowError> errors = Lists.newArrayList();
    for (WorkflowStep step : workflow.getSteps().values()) {
        if (step.getActivity() instanceof InlineWorkflowActivity) {
            // TODO when the tosca model is clear we should create InlineWorkflowStep
            String inlinedWorkflow = ((InlineWorkflowActivity) step.getActivity()).getInline();
            if (topologyContext.getTopology().getWorkflows() == null || !topologyContext.getTopology().getWorkflows().containsKey(inlinedWorkflow)) {
                errors.add(new InlinedWorkflowNotFoundError(step.getName(), inlinedWorkflow));
            }
        } else if (StringUtils.isEmpty(step.getTarget())) {
            errors.add(new UnknownNodeError(step.getName(), "undefined target in non inline workflow activity"));
        } else {
            String nodeId = step.getTarget();
            NodeTemplate nodeTemplate = null;
            if (topologyContext.getTopology().getNodeTemplates() != null) {
                nodeTemplate = topologyContext.getTopology().getNodeTemplates().get(nodeId);
            }
            if (nodeTemplate == null) {
                errors.add(new UnknownNodeError(step.getName(), nodeId));
            } else if (step instanceof RelationshipWorkflowStep) {
                RelationshipWorkflowStep relationshipWorkflowStep = (RelationshipWorkflowStep) step;
                String relationshipId = relationshipWorkflowStep.getTargetRelationship();
                if (nodeTemplate.getRelationships() == null || !nodeTemplate.getRelationships().containsKey(relationshipId)) {
                    errors.add(new UnknownRelationshipError(step.getName(), nodeId, relationshipId));
                }
            }
        // TODO: here we should check interface & operation
        }
    }
    return errors;
}
Also used : InlineWorkflowActivity(org.alien4cloud.tosca.model.workflow.activities.InlineWorkflowActivity) NodeTemplate(org.alien4cloud.tosca.model.templates.NodeTemplate) RelationshipWorkflowStep(org.alien4cloud.tosca.model.workflow.RelationshipWorkflowStep) WorkflowStep(org.alien4cloud.tosca.model.workflow.WorkflowStep) RelationshipWorkflowStep(org.alien4cloud.tosca.model.workflow.RelationshipWorkflowStep)

Example 28 with WorkflowStep

use of org.alien4cloud.tosca.model.workflow.WorkflowStep in project alien4cloud by alien4cloud.

the class WorkflowStepDefinitions method the_workflow_step_is_preceded_by.

@When("^The workflow step \"(.*?)\" is preceded by: (.*)$")
public void the_workflow_step_is_preceded_by(String stepId, List<String> predecesors) throws Throwable {
    String topologyResponseText = Context.getInstance().getRestResponse();
    RestResponse<TopologyDTO> topologyResponse = JsonUtil.read(topologyResponseText, TopologyDTO.class, Context.getJsonMapper());
    String workflowName = Context.getInstance().getCurrentWorkflowName();
    Workflow workflow = topologyResponse.getData().getTopology().getWorkflows().get(workflowName);
    WorkflowStep step = workflow.getSteps().get(stepId);
    Set<String> actualPredecessors = step.getPrecedingSteps();
    assertNotNull(actualPredecessors);
    assertEquals(predecesors.size(), actualPredecessors.size());
    for (String expectedPredecessor : predecesors) {
        // we just remove the surrounding quotes
        String predecessor = expectedPredecessor.substring(1, expectedPredecessor.length() - 1);
        assertTrue(actualPredecessors.contains(predecessor));
    }
}
Also used : TopologyDTO(alien4cloud.topology.TopologyDTO) WorkflowStep(org.alien4cloud.tosca.model.workflow.WorkflowStep) Workflow(org.alien4cloud.tosca.model.workflow.Workflow) When(cucumber.api.java.en.When)

Example 29 with WorkflowStep

use of org.alien4cloud.tosca.model.workflow.WorkflowStep in project alien4cloud by alien4cloud.

the class WorkflowStepDefinitions method the_workflow_step_has_no_followers.

@Then("^The workflow step \"(.*?)\" has no followers$")
public void the_workflow_step_has_no_followers(String stepId) throws Throwable {
    String topologyResponseText = Context.getInstance().getRestResponse();
    RestResponse<TopologyDTO> topologyResponse = JsonUtil.read(topologyResponseText, TopologyDTO.class, Context.getJsonMapper());
    String workflowName = Context.getInstance().getCurrentWorkflowName();
    Workflow workflow = topologyResponse.getData().getTopology().getWorkflows().get(workflowName);
    WorkflowStep step = workflow.getSteps().get(stepId);
    assertTrue(step.getOnSuccess() == null || step.getOnSuccess().isEmpty());
}
Also used : TopologyDTO(alien4cloud.topology.TopologyDTO) WorkflowStep(org.alien4cloud.tosca.model.workflow.WorkflowStep) Workflow(org.alien4cloud.tosca.model.workflow.Workflow) Then(cucumber.api.java.en.Then)

Example 30 with WorkflowStep

use of org.alien4cloud.tosca.model.workflow.WorkflowStep in project alien4cloud by alien4cloud.

the class WorkflowStepDefinitions method the_workflow_step_has_no_predecessors.

@Then("^The workflow step \"(.*?)\" has no predecessors$")
public void the_workflow_step_has_no_predecessors(String stepId) throws Throwable {
    String topologyResponseText = Context.getInstance().getRestResponse();
    RestResponse<TopologyDTO> topologyResponse = JsonUtil.read(topologyResponseText, TopologyDTO.class, Context.getJsonMapper());
    String workflowName = Context.getInstance().getCurrentWorkflowName();
    Workflow workflow = topologyResponse.getData().getTopology().getWorkflows().get(workflowName);
    WorkflowStep step = workflow.getSteps().get(stepId);
    assertTrue(step.getPrecedingSteps() == null || step.getPrecedingSteps().isEmpty());
}
Also used : TopologyDTO(alien4cloud.topology.TopologyDTO) WorkflowStep(org.alien4cloud.tosca.model.workflow.WorkflowStep) Workflow(org.alien4cloud.tosca.model.workflow.Workflow) Then(cucumber.api.java.en.Then)

Aggregations

WorkflowStep (org.alien4cloud.tosca.model.workflow.WorkflowStep)51 RelationshipWorkflowStep (org.alien4cloud.tosca.model.workflow.RelationshipWorkflowStep)24 NodeWorkflowStep (org.alien4cloud.tosca.model.workflow.NodeWorkflowStep)23 Workflow (org.alien4cloud.tosca.model.workflow.Workflow)20 Test (org.junit.Test)17 Path (alien4cloud.paas.wf.model.Path)7 Map (java.util.Map)6 ArrayList (java.util.ArrayList)5 Set (java.util.Set)5 NodeTemplate (org.alien4cloud.tosca.model.templates.NodeTemplate)5 InconsistentWorkflowException (alien4cloud.paas.wf.exception.InconsistentWorkflowException)4 TopologyDTO (alien4cloud.topology.TopologyDTO)4 AlienUtils.safe (alien4cloud.utils.AlienUtils.safe)4 List (java.util.List)4 Collectors (java.util.stream.Collectors)4 HashMap (java.util.HashMap)3 LinkedList (java.util.LinkedList)3 RelationshipTemplate (org.alien4cloud.tosca.model.templates.RelationshipTemplate)3 RelationshipType (org.alien4cloud.tosca.model.types.RelationshipType)3 StringUtils (org.apache.commons.lang3.StringUtils)3