From 98beda1d92c279137f838fb57e5b17a9c931a3b8 Mon Sep 17 00:00:00 2001
From: Eddie Groh <groh@fortiss.org>
Date: Mon, 3 Jul 2023 18:16:30 +0200
Subject: [PATCH] Refactored the data structure storing the metric data

Issue-Ref: 4310
Issue-Url: https://git.fortiss.org/af3/af3/-/issues/4310

Signed-off-by: Eddie Groh <groh@fortiss.org>
---
 .../ui/ModelQualityExtractionMenu.java        |   1 -
 .../ui/view/fx/MetricsFXController.java       |  47 ++-
 .../META-INF/MANIFEST.MF                      |   1 +
 .../ext/quality/AF3QualityActivator.java      |   1 -
 .../HierarchicElementSizeProvider.java        | 163 +++++++++
 .../{service => }/IModelQualityProvider.java  |  64 +---
 .../data/HierarchicalMetricDataContainer.java |  54 +++
 .../quality/data/IMetricDataContainer.java    |  25 ++
 .../ext/quality/data/MetricDataManager.java   |  57 ++++
 .../ext/quality/data/MetricTreeNode.java      | 102 ++++++
 .../HierarchicElementSizeProvider.java        | 311 ------------------
 .../quality/service/IModelQualityService.java |  14 +-
 .../quality/service/ModelQualityService.java  |  91 +++--
 13 files changed, 475 insertions(+), 456 deletions(-)
 create mode 100644 org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/HierarchicElementSizeProvider.java
 rename org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/{service => }/IModelQualityProvider.java (53%)
 create mode 100644 org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/data/HierarchicalMetricDataContainer.java
 create mode 100644 org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/data/IMetricDataContainer.java
 create mode 100644 org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/data/MetricDataManager.java
 create mode 100644 org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/data/MetricTreeNode.java
 delete mode 100644 org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/service/HierarchicElementSizeProvider.java

diff --git a/org.fortiss.tooling.ext.quality.ui/src/org/fortiss/tooling/ext/quality/ui/ModelQualityExtractionMenu.java b/org.fortiss.tooling.ext.quality.ui/src/org/fortiss/tooling/ext/quality/ui/ModelQualityExtractionMenu.java
index 56f749fa3..1bb5f9056 100644
--- a/org.fortiss.tooling.ext.quality.ui/src/org/fortiss/tooling/ext/quality/ui/ModelQualityExtractionMenu.java
+++ b/org.fortiss.tooling.ext.quality.ui/src/org/fortiss/tooling/ext/quality/ui/ModelQualityExtractionMenu.java
@@ -82,7 +82,6 @@ public class ModelQualityExtractionMenu implements IContextMenuContributor {
 		public void run() {
 			ITopLevelElement top = IPersistencyService.getInstance().getTopLevelElementFor(this.fp);
 			IModelQualityService.getInstance().performMetricAnalysis(top);
-			System.out.println("We print something");
 		}
 	}
 }
diff --git a/org.fortiss.tooling.ext.quality.ui/src/org/fortiss/tooling/ext/quality/ui/view/fx/MetricsFXController.java b/org.fortiss.tooling.ext.quality.ui/src/org/fortiss/tooling/ext/quality/ui/view/fx/MetricsFXController.java
index 29a4abe45..7fd2453d1 100644
--- a/org.fortiss.tooling.ext.quality.ui/src/org/fortiss/tooling/ext/quality/ui/view/fx/MetricsFXController.java
+++ b/org.fortiss.tooling.ext.quality.ui/src/org/fortiss/tooling/ext/quality/ui/view/fx/MetricsFXController.java
@@ -41,7 +41,7 @@ import org.fortiss.tooling.common.ui.javafx.layout.CompositeFXControllerBase;
 import org.fortiss.tooling.common.ui.javafx.style.FillStyle;
 import org.fortiss.tooling.common.ui.javafx.style.FontStyle;
 import org.fortiss.tooling.common.ui.javafx.style.LineStyle;
-import org.fortiss.tooling.ext.quality.service.IModelQualityProvider;
+import org.fortiss.tooling.ext.quality.data.MetricTreeNode;
 import org.fortiss.tooling.ext.quality.service.ModelQualityService;
 import org.fortiss.tooling.kernel.model.IProjectRootElement;
 import org.fortiss.tooling.spiderchart.control.SpiderChartViewer;
@@ -111,8 +111,8 @@ public class MetricsFXController extends CompositeFXControllerBase<SplitPane, No
 	public void selectionChanged(IWorkbenchPart part, ISelection selection) {
 
 		ModelQualityService.getInstance();
-		var last_metrics = ModelQualityService.last_metrics;
-		if(last_metrics == null) {
+		var manager = ModelQualityService.metricDataManagerInstance;
+		if(manager == null) {
 			topLabel.setText(
 					"No Metrics were available at " + timeFormat.format(LocalDateTime.now()));
 			return;
@@ -144,7 +144,7 @@ public class MetricsFXController extends CompositeFXControllerBase<SplitPane, No
 		}
 
 		if(selected instanceof IHierarchicElement) {
-			var root_provider = last_metrics.get(currentRootElement);
+			var root_provider = manager.getRootNodes().get(currentRootElement);
 
 			if(root_provider == null) {
 				topLabel.setText("No Metric found for this project, did you export metrics?");
@@ -152,24 +152,22 @@ public class MetricsFXController extends CompositeFXControllerBase<SplitPane, No
 			}
 
 			var element = (IHierarchicElement)selected;
-			var provider = root_provider.getProvider(element);
-			if(provider != null) {
+			var node = manager.getHierarchicLookupTable().get(element);
+			if(node != null) {
 
-				var string = provider.getExampleString();
-				topLabel.setText(string);
+				topLabel.setText("Text");
 
-				if(!provider.getContainedProviders().isEmpty()) {
+				if(!node.getChildren().isEmpty()) {
 
-					SpiderChartViewer viewer =
-							buildSpiderChart((IModelQualityProvider<IHierarchicElement>)provider);
+					SpiderChartViewer viewer = buildSpiderChart(node);
 					borderPane.setCenter(viewer.getViewerPane());
 
 					// Create PieChart and add data
 					pieChart.getData().clear();
-					for(var prov : provider.getContainedProviders()) {
+					for(var child : node.getChildren()) {
 
-						PieChart.Data slice = new PieChart.Data(prov.getName(),
-								((IModelQualityProvider<?>)prov).getExampleValues().get(0));
+						PieChart.Data slice =
+								new PieChart.Data(child.getName(), child.getTotalPortAmount());
 						pieChart.getData().add(slice);
 						pieChart.setLegendVisible(false);
 						pieChart.setTitle("");
@@ -202,37 +200,34 @@ public class MetricsFXController extends CompositeFXControllerBase<SplitPane, No
 	 *            the provider for which the spider chart should be generated
 	 * @return {@link SpiderChartViewer} with the matching metrics
 	 */
-	private static SpiderChartViewer
-			buildSpiderChart(IModelQualityProvider<IHierarchicElement> provider) {
+	private static SpiderChartViewer buildSpiderChart(MetricTreeNode node) {
 		SpiderChart spiderChart = new SpiderChart();
-		spiderChart.setTitle("Smartphone Comparison Scale");
+		spiderChart.setTitle("Amount of Ports");
 		spiderChart.setLegendLabel("Legend");
 		ChartStyle chartStyle = new ChartStyle(true, true, true);
 
-		List<IModelQualityProvider<IHierarchicElement>> containedProviders =
-				provider.getContainedProviders();
+		List<MetricTreeNode> children = node.getChildren();
 
-		if(containedProviders.isEmpty()) {
+		if(children.isEmpty()) {
 			return null;
 		}
 
-		double maxval = containedProviders.stream().mapToDouble(p -> p.getExampleValues().get(0))
-				.max().getAsDouble();
+		double maxval =
+				children.stream().mapToDouble(p -> p.getTotalPortAmount()).max().getAsDouble();
 
 		chartStyle.setUseIndividualAxisSegments(false);
 		chartStyle.setTitleStyle(new FontStyle("Verdana", 14, BLUE.brighter()));
 
 		DataSeries elementData = new DataSeries("Data");
-		for(var prov : containedProviders) {
-			DoubleAxis testing = new DoubleAxis(prov.getName(), 0.0, maxval);
+		for(var child : node.getChildren()) {
+			DoubleAxis testing = new DoubleAxis(child.getName(), 0.0, maxval);
 
 			AxisStyle aStyle3Segs = new AxisStyle(SOLID_BLACK_1PT, BLACK_VERDANA_14PT, 3,
 					BLACK_VERDANA_8PT, new DecimalFormat("#.##"));
 			chartStyle.setAxisStyle(testing, aStyle3Segs);
 
 			spiderChart.addAxis(testing);
-			elementData.setPoint(testing,
-					((IModelQualityProvider<?>)prov).getExampleValues().get(0));
+			elementData.setPoint(testing, child.getTotalPortAmount());
 		}
 		spiderChart.addData(elementData);
 
diff --git a/org.fortiss.tooling.ext.quality/META-INF/MANIFEST.MF b/org.fortiss.tooling.ext.quality/META-INF/MANIFEST.MF
index b7c389724..9b9be8e7a 100644
--- a/org.fortiss.tooling.ext.quality/META-INF/MANIFEST.MF
+++ b/org.fortiss.tooling.ext.quality/META-INF/MANIFEST.MF
@@ -13,5 +13,6 @@ Require-Bundle: org.eclipse.core.runtime,
  org.fortiss.tooling.kernel;visibility:=reexport,
  org.fortiss.af3.project
 Export-Package: org.fortiss.tooling.ext.quality,
+ org.fortiss.tooling.ext.quality.data,
  org.fortiss.tooling.ext.quality.service
 
diff --git a/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/AF3QualityActivator.java b/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/AF3QualityActivator.java
index 7ab8cb483..ef935dcfc 100644
--- a/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/AF3QualityActivator.java
+++ b/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/AF3QualityActivator.java
@@ -18,7 +18,6 @@ package org.fortiss.tooling.ext.quality;
 
 import org.eclipse.core.runtime.Plugin;
 import org.fortiss.tooling.base.model.element.IHierarchicElement;
-import org.fortiss.tooling.ext.quality.service.HierarchicElementSizeProvider;
 import org.fortiss.tooling.ext.quality.service.IModelQualityService;
 import org.fortiss.tooling.ext.quality.service.ModelQualityService;
 import org.osgi.framework.BundleContext;
diff --git a/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/HierarchicElementSizeProvider.java b/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/HierarchicElementSizeProvider.java
new file mode 100644
index 000000000..cb3eb2cb2
--- /dev/null
+++ b/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/HierarchicElementSizeProvider.java
@@ -0,0 +1,163 @@
+/*-------------------------------------------------------------------------+
+| Copyright 2023 fortiss GmbH                                              |
+|                                                                          |
+| 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 org.fortiss.tooling.ext.quality;
+
+import java.util.Optional;
+
+import org.eclipse.emf.common.util.EList;
+import org.fortiss.tooling.base.model.element.IHierarchicElement;
+import org.fortiss.tooling.ext.quality.data.MetricDataManager;
+import org.fortiss.tooling.ext.quality.data.MetricTreeNode;
+import org.fortiss.tooling.kernel.model.INamedCommentedElement;
+
+/**
+ * {@link IModelQualityProvider} to count the ratio of filled out comments of
+ * INamedCommentedElements.
+ * 
+ * @author blaschke
+ * @author groh
+ */
+public class HierarchicElementSizeProvider implements IModelQualityProvider<IHierarchicElement> {
+	/**
+	 * returns an array of integers or <String,Double> Map Number of children of the
+	 * hierarchical Element (on this level) Number of ports on the hierarchical
+	 * Element (on this level) Number of channels in the hierarchical element (on
+	 * this level) Number of totalPorts in whole tree Number of totalElements in
+	 * whole tree Average SubTree Size
+	 */
+
+	/** Key for the metric counting ports */
+	public static final String NUMBER_OF_PORTS = "numberOfPorts";
+
+	/** Key for the metric counting elements */
+	public static final String NUMBER_OF_CONTAINED_ELEMENTS = "numberOfContainedElements";
+
+	/** Key for the metric counting channels */
+	public static final String NUMBER_OF_CHANNELS = "numberOfChannels";
+
+	/** Key for the metric counting the total amount of ports contained */
+	public static final String NUMBER_OF_TOTAL_PORTS = "numberOfTotalPorts";
+	/** Key for the metric counting the total amount of elements contained */
+	public static final String NUMBER_OF_TOTAL_ELEMENTS = "numberOfTotalElements";
+	/** Key for the metric counting the total amount of elements which can be commented */
+	public static final String NUMBER_OF_TOTAL_COMMENTABLE_ELEMENTS =
+			"numberOfTotalCommentableElements";
+	/** Key for the metric counting the total amount of elements which are commented */
+	public static final String NUMBER_OF_TOTAL_COMMENTED_ELEMENTS =
+			"numberOfTotalCommentedElements";
+	/**
+	 * Key for the metric counting the total amount of elements which do not contain other elements
+	 */
+	public static final String NUMBER_OF_TOTAL_LEAF_ELEMENTS = "numberOfTotalLeafElements";
+
+	/**
+	 * List containing all HierarchicElementSizeProvider for components inside the
+	 * IHierarchicElement
+	 */
+
+	/** */
+	public HierarchicElementSizeProvider() {
+		super();
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public void apply(MetricDataManager manager, MetricTreeNode node,
+			IHierarchicElement currentElement) {
+
+		var metrics = node.getStoredMetrics();
+		boolean isElementCommentable = currentElement instanceof INamedCommentedElement;
+		metrics.put(NUMBER_OF_TOTAL_COMMENTABLE_ELEMENTS, isElementCommentable ? 1.0 : 0.0);
+		String comment =
+				isElementCommentable ? ((INamedCommentedElement)currentElement).getComment() : null;
+		metrics.put(NUMBER_OF_TOTAL_COMMENTED_ELEMENTS,
+				comment != null && comment != "" ? 1.0 : 0.0);
+		if(isElementCommentable) {
+			node.setName(((INamedCommentedElement)currentElement).getName());
+		} else {
+			node.setName("Unnamable Element");
+		}
+
+		// Check if any of the specifications is an IHierarchicElement
+		// This is for example the case with an StateAutomaton
+		Optional<IHierarchicElement> hierarchicElementOptional = currentElement.getSpecifications()
+				.stream().filter(s -> s instanceof IHierarchicElement)
+				.map(s -> (IHierarchicElement)s).findAny();
+		if(hierarchicElementOptional.isPresent()) {
+			// Do not collect statistics for the current element, but instead collect them for the
+			// specification
+			IHierarchicElement specificationElement = hierarchicElementOptional.get();
+			EList<IHierarchicElement> containedElements =
+					specificationElement.getContainedElements();
+			if(containedElements.size() == 1) {
+				// Add reference from the element to this, so the lookups works as expected
+				manager.getHierarchicLookupTable().put(specificationElement, node);
+				// Skip the specification element to get a more useful tree structure
+				this.applyMetrics(manager, node, containedElements.get(0));
+			} else {
+				this.applyMetrics(manager, node, specificationElement);
+			}
+			// Add reference from the element to this, so the lookups works as expected
+			manager.getHierarchicLookupTable().put(currentElement, node);
+			return;
+		}
+		this.applyMetrics(manager, node, currentElement);
+	}
+
+	/**
+	 * @param manager
+	 *            for saving the lookup data
+	 * @param node
+	 *            for saving the metric data
+	 * @param currentElement
+	 *            the element on which to collect data
+	 */
+	private void applyMetrics(MetricDataManager manager, MetricTreeNode node,
+			IHierarchicElement currentElement) {
+
+		// TODO input ports number
+		// TODO output ports number
+
+		// EcoreUtils.pickInstanceOf(target, srcList)
+		var metrics = node.getStoredMetrics();
+
+		metrics.put(NUMBER_OF_PORTS, (double)currentElement.getConnectors().size());
+		metrics.put(NUMBER_OF_CONTAINED_ELEMENTS,
+				(double)currentElement.getContainedElements().size());
+		metrics.put(NUMBER_OF_CHANNELS, (double)currentElement.getConnections().size());
+
+		// depth metrics
+		metrics.put(NUMBER_OF_TOTAL_PORTS, (double)currentElement.getConnectors().size());
+		metrics.put(NUMBER_OF_TOTAL_ELEMENTS, 1.0);
+
+		metrics.put(NUMBER_OF_TOTAL_LEAF_ELEMENTS,
+				currentElement.getContainedElements().size() == 0 ? 1.0 : 0.0);
+
+		for(IHierarchicElement containedElement : currentElement.getContainedElements()) {
+			MetricTreeNode child = new MetricTreeNode();
+			node.getChildren().add(child);
+			apply(manager, child, containedElement);
+
+			for(String key : new String[] {NUMBER_OF_TOTAL_PORTS, NUMBER_OF_TOTAL_ELEMENTS,
+					NUMBER_OF_TOTAL_COMMENTABLE_ELEMENTS, NUMBER_OF_TOTAL_COMMENTED_ELEMENTS,
+					NUMBER_OF_TOTAL_LEAF_ELEMENTS}) {
+				metrics.merge(key, child.getStoredMetrics().get(key), Double::sum);
+			}
+		}
+
+		manager.getHierarchicLookupTable().put(currentElement, node);
+	}
+}
diff --git a/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/service/IModelQualityProvider.java b/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/IModelQualityProvider.java
similarity index 53%
rename from org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/service/IModelQualityProvider.java
rename to org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/IModelQualityProvider.java
index d4496e97b..15cc41a29 100644
--- a/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/service/IModelQualityProvider.java
+++ b/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/IModelQualityProvider.java
@@ -13,12 +13,12 @@
 | See the License for the specific language governing permissions and      |
 | limitations under the License.                                           |
 +--------------------------------------------------------------------------*/
-package org.fortiss.tooling.ext.quality.service;
-
-import java.util.List;
+package org.fortiss.tooling.ext.quality;
 
 import org.eclipse.emf.ecore.EObject;
-import org.fortiss.tooling.base.model.element.IHierarchicElement;
+import org.fortiss.tooling.ext.quality.data.MetricDataManager;
+import org.fortiss.tooling.ext.quality.data.MetricTreeNode;
+import org.fortiss.tooling.ext.quality.service.IModelQualityService;
 import org.fortiss.tooling.kernel.service.base.IEObjectAware;
 
 /**
@@ -31,59 +31,5 @@ import org.fortiss.tooling.kernel.service.base.IEObjectAware;
 public interface IModelQualityProvider<C extends EObject> extends IEObjectAware<EObject> {
 
 	/** Applies the IMetricProvider to the given model element. */
-	void apply(C element);
-
-	/**
-	 * @return a simple example string demonstrating some metric capability
-	 */
-	String getExampleString();
-
-	/**
-	 * @return a simple example values demonstrating some metric capability
-	 */
-	List<Double> getExampleValues();
-
-	/**
-	 * @return providers contained in this provider
-	 */
-	List<IModelQualityProvider<C>> getContainedProviders();
-
-	/**
-	 * @return the name of the element
-	 */
-	String getName();
-
-	/**
-	 * @param element
-	 *            the element for which the matching {@link IModelQualityProvider} is searched
-	 * @return the matching provider
-	 */
-	IModelQualityProvider<C> getProvider(IHierarchicElement element);
-
-	/**
-	 * Visits all nodes of the provider tree in post-order
-	 * 
-	 * @param visitor
-	 *            the object on which the methods will be called
-	 */
-	void traverse(IVisitorModelQualityProvider visitor);
-
-	/**
-	 * @return set of keys of metrics contained in this provider
-	 */
-	List<String> metricKeys();
-
-	/**
-	 * Visitor pattern class
-	 * 
-	 * @author groh
-	 */
-	public interface IVisitorModelQualityProvider {
-
-		/**
-		 * @param provider
-		 *            gets a HierarchicElementSizeProvider
-		 */
-		void accept(HierarchicElementSizeProvider provider);
-	}
+	void apply(MetricDataManager manager, MetricTreeNode node, C element);
 }
diff --git a/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/data/HierarchicalMetricDataContainer.java b/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/data/HierarchicalMetricDataContainer.java
new file mode 100644
index 000000000..175f35a94
--- /dev/null
+++ b/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/data/HierarchicalMetricDataContainer.java
@@ -0,0 +1,54 @@
+/*-------------------------------------------------------------------------+
+| Copyright 2023 fortiss GmbH                                              |
+|                                                                          |
+| 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 org.fortiss.tooling.ext.quality.data;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.fortiss.tooling.ext.quality.HierarchicElementSizeProvider;
+
+/**
+ * Class for storing data generated by the {@link HierarchicElementSizeProvider}
+ * 
+ * @author groh
+ */
+public class HierarchicalMetricDataContainer implements IMetricDataContainer {
+
+	/** Map containing all metrics which are a double */
+	private Map<String, Double> storedMetrics = new HashMap<>();
+
+	/** name of the element which is associated with this data */
+	private String name;
+
+	/**
+	 * @return the name of the element which is associated with this data
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/** Set the name */
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	/**
+	 * @return the stored metrics map
+	 */
+	public Map<String, Double> getStoredMetrics() {
+		return storedMetrics;
+	}
+}
diff --git a/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/data/IMetricDataContainer.java b/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/data/IMetricDataContainer.java
new file mode 100644
index 000000000..7cbd00479
--- /dev/null
+++ b/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/data/IMetricDataContainer.java
@@ -0,0 +1,25 @@
+/*-------------------------------------------------------------------------+
+| Copyright 2023 fortiss GmbH                                              |
+|                                                                          |
+| 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 org.fortiss.tooling.ext.quality.data;
+
+/**
+ * Interface which is implemented by all
+ * 
+ * @author groh
+ */
+public interface IMetricDataContainer {
+	// Nothing here yet
+}
diff --git a/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/data/MetricDataManager.java b/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/data/MetricDataManager.java
new file mode 100644
index 000000000..c3f109913
--- /dev/null
+++ b/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/data/MetricDataManager.java
@@ -0,0 +1,57 @@
+/*-------------------------------------------------------------------------+
+| Copyright 2023 fortiss GmbH                                              |
+|                                                                          |
+| 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 org.fortiss.tooling.ext.quality.data;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.fortiss.tooling.base.model.element.IHierarchicElement;
+import org.fortiss.tooling.kernel.model.IProjectRootElement;
+
+/**
+ * 
+ * @author groh
+ */
+public class MetricDataManager {
+
+	/** a map to lookup the corresponding tree node */
+	private Map<IHierarchicElement, MetricTreeNode> hierarchicLookupTable;
+
+	/** the root tree node */
+	private Map<IProjectRootElement, MetricTreeNode> root_nodes;
+
+	/**
+	 * Constructs a new instance of the MetricDataManager
+	 */
+	public MetricDataManager() {
+		root_nodes = new HashMap<>();
+		hierarchicLookupTable = new HashMap<>();
+	}
+
+	/**
+	 * @return the lookup map
+	 */
+	public Map<IHierarchicElement, MetricTreeNode> getHierarchicLookupTable() {
+		return hierarchicLookupTable;
+	}
+
+	/**
+	 * @return a map containing all root nodes
+	 */
+	public Map<IProjectRootElement, MetricTreeNode> getRootNodes() {
+		return root_nodes;
+	}
+}
diff --git a/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/data/MetricTreeNode.java b/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/data/MetricTreeNode.java
new file mode 100644
index 000000000..200c67bd8
--- /dev/null
+++ b/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/data/MetricTreeNode.java
@@ -0,0 +1,102 @@
+/*-------------------------------------------------------------------------+
+| Copyright 2023 fortiss GmbH                                              |
+|                                                                          |
+| 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 org.fortiss.tooling.ext.quality.data;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.fortiss.tooling.ext.quality.IModelQualityProvider;
+
+/**
+ * A general class for storing all kinds of metric data in a hierarchical tree structure.
+ * 
+ * Allows for efficient storage and retrieval of data
+ * 
+ * @author groh
+ */
+public class MetricTreeNode {
+
+	/** stores the children of this tree node */
+	private List<MetricTreeNode> children;
+
+	/**
+	 * This map stores a relationship between a {@link IModelQualityProvider} and
+	 * {@link IMetricDataContainer}.
+	 * 
+	 * This allows all {@linkplain IModelQualityProvider} to deposit data inside this structure, and
+	 * quickly retrieve it for processing
+	 * 
+	 * The stored data can then also be accessed by other methods, for displaying information,
+	 * creating statistics, etc.
+	 */
+	private Map<Class<? extends IModelQualityProvider<?>>, IMetricDataContainer> dataContainers;
+
+	/** Map containing all metrics which are a double */
+	private Map<String, Double> storedMetrics = new HashMap<>();
+
+	/** name of the element which is associated with this data */
+	private String name;
+
+	/**
+	 * Constructs a new node
+	 */
+	public MetricTreeNode() {
+		children = new ArrayList<MetricTreeNode>();
+		dataContainers = new HashMap<>();
+	}
+
+	/**
+	 * @return the children of this node
+	 */
+	public List<MetricTreeNode> getChildren() {
+		return children;
+	}
+
+	/**
+	 * See {@link MetricTreeNode#dataContainers}
+	 * 
+	 * @return the map storing all DataContainers in this node
+	 */
+	public Map<Class<? extends IModelQualityProvider<?>>, IMetricDataContainer>
+			getDataContainers() {
+		return dataContainers;
+	}
+
+	/**
+	 * @return the name of the element which is associated with this data
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/** Set the name */
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	/**
+	 * @return the stored metrics map
+	 */
+	public Map<String, Double> getStoredMetrics() {
+		return storedMetrics;
+	}
+
+	public double getTotalPortAmount() {
+		return storedMetrics.get("numberOfTotalPorts");
+	}
+}
diff --git a/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/service/HierarchicElementSizeProvider.java b/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/service/HierarchicElementSizeProvider.java
deleted file mode 100644
index da40a0282..000000000
--- a/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/service/HierarchicElementSizeProvider.java
+++ /dev/null
@@ -1,311 +0,0 @@
-/*-------------------------------------------------------------------------+
-| Copyright 2023 fortiss GmbH                                              |
-|                                                                          |
-| 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 org.fortiss.tooling.ext.quality.service;
-
-import java.text.DecimalFormat;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-
-import org.eclipse.emf.common.util.EList;
-import org.fortiss.tooling.base.model.element.IHierarchicElement;
-import org.fortiss.tooling.kernel.model.INamedCommentedElement;
-
-/**
- * {@link IModelQualityProvider} to count the ratio of filled out comments of
- * INamedCommentedElements.
- * 
- * @author blaschke
- * @author groh
- */
-public class HierarchicElementSizeProvider implements IModelQualityProvider<IHierarchicElement> {
-	/**
-	 * returns an array of integers or <String,Double> Map Number of children of the
-	 * hierarchical Element (on this level) Number of ports on the hierarchical
-	 * Element (on this level) Number of channels in the hierarchical element (on
-	 * this level) Number of totalPorts in whole tree Number of totalElements in
-	 * whole tree Average SubTree Size
-	 */
-
-	/** Key for the metric counting ports */
-	public static final String NUMBER_OF_PORTS = "numberOfPorts";
-
-	/** Key for the metric counting elements */
-	public static final String NUMBER_OF_CONTAINED_ELEMENTS = "numberOfContainedElements";
-
-	/** Key for the metric counting channels */
-	public static final String NUMBER_OF_CHANNELS = "numberOfChannels";
-
-	/** Key for the metric counting the total amount of ports contained */
-	public static final String NUMBER_OF_TOTAL_PORTS = "numberOfTotalPorts";
-	/** Key for the metric counting the total amount of elements contained */
-	public static final String NUMBER_OF_TOTAL_ELEMENTS = "numberOfTotalElements";
-	/** Key for the metric counting the total amount of elements which can be commented */
-	public static final String NUMBER_OF_TOTAL_COMMENTABLE_ELEMENTS =
-			"numberOfTotalCommentableElements";
-	/** Key for the metric counting the total amount of elements which are commented */
-	public static final String NUMBER_OF_TOTAL_COMMENTED_ELEMENTS =
-			"numberOfTotalCommentedElements";
-
-	/** Map containing all metrics concerning the current IHierarchicElement */
-	private Map<String, Double> storedMetrics;
-	/**
-	 * List containing all HierarchicElementSizeProvider for components inside the
-	 * IHierarchicElement
-	 */
-	private List<HierarchicElementSizeProvider> containedProviders;
-
-	/**
-	 * Mapping containing all providers from this element and any elements contained in that element
-	 */
-	private Map<IHierarchicElement, HierarchicElementSizeProvider> allProviders;
-
-	/** Variable storing the name */
-	private String name;
-
-	/**
-	 * @return Map containing the mapping between a metric keys and the corresponding values for
-	 *         this element
-	 */
-	public Map<String, Double> getStoredMetrics() {
-		return storedMetrics;
-	}
-
-	/** */
-	public HierarchicElementSizeProvider() {
-		super();
-		this.storedMetrics = new HashMap<>();
-		this.allProviders = new HashMap<>();
-		this.containedProviders = new ArrayList<>();
-		this.name = null;
-	}
-
-	/** {@inheritDoc} */
-	@Override
-	public void apply(IHierarchicElement currentElement) {
-
-		boolean isElementCommentable = currentElement instanceof INamedCommentedElement;
-		storedMetrics.put(NUMBER_OF_TOTAL_COMMENTABLE_ELEMENTS, isElementCommentable ? 1.0 : 0.0);
-		String comment =
-				isElementCommentable ? ((INamedCommentedElement)currentElement).getComment() : null;
-		storedMetrics.put(NUMBER_OF_TOTAL_COMMENTED_ELEMENTS,
-				comment != null && comment != "" ? 1.0 : 0.0);
-		if(isElementCommentable) {
-			this.name = ((INamedCommentedElement)currentElement).getName();
-		} else {
-			this.name = "Unnamable Element";
-		}
-
-		// Check if any of the specifications is an IHierarchicElement
-		// This is for example the case with an StateAutomaton
-		Optional<IHierarchicElement> hierarchicElementOptional = currentElement.getSpecifications()
-				.stream().filter(s -> s instanceof IHierarchicElement)
-				.map(s -> (IHierarchicElement)s).findAny();
-		if(hierarchicElementOptional.isPresent()) {
-			// Do not collect statistics for the current element, but instead collect them for the
-			// specification
-			IHierarchicElement specificationElement = hierarchicElementOptional.get();
-			EList<IHierarchicElement> containedElements =
-					specificationElement.getContainedElements();
-			if(containedElements.size() == 1) {
-				// Add reference from the element to this, so the lookups works as expected
-				allProviders.put(specificationElement, this);
-				// Skip the specification element to get a more useful tree structure
-				this.applyMetrics(containedElements.get(0));
-			} else {
-				this.applyMetrics(specificationElement);
-			}
-			// Add reference from the element to this, so the lookups works as expected
-			allProviders.put(currentElement, this);
-			return;
-		}
-		this.applyMetrics(currentElement);
-	}
-
-	/**
-	 * @param currentElement
-	 *            the element on which to collect the metrics and recursively descend
-	 */
-	private void applyMetrics(IHierarchicElement currentElement) {
-
-		storedMetrics.put(NUMBER_OF_PORTS, (double)currentElement.getConnectors().size());
-		storedMetrics.put(NUMBER_OF_CONTAINED_ELEMENTS,
-				(double)currentElement.getContainedElements().size());
-		storedMetrics.put(NUMBER_OF_CHANNELS, (double)currentElement.getConnections().size());
-
-		// depth metrics
-		storedMetrics.put(NUMBER_OF_TOTAL_PORTS, (double)currentElement.getConnectors().size());
-		storedMetrics.put(NUMBER_OF_TOTAL_ELEMENTS, 1.0);
-
-		for(IHierarchicElement containedElement : currentElement.getContainedElements()) {
-			HierarchicElementSizeProvider provider = new HierarchicElementSizeProvider();
-			containedProviders.add(provider);
-			provider.apply(containedElement);
-			allProviders.putAll(provider.allProviders);
-
-			for(String key : new String[] {NUMBER_OF_TOTAL_PORTS, NUMBER_OF_TOTAL_ELEMENTS,
-					NUMBER_OF_TOTAL_COMMENTABLE_ELEMENTS, NUMBER_OF_TOTAL_COMMENTED_ELEMENTS}) {
-				storedMetrics.merge(key, provider.storedMetrics.get(key), Double::sum);
-			}
-		}
-
-		allProviders.put(currentElement, this);
-	}
-
-	/** {@inheritDoc} */
-	@Override
-	public String getExampleString() {
-		double commentable = storedMetrics.getOrDefault(
-				HierarchicElementSizeProvider.NUMBER_OF_TOTAL_COMMENTABLE_ELEMENTS, 0.0);
-		double commented = storedMetrics.getOrDefault(
-				HierarchicElementSizeProvider.NUMBER_OF_TOTAL_COMMENTED_ELEMENTS, 0.0);
-
-		// Create a DecimalFormat object to format the percentage
-		DecimalFormat decimalFormat = new DecimalFormat("0.00");
-
-		// Format the percentage value and append the '%' symbol
-		String formattedPercentage = decimalFormat.format((commented / commentable) * 100) + "%";
-
-		return "Commented elements: " + (int)commented + ", Total elements: " + (int)commentable +
-				", Ratio: " + formattedPercentage;
-	}
-
-	/** {@inheritDoc} */
-	@Override
-	public IModelQualityProvider<IHierarchicElement> getProvider(IHierarchicElement element) {
-		return allProviders.get(element);
-	}
-
-	/** {@inheritDoc} */
-	@Override
-	public void traverse(IVisitorModelQualityProvider visitor) {
-
-		// iterate through all contained providers
-		for(HierarchicElementSizeProvider provider : containedProviders) {
-			provider.traverse(visitor);
-		}
-
-		// visit this provider
-		visitor.accept(this);
-	}
-
-	/** {@inheritDoc} */
-	@Override
-	public List<String> metricKeys() {
-		return new ArrayList<>(storedMetrics.keySet());
-	}
-
-	/** {@inheritDoc} */
-	@Override
-	public List<Double> getExampleValues() {
-		List<Double> list = new ArrayList<>();
-		list.add(storedMetrics.get(NUMBER_OF_TOTAL_PORTS));
-		return list;
-	}
-
-	/** {@inheritDoc} */
-	@Override
-	public List<IModelQualityProvider<IHierarchicElement>> getContainedProviders() {
-		List<IModelQualityProvider<IHierarchicElement>> list = new ArrayList<>();
-		list.addAll(containedProviders);
-		return list;
-	}
-
-	/** Returns name. */
-	@Override
-	public String getName() {
-		return name;
-	}
-
-	/*
-	 * 
-	 * CLONE DETECTION START public class CloneDetection {
-	 * 
-	 * private Map<Integer, List<IHierarchicElement>> map = new HashMap<>();
-	 * 
-	 * public void printResult() { System.out.println("Stuff"); }
-	 * 
-	 * public void apply(IHierarchicElement element) { int hash = 1; for(IConnector
-	 * connector : element.getConnectors()) { EList<IModelElementSpecification>
-	 * specifications = connector.getSpecifications(); if(!specifications.isEmpty()
-	 * && connector.getSpecifications().get(0) instanceof PortSpecification) {
-	 * 
-	 * PortSpecification port =
-	 * (PortSpecification)connector.getSpecifications().get(0); hash = 31 * hash +
-	 * (connector instanceof InputPort ? 1 : 2) *
-	 * port.getType().getClass().hashCode(); } else { // Clone Detection for State
-	 * diagrams not supported return; } }map.putIfAbsent(hash,new ArrayList<>());
-	 * 
-	 * List<IHierarchicElement> elements = map.get(hash);
-	 * 
-	 * for( IHierarchicElement element_b:elements) {
-	 * 
-	 * List<String> element_a_input = new ArrayList<String>(); List<String>
-	 * element_b_input = new ArrayList<String>(); List<String> element_a_output =
-	 * new ArrayList<String>(); List<String> element_b_output = new
-	 * ArrayList<String>();
-	 * 
-	 * for(IConnector connector : element.getConnectors()) { PortSpecification port
-	 * = (PortSpecification)connector.getSpecifications().get(0); String type =
-	 * port.getType().getClass().getSimpleName(); if(connector instanceof InputPort)
-	 * { element_a_input.add(type); } else { element_a_output.add(type); } }
-	 * 
-	 * for(IConnector connector : element_b.getConnectors()) { PortSpecification
-	 * port = (PortSpecification)connector.getSpecifications().get(0); String type =
-	 * port.getType().getClass().getSimpleName(); if(connector instanceof InputPort)
-	 * { element_b_input.add(type); } else { element_b_output.add(type); } }
-	 * 
-	 * boolean equals = true;
-	 * 
-	 * for(String type_a_input : element_a_input) {
-	 * if(!element_b_input.remove(type_a_input)) { equals = false; break; }
-	 * 
-	 * }
-	 * 
-	 * for(String type_a_output : element_a_output) {
-	 * if(!element_b_output.remove(type_a_output)) { equals = false; break; }
-	 * 
-	 * } if(equals) { System.out .println("Found duplicate: " +
-	 * ((INamedCommentedElement)element).getName() + ", " +
-	 * ((INamedCommentedElement)element_b).getName()); break; } else {
-	 * System.out.println("Same but not duplicate"); } }elements.add(element); }
-	 * CLONE DETECTION END
-	 * 
-	 * 
-	 * public void printShare(HierarchicElementBase element) {
-	 * 
-	 * Set<Tuple<String, Integer>> counts = new HashSet<>(); this.apply(element);
-	 * counts.add(new Tuple<>("[Self]" + element.getName(), count)); this.count = 0;
-	 * 
-	 * for(IHierarchicElement child : element.getContainedElements()) {
-	 * 
-	 * HierarchicElementBase real_child = (HierarchicElementBase)child;
-	 * 
-	 * recursiveDescent(real_child, this);
-	 * 
-	 * counts.add(new Tuple<>(real_child.getName(), count)); count = 0; }
-	 * 
-	 * double total = counts.stream().mapToInt(t -> t.getElement2()).sum();
-	 * 
-	 * System.out.println("[" + this.getClass().getSimpleName() + "] shares:");
-	 * for(Tuple<String, Integer> tuple : counts) { System.out.println("\t " +
-	 * String.format("%05.2f%%", tuple.element2 / total * 100) + ", " +
-	 * tuple.element2 + ": " + tuple.element1); } }
-	 * 
-	 */
-}
diff --git a/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/service/IModelQualityService.java b/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/service/IModelQualityService.java
index b2e4cfceb..848aa951c 100644
--- a/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/service/IModelQualityService.java
+++ b/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/service/IModelQualityService.java
@@ -15,16 +15,13 @@
 +--------------------------------------------------------------------------*/
 package org.fortiss.tooling.ext.quality.service;
 
-import java.util.Map;
-
-import org.eclipse.emf.ecore.EObject;
+import org.fortiss.tooling.ext.quality.IModelQualityProvider;
 import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
-import org.fortiss.tooling.kernel.model.IProjectRootElement;
 
 /**
- * The migration service checks and upgrades the old models from the last release.
+ * Performs metric analysis
  * 
- * @author mou
+ * @author groh
  */
 public interface IModelQualityService {
 	/** Returns the service instance. */
@@ -35,7 +32,6 @@ public interface IModelQualityService {
 	/** Registers the metric provider with the service. */
 	void registerMetricProvider(IModelQualityProvider<?> provider, Class<?> modelElementClass);
 
-	/** */
-	Map<IProjectRootElement, IModelQualityProvider<? extends EObject>>
-			performMetricAnalysis(ITopLevelElement top);
+	/** analyses the metrics and processes them */
+	void performMetricAnalysis(ITopLevelElement top);
 }
diff --git a/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/service/ModelQualityService.java b/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/service/ModelQualityService.java
index abfac2b2e..82c09021b 100644
--- a/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/service/ModelQualityService.java
+++ b/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/service/ModelQualityService.java
@@ -32,17 +32,17 @@ import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 import org.eclipse.emf.common.util.EList;
 import org.eclipse.emf.ecore.EObject;
 import org.fortiss.tooling.base.model.element.IHierarchicElement;
-import org.fortiss.tooling.ext.quality.service.IModelQualityProvider.IVisitorModelQualityProvider;
+import org.fortiss.tooling.ext.quality.HierarchicElementSizeProvider;
+import org.fortiss.tooling.ext.quality.IModelQualityProvider;
+import org.fortiss.tooling.ext.quality.data.MetricDataManager;
+import org.fortiss.tooling.ext.quality.data.MetricTreeNode;
 import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
 import org.fortiss.tooling.kernel.introspection.IIntrospectionDetailsItem;
 import org.fortiss.tooling.kernel.introspection.IIntrospectionItem;
@@ -79,9 +79,8 @@ public class ModelQualityService extends EObjectAwareServiceBase<IModelQualityPr
 	/** The connector attribute name. */
 	private static final String ATTRIBUTE_NAME = "metricService";
 
-	/** Static Map containing the last result of the metric extraction */
-	public static Map<IProjectRootElement, IModelQualityProvider<? extends EObject>> last_metrics =
-			new HashMap<>();
+	/** Static instance of the MetricDataManager */
+	public static MetricDataManager metricDataManagerInstance = new MetricDataManager();
 
 	/** */
 	@Override
@@ -121,39 +120,32 @@ public class ModelQualityService extends EObjectAwareServiceBase<IModelQualityPr
 	/**
 	 * @param topLvl
 	 *            the file project on which the analysis should be performed
-	 * @return result resulting metrics
 	 */
 	@Override
-	public Map<IProjectRootElement, IModelQualityProvider<? extends EObject>>
-			performMetricAnalysis(ITopLevelElement topLvl) {
-		Map<IProjectRootElement, IModelQualityProvider<? extends EObject>> result = new HashMap<>();
+	public void performMetricAnalysis(ITopLevelElement topLvl) {
+
 		for(IProjectRootElement rootElement : EcoreUtils
 				.getChildrenWithType(topLvl.getRootModelElement(), IProjectRootElement.class)) {
 			if(rootElement instanceof IHierarchicElement) {
-				// TODO check get(0)
+
 				EList<IHierarchicElement> elements =
 						((IHierarchicElement)rootElement).getContainedElements();
 				if(elements.isEmpty()) {
 					continue;
 				}
+				var root_nodes = metricDataManagerInstance.getRootNodes();
+
 				// Get first element, there should not be any other elements
 				IHierarchicElement firstNode = elements.get(0);
-				
+				MetricTreeNode root_node = new MetricTreeNode();
 				HierarchicElementSizeProvider hes = new HierarchicElementSizeProvider();
-				hes.apply(firstNode);
-				System.out.println("checked in hierarchic metrics for: " + rootElement.getName());
-				double commentable = hes.getStoredMetrics().getOrDefault(
-						HierarchicElementSizeProvider.NUMBER_OF_TOTAL_COMMENTABLE_ELEMENTS, 0.0);
-				double commented = hes.getStoredMetrics().getOrDefault(
-						HierarchicElementSizeProvider.NUMBER_OF_TOTAL_COMMENTED_ELEMENTS, 0.0);
-				System.out.println("Commented to total: " + commented + ", " + commentable + ", " +
-						commented / commentable);
-				result.put(rootElement, hes);
+				hes.apply(metricDataManagerInstance, root_node, firstNode);
+				root_nodes.put(rootElement, root_node);
 			}
 		}
-		result.forEach((k, v) -> last_metrics.merge(k, v, (oldValue, newValue) -> newValue));
-		metricExtractionToCSV(result);
-		return result;
+		// result.forEach((k, v) -> last_metrics.merge(k, v, (oldValue, newValue) -> newValue));
+		// metricExtractionToCSV(result);
+		// return result;
 	}
 
 	/** */
@@ -237,7 +229,8 @@ public class ModelQualityService extends EObjectAwareServiceBase<IModelQualityPr
 			if(createNewIndex) {
 				// Create new index and write it into the first line of the file
 				var anyProvider = data.values().iterator().next();
-				List<String> keys = anyProvider.metricKeys();
+				// List<String> keys = anyProvider.metricKeys();
+				List<String> keys = new ArrayList<String>();
 				allKeys.add("timestamp");
 				allKeys.add("root");
 				allKeys.add("node");
@@ -259,29 +252,29 @@ public class ModelQualityService extends EObjectAwareServiceBase<IModelQualityPr
 				// iterate over all project roots
 				String rootName = rootProject.getName();
 
-				rootProvider.traverse(new IVisitorModelQualityProvider() {
-
-					@Override
-					public void accept(HierarchicElementSizeProvider provider) {
-
-						var metrics = provider.getStoredMetrics();
-						// These 4 data entries are just concatenated in front
-						var startStream = Stream.of(formattedDateTime, rootName, "null", "null");
-						// Collect all values from provider in the correct order and combine
-						var values = Stream
-								.concat(startStream,
-										valueKeys.stream().map(metrics::get).map(String::valueOf))
-								.collect(Collectors.joining(","));
-
-						try {
-							// write values
-							writer.write(values);
-							writer.write("\n");
-						} catch(IOException e) {
-							e.printStackTrace();
-						}
-					}
-				});
+				// rootProvider.traverse(new IVisitorModelQualityProvider() {
+				//
+				// @Override
+				// public void accept(HierarchicElementSizeProvider provider) {
+				//
+				// var metrics = provider.getStoredMetrics();
+				// // These 4 data entries are just concatenated in front
+				// var startStream = Stream.of(formattedDateTime, rootName, "null", "null");
+				// // Collect all values from provider in the correct order and combine
+				// var values = Stream
+				// .concat(startStream,
+				// valueKeys.stream().map(metrics::get).map(String::valueOf))
+				// .collect(Collectors.joining(","));
+				//
+				// try {
+				// // write values
+				// writer.write(values);
+				// writer.write("\n");
+				// } catch(IOException e) {
+				// e.printStackTrace();
+				// }
+				// }
+				// });
 			});
 		} catch(IOException e) {
 			e.printStackTrace();
-- 
GitLab