From 9207c5c23a943e4a130e9173637c3d7129c98ab8 Mon Sep 17 00:00:00 2001 From: Eddie Groh <groh@fortiss.org> Date: Mon, 26 Jun 2023 12:18:09 +0200 Subject: [PATCH] Added basic metric view functionality Issue-Ref: 4310 Issue-Url: https://git.fortiss.org/af3/af3/-/issues/4310 Signed-off-by: Eddie Groh <groh@fortiss.org> --- .../META-INF/MANIFEST.MF | 1 + .../build.properties | 6 +- .../ext/quality/ui/view/fx/MetricsViewFx.fxml | 2 +- .../ui/view/fx/MetricsFXController.java | 67 ++++++++++++++- .../quality/ui/view/fx/MetricsFXViewPart.java | 12 +++ .../build.properties | 3 +- .../html/developer/documentation.html | 12 +++ org.fortiss.tooling.ext.quality/plugin.xml | 5 -- .../HierarchicElementSizeProvider.java | 84 ++++++++++++++----- .../service/IModelQualityProvider.java | 13 +++ .../quality/service/ModelQualityService.java | 51 ++++++----- 11 files changed, 201 insertions(+), 55 deletions(-) create mode 100644 org.fortiss.tooling.ext.quality/html/developer/documentation.html delete mode 100644 org.fortiss.tooling.ext.quality/plugin.xml diff --git a/org.fortiss.tooling.ext.quality.ui/META-INF/MANIFEST.MF b/org.fortiss.tooling.ext.quality.ui/META-INF/MANIFEST.MF index 22a3e7f38..a45f40120 100644 --- a/org.fortiss.tooling.ext.quality.ui/META-INF/MANIFEST.MF +++ b/org.fortiss.tooling.ext.quality.ui/META-INF/MANIFEST.MF @@ -15,3 +15,4 @@ Require-Bundle: org.eclipse.ui.ide;visibility:=reexport, org.eclipse.emf.ecore, org.fortiss.tooling.ext.quality Import-Package: org.fortiss.af3.project.model +Export-Package: org.fortiss.tooling.ext.quality.ui.view.fx diff --git a/org.fortiss.tooling.ext.quality.ui/build.properties b/org.fortiss.tooling.ext.quality.ui/build.properties index 34d2e4d2d..890c18242 100644 --- a/org.fortiss.tooling.ext.quality.ui/build.properties +++ b/org.fortiss.tooling.ext.quality.ui/build.properties @@ -1,4 +1,6 @@ -source.. = src/ +source.. = src/,\ + res/ output.. = bin/ bin.includes = META-INF/,\ - . + .,\ + plugin.xml diff --git a/org.fortiss.tooling.ext.quality.ui/res/org/fortiss/tooling/ext/quality/ui/view/fx/MetricsViewFx.fxml b/org.fortiss.tooling.ext.quality.ui/res/org/fortiss/tooling/ext/quality/ui/view/fx/MetricsViewFx.fxml index f3d4a50e9..16e161e79 100644 --- a/org.fortiss.tooling.ext.quality.ui/res/org/fortiss/tooling/ext/quality/ui/view/fx/MetricsViewFx.fxml +++ b/org.fortiss.tooling.ext.quality.ui/res/org/fortiss/tooling/ext/quality/ui/view/fx/MetricsViewFx.fxml @@ -19,7 +19,7 @@ prefHeight="25.0" prefWidth="626.0"> <center> <Label fx:id="topLabel" alignment="CENTER" - contentDisplay="CENTER" prefHeight="51.0" prefWidth="247.0" + contentDisplay="CENTER" prefHeight="51.0" prefWidth="500.0" textAlignment="CENTER" BorderPane.alignment="CENTER" /> </center> <left> 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 40f38516d..28533073f 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 @@ -15,9 +15,20 @@ +--------------------------------------------------------------------------*/ package org.fortiss.tooling.ext.quality.ui.view.fx; +import static org.fortiss.tooling.kernel.ui.util.SelectionUtils.checkAndPickFirst; +import static org.fortiss.tooling.kernel.utils.EcoreUtils.getFirstParentWithType; + import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWorkbenchPart; +import org.fortiss.tooling.base.model.element.IHierarchicElement; import org.fortiss.tooling.common.ui.javafx.layout.CompositeFXControllerBase; +import org.fortiss.tooling.ext.quality.service.ModelQualityService; +import org.fortiss.tooling.kernel.model.IProjectRootElement; import javafx.fxml.FXML; import javafx.scene.Node; @@ -32,7 +43,11 @@ import javafx.scene.control.SplitPane; */ @SuppressWarnings("unchecked") -public class MetricsFXController extends CompositeFXControllerBase<SplitPane, Node> { +public class MetricsFXController extends CompositeFXControllerBase<SplitPane, Node> + implements ISelectionListener { + + /** The {@link IProjectRootElement} in which the selected element is contained in. */ + private IProjectRootElement curentRootElement; /** The refresh {@link Button} to refresh the metrics. */ @FXML @@ -54,7 +69,55 @@ public class MetricsFXController extends CompositeFXControllerBase<SplitPane, No /** {@inheritDoc} */ @Override public void initialize() { - + // Not used + } + + /** {@inheritDoc} */ + @Override + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + + ModelQualityService.getInstance(); + var last_metrics = ModelQualityService.last_metrics; + if(last_metrics == null) { + topLabel.setText( + "No Metrics were available at " + timeFormat.format(LocalDateTime.now())); + return; + } + + EObject selected = checkAndPickFirst(selection, EObject.class); + + if(selected == null) { + topLabel.setText("Nothing selected"); + return; + } + + if(selected instanceof IProjectRootElement) { + curentRootElement = (IProjectRootElement)selected; + } else { + curentRootElement = getFirstParentWithType(selected, IProjectRootElement.class); + } + + if(curentRootElement == null) { + // There was no root element for the selected element. (Usually should be the + // FileProject.) This is not displayed here. + topLabel.setText("No root found"); + return; + } + + if(selected instanceof IHierarchicElement) { + var root_provider = last_metrics.get(curentRootElement); + var element = (IHierarchicElement)selected; + var provider = root_provider.getProvider(element); + if(provider != null) { + + var string = provider.getExampleString(); + topLabel.setText(string); + } else { + topLabel.setText("Element not in metrics"); + } + } else { + topLabel.setText("Not a IHierarchicElement"); + } } /** diff --git a/org.fortiss.tooling.ext.quality.ui/src/org/fortiss/tooling/ext/quality/ui/view/fx/MetricsFXViewPart.java b/org.fortiss.tooling.ext.quality.ui/src/org/fortiss/tooling/ext/quality/ui/view/fx/MetricsFXViewPart.java index d422973c6..470c3736e 100644 --- a/org.fortiss.tooling.ext.quality.ui/src/org/fortiss/tooling/ext/quality/ui/view/fx/MetricsFXViewPart.java +++ b/org.fortiss.tooling.ext.quality.ui/src/org/fortiss/tooling/ext/quality/ui/view/fx/MetricsFXViewPart.java @@ -18,6 +18,8 @@ package org.fortiss.tooling.ext.quality.ui.view.fx; import org.eclipse.ui.part.ViewPart; import org.fortiss.tooling.common.ui.javafx.AF3FXViewPart; +import javafx.scene.Scene; + /** * {@link ViewPart} for the FX implementation of the metrics view. * @@ -47,4 +49,14 @@ public class MetricsFXViewPart extends AF3FXViewPart implements IMetricsViewPart return VIEW_CONTROLLER; } + /** {@inheritDoc} */ + @Override + protected Scene createFxScene() { + Scene scene = super.createFxScene(); + + getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(VIEW_CONTROLLER); + + return scene; + } + } diff --git a/org.fortiss.tooling.ext.quality/build.properties b/org.fortiss.tooling.ext.quality/build.properties index 25fdb6e84..9ce7c73b0 100644 --- a/org.fortiss.tooling.ext.quality/build.properties +++ b/org.fortiss.tooling.ext.quality/build.properties @@ -4,5 +4,4 @@ source.. = src/,\ test-src/ bin.includes = .,\ - META-INF/,\ - plugin.xml + META-INF/ diff --git a/org.fortiss.tooling.ext.quality/html/developer/documentation.html b/org.fortiss.tooling.ext.quality/html/developer/documentation.html new file mode 100644 index 000000000..d8e07a13f --- /dev/null +++ b/org.fortiss.tooling.ext.quality/html/developer/documentation.html @@ -0,0 +1,12 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> +<head> +</head> + +<body lang="en-US" dir="ltr"> +<h1>Developer Documentation for <i>Quality Functionality +(</i><i>org.fortiss.tooling.ext.quality</i><i>)</i></h1> +<p>Lorem Ipsum</p> + +</body> +</html> \ No newline at end of file diff --git a/org.fortiss.tooling.ext.quality/plugin.xml b/org.fortiss.tooling.ext.quality/plugin.xml deleted file mode 100644 index 5535690d3..000000000 --- a/org.fortiss.tooling.ext.quality/plugin.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<?eclipse version="3.4"?> -<plugin> - -</plugin> 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 index f0a2fbbc7..00dc10296 100644 --- 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 @@ -15,26 +15,21 @@ +--------------------------------------------------------------------------*/ package org.fortiss.tooling.ext.quality.service; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; -import org.eclipse.emf.common.util.EList; -import org.fortiss.tooling.base.model.base.HierarchicElementBase; -import org.fortiss.tooling.base.model.element.IConnector; import org.fortiss.tooling.base.model.element.IHierarchicElement; -import org.fortiss.tooling.base.model.element.IModelElementSpecification; import org.fortiss.tooling.kernel.model.INamedCommentedElement; -import org.fortiss.tooling.kernel.model.INamedElement; /** * {@link IModelQualityProvider} to count the ratio of filled out comments of * INamedCommentedElements. * * @author blaschke + * @author groh */ public class HierarchicElementSizeProvider implements IModelQualityProvider<IHierarchicElement> { /** @@ -45,14 +40,25 @@ public class HierarchicElementSizeProvider implements IModelQualityProvider<IHie * 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"; - public static final String NUMBER_OF_TOTAL_COMMENTABLE_ELEMENTS = "numberOfTotalCommentableElements"; - public static final String NUMBER_OF_TOTAL_COMMENTED_ELEMENTS = "numberOfTotalCommentedElements"; + /** 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; @@ -62,6 +68,15 @@ public class HierarchicElementSizeProvider implements IModelQualityProvider<IHie */ private List<HierarchicElementSizeProvider> containedProviders; + /** + * Mapping containing all providers from this element and any elements contained in that element + */ + private Map<IHierarchicElement, HierarchicElementSizeProvider> allProviders; + + /** + * @return Map containing the mapping between a metric keys and the corresponding values for + * this element + */ public Map<String, Double> getStoredMetrics() { return storedMetrics; } @@ -70,6 +85,7 @@ public class HierarchicElementSizeProvider implements IModelQualityProvider<IHie public HierarchicElementSizeProvider() { super(); this.storedMetrics = new HashMap<>(); + this.allProviders = new HashMap<>(); this.containedProviders = new ArrayList<>(); } @@ -77,32 +93,58 @@ public class HierarchicElementSizeProvider implements IModelQualityProvider<IHie @Override public void apply(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()); + 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_PORTS, (double)currentElement.getConnectors().size()); storedMetrics.put(NUMBER_OF_TOTAL_ELEMENTS, 1.0); 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); + String comment = + isElementCommentable ? ((INamedCommentedElement)currentElement).getComment() : null; + storedMetrics.put(NUMBER_OF_TOTAL_COMMENTED_ELEMENTS, + comment != null && comment != "" ? 1.0 : 0.0); - for (IHierarchicElement containedElement : currentElement.getContainedElements()) { + 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 }) { + 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); } } -// System.out.println("Finished traversing Node: " -// + ((currentElement instanceof INamedElement) ? ((INamedElement) currentElement).getName() -// : "Not Named")); + 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); } /* 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/service/IModelQualityProvider.java index 77c3bf38e..4e9b35b11 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/service/IModelQualityProvider.java @@ -16,6 +16,7 @@ package org.fortiss.tooling.ext.quality.service; import org.eclipse.emf.ecore.EObject; +import org.fortiss.tooling.base.model.element.IHierarchicElement; import org.fortiss.tooling.kernel.service.base.IEObjectAware; /** @@ -29,4 +30,16 @@ public interface IModelQualityProvider<C extends EObject> extends IEObjectAware< /** Applies the IMetricProvider to the given model element. */ void apply(C element); + + /** + * @return a simple example string demonstrating some metric capability + */ + String getExampleString(); + + /** + * @param element + * the element for which the matching {@link IModelQualityProvider} is searched + * @return the matching provider + */ + IModelQualityProvider<C> getProvider(IHierarchicElement element); } 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 a14e4e0f2..0e6068a4b 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 @@ -24,7 +24,7 @@ import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; -import java.util.LinkedList; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -66,6 +66,9 @@ 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; + /** */ @Override public void startService() { @@ -90,7 +93,7 @@ public class ModelQualityService extends EObjectAwareServiceBase<IModelQualityPr } /** Get all suitable {@link IModelQualityProvider} for the given input. */ - private List<IModelQualityProvider<?>> getAllMetricProviders(EObject input) { + protected List<IModelQualityProvider<?>> getAllMetricProviders(EObject input) { List<IModelQualityProvider<?>> providers = new ArrayList<>(); for(Entry<Class<?>, List<IModelQualityProvider<?>>> migEntry : handlerMap.entrySet()) { if(getFirstChildWithType(input, migEntry.getKey()) != null) { @@ -102,26 +105,29 @@ public class ModelQualityService extends EObjectAwareServiceBase<IModelQualityPr } /** - * @param fp - * @return + * @param fp the file project on which the analysis should be performed + * @return result resulting metrics */ - public List<IModelQualityProvider<? extends EObject>> performMetricAnalysis(FileProject fp) { - List<IModelQualityProvider<? extends EObject>> result = - new LinkedList<>(); - for(IProjectRootElement ele : fp.getRootElements()) { - if(ele instanceof IHierarchicElement) { - - //TODO check get(0) - IHierarchicElement firstNode = ((IHierarchicElement) ele).getContainedElements().get(0); - - HierarchicElementSizeProvider hes = - new HierarchicElementSizeProvider(); + public Map<IProjectRootElement, IModelQualityProvider<? extends EObject>> + performMetricAnalysis(FileProject fp) { + Map<IProjectRootElement, IModelQualityProvider<? extends EObject>> result = new HashMap<>(); + for(IProjectRootElement rootElement : fp.getRootElements()) { + if(rootElement instanceof IHierarchicElement) { + + // TODO check get(0) + IHierarchicElement firstNode = + ((IHierarchicElement)rootElement).getContainedElements().get(0); + + HierarchicElementSizeProvider hes = new HierarchicElementSizeProvider(); hes.apply(firstNode); - System.out.println("checked in hierarchic metrics for: " + ele.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.add(hes); + 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); } } @@ -141,7 +147,8 @@ public class ModelQualityService extends EObjectAwareServiceBase<IModelQualityPr // metricsList.addAll(metrics); // } // } - + + last_metrics = result; return result; } @@ -181,7 +188,7 @@ public class ModelQualityService extends EObjectAwareServiceBase<IModelQualityPr return true; } - @SuppressWarnings("javadoc") + /** {@inheritDoc} */ @Override public IIntrospectionDetailsItem getDetailsItem() { return null; -- GitLab