From ec8083b6540ba174ce568ec12704fb9b2a048023 Mon Sep 17 00:00:00 2001
From: Simon Barner <barner@fortiss.org>
Date: Thu, 4 Sep 2014 16:29:12 +0000
Subject: [PATCH] - SingleEStructuralFeatureValueProvider ->
 EStructuralFeatureValueProvider (can optionally handle multiple
 EStructuralFeatures contained in a specification)

- TODO: Mixing the edit support (ComboBox, Text) and the EStructuralFeature type (enum vs. other primitive data types) is not possible)
refs 1841
---
 .../base/ui/annotation/AnnotationEntry.java   |  18 +-
 .../AnnotationEditingSupportBase.java         |   2 +-
 ...iInstanceAnnotationTextEditingSupport.java |  11 ++
 ...icInstanceAnnotationValueProviderBase.java |  21 ++-
 .../EStructuralFeatureDescriptor.java         |  62 +++++++
 ... EStructuralFeatureValueProviderBase.java} | 154 +++++++++++++-----
 .../IAnnotationValueProvider.java             |   5 +-
 .../SingleEnumAttributeValueProviderBase.java |   2 +-
 .../valueprovider/ValueProviderBase.java      |  46 +++++-
 9 files changed, 253 insertions(+), 68 deletions(-)
 create mode 100644 org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/EStructuralFeatureDescriptor.java
 rename org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/{SingleEStructuralFeatureValueProviderBase.java => EStructuralFeatureValueProviderBase.java} (53%)

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 1caa3186a..fc716aa78 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
@@ -18,6 +18,7 @@ $Id$
 package org.fortiss.tooling.base.ui.annotation;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -43,9 +44,6 @@ import org.fortiss.tooling.base.ui.annotation.view.GenericAnnotationView;
  */
 public final class AnnotationEntry {
 
-	/** Value not available */
-	public static final String NOVAL = "-";
-
 	/** Model Element */
 	private IModelElement modelElement;
 
@@ -104,12 +102,12 @@ public final class AnnotationEntry {
 				try {
 					return providerSpecMapping.get(clazz).getAnnotationValue(s, instanceKey);
 				} catch(Exception e) {
-					throw null;
+					return null;
 				}
 			}
 		}
 
-		throw null;
+		return null;
 	}
 
 	/**
@@ -119,11 +117,15 @@ public final class AnnotationEntry {
 	public <V> V getSpecificationValue(Class<? extends IAnnotatedSpecification> clazz) {
 		for(IAnnotatedSpecification s : specificationsList) {
 			if(clazz.isInstance(s)) {
-				return providerSpecMapping.get(clazz).getAnnotationValue(s);
+				try {
+					return providerSpecMapping.get(clazz).getAnnotationValue(s);
+				} catch(Exception e) {
+					// Ignore exception
+				}
 			}
 		}
 
-		throw null;
+		return null;
 	}
 
 	/**
@@ -209,7 +211,7 @@ public final class AnnotationEntry {
 	 * the
 	 * latter case, this method returns current list of dynamic annotation instances.
 	 */
-	public List<String> getInstanceKeys(Class<? extends IAnnotatedSpecification> clazz) {
+	public Collection<String> getInstanceKeys(Class<? extends IAnnotatedSpecification> clazz) {
 		for(IAnnotatedSpecification s : specificationsList) {
 			if(clazz.isInstance(s)) {
 				return providerSpecMapping.get(clazz).getInstanceKeys(s);
diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/editingsupport/AnnotationEditingSupportBase.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/editingsupport/AnnotationEditingSupportBase.java
index 3360ba97b..4a6c19764 100644
--- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/editingsupport/AnnotationEditingSupportBase.java
+++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/editingsupport/AnnotationEditingSupportBase.java
@@ -52,7 +52,7 @@ public abstract class AnnotationEditingSupportBase extends EditingSupport {
 	protected boolean canEdit(Object element) {
 		if(element instanceof AnnotationEntry) {
 			AnnotationEntry data = (AnnotationEntry)element;
-			return data.getSpecificationValue(specClass) != AnnotationEntry.NOVAL;
+			return data.getSpecificationValue(specClass) != null;
 		}
 
 		return true;
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
index b53cc4e2c..5f2f22e10 100644
--- 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
@@ -57,4 +57,15 @@ public class MultiInstanceAnnotationTextEditingSupport extends TextEditingSuppor
 	protected void doSetValue(AnnotationEntry annotationEntry, String value) throws Exception {
 		annotationEntry.setSpecificationValue(value, specClass, instanceKey);
 	}
+
+	/** {@inheritDoc} */
+	@Override
+	protected boolean canEdit(Object element) {
+		if(element instanceof AnnotationEntry) {
+			AnnotationEntry data = (AnnotationEntry)element;
+			return data.getSpecificationValue(specClass, instanceKey) != null;
+		}
+
+		return true;
+	}
 }
diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/DynamicInstanceAnnotationValueProviderBase.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/DynamicInstanceAnnotationValueProviderBase.java
index bc5044250..589d22176 100644
--- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/DynamicInstanceAnnotationValueProviderBase.java
+++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/DynamicInstanceAnnotationValueProviderBase.java
@@ -52,7 +52,7 @@ import org.fortiss.tooling.base.ui.annotation.editingsupport.MultiInstanceAnnota
  * @ConQAT.Rating RED Hash:
  */
 public abstract class DynamicInstanceAnnotationValueProviderBase<T extends IAnnotatedSpecification>
-		extends SingleEStructuralFeatureValueProviderBase<T> {
+		extends EStructuralFeatureValueProviderBase<T> {
 
 	/**
 	 * {@link EDataType} of the value type V of the underlying EMap<String, V> storing the
@@ -84,7 +84,7 @@ public abstract class DynamicInstanceAnnotationValueProviderBase<T extends IAnno
 	/** {@inheritDoc} */
 	@SuppressWarnings("unchecked")
 	@Override
-	public <V> V getAnnotationValue(T spec, String instanceKey) {
+	public <V> V getAnnotationValue(T spec, String instanceKey) throws Exception {
 		// Return value of current instance (entry map containing all instances of the annotation)
 		return ((EMap<String, V>)getAnnotationValue(spec)).get(instanceKey);
 
@@ -96,7 +96,8 @@ public abstract class DynamicInstanceAnnotationValueProviderBase<T extends IAnno
 	 */
 	@SuppressWarnings("unchecked")
 	private <V> void
-			setAnnotationValueFromString(String value, T specification, String instanceKey) {
+			setAnnotationValueFromString(String value, T specification, String instanceKey)
+					throws Exception {
 		((EMap<String, V>)getAnnotationValue(specification)).put(instanceKey,
 				(V)valueFactory.createFromString(valueDataType, value));
 	}
@@ -104,7 +105,8 @@ public abstract class DynamicInstanceAnnotationValueProviderBase<T extends IAnno
 	/** {@inheritDoc} */
 	@SuppressWarnings("unchecked")
 	@Override
-	public <V> void setAnnotationValue(V value, T specification, String instanceKey) {
+	public <V> void setAnnotationValue(V value, T specification, String instanceKey)
+			throws Exception {
 		if(value instanceof String) {
 			setAnnotationValueFromString((String)value, specification, instanceKey);
 		} else {
@@ -115,7 +117,8 @@ public abstract class DynamicInstanceAnnotationValueProviderBase<T extends IAnno
 
 	/** {@inheritDoc} */
 	@Override
-	public void setAnnotationValue(String value, T specification, String instanceKey) {
+	public void setAnnotationValue(String value, T specification, String instanceKey)
+			throws Exception {
 		setAnnotationValueFromString(value, specification, instanceKey);
 	}
 
@@ -131,7 +134,13 @@ public abstract class DynamicInstanceAnnotationValueProviderBase<T extends IAnno
 	@Override
 	public List<String> getInstanceKeys(T specification) {
 		// Return the (sorted) list of dynamic instances created so far.
-		EMap<String, ?> kVMap = getAnnotationValue(specification);
+		EMap<String, ?> kVMap = null;
+
+		try {
+			kVMap = getAnnotationValue(specification);
+		} catch(Exception e) {
+			// Ignore exception
+		}
 
 		if(kVMap != null) {
 			List<String> rval = new ArrayList<String>();
diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/EStructuralFeatureDescriptor.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/EStructuralFeatureDescriptor.java
new file mode 100644
index 000000000..592e25581
--- /dev/null
+++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/EStructuralFeatureDescriptor.java
@@ -0,0 +1,62 @@
+/*--------------------------------------------------------------------------+
+$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.EClass;
+import org.eclipse.emf.ecore.EFactory;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+/**
+ * Descriptor for a single {@link EStructuralFeature} (used in
+ * {@link EStructuralFeatureValueProviderBase} to support multiple {@link EStructuralFeature}s
+ * contained in a single {@link EClass}.
+ */
+public class EStructuralFeatureDescriptor {
+	/** Reference to {@link EStructuralFeature}. */
+	private EStructuralFeature structuralFeature;
+
+	/** {@link EFactory} used to initialize {@link EStructuralFeature}. */
+	EFactory structuralFeatureFactory;
+
+	/** Default value used to initialize {@link EStructuralFeature}. */
+	String structuralFeatureDefaultValue;
+
+	/** Generates a descriptor for a single {@link EStructuralFeature}. */
+	public EStructuralFeatureDescriptor(EStructuralFeature structuralFeature,
+			EFactory structuralFeatureFactory, String structuralFeatureDefaultValue) {
+		this.structuralFeature = structuralFeature;
+		this.structuralFeatureFactory = structuralFeatureFactory;
+		this.structuralFeatureDefaultValue = structuralFeatureDefaultValue;
+	}
+
+	/** Returns structuralFeature. */
+	public EStructuralFeature getStructuralFeature() {
+		return structuralFeature;
+	}
+
+	/** Returns structuralFeatureFactory. */
+	public EFactory getStructuralFeatureFactory() {
+		return structuralFeatureFactory;
+	}
+
+	/** Returns structuralFeatureDefaultValue. */
+	public String getStructuralFeatureDefaultValue() {
+		return structuralFeatureDefaultValue;
+	}
+
+}
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/EStructuralFeatureValueProviderBase.java
similarity index 53%
rename from org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/SingleEStructuralFeatureValueProviderBase.java
rename to org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/EStructuralFeatureValueProviderBase.java
index a7776ad11..23ac948b4 100644
--- 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/EStructuralFeatureValueProviderBase.java
@@ -17,6 +17,10 @@ $Id$
 +--------------------------------------------------------------------------*/
 package org.fortiss.tooling.base.ui.annotation.valueprovider;
 
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
 import org.eclipse.emf.ecore.EAttribute;
 import org.eclipse.emf.ecore.EClass;
 import org.eclipse.emf.ecore.EDataType;
@@ -27,7 +31,7 @@ import org.fortiss.tooling.base.model.element.IAnnotatedSpecification;
 import org.fortiss.tooling.base.model.element.IModelElement;
 
 /**
- * Base class for {@link IAnnotationValueProvider}s that manages a single {@link EStructuralFeature}
+ * Base class for {@link IAnnotationValueProvider}s that manages {@link EStructuralFeature}s
  * contained by a {@link IAnnotatedSpecification}.
  * 
  * @author barner
@@ -35,32 +39,34 @@ import org.fortiss.tooling.base.model.element.IModelElement;
  * @version $Rev$
  * @ConQAT.Rating RED Hash:
  */
-public abstract class SingleEStructuralFeatureValueProviderBase<T extends IAnnotatedSpecification>
+public abstract class EStructuralFeatureValueProviderBase<T extends IAnnotatedSpecification>
 		extends ValueProviderBase<T> {
 
 	/**
-	 * The structural feature of the {@link IAnnotatedSpecification} that is managed by this
-	 * {@link IAnnotationValueProvider}.
+	 * Default key used in case this {@link IAnnotationValueProvider} is used to manage a single
+	 * {@link EStructuralFeature}, only.
 	 */
-	final protected EStructuralFeature structuralFeature;
+	final static String DEFAULT_KEY = null;
 
 	/**
-	 * {@link EFactory} of used to create new attribute instances.
+	 * Map: Instance key -> {@link EStructuralFeatureDescriptor}s of the
+	 * {@link IAnnotatedSpecification} managed by
+	 * this {@link IAnnotationValueProvider}.
 	 */
-	final protected EFactory structuralFeatureFactory;
+	final protected Map<String, EStructuralFeatureDescriptor> structuralFeatureDescriptorMap;
 
 	/**
-	 * 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.
+	 * Flag if multiple {@link EStructuralFeature}s are managed by this
+	 * {@link IAnnotationValueProvider}.
 	 */
-	final protected String structuralFeatureDefaultValue;
+	boolean handlesMultipleEstructuralFeatures;
 
 	/**
 	 * Constructs a {@link IAnnotationValueProvider} for a {@link IAnnotatedSpecification} that
-	 * whose storage is implemented by a single {@link EStructuralFeature}.
+	 * whose storage is implemented by a single {@link EStructuralFeature}, and that uses the
+	 * default constructor to construct a new value for the structural feature.
 	 */
-	public SingleEStructuralFeatureValueProviderBase(EClass annotatedSpecificationEClass,
+	public EStructuralFeatureValueProviderBase(EClass annotatedSpecificationEClass,
 			EFactory annotationFactory, EStructuralFeature structuralFeature,
 			EFactory structuralFeatureFactory) {
 		this(annotatedSpecificationEClass, annotationFactory, structuralFeature,
@@ -71,32 +77,56 @@ public abstract class SingleEStructuralFeatureValueProviderBase<T extends IAnnot
 	 * Constructs a {@link IAnnotationValueProvider} for a {@link IAnnotatedSpecification} that
 	 * whose storage is implemented by a single {@link EStructuralFeature}.
 	 */
-	public SingleEStructuralFeatureValueProviderBase(EClass annotatedSpecificationEClass,
+	public EStructuralFeatureValueProviderBase(EClass annotatedSpecificationEClass,
 			EFactory annotationFactory, EStructuralFeature structuralFeature,
 			EFactory structuralFeatureFactory, final String structuralFeatureDefaultValue) {
 
 		super(annotatedSpecificationEClass, annotationFactory);
 
-		this.structuralFeature = structuralFeature;
-		this.structuralFeatureFactory = structuralFeatureFactory;
-		this.structuralFeatureDefaultValue = structuralFeatureDefaultValue;
+		structuralFeatureDescriptorMap = new HashMap<String, EStructuralFeatureDescriptor>();
+		structuralFeatureDescriptorMap.put(DEFAULT_KEY, new EStructuralFeatureDescriptor(
+				structuralFeature, structuralFeatureFactory, structuralFeatureDefaultValue));
+
+		handlesMultipleEstructuralFeatures = false;
+	}
+
+	/**
+	 * Constructs a {@link IAnnotationValueProvider} for a {@link IAnnotatedSpecification} that
+	 * whose storage is implemented by a number of {@link EStructuralFeature}s contained in a single
+	 * EClass, and that uses the default constructor to construct a new value for the structural
+	 * features.
+	 */
+	public EStructuralFeatureValueProviderBase(EClass annotatedSpecificationEClass,
+			EFactory annotationFactory,
+			Map<String, EStructuralFeatureDescriptor> structuralFeatureDescriptorMap) {
+
+		super(annotatedSpecificationEClass, annotationFactory);
+
+		this.structuralFeatureDescriptorMap = structuralFeatureDescriptorMap;
+
+		handlesMultipleEstructuralFeatures = true;
 	}
 
 	/**
 	 * Sets a value for a {@link IAnnotatedSpecification} from a {@link String} representation of
 	 * the input.
 	 */
-	private <V> void setAnnotationValueFromString(String value, T specification) {
+	private <V> void
+			setAnnotationValueFromString(String value, T specification, String instanceKey) {
+
+		EStructuralFeatureDescriptor fd = structuralFeatureDescriptorMap.get(instanceKey);
+
 		specification.eSet(
-				structuralFeature,
-				structuralFeatureFactory.createFromString(
-						((EAttribute)structuralFeature).getEAttributeType(), value));
+				fd.getStructuralFeature(),
+				fd.getStructuralFeatureFactory().createFromString(
+						((EAttribute)fd.getStructuralFeature()).getEAttributeType(), value));
 	}
 
 	/** {@inheritDoc} */
 	@SuppressWarnings("unchecked")
 	@Override
-	public <U> void setAnnotationValue(U value, T specification) throws Exception {
+	public <U> void setAnnotationValue(U value, T specification, String instanceKey)
+			throws Exception {
 		if(value instanceof String) {
 			// In case, the input choice is presented in dynamically managed combo box (i.e., where
 			// new value choices can be entered by the user, the empty String indicates that the
@@ -110,15 +140,23 @@ public abstract class SingleEStructuralFeatureValueProviderBase<T extends IAnnot
 				}
 			}
 
-			setAnnotationValueFromString((String)value, specification);
+			setAnnotationValueFromString((String)value, specification, instanceKey);
 		} else {
-			specification.eSet(structuralFeature, value);
+			specification.eSet(structuralFeatureDescriptorMap.get(instanceKey)
+					.getStructuralFeature(), value);
 		}
 	}
 
 	/** {@inheritDoc} */
 	@Override
-	public void setAnnotationValue(String value, T specification) throws Exception {
+	public <U> void setAnnotationValue(U value, T specification) throws Exception {
+		setAnnotationValue(value, specification, DEFAULT_KEY);
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public void setAnnotationValue(String value, T specification, String instanceKey)
+			throws Exception {
 		// See comment in setAnnotationValue(U value, T specification)
 		if((value == null || value.isEmpty())) {
 			String rval = getAnnotationValueAndUpdateInputChoice(value, specification);
@@ -127,8 +165,11 @@ public abstract class SingleEStructuralFeatureValueProviderBase<T extends IAnnot
 			}
 		}
 
+		EStructuralFeature structuralFeature =
+				structuralFeatureDescriptorMap.get(instanceKey).getStructuralFeature();
+
 		if(structuralFeature instanceof EAttribute) {
-			setAnnotationValueFromString(value, specification);
+			setAnnotationValueFromString(value, specification, instanceKey);
 		} else {
 			throw new Exception(
 					"setAnnotationValue(String, T) is not supported / has not been implemented the annotation type " +
@@ -138,11 +179,24 @@ public abstract class SingleEStructuralFeatureValueProviderBase<T extends IAnnot
 		}
 	}
 
+	/** {@inheritDoc} */
+	@Override
+	public void setAnnotationValue(String value, T specification) throws Exception {
+		setAnnotationValue(value, specification, DEFAULT_KEY);
+	}
+
 	/** {@inheritDoc} */
 	@SuppressWarnings("unchecked")
 	@Override
-	public <U> U getAnnotationValue(T specification) {
-		return (U)specification.eGet(structuralFeature);
+	public <U> U getAnnotationValue(T specification, String instanceKey) throws Exception {
+		return (U)specification.eGet(structuralFeatureDescriptorMap.get(instanceKey)
+				.getStructuralFeature());
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public <U> U getAnnotationValue(T specification) throws Exception {
+		return getAnnotationValue(specification, DEFAULT_KEY);
 	}
 
 	/**
@@ -150,15 +204,18 @@ public abstract class SingleEStructuralFeatureValueProviderBase<T extends IAnnot
 	 * annotation instances created in
 	 * {@link #getAnnotatedSpecificationForModelElement(IModelElement)}.
 	 */
-	protected Object createStructuralFeatureInstance() throws Exception {
-		if(structuralFeature instanceof EAttribute) {
+	protected Object createStructuralFeatureInstance(String instanceKey) throws Exception {
+		EStructuralFeatureDescriptor fd = structuralFeatureDescriptorMap.get(instanceKey);
+
+		if(fd.getStructuralFeature() instanceof EAttribute) {
 
-			EDataType attributeEDataType = ((EAttribute)structuralFeature).getEAttributeType();
+			EDataType attributeEDataType =
+					((EAttribute)fd.getStructuralFeature()).getEAttributeType();
 
-			if(structuralFeatureDefaultValue != null) {
+			if(fd.getStructuralFeatureDefaultValue() != null) {
 				// Use default value if it has been specified
-				return structuralFeatureFactory.createFromString(attributeEDataType,
-						structuralFeatureDefaultValue);
+				return fd.structuralFeatureFactory.createFromString(attributeEDataType,
+						fd.getStructuralFeatureDefaultValue());
 			}
 
 			// Return data types default value, if it is non-null.
@@ -170,37 +227,48 @@ public abstract class SingleEStructuralFeatureValueProviderBase<T extends IAnnot
 
 			try {
 				// Try to construct attribute from empty string
-				rval = structuralFeatureFactory.createFromString(attributeEDataType, "");
+				rval = fd.getStructuralFeatureFactory().createFromString(attributeEDataType, "");
 			} catch(NumberFormatException e) {
 				// Last try: initialize numbers with 0 (throws NumberFormatException if not
 				// successful).
-				rval = structuralFeatureFactory.createFromString(attributeEDataType, "0");
+				rval = fd.getStructuralFeatureFactory().createFromString(attributeEDataType, "0");
 			}
 
 			return rval;
-		} else if(structuralFeature instanceof EReference) {
-			EReference reference = (EReference)structuralFeature;
+		} else if(fd.getStructuralFeature() instanceof EReference) {
+			EReference reference = (EReference)fd.getStructuralFeature();
 			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());
+			return fd.getStructuralFeatureFactory().create(reference.getEReferenceType());
 		} else {
 			throw new Exception(
 					"createStructuralFeatureInstance() is not supported / has not been implemented the annotation type " +
-							structuralFeature.getEType().getName() + ".");
+							fd.getStructuralFeature().getEType().getName() + ".");
 		}
 	}
 
 	/** {@inheritDoc} */
 	@Override
-	protected void decorateAnnotationSpecification(T specification) throws Exception {
+	protected void decorateAnnotationSpecification(T specification, String instanceKey)
+			throws Exception {
+
 		// Create and set structural feature implementing the annotation
-		Object structuralFeatureVal = createStructuralFeatureInstance();
+		Object structuralFeatureVal = createStructuralFeatureInstance(instanceKey);
 		if(structuralFeatureVal != null) {
-			specification.eSet(structuralFeature, structuralFeatureVal);
+			specification.eSet(structuralFeatureDescriptorMap.get(instanceKey)
+					.getStructuralFeature(), structuralFeatureVal);
 		}
 	}
 
+	/** {@inheritDoc} */
+	@Override
+	public Collection<String> getInstanceKeys(T specification) {
+		if(handlesMultipleEstructuralFeatures) {
+			return structuralFeatureDescriptorMap.keySet();
+		}
+		return super.getInstanceKeys(specification);
+	}
 }
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 5673cd22e..280b7d8e6 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
@@ -17,6 +17,7 @@ $Id$
 +--------------------------------------------------------------------------*/
 package org.fortiss.tooling.base.ui.annotation.valueprovider;
 
+import java.util.Collection;
 import java.util.List;
 
 import org.eclipse.emf.ecore.EObject;
@@ -80,7 +81,7 @@ public interface IAnnotationValueProvider<T extends IAnnotatedSpecification> ext
 	public boolean setAnnotationName(String name, T specification);
 
 	/** Returns the value of the annotation. */
-	public <U> U getAnnotationValue(T specification);
+	public <U> U getAnnotationValue(T specification) throws Exception;
 
 	/**
 	 * Returns the value of a multi-instance annotation's instance denoted by {@code instanceKey}.
@@ -174,7 +175,7 @@ public interface IAnnotationValueProvider<T extends IAnnotatedSpecification> ext
 	 * dynamic creation of instance keys using {@link #allowsDynamicAnnotationInstances()}. In the
 	 * latter case, this method returns current list of dynamic annotation instances.
 	 */
-	public List<String> getInstanceKeys(T specification);
+	public Collection<String> getInstanceKeys(T specification);
 
 	/**
 	 * <p>
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 4ce5139a6..921851247 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 SingleEStructuralFeatureValueProviderBase<T> {
+		extends EStructuralFeatureValueProviderBase<T> {
 
 	/** Data type of the enumeration managed by this {@link IAnnotationValueProvider} */
 	private EEnum eEnum;
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 d94fb7b38..a8081095c 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
@@ -35,6 +35,7 @@ import org.fortiss.tooling.base.model.element.IModelElement;
 import org.fortiss.tooling.base.model.element.IModelElementSpecification;
 import org.fortiss.tooling.base.ui.annotation.AnnotationEntry;
 import org.fortiss.tooling.base.ui.annotation.editingsupport.ComboBoxEditingSupport;
+import org.fortiss.tooling.base.ui.annotation.editingsupport.MultiInstanceAnnotationTextEditingSupport;
 import org.fortiss.tooling.base.ui.annotation.editingsupport.TextEditingSupport;
 import org.fortiss.tooling.kernel.utils.EcoreUtils;
 
@@ -132,13 +133,24 @@ public abstract class ValueProviderBase<T extends IAnnotatedSpecification> imple
 	public EditingSupport createEditingSupport(ColumnViewer viewer,
 			Class<? extends IAnnotatedSpecification> clazz, String instanceKey) {
 
-		initializeInputChoice(viewer, clazz);
+		try {
+			initializeInputChoice(viewer, clazz);
+		} catch(Exception e) {
+			// Use standard text editor as fallback
+			currentInputChoice = null;
+		}
 
 		// Input is not restricted -> free editing in text cell
 		if(currentInputChoice == null) {
-			return new TextEditingSupport(viewer, clazz);
+			if(instanceKey == null) {
+				return new TextEditingSupport(viewer, clazz);
+			}
+			return new MultiInstanceAnnotationTextEditingSupport(viewer, clazz, instanceKey);
 		}
 
+		// Multiple instances are not supported (yet) for input to be edited in Comboboxes
+		assert (instanceKey == null);
+
 		// Input is restricted to concrete set of values
 		// (use SingleEnumAttributeValueProviderBase for Enum types!)
 		return new ComboBoxEditingSupport(viewer, clazz, currentInputChoice,
@@ -169,6 +181,20 @@ public abstract class ValueProviderBase<T extends IAnnotatedSpecification> imple
 	 *            annotation to be decorated
 	 */
 	protected void decorateAnnotationSpecification(T specification) throws Exception {
+		decorateAnnotationSpecification(specification, null);
+	}
+
+	/**
+	 * Add decorations to an annotation when its instance is newly created by
+	 * {@link #getAnnotatedSpecificationForModelElement(IModelElement)}.
+	 * 
+	 * @param specification
+	 *            annotation to be decorated
+	 * @param instanceKey
+	 *            instanceKey of annotation to be decorated
+	 */
+	protected void decorateAnnotationSpecification(T specification, String instanceKey)
+			throws Exception {
 		// No decoration
 	}
 
@@ -185,7 +211,13 @@ public abstract class ValueProviderBase<T extends IAnnotatedSpecification> imple
 
 		// Create annotation
 		T specification = (T)annotationFactory.create(annotatedSpecificationEClass);
-		decorateAnnotationSpecification(specification);
+		if(getInstanceKeys(specification).isEmpty()) {
+			decorateAnnotationSpecification(specification);
+		} else {
+			for(String key : getInstanceKeys(specification)) {
+				decorateAnnotationSpecification(specification, key);
+			}
+		}
 
 		// Hook specification to model element
 		element.addSpecification(specification);
@@ -202,7 +234,7 @@ public abstract class ValueProviderBase<T extends IAnnotatedSpecification> imple
 
 	/** {@inheritDoc} */
 	@Override
-	public List<String> getInstanceKeys(T specification) {
+	public Collection<String> getInstanceKeys(T specification) {
 		return Collections.emptyList();
 	}
 
@@ -223,7 +255,7 @@ public abstract class ValueProviderBase<T extends IAnnotatedSpecification> imple
 	 */
 	@SuppressWarnings("unchecked")
 	private void initializeInputChoice(ColumnViewer viewer,
-			Class<? extends IAnnotatedSpecification> clazz) {
+			Class<? extends IAnnotatedSpecification> clazz) throws Exception {
 		// Input choice is not set, or it is restricted to concrete set of values
 		// (use SingleEnumAttributeValueProviderBase for Enum types!)
 		if(fixedInputChoice == null || !fixedInputChoice.isEmpty()) {
@@ -255,7 +287,8 @@ public abstract class ValueProviderBase<T extends IAnnotatedSpecification> imple
 	 * {@link #setAnnotationValue(String, IAnnotatedSpecification)}. In particular, this
 	 * method handles the removal of input choices from if these are dynamically managed.
 	 */
-	protected String getAnnotationValueAndUpdateInputChoice(String value, T specification) {
+	protected String getAnnotationValueAndUpdateInputChoice(String value, T specification)
+			throws Exception {
 		if((value == null || value.isEmpty()) && currentInputChoice != null &&
 				!currentInputChoice.isEmpty()) {
 			// Only one entry left: do not remove
@@ -286,5 +319,4 @@ public abstract class ValueProviderBase<T extends IAnnotatedSpecification> imple
 		}
 		return null;
 	}
-
 }
-- 
GitLab