diff --git a/self-core-impl/src/main/java/com/selfxdsd/core/managers/StepComposer.java b/self-core-impl/src/main/java/com/selfxdsd/core/managers/StepComposer.java
new file mode 100644
index 00000000..5b28b3c8
--- /dev/null
+++ b/self-core-impl/src/main/java/com/selfxdsd/core/managers/StepComposer.java
@@ -0,0 +1,141 @@
+package com.selfxdsd.core.managers;
+
+import com.selfxdsd.api.pm.Step;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+/**
+ * Helper class that allows chaining {@link com.selfxdsd.api.pm.Intermediary}
+ * steps.
+ *
+ * It also provides composition support for
+ * {@link com.selfxdsd.api.pm.PreconditionCheck}.
+ * @author criske
+ * @version $Id$
+ * @since 0.0.20
+ */
+public final class StepComposer {
+
+ /**
+ * Call stack of step functions. Usually this functions produce
+ * {@link com.selfxdsd.api.pm.Intermediary} steps.
+ */
+ private final Deque> callStack = new ArrayDeque<>();
+
+ /**
+ * Next Step in chain.
+ * @param stepFunction Step Function.
+ * @return Step, usually an Intermediary.
+ */
+ public StepComposer next(final Function stepFunction) {
+ callStack.push(stepFunction);
+ return this;
+ }
+
+ /**
+ * Stars a ConditionComposer.
+ * @param when BiFunction providing onTrue, onFalse. Returning should be a
+ * {@link com.selfxdsd.api.pm.PreconditionCheck}.
+ * @return ConditionComposer.
+ */
+ public ConditionComposer when(final BiFunction when) {
+ if(!callStack.isEmpty()){
+ throw new IllegalStateException("Condition composition can't be "
+ + " called after an next() call!");
+ }
+ return new ConditionComposer(when);
+ }
+
+ /**
+ * Finishes the chain into one step.
+ * @param lastStep Last Step.
+ * @return Composed Step.
+ */
+ public Step finish(final Step lastStep) {
+ Step composedStep = lastStep;
+ while (!callStack.isEmpty()) {
+ composedStep = callStack.pop().apply(composedStep);
+ }
+ return composedStep;
+ }
+
+ /**
+ * Finishes the chain into one step.
+ * @return Composed Step.
+ */
+ public Step finish(){
+ return finish(lastly -> {});
+ }
+
+
+ /**
+ * StepComposer for a PreconditionCheck.
+ */
+ public static final class ConditionComposer {
+
+ /**
+ * BiFunction providing onTrue, onFalse steps. Returning should be a
+ * PreconditionCheck.
+ */
+ private final BiFunction when;
+
+ /**
+ * OnTrue Step supplier.
+ */
+ private Supplier onTrue;
+
+ /**
+ * OnFalse Step supplier.
+ */
+ private Supplier onFalse;
+
+ /**
+ * Private constructor.
+ * @param when BiFunction providing onTrue, onFalse. Returning
+ * should be a PreconditionCheck.
+ */
+ private ConditionComposer(final BiFunction when) {
+ this.when = when;
+ }
+
+ /**
+ * OnTrue setter.
+ * @param onTrue OnTrue Step supplier.
+ * @return This ConditionComposer.
+ */
+ public ConditionComposer onTrue(final Supplier onTrue){
+ this.onTrue = onTrue;
+ return this;
+ }
+
+ /**
+ * OnFalse setter.
+ * @param onFalse OnFalse Step supplier.
+ * @return This ConditionComposer.
+ */
+ public ConditionComposer onFalse(final Supplier onFalse){
+ this.onFalse = onFalse;
+ return this;
+ }
+
+ /**
+ * Finishes the composition into a composed Step provided by `when`.
+ * @return Step.
+ */
+ public Step finish(){
+ if (onFalse == null) {
+ onFalse = () -> e -> { };
+ }
+ if (onTrue == null) {
+ onTrue = () -> e -> { };
+ }
+ return when.apply(onTrue.get(), onFalse.get());
+ }
+ }
+
+}
+
diff --git a/self-core-impl/src/test/java/com/selfxdsd/core/managers/StepComposerTestCase.java b/self-core-impl/src/test/java/com/selfxdsd/core/managers/StepComposerTestCase.java
new file mode 100644
index 00000000..6fa60052
--- /dev/null
+++ b/self-core-impl/src/test/java/com/selfxdsd/core/managers/StepComposerTestCase.java
@@ -0,0 +1,107 @@
+package com.selfxdsd.core.managers;
+
+import com.selfxdsd.api.Event;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Unit tests for {@link StepComposer}.
+ * @author criske
+ * @version $Id$
+ * @since 0.0.20
+ */
+public final class StepComposerTestCase {
+
+ /**
+ * Executes the steps in order of chaining.
+ */
+ @Test
+ public void executesStepsInOrder() {
+ final StringBuilder builder = new StringBuilder();
+ final AtomicInteger counter = new AtomicInteger();
+ new StepComposer()
+ .next(s -> e -> {
+ builder.append(counter.incrementAndGet());
+ s.perform(e);
+ })
+ .next(s -> e -> {
+ builder.append(counter.incrementAndGet());
+ s.perform(e);
+ })
+ .next(s -> e -> {
+ builder.append(counter.incrementAndGet());
+ s.perform(e);
+ })
+ .next(s -> e -> {
+ builder.append(counter.incrementAndGet());
+ s.perform(e);
+ })
+ .finish(lastly -> builder.append(counter.incrementAndGet()))
+ .perform(Mockito.mock(Event.class));
+ final String order = builder.toString();
+ MatcherAssert.assertThat(order, Matchers.equalTo("12345"));
+ }
+
+ /**
+ * Can perform conditional composition on true branch.
+ */
+ @Test
+ public void shouldTakeTrueConditionBranch(){
+ final StringBuilder builder = new StringBuilder();
+ final AtomicInteger counter = new AtomicInteger();
+ new StepComposer()
+ .when((tru, fls) -> e -> {
+ builder.append("true");
+ tru.perform(e);
+ })
+ .onTrue(() -> new StepComposer()
+ .next(s -> e -> {
+ builder.append(counter.incrementAndGet());
+ s.perform(e);
+ })
+ .next(s -> e -> {
+ builder.append(counter.incrementAndGet());
+ s.perform(e);
+ })
+ .finish())
+ .finish()
+ .perform(Mockito.mock(Event.class));
+
+ final String order = builder.toString();
+ MatcherAssert.assertThat(order, Matchers.equalTo("true12"));
+ }
+
+ /**
+ * Can perform conditional composition on false branch.
+ */
+ @Test
+ public void shouldTakeFalseConditionBranch(){
+ final StringBuilder builder = new StringBuilder();
+ final AtomicInteger counter = new AtomicInteger();
+ new StepComposer()
+ .when((tru, fls) -> e -> {
+ builder.append("false");
+ fls.perform(e);
+ })
+ .onFalse(() -> new StepComposer()
+ .next(s -> e -> {
+ builder.append(counter.incrementAndGet());
+ s.perform(e);
+ })
+ .next(s -> e -> {
+ builder.append(counter.incrementAndGet());
+ s.perform(e);
+ })
+ .finish())
+ .finish()
+ .perform(Mockito.mock(Event.class));
+
+ final String order = builder.toString();
+ MatcherAssert.assertThat(order, Matchers.equalTo("false12"));
+ }
+
+}