From 88a744e70e0cedbb744101ddd8140f5f2b98839b Mon Sep 17 00:00:00 2001
From: Nils Christian Ehmke <nie@informatik.uni-kiel.de>
Date: Wed, 17 Dec 2014 15:28:35 +0100
Subject: [PATCH] Added views for failed and failure containing aggregated
 traces

---
 build.gradle                                  |  2 +
 ...gregatedFailedTracesSubViewController.java | 59 +++++++++++++++++++
 .../AggregatedTracesSubViewController.java    |  4 +-
 .../FailedTracesSubViewController.java        |  2 +-
 ...ningAggregatedTracesSubViewController.java | 59 +++++++++++++++++++
 ...lureContainingTracesSubViewController.java |  2 +-
 .../gui/controller/MainViewController.java    | 12 +++-
 .../controller/TracesSubViewController.java   |  2 +-
 src/main/java/kieker/gui/model/DataModel.java | 12 ++++
 .../java/kieker/gui/model/MainViewModel.java  |  2 +-
 .../gui/model/domain/AggregatedExecution.java |  9 ++-
 .../java/kieker/gui/model/domain/Record.java  |  2 +-
 .../importer/ImportAnalysisConfiguration.java | 25 +++++++-
 .../stages/FailedAggregatedTraceFilter.java   | 38 ++++++++++++
 ...ailureContainingAggregatedTraceFilter.java | 38 ++++++++++++
 .../gui/view/AggregatedTracesSubView.java     | 46 ++++++++++++---
 src/main/java/kieker/gui/view/MainView.java   | 32 +++++++++-
 ...gatedExecutionTotalDurationComparator.java | 19 ++++++
 18 files changed, 345 insertions(+), 20 deletions(-)
 create mode 100644 src/main/java/kieker/gui/controller/AggregatedFailedTracesSubViewController.java
 create mode 100644 src/main/java/kieker/gui/controller/FailureContainingAggregatedTracesSubViewController.java
 create mode 100644 src/main/java/kieker/gui/model/importer/stages/FailedAggregatedTraceFilter.java
 create mode 100644 src/main/java/kieker/gui/model/importer/stages/FailureContainingAggregatedTraceFilter.java
 create mode 100644 src/main/java/kieker/gui/view/util/AggregatedExecutionTotalDurationComparator.java

diff --git a/build.gradle b/build.gradle
index 762d7fe2..d869d805 100644
--- a/build.gradle
+++ b/build.gradle
@@ -37,6 +37,8 @@ dependencies {
 	compile 'org.eclipse:jface:3.2.1-M20060908-1000'
   
 	testCompile 'org.hamcrest:hamcrest-core:1.3'
+	testCompile 'org.hamcrest:hamcrest-library:1.3'
+	testCompile 'junit:junit:4.12'
 }
 
 // Add the provided-scoped dependencies to the classpaths
diff --git a/src/main/java/kieker/gui/controller/AggregatedFailedTracesSubViewController.java b/src/main/java/kieker/gui/controller/AggregatedFailedTracesSubViewController.java
new file mode 100644
index 00000000..7305d60e
--- /dev/null
+++ b/src/main/java/kieker/gui/controller/AggregatedFailedTracesSubViewController.java
@@ -0,0 +1,59 @@
+/***************************************************************************
+ * Copyright 2014 Kieker Project (http://kieker-monitoring.net)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+
+package kieker.gui.controller;
+
+import kieker.gui.model.AggregatedTracesSubViewModel;
+import kieker.gui.model.DataModel;
+import kieker.gui.model.PropertiesModel;
+import kieker.gui.model.domain.AggregatedExecution;
+import kieker.gui.view.AggregatedTracesSubView;
+import kieker.gui.view.ISubView;
+
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+
+/**
+ * The sub-controller responsible for the sub-view presenting the available aggregated traces.
+ *
+ * @author Nils Christian Ehmke
+ */
+public final class AggregatedFailedTracesSubViewController implements SelectionListener, ISubController {
+
+	private final ISubView view;
+	private final AggregatedTracesSubViewModel model;
+
+	public AggregatedFailedTracesSubViewController(final DataModel dataModel, final PropertiesModel propertiesModel) {
+		this.model = new AggregatedTracesSubViewModel();
+		this.view = new AggregatedTracesSubView(AggregatedTracesSubView.Type.SHOW_JUST_FAILED_TRACES, dataModel, this.model, propertiesModel, this);
+	}
+
+	@Override
+	public ISubView getView() {
+		return this.view;
+	}
+
+	@Override
+	public void widgetSelected(final SelectionEvent e) {
+		if (e.item.getData() instanceof AggregatedExecution) {
+			this.model.setCurrentActiveTrace((AggregatedExecution) e.item.getData());
+		}
+	}
+
+	@Override
+	public void widgetDefaultSelected(final SelectionEvent e) {}
+
+}
diff --git a/src/main/java/kieker/gui/controller/AggregatedTracesSubViewController.java b/src/main/java/kieker/gui/controller/AggregatedTracesSubViewController.java
index aab97549..a6addc51 100644
--- a/src/main/java/kieker/gui/controller/AggregatedTracesSubViewController.java
+++ b/src/main/java/kieker/gui/controller/AggregatedTracesSubViewController.java
@@ -31,14 +31,14 @@ import org.eclipse.swt.events.SelectionListener;
  *
  * @author Nils Christian Ehmke
  */
-public class AggregatedTracesSubViewController implements SelectionListener, ISubController {
+public final class AggregatedTracesSubViewController implements SelectionListener, ISubController {
 
 	private final ISubView view;
 	private final AggregatedTracesSubViewModel model;
 
 	public AggregatedTracesSubViewController(final DataModel dataModel, final PropertiesModel propertiesModel) {
 		this.model = new AggregatedTracesSubViewModel();
-		this.view = new AggregatedTracesSubView(dataModel, this.model, propertiesModel, this);
+		this.view = new AggregatedTracesSubView(AggregatedTracesSubView.Type.SHOW_ALL_TRACES, dataModel, this.model, propertiesModel, this);
 	}
 
 	@Override
diff --git a/src/main/java/kieker/gui/controller/FailedTracesSubViewController.java b/src/main/java/kieker/gui/controller/FailedTracesSubViewController.java
index 3eaa735e..6593bb65 100644
--- a/src/main/java/kieker/gui/controller/FailedTracesSubViewController.java
+++ b/src/main/java/kieker/gui/controller/FailedTracesSubViewController.java
@@ -31,7 +31,7 @@ import org.eclipse.swt.events.SelectionListener;
  *
  * @author Nils Christian Ehmke
  */
-public class FailedTracesSubViewController implements SelectionListener, ISubController {
+public final class FailedTracesSubViewController implements SelectionListener, ISubController {
 
 	private final TracesSubViewModel model;
 	private final ISubView view;
diff --git a/src/main/java/kieker/gui/controller/FailureContainingAggregatedTracesSubViewController.java b/src/main/java/kieker/gui/controller/FailureContainingAggregatedTracesSubViewController.java
new file mode 100644
index 00000000..c46401d3
--- /dev/null
+++ b/src/main/java/kieker/gui/controller/FailureContainingAggregatedTracesSubViewController.java
@@ -0,0 +1,59 @@
+/***************************************************************************
+ * Copyright 2014 Kieker Project (http://kieker-monitoring.net)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+
+package kieker.gui.controller;
+
+import kieker.gui.model.AggregatedTracesSubViewModel;
+import kieker.gui.model.DataModel;
+import kieker.gui.model.PropertiesModel;
+import kieker.gui.model.domain.AggregatedExecution;
+import kieker.gui.view.AggregatedTracesSubView;
+import kieker.gui.view.ISubView;
+
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+
+/**
+ * The sub-controller responsible for the sub-view presenting the available aggregated traces.
+ *
+ * @author Nils Christian Ehmke
+ */
+public final class FailureContainingAggregatedTracesSubViewController implements SelectionListener, ISubController {
+
+	private final ISubView view;
+	private final AggregatedTracesSubViewModel model;
+
+	public FailureContainingAggregatedTracesSubViewController(final DataModel dataModel, final PropertiesModel propertiesModel) {
+		this.model = new AggregatedTracesSubViewModel();
+		this.view = new AggregatedTracesSubView(AggregatedTracesSubView.Type.SHOW_JUST_FAILURE_CONTAINING_TRACES, dataModel, this.model, propertiesModel, this);
+	}
+
+	@Override
+	public ISubView getView() {
+		return this.view;
+	}
+
+	@Override
+	public void widgetSelected(final SelectionEvent e) {
+		if (e.item.getData() instanceof AggregatedExecution) {
+			this.model.setCurrentActiveTrace((AggregatedExecution) e.item.getData());
+		}
+	}
+
+	@Override
+	public void widgetDefaultSelected(final SelectionEvent e) {}
+
+}
diff --git a/src/main/java/kieker/gui/controller/FailureContainingTracesSubViewController.java b/src/main/java/kieker/gui/controller/FailureContainingTracesSubViewController.java
index 99bceb8d..ef4e4272 100644
--- a/src/main/java/kieker/gui/controller/FailureContainingTracesSubViewController.java
+++ b/src/main/java/kieker/gui/controller/FailureContainingTracesSubViewController.java
@@ -31,7 +31,7 @@ import org.eclipse.swt.events.SelectionListener;
  *
  * @author Nils Christian Ehmke
  */
-public class FailureContainingTracesSubViewController implements SelectionListener, ISubController {
+public final class FailureContainingTracesSubViewController implements SelectionListener, ISubController {
 
 	private final TracesSubViewModel model;
 	private final ISubView view;
diff --git a/src/main/java/kieker/gui/controller/MainViewController.java b/src/main/java/kieker/gui/controller/MainViewController.java
index 4cddd711..84440f3b 100644
--- a/src/main/java/kieker/gui/controller/MainViewController.java
+++ b/src/main/java/kieker/gui/controller/MainViewController.java
@@ -50,6 +50,8 @@ public final class MainViewController implements SelectionListener {
 		final ISubController subViewController3 = new FailedTracesSubViewController(this.dataModel, this.propertiesModel);
 		final ISubController subViewController4 = new AggregatedTracesSubViewController(this.dataModel, this.propertiesModel);
 		final ISubController subViewController5 = new FailureContainingTracesSubViewController(this.dataModel, this.propertiesModel);
+		final ISubController subViewController6 = new AggregatedFailedTracesSubViewController(this.dataModel, this.propertiesModel);
+		final ISubController subViewController7 = new FailureContainingAggregatedTracesSubViewController(this.dataModel, this.propertiesModel);
 
 		// Get the sub-views from the controllers
 		final ISubView subView1 = subViewController1.getView();
@@ -57,10 +59,12 @@ public final class MainViewController implements SelectionListener {
 		final ISubView subView3 = subViewController3.getView();
 		final ISubView subView4 = subViewController4.getView();
 		final ISubView subView5 = subViewController5.getView();
+		final ISubView subView6 = subViewController6.getView();
+		final ISubView subView7 = subViewController7.getView();
 
 		// Create the main model and the main view
 		this.mainViewModel = new MainViewModel();
-		this.mainView = new MainView(this.dataModel, this.mainViewModel, this, subView1, subView2, subView3, subView4, subView5);
+		this.mainView = new MainView(this.dataModel, this.mainViewModel, this, subView1, subView2, subView3, subView4, subView5, subView6, subView7);
 	}
 
 	public void showView() {
@@ -122,6 +126,12 @@ public final class MainViewController implements SelectionListener {
 		if (e.item == this.mainView.getTrtmJustTracesContaining()) {
 			this.mainViewModel.setCurrentActiveSubView(SubView.FAILURE_CONTAINING_TRACES_SUB_VIEW);
 		}
+		if (e.item == this.mainView.getTrtmJustFailedAggTraces()) {
+			this.mainViewModel.setCurrentActiveSubView(SubView.FAILED_AGGREGATED_TRACES_SUB_VIEW);
+		}
+		if (e.item == this.mainView.getTrtmJustAggTracesContaining()) {
+			this.mainViewModel.setCurrentActiveSubView(SubView.FAILURE_CONTAINING_AGGREGATED_TRACES_SUB_VIEW);
+		}
 	}
 
 	@Override
diff --git a/src/main/java/kieker/gui/controller/TracesSubViewController.java b/src/main/java/kieker/gui/controller/TracesSubViewController.java
index b2cf09d4..a1e50579 100644
--- a/src/main/java/kieker/gui/controller/TracesSubViewController.java
+++ b/src/main/java/kieker/gui/controller/TracesSubViewController.java
@@ -31,7 +31,7 @@ import org.eclipse.swt.events.SelectionListener;
  *
  * @author Nils Christian Ehmke
  */
-public class TracesSubViewController implements SelectionListener, ISubController {
+public final class TracesSubViewController implements SelectionListener, ISubController {
 
 	private final TracesSubViewModel model;
 	private final ISubView view;
diff --git a/src/main/java/kieker/gui/model/DataModel.java b/src/main/java/kieker/gui/model/DataModel.java
index 76f49a36..252caaf0 100644
--- a/src/main/java/kieker/gui/model/DataModel.java
+++ b/src/main/java/kieker/gui/model/DataModel.java
@@ -42,6 +42,8 @@ public final class DataModel extends Observable {
 	private List<Execution> failureContainingTraces = Collections.emptyList();
 	private List<Execution> failedTraces = Collections.emptyList();
 	private List<AggregatedExecution> aggregatedTraces = Collections.emptyList();
+	private List<AggregatedExecution> failedAggregatedTraces = Collections.emptyList();
+	private List<AggregatedExecution> failureAggregatedContainingTraces = Collections.emptyList();
 	private String shortTimeUnit = "";
 
 	public DataModel() {}
@@ -60,6 +62,8 @@ public final class DataModel extends Observable {
 		this.failedTraces = analysisConfiguration.getFailedTracesList();
 		this.failureContainingTraces = analysisConfiguration.getFailureContainingTracesList();
 		this.aggregatedTraces = analysisConfiguration.getAggregatedTraces();
+		this.failedAggregatedTraces = analysisConfiguration.getFailedAggregatedTracesList();
+		this.failureAggregatedContainingTraces = analysisConfiguration.getFailureContainingAggregatedTracesList();
 
 		final List<KiekerMetadataRecord> metadataRecords = analysisConfiguration.getMetadataRecords();
 		if (metadataRecords.size() == 1) {
@@ -130,4 +134,12 @@ public final class DataModel extends Observable {
 		return this.shortTimeUnit;
 	}
 
+	public List<AggregatedExecution> getFailedAggregatedTracesCopy() {
+		return new ArrayList<>(this.failedAggregatedTraces);
+	}
+
+	public List<AggregatedExecution> getFailureContainingAggregatedTracesCopy() {
+		return new ArrayList<>(this.failureAggregatedContainingTraces);
+	}
+
 }
diff --git a/src/main/java/kieker/gui/model/MainViewModel.java b/src/main/java/kieker/gui/model/MainViewModel.java
index 12ddc393..68158107 100644
--- a/src/main/java/kieker/gui/model/MainViewModel.java
+++ b/src/main/java/kieker/gui/model/MainViewModel.java
@@ -34,7 +34,7 @@ public final class MainViewModel extends Observable {
 	}
 
 	public enum SubView {
-		RECORDS_SUB_VIEW, TRACES_SUB_VIEW, FAILED_TRACES_SUB_VIEW, AGGREGATED_TRACES_SUB_VIEW, NONE, FAILURE_CONTAINING_TRACES_SUB_VIEW
+		RECORDS_SUB_VIEW, TRACES_SUB_VIEW, FAILED_TRACES_SUB_VIEW, AGGREGATED_TRACES_SUB_VIEW, NONE, FAILURE_CONTAINING_TRACES_SUB_VIEW, FAILED_AGGREGATED_TRACES_SUB_VIEW, FAILURE_CONTAINING_AGGREGATED_TRACES_SUB_VIEW
 	}
 
 }
diff --git a/src/main/java/kieker/gui/model/domain/AggregatedExecution.java b/src/main/java/kieker/gui/model/domain/AggregatedExecution.java
index 4e61b0e2..cfd6a89e 100644
--- a/src/main/java/kieker/gui/model/domain/AggregatedExecution.java
+++ b/src/main/java/kieker/gui/model/domain/AggregatedExecution.java
@@ -21,6 +21,7 @@ public final class AggregatedExecution extends AbstractExecution<AggregatedExecu
 	private long minDuration;
 	private long maxDuration;
 	private long avgDuration;
+	private long totalDuration;
 	private int calls;
 
 	public AggregatedExecution(final Execution execEntry) {
@@ -39,11 +40,11 @@ public final class AggregatedExecution extends AbstractExecution<AggregatedExecu
 		this.calls++;
 		this.minDuration = Math.min(this.minDuration, executionEntry.getDuration());
 		this.maxDuration = Math.max(this.maxDuration, executionEntry.getDuration());
-		this.avgDuration += executionEntry.getDuration();
+		this.totalDuration += executionEntry.getDuration();
 	}
 
 	public void recalculateValues() {
-		this.avgDuration /= this.calls;
+		this.avgDuration = this.totalDuration / this.calls;
 	}
 
 	public long getMinDuration() {
@@ -58,6 +59,10 @@ public final class AggregatedExecution extends AbstractExecution<AggregatedExecu
 		return this.avgDuration;
 	}
 
+	public long getTotalDuration() {
+		return this.totalDuration;
+	}
+
 	public int getCalls() {
 		return this.calls;
 	}
diff --git a/src/main/java/kieker/gui/model/domain/Record.java b/src/main/java/kieker/gui/model/domain/Record.java
index 4e8e349a..673e4a0d 100644
--- a/src/main/java/kieker/gui/model/domain/Record.java
+++ b/src/main/java/kieker/gui/model/domain/Record.java
@@ -26,7 +26,7 @@ public final class Record {
 	private final long timestamp;
 	private final String type;
 	private final String representation;
- 
+
 	public Record(final long timestamp, final String type, final String representation) {
 		this.timestamp = timestamp;
 		this.type = type;
diff --git a/src/main/java/kieker/gui/model/importer/ImportAnalysisConfiguration.java b/src/main/java/kieker/gui/model/importer/ImportAnalysisConfiguration.java
index 9e33e663..61bf4fdf 100644
--- a/src/main/java/kieker/gui/model/importer/ImportAnalysisConfiguration.java
+++ b/src/main/java/kieker/gui/model/importer/ImportAnalysisConfiguration.java
@@ -26,7 +26,9 @@ import kieker.common.record.misc.KiekerMetadataRecord;
 import kieker.gui.model.domain.AggregatedExecution;
 import kieker.gui.model.domain.Execution;
 import kieker.gui.model.domain.Record;
+import kieker.gui.model.importer.stages.FailedAggregatedTraceFilter;
 import kieker.gui.model.importer.stages.FailedTraceFilter;
+import kieker.gui.model.importer.stages.FailureContainingAggregatedTraceFilter;
 import kieker.gui.model.importer.stages.FailureContainingTraceFilter;
 import kieker.gui.model.importer.stages.RecordSimplificator;
 import kieker.gui.model.importer.stages.TraceAggregator;
@@ -55,6 +57,8 @@ public final class ImportAnalysisConfiguration extends AnalysisConfiguration {
 	private final List<Execution> failureContainingTracesList = new Vector<>(1000);
 	private final List<Execution> tracesList = new Vector<>(1000);
 	private final List<AggregatedExecution> aggregatedTraces = new Vector<>(1000);
+	private final List<AggregatedExecution> failedAggregatedTracesList = new Vector<>(1000);
+	private final List<AggregatedExecution> failureContainingAggregatedTracesList = new Vector<>(1000);
 	private final List<KiekerMetadataRecord> metadataRecords = new Vector<>(1000);
 
 	public ImportAnalysisConfiguration(final File importDirectory) {
@@ -75,10 +79,16 @@ public final class ImportAnalysisConfiguration extends AnalysisConfiguration {
 		final TraceAggregator traceAggregator = new TraceAggregator();
 		final CollectorSink<AggregatedExecution> aggregatedTraceCollector = new CollectorSink<>(this.aggregatedTraces);
 		final CollectorSink<KiekerMetadataRecord> metadataCollector = new CollectorSink<>(this.metadataRecords);
+		final FailedAggregatedTraceFilter failedAggregatedTraceFilter = new FailedAggregatedTraceFilter();
+		final Distributor<AggregatedExecution> thrdDistributor = new Distributor<>();
+		final CollectorSink<AggregatedExecution> failedAggregatedTraceCollector = new CollectorSink<>(this.failedAggregatedTracesList);
+		final FailureContainingAggregatedTraceFilter failureContainingAggregatedTraceFilter = new FailureContainingAggregatedTraceFilter();
+		final CollectorSink<AggregatedExecution> failureContainingAggregatedTraceCollector = new CollectorSink<>(this.failureContainingAggregatedTracesList);
 
 		// Configure the stages
 		fstDistributor.setStrategy(new CopyByReferenceStrategy<IFlowRecord>());
 		sndDistributor.setStrategy(new CopyByReferenceStrategy<Execution>());
+		thrdDistributor.setStrategy(new CopyByReferenceStrategy<AggregatedExecution>());
 
 		// Connect the stages
 		final IPipeFactory pipeFactory = AnalysisConfiguration.PIPE_FACTORY_REGISTRY.getPipeFactory(ThreadCommunication.INTRA, PipeOrdering.ARBITRARY, false);
@@ -95,7 +105,12 @@ public final class ImportAnalysisConfiguration extends AnalysisConfiguration {
 		pipeFactory.create(failedTraceFilter.getOutputPort(), failedTraceCollector.getInputPort());
 		pipeFactory.create(sndDistributor.getNewOutputPort(), failureContainingTraceFilter.getInputPort());
 		pipeFactory.create(failureContainingTraceFilter.getOutputPort(), failureContainingTraceCollector.getInputPort());
-		pipeFactory.create(traceAggregator.getOutputPort(), aggregatedTraceCollector.getInputPort());
+		pipeFactory.create(traceAggregator.getOutputPort(), thrdDistributor.getInputPort());
+		pipeFactory.create(thrdDistributor.getNewOutputPort(), aggregatedTraceCollector.getInputPort());
+		pipeFactory.create(thrdDistributor.getNewOutputPort(), failedAggregatedTraceFilter.getInputPort());
+		pipeFactory.create(thrdDistributor.getNewOutputPort(), failureContainingAggregatedTraceFilter.getInputPort());
+		pipeFactory.create(failedAggregatedTraceFilter.getOutputPort(), failedAggregatedTraceCollector.getInputPort());
+		pipeFactory.create(failureContainingAggregatedTraceFilter.getOutputPort(), failureContainingAggregatedTraceCollector.getInputPort());
 		pipeFactory.create(typeFilter.getOutputPortForType(KiekerMetadataRecord.class), metadataCollector.getInputPort());
 
 		// Make sure that the producer is executed by the analysis
@@ -118,6 +133,14 @@ public final class ImportAnalysisConfiguration extends AnalysisConfiguration {
 		return this.failureContainingTracesList;
 	}
 
+	public List<AggregatedExecution> getFailedAggregatedTracesList() {
+		return this.failedAggregatedTracesList;
+	}
+
+	public List<AggregatedExecution> getFailureContainingAggregatedTracesList() {
+		return this.failureContainingAggregatedTracesList;
+	}
+
 	public List<AggregatedExecution> getAggregatedTraces() {
 		return this.aggregatedTraces;
 	}
diff --git a/src/main/java/kieker/gui/model/importer/stages/FailedAggregatedTraceFilter.java b/src/main/java/kieker/gui/model/importer/stages/FailedAggregatedTraceFilter.java
new file mode 100644
index 00000000..3b360120
--- /dev/null
+++ b/src/main/java/kieker/gui/model/importer/stages/FailedAggregatedTraceFilter.java
@@ -0,0 +1,38 @@
+/***************************************************************************
+ * Copyright 2014 Kieker Project (http://kieker-monitoring.net)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+
+package kieker.gui.model.importer.stages;
+
+import kieker.gui.model.domain.AggregatedExecution;
+import teetime.framework.AbstractConsumerStage;
+import teetime.framework.OutputPort;
+
+public final class FailedAggregatedTraceFilter extends AbstractConsumerStage<AggregatedExecution> {
+
+	private final OutputPort<AggregatedExecution> outputPort = super.createOutputPort();
+
+	@Override
+	protected void execute(final AggregatedExecution element) {
+		if (element.isFailed()) {
+			this.outputPort.send(element);
+		}
+	}
+
+	public OutputPort<AggregatedExecution> getOutputPort() {
+		return this.outputPort;
+	}
+
+}
diff --git a/src/main/java/kieker/gui/model/importer/stages/FailureContainingAggregatedTraceFilter.java b/src/main/java/kieker/gui/model/importer/stages/FailureContainingAggregatedTraceFilter.java
new file mode 100644
index 00000000..bf4a071a
--- /dev/null
+++ b/src/main/java/kieker/gui/model/importer/stages/FailureContainingAggregatedTraceFilter.java
@@ -0,0 +1,38 @@
+/***************************************************************************
+ * Copyright 2014 Kieker Project (http://kieker-monitoring.net)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+
+package kieker.gui.model.importer.stages;
+
+import kieker.gui.model.domain.AggregatedExecution;
+import teetime.framework.AbstractConsumerStage;
+import teetime.framework.OutputPort;
+
+public final class FailureContainingAggregatedTraceFilter extends AbstractConsumerStage<AggregatedExecution> {
+
+	private final OutputPort<AggregatedExecution> outputPort = super.createOutputPort();
+
+	@Override
+	protected void execute(final AggregatedExecution element) {
+		if (element.containsFailure()) {
+			this.outputPort.send(element);
+		}
+	}
+
+	public OutputPort<AggregatedExecution> getOutputPort() {
+		return this.outputPort;
+	}
+
+}
diff --git a/src/main/java/kieker/gui/view/AggregatedTracesSubView.java b/src/main/java/kieker/gui/view/AggregatedTracesSubView.java
index 08f0c25e..6b12eebc 100644
--- a/src/main/java/kieker/gui/view/AggregatedTracesSubView.java
+++ b/src/main/java/kieker/gui/view/AggregatedTracesSubView.java
@@ -20,7 +20,6 @@ import java.util.List;
 import java.util.Observable;
 import java.util.Observer;
 
-import kieker.gui.controller.AggregatedTracesSubViewController;
 import kieker.gui.model.AggregatedTracesSubViewModel;
 import kieker.gui.model.DataModel;
 import kieker.gui.model.PropertiesModel;
@@ -29,6 +28,7 @@ import kieker.gui.view.util.AggregatedExecutionAvgDurationComparator;
 import kieker.gui.view.util.AggregatedExecutionCallComparator;
 import kieker.gui.view.util.AggregatedExecutionMaxDurationComparator;
 import kieker.gui.view.util.AggregatedExecutionMinDurationComparator;
+import kieker.gui.view.util.AggregatedExecutionTotalDurationComparator;
 import kieker.gui.view.util.ExecutionComponentComparator;
 import kieker.gui.view.util.ExecutionContainerComparator;
 import kieker.gui.view.util.ExecutionOperationComparator;
@@ -36,6 +36,7 @@ import kieker.gui.view.util.TreeColumnSortListener;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.events.SelectionListener;
 import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.layout.FillLayout;
 import org.eclipse.swt.layout.GridLayout;
@@ -52,7 +53,7 @@ import org.eclipse.wb.swt.SWTResourceManager;
 public class AggregatedTracesSubView implements Observer, ISubView {
 
 	private final AggregatedTracesSubViewModel aggregatedTracesSubViewModel;
-	private final AggregatedTracesSubViewController controller;
+	private final SelectionListener controller;
 	private final DataModel model;
 	private Composite composite;
 	private Tree tree;
@@ -69,13 +70,16 @@ public class AggregatedTracesSubView implements Observer, ISubView {
 	private Label lblExecutionContainerDisplay;
 	private Label lblFailed;
 	private final PropertiesModel propertiesModel;
+	private Label lblTotalDurationDisplay;
+	private final Type type;
 
-	public AggregatedTracesSubView(final DataModel model, final AggregatedTracesSubViewModel aggregatedTracesSubViewModel,
-			final PropertiesModel propertiesModel, final AggregatedTracesSubViewController controller) {
+	public AggregatedTracesSubView(final Type type, final DataModel model, final AggregatedTracesSubViewModel aggregatedTracesSubViewModel, final PropertiesModel propertiesModel,
+			final SelectionListener controller) {
 		this.controller = controller;
 		this.model = model;
 		this.propertiesModel = propertiesModel;
 		this.aggregatedTracesSubViewModel = aggregatedTracesSubViewModel;
+		this.type = type;
 
 		model.addObserver(this);
 		aggregatedTracesSubViewModel.addObserver(this);
@@ -127,6 +131,10 @@ public class AggregatedTracesSubView implements Observer, ISubView {
 		trclmnMaximalDuration.setWidth(100);
 		trclmnMaximalDuration.setText("Maximal Duration");
 
+		final TreeColumn trclmnTotalDuration = new TreeColumn(this.tree, SWT.RIGHT);
+		trclmnTotalDuration.setWidth(100);
+		trclmnTotalDuration.setText("Total Duration");
+
 		this.detailComposite = new Composite(sashForm, SWT.BORDER);
 		this.detailComposite.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
 		this.detailComposite.setLayout(new GridLayout(2, false));
@@ -187,6 +195,14 @@ public class AggregatedTracesSubView implements Observer, ISubView {
 		this.lblMaximalDurationDisplay.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
 		this.lblMaximalDurationDisplay.setText("N/A");
 
+		final Label lblTotalDuration = new Label(this.detailComposite, SWT.NONE);
+		lblTotalDuration.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		lblTotalDuration.setText("Total Duration:");
+
+		this.lblTotalDurationDisplay = new Label(this.detailComposite, SWT.NONE);
+		this.lblTotalDurationDisplay.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		this.lblTotalDurationDisplay.setText("N/A");
+
 		this.lblFailed = new Label(this.detailComposite, SWT.NONE);
 		this.lblFailed.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
 		this.lblFailed.setText("Failed:");
@@ -222,6 +238,7 @@ public class AggregatedTracesSubView implements Observer, ISubView {
 		trclmnMaximalDuration.addSelectionListener(new TreeColumnSortListener<>(new AggregatedExecutionMaxDurationComparator()));
 		trclmnAverageDuration.addSelectionListener(new TreeColumnSortListener<>(new AggregatedExecutionAvgDurationComparator()));
 		trclmnCalls.addSelectionListener(new TreeColumnSortListener<>(new AggregatedExecutionCallComparator()));
+		trclmnTotalDuration.addSelectionListener(new TreeColumnSortListener<>(new AggregatedExecutionTotalDurationComparator()));
 	}
 
 	@Override
@@ -243,8 +260,14 @@ public class AggregatedTracesSubView implements Observer, ISubView {
 	}
 
 	private void updateTree() {
-		final List<AggregatedExecution> records = this.model.getAggregatedTracesCopy();
-
+		final List<AggregatedExecution> records;
+		if (this.type == Type.SHOW_JUST_FAILED_TRACES) {
+			records = this.model.getFailedAggregatedTracesCopy();
+		} else if (this.type == Type.SHOW_JUST_FAILURE_CONTAINING_TRACES) {
+			records = this.model.getFailureContainingAggregatedTracesCopy();
+		} else {
+			records = this.model.getAggregatedTracesCopy();
+		}
 		this.tree.setData(records);
 		this.tree.setItemCount(records.size());
 
@@ -265,10 +288,12 @@ public class AggregatedTracesSubView implements Observer, ISubView {
 		final String minDuration = (Long.toString(trace.getMinDuration()) + " " + this.model.getShortTimeUnit()).trim();
 		final String maxDuration = (Long.toString(trace.getMaxDuration()) + " " + this.model.getShortTimeUnit()).trim();
 		final String avgDuration = (Long.toString(trace.getAvgDuration()) + " " + this.model.getShortTimeUnit()).trim();
+		final String totalDuration = (Long.toString(trace.getTotalDuration()) + " " + this.model.getShortTimeUnit()).trim();
 
 		this.lblMinimalDurationDisplay.setText(minDuration);
 		this.lblMaximalDurationDisplay.setText(maxDuration);
 		this.lblAverageDurationDisplay.setText(avgDuration);
+		this.lblTotalDurationDisplay.setText(totalDuration);
 
 		this.lblExecutionContainerDisplay.setText(trace.getContainer());
 		this.lblComponentDisplay.setText(trace.getComponent());
@@ -325,12 +350,13 @@ public class AggregatedTracesSubView implements Observer, ISubView {
 			final String minDuration = (Long.toString(executionEntry.getMinDuration()) + " " + AggregatedTracesSubView.this.model.getShortTimeUnit()).trim();
 			final String maxDuration = (Long.toString(executionEntry.getMaxDuration()) + " " + AggregatedTracesSubView.this.model.getShortTimeUnit()).trim();
 			final String avgDuration = (Long.toString(executionEntry.getAvgDuration()) + " " + AggregatedTracesSubView.this.model.getShortTimeUnit()).trim();
+			final String totalDuration = (Long.toString(executionEntry.getTotalDuration()) + " " + AggregatedTracesSubView.this.model.getShortTimeUnit()).trim();
 
 			if (parent != null) {
-				item.setText(new String[] { executionEntry.getContainer(), componentName, operationString, "", minDuration, avgDuration, maxDuration });
+				item.setText(new String[] { executionEntry.getContainer(), componentName, operationString, "", minDuration, avgDuration, maxDuration, totalDuration });
 			} else {
 				item.setText(new String[] { executionEntry.getContainer(), componentName, operationString, Integer.toString(executionEntry.getCalls()), minDuration, avgDuration,
-						maxDuration });
+						maxDuration, totalDuration });
 			}
 
 			if (executionEntry.isFailed()) {
@@ -344,4 +370,8 @@ public class AggregatedTracesSubView implements Observer, ISubView {
 
 	}
 
+	public enum Type {
+		SHOW_ALL_TRACES, SHOW_JUST_FAILED_TRACES, SHOW_JUST_FAILURE_CONTAINING_TRACES
+	}
+
 }
diff --git a/src/main/java/kieker/gui/view/MainView.java b/src/main/java/kieker/gui/view/MainView.java
index 017aee97..5a24def9 100644
--- a/src/main/java/kieker/gui/view/MainView.java
+++ b/src/main/java/kieker/gui/view/MainView.java
@@ -45,6 +45,8 @@ public class MainView implements Observer {
 	private final ISubView failedTracesSubView;
 	private final ISubView aggregatedTracesSubView;
 	private final ISubView failureContainingTracesSubView;
+	private final ISubView subView6;
+	private final ISubView subView7;
 	private final MainViewController controller;
 
 	private Shell shell;
@@ -65,9 +67,12 @@ public class MainView implements Observer {
 	private TreeItem trtmJustFailedTraces;
 
 	private TreeItem trtmJustTracesContaining;
+	private TreeItem trtmJustFailedAggTraces;
+	private TreeItem trtmJustAggTracesContaining;
 
 	public MainView(final DataModel dataModel, final MainViewModel mainViewModel, final MainViewController controller, final ISubView recordsSubView, final ISubView tracesSubView,
-			final ISubView failedTracesSubView, final ISubView aggregatedTracesSubView, final ISubView failureContainingTracesSubView) {
+			final ISubView failedTracesSubView, final ISubView aggregatedTracesSubView, final ISubView failureContainingTracesSubView, final ISubView subView6,
+			final ISubView subView7) {
 		this.dataModel = dataModel;
 		this.mainViewModel = mainViewModel;
 		this.recordsSubView = recordsSubView;
@@ -75,6 +80,8 @@ public class MainView implements Observer {
 		this.failureContainingTracesSubView = failureContainingTracesSubView;
 		this.failedTracesSubView = failedTracesSubView;
 		this.aggregatedTracesSubView = aggregatedTracesSubView;
+		this.subView6 = subView6;
+		this.subView7 = subView7;
 
 		this.controller = controller;
 	}
@@ -122,6 +129,14 @@ public class MainView implements Observer {
 		return this.trtmJustTracesContaining;
 	}
 
+	public TreeItem getTrtmJustFailedAggTraces() {
+		return this.trtmJustFailedAggTraces;
+	}
+
+	public TreeItem getTrtmJustAggTracesContaining() {
+		return this.trtmJustAggTracesContaining;
+	}
+
 	public MenuItem getMntmExit() {
 		return this.mntmExit;
 	}
@@ -184,6 +199,13 @@ public class MainView implements Observer {
 
 		this.trtmAggregatedTraces = new TreeItem(this.trtmExplorer, 0);
 		this.trtmAggregatedTraces.setText("Aggregated Traces");
+
+		this.trtmJustFailedAggTraces = new TreeItem(this.trtmAggregatedTraces, SWT.NONE);
+		this.trtmJustFailedAggTraces.setText("Just Failed Traces");
+
+		this.trtmJustAggTracesContaining = new TreeItem(this.trtmAggregatedTraces, SWT.NONE);
+		this.trtmJustAggTracesContaining.setText("Just Traces Containing Failures");
+		this.trtmAggregatedTraces.setExpanded(true);
 		this.trtmExplorer.setExpanded(true);
 
 		this.subViewLayout = new StackLayout();
@@ -196,6 +218,8 @@ public class MainView implements Observer {
 		this.failedTracesSubView.createComposite(this.subViewComposite);
 		this.aggregatedTracesSubView.createComposite(this.subViewComposite);
 		this.failureContainingTracesSubView.createComposite(this.subViewComposite);
+		this.subView6.createComposite(this.subViewComposite);
+		this.subView7.createComposite(this.subViewComposite);
 
 		final Menu menu = new Menu(this.shell, SWT.BAR);
 		this.shell.setMenuBar(menu);
@@ -283,6 +307,12 @@ public class MainView implements Observer {
 		case FAILURE_CONTAINING_TRACES_SUB_VIEW:
 			subViewToShow = this.failureContainingTracesSubView.getComposite();
 			break;
+		case FAILED_AGGREGATED_TRACES_SUB_VIEW:
+			subViewToShow = this.subView6.getComposite();
+			break;
+		case FAILURE_CONTAINING_AGGREGATED_TRACES_SUB_VIEW:
+			subViewToShow = this.subView7.getComposite();
+			break;
 		default:
 			subViewToShow = null;
 			break;
diff --git a/src/main/java/kieker/gui/view/util/AggregatedExecutionTotalDurationComparator.java b/src/main/java/kieker/gui/view/util/AggregatedExecutionTotalDurationComparator.java
new file mode 100644
index 00000000..9f78ef5b
--- /dev/null
+++ b/src/main/java/kieker/gui/view/util/AggregatedExecutionTotalDurationComparator.java
@@ -0,0 +1,19 @@
+package kieker.gui.view.util;
+
+import kieker.gui.model.domain.AggregatedExecution;
+
+import org.eclipse.swt.SWT;
+
+public class AggregatedExecutionTotalDurationComparator extends AbstractDirectedComparator<AggregatedExecution> {
+
+	@Override
+	public int compare(final AggregatedExecution arg0, final AggregatedExecution arg1) {
+		int result = Long.compare(arg0.getTotalDuration(), arg1.getTotalDuration());
+		if (this.getDirection() == SWT.UP) {
+			result = -result;
+		}
+		return result;
+
+	}
+
+}
-- 
GitLab