package org.requirementsascode;

import java.io.Serializable;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * A step is a part of a use case. The steps define the behavior of the use
 * case.
 *
 * <p>
 * A step is the core class of requirementsascode, providing all the necessary
 * configuration information to the {@link ModelRunner} to cause the system to
 * react to messages.
 *
 * @author b_muth
 */
public abstract class Step extends ModelElement implements Serializable {
	private static final long serialVersionUID = -2926490717985964131L;

	private UseCase useCase;
	private Actor[] actors;
	private Condition condition;
	private Class<?> messageClass;
	private SystemReaction<?> systemReaction;
	private Actor publishTo;

	/**
	 * Creates a step with the specified name that belongs to the specified use
	 * case.
	 *
	 * @param useCase   the use case this step belongs to
	 * @param stepName  the name of the step to be created
	 * @param condition
	 */
	Step(String stepName, UseCase useCase, Condition condition) {
		super(stepName, useCase.getModel());
		this.useCase = useCase;
		this.condition = condition;
	}

	public abstract Predicate<ModelRunner> getPredicate();

	public UseCase getUseCase() {
		return useCase;
	}

	public Optional<Condition> getCondition() {
		return Optional.ofNullable(condition);
	}

	public Actor[] getActors() {
		return actors;
	}

	public void setActors(Actor[] actors) {
		this.actors = actors;
		connectActorsToThisStep(this, actors);
	}
	private void connectActorsToThisStep(Step useCaseStep, Actor[] actors) {
		for (Actor actor : actors) {
			actor.connectToStep(useCaseStep);
		}
	}

	public Class<?> getMessageClass() {
		return messageClass;
	}

	public void setMessageClass(Class<?> eventClass) {
		this.messageClass = eventClass;
	}

	public SystemReaction<?> getSystemReaction() {
		return systemReaction;
	}
	
	public void setSystemReaction(Runnable systemReaction) {
		this.systemReaction = new SystemReaction<>(systemReaction);
	}
	
	public <T> void setSystemReaction(Consumer<? super T> systemReaction) {
		this.systemReaction = new SystemReaction<>(systemReaction);
	}
	
	public <T> void setSystemReaction(Function<? super T, ?> systemReaction) {
		this.systemReaction = new SystemReaction<>(systemReaction);
	}

	public <T> void setSystemReaction(Supplier<? super T> systemReaction) {
		this.systemReaction = new SystemReaction<>(systemReaction);
	}

	protected static Predicate<ModelRunner> toPredicate(Condition condition) {
		return modelRunner -> condition.evaluate();
	}

	public Optional<Actor> getPublishTo() {
		return Optional.ofNullable(publishTo);
	}

	public void setPublishTo(Actor recipient) {
		this.publishTo = recipient;
	}
}

@@ -55,16 +55,73 @@
 izable;%0A
+import java.util.ArrayList;%0Aimport java.util.Collection;%0A
 import j
@@ -768,23 +768,33 @@
 private 
+Collection%3C
 Actor
-%5B%5D
+%3E
  actors;
@@ -1566,16 +1566,38 @@
 n actors
+.toArray(new Actor%5B0%5D)
 ;%0A%09%7D%0A%0A%09p
@@ -1639,32 +1639,8 @@
 ) %7B%0A
-%09%09this.actors = actors;%0A
 %09%09co
@@ -1679,16 +1679,18 @@
 rs);%0A%09%7D%0A
+%09%0A
 %09private
@@ -1761,71 +1761,309 @@
 %7B%0A%09%09
-for (Actor actor : actors) %7B%0A%09%09%09actor.connectToStep(useCaseStep
+this.actors = new ArrayList%3C%3E();%0A%09%09for (Actor actor : actors) %7B%0A%09%09%09String actorName = actor.getName();%0A%09%09%09Actor actorInModel = getModel().hasActor(actorName) ? getModel().findActor(actorName) : getModel().newActor(actorName);%0A%09%09%09actorInModel.connectToStep(useCaseStep);%0A%09%09%09this.actors.add(actorInModel
 );%0A%09

Update Step.java