diff --git a/analyses/org.osate.modelstats.tests/.classpath b/analyses/org.osate.modelstats.tests/.classpath
new file mode 100644
index 00000000000..3e5654f17eb
--- /dev/null
+++ b/analyses/org.osate.modelstats.tests/.classpath
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/analyses/org.osate.modelstats.tests/.gitignore b/analyses/org.osate.modelstats.tests/.gitignore
new file mode 100644
index 00000000000..ae3c1726048
--- /dev/null
+++ b/analyses/org.osate.modelstats.tests/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git a/analyses/org.osate.modelstats.tests/.project b/analyses/org.osate.modelstats.tests/.project
new file mode 100644
index 00000000000..04682102cde
--- /dev/null
+++ b/analyses/org.osate.modelstats.tests/.project
@@ -0,0 +1,28 @@
+
+
+ org.osate.modelstats.tests
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.pde.ManifestBuilder
+
+
+
+
+ org.eclipse.pde.SchemaBuilder
+
+
+
+
+
+ org.eclipse.pde.PluginNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/analyses/org.osate.modelstats.tests/.settings/org.eclipse.jdt.core.prefs b/analyses/org.osate.modelstats.tests/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..9f6ece88bdf
--- /dev/null
+++ b/analyses/org.osate.modelstats.tests/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.release=disabled
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/analyses/org.osate.modelstats.tests/META-INF/MANIFEST.MF b/analyses/org.osate.modelstats.tests/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..690c6986f9b
--- /dev/null
+++ b/analyses/org.osate.modelstats.tests/META-INF/MANIFEST.MF
@@ -0,0 +1,18 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Model Statistics Tests
+Bundle-SymbolicName: org.osate.modelstats.tests
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.osate.modelstats.tests.Activator
+Require-Bundle: org.eclipse.core.runtime,
+ org.osate.modelstats;bundle-version="1.0.0",
+ org.eclipse.xtext.testing,
+ org.eclipse.xtext.junit4,
+ org.junit,
+ org.osate.testsupport,
+ org.osate.aadl2,
+ org.osate.aadl2.instantiation
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Automatic-Module-Name: org.osate.componentcounter.tests
+Bundle-ActivationPolicy: lazy
+Bundle-Vendor: CMU/SEI
diff --git a/analyses/org.osate.modelstats.tests/build.properties b/analyses/org.osate.modelstats.tests/build.properties
new file mode 100644
index 00000000000..34d2e4d2dad
--- /dev/null
+++ b/analyses/org.osate.modelstats.tests/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
diff --git a/analyses/org.osate.modelstats.tests/models/ComponentCounter/.gitignore b/analyses/org.osate.modelstats.tests/models/ComponentCounter/.gitignore
new file mode 100644
index 00000000000..11d04b41d15
--- /dev/null
+++ b/analyses/org.osate.modelstats.tests/models/ComponentCounter/.gitignore
@@ -0,0 +1 @@
+/.aadlbin-gen/
diff --git a/analyses/org.osate.modelstats.tests/models/ComponentCounter/.project b/analyses/org.osate.modelstats.tests/models/ComponentCounter/.project
new file mode 100644
index 00000000000..fdff1d48f41
--- /dev/null
+++ b/analyses/org.osate.modelstats.tests/models/ComponentCounter/.project
@@ -0,0 +1,18 @@
+
+
+ ComponentCounter
+
+
+
+
+
+ org.eclipse.xtext.ui.shared.xtextBuilder
+
+
+
+
+
+ org.osate.core.aadlnature
+ org.eclipse.xtext.ui.shared.xtextNature
+
+
diff --git a/analyses/org.osate.modelstats.tests/models/ComponentCounter/Empty.aadl b/analyses/org.osate.modelstats.tests/models/ComponentCounter/Empty.aadl
new file mode 100644
index 00000000000..1ce8fb554c5
--- /dev/null
+++ b/analyses/org.osate.modelstats.tests/models/ComponentCounter/Empty.aadl
@@ -0,0 +1,8 @@
+package Empty
+public
+ system s
+ end s;
+
+ system implementation s.impl
+ end s.impl;
+end Empty;
\ No newline at end of file
diff --git a/analyses/org.osate.modelstats.tests/models/ComponentCounter/Exhaustive.aadl b/analyses/org.osate.modelstats.tests/models/ComponentCounter/Exhaustive.aadl
new file mode 100644
index 00000000000..82ad0f468c6
--- /dev/null
+++ b/analyses/org.osate.modelstats.tests/models/ComponentCounter/Exhaustive.aadl
@@ -0,0 +1,49 @@
+package Exhaustive
+public
+ system s
+ end s;
+
+ system implementation s.impl
+ subcomponents
+ sub1: abstract;
+ sub2: bus;
+ sub3: data;
+ sub4: device;
+ sub5: memory;
+ sub6: process p.impl;
+ sub7: processor;
+ sub8: subprogram;
+ sub9: subprogram group;
+ sub10: system;
+ sub11: virtual bus;
+ sub12: virtual processor;
+ end s.impl;
+
+ process p
+ end p;
+
+ process implementation p.impl
+ subcomponents
+ sub13: thread group;
+ t1: thread t1;
+ t2: thread t2;
+ connections
+ con1: feature t1.f1 -> t2.f2;
+ flows
+ flow1: end to end flow t1.source1 -> con1 -> t2.sink2;
+ end p.impl;
+
+ thread t1
+ features
+ f1: feature;
+ flows
+ source1: flow source f1;
+ end t1;
+
+ thread t2
+ features
+ f2: feature;
+ flows
+ sink2: flow sink f2;
+ end t2;
+end Exhaustive;
\ No newline at end of file
diff --git a/analyses/org.osate.modelstats.tests/pom.xml b/analyses/org.osate.modelstats.tests/pom.xml
new file mode 100644
index 00000000000..8da0f5f422a
--- /dev/null
+++ b/analyses/org.osate.modelstats.tests/pom.xml
@@ -0,0 +1,66 @@
+
+
+ 4.0.0
+
+
+ org.osate
+ analyses.parent
+ 2.9.0-SNAPSHOT
+
+
+ org.osate
+ org.osate.modelstats.tests
+ 1.0.0-SNAPSHOT
+ eclipse-test-plugin
+
+
+
+ eclipse
+ ${eclipse.repo.url}
+ p2
+
+
+ xtext-testing
+ ${xtext-testing.repo.url}
+ p2
+
+
+
+
+
+ org.eclipse.tycho
+ target-platform-configuration
+ ${tycho.version}
+
+
+
+
+
+
+
+ eclipse-plugin
+ org.eclipse.equinox.event
+ 0.0.0
+
+
+ eclipse-plugin
+ org.eclipse.equinox.ds
+ 0.0.0
+
+
+
+ eclipse-plugin
+ org.osate.aadl2.model.editor
+ 0.0.0
+
+
+
+
+
+
+
+
+
diff --git a/analyses/org.osate.modelstats.tests/src/org/osate/modelstats/tests/Activator.java b/analyses/org.osate.modelstats.tests/src/org/osate/modelstats/tests/Activator.java
new file mode 100644
index 00000000000..565fe0a7b39
--- /dev/null
+++ b/analyses/org.osate.modelstats.tests/src/org/osate/modelstats/tests/Activator.java
@@ -0,0 +1,22 @@
+package org.osate.modelstats.tests;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class Activator implements BundleActivator {
+
+ private static BundleContext context;
+
+ static BundleContext getContext() {
+ return context;
+ }
+
+ public void start(BundleContext bundleContext) throws Exception {
+ Activator.context = bundleContext;
+ }
+
+ public void stop(BundleContext bundleContext) throws Exception {
+ Activator.context = null;
+ }
+
+}
diff --git a/analyses/org.osate.modelstats.tests/src/org/osate/modelstats/tests/ComponentCounterTest.java b/analyses/org.osate.modelstats.tests/src/org/osate/modelstats/tests/ComponentCounterTest.java
new file mode 100644
index 00000000000..303ff1767ce
--- /dev/null
+++ b/analyses/org.osate.modelstats.tests/src/org/osate/modelstats/tests/ComponentCounterTest.java
@@ -0,0 +1,69 @@
+package org.osate.modelstats.tests;
+
+import org.eclipse.xtext.testing.InjectWith;
+import org.eclipse.xtext.testing.XtextRunner;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.osate.aadl2.AadlPackage;
+import org.osate.aadl2.ComponentCategory;
+import org.osate.aadl2.SystemImplementation;
+import org.osate.aadl2.instance.SystemInstance;
+import org.osate.aadl2.instantiation.InstantiateModel;
+import org.osate.modelstats.ComponentCounter;
+import org.osate.modelstats.ElementsCounts;
+import org.osate.testsupport.Aadl2InjectorProvider;
+import org.osate.testsupport.TestHelper;
+
+import com.google.inject.Inject;
+
+
+@RunWith(XtextRunner.class)
+@InjectWith(Aadl2InjectorProvider.class)
+public class ComponentCounterTest {
+ private final String path = "org.osate.modelstats.tests/models/ComponentCounter/";
+
+ @Inject
+ private TestHelper testHelper;
+
+ @Test
+ public void emptyTest() throws Exception {
+ AadlPackage pkg = testHelper.parseFile(path + "Empty.aadl");
+ SystemImplementation impl = (SystemImplementation) pkg.getPublicSection().getOwnedClassifiers().get(1);
+ SystemInstance si = InstantiateModel.instantiate(impl);
+ ElementsCounts elementCounts = ComponentCounter.countComponents(si);
+
+ Assert.assertEquals(1, elementCounts.getTotalComponentCount());
+ Assert.assertEquals(0, elementCounts.getConnectionsCount());
+ Assert.assertEquals(0, elementCounts.getEndToEndFlowsCount());
+ Assert.assertEquals(1, elementCounts.getComponentCountMap().size());
+ Assert.assertEquals(1, elementCounts.getComponentCountMap().get(ComponentCategory.SYSTEM).intValue());
+ }
+
+ @Test
+ public void exhaustiveTest() throws Exception {
+ AadlPackage pkg = testHelper.parseFile(path + "Exhaustive.aadl");
+ SystemImplementation impl = (SystemImplementation) pkg.getPublicSection().getOwnedClassifiers().get(1);
+ SystemInstance si = InstantiateModel.instantiate(impl);
+ ElementsCounts elementCounts = ComponentCounter.countComponents(si);
+
+ Assert.assertEquals(16, elementCounts.getTotalComponentCount());
+ Assert.assertEquals(1, elementCounts.getConnectionsCount());
+ Assert.assertEquals(1, elementCounts.getEndToEndFlowsCount());
+ Assert.assertEquals(14, elementCounts.getComponentCountMap().size());
+ Assert.assertEquals(2, elementCounts.getComponentCountMap().get(ComponentCategory.SYSTEM).intValue());
+ Assert.assertEquals(1, elementCounts.getComponentCountMap().get(ComponentCategory.ABSTRACT).intValue());
+ Assert.assertEquals(1, elementCounts.getComponentCountMap().get(ComponentCategory.BUS).intValue());
+ Assert.assertEquals(1, elementCounts.getComponentCountMap().get(ComponentCategory.DATA).intValue());
+ Assert.assertEquals(1, elementCounts.getComponentCountMap().get(ComponentCategory.DEVICE).intValue());
+ Assert.assertEquals(1, elementCounts.getComponentCountMap().get(ComponentCategory.MEMORY).intValue());
+ Assert.assertEquals(1, elementCounts.getComponentCountMap().get(ComponentCategory.PROCESS).intValue());
+ Assert.assertEquals(1, elementCounts.getComponentCountMap().get(ComponentCategory.PROCESSOR).intValue());
+ Assert.assertEquals(1, elementCounts.getComponentCountMap().get(ComponentCategory.SUBPROGRAM).intValue());
+ Assert.assertEquals(1, elementCounts.getComponentCountMap().get(ComponentCategory.SUBPROGRAM_GROUP).intValue());
+ Assert.assertEquals(1, elementCounts.getComponentCountMap().get(ComponentCategory.VIRTUAL_BUS).intValue());
+ Assert.assertEquals(1,
+ elementCounts.getComponentCountMap().get(ComponentCategory.VIRTUAL_PROCESSOR).intValue());
+ Assert.assertEquals(2, elementCounts.getComponentCountMap().get(ComponentCategory.THREAD).intValue());
+ }
+}
diff --git a/analyses/org.osate.modelstats.ui/.classpath b/analyses/org.osate.modelstats.ui/.classpath
new file mode 100644
index 00000000000..eca7bdba8f0
--- /dev/null
+++ b/analyses/org.osate.modelstats.ui/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/analyses/org.osate.modelstats.ui/.gitignore b/analyses/org.osate.modelstats.ui/.gitignore
new file mode 100644
index 00000000000..ae3c1726048
--- /dev/null
+++ b/analyses/org.osate.modelstats.ui/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git a/analyses/org.osate.modelstats.ui/.project b/analyses/org.osate.modelstats.ui/.project
new file mode 100644
index 00000000000..153d4c25240
--- /dev/null
+++ b/analyses/org.osate.modelstats.ui/.project
@@ -0,0 +1,68 @@
+
+
+ org.osate.modelstats.ui
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.pde.ManifestBuilder
+
+
+
+
+ org.eclipse.pde.SchemaBuilder
+
+
+
+
+ org.eclipse.oomph.version.VersionBuilder
+
+
+ check.feature.closure.completeness
+ true
+
+
+ check.feature.closure.content
+ true
+
+
+ check.maven.pom
+ true
+
+
+ ignore.feature.content.redundancy
+ true
+
+
+ ignore.lower.bound.dependency.ranges
+ false
+
+
+ ignore.schema.builder
+ true
+
+
+ release.path
+ /releng/version-management/release.xml
+
+
+
+
+ org.eclipse.pde.api.tools.apiAnalysisBuilder
+
+
+
+
+
+ org.eclipse.pde.PluginNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.oomph.version.VersionNature
+ org.eclipse.pde.api.tools.apiAnalysisNature
+
+
diff --git a/analyses/org.osate.modelstats.ui/.settings/org.eclipse.jdt.core.prefs b/analyses/org.osate.modelstats.ui/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..9f6ece88bdf
--- /dev/null
+++ b/analyses/org.osate.modelstats.ui/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.release=disabled
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/analyses/org.osate.modelstats.ui/META-INF/MANIFEST.MF b/analyses/org.osate.modelstats.ui/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..b4f7122e6e7
--- /dev/null
+++ b/analyses/org.osate.modelstats.ui/META-INF/MANIFEST.MF
@@ -0,0 +1,17 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Model Statistics UI
+Bundle-SymbolicName: org.osate.modelstats.ui;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.osate.modelstats.ui.Activator
+Require-Bundle: org.eclipse.ui;bundle-version="[3.117.0,4.0.0)",
+ org.eclipse.core.runtime;bundle-version="[3.18.0,4.0.0)",
+ org.eclipse.core.resources;bundle-version="[3.13.0,4.0.0)",
+ org.osate.ui;bundle-version="[5.0.0,6.0.0)",
+ org.osate.aadl2;bundle-version="[4.0.0,5.0.0)",
+ org.eclipse.swt;bundle-version="[3.114.0,4.0.0)",
+ org.osate.modelstats;bundle-version="[1.0.0,2.0.0)"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Automatic-Module-Name: org.osate.modelstats.ui
+Bundle-ActivationPolicy: lazy
+Bundle-Vendor: CMU/SEI
diff --git a/analyses/org.osate.modelstats.ui/build.properties b/analyses/org.osate.modelstats.ui/build.properties
new file mode 100644
index 00000000000..e9863e281ea
--- /dev/null
+++ b/analyses/org.osate.modelstats.ui/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml
diff --git a/analyses/org.osate.modelstats.ui/help/modelStatistics.xml b/analyses/org.osate.modelstats.ui/help/modelStatistics.xml
new file mode 100644
index 00000000000..0e702f1d1fa
--- /dev/null
+++ b/analyses/org.osate.modelstats.ui/help/modelStatistics.xml
@@ -0,0 +1,7 @@
+
+
+
+ This dialog provides information about how to use the Model Statistics analyses.
+
+
+
diff --git a/analyses/org.osate.modelstats.ui/html/.gitignore b/analyses/org.osate.modelstats.ui/html/.gitignore
new file mode 100644
index 00000000000..af1ef3e71f1
--- /dev/null
+++ b/analyses/org.osate.modelstats.ui/html/.gitignore
@@ -0,0 +1,2 @@
+/ModelStatistics.html
+/images/
diff --git a/analyses/org.osate.modelstats.ui/markdown/ModelStatistics.md b/analyses/org.osate.modelstats.ui/markdown/ModelStatistics.md
new file mode 100644
index 00000000000..a7d650912da
--- /dev/null
+++ b/analyses/org.osate.modelstats.ui/markdown/ModelStatistics.md
@@ -0,0 +1,29 @@
+# Model Statistics
+
+The Analysis > Model Maintenance submenu in the main menubar contains analyses for simplifying, understanding, or otherwise "cleaning up" AADL models. **Model Statistics** is one of the tools located in the **Model Maintenance** submenu.
+
+## Executing Model Statistics
+
+The *Model Statistics* analysis returns basic statistics about your system. The counts of AADL components (i.e. systems, threads, etc.), end-to-end flows, and connections are displayed when the analysis is run. To run the analysis, follow these steps:
+
+1. Create an instance model of a system implementation.
+
+2. In the **AADL Navigator**, make sure you have that instance model selected.
+
+3. Find the **Analyses** menu located in the toolbar
+
+4. Navigate to **Model Maintenance** in the **Analyses** toolbar menu
+
+5. **Model Statistics** should appear in solid black text, if the text is gray then an instance model is not currently selected in the **AADL Navigator**.
+
+
+
+
+
+After running the analysis, a window will be displayed with the counts from your instance model. The **Components** category can be expanded to see more specific counts, as demonstrated in the image below.
+
+
+
+
+
+Click 'OK' to close the window.
\ No newline at end of file
diff --git a/analyses/org.osate.modelstats.ui/markdown/images/ModelLocation.png b/analyses/org.osate.modelstats.ui/markdown/images/ModelLocation.png
new file mode 100644
index 00000000000..007b522c4ea
Binary files /dev/null and b/analyses/org.osate.modelstats.ui/markdown/images/ModelLocation.png differ
diff --git a/analyses/org.osate.modelstats.ui/markdown/images/ModelStatistics.png b/analyses/org.osate.modelstats.ui/markdown/images/ModelStatistics.png
new file mode 100644
index 00000000000..8b10c7c9b3f
Binary files /dev/null and b/analyses/org.osate.modelstats.ui/markdown/images/ModelStatistics.png differ
diff --git a/analyses/org.osate.modelstats.ui/plugin.xml b/analyses/org.osate.modelstats.ui/plugin.xml
new file mode 100644
index 00000000000..3be4b24d9b9
--- /dev/null
+++ b/analyses/org.osate.modelstats.ui/plugin.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/analyses/org.osate.modelstats.ui/pom.xml b/analyses/org.osate.modelstats.ui/pom.xml
new file mode 100644
index 00000000000..fa703da2a87
--- /dev/null
+++ b/analyses/org.osate.modelstats.ui/pom.xml
@@ -0,0 +1,51 @@
+
+
+ 4.0.0
+
+
+ org.osate
+ analyses.parent
+ 2.9.0-SNAPSHOT
+
+
+ org.osate
+ org.osate.modelstats.ui
+ 1.0.0-SNAPSHOT
+ eclipse-plugin
+
+
+
+
+ maven-clean-plugin
+ 2.5
+
+
+
+ html
+
+ .gitignore
+
+
+
+
+
+
+ com.ruleoftech
+ markdown-page-generator-plugin
+ 2.1.0
+
+ ${project.basedir}/markdown/
+ ${project.basedir}/html/
+ images,images/**,css
+
+ BlockQuote|style="font-size:90%"
+
+ EXTANCHORLINKS,TOC
+
+
+
+
+
+
diff --git a/analyses/org.osate.modelstats.ui/src/org/osate/modelstats/ui/Activator.java b/analyses/org.osate.modelstats.ui/src/org/osate/modelstats/ui/Activator.java
new file mode 100644
index 00000000000..9e2d8569ae9
--- /dev/null
+++ b/analyses/org.osate.modelstats.ui/src/org/osate/modelstats/ui/Activator.java
@@ -0,0 +1,44 @@
+package org.osate.modelstats.ui;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.osate.componentcounter.ui"; //$NON-NLS-1$
+
+ // The shared instance
+ private static Activator plugin;
+
+ /**
+ * The constructor
+ */
+ public Activator() {
+ }
+
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+}
diff --git a/analyses/org.osate.modelstats.ui/src/org/osate/modelstats/ui/CountComponentsHandler.java b/analyses/org.osate.modelstats.ui/src/org/osate/modelstats/ui/CountComponentsHandler.java
new file mode 100644
index 00000000000..da0a12ca401
--- /dev/null
+++ b/analyses/org.osate.modelstats.ui/src/org/osate/modelstats/ui/CountComponentsHandler.java
@@ -0,0 +1,40 @@
+package org.osate.modelstats.ui;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.osate.aadl2.Element;
+import org.osate.aadl2.instance.SystemInstance;
+import org.osate.modelstats.ComponentCounter;
+import org.osate.modelstats.ElementsCounts;
+import org.osate.ui.handlers.AaxlReadOnlyHandlerAsJob;
+
+public class CountComponentsHandler extends AaxlReadOnlyHandlerAsJob {
+ private String fileName;
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ super.execute(event);
+ IStructuredSelection selection = HandlerUtil.getCurrentStructuredSelection(event);
+ IFile file = (IFile) selection.getFirstElement();
+ fileName = file.getName();
+ return null;
+ }
+
+ @Override
+ protected String getActionName() {
+ return "Model Elements Counter";
+ }
+
+ @Override
+ protected void doAaxlAction(IProgressMonitor monitor, Element root) {
+ SystemInstance si = (SystemInstance) root;
+ ElementsCounts elementCounts = ComponentCounter.countComponents(si);
+
+ CountComponentsUI dialog = new CountComponentsUI(getShell(), fileName, getActionName(), elementCounts); // creates the dialog object
+ getShell().getDisplay().asyncExec(() -> dialog.open()); // opens the dialog
+ }
+}
diff --git a/analyses/org.osate.modelstats.ui/src/org/osate/modelstats/ui/CountComponentsUI.java b/analyses/org.osate.modelstats.ui/src/org/osate/modelstats/ui/CountComponentsUI.java
new file mode 100644
index 00000000000..1d87a3def4f
--- /dev/null
+++ b/analyses/org.osate.modelstats.ui/src/org/osate/modelstats/ui/CountComponentsUI.java
@@ -0,0 +1,148 @@
+package org.osate.modelstats.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.TreeViewerColumn;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.osate.aadl2.ComponentCategory;
+import org.osate.modelstats.ElementsCounts;
+
+public class CountComponentsUI extends Dialog {
+ private final static String COMPONENTS_NODE = "Components";
+ private final static String CONNECTIONS_NODE = "Connections";
+ private final static String ETEF_NODE = "End to End Flows";
+ private final String actionName;
+ private final String fileName;
+ private final ElementsCounts elementsCounts;
+
+ // constructor
+ protected CountComponentsUI(Shell parentShell, String fileName, String actionName, ElementsCounts elementCounts) {
+ super(parentShell);
+ this.elementsCounts = elementCounts;
+ this.actionName = actionName;
+ this.fileName = fileName;
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite composite = (Composite) super.createDialogArea(parent);
+ composite.getShell().setText(actionName);
+
+ Label infoLabel = new Label(composite, SWT.NONE);
+ infoLabel.setText("Model element counts for " + fileName);
+
+ TreeViewer viewer = new TreeViewer(composite);
+ viewer.setComparator(new ViewerComparator());
+ viewer.getTree().setHeaderVisible(true);
+ viewer.getTree().setLinesVisible(true);
+ viewer.getTree().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ viewer.setContentProvider(new ViewContentProvider());
+
+ // how component column is created
+ TreeViewerColumn componentNameColumn = new TreeViewerColumn(viewer, SWT.NONE);
+ componentNameColumn.getColumn().setWidth(convertWidthInCharsToPixels(25));
+ componentNameColumn.getColumn().setResizable(true);
+ componentNameColumn.getColumn().setText("Model Elements");
+ componentNameColumn.setLabelProvider(new ColumnLabelProvider() {
+ @Override
+ public String getText(Object element) {
+ if (element instanceof String) {
+ return element.toString();
+ } else if (element instanceof ComponentCategory) {
+ String compName = ((ComponentCategory) element).getName();
+ return compName.substring(0, 1).toUpperCase() + compName.substring(1);
+ } else {
+ return null;
+ }
+ }
+ });
+
+ // how count column is created
+ TreeViewerColumn countNameColumn = new TreeViewerColumn(viewer, SWT.NONE);
+ countNameColumn.getColumn().setWidth(convertWidthInCharsToPixels(15));
+ countNameColumn.getColumn().setResizable(true);
+ countNameColumn.getColumn().setText("Counts");
+ countNameColumn.setLabelProvider(new ColumnLabelProvider() {
+ @Override
+ public String getText(Object element) {
+ if (element instanceof ComponentCategory) {
+ return elementsCounts.getComponentCountMap().get(element).toString();
+ } else if (element == COMPONENTS_NODE) {
+ return Integer.toString(elementsCounts.getTotalComponentCount());
+ } else if (element == CONNECTIONS_NODE) {
+ return Integer.toString(elementsCounts.getConnectionsCount());
+ } else if (element == ETEF_NODE) {
+ return Integer.toString(elementsCounts.getEndToEndFlowsCount());
+ }
+ return null;
+ }
+ });
+ viewer.setInput(elementsCounts);
+ return composite;
+ }
+
+ // Override the original to remove the cancel option
+ @Override
+ protected void createButtonsForButtonBar(Composite parent) {
+ createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+ }
+
+ // overrides the original so that the window can be resized
+ @Override
+ protected boolean isResizable() {
+ return true;
+ }
+
+ private class ViewContentProvider implements ITreeContentProvider {
+ @Override
+ public Object[] getElements(Object inputElement) {
+ return getChildren(inputElement);
+ }
+
+ @Override
+ public Object[] getChildren(Object parentElement) {
+ if (parentElement instanceof ElementsCounts) {
+ List