package org.requirementsascode;

import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * Part used by the {@link ModelBuilder} to build a {@link Model}. Wraps
 * {@link StepPart}.
 * 
 * @author b_muth
 */
public class FlowlessConditionPart {
	private Condition optionalCondition;
	private long flowlessStepCounter;
	private StepPart stepPart;

	FlowlessConditionPart(Condition optionalCondition, UseCasePart useCasePart, long flowlessStepCounter) {
		this.optionalCondition = optionalCondition;
		final String stepName = "S" + flowlessStepCounter;
		step(useCasePart, optionalCondition, stepName);
		this.flowlessStepCounter = flowlessStepCounter;
	}

	private void step(UseCasePart useCasePart, Condition optionalCondition, final String stepName) {
		UseCase useCase = useCasePart.getUseCase();
		FlowlessStep newStep = useCase.newFlowlessStep(optionalCondition, stepName);
		this.stepPart = new StepPart(newStep, useCasePart, null);
	}

	/**
	 * Defines the type of user commands that this step accepts. Commands of this
	 * type can cause a system reaction.
	 *
	 * <p>
	 * Given that the step's condition is true, the system reacts to objects that
	 * are instances of the specified class or instances of any direct or indirect
	 * subclass of the specified class.
	 *
	 * @param commandClass the class of commands the system reacts to in this step
	 * @param <T>          the type of the class
	 * @return the created user part of this step
	 */
	public <T> FlowlessUserPart<T> user(Class<T> commandClass) {
		StepUserPart<T> stepUserPart = stepPart.user(commandClass);
		FlowlessUserPart<T> flowlessUserPart = new FlowlessUserPart<>(stepUserPart, flowlessStepCounter);
		return flowlessUserPart;
	}

	/**
	 * Defines the type of messages or exceptions that will cause a system reaction,
	 * given that the condition is fulfilled.
	 *
	 * <p>
	 * Given that the step's condition is true, the system reacts to objects that
	 * are instances of the specified class or instances of any direct or indirect
	 * subclass of the specified class.
	 *
	 * @param messageClass the class of messages the system reacts to
	 * @param <T>          the type of the class
	 * @return the created user part of this step
	 */
	public <T> FlowlessUserPart<T> on(Class<T> messageClass) {
		StepUserPart<T> stepUserPart = stepPart.on(messageClass);
		FlowlessUserPart<T> flowlessUserPart = new FlowlessUserPart<>(stepUserPart, flowlessStepCounter);
		return flowlessUserPart;
	}

	/**
	 * Defines an "autonomous system reaction", meaning the system will react
	 * without needing a message provided via {@link ModelRunner#reactTo(Object)}.
	 *
	 * @param systemReaction the autonomous system reaction
	 * @return the created system part of this step
	 */
	public FlowlessSystemPart<ModelRunner> system(Runnable systemReaction) {
		StepSystemPart<ModelRunner> stepSystemPart = stepPart.system(systemReaction);
		FlowlessSystemPart<ModelRunner> flowlessSystemPart = new FlowlessSystemPart<>(stepSystemPart,
				flowlessStepCounter);
		return flowlessSystemPart;
	}

	/**
	 * Defines an "autonomous system reaction", meaning the system will react
	 * without needing a message provided via {@link ModelRunner#reactTo(Object)}.
	 * Instead, the model runner provides itself as an event to the system reaction.
	 *
	 * @param systemReaction the autonomous system reaction (that needs information
	 *                       from a model runner to work)
	 * @return the created system part of this step
	 */
	public FlowlessSystemPart<ModelRunner> system(Consumer<ModelRunner> systemReaction) {
		StepSystemPart<ModelRunner> stepSystemPart = stepPart.system(systemReaction);
		FlowlessSystemPart<ModelRunner> flowlessSystemPart = new FlowlessSystemPart<>(stepSystemPart,
				flowlessStepCounter);
		return flowlessSystemPart;
	}

	/**
	 * Defines an "autonomous system reaction", meaning the system will react
	 * without needing a message provided via {@link ModelRunner#reactTo(Object)}.
	 * After executing the system reaction, the runner will publish the returned
	 * event.
	 *
	 * @param systemReaction the autonomous system reaction, that returns a single
	 *                       event to be published.
	 * @return the created system part of this step
	 */
	public FlowlessSystemPart<ModelRunner> systemPublish(Supplier<?> systemReaction) {
		StepSystemPart<ModelRunner> stepSystemPart = stepPart.systemPublish(systemReaction);
		FlowlessSystemPart<ModelRunner> flowlessSystemPart = new FlowlessSystemPart<>(stepSystemPart,
				flowlessStepCounter);
		return flowlessSystemPart;
	}
	
	Condition getOptionalCondition() {
		return optionalCondition;
	}
}

@@ -260,16 +260,50 @@
 nPart %7B%0A
+%09private UseCasePart useCasePart;%0A
 %09private
@@ -547,16 +547,50 @@
 dition;%0A
+%09%09this.useCasePart = useCasePart;%0A
 %09%09final 
@@ -645,40 +645,8 @@
 tep(
-useCasePart, optionalCondition, 
 step
@@ -729,62 +729,8 @@
 tep(
-UseCasePart useCasePart, Condition optionalCondition, 
 fina

Refactor step method