diff --git a/org.fortiss.tooling.ext.quality/META-INF/MANIFEST.MF b/org.fortiss.tooling.ext.quality/META-INF/MANIFEST.MF index 4db8cb70af2dc664684e1c99e81c1954373993e1..8bf5ae2e6ab0d35404a355f09cf71d956992efaa 100644 --- a/org.fortiss.tooling.ext.quality/META-INF/MANIFEST.MF +++ b/org.fortiss.tooling.ext.quality/META-INF/MANIFEST.MF @@ -15,4 +15,5 @@ Export-Package: org.fortiss.tooling.ext.quality.service Import-Package: org.fortiss.af3.component.model, org.fortiss.af3.component.utils, org.fortiss.af3.project.model, - org.fortiss.af3.project.utils + org.fortiss.af3.project.utils, + org.fortiss.af3.rcp.application diff --git a/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/service/MetricCommentProvider.java b/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/service/MetricCommentProvider.java index e7e3890936cf724c39a9125bdc28c79efab83dd7..1361afa6c7b02fb4392a090ffb351bebc6955153 100644 --- a/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/service/MetricCommentProvider.java +++ b/org.fortiss.tooling.ext.quality/src/org/fortiss/tooling/ext/quality/service/MetricCommentProvider.java @@ -16,14 +16,23 @@ package org.fortiss.tooling.ext.quality.service; 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.ecore.EObject; +import org.fortiss.af3.component.model.InputPort; +import org.fortiss.af3.component.model.PortSpecification; +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.kernel.model.INamedCommentedElement; /** - * {@link IMetricProvider} to count the ratio of filled out comments of INamedCommentedElements. + * {@link IMetricProvider} to count the ratio of filled out comments of + * INamedCommentedElements. * * @author blaschke */ @@ -36,15 +45,287 @@ public class MetricCommentProvider implements IMetricProvider<IHierarchicElement @Override public List<String> apply(IHierarchicElement topComponent) { extractComment(topComponent); - for(IHierarchicElement child : topComponent.getContainedElements()) { + for (IHierarchicElement child : topComponent.getContainedElements()) { apply(child); } return strings; } + public void startRecursion(IHierarchicElement topElement) { + + Set<IElementConsumer> consumers = new HashSet<MetricCommentProvider.IElementConsumer>(); + consumers.add(new PortCounter()); + consumers.add(new ConnectionCounter()); + consumers.add(new ElementCounter()); + consumers.add(new CommentCompleteness()); + consumers.add(new CloneDetection()); + + traverse(topElement, consumers); + + consumers.forEach(c -> c.printResult()); + + new PortCounter().printShare((HierarchicElementBase) topElement.getContainedElements().get(0)); + } + + public void traverse(IHierarchicElement currentElement, Set<IElementConsumer> consumers) { + + consumers.forEach(c -> c.apply(currentElement)); + + for (IHierarchicElement child : currentElement.getContainedElements()) { + traverse(child, consumers); + } + + } + + public interface IElementConsumer { + + public void apply(IHierarchicElement element); + + public void printResult(); + } + + public abstract class MultiMethodDemo implements IElementConsumer { + + @Override + public void apply(IHierarchicElement element) { + if (element instanceof INamedCommentedElement) { + consume((INamedCommentedElement) element); + } else { + consume(element); + } + } + + public abstract void consume(IHierarchicElement element); + + public abstract void consume(INamedCommentedElement element); + + } + + public class CloneDetection implements IElementConsumer { + + private Map<Integer, List<IHierarchicElement>> map = new HashMap<>(); + + @Override + public void printResult() { + System.out.println("Stuff"); + } + + @Override + public void apply(IHierarchicElement element) { + if (!((INamedCommentedElement) element).getName().equals("DtB")) { + // return; + } + + int hash = 1; + for (IConnector connector : element.getConnectors()) { + PortSpecification port = (PortSpecification) connector.getSpecifications().get(0); + hash = 31 * hash + + (connector instanceof InputPort ? 1 : 2) * port.getType().getClass().hashCode(); + } + 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); + } + + } + + public class CommentCompleteness extends MultiMethodDemo { + + private int total_amount; + private int with_comments; + + public CommentCompleteness() { + total_amount = 0; + with_comments = 0; + } + + @Override + public void printResult() { + System.out.println("[CommentCompleteness] Total:" + total_amount + " With:" + with_comments + " Ratio:" + + (with_comments / (double) total_amount)); + } + + @Override + public void consume(IHierarchicElement element) { + total_amount++; + } + + @Override + public void consume(INamedCommentedElement element) { + if (element.getComment() != "") { + with_comments++; + } + total_amount++; + } + + } + + public class Tuple<T1, T2> { + private T1 element1; + private T2 element2; + + public Tuple(T1 element1, T2 element2) { + this.element1 = element1; + this.element2 = element2; + } + + public T1 getElement1() { + return element1; + } + + public T2 getElement2() { + return element2; + } + } + + public abstract class CounterConsumer implements IElementConsumer { + + protected int count; + + public CounterConsumer() { + count = 0; + } + + @Override + public void printResult() { + System.out.println("[" + this.getClass().getSimpleName() + "] Found " + count + " total"); + } + + public int getCount() { + return count; + } + + public void printShare(HierarchicElementBase element) { + + Set<Tuple<String, Integer>> counts = new HashSet<>(); + this.apply(element); + counts.add(new Tuple<>("[Self]" + element.getName(), count)); + 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); + } + } + + protected void recursiveDescent(HierarchicElementBase element, CounterConsumer consumer) { + consumer.apply(element); + + for (IHierarchicElement child : element.getContainedElements()) { + HierarchicElementBase real_child = (HierarchicElementBase) child; + + recursiveDescent(real_child, consumer); + } + } + } + + public class PortCounter extends CounterConsumer { + + @Override + public void apply(IHierarchicElement element) { + count += element.getConnectors().size(); + } + } + + public class ConnectionCounter extends CounterConsumer { + + @Override + public void apply(IHierarchicElement element) { + count += element.getConnections().size(); + } + } + + public class ElementCounter extends CounterConsumer { + @Override + public void apply(IHierarchicElement element) { + count++; + } + } + + public Map<String, Integer> sizeMetrics(IHierarchicElement ele) { + return null; + // anzahl elemente im baum ab hierarchiebene ele + // anzahl ports ab ...... + // anzahl channels....... + // completness von comments #eleMitComment/#ele + // kamelCase names + + // State Automoton + // Annotations + + // tooling.kernel -> tooling.body -> ext packages -> af3 -> rcp + } + /** */ private void extractComment(IHierarchicElement c) { - strings.add(((INamedCommentedElement)c).getComment()); + strings.add(((INamedCommentedElement) c).getComment()); } /** {@inheritDoc} */ diff --git a/org.fortiss.tooling.ext.quality/test-src/test/org/fortiss/tooling/ext/quality/metric/MetricTest.java b/org.fortiss.tooling.ext.quality/test-src/test/org/fortiss/tooling/ext/quality/metric/MetricTest.java index 174d0c3d10da6d0135e605cafb97fff10f013291..9199b9fef720cd6501c6ee2d534fd3da99f10d06 100644 --- a/org.fortiss.tooling.ext.quality/test-src/test/org/fortiss/tooling/ext/quality/metric/MetricTest.java +++ b/org.fortiss.tooling.ext.quality/test-src/test/org/fortiss/tooling/ext/quality/metric/MetricTest.java @@ -18,11 +18,9 @@ package test.org.fortiss.tooling.ext.quality.metric; import static org.fortiss.af3.component.utils.ComponentArchitectureUtils.findFirstComponentArchitecture; import static org.fortiss.af3.project.utils.TestCaseProjectUtils.loadTestProject; -import java.util.List; - -import org.fortiss.af3.component.model.Component; import org.fortiss.af3.project.model.FileProject; -import org.fortiss.tooling.ext.quality.AF3QualityActivator; +import org.fortiss.af3.rcp.application.AF3ApplicationActivator; +import org.fortiss.tooling.base.model.element.IHierarchicElement; import org.fortiss.tooling.ext.quality.service.MetricCommentProvider; import org.junit.Before; import org.junit.Test; @@ -36,13 +34,17 @@ import org.junit.Test; public class MetricTest { /** Top component. */ - private Component topComponent; + private IHierarchicElement topComponent; + /** Setup the test. */ @Before public void setup() { - FileProject project = loadTestProject(AF3QualityActivator.PLUGIN_ID, - "test-data/StateAutomataConstraintsCheckerTestData.af3_23"); + FileProject project = loadTestProject(AF3ApplicationActivator.PLUGIN_ID, + // "test-data/ACC.af3_23"); + "test-data/carla_ff1_rover.af3_23"); + + // topComponent = (IHierarchicElement) project.getRootElements().get(2); topComponent = findFirstComponentArchitecture(project).getTopComponent(); } @@ -50,7 +52,7 @@ public class MetricTest { @Test public void actionsConstraintCheck() { MetricCommentProvider mcp = new MetricCommentProvider(); - List<String> result = mcp.apply(topComponent); - System.out.println(result); + mcp.startRecursion(topComponent); + } }