diff --git a/.settings/edu.umd.cs.findbugs.core.prefs b/.settings/edu.umd.cs.findbugs.core.prefs
index 73ac78d870c97eac5872c26af03871bd22cd45fe..82e5b15f6c9bd732223febb51bce2165cfec7466 100644
--- a/.settings/edu.umd.cs.findbugs.core.prefs
+++ b/.settings/edu.umd.cs.findbugs.core.prefs
@@ -1,5 +1,5 @@
 #FindBugs User Preferences
-#Wed Jan 28 07:11:46 CET 2015
+#Mon Feb 02 14:42:51 CET 2015
 detector_threshold=3
 effort=max
 excludefilter0=.fbExcludeFilterFile|true
diff --git a/src/main/java/teetime/framework/CompositeStage.java b/src/main/java/teetime/framework/CompositeStage.java
new file mode 100644
index 0000000000000000000000000000000000000000..69653e3aabb594d7ca9c5683eae2bf598769ebcf
--- /dev/null
+++ b/src/main/java/teetime/framework/CompositeStage.java
@@ -0,0 +1,65 @@
+package teetime.framework;
+
+import java.util.Collection;
+import java.util.List;
+
+import teetime.framework.signal.ISignal;
+import teetime.framework.validation.InvalidPortConnection;
+
+public abstract class CompositeStage extends Stage {
+
+	private final Stage firstStage;
+	private final Collection<Stage> lastStages;
+
+	protected CompositeStage(final Stage firstStage, final Collection<Stage> lastStages) {
+		this.firstStage = firstStage;
+		this.lastStages = lastStages;
+	}
+
+	@Override
+	protected void executeWithPorts() {
+		firstStage.executeWithPorts();
+	}
+
+	@Override
+	protected void onSignal(final ISignal signal, final InputPort<?> inputPort) {
+		firstStage.onSignal(signal, inputPort);
+	}
+
+	@Override
+	protected TerminationStrategy getTerminationStrategy() {
+		return firstStage.getTerminationStrategy();
+	}
+
+	@Override
+	protected void terminate() {
+		firstStage.terminate();
+	}
+
+	@Override
+	protected boolean shouldBeTerminated() {
+		return firstStage.shouldBeTerminated();
+	}
+
+	@Override
+	protected InputPort<?>[] getInputPorts() {
+		return firstStage.getInputPorts();
+	}
+
+	@Override
+	public void validateOutputPorts(final List<InvalidPortConnection> invalidPortConnections) {
+		for (final Stage s : lastStages) {
+			s.validateOutputPorts(invalidPortConnections);
+		}
+	}
+
+	@Override
+	protected boolean isStarted() {
+		boolean isStarted = true;
+		for (final Stage s : lastStages) {
+			isStarted = isStarted && s.isStarted();
+		}
+		return isStarted;
+	}
+
+}
diff --git a/src/site/markdown/wiki b/src/site/markdown/wiki
index a93581905ef7b0584d52eae1898148ffa6201a31..0e4474577e1f49bc96e734c286b2d9e0363895e8 160000
--- a/src/site/markdown/wiki
+++ b/src/site/markdown/wiki
@@ -1 +1 @@
-Subproject commit a93581905ef7b0584d52eae1898148ffa6201a31
+Subproject commit 0e4474577e1f49bc96e734c286b2d9e0363895e8