From 90c20e8ffadaff6bed11fabdd1c298af455b5442 Mon Sep 17 00:00:00 2001
From: Simon Barner <barner@fortiss.org>
Date: Wed, 27 Aug 2014 15:25:13 +0000
Subject: [PATCH] Add support for IAnnotatedSpecifications for which multiple
 instances can exist:

- Extend IAnnotationValueProvider with getter/setter methods to access individual instances of a multi-instance IAnnotatedSpecification

- The storage of the instances is based on an EMap<String, V> in the corresponding IAnnotatedSpecification.

- See MultiInstanceAnnotationValueProviderBase for documentation how to create the corresponding meta-model for the annotation types, and of course use it as a basis for specific multi-instance value providers.

- Merge SingleAttributeValueProviderBase and SingleEDataValueProviderBase to SingleEStructuralFeatureValueProviderBase, and generalize it to work on EStructuralFeatures. This is required to support both EAttributes and "contained" EReferences as annotation storage in the meta-model.

- With the above change, cleanup and extend the instantiation of annotation attributes / contained references to EClasses.

- Extend the GenericAnnotationView to enable instantiation of multi-instance annoations.
refs 1841
---
 .../base/ui/annotation/AnnotationEntry.java   |  58 +++-
 ...iInstanceAnnotationTextEditingSupport.java | 104 +++++++
 .../editingsupport/TextEditingSupport.java    |  10 +-
 .../IAnnotationValueProvider.java             |  49 +++-
 ...tiInstanceAnnotationValueProviderBase.java | 121 ++++++++
 .../SingleAttributeValueProviderBase.java     | 116 --------
 ...leEDataTypeAttributeValueProviderBase.java | 118 --------
 ...leEStructuralFeatureValueProviderBase.java | 208 +++++++++++++
 .../SingleEnumAttributeValueProviderBase.java |   6 +-
 .../valueprovider/ValueProviderBase.java      |  38 ++-
 .../view/AnnotationLabelProvider.java         |  12 +-
 .../view/CreateAnnotationInstanceColumn.java  | 277 ++++++++++++++++++
 .../view/GenericAnnotationView.java           | 112 ++++++-
 13 files changed, 954 insertions(+), 275 deletions(-)
 create mode 100644 org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/editingsupport/MultiInstanceAnnotationTextEditingSupport.java
 create mode 100644 org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/MultiInstanceAnnotationValueProviderBase.java
 delete mode 100644 org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/SingleAttributeValueProviderBase.java
 delete mode 100644 org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/SingleEDataTypeAttributeValueProviderBase.java
 create mode 100644 org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/SingleEStructuralFeatureValueProviderBase.java
 create mode 100644 org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/CreateAnnotationInstanceColumn.java

diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/AnnotationEntry.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/AnnotationEntry.java
index e6053d0a4..f6b61e07c 100644
--- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/AnnotationEntry.java
+++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/AnnotationEntry.java
@@ -71,9 +71,9 @@ public final class AnnotationEntry {
 
 	/**
 	 * Indicates whether the given specification contains a value type allowing the storage of
-	 * multiple items (like a list of strings). This methods significantly simplifies the UI logic.
+	 * multiple instances of the annotation (like a list of strings).
 	 */
-	public boolean allowsMultipleValues(Class<? extends IAnnotatedSpecification> clazz) {
+	public boolean allowsMultipleAnnoationInstances(Class<? extends IAnnotatedSpecification> clazz) {
 		for(IAnnotatedSpecification s : specificationsList) {
 			if(clazz.isInstance(s)) {
 				return providerSpecMapping.get(clazz).allowsMultipleAnnotationInstances();
@@ -110,6 +110,25 @@ public final class AnnotationEntry {
 	}
 
 	/** Returns the annotation value */
+	public <V> V getSpecificationValue(Class<? extends IAnnotatedSpecification> clazz,
+			String instanceKey) {
+		for(IAnnotatedSpecification s : specificationsList) {
+			if(clazz.isInstance(s)) {
+				try {
+					return providerSpecMapping.get(clazz).getAnnotationValue(s, instanceKey);
+				} catch(Exception e) {
+					throw null;
+				}
+			}
+		}
+
+		throw null;
+	}
+
+	/**
+	 * Returns the annotation value for a specific instance for a annotation with multi-value
+	 * support.
+	 */
 	public <V> V getSpecificationValue(Class<? extends IAnnotatedSpecification> clazz) {
 		for(IAnnotatedSpecification s : specificationsList) {
 			if(clazz.isInstance(s)) {
@@ -120,6 +139,36 @@ public final class AnnotationEntry {
 		throw null;
 	}
 
+	/**
+	 * Sets a new value for the given specification clazz.
+	 */
+	public <V> void setSpecificationValue(V value, Class<? extends IAnnotatedSpecification> clazz,
+			String instanceKey) throws Exception {
+		for(IAnnotatedSpecification s : specificationsList) {
+			if(clazz.isInstance(s)) {
+				providerSpecMapping.get(clazz).setAnnotationValue(value, s, instanceKey);
+				return;
+			}
+		}
+
+		throw new Exception("Could not find a AnnotationValueProvider for " + clazz.toString());
+	}
+
+	/**
+	 * Sets a new value for the given specification clazz from a {@link String} representation.
+	 */
+	public void setSpecificationValue(String value, Class<? extends IAnnotatedSpecification> clazz,
+			String instanceKey) throws Exception {
+		for(IAnnotatedSpecification s : specificationsList) {
+			if(clazz.isInstance(s)) {
+				providerSpecMapping.get(clazz).setAnnotationValue(value, s, instanceKey);
+				return;
+			}
+		}
+
+		throw new Exception("Could not find a AnnotationValueProvider for " + clazz.toString());
+	}
+
 	/**
 	 * Sets a new value for the given specification clazz.
 	 */
@@ -155,10 +204,11 @@ public final class AnnotationEntry {
 	 * {@code clazz} (for use in the {@link GenericAnnotationView} .
 	 */
 	public EditingSupport createSpecificationEditElement(ColumnViewer viewer,
-			Class<? extends IAnnotatedSpecification> clazz) {
+			Class<? extends IAnnotatedSpecification> clazz, String instanceKey) {
 		for(IAnnotatedSpecification s : specificationsList) {
 			if(clazz.isInstance(s)) {
-				return providerSpecMapping.get(clazz).createEditingSupport(viewer, clazz);
+				return providerSpecMapping.get(clazz).createEditingSupport(viewer, clazz,
+						instanceKey);
 			}
 		}
 
diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/editingsupport/MultiInstanceAnnotationTextEditingSupport.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/editingsupport/MultiInstanceAnnotationTextEditingSupport.java
new file mode 100644
index 000000000..1b9ddcfa8
--- /dev/null
+++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/editingsupport/MultiInstanceAnnotationTextEditingSupport.java
@@ -0,0 +1,104 @@
+/*--------------------------------------------------------------------------+
+$Id$
+|                                                                          |
+| Copyright 2014 fortiss GmbH                                              |
+|                                                                          |
+| Licensed under the Apache License, Version 2.0 (the "License");          |
+| you may not use this file except in compliance with the License.         |
+| You may obtain a copy of the License at                                  |
+|                                                                          |
+|    http://www.apache.org/licenses/LICENSE-2.0                            |
+|                                                                          |
+| Unless required by applicable law or agreed to in writing, software      |
+| distributed under the License is distributed on an "AS IS" BASIS,        |
+| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+| See the License for the specific language governing permissions and      |
+| limitations under the License.                                           |
++--------------------------------------------------------------------------*/
+package org.fortiss.tooling.base.ui.annotation.editingsupport;
+
+import org.eclipse.emf.common.util.EMap;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ColumnViewer;
+import org.eclipse.swt.widgets.Shell;
+import org.fortiss.tooling.base.model.element.IAnnotatedSpecification;
+import org.fortiss.tooling.base.ui.annotation.AnnotationEntry;
+import org.fortiss.tooling.base.ui.annotation.valueprovider.MultiInstanceAnnotationValueProviderBase;
+import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
+import org.fortiss.tooling.kernel.service.IPersistencyService;
+
+/**
+ * This class extends {@link TextEditingSupport} to support text annotations for which multiple
+ * instances can exist.
+ * 
+ * @see MultiInstanceAnnotationValueProviderBase
+ * 
+ * @author diewald, barner
+ * @author $Author$
+ * @version $Rev$
+ * @ConQAT.Rating RED Hash:
+ */
+public class MultiInstanceAnnotationTextEditingSupport extends TextEditingSupport {
+
+	/** Instance key to identify the corresponding instance of the annotation */
+	private String instanceKey;
+
+	/** Constructs a new {@link MultiInstanceAnnotationTextEditingSupport} for a specific column. */
+	public MultiInstanceAnnotationTextEditingSupport(ColumnViewer viewer,
+			Class<? extends IAnnotatedSpecification> clazz, String instanceKey) {
+		super(viewer, clazz);
+
+		this.instanceKey = instanceKey;
+	}
+
+	/** {@inheritDoc} */
+	@SuppressWarnings("unchecked")
+	@Override
+	protected Object getValue(Object element) {
+		String rval = null;
+		if(element instanceof AnnotationEntry) {
+			AnnotationEntry data = (AnnotationEntry)element;
+			if(data.getSpecificationValue(specClass) != null) {
+				rval =
+						((EMap<String, String>)data.getSpecificationValue(specClass))
+								.get(instanceKey);
+			}
+		}
+		return rval != null ? rval : "";
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	protected void setValue(Object element, final Object value) {
+		if(element instanceof AnnotationEntry && value instanceof String) {
+			final AnnotationEntry entry = (AnnotationEntry)element;
+
+			if(!value.equals(entry.getSpecificationValue(specClass, instanceKey))) {
+
+				ITopLevelElement modelContext =
+						IPersistencyService.INSTANCE.getTopLevelElementFor(entry.getModelElement());
+				modelContext.runAsCommand(new Runnable() {
+
+					@Override
+					public void run() {
+						try {
+							entry.setSpecificationValue(value, specClass, instanceKey);
+						} catch(IllegalArgumentException e) {
+							// e.printStackTrace();
+							MessageDialog
+									.openError(
+											new Shell(),
+											"ERROR",
+											"The value you entered does not have the desired type.\nDetailed message:\n" +
+													e.getMessage());
+						} catch(Exception e) {
+							MessageDialog.openError(new Shell(), "ERROR", e.getMessage());
+						}
+					}
+				});
+				this.getViewer().refresh(true);
+			}
+
+		}
+	}
+}
diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/editingsupport/TextEditingSupport.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/editingsupport/TextEditingSupport.java
index ba152d6a6..09179fdbc 100644
--- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/editingsupport/TextEditingSupport.java
+++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/editingsupport/TextEditingSupport.java
@@ -82,24 +82,24 @@ public class TextEditingSupport extends EditingSupport {
 				return value.toString();
 			}
 		}
-		return "-";
+		return "";
 	}
 
 	/** {@inheritDoc} */
 	@Override
 	protected void setValue(Object element, final Object value) {
 		if(element instanceof AnnotationEntry && value instanceof String) {
-			final AnnotationEntry data = (AnnotationEntry)element;
+			final AnnotationEntry entry = (AnnotationEntry)element;
 
-			if(!value.equals(data.getSpecificationValue(specClass))) {
+			if(!value.equals(entry.getSpecificationValue(specClass))) {
 				ITopLevelElement modelContext =
-						IPersistencyService.INSTANCE.getTopLevelElementFor(data.getModelElement());
+						IPersistencyService.INSTANCE.getTopLevelElementFor(entry.getModelElement());
 				modelContext.runAsCommand(new Runnable() {
 
 					@Override
 					public void run() {
 						try {
-							data.setSpecificationValue((String)value, specClass);
+							entry.setSpecificationValue((String)value, specClass);
 						} catch(IllegalArgumentException e) {
 							// e.printStackTrace();
 							MessageDialog
diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/IAnnotationValueProvider.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/IAnnotationValueProvider.java
index 99394f9db..386f92a76 100644
--- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/IAnnotationValueProvider.java
+++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/IAnnotationValueProvider.java
@@ -67,10 +67,10 @@ public interface IAnnotationValueProvider<T extends IAnnotatedSpecification> ext
 		IEObjectAware<IModelElement> {
 
 	/**
-	 * Predicate whether multiple instances of the {@link IAnnotatedSpecification} managed
-	 * by this {@link IAnnotationValueProvider} can exist. For instance, the
-	 * {@link GenericAnnotationView} will in this case create UI controls to enable the creation of
-	 * these instances.
+	 * Predicate whether the {@link IAnnotatedSpecification} managed
+	 * by this {@link IAnnotationValueProvider} provides support for multiple (named) instances. For
+	 * instance, the {@link GenericAnnotationView} will in this case create UI controls to enable
+	 * the creation of these instances.
 	 */
 	public boolean allowsMultipleAnnotationInstances();
 
@@ -87,12 +87,16 @@ public interface IAnnotationValueProvider<T extends IAnnotatedSpecification> ext
 	 */
 	public boolean setAnnotationName(String name, T specification);
 
-	/** Returns the value of the annotation in the user-specified data-type. */
+	/** Returns the value of the annotation. */
 	public <U> U getAnnotationValue(T specification);
 
 	/**
-	 * Sets a new value for the annotation, taking an instance the user-specified data type has an
-	 * input.
+	 * Returns the value of a multi-instance annotation's instance denoted by {@code instanceKey}.
+	 */
+	public <U> U getAnnotationValue(T specification, String instanceKey) throws Exception;
+
+	/**
+	 * Sets a new value for the annotation.
 	 * 
 	 * @throws Exception
 	 *             is thrown if the conversion from the UI internal value representation ({@code U})
@@ -102,7 +106,7 @@ public interface IAnnotationValueProvider<T extends IAnnotatedSpecification> ext
 	public <U> void setAnnotationValue(U value, T specification) throws Exception;
 
 	/**
-	 * Sets a new value in the annotation from a {@link String} representation.
+	 * Sets a new value in the annotation from a {@link String} initializer.
 	 * 
 	 * @throws Exception
 	 *             is thrown if the conversion from {@link String} to the respective specialization
@@ -111,14 +115,39 @@ public interface IAnnotationValueProvider<T extends IAnnotatedSpecification> ext
 	 */
 	public void setAnnotationValue(String value, T specification) throws Exception;
 
+	/**
+	 * Sets a new value for a multi-instance annotation's instance denoted by {@code instanceKey}.
+	 * 
+	 * @throws Exception
+	 *             is thrown if the conversion from the UI internal value representation ({@code U})
+	 *             to the respective specialization of {@link IAnnotatedSpecification} has failed,
+	 *             or if this operation is not available.
+	 */
+	public <U> void setAnnotationValue(U value, T specification, String instanceKey)
+			throws Exception;
+
+	/**
+	 * Sets a new value for a multi-instance annotation's instance denoted by {@code instanceKey}
+	 * from a {@link String} initializer.
+	 * 
+	 * @throws Exception
+	 *             is thrown if the conversion from {@link String} to the respective specialization
+	 *             of {@link IAnnotatedSpecification} has failed, or if this operation is not
+	 *             available.
+	 */
+	public void setAnnotationValue(String value, T specification, String instanceKey)
+			throws Exception;
+
 	/**
 	 * Creates and returns the {@link EditingSupport} support element for the table-based
 	 * {@link GenericAnnotationView}. {@link IAnnotationValueProvider}s for specialized
 	 * {@link IAnnotatedSpecification} may choose to provide a dedicated, custom
-	 * {@link EditingSupport}.
+	 * {@link EditingSupport}. For annotations whose {@link IAnnotationValueProvider}s support
+	 * multiple instances, an {@code instanceKey} to identify the corresponding instance of the
+	 * {@link IAnnotatedSpecification} needs to be provided.
 	 */
 	public EditingSupport createEditingSupport(ColumnViewer viewer,
-			Class<? extends IAnnotatedSpecification> clazz);
+			Class<? extends IAnnotatedSpecification> clazz, String instanceKey);
 
 	/**
 	 * Factory method that creates a new {@link IAnnotatedSpecification} specialization of type T to
diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/MultiInstanceAnnotationValueProviderBase.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/MultiInstanceAnnotationValueProviderBase.java
new file mode 100644
index 000000000..832cc75ba
--- /dev/null
+++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/MultiInstanceAnnotationValueProviderBase.java
@@ -0,0 +1,121 @@
+/*--------------------------------------------------------------------------+
+$Id$
+|                                                                          |
+| Copyright 2014 fortiss GmbH                                              |
+|                                                                          |
+| Licensed under the Apache License, Version 2.0 (the "License");          |
+| you may not use this file except in compliance with the License.         |
+| You may obtain a copy of the License at                                  |
+|                                                                          |
+|    http://www.apache.org/licenses/LICENSE-2.0                            |
+|                                                                          |
+| Unless required by applicable law or agreed to in writing, software      |
+| distributed under the License is distributed on an "AS IS" BASIS,        |
+| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+| See the License for the specific language governing permissions and      |
+| limitations under the License.                                           |
++--------------------------------------------------------------------------*/
+package org.fortiss.tooling.base.ui.annotation.valueprovider;
+
+import org.eclipse.emf.common.util.EMap;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EDataType;
+import org.eclipse.emf.ecore.EFactory;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.jface.viewers.ColumnViewer;
+import org.eclipse.jface.viewers.EditingSupport;
+import org.fortiss.tooling.base.model.element.IAnnotatedSpecification;
+import org.fortiss.tooling.base.ui.annotation.editingsupport.MultiInstanceAnnotationTextEditingSupport;
+
+/**
+ * <p>
+ * Base class for {@link IAnnotationValueProvider}s that support {@link IAnnotatedSpecification} for
+ * which multiple instances can exist. For each model element, a single instance of this
+ * {@link IAnnotatedSpecification} exists whose storage is implemented by a {@link EMap}
+ * {@code <EString, V>}, where the key is used as the instance name, and V is an EClass depicting
+ * the annotation type (e.g., {@code EString, EIntegerObject, ...}.
+ * </p>
+ * 
+ * <p>
+ * The underlying {@link EMap} must be declared in the {@link IAnnotatedSpecification}'s meta-model
+ * as detailed here: <a href="http://wiki.eclipse.org/EMF/FAQ#How_do_I_create_a_Map_in_EMF.3F">
+ * http://wiki.eclipse.org/EMF/FAQ#How_do_I_create_a_Map_in_EMF.3F</a>.
+ * </p>
+ * 
+ * @author diewald, barner
+ * @author $Author$
+ * @version $Rev$
+ * @ConQAT.Rating RED Hash:
+ */
+public abstract class MultiInstanceAnnotationValueProviderBase<T extends IAnnotatedSpecification>
+		extends SingleEStructuralFeatureValueProviderBase<T> {
+
+	/**
+	 * {@link EDataType} of the value type V of the underlying EMap<String, V> storing the annotation
+	 * instances.
+	 */
+	EDataType valueDataType;
+
+	/**
+	 * {@link EFactory} to construct (in particular from a {@link String} representation instances of
+	 * the value type V of the underlying EMap<String, V> storing the annotation instances.
+	 */
+	EFactory valueFactory;
+
+	/**
+	 * Constructs a multi-instance enabled {@link IAnnotationValueProvider} for a
+	 * {@link IAnnotatedSpecification} that whose storage is implemented by a single
+	 * {@link EStructuralFeature}.
+	 */
+	public MultiInstanceAnnotationValueProviderBase(EClass annotatedSpecificationEClass,
+			EFactory annotationFactory, EStructuralFeature structuralFeature,
+			EFactory attributeFactory, EDataType valueDataType, EFactory valueFactory) {
+		super(annotatedSpecificationEClass, annotationFactory, structuralFeature, attributeFactory);
+		this.valueDataType = valueDataType;
+		this.valueFactory = valueFactory;
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public boolean allowsMultipleAnnotationInstances() {
+		return true;
+	}
+
+	/** {@inheritDoc} */
+	@SuppressWarnings("unchecked")
+	@Override
+	public <V> V getAnnotationValue(T spec, String instanceKey) {
+		// Return value of current instance (entry map containing all instances of the annotation)
+		return ((EMap<String, V>)getAnnotationValue(spec)).get(instanceKey);
+
+	}
+
+	/** {@inheritDoc} */
+	@SuppressWarnings("unchecked")
+	@Override
+	public <V> void setAnnotationValue(V value, T specification, String instanceKey) {
+		if(value instanceof String) {
+			((EMap<String, V>)getAnnotationValue(specification)).put(instanceKey,
+					(V)valueFactory.createFromString(valueDataType, (String)value));
+		} else {
+			((EMap<String, V>)getAnnotationValue(specification)).put(instanceKey, value);
+		}
+
+	}
+
+	/** {@inheritDoc} */
+	@SuppressWarnings("unchecked")
+	@Override
+	public void setAnnotationValue(String value, T specification, String instanceKey) {
+		((EMap<String, String>)getAnnotationValue(specification)).put(instanceKey, value);
+
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public EditingSupport createEditingSupport(ColumnViewer viewer,
+			Class<? extends IAnnotatedSpecification> clazz, String instanceKey) {
+
+		return new MultiInstanceAnnotationTextEditingSupport(viewer, clazz, instanceKey);
+	}
+}
diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/SingleAttributeValueProviderBase.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/SingleAttributeValueProviderBase.java
deleted file mode 100644
index fe2649995..000000000
--- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/SingleAttributeValueProviderBase.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*--------------------------------------------------------------------------+
-$Id$
-|                                                                          |
-| Copyright 2014 ForTISS GmbH                     |
-|                                                                          |
-| Licensed under the Apache License, Version 2.0 (the "License");          |
-| you may not use this file except in compliance with the License.         |
-| You may obtain a copy of the License at                                  |
-|                                                                          |
-|    http://www.apache.org/licenses/LICENSE-2.0                            |
-|                                                                          |
-| Unless required by applicable law or agreed to in writing, software      |
-| distributed under the License is distributed on an "AS IS" BASIS,        |
-| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
-| See the License for the specific language governing permissions and      |
-| limitations under the License.                                           |
-+--------------------------------------------------------------------------*/
-package org.fortiss.tooling.base.ui.annotation.valueprovider;
-
-import org.eclipse.emf.ecore.EAttribute;
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EFactory;
-import org.fortiss.tooling.base.model.element.IAnnotatedSpecification;
-import org.fortiss.tooling.base.model.element.IModelElement;
-import org.fortiss.tooling.base.model.element.IModelElementSpecification;
-
-/**
- * Base class for {@link IAnnotationValueProvider}s that manages a single {@link EAttribute}
- * contained by a {@link IAnnotatedSpecification}.
- * 
- * @author barner
- * @author $Author$
- * @version $Rev$
- * @ConQAT.Rating RED Hash:
- */
-public abstract class SingleAttributeValueProviderBase<T extends IAnnotatedSpecification> extends
-		ValueProviderBase<T> {
-
-	/**
-	 * {@link EClass} of {@link IAnnotatedSpecification} that contains the respective attribute and
-	 * that is managed by this {@link IAnnotationValueProvider}.
-	 */
-	final protected EClass annotatedSpecificationEClass;
-
-	/**
-	 * {@link EFactory} of ECore model that contains {@link IAnnotatedSpecification} identified by
-	 * {@code annotatedSpecificationEClass} (used to create new instances of the annotation).
-	 */
-	final protected EFactory annotationFactory;
-
-	/**
-	 * The attribute of the {@link IAnnotatedSpecification} that is managed by this
-	 * {@link IAnnotationValueProvider}.
-	 */
-	final protected EAttribute attribute;
-
-	/**
-	 * Constructs a {@link IAnnotationValueProvider} for a {@link IAnnotatedSpecification} that
-	 * whose storage is implemented by a single attribute.
-	 */
-	public SingleAttributeValueProviderBase(EClass annotatedSpecificationEClass, EFactory eFactory,
-			EAttribute attribute) {
-		this.annotatedSpecificationEClass = annotatedSpecificationEClass;
-		this.annotationFactory = eFactory;
-		this.attribute = attribute;
-	}
-
-	/** {@inheritDoc} */
-	@Override
-	public <U> void setAnnotationValue(U value, T specification) throws Exception {
-		specification.eSet(attribute, value);
-	}
-
-	/** {@inheritDoc} */
-	@SuppressWarnings("unchecked")
-	@Override
-	public <U> U getAnnotationValue(T specification) {
-		return (U)specification.eGet(attribute);
-	}
-
-	/**
-	 * Creates a new instance of the attribute (use to populate newly created annotation instances
-	 * created in {@link #getAnnotatedSpecificationForModelElement(IModelElement)}.
-	 */
-	protected abstract Object createAttributeValue() throws Exception;
-
-	/** {@inheritDoc} */
-	@SuppressWarnings("unchecked")
-	@Override
-	public T getAnnotatedSpecificationForModelElement(IModelElement element) throws Exception {
-		// Return existing annotation
-		for(IModelElementSpecification specification : element.getSpecifications()) {
-			if(annotatedSpecificationEClass.equals(specification.eClass())) {
-				return (T)specification;
-			}
-		}
-
-		// Create annotation
-		T specification = (T)annotationFactory.create(annotatedSpecificationEClass);
-
-		// Create an set annotation attribute
-		specification.eSet(attribute, createAttributeValue());
-
-		// Hook specification to model element
-		element.addSpecification(specification);
-
-		return specification;
-	}
-
-	/** {@inheritDoc} */
-	@SuppressWarnings("unchecked")
-	@Override
-	public Class<T> getAnnotationClazz() {
-		return (Class<T>)annotatedSpecificationEClass.getClass();
-	}
-}
diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/SingleEDataTypeAttributeValueProviderBase.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/SingleEDataTypeAttributeValueProviderBase.java
deleted file mode 100644
index 35590a870..000000000
--- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/SingleEDataTypeAttributeValueProviderBase.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*--------------------------------------------------------------------------+
-$Id$
-|                                                                          |
-| Copyright 2014 ForTISS GmbH                     |
-|                                                                          |
-| Licensed under the Apache License, Version 2.0 (the "License");          |
-| you may not use this file except in compliance with the License.         |
-| You may obtain a copy of the License at                                  |
-|                                                                          |
-|    http://www.apache.org/licenses/LICENSE-2.0                            |
-|                                                                          |
-| Unless required by applicable law or agreed to in writing, software      |
-| distributed under the License is distributed on an "AS IS" BASIS,        |
-| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
-| See the License for the specific language governing permissions and      |
-| limitations under the License.                                           |
-+--------------------------------------------------------------------------*/
-package org.fortiss.tooling.base.ui.annotation.valueprovider;
-
-import org.eclipse.emf.ecore.EAttribute;
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EDataType;
-import org.eclipse.emf.ecore.EFactory;
-import org.fortiss.tooling.base.model.element.IAnnotatedSpecification;
-
-/**
- * Base class for {@link IAnnotationValueProvider}s that manages a single {@link EDataType}
- * attribute contained in a {@link IAnnotatedSpecification} (e.g., including primitive data types
- * such as {@code int, double, ...}).
- * 
- * @author barner
- * @author $Author$
- * @version $Rev$
- * @ConQAT.Rating RED Hash:
- */
-public abstract class SingleEDataTypeAttributeValueProviderBase<T extends IAnnotatedSpecification>
-		extends SingleAttributeValueProviderBase<T> {
-
-	/**
-	 * {@link EDataType} of the primitive attribute used to implemented the storage
-	 * of the underlying {@link IAnnotatedSpecification}.
-	 */
-	final protected EDataType attributeEDataType;
-
-	/**
-	 * String representation of default value used to initialize the primitive attribute of the
-	 * underlying {@link IAnnotatedSpecification}. If it is {@code null}, {@link EDataType}'s
-	 * default value will be used.
-	 */
-	final protected String attributeDefaultValue;
-
-	/**
-	 * {@link EFactory} of used to create new attribute instances.
-	 */
-	final protected EFactory attributeFactory;
-
-	/**
-	 * Constructs a {@link IAnnotationValueProvider} for a {@link IAnnotatedSpecification} that
-	 * that manages a single {@link EDataType} attribute contained in a
-	 * {@link IAnnotatedSpecification}. New instances of the attribute will be initialized to the
-	 * respective default value.
-	 */
-	public SingleEDataTypeAttributeValueProviderBase(EClass annotatedSpecificationEClass,
-			EFactory annotationFactory, EAttribute attribute, EDataType attributeEDataType,
-			EFactory attributeFactory) {
-		this(annotatedSpecificationEClass, annotationFactory, attribute, attributeEDataType,
-				attributeFactory, null);
-	}
-
-	/**
-	 * Constructs a {@link IAnnotationValueProvider} for a {@link IAnnotatedSpecification} that
-	 * that that manages a single {@link EDataType} attribute contained in a
-	 * {@link IAnnotatedSpecification}. The constructor assumes that an instance of the attribute
-	 * type can initialized from a {@link String}.
-	 */
-	public SingleEDataTypeAttributeValueProviderBase(EClass annotatedSpecificationEClass,
-			EFactory annotationFactory, EAttribute attribute, EDataType attributeEDataType,
-			EFactory attributeFactory, final String attributeDefaultValue) {
-		super(annotatedSpecificationEClass, annotationFactory, attribute);
-		this.attributeEDataType = attributeEDataType;
-		this.attributeDefaultValue = attributeDefaultValue;
-		this.attributeFactory = attributeFactory;
-	}
-
-	/** {@inheritDoc} */
-	@Override
-	public void setAnnotationValue(String value, T specification) throws Exception {
-		setAnnotationValue(attributeFactory.createFromString(attributeEDataType, value),
-				specification);
-	}
-
-	/** {@inheritDoc} */
-	@Override
-	protected Object createAttributeValue() throws Exception {
-		if(attributeDefaultValue != null) {
-			// Use default value if it has been specified
-			return attributeFactory.createFromString(attributeEDataType, attributeDefaultValue);
-		}
-
-		// Return data types default value, it it is non-null.
-		Object rval = attributeEDataType.getDefaultValue();
-
-		if(rval != null) {
-			return rval;
-		}
-
-		try {
-			// Try to construct attribute from empty string
-			rval = attributeFactory.createFromString(attributeEDataType, "");
-		} catch(NumberFormatException e) {
-			// Last try: initialize numbers with 0 (throws NumberFormatException if not
-			// successful).
-			rval = attributeFactory.createFromString(attributeEDataType, "0");
-		}
-
-		return rval;
-	}
-}
diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/SingleEStructuralFeatureValueProviderBase.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/SingleEStructuralFeatureValueProviderBase.java
new file mode 100644
index 000000000..1a33ffcc4
--- /dev/null
+++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/SingleEStructuralFeatureValueProviderBase.java
@@ -0,0 +1,208 @@
+/*--------------------------------------------------------------------------+
+$Id$
+|                                                                          |
+| Copyright 2014 ForTISS GmbH                     |
+|                                                                          |
+| Licensed under the Apache License, Version 2.0 (the "License");          |
+| you may not use this file except in compliance with the License.         |
+| You may obtain a copy of the License at                                  |
+|                                                                          |
+|    http://www.apache.org/licenses/LICENSE-2.0                            |
+|                                                                          |
+| Unless required by applicable law or agreed to in writing, software      |
+| distributed under the License is distributed on an "AS IS" BASIS,        |
+| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+| See the License for the specific language governing permissions and      |
+| limitations under the License.                                           |
++--------------------------------------------------------------------------*/
+package org.fortiss.tooling.base.ui.annotation.valueprovider;
+
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EDataType;
+import org.eclipse.emf.ecore.EFactory;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.fortiss.tooling.base.model.element.IAnnotatedSpecification;
+import org.fortiss.tooling.base.model.element.IModelElement;
+import org.fortiss.tooling.base.model.element.IModelElementSpecification;
+
+/**
+ * Base class for {@link IAnnotationValueProvider}s that manages a single {@link EStructuralFeature}
+ * contained by a {@link IAnnotatedSpecification}.
+ * 
+ * @author barner
+ * @author $Author$
+ * @version $Rev$
+ * @ConQAT.Rating RED Hash:
+ */
+public abstract class SingleEStructuralFeatureValueProviderBase<T extends IAnnotatedSpecification>
+		extends ValueProviderBase<T> {
+
+	/**
+	 * {@link EClass} of {@link IAnnotatedSpecification} that contains the respective structural
+	 * feature and that is managed by this {@link IAnnotationValueProvider}.
+	 */
+	final protected EClass annotatedSpecificationEClass;
+
+	/**
+	 * {@link EFactory} of ECore model that contains {@link IAnnotatedSpecification} identified by
+	 * {@code annotatedSpecificationEClass} (used to create new instances of the annotation).
+	 */
+	final protected EFactory annotationFactory;
+
+	/**
+	 * The structural feature of the {@link IAnnotatedSpecification} that is managed by this
+	 * {@link IAnnotationValueProvider}.
+	 */
+	final protected EStructuralFeature structuralFeature;
+
+	/**
+	 * {@link EFactory} of used to create new attribute instances.
+	 */
+	final protected EFactory structuralFeatureFactory;
+
+	/**
+	 * String representation of default value used to initialize the primitive attribute of the
+	 * underlying {@link IAnnotatedSpecification}. If it is {@code null}, {@link EDataType}'s
+	 * default value will be used.
+	 */
+	final protected String structuralFeatureDefaultValue;
+
+	/**
+	 * Constructs a {@link IAnnotationValueProvider} for a {@link IAnnotatedSpecification} that
+	 * whose storage is implemented by a single {@link EStructuralFeature}.
+	 */
+	public SingleEStructuralFeatureValueProviderBase(EClass annotatedSpecificationEClass,
+			EFactory annotationFactory, EStructuralFeature structuralFeature,
+			EFactory structuralFeatureFactory) {
+		this(annotatedSpecificationEClass, annotationFactory, structuralFeature,
+				structuralFeatureFactory, null);
+	}
+
+	/**
+	 * Constructs a {@link IAnnotationValueProvider} for a {@link IAnnotatedSpecification} that
+	 * whose storage is implemented by a single {@link EStructuralFeature}.
+	 */
+	public SingleEStructuralFeatureValueProviderBase(EClass annotatedSpecificationEClass,
+			EFactory annotationFactory, EStructuralFeature structuralFeature,
+			EFactory structuralFeatureFactory, final String structuralFeatureDefaultValue) {
+
+		this.annotatedSpecificationEClass = annotatedSpecificationEClass;
+		this.annotationFactory = annotationFactory;
+		this.structuralFeature = structuralFeature;
+		this.structuralFeatureFactory = structuralFeatureFactory;
+		this.structuralFeatureDefaultValue = structuralFeatureDefaultValue;
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public <U> void setAnnotationValue(U value, T specification) throws Exception {
+		specification.eSet(structuralFeature, value);
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public void setAnnotationValue(String value, T specification) throws Exception {
+		if(structuralFeature instanceof EAttribute) {
+			setAnnotationValue(
+					structuralFeatureFactory.createFromString(
+							((EAttribute)structuralFeature).getEAttributeType(), value),
+					specification);
+		} else {
+			throw new Exception(
+					"setAnnotationValue(String, T) is not supported / has not been implemented the annotation type " +
+							structuralFeature.getEType().getName() +
+							"(specification class: " +
+							specification.getClass() + ").");
+		}
+	}
+
+	/** {@inheritDoc} */
+	@SuppressWarnings("unchecked")
+	@Override
+	public <U> U getAnnotationValue(T specification) {
+		return (U)specification.eGet(structuralFeature);
+	}
+
+	/**
+	 * Creates a new instance of the {@link EStructuralFeature} (use to populate newly created
+	 * annotation instances created in
+	 * {@link #getAnnotatedSpecificationForModelElement(IModelElement)}.
+	 */
+	protected Object createStructuralFeatureInstance() throws Exception {
+		if(structuralFeature instanceof EAttribute) {
+
+			EDataType attributeEDataType = ((EAttribute)structuralFeature).getEAttributeType();
+
+			if(structuralFeatureDefaultValue != null) {
+				// Use default value if it has been specified
+				return structuralFeatureFactory.createFromString(attributeEDataType,
+						structuralFeatureDefaultValue);
+			}
+
+			// Return data types default value, if it is non-null.
+			Object rval = attributeEDataType.getDefaultValue();
+
+			if(rval != null) {
+				return rval;
+			}
+
+			try {
+				// Try to construct attribute from empty string
+				rval = structuralFeatureFactory.createFromString(attributeEDataType, "");
+			} catch(NumberFormatException e) {
+				// Last try: initialize numbers with 0 (throws NumberFormatException if not
+				// successful).
+				rval = structuralFeatureFactory.createFromString(attributeEDataType, "0");
+			}
+
+			return rval;
+		} else if(structuralFeature instanceof EReference) {
+			EReference reference = (EReference)structuralFeature;
+			if(reference.isContainment()) {
+				// EClasses attached to contained EReferences are created lazily by the
+				// corresponding generated code on the first access (i.e., also during get / "read")
+				return null;
+			}
+			return structuralFeatureFactory.create(reference.getEReferenceType());
+		} else {
+			throw new Exception(
+					"createStructuralFeatureInstance() is not supported / has not been implemented the annotation type " +
+							structuralFeature.getEType().getName() + ".");
+		}
+	}
+
+	/** {@inheritDoc} */
+	@SuppressWarnings("unchecked")
+	@Override
+	public T getAnnotatedSpecificationForModelElement(IModelElement element) throws Exception {
+		// Return existing annotation
+		for(IModelElementSpecification specification : element.getSpecifications()) {
+			if(annotatedSpecificationEClass.equals(specification.eClass())) {
+				return (T)specification;
+			}
+		}
+
+		// Create annotation
+		T specification = (T)annotationFactory.create(annotatedSpecificationEClass);
+
+		// Create and set structural feature implementing the annotation
+		Object structuralFeatureVal = createStructuralFeatureInstance();
+		if(structuralFeatureVal != null) {
+			specification.eSet(structuralFeature, structuralFeatureVal);
+		}
+
+		// Hook specification to model element
+		element.addSpecification(specification);
+
+		return specification;
+	}
+
+	/** {@inheritDoc} */
+	@SuppressWarnings("unchecked")
+	@Override
+	public Class<T> getAnnotationClazz() {
+		return (Class<T>)annotatedSpecificationEClass.getClass();
+	}
+}
diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/SingleEnumAttributeValueProviderBase.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/SingleEnumAttributeValueProviderBase.java
index cc0a39c73..491b128fa 100644
--- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/SingleEnumAttributeValueProviderBase.java
+++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/SingleEnumAttributeValueProviderBase.java
@@ -42,7 +42,7 @@ import org.fortiss.tooling.base.ui.annotation.editingsupport.ComboBoxEditingSupp
  * @ConQAT.Rating RED Hash:
  */
 public abstract class SingleEnumAttributeValueProviderBase<T extends IAnnotatedSpecification>
-		extends SingleEDataTypeAttributeValueProviderBase<T> {
+		extends SingleEStructuralFeatureValueProviderBase<T> {
 
 	/** Data type of the enumeration managed by this {@link IAnnotationValueProvider} */
 	private EEnum eEnum;
@@ -68,7 +68,7 @@ public abstract class SingleEnumAttributeValueProviderBase<T extends IAnnotatedS
 	public SingleEnumAttributeValueProviderBase(EClass annotatedSpecificationEClass,
 			EFactory annotationFactory, EAttribute attribute, EEnum eEnum,
 			EFactory attributeFactory, final String attributeDefaultValue) {
-		super(annotatedSpecificationEClass, annotationFactory, attribute, eEnum, attributeFactory,
+		super(annotatedSpecificationEClass, annotationFactory, attribute, attributeFactory,
 				attributeDefaultValue);
 		this.eEnum = eEnum;
 	}
@@ -76,7 +76,7 @@ public abstract class SingleEnumAttributeValueProviderBase<T extends IAnnotatedS
 	/** {@inheritDoc} */
 	@Override
 	public EditingSupport createEditingSupport(ColumnViewer viewer,
-			Class<? extends IAnnotatedSpecification> clazz) {
+			Class<? extends IAnnotatedSpecification> clazz, String instanceKey) {
 
 		List<String> enumValues = new ArrayList<String>();
 		for(EEnumLiteral e : eEnum.getELiterals()) {
diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/ValueProviderBase.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/ValueProviderBase.java
index 0422a2bd5..82bcc9b28 100644
--- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/ValueProviderBase.java
+++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/ValueProviderBase.java
@@ -43,20 +43,40 @@ public abstract class ValueProviderBase<T extends IAnnotatedSpecification> imple
 		return false;
 	}
 
+	/** {@inheritDoc} */
+	@Override
+	public <U> U getAnnotationValue(T specification, String instanceKey) throws Exception {
+		return getAnnotationValue(specification);
+	}
+
 	/** {@inheritDoc} */
 	@Override
 	public void setAnnotationValue(String value, T specification) throws Exception {
+		setAnnotationValue(value, specification, null);
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public <U> void setAnnotationValue(U value, T specification) throws Exception {
+		setAnnotationValue(value, specification, null);
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public void setAnnotationValue(String value, T specification, String instanceKey)
+			throws Exception {
 		throw new Exception(
 				"setAnnotationValue(String) is not supported / has not been implemented for annotations of type " +
-						getClass());
+						specification.getClass());
 	}
 
 	/** {@inheritDoc} */
 	@Override
-	public <U> void setAnnotationValue(U value, T specification) throws Exception {
+	public <U> void setAnnotationValue(U value, T specification, String instanceKey)
+			throws Exception {
 		throw new Exception(
 				"setAnnotationValue(U) is not supported / has not been implemented for annotations of type " +
-						getClass());
+						specification.getClass());
 	}
 
 	/** {@inheritDoc} */
@@ -68,12 +88,22 @@ public abstract class ValueProviderBase<T extends IAnnotatedSpecification> imple
 	/** {@inheritDoc} */
 	@Override
 	public EditingSupport createEditingSupport(ColumnViewer viewer,
-			Class<? extends IAnnotatedSpecification> clazz) {
+			Class<? extends IAnnotatedSpecification> clazz, String instanceKey) {
 
 		// Default to text editing cell.
 		return new TextEditingSupport(viewer, clazz);
 	}
 
+	/**
+	 * Creates the editing support without referring to the optional {@code userData} (see
+	 * {@link #createEditingSupport(ColumnViewer, Class, String)}).
+	 */
+	public EditingSupport createEditingSupport(ColumnViewer viewer,
+			Class<? extends IAnnotatedSpecification> clazz) {
+
+		return createEditingSupport(viewer, clazz, null);
+	}
+
 	/** {@inheritDoc} */
 	@Override
 	public List<Class<? extends EObject>> excludeModelElementTypeFromAnnotatedSpecification() {
diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/AnnotationLabelProvider.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/AnnotationLabelProvider.java
index 7922a2956..264049cde 100644
--- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/AnnotationLabelProvider.java
+++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/AnnotationLabelProvider.java
@@ -39,17 +39,22 @@ public class AnnotationLabelProvider extends ColumnLabelProvider {
 	/** Contains the basic annotation view class */
 	protected AnnotationViewPartBase parentView;
 
+	/** String holding the key of which identifies the value to be displayed */
+	protected String instanceKey;
+
 	/**
 	 * @param class1
 	 *            specification which provides the values to be displayed
 	 * 
 	 * @param parent
 	 *            view required to retrieve the selected elements
+	 * @param instanceKey
 	 */
 	public AnnotationLabelProvider(Class<? extends IAnnotatedSpecification> class1,
-			AnnotationViewPartBase parent) {
+			AnnotationViewPartBase parent, String instanceKey) {
 		specClass = class1;
 		parentView = parent;
+		this.instanceKey = instanceKey;
 	}
 
 	/** {@inheritDoc} */
@@ -57,12 +62,13 @@ public class AnnotationLabelProvider extends ColumnLabelProvider {
 	public String getText(Object element) {
 		if(element instanceof AnnotationEntry) {
 			AnnotationEntry annotationEntry = (AnnotationEntry)element;
-			Object value = annotationEntry.getSpecificationValue(specClass);
+
+			Object value = annotationEntry.getSpecificationValue(specClass, instanceKey);
 			if(value != null) {
 				return value.toString();
 			}
 		}
-		return "-";
+		return "";
 	}
 
 	/** {@inheritDoc} */
diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/CreateAnnotationInstanceColumn.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/CreateAnnotationInstanceColumn.java
new file mode 100644
index 000000000..24678fe1f
--- /dev/null
+++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/CreateAnnotationInstanceColumn.java
@@ -0,0 +1,277 @@
+/*--------------------------------------------------------------------------+
+$Id$
+|                                                                          |
+| Copyright 2014 fortiss GmbH                                              |
+|                                                                          |
+| Licensed under the Apache License, Version 2.0 (the "License");          |
+| you may not use this file except in compliance with the License.         |
+| You may obtain a copy of the License at                                  |
+|                                                                          |
+|    http://www.apache.org/licenses/LICENSE-2.0                            |
+|                                                                          |
+| Unless required by applicable law or agreed to in writing, software      |
+| distributed under the License is distributed on an "AS IS" BASIS,        |
+| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+| See the License for the specific language governing permissions and      |
+| limitations under the License.                                           |
++--------------------------------------------------------------------------*/
+package org.fortiss.tooling.base.ui.annotation.view;
+
+import org.eclipse.emf.common.util.EMap;
+import org.eclipse.jface.dialogs.IInputValidator;
+import org.eclipse.jface.dialogs.InputDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.jface.viewers.ViewerCell;
+import org.eclipse.jface.viewers.ViewerColumn;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.TableEditor;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.fortiss.tooling.base.model.element.IAnnotatedSpecification;
+import org.fortiss.tooling.base.ui.annotation.AnnotationEntry;
+import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
+import org.fortiss.tooling.kernel.service.IPersistencyService;
+
+/**
+ * This class is responsible to construct a column which holds a button that allows adding new
+ * instance for multi-instance annotations.
+ * 
+ * This class is in part based on code from the class {@link TableViewerColumn}.
+ * 
+ * @author diewald, barner
+ * @author $Author$
+ * @version $Rev$
+ * @ConQAT.Rating RED
+ */
+public class CreateAnnotationInstanceColumn extends ViewerColumn {
+
+	/** the column to be added to the table */
+	private TableColumn column;
+
+	/** annotation specification this column refers to */
+	private IAnnotatedSpecification columnSpec;
+
+	/** annotation entry the specification {@code columnSpec} is associated with */
+	private AnnotationEntry columnSpecAnnEntry;
+
+	/** the button which opens a dialog to create new values for the specification {@code columnSpec} */
+	private Button crButton;
+
+	/**
+	 * Creates a new viewer column for the given {@link TableViewer} on a new {@link TableColumn}
+	 * with the given style bits. The column is added at the
+	 * end of the list of columns.
+	 * 
+	 * @param viewer
+	 *            the table viewer to which this column belongs
+	 * @param style
+	 *            the style used to create the column, for applicable style bits
+	 *            see {@link TableColumn}
+	 * @see TableColumn#TableColumn(Table, int)
+	 */
+	public CreateAnnotationInstanceColumn(TableViewer viewer, int style) {
+		this(viewer, style, -1);
+	}
+
+	/**
+	 * Creates a new viewer column for the given {@link TableViewer} on a new {@link TableColumn}
+	 * with the given style bits. The column is inserted at
+	 * the given index into the list of columns.
+	 * 
+	 * @param viewer
+	 *            the table viewer to which this column belongs
+	 * @param style
+	 *            the style used to create the column, for applicable style bits
+	 *            see {@link TableColumn}
+	 * @param index
+	 *            the index at which to place the newly created column
+	 * @see TableColumn#TableColumn(Table, int, int)
+	 */
+	public CreateAnnotationInstanceColumn(TableViewer viewer, int style, int index) {
+		this(viewer, createColumn(viewer.getTable(), style, index));
+	}
+
+	/**
+	 * This class creates a standard table columns by calling the default of this class which is
+	 * taken form {@link TableViewerColumn}. Additionally, it sets some specific values that are
+	 * associated with the given annotation specification {@code spec}. Furthermore, it manages the
+	 * creation and the functionality of the 'create' button and the associated dialog.
+	 * 
+	 * @param viewer
+	 *            the table in which the column shall appear
+	 * @param style
+	 *            the column's style
+	 * @param spec
+	 *            the annotation specification that this class shall refer to
+	 * @param entry
+	 *            the AnnotationEntry associated with the given specification {@code spec}
+	 */
+	public CreateAnnotationInstanceColumn(TableViewer viewer, int style,
+			IAnnotatedSpecification spec, AnnotationEntry entry) {
+		this(viewer, style, -1);
+
+		columnSpec = spec;
+		columnSpecAnnEntry = entry;
+		column.setText(entry.getSpecificationAnnotationName(spec.getClass()));
+
+		setLabelProvider(new CreateNewAnnotationColumn());
+	}
+
+	/**
+	 * Creates a new viewer column for the given {@link TableViewer} on the given
+	 * {@link TableColumn}.
+	 * 
+	 * @param viewer
+	 *            the table viewer to which this column belongs
+	 * @param column
+	 *            the underlying table column
+	 */
+	public CreateAnnotationInstanceColumn(TableViewer viewer, TableColumn column) {
+		super(viewer, column);
+		this.column = column;
+	}
+
+	/** creates the column by instantiating TableColumn */
+	private static TableColumn createColumn(Table table, int style, int index) {
+		if(index >= 0) {
+			return new TableColumn(table, style, index);
+		}
+
+		return new TableColumn(table, style);
+	}
+
+	/**
+	 * @return the underlying SWT table column
+	 */
+	public TableColumn getColumn() {
+		return column;
+	}
+
+	/**
+	 * creates the content of a new column via the update method of the table viewer to provide a
+	 * "Create" button in the first row such that new values can be added to the table
+	 */
+	private class CreateNewAnnotationColumn extends ColumnLabelProvider {
+		/** {@inheritDoc} */
+		@Override
+		public void update(ViewerCell cell) {
+
+			TableItem item = (TableItem)cell.getItem();
+
+			if(columnSpec != null && crButton == null) {
+				crButton = new Button((Composite)cell.getViewerRow().getControl(), SWT.NONE);
+				crButton.setText("Create");
+
+				crButton.addListener(SWT.Selection, new CreateButtonListener());
+
+				TableEditor editor = new TableEditor(item.getParent());
+				editor.grabHorizontal = true;
+				editor.grabVertical = true;
+				editor.setEditor(crButton, item, cell.getColumnIndex());
+				editor.layout();
+			}
+		}
+	}
+
+	/**
+	 * This Listener watches the "Create" button such that a dialog is opened if pressed and a new
+	 * key can be added to the specification type of this column
+	 */
+	private class CreateButtonListener implements Listener {
+		/** Buffer holding the annotation's map to support the get/set functions of the model */
+
+		/** {@inheritDoc} */
+		@Override
+		public void handleEvent(Event event) {
+			if(event.widget == crButton) {
+				InputDialog dlg =
+						new InputDialog(Display.getCurrent().getActiveShell(), "Create Annotation",
+								"Enter the name of the new annotation", "",
+								new AnnotationNameValidator());
+				if(dlg.open() == Window.OK) {
+					final String instanceKey = dlg.getValue();
+
+					// Register the new annotation instance with the model, by writing a null value
+					// for the input key provided by the user. A write transaction / a switch to the
+					// model context is required to modify the from the GUI context.
+					ITopLevelElement modelContext =
+							IPersistencyService.INSTANCE.getTopLevelElementFor(columnSpecAnnEntry
+									.getModelElement());
+					modelContext.runAsCommand(new Runnable() {
+
+						@SuppressWarnings("unchecked")
+						@Override
+						public void run() {
+							try {
+								// Work around the fact that getSpecificationValue(null,
+								// columnSpec.getClass(), instanceKey) would resolve
+								// to the more specific getSpecificationValue(String, Class<?
+								// extends IAnnotatedSpecification>, String) overload of the method,
+								// and thus would not work for maps whose value type is not String.
+								//
+								// Hence, the entire instance map is retrieved here, and put() is
+								// called explicitly.
+								((EMap<String, ?>)columnSpecAnnEntry
+										.getSpecificationValue(columnSpec.getClass())).put(
+										instanceKey, null);
+							} catch(IllegalArgumentException e) {
+								// e.printStackTrace();
+								MessageDialog
+										.openError(
+												new Shell(),
+												"ERROR",
+												"The value you entered does not have the desired type.\nDetailed message:\n" +
+														e.getMessage());
+							} catch(Exception e) {
+								MessageDialog.openError(new Shell(), "ERROR", e.getMessage());
+							}
+						}
+					});
+				}
+			}
+		}
+	}
+
+	/** Provides a validator which checks if an input string is not an existing annotation name */
+	class AnnotationNameValidator implements IInputValidator {
+		/**
+		 * Validates the String. Returns null for no error, or an error message
+		 * 
+		 * @param inputText
+		 *            the String to validate
+		 * @return String
+		 */
+		@Override
+		public String isValid(String inputText) {
+			@SuppressWarnings("unchecked") EMap<String, ?> kVMap =
+					(EMap<String, ?>)columnSpecAnnEntry
+							.getSpecificationValue(columnSpec.getClass());
+			if(kVMap != null) {
+				if(kVMap.containsKey(inputText))
+					return "You cannot create a new key that already exists for the selected specification class.";
+			}
+			return null;
+		}
+	}
+
+	/**
+	 * Disposes the UI elements created by this class, namely {@code crButton} and {@code column}.
+	 * This is required whenever the parent UI-element is repainted. See the general Java-UI
+	 * documentation for details.
+	 */
+	public void dispose() {
+		crButton.dispose();
+		column.dispose();
+	}
+}
diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/GenericAnnotationView.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/GenericAnnotationView.java
index d2a5a49ca..48ceece4f 100644
--- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/GenericAnnotationView.java
+++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/GenericAnnotationView.java
@@ -17,8 +17,12 @@ $Id$
 +--------------------------------------------------------------------------*/
 package org.fortiss.tooling.base.ui.annotation.view;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
+import org.eclipse.emf.common.util.EMap;
 import org.eclipse.jface.viewers.ArrayContentProvider;
 import org.eclipse.jface.viewers.ColumnLabelProvider;
 import org.eclipse.jface.viewers.EditingSupport;
@@ -43,7 +47,7 @@ import org.fortiss.tooling.kernel.model.INamedCommentedElement;
  * Per default, this class only supports displaying simple annotation types. You are required to
  * override the {@code selectionChanged} method to support displaying these annotations.
  * 
- * @author eder
+ * @author eder, diewald, barner
  * @author $Author$
  * @version $Rev$
  * @ConQAT.Rating YELLOW Hash: D91763408246ECD3578DAD0E37BC4C41
@@ -54,6 +58,20 @@ public class GenericAnnotationView extends AnnotationViewPartBase {
 	protected HashMap<Class<? extends IAnnotatedSpecification>, TableViewerColumn> annotationSpecColumns =
 			new HashMap<Class<? extends IAnnotatedSpecification>, TableViewerColumn>();
 
+	/**
+	 * List containing the columns that are responsible for creating new keys. Required for
+	 * disposing when updating the view.
+	 */
+	private List<CreateAnnotationInstanceColumn> createColumns =
+			new ArrayList<CreateAnnotationInstanceColumn>();
+
+	/**
+	 * Map for associating those specifications that allow multiple values with their according
+	 * AnnotationEntries.
+	 */
+	private Map<IAnnotatedSpecification, AnnotationEntry> specsAllowingMultipleValues =
+			new HashMap<IAnnotatedSpecification, AnnotationEntry>();
+
 	/** The table viewer */
 	protected TableViewer tableViewer;
 
@@ -77,9 +95,15 @@ public class GenericAnnotationView extends AnnotationViewPartBase {
 	public void selectionChanged(IWorkbenchPart part, ISelection selection) {
 		super.selectionChanged(part, selection);
 
+		createSingleInstanceAnnotationColumns();
+		createMultiInstanceAnnotationColumns();
+	}
+
+	/** Create columns for ordinary (single instance) {@link IAnnotatedSpecification}s */
+	private void createSingleInstanceAnnotationColumns() {
 		/*
-		 * disposes all columns of the table viewer, except the first column, which holds the model
-		 * elements
+		 * disposes all columns of the table viewer, except the first column, which holds the names
+		 * of the model elements
 		 */
 		while(tableViewer.getTable().getColumnCount() > 1) {
 			tableViewer.getTable().getColumn(1).dispose();
@@ -93,15 +117,69 @@ public class GenericAnnotationView extends AnnotationViewPartBase {
 		 */
 		for(AnnotationEntry entry : annotationEntryList) {
 			for(IAnnotatedSpecification spec : entry.getSpecificationsList()) {
-				if(!isExistingColumn(spec) && !entry.allowsMultipleValues(spec.getClass())) {
-					createAnnotationColumn(entry, spec);
+				if(!isExistingColumn(spec) &&
+						!entry.allowsMultipleAnnoationInstances(spec.getClass())) {
+					createAnnotationColumn(entry, spec, null);
 				}
 			}
 		}
 
 		if(!tableViewer.getTable().isDisposed())
 			tableViewer.setInput(annotationEntryList);
+	}
+
+	/** Create columns for multi-instance {@link IAnnotatedSpecification}s */
+	private void createMultiInstanceAnnotationColumns() {
+		for(CreateAnnotationInstanceColumn col : createColumns) {
+			col.dispose();
+		}
+
+		specsAllowingMultipleValues.clear();
+
+		/*
+		 * Iterate over all available specifications in the model. Columns for specifications
+		 * with simple values have already been created by the superclass 'GenericAnnotationView',
+		 * others are stored in the map 'specsAllowingMultipleValues'.
+		 * Each annotation specification type may exist only once in the table view or the map
+		 * 'code specsAllowingMultipleValues'.
+		 */
+		List<String> specClassNamesMult = new ArrayList<String>();
+		for(AnnotationEntry entry : annotationEntryList) {
+			for(IAnnotatedSpecification spec : entry.getSpecificationsList()) {
+				if(entry.allowsMultipleAnnoationInstances(spec.getClass()) &&
+						!specClassNamesMult.contains(spec.getClass().getSimpleName())) {
+					specsAllowingMultipleValues.put(spec, entry);
+					specClassNamesMult.add(spec.getClass().getSimpleName());
+				}
+			}
+		}
 
+		// Iterate over all specification supporting multiple values.
+		for(IAnnotatedSpecification spec : specsAllowingMultipleValues.keySet().toArray(
+				new IAnnotatedSpecification[specsAllowingMultipleValues.keySet().size()])) {
+			AnnotationEntry entry = specsAllowingMultipleValues.get(spec);
+
+			// Map holding the values of the current multi-instance specification type
+			EMap<String, ?> kVMap = entry.getSpecificationValue(spec.getClass());
+
+			if(kVMap != null) {
+				// Create new column for each instance of the current multi-instance annotation
+				for(String key : kVMap.keySet().toArray(new String[kVMap.keySet().size()])) {
+					createAnnotationColumn(entry, spec, key);
+				}
+			}
+
+			// Create column that contains a button for adding new instances of the
+			// current annotation type.
+			createColumns
+					.add(new CreateAnnotationInstanceColumn(tableViewer, SWT.NONE, spec, entry));
+			(createColumns.get(createColumns.size() - 1)).getColumn().setWidth(125);
+
+		}
+
+		// Refresh table to trigger the update method of the create columns in order to actually
+		// instantiate the "Create" buttons
+		tableViewer.refresh();
 	}
 
 	/** Creates the (leading) column which displays the model elements */
@@ -138,23 +216,33 @@ public class GenericAnnotationView extends AnnotationViewPartBase {
 	}
 
 	/** Creates a column in tableViewer that displays the annotation given in spec */
-	protected void createAnnotationColumn(AnnotationEntry entry, IAnnotatedSpecification spec) {
-		/* add the new column and name it */
-		TableViewerColumn column = new TableViewerColumn(tableViewer, SWT.NONE);
+	protected void createAnnotationColumn(AnnotationEntry entry, IAnnotatedSpecification spec,
+			String instanceKey) {
+
+		// Determine column name
 		String specName = entry.getSpecificationAnnotationName(spec.getClass());
-		if(specName == null)
-			specName = "Empty Annotation";
+		if(specName == null || specName.isEmpty()) {
+			specName = "<Unnamed Annotation>";
+		}
+
+		if(instanceKey != null) {
+			specName += ": " + instanceKey;
+		}
+
+		// Add new new column
+		TableViewerColumn column = new TableViewerColumn(tableViewer, SWT.NONE);
 		column.getColumn().setText(specName);
+
 		column.getColumn().setWidth(125);
 		annotationSpecColumns.put(spec.getClass(), column);
 
 		// Have the matching EditingSupport created for the current annotated specification
 		// (work is delegated to respective IAnnotationValueProvider implementation)
 		EditingSupport editingSupport =
-				entry.createSpecificationEditElement(tableViewer, spec.getClass());
+				entry.createSpecificationEditElement(tableViewer, spec.getClass(), instanceKey);
 
 		// Add column label provider, and set EditingSupport
-		column.setLabelProvider(new AnnotationLabelProvider(spec.getClass(), this));
+		column.setLabelProvider(new AnnotationLabelProvider(spec.getClass(), this, instanceKey));
 		column.setEditingSupport(editingSupport);
 
 	}
-- 
GitLab