Skip to content
Snippets Groups Projects
Commit 98beda1d authored by Eddie Groh's avatar Eddie Groh
Browse files

Refactored the data structure storing the metric data

Issue-Ref: 4310
Issue-Url: af3#4310



Signed-off-by: default avatarEddie Groh <groh@fortiss.org>
parent f731e7d5
No related branches found
No related tags found
1 merge request!210Setting up Metric extraction plugin for AF3 : Issue 4310
Showing
with 475 additions and 145 deletions
...@@ -82,7 +82,6 @@ public class ModelQualityExtractionMenu implements IContextMenuContributor { ...@@ -82,7 +82,6 @@ public class ModelQualityExtractionMenu implements IContextMenuContributor {
public void run() { public void run() {
ITopLevelElement top = IPersistencyService.getInstance().getTopLevelElementFor(this.fp); ITopLevelElement top = IPersistencyService.getInstance().getTopLevelElementFor(this.fp);
IModelQualityService.getInstance().performMetricAnalysis(top); IModelQualityService.getInstance().performMetricAnalysis(top);
System.out.println("We print something");
} }
} }
} }
...@@ -41,7 +41,7 @@ import org.fortiss.tooling.common.ui.javafx.layout.CompositeFXControllerBase; ...@@ -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.FillStyle;
import org.fortiss.tooling.common.ui.javafx.style.FontStyle; import org.fortiss.tooling.common.ui.javafx.style.FontStyle;
import org.fortiss.tooling.common.ui.javafx.style.LineStyle; 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.ext.quality.service.ModelQualityService;
import org.fortiss.tooling.kernel.model.IProjectRootElement; import org.fortiss.tooling.kernel.model.IProjectRootElement;
import org.fortiss.tooling.spiderchart.control.SpiderChartViewer; import org.fortiss.tooling.spiderchart.control.SpiderChartViewer;
...@@ -111,8 +111,8 @@ public class MetricsFXController extends CompositeFXControllerBase<SplitPane, No ...@@ -111,8 +111,8 @@ public class MetricsFXController extends CompositeFXControllerBase<SplitPane, No
public void selectionChanged(IWorkbenchPart part, ISelection selection) { public void selectionChanged(IWorkbenchPart part, ISelection selection) {
ModelQualityService.getInstance(); ModelQualityService.getInstance();
var last_metrics = ModelQualityService.last_metrics; var manager = ModelQualityService.metricDataManagerInstance;
if(last_metrics == null) { if(manager == null) {
topLabel.setText( topLabel.setText(
"No Metrics were available at " + timeFormat.format(LocalDateTime.now())); "No Metrics were available at " + timeFormat.format(LocalDateTime.now()));
return; return;
...@@ -144,7 +144,7 @@ public class MetricsFXController extends CompositeFXControllerBase<SplitPane, No ...@@ -144,7 +144,7 @@ public class MetricsFXController extends CompositeFXControllerBase<SplitPane, No
} }
if(selected instanceof IHierarchicElement) { if(selected instanceof IHierarchicElement) {
var root_provider = last_metrics.get(currentRootElement); var root_provider = manager.getRootNodes().get(currentRootElement);
if(root_provider == null) { if(root_provider == null) {
topLabel.setText("No Metric found for this project, did you export metrics?"); topLabel.setText("No Metric found for this project, did you export metrics?");
...@@ -152,24 +152,22 @@ public class MetricsFXController extends CompositeFXControllerBase<SplitPane, No ...@@ -152,24 +152,22 @@ public class MetricsFXController extends CompositeFXControllerBase<SplitPane, No
} }
var element = (IHierarchicElement)selected; var element = (IHierarchicElement)selected;
var provider = root_provider.getProvider(element); var node = manager.getHierarchicLookupTable().get(element);
if(provider != null) { if(node != null) {
var string = provider.getExampleString(); topLabel.setText("Text");
topLabel.setText(string);
if(!provider.getContainedProviders().isEmpty()) { if(!node.getChildren().isEmpty()) {
SpiderChartViewer viewer = SpiderChartViewer viewer = buildSpiderChart(node);
buildSpiderChart((IModelQualityProvider<IHierarchicElement>)provider);
borderPane.setCenter(viewer.getViewerPane()); borderPane.setCenter(viewer.getViewerPane());
// Create PieChart and add data // Create PieChart and add data
pieChart.getData().clear(); pieChart.getData().clear();
for(var prov : provider.getContainedProviders()) { for(var child : node.getChildren()) {
PieChart.Data slice = new PieChart.Data(prov.getName(), PieChart.Data slice =
((IModelQualityProvider<?>)prov).getExampleValues().get(0)); new PieChart.Data(child.getName(), child.getTotalPortAmount());
pieChart.getData().add(slice); pieChart.getData().add(slice);
pieChart.setLegendVisible(false); pieChart.setLegendVisible(false);
pieChart.setTitle(""); pieChart.setTitle("");
...@@ -202,37 +200,34 @@ public class MetricsFXController extends CompositeFXControllerBase<SplitPane, No ...@@ -202,37 +200,34 @@ public class MetricsFXController extends CompositeFXControllerBase<SplitPane, No
* the provider for which the spider chart should be generated * the provider for which the spider chart should be generated
* @return {@link SpiderChartViewer} with the matching metrics * @return {@link SpiderChartViewer} with the matching metrics
*/ */
private static SpiderChartViewer private static SpiderChartViewer buildSpiderChart(MetricTreeNode node) {
buildSpiderChart(IModelQualityProvider<IHierarchicElement> provider) {
SpiderChart spiderChart = new SpiderChart(); SpiderChart spiderChart = new SpiderChart();
spiderChart.setTitle("Smartphone Comparison Scale"); spiderChart.setTitle("Amount of Ports");
spiderChart.setLegendLabel("Legend"); spiderChart.setLegendLabel("Legend");
ChartStyle chartStyle = new ChartStyle(true, true, true); ChartStyle chartStyle = new ChartStyle(true, true, true);
List<IModelQualityProvider<IHierarchicElement>> containedProviders = List<MetricTreeNode> children = node.getChildren();
provider.getContainedProviders();
if(containedProviders.isEmpty()) { if(children.isEmpty()) {
return null; return null;
} }
double maxval = containedProviders.stream().mapToDouble(p -> p.getExampleValues().get(0)) double maxval =
.max().getAsDouble(); children.stream().mapToDouble(p -> p.getTotalPortAmount()).max().getAsDouble();
chartStyle.setUseIndividualAxisSegments(false); chartStyle.setUseIndividualAxisSegments(false);
chartStyle.setTitleStyle(new FontStyle("Verdana", 14, BLUE.brighter())); chartStyle.setTitleStyle(new FontStyle("Verdana", 14, BLUE.brighter()));
DataSeries elementData = new DataSeries("Data"); DataSeries elementData = new DataSeries("Data");
for(var prov : containedProviders) { for(var child : node.getChildren()) {
DoubleAxis testing = new DoubleAxis(prov.getName(), 0.0, maxval); DoubleAxis testing = new DoubleAxis(child.getName(), 0.0, maxval);
AxisStyle aStyle3Segs = new AxisStyle(SOLID_BLACK_1PT, BLACK_VERDANA_14PT, 3, AxisStyle aStyle3Segs = new AxisStyle(SOLID_BLACK_1PT, BLACK_VERDANA_14PT, 3,
BLACK_VERDANA_8PT, new DecimalFormat("#.##")); BLACK_VERDANA_8PT, new DecimalFormat("#.##"));
chartStyle.setAxisStyle(testing, aStyle3Segs); chartStyle.setAxisStyle(testing, aStyle3Segs);
spiderChart.addAxis(testing); spiderChart.addAxis(testing);
elementData.setPoint(testing, elementData.setPoint(testing, child.getTotalPortAmount());
((IModelQualityProvider<?>)prov).getExampleValues().get(0));
} }
spiderChart.addData(elementData); spiderChart.addData(elementData);
......
...@@ -13,5 +13,6 @@ Require-Bundle: org.eclipse.core.runtime, ...@@ -13,5 +13,6 @@ Require-Bundle: org.eclipse.core.runtime,
org.fortiss.tooling.kernel;visibility:=reexport, org.fortiss.tooling.kernel;visibility:=reexport,
org.fortiss.af3.project org.fortiss.af3.project
Export-Package: org.fortiss.tooling.ext.quality, Export-Package: org.fortiss.tooling.ext.quality,
org.fortiss.tooling.ext.quality.data,
org.fortiss.tooling.ext.quality.service org.fortiss.tooling.ext.quality.service
...@@ -18,7 +18,6 @@ package org.fortiss.tooling.ext.quality; ...@@ -18,7 +18,6 @@ package org.fortiss.tooling.ext.quality;
import org.eclipse.core.runtime.Plugin; import org.eclipse.core.runtime.Plugin;
import org.fortiss.tooling.base.model.element.IHierarchicElement; 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.IModelQualityService;
import org.fortiss.tooling.ext.quality.service.ModelQualityService; import org.fortiss.tooling.ext.quality.service.ModelQualityService;
import org.osgi.framework.BundleContext; import org.osgi.framework.BundleContext;
......
...@@ -13,17 +13,14 @@ ...@@ -13,17 +13,14 @@
| See the License for the specific language governing permissions and | | See the License for the specific language governing permissions and |
| limitations under the License. | | limitations under the License. |
+--------------------------------------------------------------------------*/ +--------------------------------------------------------------------------*/
package org.fortiss.tooling.ext.quality.service; package org.fortiss.tooling.ext.quality;
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 java.util.Optional;
import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.EList;
import org.fortiss.tooling.base.model.element.IHierarchicElement; 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; import org.fortiss.tooling.kernel.model.INamedCommentedElement;
/** /**
...@@ -61,54 +58,37 @@ public class HierarchicElementSizeProvider implements IModelQualityProvider<IHie ...@@ -61,54 +58,37 @@ public class HierarchicElementSizeProvider implements IModelQualityProvider<IHie
/** Key for the metric counting the total amount of elements which are commented */ /** Key for the metric counting the total amount of elements which are commented */
public static final String NUMBER_OF_TOTAL_COMMENTED_ELEMENTS = public static final String NUMBER_OF_TOTAL_COMMENTED_ELEMENTS =
"numberOfTotalCommentedElements"; "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 * Key for the metric counting the total amount of elements which do not contain other elements
*/ */
private Map<IHierarchicElement, HierarchicElementSizeProvider> allProviders; public static final String NUMBER_OF_TOTAL_LEAF_ELEMENTS = "numberOfTotalLeafElements";
/** Variable storing the name */
private String name;
/** /**
* @return Map containing the mapping between a metric keys and the corresponding values for * List containing all HierarchicElementSizeProvider for components inside the
* this element * IHierarchicElement
*/ */
public Map<String, Double> getStoredMetrics() {
return storedMetrics;
}
/** */ /** */
public HierarchicElementSizeProvider() { public HierarchicElementSizeProvider() {
super(); super();
this.storedMetrics = new HashMap<>();
this.allProviders = new HashMap<>();
this.containedProviders = new ArrayList<>();
this.name = null;
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void apply(IHierarchicElement currentElement) { public void apply(MetricDataManager manager, MetricTreeNode node,
IHierarchicElement currentElement) {
var metrics = node.getStoredMetrics();
boolean isElementCommentable = currentElement instanceof INamedCommentedElement; boolean isElementCommentable = currentElement instanceof INamedCommentedElement;
storedMetrics.put(NUMBER_OF_TOTAL_COMMENTABLE_ELEMENTS, isElementCommentable ? 1.0 : 0.0); metrics.put(NUMBER_OF_TOTAL_COMMENTABLE_ELEMENTS, isElementCommentable ? 1.0 : 0.0);
String comment = String comment =
isElementCommentable ? ((INamedCommentedElement)currentElement).getComment() : null; isElementCommentable ? ((INamedCommentedElement)currentElement).getComment() : null;
storedMetrics.put(NUMBER_OF_TOTAL_COMMENTED_ELEMENTS, metrics.put(NUMBER_OF_TOTAL_COMMENTED_ELEMENTS,
comment != null && comment != "" ? 1.0 : 0.0); comment != null && comment != "" ? 1.0 : 0.0);
if(isElementCommentable) { if(isElementCommentable) {
this.name = ((INamedCommentedElement)currentElement).getName(); node.setName(((INamedCommentedElement)currentElement).getName());
} else { } else {
this.name = "Unnamable Element"; node.setName("Unnamable Element");
} }
// Check if any of the specifications is an IHierarchicElement // Check if any of the specifications is an IHierarchicElement
...@@ -124,188 +104,60 @@ public class HierarchicElementSizeProvider implements IModelQualityProvider<IHie ...@@ -124,188 +104,60 @@ public class HierarchicElementSizeProvider implements IModelQualityProvider<IHie
specificationElement.getContainedElements(); specificationElement.getContainedElements();
if(containedElements.size() == 1) { if(containedElements.size() == 1) {
// Add reference from the element to this, so the lookups works as expected // Add reference from the element to this, so the lookups works as expected
allProviders.put(specificationElement, this); manager.getHierarchicLookupTable().put(specificationElement, node);
// Skip the specification element to get a more useful tree structure // Skip the specification element to get a more useful tree structure
this.applyMetrics(containedElements.get(0)); this.applyMetrics(manager, node, containedElements.get(0));
} else { } else {
this.applyMetrics(specificationElement); this.applyMetrics(manager, node, specificationElement);
} }
// Add reference from the element to this, so the lookups works as expected // Add reference from the element to this, so the lookups works as expected
allProviders.put(currentElement, this); manager.getHierarchicLookupTable().put(currentElement, node);
return; return;
} }
this.applyMetrics(currentElement); this.applyMetrics(manager, node, currentElement);
} }
/** /**
* @param manager
* for saving the lookup data
* @param node
* for saving the metric data
* @param currentElement * @param currentElement
* the element on which to collect the metrics and recursively descend * the element on which to collect data
*/ */
private void applyMetrics(IHierarchicElement currentElement) { 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();
storedMetrics.put(NUMBER_OF_PORTS, (double)currentElement.getConnectors().size()); metrics.put(NUMBER_OF_PORTS, (double)currentElement.getConnectors().size());
storedMetrics.put(NUMBER_OF_CONTAINED_ELEMENTS, metrics.put(NUMBER_OF_CONTAINED_ELEMENTS,
(double)currentElement.getContainedElements().size()); (double)currentElement.getContainedElements().size());
storedMetrics.put(NUMBER_OF_CHANNELS, (double)currentElement.getConnections().size()); metrics.put(NUMBER_OF_CHANNELS, (double)currentElement.getConnections().size());
// depth metrics // depth metrics
storedMetrics.put(NUMBER_OF_TOTAL_PORTS, (double)currentElement.getConnectors().size()); metrics.put(NUMBER_OF_TOTAL_PORTS, (double)currentElement.getConnectors().size());
storedMetrics.put(NUMBER_OF_TOTAL_ELEMENTS, 1.0); 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()) { for(IHierarchicElement containedElement : currentElement.getContainedElements()) {
HierarchicElementSizeProvider provider = new HierarchicElementSizeProvider(); MetricTreeNode child = new MetricTreeNode();
containedProviders.add(provider); node.getChildren().add(child);
provider.apply(containedElement); apply(manager, child, containedElement);
allProviders.putAll(provider.allProviders);
for(String key : new String[] {NUMBER_OF_TOTAL_PORTS, NUMBER_OF_TOTAL_ELEMENTS, 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_COMMENTABLE_ELEMENTS, NUMBER_OF_TOTAL_COMMENTED_ELEMENTS,
storedMetrics.merge(key, provider.storedMetrics.get(key), Double::sum); NUMBER_OF_TOTAL_LEAF_ELEMENTS}) {
metrics.merge(key, child.getStoredMetrics().get(key), Double::sum);
} }
} }
allProviders.put(currentElement, this); manager.getHierarchicLookupTable().put(currentElement, node);
}
/** {@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); } }
*
*/
} }
...@@ -13,12 +13,12 @@ ...@@ -13,12 +13,12 @@
| See the License for the specific language governing permissions and | | See the License for the specific language governing permissions and |
| limitations under the License. | | limitations under the License. |
+--------------------------------------------------------------------------*/ +--------------------------------------------------------------------------*/
package org.fortiss.tooling.ext.quality.service; package org.fortiss.tooling.ext.quality;
import java.util.List;
import org.eclipse.emf.ecore.EObject; 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; import org.fortiss.tooling.kernel.service.base.IEObjectAware;
/** /**
...@@ -31,59 +31,5 @@ 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> { public interface IModelQualityProvider<C extends EObject> extends IEObjectAware<EObject> {
/** Applies the IMetricProvider to the given model element. */ /** Applies the IMetricProvider to the given model element. */
void apply(C element); void apply(MetricDataManager manager, MetricTreeNode node, 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);
}
} }
/*-------------------------------------------------------------------------+
| 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;
}
}
/*-------------------------------------------------------------------------+
| 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
}
/*-------------------------------------------------------------------------+
| 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;
}
}
/*-------------------------------------------------------------------------+
| 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");
}
}
...@@ -15,16 +15,13 @@ ...@@ -15,16 +15,13 @@
+--------------------------------------------------------------------------*/ +--------------------------------------------------------------------------*/
package org.fortiss.tooling.ext.quality.service; package org.fortiss.tooling.ext.quality.service;
import java.util.Map; import org.fortiss.tooling.ext.quality.IModelQualityProvider;
import org.eclipse.emf.ecore.EObject;
import org.fortiss.tooling.kernel.extension.data.ITopLevelElement; 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 { public interface IModelQualityService {
/** Returns the service instance. */ /** Returns the service instance. */
...@@ -35,7 +32,6 @@ public interface IModelQualityService { ...@@ -35,7 +32,6 @@ public interface IModelQualityService {
/** Registers the metric provider with the service. */ /** Registers the metric provider with the service. */
void registerMetricProvider(IModelQualityProvider<?> provider, Class<?> modelElementClass); void registerMetricProvider(IModelQualityProvider<?> provider, Class<?> modelElementClass);
/** */ /** analyses the metrics and processes them */
Map<IProjectRootElement, IModelQualityProvider<? extends EObject>> void performMetricAnalysis(ITopLevelElement top);
performMetricAnalysis(ITopLevelElement top);
} }
...@@ -32,17 +32,17 @@ import java.time.format.DateTimeFormatter; ...@@ -32,17 +32,17 @@ import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; 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.common.util.EList;
import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EObject;
import org.fortiss.tooling.base.model.element.IHierarchicElement; 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.extension.data.ITopLevelElement;
import org.fortiss.tooling.kernel.introspection.IIntrospectionDetailsItem; import org.fortiss.tooling.kernel.introspection.IIntrospectionDetailsItem;
import org.fortiss.tooling.kernel.introspection.IIntrospectionItem; import org.fortiss.tooling.kernel.introspection.IIntrospectionItem;
...@@ -79,9 +79,8 @@ public class ModelQualityService extends EObjectAwareServiceBase<IModelQualityPr ...@@ -79,9 +79,8 @@ public class ModelQualityService extends EObjectAwareServiceBase<IModelQualityPr
/** The connector attribute name. */ /** The connector attribute name. */
private static final String ATTRIBUTE_NAME = "metricService"; private static final String ATTRIBUTE_NAME = "metricService";
/** Static Map containing the last result of the metric extraction */ /** Static instance of the MetricDataManager */
public static Map<IProjectRootElement, IModelQualityProvider<? extends EObject>> last_metrics = public static MetricDataManager metricDataManagerInstance = new MetricDataManager();
new HashMap<>();
/** */ /** */
@Override @Override
...@@ -121,39 +120,32 @@ public class ModelQualityService extends EObjectAwareServiceBase<IModelQualityPr ...@@ -121,39 +120,32 @@ public class ModelQualityService extends EObjectAwareServiceBase<IModelQualityPr
/** /**
* @param topLvl * @param topLvl
* the file project on which the analysis should be performed * the file project on which the analysis should be performed
* @return result resulting metrics
*/ */
@Override @Override
public Map<IProjectRootElement, IModelQualityProvider<? extends EObject>> public void performMetricAnalysis(ITopLevelElement topLvl) {
performMetricAnalysis(ITopLevelElement topLvl) {
Map<IProjectRootElement, IModelQualityProvider<? extends EObject>> result = new HashMap<>();
for(IProjectRootElement rootElement : EcoreUtils for(IProjectRootElement rootElement : EcoreUtils
.getChildrenWithType(topLvl.getRootModelElement(), IProjectRootElement.class)) { .getChildrenWithType(topLvl.getRootModelElement(), IProjectRootElement.class)) {
if(rootElement instanceof IHierarchicElement) { if(rootElement instanceof IHierarchicElement) {
// TODO check get(0)
EList<IHierarchicElement> elements = EList<IHierarchicElement> elements =
((IHierarchicElement)rootElement).getContainedElements(); ((IHierarchicElement)rootElement).getContainedElements();
if(elements.isEmpty()) { if(elements.isEmpty()) {
continue; continue;
} }
var root_nodes = metricDataManagerInstance.getRootNodes();
// Get first element, there should not be any other elements // Get first element, there should not be any other elements
IHierarchicElement firstNode = elements.get(0); IHierarchicElement firstNode = elements.get(0);
MetricTreeNode root_node = new MetricTreeNode();
HierarchicElementSizeProvider hes = new HierarchicElementSizeProvider(); HierarchicElementSizeProvider hes = new HierarchicElementSizeProvider();
hes.apply(firstNode); hes.apply(metricDataManagerInstance, root_node, firstNode);
System.out.println("checked in hierarchic metrics for: " + rootElement.getName()); root_nodes.put(rootElement, root_node);
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);
} }
} }
result.forEach((k, v) -> last_metrics.merge(k, v, (oldValue, newValue) -> newValue)); // result.forEach((k, v) -> last_metrics.merge(k, v, (oldValue, newValue) -> newValue));
metricExtractionToCSV(result); // metricExtractionToCSV(result);
return result; // return result;
} }
/** */ /** */
...@@ -237,7 +229,8 @@ public class ModelQualityService extends EObjectAwareServiceBase<IModelQualityPr ...@@ -237,7 +229,8 @@ public class ModelQualityService extends EObjectAwareServiceBase<IModelQualityPr
if(createNewIndex) { if(createNewIndex) {
// Create new index and write it into the first line of the file // Create new index and write it into the first line of the file
var anyProvider = data.values().iterator().next(); 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("timestamp");
allKeys.add("root"); allKeys.add("root");
allKeys.add("node"); allKeys.add("node");
...@@ -259,29 +252,29 @@ public class ModelQualityService extends EObjectAwareServiceBase<IModelQualityPr ...@@ -259,29 +252,29 @@ public class ModelQualityService extends EObjectAwareServiceBase<IModelQualityPr
// iterate over all project roots // iterate over all project roots
String rootName = rootProject.getName(); String rootName = rootProject.getName();
rootProvider.traverse(new IVisitorModelQualityProvider() { // rootProvider.traverse(new IVisitorModelQualityProvider() {
//
@Override // @Override
public void accept(HierarchicElementSizeProvider provider) { // public void accept(HierarchicElementSizeProvider provider) {
//
var metrics = provider.getStoredMetrics(); // var metrics = provider.getStoredMetrics();
// These 4 data entries are just concatenated in front // // These 4 data entries are just concatenated in front
var startStream = Stream.of(formattedDateTime, rootName, "null", "null"); // var startStream = Stream.of(formattedDateTime, rootName, "null", "null");
// Collect all values from provider in the correct order and combine // // Collect all values from provider in the correct order and combine
var values = Stream // var values = Stream
.concat(startStream, // .concat(startStream,
valueKeys.stream().map(metrics::get).map(String::valueOf)) // valueKeys.stream().map(metrics::get).map(String::valueOf))
.collect(Collectors.joining(",")); // .collect(Collectors.joining(","));
//
try { // try {
// write values // // write values
writer.write(values); // writer.write(values);
writer.write("\n"); // writer.write("\n");
} catch(IOException e) { // } catch(IOException e) {
e.printStackTrace(); // e.printStackTrace();
} // }
} // }
}); // });
}); });
} catch(IOException e) { } catch(IOException e) {
e.printStackTrace(); e.printStackTrace();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment