Allow display of plantUML graph and matrix from selecting graphical elements

The functionality is now generic and depends on the handlers to get the selected Object as an EObject.
The code also contains functionality that allows to use toggle transitivity to switch between seeing the selected elements only and seeing the selected elements and their children in the Matrix view. Test cases for this also added.

Change-Id: Ia873a48665476bfa4cf906877f5d0e58a53b5cc1
diff --git a/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestGraphicalVisualization.java b/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestGraphicalVisualization.java
new file mode 100644
index 0000000..d08569a
--- /dev/null
+++ b/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestGraphicalVisualization.java
@@ -0,0 +1,133 @@
+package org.eclipse.capra.testsuite;
+
+import static org.eclipse.capra.testsuite.TestHelper.clearWorkspace;
+import static org.eclipse.capra.testsuite.TestHelper.createEClassInEPackage;
+import static org.eclipse.capra.testsuite.TestHelper.createEcoreModel;
+import static org.eclipse.capra.testsuite.TestHelper.createSimpleProject;
+import static org.eclipse.capra.testsuite.TestHelper.createTraceForCurrentSelectionOfType;
+import static org.eclipse.capra.testsuite.TestHelper.getProject;
+import static org.eclipse.capra.testsuite.TestHelper.load;
+import static org.eclipse.capra.testsuite.TestHelper.projectExists;
+import static org.eclipse.capra.testsuite.TestHelper.resetSelectionView;
+import static org.eclipse.capra.testsuite.TestHelper.save;
+import static org.eclipse.capra.testsuite.TestHelper.thereIsATraceBetween;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.capra.GenericTraceMetaModel.GenericTraceMetaModelPackage;
+import org.eclipse.capra.core.adapters.TracePersistenceAdapter;
+import org.eclipse.capra.core.helpers.ExtensionPointHelper;
+import org.eclipse.capra.ui.plantuml.DiagramTextProviderHandler;
+import org.eclipse.capra.ui.plantuml.DisplayTracesHandler;
+import org.eclipse.capra.ui.views.SelectionView;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestGraphicalVisualization {
+
+	private final static String EXPECTED_TEXT_FOR_DIRECT_CONNECTIONS = "@startuml\n"
+			+ "object \"A : EClass\" as o0 #pink\n" + "object \"B : EClass\" as o1\n" + "o0--o1:RelatedTo\n"
+			+ "@enduml\n";
+
+	private final static String EXPECTED_TEXT_FOR_TRANSITIVE_CONNECTIONS = "@startuml\n"
+			+ "object \"A : EClass\" as o0 #pink\n" + "object \"B : EClass\" as o1\n" + "object \"C : EClass\" as o2\n"
+			+ "o0--o1:RelatedTo\n" + "o1--o2:RelatedTo\n" + "@enduml\n";
+
+	@Before
+	public void init() throws CoreException {
+		clearWorkspace();
+		resetSelectionView();
+	}
+
+	@Test
+	public void testPlantUMLGraphView() throws CoreException, IOException, InterruptedException {
+
+		// Create a project
+		createSimpleProject("TestProject");
+		assertTrue(projectExists("TestProject"));
+
+		// Create two models each with two classes and persist them
+		IProject testProject = getProject("TestProject");
+		EPackage a = TestHelper.createEcoreModel("modelA");
+		createEClassInEPackage(a, "A");
+		save(testProject, a);
+
+		EPackage b = createEcoreModel("modelB");
+		createEClassInEPackage(b, "B");
+		createEClassInEPackage(b, "C");
+		save(testProject, b);
+
+		// Load them and choose the four classes
+		ResourceSet rs = new ResourceSetImpl();
+
+		EPackage _a = load(testProject, "modelA.ecore", rs);
+		assertEquals(_a.getName(), "modelA");
+		EClass _A = (EClass) _a.getEClassifier("A");
+
+		EPackage _b = load(testProject, "modelB.ecore", rs);
+		assertEquals(_b.getName(), "modelB");
+		EClass _B = (EClass) _b.getEClassifier("B");
+		EClass _C = (EClass) _b.getEClassifier("C");
+
+		// Add A and B to the selection view
+		assertTrue(SelectionView.getOpenedView().getSelection().isEmpty());
+		SelectionView.getOpenedView().dropToSelection(_A);
+		SelectionView.getOpenedView().dropToSelection(_B);
+		assertFalse(SelectionView.getOpenedView().getSelection().isEmpty());
+
+		// Create a trace via the selection view
+		assertFalse(thereIsATraceBetween(_A, _B));
+		createTraceForCurrentSelectionOfType(GenericTraceMetaModelPackage.eINSTANCE.getRelatedTo());
+		assertTrue(thereIsATraceBetween(_A, _B));
+
+		// Clear selection view
+		SelectionView.getOpenedView().clearSelection();
+
+		// Add B and C to selection view
+		SelectionView.getOpenedView().dropToSelection(_B);
+		SelectionView.getOpenedView().dropToSelection(_C);
+
+		// Create a traceLink between B and C
+		assertFalse(thereIsATraceBetween(_B, _C));
+		createTraceForCurrentSelectionOfType(GenericTraceMetaModelPackage.eINSTANCE.getRelatedTo());
+		// Remove trace model from resource set to make sure the trace model is
+		// re-loaded to capture the second trace link
+		removeTraceModel(rs);
+		assertTrue(thereIsATraceBetween(_B, _C));
+
+		// create a selection with class A
+		List<Object> selection = new ArrayList<>();
+		selection.add(_A);
+
+		// Test directly connected Elements
+		DisplayTracesHandler.setTraceViewTransitive(false);
+		DiagramTextProviderHandler provider = new DiagramTextProviderHandler();
+		String DirectlyConnectedElements = provider.getDiagramText(selection);
+		assertTrue(DirectlyConnectedElements.equals(EXPECTED_TEXT_FOR_DIRECT_CONNECTIONS));
+
+		// Test transitively connected Elements
+		DisplayTracesHandler.setTraceViewTransitive(true);
+		String transitivelysConnectedElements = provider.getDiagramText(selection);
+		assertTrue(transitivelysConnectedElements.equals(EXPECTED_TEXT_FOR_TRANSITIVE_CONNECTIONS));
+
+	}
+
+	private void removeTraceModel(ResourceSet rs) {
+		TracePersistenceAdapter persistenceAdapter = ExtensionPointHelper.getTracePersistenceAdapter().get();
+		EObject tm = persistenceAdapter.getTraceModel(rs);
+		rs.getResources().remove(tm.eResource());
+	}
+
+}
diff --git a/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestTraceabiltyMatrix.java b/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestTraceabiltyMatrix.java
index 3c022db..68fdac8 100644
--- a/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestTraceabiltyMatrix.java
+++ b/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestTraceabiltyMatrix.java
@@ -23,6 +23,7 @@
 import org.eclipse.capra.core.adapters.TracePersistenceAdapter;
 import org.eclipse.capra.core.helpers.ExtensionPointHelper;
 import org.eclipse.capra.ui.plantuml.DiagramTextProviderHandler;
+import org.eclipse.capra.ui.plantuml.DisplayTracesHandler;
 import org.eclipse.capra.ui.views.SelectionView;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.CoreException;
@@ -36,9 +37,12 @@
 
 public class TestTraceabiltyMatrix {
 
-	private final static String EXPECTED_TEXT_FOR_SELECTED_PACKAGES = "@startuml\n" + "salt\n" + "{#\n"
+	private final static String EXPECTED_TEXT_FOR_SELECTED_PACKAGES_DIRECT = "@startuml\n" + "salt\n" + "{#\n"
+			+ ".|modelB : EPackage\n" + "modelA : EPackage |X\n" + "}\n" + "\n" + "@enduml\n";
+
+	private final static String EXPECTED_TEXT_FOR_SELECTED_PACKAGES_TRANSITIVE = "@startuml\n" + "salt\n" + "{#\n"
 			+ ".|B : EClass|BB : EClass|modelB : EPackage\n" + "A : EClass |X|.|.\n" + "AA : EClass |.|X|.\n"
-			+ "modelA : EPackage |.|.|.\n" + "}\n" + "\n" + "@enduml\n";
+			+ "modelA : EPackage |.|.|X\n" + "}\n" + "\n" + "@enduml\n";
 
 	private final static String EXPECTED_TEXT_FOR_SELECTED_CLASSES = "@startuml\n" + "salt\n" + "{#\n"
 			+ ".|A : EClass|B : EClass|AA : EClass|BB : EClass\n" + "A : EClass |.|X|.|.\n" + "B : EClass |X|.|.|.\n"
@@ -111,16 +115,42 @@
 		removeTraceModel(rs);
 		assertTrue(thereIsATraceBetween(_AA, _BB));
 
+		// create trace link between package A and B
+		// clear selection
+		SelectionView.getOpenedView().clearSelection();
+		assertTrue(SelectionView.getOpenedView().getSelection().isEmpty());
+
+		// Add Package A and B to selection view
+		SelectionView.getOpenedView().dropToSelection(_a);
+		SelectionView.getOpenedView().dropToSelection(_b);
+		assertFalse(SelectionView.getOpenedView().getSelection().isEmpty());
+
+		// Create a trace between Package A and B
+		assertFalse(thereIsATraceBetween(_a, _b));
+		createTraceForCurrentSelectionOfType(GenericTraceMetaModelPackage.eINSTANCE.getRelatedTo());
+
+		// Remove trace model from resource set to make sure the trace model is
+		// re-loaded to capture the third trace link
+		removeTraceModel(rs);
+		assertTrue(thereIsATraceBetween(_a, _b));
+
 		// create a selection with Package A and B
 		List<Object> selectedPackages = new ArrayList<>();
 		selectedPackages.add(_a);
 		selectedPackages.add(_b);
 
+		// Test directly connected Elements
+		DisplayTracesHandler.setTraceViewTransitive(false);
 		DiagramTextProviderHandler provider = new DiagramTextProviderHandler();
-		String plantUMLTextForSelectedPackages = provider.getDiagramText(selectedPackages);
+		String plantUMLTextForSelectedPackages_Direct = provider.getDiagramText(selectedPackages);
+		assertTrue(plantUMLTextForSelectedPackages_Direct.equals(EXPECTED_TEXT_FOR_SELECTED_PACKAGES_DIRECT));
 
-		assertTrue(plantUMLTextForSelectedPackages.equals(EXPECTED_TEXT_FOR_SELECTED_PACKAGES));
+		// Test transitively connected Elements
+		DisplayTracesHandler.setTraceViewTransitive(true);
+		String plantUMLTextForSelectedPackages_Transitive = provider.getDiagramText(selectedPackages);
+		assertTrue(plantUMLTextForSelectedPackages_Transitive.equals(EXPECTED_TEXT_FOR_SELECTED_PACKAGES_TRANSITIVE));
 
+		// test multiple classes selected
 		List<Object> selectedClasses = new ArrayList<>();
 		selectedClasses.add(_A);
 		selectedClasses.add(_B);
@@ -136,5 +166,4 @@
 		EObject tm = persistenceAdapter.getTraceModel(rs);
 		rs.getResources().remove(tm.eResource());
 	}
-
 }
diff --git a/org.eclipse.capra.ui.plantuml/META-INF/MANIFEST.MF b/org.eclipse.capra.ui.plantuml/META-INF/MANIFEST.MF
index 1e014c3..e1247df 100644
--- a/org.eclipse.capra.ui.plantuml/META-INF/MANIFEST.MF
+++ b/org.eclipse.capra.ui.plantuml/META-INF/MANIFEST.MF
@@ -7,16 +7,14 @@
  org.eclipse.jface,
  org.eclipse.capra.core,
  org.eclipse.emf.ecore.editor,
- com.google.guava,
- org.eclipse.xtext.xbase.lib,
- org.eclipse.xtend.lib,
- org.eclipse.xtend.lib.macro,
  net.sourceforge.plantuml.eclipse,
  org.eclipse.ui,
  org.eclipse.core.resources,
  org.eclipse.core.runtime;bundle-version="3.10.0",
  org.eclipse.capra.ui;bundle-version="0.7.0",
- org.eclipse.capra.generic.tracemodels
+ org.eclipse.capra.generic.tracemodels,
+ org.eclipse.xtext.xbase.lib;bundle-version="2.10.0",
+ org.eclipse.xtend.lib;bundle-version="2.10.0"
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Export-Package: org.eclipse.capra.ui.plantuml
 Bundle-Vendor: Capra Development Team
diff --git a/org.eclipse.capra.ui.plantuml/src/org/eclipse/capra/ui/plantuml/DiagramTextProviderHandler.java b/org.eclipse.capra.ui.plantuml/src/org/eclipse/capra/ui/plantuml/DiagramTextProviderHandler.java
index be4477f..8ef398b 100644
--- a/org.eclipse.capra.ui.plantuml/src/org/eclipse/capra/ui/plantuml/DiagramTextProviderHandler.java
+++ b/org.eclipse.capra.ui.plantuml/src/org/eclipse/capra/ui/plantuml/DiagramTextProviderHandler.java
@@ -11,12 +11,14 @@
 package org.eclipse.capra.ui.plantuml;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.stream.Collectors;
 
 import org.eclipse.capra.core.adapters.Connection;
 import org.eclipse.capra.core.adapters.TraceMetaModelAdapter;
 import org.eclipse.capra.core.adapters.TracePersistenceAdapter;
+import org.eclipse.capra.core.handlers.ArtifactHandler;
 import org.eclipse.capra.core.helpers.EMFHelper;
 import org.eclipse.capra.core.helpers.ExtensionPointHelper;
 import org.eclipse.capra.ui.helpers.TraceCreationHelper;
@@ -35,60 +37,87 @@
  * @author Anthony Anjorin, Salome Maro
  */
 public class DiagramTextProviderHandler implements DiagramTextProvider {
-	private TraceMetaModelAdapter metamodelAdapter;
-	private List<Connection> traces = new ArrayList<>();
+	private EObject artifactModel = null;
 
 	@Override
 	public String getDiagramText(IEditorPart editor, ISelection input) {
 		List<Object> selectedModels = TraceCreationHelper
 				.extractSelectedElements(editor.getSite().getSelectionProvider().getSelection());
-
 		return getDiagramText(selectedModels);
 	}
 
-	/**
-	 * Creates the {@code String} representation PlantUML uses to render the
-	 * graphics. Based on the selected models, the relevant trace links are
-	 * extracted and a decision is made whether a matrix of a tree view has to
-	 * be displayed.
-	 * 
-	 * @param selectedModels
-	 *            the models whose trace links should be displayed
-	 * @return a string representation of the visualisation that can be rendered
-	 *         by PlantUML
-	 */
 	public String getDiagramText(List<Object> selectedModels) {
 		List<EObject> firstModelElements = null;
 		List<EObject> secondModelElements = null;
+		EObject selectedObject = null;
+		ResourceSet resourceSet = new ResourceSetImpl();
+		EObject traceModel = null;
+		List<Connection> traces = new ArrayList<>();
 
 		TracePersistenceAdapter persistenceAdapter = ExtensionPointHelper.getTracePersistenceAdapter().get();
-		metamodelAdapter = ExtensionPointHelper.getTraceMetamodelAdapter().get();
+		TraceMetaModelAdapter metamodelAdapter = ExtensionPointHelper.getTraceMetamodelAdapter().get();
 
-		ResourceSet resourceSet = new ResourceSetImpl();
-		if (selectedModels.size() > 0 && selectedModels.get(0) instanceof EObject)
-			resourceSet = ((EObject) selectedModels.get(0)).eResource().getResourceSet();
+		artifactModel = persistenceAdapter.getArtifactWrappers(resourceSet);
 
-		EObject traceModel = persistenceAdapter.getTraceModel(resourceSet);
+		Collection<ArtifactHandler> artifactHandlers = ExtensionPointHelper.getArtifactHandlers();
+		if (selectedModels.size() > 0) {
+			// check if there is a hander for the selected elements and if yes
+			// get its EObject representation
+			List<ArtifactHandler> availableHandlers = artifactHandlers.stream()
+					.filter(handler -> handler.canHandleSelection(selectedModels.get(0))).collect(Collectors.toList());
+			if (availableHandlers.size() >= 1) {
+				selectedObject = availableHandlers.get(0).getEObjectForSelection(selectedModels.get(0), artifactModel);
 
-		if (selectedModels.size() == 1 && selectedModels.get(0) instanceof EObject) {
-			EObject selectedEObject = (EObject) selectedModels.get(0);
-			if (DisplayTracesHandler.isTraceViewTransitive()) {
-				traces = metamodelAdapter.getTransitivelyConnectedElements(selectedEObject, traceModel);
-			} else {
-				traces = metamodelAdapter.getConnectedElements(selectedEObject, traceModel);
+				if (selectedObject != null) {
+					resourceSet = selectedObject.eResource().getResourceSet();
+					traceModel = persistenceAdapter.getTraceModel(resourceSet);
+
+					if (selectedModels.size() == 1) {
+						if (DisplayTracesHandler.isTraceViewTransitive()) {
+							traces = metamodelAdapter.getTransitivelyConnectedElements(selectedObject, traceModel);
+						} else {
+							traces = metamodelAdapter.getConnectedElements(selectedObject, traceModel);
+						}
+
+						return VisualizationHelper.createNeighboursView(traces, selectedObject);
+					} else if (selectedModels.size() == 2) {
+						if (DisplayTracesHandler.isTraceViewTransitive()) {
+							firstModelElements = EMFHelper.linearize(availableHandlers.get(0)
+									.getEObjectForSelection(selectedModels.get(0), artifactModel));
+							secondModelElements = EMFHelper.linearize(availableHandlers.get(0)
+									.getEObjectForSelection(selectedModels.get(1), artifactModel));
+						} else {
+							List<EObject> firstObject = new ArrayList<>();
+							firstObject.add(availableHandlers.get(0).getEObjectForSelection(selectedModels.get(0),
+									artifactModel));
+							List<EObject> secondObject = new ArrayList<>();
+							secondObject.add(availableHandlers.get(0).getEObjectForSelection(selectedModels.get(1),
+									artifactModel));
+							firstModelElements = firstObject;
+							secondModelElements = secondObject;
+						}
+					} else if (selectedModels.size() > 2) {
+						if (DisplayTracesHandler.isTraceViewTransitive()) {
+							firstModelElements = selectedModels.stream()
+									.flatMap(r -> EMFHelper
+											.linearize(
+													availableHandlers.get(0).getEObjectForSelection(r, artifactModel))
+											.stream())
+									.collect(Collectors.toList());
+							secondModelElements = firstModelElements;
+						} else {
+							List<EObject> Objects = new ArrayList<>();
+							selectedModels.stream().forEach(o -> {
+								Objects.add(availableHandlers.get(0).getEObjectForSelection(o, artifactModel));
+
+							});
+							firstModelElements = Objects;
+							secondModelElements = firstModelElements;
+						}
+					}
+				}
 			}
-
-			return VisualizationHelper.createNeighboursView(traces, selectedEObject);
-		} else if (selectedModels.size() == 2) {
-			firstModelElements = EMFHelper.linearize(selectedModels.get(0));
-			secondModelElements = EMFHelper.linearize(selectedModels.get(1));
-		} else {
-			firstModelElements = selectedModels.stream().flatMap(r -> EMFHelper.linearize(r).stream())
-					.collect(Collectors.toList());
-
-			secondModelElements = firstModelElements;
 		}
-
 		String umlString = VisualizationHelper.createMatrix(traceModel, firstModelElements, secondModelElements);
 
 		return umlString;