package org.requirementsascode;

import java.io.Serializable;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Stream;

/**
 * @author b_muth
 */
public class InterruptableFlowStep extends FlowStep implements Serializable {
    private static final long serialVersionUID = -2926490717985964131L;

    /**
     * Creates a use case step with the specified name as the last step of the
     * specified use case flow.
     *
     * @param stepName
     *            the name of the step to be created
     * @param useCaseFlow
     *            the use case flow that will contain the new use case
     */
    InterruptableFlowStep(String stepName, UseCase useCase, Flow useCaseFlow) {
	super(stepName, useCase, useCaseFlow);
	appendToLastStepOfFlow();
    }

    private void appendToLastStepOfFlow() {
	List<FlowStep> flowSteps = getFlow().getSteps();
	FlowStep lastFlowStep = flowSteps.size() > 0 ? flowSteps.get(flowSteps.size() - 1) : null;
	setPreviousStepInFlow(lastFlowStep);
    }

    @Override
    public Predicate<UseCaseModelRunner> getPredicate() {
	Predicate<UseCaseModelRunner> predicate;
	Predicate<UseCaseModelRunner> reactWhile = getReactWhile();

	if (reactWhile != null) {
	    predicate = reactWhile;
	} else {
	    predicate = getFlowPosition().get().and(noStepInterrupts());
	}

	return predicate;
    }

    private Predicate<UseCaseModelRunner> noStepInterrupts() {
	return useCaseModelRunner -> {
	    Class<?> theStepsEventClass = getUserEventClass();
	    UseCaseModel useCaseModel = getUseCaseModel();

	    Stream<Step> stepsStream = useCaseModel.getModifiableSteps().stream();
	    Stream<Step> conditionalStepsStream = stepsStream
		    .filter(isInterruptingStep().and(isOtherStepThan(this)));

	    Set<Step> conditionalStepsThatCanReact = useCaseModelRunner
		    .stepsInStreamThatCanReactTo(theStepsEventClass, conditionalStepsStream);
	    return conditionalStepsThatCanReact.size() == 0;
	};
    }

    private Predicate<Step> isInterruptingStep() {
	return step -> InterruptingFlowStep.class.equals(step.getClass());
    }

    private Predicate<Step> isOtherStepThan(FlowStep theStep) {
	return step -> !step.equals(theStep);
    }
}

@@ -170,16 +170,118 @@
 tream;%0A%0A
+import org.requirementsascode.predicate.After;%0Aimport org.requirementsascode.predicate.FlowPosition;%0A%0A
 /**%0A * @
@@ -1130,24 +1130,67 @@
 tFlowStep);%0A
+%09setFlowPosition(new After(lastFlowStep));%0A
     %7D%0A%0A    @
@@ -1435,43 +1435,84 @@
     
-predicate = getFlowPosition().get()
+FlowPosition flowPosition = getFlowPosition();%0A%09    predicate = flowPosition
 .and

Fix flow position issues