From 793757ed9ee97f8b4bf15d98fe92b5391cda7213 Mon Sep 17 00:00:00 2001
From: Simon Barner <barner@fortiss.org>
Date: Mon, 1 Sep 2014 07:44:07 +0000
Subject: [PATCH] - IAnnotationValueProvider  -
 allowsMultipleAnnotationInstances() -> allowsDynamicAnnotationInstances()  -
 add getInstanceKeys() - MultiInstanceValueProviderBase ->
 DynamicInstanceValueProviderBase - Concrete IValueProviders may now either
 support the dynamic creation of instances (using the EMap based
 implementation provided by DynamicInstanceValueProviderBase) - Alternatively,
 IValueProviders may statically support a number of "views" onto an annotation
 by returning the supported instance keys in getInstanceKeys() and
 implementing the required case distinction in get/setAnnotationValue() and
 createEditingSupport() refs 1841

---
 .../base/ui/annotation/AnnotationEntry.java   | 49 +++++++++++++------
 ...iInstanceAnnotationTextEditingSupport.java |  4 +-
 ...cInstanceAnnotationValueProviderBase.java} | 42 +++++++++++-----
 .../IAnnotationValueProvider.java             | 32 +++++++++---
 .../valueprovider/ValueProviderBase.java      | 21 +++++---
 .../view/GenericAnnotationView.java           | 30 ++++++------
 6 files changed, 120 insertions(+), 58 deletions(-)
 rename org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/{MultiInstanceAnnotationValueProviderBase.java => DynamicInstanceAnnotationValueProviderBase.java} (82%)

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 f6b61e07c..1caa3186a 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.Collections;
 import java.util.HashMap;
 import java.util.List;
 
@@ -69,20 +70,6 @@ public final class AnnotationEntry {
 		specificationsList.add(spec);
 	}
 
-	/**
-	 * Indicates whether the given specification contains a value type allowing the storage of
-	 * multiple instances of the annotation (like a list of strings).
-	 */
-	public boolean allowsMultipleAnnoationInstances(Class<? extends IAnnotatedSpecification> clazz) {
-		for(IAnnotatedSpecification s : specificationsList) {
-			if(clazz.isInstance(s)) {
-				return providerSpecMapping.get(clazz).allowsMultipleAnnotationInstances();
-			}
-		}
-
-		return false;
-	}
-
 	/** Returns the name / "label" for a given annotation {@code clazz}. */
 	public String getSpecificationAnnotationName(Class<? extends IAnnotatedSpecification> clazz) {
 		for(IAnnotatedSpecification s : specificationsList) {
@@ -215,6 +202,40 @@ public final class AnnotationEntry {
 		return null;
 	}
 
+	/**
+	 * Returns the instance keys supported by the respective {@link IAnnotationValueProvider}.
+	 * {@link IAnnotationValueProvider}s can either define a static {@link List}, or enable the
+	 * dynamic creation of instance keys using {@link #allowsDynamicAnnotationInstances(Class)}. In
+	 * the
+	 * latter case, this method returns current list of dynamic annotation instances.
+	 */
+	public List<String> getInstanceKeys(Class<? extends IAnnotatedSpecification> clazz) {
+		for(IAnnotatedSpecification s : specificationsList) {
+			if(clazz.isInstance(s)) {
+				return providerSpecMapping.get(clazz).getInstanceKeys(s);
+			}
+		}
+
+		return Collections.emptyList();
+	}
+
+	/**
+	 * Indicates whether the given specification contains a value type allowing the storage of
+	 * dynamically created instances of the annotation (like a list of strings). Static instances
+	 * can be implemented by overriding
+	 * {@link IAnnotationValueProvider#getInstanceKeys(IAnnotatedSpecification)} and returning the
+	 * {@link List} of admissible instance keys.
+	 */
+	public boolean allowsDynamicAnnotationInstances(Class<? extends IAnnotatedSpecification> clazz) {
+		for(IAnnotatedSpecification s : specificationsList) {
+			if(clazz.isInstance(s)) {
+				return providerSpecMapping.get(clazz).allowsDynamicAnnotationInstances();
+			}
+		}
+
+		return false;
+	}
+
 	/** Returns modelElement. */
 	public IModelElement getModelElement() {
 		return modelElement;
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 cc44d6195..b53cc4e2c 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
@@ -20,13 +20,13 @@ package org.fortiss.tooling.base.ui.annotation.editingsupport;
 import org.eclipse.jface.viewers.ColumnViewer;
 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.base.ui.annotation.valueprovider.DynamicInstanceAnnotationValueProviderBase;
 
 /**
  * This class extends {@link TextEditingSupport} to support text annotations for which multiple
  * instances can exist.
  * 
- * @see MultiInstanceAnnotationValueProviderBase
+ * @see DynamicInstanceAnnotationValueProviderBase
  * 
  * @author diewald, barner
  * @author $Author$
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/DynamicInstanceAnnotationValueProviderBase.java
similarity index 82%
rename from org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/MultiInstanceAnnotationValueProviderBase.java
rename to org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/valueprovider/DynamicInstanceAnnotationValueProviderBase.java
index 97f068506..bc5044250 100644
--- 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/DynamicInstanceAnnotationValueProviderBase.java
@@ -17,6 +17,10 @@ $Id$
 +--------------------------------------------------------------------------*/
 package org.fortiss.tooling.base.ui.annotation.valueprovider;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
 import org.eclipse.emf.common.util.EMap;
 import org.eclipse.emf.ecore.EClass;
 import org.eclipse.emf.ecore.EDataType;
@@ -30,8 +34,8 @@ import org.fortiss.tooling.base.ui.annotation.editingsupport.MultiInstanceAnnota
 /**
  * <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}
+ * which multiple instances can be dynamically created. 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>
@@ -47,7 +51,7 @@ import org.fortiss.tooling.base.ui.annotation.editingsupport.MultiInstanceAnnota
  * @version $Rev$
  * @ConQAT.Rating RED Hash:
  */
-public abstract class MultiInstanceAnnotationValueProviderBase<T extends IAnnotatedSpecification>
+public abstract class DynamicInstanceAnnotationValueProviderBase<T extends IAnnotatedSpecification>
 		extends SingleEStructuralFeatureValueProviderBase<T> {
 
 	/**
@@ -69,7 +73,7 @@ public abstract class MultiInstanceAnnotationValueProviderBase<T extends IAnnota
 	 * {@link IAnnotatedSpecification} that whose storage is implemented by a single
 	 * {@link EStructuralFeature}.
 	 */
-	public MultiInstanceAnnotationValueProviderBase(EClass annotatedSpecificationEClass,
+	public DynamicInstanceAnnotationValueProviderBase(EClass annotatedSpecificationEClass,
 			EFactory annotationFactory, EStructuralFeature structuralFeature,
 			EFactory attributeFactory, EDataType valueDataType, EFactory valueFactory) {
 		super(annotatedSpecificationEClass, annotationFactory, structuralFeature, attributeFactory);
@@ -77,12 +81,6 @@ public abstract class MultiInstanceAnnotationValueProviderBase<T extends IAnnota
 		this.valueFactory = valueFactory;
 	}
 
-	/** {@inheritDoc} */
-	@Override
-	public boolean allowsMultipleAnnotationInstances() {
-		return true;
-	}
-
 	/** {@inheritDoc} */
 	@SuppressWarnings("unchecked")
 	@Override
@@ -97,7 +95,8 @@ public abstract class MultiInstanceAnnotationValueProviderBase<T extends IAnnota
 	 * representation of the input.
 	 */
 	@SuppressWarnings("unchecked")
-	private <V> void setAnnotationValueFromString(String value, T specification, String instanceKey) {
+	private <V> void
+			setAnnotationValueFromString(String value, T specification, String instanceKey) {
 		((EMap<String, V>)getAnnotationValue(specification)).put(instanceKey,
 				(V)valueFactory.createFromString(valueDataType, value));
 	}
@@ -127,4 +126,25 @@ public abstract class MultiInstanceAnnotationValueProviderBase<T extends IAnnota
 
 		return new MultiInstanceAnnotationTextEditingSupport(viewer, clazz, instanceKey);
 	}
+
+	/** {@inheritDoc} */
+	@Override
+	public List<String> getInstanceKeys(T specification) {
+		// Return the (sorted) list of dynamic instances created so far.
+		EMap<String, ?> kVMap = getAnnotationValue(specification);
+
+		if(kVMap != null) {
+			List<String> rval = new ArrayList<String>();
+			rval.addAll(kVMap.keySet());
+			Collections.sort(rval);
+			return rval;
+		}
+		return Collections.emptyList();
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public boolean allowsDynamicAnnotationInstances() {
+		return true;
+	}
 }
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 386f92a76..5673cd22e 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
@@ -66,14 +66,6 @@ import org.fortiss.tooling.kernel.service.base.IEObjectAware;
 public interface IAnnotationValueProvider<T extends IAnnotatedSpecification> extends
 		IEObjectAware<IModelElement> {
 
-	/**
-	 * 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();
-
 	/**
 	 * Returns the name of the annotation (e.g., used as column label in the table-based
 	 * {@link GenericAnnotationView}).
@@ -176,4 +168,28 @@ public interface IAnnotationValueProvider<T extends IAnnotatedSpecification> ext
 	 */
 	public List<Class<? extends EObject>> excludeModelElementTypeFromAnnotatedSpecification();
 
+	/**
+	 * Returns the instance keys supported by this {@link IAnnotationValueProvider}.
+	 * {@link IAnnotationValueProvider}s can either define a static {@link List}, or enable the
+	 * 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);
+
+	/**
+	 * <p>
+	 * Predicate whether the {@link IAnnotatedSpecification} managed by this
+	 * {@link IAnnotationValueProvider} contains a value type allowing the storage of dynamically
+	 * created instances of the annotation (like a list of strings). For instance, the
+	 * {@link GenericAnnotationView} will in this case create UI controls to enable the creation of
+	 * these instances.
+	 * </p>
+	 * <p>
+	 * Static instances can be implemented by overriding
+	 * {@link #getInstanceKeys(IAnnotatedSpecification)} and returning the {@link List} of
+	 * admissible instance keys.
+	 * </p>
+	 */
+	public boolean allowsDynamicAnnotationInstances();
+
 }
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 b964a1fd0..e281dd030 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
@@ -17,6 +17,7 @@ $Id$
 +--------------------------------------------------------------------------*/
 package org.fortiss.tooling.base.ui.annotation.valueprovider;
 
+import java.util.Collections;
 import java.util.List;
 
 import org.eclipse.emf.ecore.EClass;
@@ -103,12 +104,6 @@ public abstract class ValueProviderBase<T extends IAnnotatedSpecification> imple
 						specification.getClass());
 	}
 
-	/** {@inheritDoc} */
-	@Override
-	public boolean allowsMultipleAnnotationInstances() {
-		return false;
-	}
-
 	/** {@inheritDoc} */
 	@Override
 	public EditingSupport createEditingSupport(ColumnViewer viewer,
@@ -119,7 +114,7 @@ public abstract class ValueProviderBase<T extends IAnnotatedSpecification> imple
 	}
 
 	/**
-	 * Creates the editing support without referring to the optional {@code userData} (see
+	 * Creates the editing support without referring to the optional {@code instanceKey} (see
 	 * {@link #createEditingSupport(ColumnViewer, Class, String)}).
 	 */
 	public EditingSupport createEditingSupport(ColumnViewer viewer,
@@ -173,4 +168,16 @@ public abstract class ValueProviderBase<T extends IAnnotatedSpecification> imple
 		return (Class<T>)annotatedSpecificationEClass.getClass();
 	}
 
+	/** {@inheritDoc} */
+	@Override
+	public List<String> getInstanceKeys(T specification) {
+		return Collections.emptyList();
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public boolean allowsDynamicAnnotationInstances() {
+		return false;
+	}
+
 }
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 1eb0b7efe..4f186af7f 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
@@ -23,7 +23,6 @@ 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.EditingSupport;
 import org.eclipse.jface.viewers.TableViewer;
@@ -104,7 +103,8 @@ public class GenericAnnotationView extends AnnotationViewPartBase {
 		for(AnnotationEntry entry : annotationEntries) {
 			for(IAnnotatedSpecification spec : entry.getSpecificationsList()) {
 				if(!isExistingColumn(spec) &&
-						!entry.allowsMultipleAnnoationInstances(spec.getClass())) {
+						!entry.allowsDynamicAnnotationInstances(spec.getClass()) &&
+						entry.getInstanceKeys(spec.getClass()).isEmpty()) {
 					createAnnotationColumn(entry, spec, null);
 				}
 			}
@@ -133,7 +133,8 @@ public class GenericAnnotationView extends AnnotationViewPartBase {
 		List<String> specClassNamesMult = new ArrayList<String>();
 		for(AnnotationEntry entry : annotationEntries) {
 			for(IAnnotatedSpecification spec : entry.getSpecificationsList()) {
-				if(entry.allowsMultipleAnnoationInstances(spec.getClass()) &&
+				if((!entry.getInstanceKeys(spec.getClass()).isEmpty() || entry
+						.allowsDynamicAnnotationInstances(spec.getClass())) &&
 						!specClassNamesMult.contains(spec.getClass().getSimpleName())) {
 					specsAllowingMultipleValues.put(spec, entry);
 					specClassNamesMult.add(spec.getClass().getSimpleName());
@@ -146,21 +147,18 @@ public class GenericAnnotationView extends AnnotationViewPartBase {
 				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 new column for each instance of the current multi-instance annotation
+			for(String key : entry.getInstanceKeys(spec.getClass())) {
+				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);
+			if(entry.allowsDynamicAnnotationInstances(spec.getClass())) {
+				// 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);
+			}
 
 		}
 
-- 
GitLab