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
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