Skip to content
Snippets Groups Projects
Commit fdf98d93 authored by blaschke's avatar blaschke
Browse files

Merge branch '4310' of https://git.fortiss.org/af3/kernel.git into 4310

parents a182c6f7 d744207d
No related branches found
No related tags found
1 merge request!210Setting up Metric extraction plugin for AF3 : Issue 4310
IModelQualityViewPart.java 708f8089645df12098ea67190805cce343045d2e YELLOW
ModelQualityFXController.java 391dc121678e1741b8ee98f90de18996ba2c37b2 YELLOW
ModelQualityFXController.java 4272d7043944effc9532d4a122fd50b63b79fb82 YELLOW
ModelQualityFXViewPart.java 179abf18d6e3b6c844076620f53b43ac8a42c217 YELLOW
......@@ -122,7 +122,7 @@ public class ModelQualityFXController extends CompositeFXControllerBase<SplitPan
EObject selected = checkAndPickFirst(selection, EObject.class);
if(selected == null) {
updateCharts();
updateCharts("Nothing selected");
return;
}
......@@ -131,30 +131,35 @@ public class ModelQualityFXController extends CompositeFXControllerBase<SplitPan
: getFirstParentWithType(selected, IProjectRootElement.class);
if(currentRootElement == null) {
updateCharts();
updateCharts("Selection does not have a ProjectRoot");
return;
}
var root_provider = manager.getRootNodesMap().get(currentRootElement);
if(root_provider == null) {
updateCharts();
updateCharts("Currently no metrics available, try generating them");
return;
}
lastSelectedElement = selected;
updateCharts();
updateCharts("Selection does not have metric information");
}
/**
* Is triggered when the choice box changes.
*/
public void onChoiceBoxChange() {
updateCharts();
updateCharts("Invalid selection or metrics not available");
}
/** Updates the chart in the metric view. */
private void updateCharts() {
/**
* Updates the chart in the metric view.
*
* @param message
* to display if metric is not available
*/
private void updateCharts(String message) {
if(lastSelectedElement != null) {
MetricDataManager manager =
......@@ -187,13 +192,16 @@ public class ModelQualityFXController extends CompositeFXControllerBase<SplitPan
// Create PieChart and add data
pieChart.getData().clear();
pieChart.setLegendVisible(false);
pieChart.setTitle("");
DecimalFormat format = new DecimalFormat("0.#");
for(var child : node.getChildren()) {
Double value = child.getValueAsDouble(choiceBox.getValue());
if(value != null) {
PieChart.Data slice = new PieChart.Data(child.getName(), value);
PieChart.Data slice = new PieChart.Data(
child.getName() + ": " + format.format(value), value);
pieChart.getData().add(slice);
pieChart.setLegendVisible(false);
pieChart.setTitle("");
}
}
}
......@@ -221,9 +229,12 @@ public class ModelQualityFXController extends CompositeFXControllerBase<SplitPan
// Return, otherwise the data will be cleared
return;
}
message = "Selection does not have contained elements";
} else {
message = "Selection does not have metric information";
}
}
borderPane.setCenter(new Label("No metrics available for this selection"));
borderPane.setCenter(new Label(message));
pieChart.getData().clear();
}
......
AF3QualityActivator.java 353c3d99f423997e4e99a896b3c095fd77d81431 YELLOW
GraphMetricsProvider.java 2d3fff61af2537bc5b10b3c210dc8e4b3ad49c1d YELLOW
GraphMetricsProvider.java d2d0db1d00adeffeeb55b881a2ed81b7107cdbe2 YELLOW
HierarchicElementProvider.java 3c114abd47ecc0d7da751c3f05c83fd49a30717b YELLOW
IMetricProvider.java 99fc8993b0e65b2f8757978eeb0481d912f5608c YELLOW
......@@ -227,71 +227,23 @@ public class GraphMetricsProvider {
// Initialize all variables
Stack<IHierarchicElement> stack = new Stack<>();
Map<IHierarchicElement, List<IHierarchicElement>> pred = new HashMap<>();
Map<IHierarchicElement, Integer> dist = new HashMap<>();
Map<IHierarchicElement, Double> sigma = new HashMap<>();
Map<IHierarchicElement, List<IHierarchicElement>> predecessors = new HashMap<>();
Map<IHierarchicElement, Integer> distance = new HashMap<>();
Map<IHierarchicElement, Double> dependency = new HashMap<>();
Queue<IHierarchicElement> queue = new LinkedList<>();
for(IHierarchicElement v : graphNodes) {
pred.put(v, new ArrayList<>());
dist.put(v, -1);
sigma.put(v, 0.0);
predecessors.put(v, new ArrayList<>());
distance.put(v, -1);
dependency.put(v, 0.0);
}
sigma.put(elementNode, 1.0);
dist.put(elementNode, 0);
dependency.put(elementNode, 1.0);
distance.put(elementNode, 0);
queue.add(elementNode);
while(!queue.isEmpty()) {
IHierarchicElement v = queue.remove();
stack.push(v);
// Iterate over all connectors going out from the element
for(ExitConnectorBase exitConnectors : EcoreUtils
.pickInstanceOf(ExitConnectorBase.class, v.getConnectors())) {
// Iterate over all connections
for(IConnection outgoingConnection : exitConnectors.getOutgoing()) {
Set<IHierarchicElement> targetElements = new HashSet<>();
if(recursively) {
recursivlyFollowOutgoingConnection(outgoingConnection.getTarget(),
targetElements);
} else {
IHierarchicElement primaryTargetElement =
outgoingConnection.getTarget().getOwner();
// When we have a connection to the scopeElement, we have a
// connection leaving the local scope
if(scopeElement == primaryTargetElement) {
// Continue searching for outgoing connections on the target
// Connector
IConnector targetConnector = outgoingConnection.getTarget();
for(IConnection secondaryOutgoingConnection : targetConnector
.getOutgoing()) {
targetElements.add(
secondaryOutgoingConnection.getTarget().getOwner());
}
} else {
targetElements.add(primaryTargetElement);
}
}
for(IHierarchicElement targetElement : targetElements) {
// Check if element is in node list, to avoid creating data for
// nodes outside of our graph
if(graphNodes.contains(targetElement)) {
if(dist.get(targetElement) < 0) {
queue.add(targetElement);
dist.put(targetElement, dist.get(v) + 1);
}
if(dist.get(targetElement) == dist.get(v) + 1) {
sigma.put(targetElement,
sigma.get(targetElement) + sigma.get(v));
pred.get(targetElement).add(v);
}
}
}
}
}
}
processCentrality(queue, stack, predecessors, distance, dependency, graphNodes,
elementNode, recursively);
// Initialize delta
Map<IHierarchicElement, Double> delta = new HashMap<>();
for(IHierarchicElement v : graphNodes) {
......@@ -300,8 +252,8 @@ public class GraphMetricsProvider {
while(!stack.isEmpty()) {
IHierarchicElement w = stack.pop();
for(IHierarchicElement v : pred.get(w)) {
double c = (sigma.get(v) / sigma.get(w)) * (1.0 + delta.get(w));
for(IHierarchicElement v : predecessors.get(w)) {
double c = (dependency.get(v) / dependency.get(w)) * (1.0 + delta.get(w));
delta.put(v, delta.get(v) + c);
}
if(!w.equals(elementNode)) {
......@@ -324,4 +276,85 @@ public class GraphMetricsProvider {
betweenness.get(child));
}
}
/**
* Performs intermediate calculations for the betweenness centrality algorithm
*
* @param queue
* of nodes for Breadth-First Search.
* @param stack
* of nodes for Breadth-First Search.
* @param predecessor
* maps to lists used to keep track of the predecessors of nodes in the shortest
* paths.
* @param distance
* map used to store the shortest distances from the source node to other nodes.
* @param dependency
* map used to calculate and store the dependency values for nodes in the network.
* These values are part of the calculation for betweenness centrality.
* @param graphNodes
* list of nodes
* @param scopeElement
* the scope of this calculation
* @param recursively
* if true, all calculation will be carried out on leaf elements
*/
private static void processCentrality(Queue<IHierarchicElement> queue,
Stack<IHierarchicElement> stack,
Map<IHierarchicElement, List<IHierarchicElement>> predecessor,
Map<IHierarchicElement, Integer> distance, Map<IHierarchicElement, Double> dependency,
Set<IHierarchicElement> graphNodes, IHierarchicElement scopeElement,
boolean recursively) {
while(!queue.isEmpty()) {
IHierarchicElement v = queue.remove();
stack.push(v);
// Iterate over all connectors going out from the element
for(ExitConnectorBase exitConnectors : EcoreUtils
.pickInstanceOf(ExitConnectorBase.class, v.getConnectors())) {
// Iterate over all connections
for(IConnection outgoingConnection : exitConnectors.getOutgoing()) {
Set<IHierarchicElement> targetElements = new HashSet<>();
if(recursively) {
recursivlyFollowOutgoingConnection(outgoingConnection.getTarget(),
targetElements);
} else {
IHierarchicElement primaryTargetElement =
outgoingConnection.getTarget().getOwner();
// When we have a connection to the scopeElement, we have a
// connection leaving the local scope
if(scopeElement == primaryTargetElement) {
// Continue searching for outgoing connections on the target
// Connector
IConnector targetConnector = outgoingConnection.getTarget();
for(IConnection secondaryOutgoingConnection : targetConnector
.getOutgoing()) {
targetElements
.add(secondaryOutgoingConnection.getTarget().getOwner());
}
} else {
targetElements.add(primaryTargetElement);
}
}
for(IHierarchicElement targetElement : targetElements) {
// Check if element is in node list, to avoid creating data for
// nodes outside of our graph
if(graphNodes.contains(targetElement)) {
if(distance.get(targetElement) < 0) {
queue.add(targetElement);
distance.put(targetElement, distance.get(v) + 1);
}
if(distance.get(targetElement) == distance.get(v) + 1) {
dependency.put(targetElement,
dependency.get(targetElement) + dependency.get(v));
predecessor.get(targetElement).add(v);
}
}
}
}
}
}
}
}
CSVFileWriter.java 4e079908d3dd9af600ef97773f795c3e6a726c4b YELLOW
CSVFileWriter.java 3798d6cfd828cf103885c168066853b28fac85f7 YELLOW
ModelQualityStorageManager.java 124faddb3d297d23448c15379446cc847a2790a9 YELLOW
......@@ -86,8 +86,25 @@ public class CSVFileWriter {
} catch(IOException e) {
e.printStackTrace();
}
writeMetricsToFile(map, allKeys, path, createNewIndex);
}
}
/**
* Function to write the specified metrics into a csv file.
*
*
* @param map
* of the metrics which are written into the file
* @param allKeys
* a list of keys which will be extracted from the provided map
* @param path
* location of the file
* @param createNewIndex
* if a index should be written before writing any values
*/
private static void writeMetricsToFile(Map<IProjectRootElement, MetricTreeNode> map,
List<String> allKeys, Path path, boolean createNewIndex) {
try(var writer = new BufferedWriter(new FileWriter(path.toFile(), true))) {
if(createNewIndex) {
......
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