Added support for showing connections and artifacts in the property view

In this commit, an adapter factory and two adapters are added that
provide initial support to show artifacts and trace links in the
properties view. For trace links, all relevant generic properties
(origin, targets, type) as well as link type-specific metadata are
shown. For artifacts, location and label as well as artifact-specific
metadata are shown. This generic implementation can be used by
registering the provided factory to the o.e.c.r.adapters extension point
and implementing an ISelectionProvider in the view that returns a
Connection or an EObject.
diff --git a/bundles/org.eclipse.capra.ui/META-INF/MANIFEST.MF b/bundles/org.eclipse.capra.ui/META-INF/MANIFEST.MF
index 8e65903..8294db4 100644
--- a/bundles/org.eclipse.capra.ui/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.capra.ui/META-INF/MANIFEST.MF
@@ -24,7 +24,8 @@
  org.eclipse.core.commands,
  org.eclipse.capra.core
 Bundle-ActivationPolicy: lazy
-Export-Package: org.eclipse.capra.ui.handlers,
+Export-Package: org.eclipse.capra.ui.adapters,
+ org.eclipse.capra.ui.handlers,
  org.eclipse.capra.ui.handlers.selection,
  org.eclipse.capra.ui.helpers,
  org.eclipse.capra.ui.operations,
diff --git a/bundles/org.eclipse.capra.ui/src/org/eclipse/capra/ui/adapters/ArtifactAdapter.java b/bundles/org.eclipse.capra.ui/src/org/eclipse/capra/ui/adapters/ArtifactAdapter.java
new file mode 100644
index 0000000..d6374ab
--- /dev/null
+++ b/bundles/org.eclipse.capra.ui/src/org/eclipse/capra/ui/adapters/ArtifactAdapter.java
@@ -0,0 +1,110 @@
+package org.eclipse.capra.ui.adapters;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.eclipse.capra.core.adapters.TracePersistenceAdapter;
+import org.eclipse.capra.core.helpers.ArtifactHelper;
+import org.eclipse.capra.core.helpers.ExtensionPointHelper;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.ui.views.properties.IPropertyDescriptor;
+import org.eclipse.ui.views.properties.IPropertySource;
+import org.eclipse.ui.views.properties.PropertyDescriptor;
+import org.eclipse.ui.views.properties.TextPropertyDescriptor;
+
+/**
+ * An {@link IPropertySource} for artifacts. It provides access to all
+ * properties of the {@link EObject} representing the artifact. In practice,
+ * that means that it either shows the properties of the {@link ArtifactWrapper}
+ * or the {@code EObject} that is linked to.
+ * 
+ * @author Jan-Philipp Steghöfer
+ *
+ */
+public class ArtifactAdapter implements IPropertySource {
+
+	private static enum DescriptorIDs {
+		LABEL, LOCATION
+	}
+
+	private static final String CATEGORY_NAME = "General";
+
+	private final EObject artifact;
+
+	private final ArtifactHelper artifactHelper;
+
+	/**
+	 * Creates a new {@link ArtifactAdapter} that represents the provided artifact.
+	 * 
+	 * @param theItem the artifact this adapter represents.
+	 */
+	public ArtifactAdapter(EObject theItem) {
+		this.artifact = theItem;
+
+		TracePersistenceAdapter persistenceAdapter = ExtensionPointHelper.getTracePersistenceAdapter().get();
+		ResourceSet resourceSet = new ResourceSetImpl();
+		EObject artifactModel = persistenceAdapter.getArtifactWrappers(resourceSet);
+		artifactHelper = new ArtifactHelper(artifactModel);
+	}
+
+	@Override
+	public Object getEditableValue() {
+		return this;
+	}
+
+	@Override
+	public IPropertyDescriptor[] getPropertyDescriptors() {
+		List<IPropertyDescriptor> propertyDescriptors = new ArrayList<>();
+		if (!isArtifactWrapper(artifact)) {
+			PropertyDescriptor labelDescriptor = new PropertyDescriptor(DescriptorIDs.LABEL, "Label");
+			labelDescriptor.setCategory(CATEGORY_NAME);
+			propertyDescriptors.add(labelDescriptor);
+			PropertyDescriptor locationDescriptor = new PropertyDescriptor(DescriptorIDs.LOCATION, "Location");
+			locationDescriptor.setCategory(CATEGORY_NAME);
+			propertyDescriptors.add(locationDescriptor);
+		}
+		propertyDescriptors.addAll(artifact.eClass().getEAllAttributes().stream()
+				.map(attribute -> new TextPropertyDescriptor(attribute.getName(), attribute.getName()))
+				.collect(Collectors.toList()));
+
+		IPropertyDescriptor[] dummyList = new IPropertyDescriptor[propertyDescriptors.size()];
+		return propertyDescriptors.toArray(dummyList);
+	}
+
+	@Override
+	public Object getPropertyValue(Object id) {
+		if (id.equals(DescriptorIDs.LABEL)) {
+			return artifactHelper.getArtifactLabel(artifact);
+		} else if (id.equals(DescriptorIDs.LOCATION)) {
+			return artifactHelper.getArtifactLocation(artifact);
+		} else {
+			EStructuralFeature a = artifact.eClass().getEStructuralFeature((String) id);
+			return artifact.eGet(a);
+		}
+	}
+
+	@Override
+	public boolean isPropertySet(Object id) {
+		return false;
+	}
+
+	@Override
+	public void resetPropertyValue(Object id) {
+		// Deliberately do nothing
+	}
+
+	@Override
+	public void setPropertyValue(Object id, Object value) {
+		EStructuralFeature feature = artifact.eClass().getEStructuralFeature((String) id);
+		artifact.eSet(feature, value);
+	}
+
+	private boolean isArtifactWrapper(EObject artifact) {
+		return !artifact.equals(artifactHelper.unwrapWrapper(artifact));
+	}
+
+}
diff --git a/bundles/org.eclipse.capra.ui/src/org/eclipse/capra/ui/adapters/ConnectionAdapter.java b/bundles/org.eclipse.capra.ui/src/org/eclipse/capra/ui/adapters/ConnectionAdapter.java
new file mode 100644
index 0000000..89d5b4b
--- /dev/null
+++ b/bundles/org.eclipse.capra.ui/src/org/eclipse/capra/ui/adapters/ConnectionAdapter.java
@@ -0,0 +1,114 @@
+package org.eclipse.capra.ui.adapters;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.eclipse.capra.core.adapters.Connection;
+import org.eclipse.capra.core.adapters.TracePersistenceAdapter;
+import org.eclipse.capra.core.helpers.ArtifactHelper;
+import org.eclipse.capra.core.helpers.ExtensionPointHelper;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.ui.views.properties.IPropertyDescriptor;
+import org.eclipse.ui.views.properties.IPropertySource;
+import org.eclipse.ui.views.properties.PropertyDescriptor;
+import org.eclipse.ui.views.properties.TextPropertyDescriptor;
+
+/**
+ * An {@link IPropertySource} for trace links. It provides access to all
+ * properties of the underlying {@link Connection}, i.e., all properties that
+ * are defined in the traceability information model.
+ * 
+ * @author Jan-Philipp Steghöfer
+ *
+ */
+public class ConnectionAdapter implements IPropertySource {
+
+	private static enum DescriptorIDs {
+		ORIGIN, TARGETS, TYPE
+	}
+
+	private static final String CATEGORY_NAME = "General";
+
+	private final Connection connection;
+
+	private final ArtifactHelper artifactHelper;
+
+	/**
+	 * Create a new instance based on the provided {@link Connection}.
+	 * 
+	 * @param theItem the connection this adapter represents
+	 */
+	public ConnectionAdapter(Connection theItem) {
+		this.connection = theItem;
+
+		TracePersistenceAdapter persistenceAdapter = ExtensionPointHelper.getTracePersistenceAdapter().get();
+		ResourceSet resourceSet = new ResourceSetImpl();
+		EObject artifactModel = persistenceAdapter.getArtifactWrappers(resourceSet);
+		artifactHelper = new ArtifactHelper(artifactModel);
+	}
+
+	@Override
+	public Object getEditableValue() {
+		return this;
+	}
+
+	@Override
+	public IPropertyDescriptor[] getPropertyDescriptors() {
+		List<IPropertyDescriptor> propertyDescriptors = new ArrayList<>();
+		// Add generic properties of a connection to their own category.
+		PropertyDescriptor originDescriptor = new PropertyDescriptor(DescriptorIDs.ORIGIN, "Origin");
+		originDescriptor.setCategory(CATEGORY_NAME);
+		propertyDescriptors.add(originDescriptor);
+		PropertyDescriptor targetDescriptor = new PropertyDescriptor(DescriptorIDs.TARGETS, "Targets");
+		targetDescriptor.setCategory(CATEGORY_NAME);
+		propertyDescriptors.add(targetDescriptor);
+		PropertyDescriptor typeDescriptor = new PropertyDescriptor(DescriptorIDs.TYPE, "Type");
+		typeDescriptor.setCategory(CATEGORY_NAME);
+		propertyDescriptors.add(typeDescriptor);
+		// All other properties of the underlying class are added without category.
+		propertyDescriptors.addAll(connection.getTlink().eClass().getEAllAttributes().stream()
+				.map(attribute -> new TextPropertyDescriptor(attribute.getName(), attribute.getName()))
+				.collect(Collectors.toList()));
+
+		IPropertyDescriptor[] dummyList = new IPropertyDescriptor[propertyDescriptors.size()];
+		return propertyDescriptors.toArray(dummyList);
+
+	}
+
+	@Override
+	public Object getPropertyValue(Object id) {
+		if (id.equals(DescriptorIDs.ORIGIN)) {
+			return artifactHelper.getArtifactLabel(connection.getOrigin());
+		} else if (id.equals(DescriptorIDs.TARGETS)) {
+			return connection.getTargets().stream().map(t -> artifactHelper.getArtifactLabel(t))
+					.collect(Collectors.toList());
+		} else if (id.equals(DescriptorIDs.TYPE)) {
+			return connection.getTlink().eClass().getName();
+		} else {
+			EStructuralFeature a = connection.getTlink().eClass().getEStructuralFeature((String) id);
+			return connection.getTlink().eGet(a);
+		}
+
+	}
+
+	@Override
+	public boolean isPropertySet(Object id) {
+		return false;
+	}
+
+	@Override
+	public void resetPropertyValue(Object id) {
+		// Deliberately do nothing
+	}
+
+	@Override
+	public void setPropertyValue(Object id, Object value) {
+		EStructuralFeature feature = connection.getTlink().eClass().getEStructuralFeature((String) id);
+		connection.getTlink().eSet(feature, value);
+	}
+
+}
diff --git a/bundles/org.eclipse.capra.ui/src/org/eclipse/capra/ui/adapters/TraceItemAdapterFactory.java b/bundles/org.eclipse.capra.ui/src/org/eclipse/capra/ui/adapters/TraceItemAdapterFactory.java
new file mode 100644
index 0000000..97fdb41
--- /dev/null
+++ b/bundles/org.eclipse.capra.ui/src/org/eclipse/capra/ui/adapters/TraceItemAdapterFactory.java
@@ -0,0 +1,42 @@
+package org.eclipse.capra.ui.adapters;
+
+import org.eclipse.capra.core.adapters.Connection;
+import org.eclipse.core.runtime.IAdapterFactory;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.ui.views.properties.IPropertySource;
+
+/**
+ * Provides adapters for the properties view of trace links and artifacts. This
+ * can be used in visualisations to show the properties of a selected link or a
+ * selected artifact.
+ * <p>
+ * To enable the property view, two conditions have to be met:
+ * <ol>
+ * <li>The view of the visualisation needs to implement a selection provider
+ * that returns a {@link Connection} for a selected trace link and an
+ * {@code EObject} for a selected artifact.
+ * <li>The {@code plugin.xml} of a visualisation needs to contain an extension
+ * of {@code org.eclipse.core.runtime.adapters} that maps the
+ * {@link ConnectionAdapter} and the {@link ArtifactAdapter} to this class.
+ * </ol>
+ * 
+ * @author Jan-Philipp Steghöfer
+ */
+@SuppressWarnings({ "rawtypes", "unchecked" })
+public class TraceItemAdapterFactory implements IAdapterFactory {
+
+	@Override
+	public Object getAdapter(Object adaptableObject, Class adapterType) {
+		if (adapterType == IPropertySource.class && adaptableObject instanceof Connection) {
+			return new ConnectionAdapter((Connection) adaptableObject);
+		} else if (adapterType == IPropertySource.class && adaptableObject instanceof EObject) {
+			return new ArtifactAdapter((EObject) adaptableObject);
+		}
+		return null;
+	}
+
+	@Override
+	public Class[] getAdapterList() {
+		return new Class[] { ConnectionAdapter.class, ArtifactAdapter.class };
+	}
+}