package org.requirementsascode.flowposition;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

import org.requirementsascode.FlowStep;
import org.requirementsascode.Step;
import org.requirementsascode.ModelRunner;

public abstract class FlowPosition implements Predicate<ModelRunner>, Serializable {
	private static final long serialVersionUID = -8952890128132543927L;

	private List<FlowStep> orAfterSteps;
	private FlowStep step;

	protected abstract boolean isRunnerAtRightPositionFor(FlowStep step, ModelRunner modelRunner);

	public FlowPosition(FlowStep step) {
		this.step = step;
		this.orAfterSteps = new ArrayList<>();
	}

	@Override
	public final boolean test(ModelRunner modelRunner) {
		boolean isRunnerAtRightPositionForStepOrAfterAnyMergedStep = isRunnerAtRightPositionFor(step, modelRunner)
			|| afterAnyMergedStep(modelRunner);
		return isRunnerAtRightPositionForStepOrAfterAnyMergedStep;
	}

	private boolean afterAnyMergedStep(ModelRunner modelRunner) {
		return orAfterSteps.stream().anyMatch(step -> new After(step).test(modelRunner));
	}

	public final Step getStep() {
		return step;
	}

	public FlowPosition orAfter(FlowStep mergeStep) {
		orAfterSteps.add(mergeStep);
		return this;
	}
}

@@ -456,23 +456,21 @@
 owStep%3E 
-orAfter
+merge
 Steps;%0A%09
@@ -655,23 +655,21 @@
 %0A%09%09this.
-orAfter
+merge
 Steps = 
@@ -1038,54 +1038,85 @@
 %7B%0A%09%09
-return orAfterSteps.stream().anyMatch(step -%3E 
+boolean isAfterStep = false;%0A%09%09for (FlowStep mergeStep : mergeSteps) %7B%0A%09%09%09if(
 new 
@@ -1121,17 +1121,22 @@
 w After(
-s
+mergeS
 tep).tes
@@ -1150,16 +1150,83 @@
 Runner))
+ %7B%0A%09%09%09%09isAfterStep = true;%0A%09%09%09%09break;%0A%09%09%09%7D%0A%09%09%7D%0A%09%09return isAfterStep
 ;%0A%09%7D%0A%0A%09p
@@ -1326,23 +1326,21 @@
 ep) %7B%0A%09%09
-orAfter
+merge
 Steps.ad

Remove stream