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

Adapted csv writer to the new data structure

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



Signed-off-by: default avatarEddie Groh <groh@fortiss.org>
parent 98beda1d
No related branches found
No related tags found
1 merge request!210Setting up Metric extraction plugin for AF3 : Issue 4310
......@@ -41,6 +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.data.MetricKey;
import org.fortiss.tooling.ext.quality.data.MetricTreeNode;
import org.fortiss.tooling.ext.quality.service.ModelQualityService;
import org.fortiss.tooling.kernel.model.IProjectRootElement;
......@@ -103,7 +104,6 @@ public class MetricsFXController extends CompositeFXControllerBase<SplitPane, No
@Override
public void initialize() {
// Not used
}
/** {@inheritDoc} */
......@@ -166,8 +166,8 @@ public class MetricsFXController extends CompositeFXControllerBase<SplitPane, No
pieChart.getData().clear();
for(var child : node.getChildren()) {
PieChart.Data slice =
new PieChart.Data(child.getName(), child.getTotalPortAmount());
PieChart.Data slice = new PieChart.Data(child.getName(),
child.getStoredMetrics().get(MetricKey.NUMBER_OF_TOTAL_PORTS));
pieChart.getData().add(slice);
pieChart.setLegendVisible(false);
pieChart.setTitle("");
......@@ -196,8 +196,8 @@ public class MetricsFXController extends CompositeFXControllerBase<SplitPane, No
}
/**
* @param provider
* the provider for which the spider chart should be generated
* @param node
* of which the data will be visualized
* @return {@link SpiderChartViewer} with the matching metrics
*/
private static SpiderChartViewer buildSpiderChart(MetricTreeNode node) {
......@@ -212,8 +212,9 @@ public class MetricsFXController extends CompositeFXControllerBase<SplitPane, No
return null;
}
double maxval =
children.stream().mapToDouble(p -> p.getTotalPortAmount()).max().getAsDouble();
double maxval = children.stream()
.mapToDouble(p -> p.getStoredMetrics().get(MetricKey.NUMBER_OF_TOTAL_PORTS)).max()
.getAsDouble();
chartStyle.setUseIndividualAxisSegments(false);
chartStyle.setTitleStyle(new FontStyle("Verdana", 14, BLUE.brighter()));
......@@ -227,7 +228,8 @@ public class MetricsFXController extends CompositeFXControllerBase<SplitPane, No
chartStyle.setAxisStyle(testing, aStyle3Segs);
spiderChart.addAxis(testing);
elementData.setPoint(testing, child.getTotalPortAmount());
elementData.setPoint(testing,
child.getStoredMetrics().get(MetricKey.NUMBER_OF_TOTAL_PORTS));
}
spiderChart.addData(elementData);
......
......@@ -42,7 +42,7 @@ public class AF3QualityActivator extends Plugin {
System.out.println("[Plugin] " + PLUGIN_ID + " started.");
ModelQualityService.getInstance().startService();
IModelQualityService.getInstance().registerMetricProvider(
new HierarchicElementSizeProvider(), IHierarchicElement.class);
new HierarchicElementProvider(), IHierarchicElement.class);
}
/** {@inheritDoc} */
......
......@@ -20,7 +20,9 @@ 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.MetricKey;
import org.fortiss.tooling.ext.quality.data.MetricTreeNode;
import org.fortiss.tooling.kernel.model.IIdLabeled;
import org.fortiss.tooling.kernel.model.INamedCommentedElement;
/**
......@@ -30,7 +32,7 @@ import org.fortiss.tooling.kernel.model.INamedCommentedElement;
* @author blaschke
* @author groh
*/
public class HierarchicElementSizeProvider implements IModelQualityProvider<IHierarchicElement> {
public class HierarchicElementProvider 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
......@@ -39,37 +41,13 @@ 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";
/** 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() {
public HierarchicElementProvider() {
super();
}
......@@ -80,10 +58,11 @@ public class HierarchicElementSizeProvider implements IModelQualityProvider<IHie
var metrics = node.getStoredMetrics();
boolean isElementCommentable = currentElement instanceof INamedCommentedElement;
metrics.put(NUMBER_OF_TOTAL_COMMENTABLE_ELEMENTS, isElementCommentable ? 1.0 : 0.0);
metrics.put(MetricKey.NUMBER_OF_TOTAL_COMMENTABLE_ELEMENTS,
isElementCommentable ? 1.0 : 0.0);
String comment =
isElementCommentable ? ((INamedCommentedElement)currentElement).getComment() : null;
metrics.put(NUMBER_OF_TOTAL_COMMENTED_ELEMENTS,
metrics.put(MetricKey.NUMBER_OF_TOTAL_COMMENTED_ELEMENTS,
comment != null && comment != "" ? 1.0 : 0.0);
if(isElementCommentable) {
node.setName(((INamedCommentedElement)currentElement).getName());
......@@ -134,16 +113,18 @@ public class HierarchicElementSizeProvider implements IModelQualityProvider<IHie
// EcoreUtils.pickInstanceOf(target, srcList)
var metrics = node.getStoredMetrics();
metrics.put(NUMBER_OF_PORTS, (double)currentElement.getConnectors().size());
metrics.put(NUMBER_OF_CONTAINED_ELEMENTS,
metrics.put(MetricKey.UNQIUE_ID, (currentElement instanceof IIdLabeled)
? ((IIdLabeled)currentElement).getId() : -1.0);
metrics.put(MetricKey.NUMBER_OF_PORTS, (double)currentElement.getConnectors().size());
metrics.put(MetricKey.NUMBER_OF_CONTAINED_ELEMENTS,
(double)currentElement.getContainedElements().size());
metrics.put(NUMBER_OF_CHANNELS, (double)currentElement.getConnections().size());
metrics.put(MetricKey.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(MetricKey.NUMBER_OF_TOTAL_PORTS, (double)currentElement.getConnectors().size());
metrics.put(MetricKey.NUMBER_OF_TOTAL_ELEMENTS, 1.0);
metrics.put(NUMBER_OF_TOTAL_LEAF_ELEMENTS,
metrics.put(MetricKey.NUMBER_OF_TOTAL_LEAF_ELEMENTS,
currentElement.getContainedElements().size() == 0 ? 1.0 : 0.0);
for(IHierarchicElement containedElement : currentElement.getContainedElements()) {
......@@ -151,9 +132,11 @@ public class HierarchicElementSizeProvider implements IModelQualityProvider<IHie
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}) {
for(MetricKey key : new MetricKey[] {MetricKey.NUMBER_OF_TOTAL_PORTS,
MetricKey.NUMBER_OF_TOTAL_ELEMENTS,
MetricKey.NUMBER_OF_TOTAL_COMMENTABLE_ELEMENTS,
MetricKey.NUMBER_OF_TOTAL_COMMENTED_ELEMENTS,
MetricKey.NUMBER_OF_TOTAL_LEAF_ELEMENTS}) {
metrics.merge(key, child.getStoredMetrics().get(key), Double::sum);
}
}
......
......@@ -18,10 +18,10 @@ package org.fortiss.tooling.ext.quality.data;
import java.util.HashMap;
import java.util.Map;
import org.fortiss.tooling.ext.quality.HierarchicElementSizeProvider;
import org.fortiss.tooling.ext.quality.HierarchicElementProvider;
/**
* Class for storing data generated by the {@link HierarchicElementSizeProvider}
* Class for storing data generated by the {@link HierarchicElementProvider}
*
* @author groh
*/
......
/*-------------------------------------------------------------------------+
| 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;
/**
*
* @author groh
*/
public enum MetricKey {
//
// Metrics provided by the HierarchicElementProvider
//
/** Unique ID of the element */
UNQIUE_ID,
/** Key for the metric counting ports */
NUMBER_OF_PORTS,
/** Key for the metric counting elements */
NUMBER_OF_CONTAINED_ELEMENTS,
/** Key for the metric counting channels */
NUMBER_OF_CHANNELS,
// Metrics which are collected over all children nodes
/** Key for the metric counting the total amount of ports contained */
NUMBER_OF_TOTAL_PORTS,
/** Key for the metric counting the total amount of elements contained */
NUMBER_OF_TOTAL_ELEMENTS,
/** Key for the metric counting the total amount of elements which can be commented */
NUMBER_OF_TOTAL_COMMENTABLE_ELEMENTS,
/** Key for the metric counting the total amount of elements which are commented */
NUMBER_OF_TOTAL_COMMENTED_ELEMENTS,
/**
* Key for the metric counting the total amount of elements which do not contain other elements
*/
NUMBER_OF_TOTAL_LEAF_ELEMENTS,
}
......@@ -19,6 +19,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import org.fortiss.tooling.ext.quality.IModelQualityProvider;
......@@ -47,7 +48,7 @@ public class MetricTreeNode {
private Map<Class<? extends IModelQualityProvider<?>>, IMetricDataContainer> dataContainers;
/** Map containing all metrics which are a double */
private Map<String, Double> storedMetrics = new HashMap<>();
private Map<MetricKey, Double> storedMetrics;
/** name of the element which is associated with this data */
private String name;
......@@ -56,8 +57,9 @@ public class MetricTreeNode {
* Constructs a new node
*/
public MetricTreeNode() {
children = new ArrayList<MetricTreeNode>();
children = new ArrayList<>();
dataContainers = new HashMap<>();
storedMetrics = new HashMap<>();
}
/**
......@@ -92,11 +94,24 @@ public class MetricTreeNode {
/**
* @return the stored metrics map
*/
public Map<String, Double> getStoredMetrics() {
public Map<MetricKey, Double> getStoredMetrics() {
return storedMetrics;
}
public double getTotalPortAmount() {
return storedMetrics.get("numberOfTotalPorts");
/**
* Traverses the tree in post-order
*
* @param consumer
* which is applied to each node
*/
public void traverseTree(Consumer<MetricTreeNode> consumer) {
// traverse all children
for(var child : getChildren()) {
child.traverseTree(consumer);
}
// apply consumer to self
consumer.accept(this);
}
}
......@@ -26,22 +26,23 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
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.HierarchicElementSizeProvider;
import org.fortiss.tooling.ext.quality.HierarchicElementProvider;
import org.fortiss.tooling.ext.quality.IModelQualityProvider;
import org.fortiss.tooling.ext.quality.data.MetricDataManager;
import org.fortiss.tooling.ext.quality.data.MetricKey;
import org.fortiss.tooling.ext.quality.data.MetricTreeNode;
import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
import org.fortiss.tooling.kernel.introspection.IIntrospectionDetailsItem;
......@@ -138,14 +139,13 @@ public class ModelQualityService extends EObjectAwareServiceBase<IModelQualityPr
// Get first element, there should not be any other elements
IHierarchicElement firstNode = elements.get(0);
MetricTreeNode root_node = new MetricTreeNode();
HierarchicElementSizeProvider hes = new HierarchicElementSizeProvider();
HierarchicElementProvider hes = new HierarchicElementProvider();
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;
// Store all currently saved metrics to the csv
metricExtractionToCSV(metricDataManagerInstance.getRootNodes());
}
/** */
......@@ -193,20 +193,19 @@ public class ModelQualityService extends EObjectAwareServiceBase<IModelQualityPr
/**
* Method to write the data into a csv
*
* @param data
* @param map
* to convert into csv
*
*/
public void metricExtractionToCSV(
Map<IProjectRootElement, IModelQualityProvider<? extends EObject>> data) {
public void metricExtractionToCSV(Map<IProjectRootElement, MetricTreeNode> map) {
// check if there is any data to export
if(data == null || data.isEmpty()) {
if(map == null || map.isEmpty()) {
return;
}
// path to csv file
Path path = Paths.get("data_ultra_cool.csv");
Path path = Paths.get("data_mega_cool.csv");
List<String> allKeys = new ArrayList<>();
boolean createNewIndex = true;
......@@ -228,14 +227,14 @@ 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 = new ArrayList<String>();
allKeys.add("timestamp");
allKeys.add("root");
allKeys.add("node");
allKeys.add("parent");
allKeys.addAll(keys);
allKeys.add("root_name");
allKeys.add("name");
allKeys.add("children");
// Collect all MetricKeys, convert them to a string and append them to the allKeys
// list
allKeys.addAll(Arrays.stream(MetricKey.values()).map(MetricKey::toString)
.map(String::toLowerCase).collect(Collectors.toList()));
// Write first line
writer.write(String.join(",", allKeys));
......@@ -248,87 +247,37 @@ public class ModelQualityService extends EObjectAwareServiceBase<IModelQualityPr
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
String formattedDateTime = dateTime.format(formatter);
data.forEach((rootProject, rootProvider) -> {
map.forEach((rootProject, rootNode) -> {
// 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();
// }
// }
// });
rootNode.traverseTree(node -> {
var metrics = node.getStoredMetrics();
// collect IDs of children
String children_ids = node.getChildren().stream()
.map(n -> n.getStoredMetrics().get(MetricKey.UNQIUE_ID))
.map(id -> id.toString()).reduce((a, b) -> a + " " + b).orElse("");
// These 4 data entries are just concatenated in front
var startStream =
Stream.of(formattedDateTime, rootName, node.getName(), children_ids);
// Collect all values from provider in the correct order and combine
var values = Stream
.concat(startStream, valueKeys.stream().map(String::toUpperCase)
.map(MetricKey::valueOf).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();
}
}
/**
*
* @author blaschke
*/
public static class MetricCSVWriter {
/** */
private static final String FILE_PATH = "data_ultra_cool.csv";
/** */
private BufferedWriter writer;
/**
* @throws IOException
*/
public void openFile() throws IOException {
writer = new BufferedWriter(new FileWriter(FILE_PATH, true));
}
/**
* @param data
*/
public void writeData(Map<String, Double> data) {
try {
String timestamp = getCurrentTimestamp();
writer.write(timestamp + ": ");
for(Map.Entry<String, Double> entry : data.entrySet()) {
writer.write(entry.getKey() + ":" + entry.getValue() + ",");
writer.newLine();
}
writer.flush();
} catch(IOException e) {
e.printStackTrace();
}
}
/**
* @throws IOException
*/
public void closeFile() throws IOException {
if(writer != null) {
writer.close();
}
}
/** */
private String getCurrentTimestamp() {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date now = new Date();
return dateFormat.format(now);
}
}
}
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