Skip to content
Snippets Groups Projects
Commit 5c29401c authored by Simon Barner's avatar Simon Barner
Browse files

Remove support to dynamically create annotation instances. The feature is unused.

refs 2964
parent 128e48ae
No related branches found
No related tags found
No related merge requests found
Showing
with 36 additions and 635 deletions
AnnotationEditingSupportBase.java 7a16abe842cb44918d75395947bb6561e468ca03 GREEN
CheckBoxEditingSupport.java c7bc95da565bad53a125ff08982ea73ba06da3e5 GREEN
ComboBoxEditingSupport.java 1c778b6017f791339483606a31b72d0f8a39098c GREEN
EditingSupportFactory.java df0d9c107a40165db19431cf33c297d52e8ebc73 GREEN
EditingSupportFactory.java c72b4847ba219755178b785ea80f91295f259760 YELLOW
ElementCommentEditingSupport.java b7cbec5084aab81efc1da6b48647b172206f6256 GREEN
ElementEditingSupportBase.java e04393748a0a0223b838fc59ef3c0e4f0960951b GREEN
ElementNameEditingSupport.java 6393bb52ad1f7ff4823a3f0dd30128124b0e3347 GREEN
......
......@@ -31,7 +31,6 @@ import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.EditingSupport;
import org.fortiss.tooling.base.annotation.AnnotationEntry;
import org.fortiss.tooling.base.annotation.valueprovider.DerivedAnnotationValueProviderBase;
import org.fortiss.tooling.base.annotation.valueprovider.DynamicInstanceAnnotationValueProviderBase;
import org.fortiss.tooling.base.annotation.valueprovider.EStructuralFeatureDescriptor;
import org.fortiss.tooling.base.annotation.valueprovider.EStructuralFeatureDescriptor.EReferenceScope;
import org.fortiss.tooling.base.annotation.valueprovider.EStructuralFeatureValueProviderBase;
......@@ -69,32 +68,6 @@ public class EditingSupportFactory {
specification, instanceKey);
}
/**
* Creates the {@link EditingSupport} for annotations that can be instantiated dynamically.
*
* @param valueProvider
* Annotation's {@link IAnnotationValueProvider}
* @param viewer
* {@link ColumnViewer} used to display annotation
* @param clazz
* Annotation type
* @param specification
* Annotation instance
* @param instanceKey
* Key identifying annotation instance
*
* @return {@link EditingSupport} for annotations that can be instantiated dynamically.
*/
private static
<T extends IAnnotatedSpecification, V extends DynamicInstanceAnnotationValueProviderBase<T>>
EditingSupport createEditingSupport4DynamicInstanceAnnotationValueProviderBase(
V valueProvider, ColumnViewer viewer,
Class<? extends IAnnotatedSpecification> clazz, T specification,
String instanceKey) throws Exception {
return new TextEditingSupport(viewer, clazz, instanceKey);
}
/**
* Creates the {@link EditingSupport} that is directly based on
* {@link EStructuralFeatureValueProviderBase}.
......@@ -291,10 +264,6 @@ public class EditingSupportFactory {
return createEditingSupport4DerivedAnnotationValueProviderBase(
(DerivedAnnotationValueProviderBase)valueProvider, viewer, clazz,
(IDerivedAnnotation)specification, instanceKey);
} else if(valueProvider instanceof DynamicInstanceAnnotationValueProviderBase<?>) {
return createEditingSupport4DynamicInstanceAnnotationValueProviderBase(
(DynamicInstanceAnnotationValueProviderBase)valueProvider, viewer, clazz,
specification, instanceKey);
} else if(valueProvider instanceof EStructuralFeatureValueProviderBase<?>) {
return createEditingSupport4EStructuralFeatureValueProviderBase(
(EStructuralFeatureValueProviderBase<T>)valueProvider, viewer, clazz,
......
ColumnHandle.java cb484315e4830bd03301f3e920f0eaf4465d4e7d GREEN
ColumnHandle.java 7fac3dbdd7da328052cbee3fa180ac78f51987e8 YELLOW
CreateAnnotationInstanceColumn.java f0e630afc37340c71d1afdf037b2df3c0f397a58 GREEN
GenericAnnotationView.java f1c6be1cac276280724bfcfb94b991f811f75928 GREEN
GenericAnnotationView.java 6b1bcf8e6a561aa586463cf6da9da8b2624a7c71 YELLOW
HierarchicalNameViewerComparator.java edf1d012a3d18860d2ef7f9e07baf46cdfeec381 GREEN
......@@ -34,24 +34,11 @@ public class ColumnHandle<T extends IAnnotatedSpecification> extends AnnotationI
*/
private final static String MULTIINSTANCE_NAME_SEPARATOR = ":";
/** Flag if this {@link ColumnHandle} represents a {@link CreateAnnotationInstanceColumn}. */
private boolean isCreateColumn;
/** Constructs a new {@link ColumnHandle}. */
@SuppressWarnings("unchecked")
public ColumnHandle(AnnotationEntry entry, T annotatedSpecification, String instanceKey,
boolean isCreateColumn) {
public ColumnHandle(AnnotationEntry entry, T annotatedSpecification, String instanceKey) {
super(entry, (Class<T>)annotatedSpecification.getClass(), annotatedSpecification,
instanceKey);
this.isCreateColumn = isCreateColumn;
}
/**
* Returns a flag if this {@link ColumnHandle} represents a
* {@link CreateAnnotationInstanceColumn}.
*/
public boolean isCreateColumn() {
return isCreateColumn;
}
/**
......@@ -99,16 +86,7 @@ public class ColumnHandle<T extends IAnnotatedSpecification> extends AnnotationI
// Place "create" columns (label: "<specification name>") after their instances
// (which are labeled "<specification name>: <instance name>").
if(annotationName.equals(otherAnnotationName)) {
// Ensure uniqueness of "create" columns"
if(isCreateColumn && other.isCreateColumn) {
return 0;
}
if(isCreateColumn) {
return 1;
}
if(other.isCreateColumn) {
return -1;
}
return 0;
}
// Sort alphabetically by specification column label
......
/*-------------------------------------------------------------------------+
| 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.generic;
import static org.eclipse.jface.dialogs.MessageDialog.openError;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.NotificationImpl;
import org.eclipse.emf.common.util.EMap;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog;
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.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
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.annotation.AnnotationEntry;
import org.fortiss.tooling.base.annotation.IAnnotationValueService;
import org.fortiss.tooling.base.model.element.IAnnotatedSpecification;
import org.fortiss.tooling.base.model.element.IModelElement;
import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
import org.fortiss.tooling.kernel.service.IPersistencyService;
/**
* <p>
* This class is responsible to construct a column which holds a button that allows adding new
* instance for multi-instance annotations.
* </p>
*
* <p>
* This class is in part based on code from the class {@link TableViewerColumn}
* </p>
* .
*
* @author diewald, barner
*/
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 {@link 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());
column.addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
if(crButton != null) {
crButton.dispose();
crButton = null;
}
}
});
}
/**
* 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 {@link 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);
}
/** Returns 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 {
/** {@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.
IModelElement modelElt = columnSpecAnnEntry.getModelElement();
ITopLevelElement modelContext =
IPersistencyService.getInstance().getTopLevelElementFor(modelElt);
modelContext
.runAsCommand(() -> {
try {
String value = populateInstance();
IAnnotationValueService avs =
IAnnotationValueService.getInstance();
AnnotationEntry entry = avs.getAnnotationEntry(modelElt);
entry.setSpecificationValue(value, columnSpec.getClass(),
instanceKey);
// Inform others, e.g. the respective annotation view that a new
// instance of this annotation has been created.
modelElt.eNotify(new NotificationImpl(Notification.SET, null,
null) {
@Override
public Object getNotifier() {
return modelElt;
}
});
} catch(IllegalArgumentException e) {
openError(
new Shell(),
"ERROR",
"The value you entered does not have the desired type.\nDetailed message:\n" +
e.getMessage());
} catch(Exception e) {
openError(new Shell(), "ERROR", e.getMessage());
}
});
}
}
}
}
/** Populate new instance (in order to make the corresponding cells editable */
private String populateInstance() {
String value = "";
if(!columnSpec.eClass().getEStructuralFeatures().isEmpty()) {
// get(0) is safe because list is guaranteed to be non-empty.
// Furthermore, the first element is the one to use, since...
EStructuralFeature dynamicInstanceFeature =
columnSpec.eClass().getEStructuralFeatures().get(0);
// ...annotations that can be dynamically instantiated are implemented using an
// appropriate EMap (which by convention has to be the first (and only)) feature of the
// corresponding annotation class.
if(dynamicInstanceFeature.getEType().getInstanceTypeName()
.equals("java.util.Map$Entry")) {
// Determine value type
EStructuralFeature valueFeature =
((EClass)dynamicInstanceFeature.getEType()).getEStructuralFeature("value");
if(Number.class.isAssignableFrom(valueFeature.getEType().getInstanceClass())) {
// Initialize numbers with 0 (initialization fails with "")
value = "0";
}
}
}
return value;
}
/**
* Provides a {@link IInputValidator} 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;
}
}
}
......@@ -242,28 +242,21 @@ public class GenericAnnotationView extends AnnotationViewPartBase {
// Create new column for each instance of the current multi-instance annotation
Class<? extends IAnnotatedSpecification> specClass = spec.getClass();
boolean isSingleInstanceAnnotation = entry.getInstanceKeys(specClass).isEmpty();
boolean allowsDynamicInstances =
entry.allowsDynamicAnnotationInstances(specClass);
if(allowsDynamicInstances || !isSingleInstanceAnnotation) {
if(!isSingleInstanceAnnotation) {
for(String instanceKey : entry.getInstanceKeys(specClass)) {
ColumnHandle<IAnnotatedSpecification> columnHandle =
new ColumnHandle<IAnnotatedSpecification>(entry, spec,
instanceKey, false);
instanceKey);
if(annotationFilter.passesColumnFilter(columnHandle)) {
sortedColumnHandles.add(columnHandle);
}
}
}
} else {
// Create a new column for
// - ordinary (single-instance) annotations
// - "create" column for multi-instance annotations for which instances can be
// created dynamically
if(allowsDynamicInstances || isSingleInstanceAnnotation) {
// Create a new column for ordinary (single-instance) annotations
ColumnHandle<IAnnotatedSpecification> columnHandle =
new ColumnHandle<IAnnotatedSpecification>(entry, spec, null,
allowsDynamicInstances);
new ColumnHandle<IAnnotatedSpecification>(entry, spec, null);
if(annotationFilter.passesColumnFilter(columnHandle)) {
sortedColumnHandles.add(columnHandle);
......@@ -687,34 +680,22 @@ public class GenericAnnotationView extends AnnotationViewPartBase {
ColumnHandle<? extends IAnnotatedSpecification> columnHandle) {
TableColumn tableColumn = null;
if(columnHandle.isCreateColumn()) {
// Create column that contains a button for adding new instances of the
// current annotation type.
@SuppressWarnings("unchecked") Class<IAnnotatedSpecification> annotationClass =
(Class<IAnnotatedSpecification>)columnHandle.getAnnotatedSpecification().getClass();
// Add new column
try {
@SuppressWarnings("unchecked") TableViewerColumn column =
createAnnotationTableViewerColumn(
(ColumnHandle<IAnnotatedSpecification>)columnHandle, annotationClass);
CreateAnnotationInstanceColumn column =
new CreateAnnotationInstanceColumn(tableViewer, SWT.NONE,
columnHandle.getAnnotatedSpecification(), columnHandle.getEntry());
tableColumn = column.getColumn();
} else {
@SuppressWarnings("unchecked") Class<IAnnotatedSpecification> annotationClass =
(Class<IAnnotatedSpecification>)columnHandle.getAnnotatedSpecification()
.getClass();
// Add new column
try {
@SuppressWarnings("unchecked") TableViewerColumn column =
createAnnotationTableViewerColumn(
(ColumnHandle<IAnnotatedSpecification>)columnHandle,
annotationClass);
tableColumn = column.getColumn();
String specName = columnHandle.getColumnName();
tableColumn.setText(specName);
} catch(Exception e) {
System.out.println("Failed to create table viewer column for annotation class " +
annotationClass.getCanonicalName() +
((e.getMessage() != null) ? ": " + e.getMessage() : "."));
}
String specName = columnHandle.getColumnName();
tableColumn.setText(specName);
} catch(Exception e) {
System.out.println("Failed to create table viewer column for annotation class " +
annotationClass.getCanonicalName() +
((e.getMessage() != null) ? ": " + e.getMessage() : "."));
}
if(tableColumn != null) {
......
AnnotationEntry.java 653f23f2e90f8261aa09172cd3db24ba88e6777e GREEN
AnnotationEntry.java d3405f0bbc26452812b0bc65043291fdac805287 YELLOW
AnnotationValueService.java 8e999ff1c54a15018f19117900822d2a749360e1 GREEN
IAnnotationValueService.java ab22e1bf3e021f5f897d4d5a20e5fc51e084c734 GREEN
......@@ -15,9 +15,10 @@
+--------------------------------------------------------------------------*/
package org.fortiss.tooling.base.annotation;
import static java.util.Collections.emptyList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
......@@ -257,9 +258,7 @@ public final class AnnotationEntry {
/**
* 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.
* {@link IAnnotationValueProvider}s (defined a static {@link List}).
*/
public Collection<String> getInstanceKeys(Class<? extends IAnnotatedSpecification> clazz) {
......@@ -269,25 +268,7 @@ public final class AnnotationEntry {
return getAnnotationValueProvider(clazz).getInstanceKeys(specification);
}
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) {
IAnnotatedSpecification specification = getSpecification(clazz);
if(isOperationEnabled(specification)) {
return getAnnotationValueProvider(clazz).allowsDynamicAnnotationInstances();
}
return false;
return emptyList();
}
/** Returns {@link #modelElement}. */
......
AnnotationInstSpec.java 86eaeb6f2f5b8d4a8322de69ff5196101b811b0a GREEN
DerivedAnnotationValueProviderBase.java 79e0a62f9cafb2cf8eebb3af7b9597cab8b820bf GREEN
DynamicInstanceAnnotationValueProviderBase.java 223db3e74361b61bb5a71cbb61e218a294c31dbb GREEN
EStructuralFeatureDescriptor.java b4093c8997472d0ab63a69c1d025d9aeb9b4f294 GREEN
EStructuralFeatureValueProviderBase.java c09e93e99816d02176fe9ee6343269ac20883f30 GREEN
IAnnotationValueProvider.java 268398d84324d20bfc885ddf69f1f934a83f76c2 GREEN
ValueProviderBase.java f31d18aebcaf22bd29d5f897773d4a5fea9667e0 GREEN
IAnnotationValueProvider.java 40effc71478aa1429dfce90ac8ed6e1e462d0044 YELLOW
ValueProviderBase.java 3138017b6c19933551b5e46033107df5ad954352 YELLOW
/*-------------------------------------------------------------------------+
| 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.annotation.valueprovider;
import static java.util.Collections.emptyList;
import static java.util.Collections.sort;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.emf.common.util.EMap;
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.fortiss.tooling.base.model.element.IAnnotatedSpecification;
/**
* <p>
* Base class for {@link IAnnotationValueProvider}s that support {@link IAnnotatedSpecification} for
* 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>
*
* <p>
* The underlying {@link EMap} must be declared in the {@link IAnnotatedSpecification}'s metamodel
* 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
*/
public abstract class DynamicInstanceAnnotationValueProviderBase<T extends IAnnotatedSpecification>
extends EStructuralFeatureValueProviderBase<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} whose storage is implemented by a single {@link EAttribute}.
*/
public DynamicInstanceAnnotationValueProviderBase(EClass annotatedSpecificationEClass,
EAttribute eAttribute, EDataType valueDataType, EFactory valueFactory) {
super(annotatedSpecificationEClass, eAttribute);
this.valueDataType = valueDataType;
this.valueFactory = valueFactory;
}
/**
* Constructs a multi-instance enabled {@link IAnnotationValueProvider} for a
* {@link IAnnotatedSpecification} whose storage is implemented by a single {@link EReference}.
*/
public DynamicInstanceAnnotationValueProviderBase(EClass annotatedSpecificationEClass,
EReference eReference, EStructuralFeatureDescriptor.EReferenceScope eReferenceScope,
EDataType valueDataType, EFactory valueFactory) {
super(annotatedSpecificationEClass, eReference, eReferenceScope);
this.valueDataType = valueDataType;
this.valueFactory = valueFactory;
}
/** {@inheritDoc} */
@Override
public <V> V getAnnotationValue(T specification, String instanceKey) throws Exception {
// Return value of current instance (entry map containing all instances of the annotation)
EMap<String, V> map = super.getAnnotationValue(specification, DEFAULT_KEY);
return map.get(instanceKey);
}
/**
* Sets a value for a multi-instance {@link IAnnotatedSpecification} from a {@link String}
* representation of the input.
*/
@Override
@SuppressWarnings("unchecked")
protected <V> void setAnnotationValueFromString(String value, T specification,
String instanceKey) throws Exception {
EMap<String, V> map = super.getAnnotationValue(specification, DEFAULT_KEY);
// Try to create annotation value from string representation
V val = (V)valueFactory.createFromString(valueDataType, value);
if(val == null) {
// If that fails, use the value types default value
val = (V)valueDataType.getDefaultValue();
if(val == null) {
// in case that should be null, too, assume it is a number and initialize it to 0.
val = (V)valueFactory.createFromString(valueDataType, "0");
}
}
map.put(instanceKey, val);
}
/** {@inheritDoc} */
@Override
public <V> void setAnnotationValue(V value, T specification, String instanceKey)
throws Exception {
if(value instanceof String) {
setAnnotationValueFromString((String)value, specification, instanceKey);
} else {
EMap<String, V> map = super.getAnnotationValue(specification, DEFAULT_KEY);
map.put(instanceKey, value);
}
}
/** {@inheritDoc} */
@Override
public void setAnnotationValue(String value, T specification, String instanceKey)
throws Exception {
setAnnotationValueFromString(value, specification, instanceKey);
}
/** {@inheritDoc} */
@Override
public List<String> getInstanceKeys(T specification) {
// Return the (sorted) list of dynamic instances created so far.
EMap<String, ?> kVMap = null;
try {
kVMap = super.getAnnotationValue(specification, DEFAULT_KEY);
} catch(Exception e) {
return emptyList();
}
if(kVMap != null) {
List<String> rval = new ArrayList<String>(kVMap.keySet());
sort(rval);
return rval;
}
return emptyList();
}
/** {@inheritDoc} */
@Override
public boolean allowsDynamicAnnotationInstances() {
return true;
}
}
......@@ -42,11 +42,8 @@ import org.fortiss.tooling.kernel.service.base.IEObjectAware;
* </p>
* Instance keys:
* <ul>
* <li>Since multiple instances can exist for a single {@link IAnnotatedSpecification} (dynamic
* instantiation by the user (see {@link DynamicInstanceAnnotationValueProviderBase}), <b>instance
* keys</b> are used to differentiate the different instances.</li>
* <li>Additionally, keys are used to differentiate the different annotations that can be hosted by
* a single {@link IAnnotatedSpecification}. A typical use case is a single
* <li>Kys are used to differentiate the different annotations that can be hosted by a single
* {@link IAnnotatedSpecification}. A typical use case is a single
* {@link EStructuralFeatureValueProviderBase} that supports multiple (or all)
* {@link EStructuralFeature} provided by single annotation class.</li>
* <li>In case the annotation only provides a single value, the {@link #DEFAULT_KEY} is used. For
......@@ -408,29 +405,13 @@ public interface IAnnotationValueProvider<T extends IAnnotatedSpecification> ext
/**
* 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.
* {@link IAnnotationValueProvider}s can either define a static {@link List}.
*/
public Collection<String> getInstanceKeys(T specification);
/** Returns the {@link EStructuralFeatureDescriptor} for a given {@code instanceKey}. */
public EStructuralFeatureDescriptor getEStructuralFeatureDescriptor(String instanceKey);
/**
* <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).
* </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();
/**
* <p>
* Returns a list of {@link AnnotationActionEntry}s <--> {@link BiConsumer} {@link Pair}s that
......
......@@ -15,11 +15,11 @@
+--------------------------------------------------------------------------*/
package org.fortiss.tooling.base.annotation.valueprovider;
import static java.util.Collections.emptyList;
import static org.fortiss.tooling.kernel.utils.EcoreUtils.pickFirstInstanceOf;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
......@@ -235,13 +235,7 @@ public abstract class ValueProviderBase<T extends IAnnotatedSpecification> imple
/** {@inheritDoc} */
@Override
public Collection<String> getInstanceKeys(T specification) {
return Collections.emptyList();
}
/** {@inheritDoc} */
@Override
public boolean allowsDynamicAnnotationInstances() {
return false;
return emptyList();
}
/** Returns the {@link #fixedInputChoiceMap}. */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment