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

- Avoid unbounded recursion in DynamicInstanceAnnotationValueProviderBase

- Fix editing of dynamically instantiated annotations
refs 1841
parent 41140626
No related branches found
No related tags found
No related merge requests found
...@@ -20,6 +20,7 @@ package org.fortiss.tooling.base.ui.annotation.editingsupport; ...@@ -20,6 +20,7 @@ package org.fortiss.tooling.base.ui.annotation.editingsupport;
import org.eclipse.jface.viewers.ColumnViewer; import org.eclipse.jface.viewers.ColumnViewer;
import org.fortiss.tooling.base.model.element.IAnnotatedSpecification; import org.fortiss.tooling.base.model.element.IAnnotatedSpecification;
import org.fortiss.tooling.base.ui.annotation.AnnotationEntry; import org.fortiss.tooling.base.ui.annotation.AnnotationEntry;
import org.fortiss.tooling.base.ui.annotation.IAnnotationValueService;
import org.fortiss.tooling.base.ui.annotation.valueprovider.DynamicInstanceAnnotationValueProviderBase; import org.fortiss.tooling.base.ui.annotation.valueprovider.DynamicInstanceAnnotationValueProviderBase;
/** /**
...@@ -63,7 +64,21 @@ public class MultiInstanceAnnotationTextEditingSupport extends TextEditingSuppor ...@@ -63,7 +64,21 @@ public class MultiInstanceAnnotationTextEditingSupport extends TextEditingSuppor
protected boolean canEdit(Object element) { protected boolean canEdit(Object element) {
if(element instanceof AnnotationEntry) { if(element instanceof AnnotationEntry) {
AnnotationEntry data = (AnnotationEntry)element; AnnotationEntry data = (AnnotationEntry)element;
return data.getSpecificationValue(specClass, instanceKey) != null;
// Check if a value already exists.
if(data.getSpecificationValue(specClass, instanceKey) != null) {
return true;
}
// For dynamically instantiated annotations, check if the key exists with at least one
// model element.
for(AnnotationEntry entry : IAnnotationValueService.INSTANCE.getValues(data
.getModelElement())) {
if(entry.getInstanceKeys(specClass).contains(instanceKey)) {
return true;
}
}
} }
return true; return true;
......
...@@ -81,11 +81,12 @@ public abstract class DynamicInstanceAnnotationValueProviderBase<T extends IAnno ...@@ -81,11 +81,12 @@ public abstract class DynamicInstanceAnnotationValueProviderBase<T extends IAnno
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override @Override
public <V> V getAnnotationValue(T spec, String instanceKey) throws Exception { public <V> V getAnnotationValue(T specification, String instanceKey) throws Exception {
// Return value of current instance (entry map containing all instances of the annotation) // Return value of current instance (entry map containing all instances of the annotation)
return ((EMap<String, V>)getAnnotationValue(spec)).get(instanceKey); EMap<String, V> map = super.getAnnotationValue(specification, DEFAULT_KEY);
return map.get(instanceKey);
} }
...@@ -97,19 +98,28 @@ public abstract class DynamicInstanceAnnotationValueProviderBase<T extends IAnno ...@@ -97,19 +98,28 @@ public abstract class DynamicInstanceAnnotationValueProviderBase<T extends IAnno
private <V> void private <V> void
setAnnotationValueFromString(String value, T specification, String instanceKey) setAnnotationValueFromString(String value, T specification, String instanceKey)
throws Exception { throws Exception {
((EMap<String, V>)getAnnotationValue(specification)).put(instanceKey, EMap<String, V> map = super.getAnnotationValue(specification, DEFAULT_KEY);
(V)valueFactory.createFromString(valueDataType, value));
V val = (V)valueFactory.createFromString(valueDataType, value);
if(val == null) {
val = (V)valueDataType.getDefaultValue();
}
if(val == null) {
val = (V)valueFactory.createFromString(valueDataType, "0");
}
map.put(instanceKey, val);
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override @Override
public <V> void setAnnotationValue(V value, T specification, String instanceKey) public <V> void setAnnotationValue(V value, T specification, String instanceKey)
throws Exception { throws Exception {
if(value instanceof String) { if(value instanceof String) {
setAnnotationValueFromString((String)value, specification, instanceKey); setAnnotationValueFromString((String)value, specification, instanceKey);
} else { } else {
((EMap<String, V>)getAnnotationValue(specification)).put(instanceKey, value); EMap<String, V> map = super.getAnnotationValue(specification, DEFAULT_KEY);
map.put(instanceKey, value);
} }
} }
...@@ -136,7 +146,7 @@ public abstract class DynamicInstanceAnnotationValueProviderBase<T extends IAnno ...@@ -136,7 +146,7 @@ public abstract class DynamicInstanceAnnotationValueProviderBase<T extends IAnno
EMap<String, ?> kVMap = null; EMap<String, ?> kVMap = null;
try { try {
kVMap = getAnnotationValue(specification); kVMap = super.getAnnotationValue(specification, DEFAULT_KEY);
} catch(Exception e) { } catch(Exception e) {
// Ignore exception // Ignore exception
} }
......
...@@ -20,6 +20,8 @@ package org.fortiss.tooling.base.ui.annotation.view; ...@@ -20,6 +20,8 @@ package org.fortiss.tooling.base.ui.annotation.view;
import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.NotificationImpl; import org.eclipse.emf.common.notify.impl.NotificationImpl;
import org.eclipse.emf.common.util.EMap; 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.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.MessageDialog;
...@@ -44,6 +46,7 @@ import org.eclipse.swt.widgets.TableColumn; ...@@ -44,6 +46,7 @@ import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.TableItem;
import org.fortiss.tooling.base.model.element.IAnnotatedSpecification; import org.fortiss.tooling.base.model.element.IAnnotatedSpecification;
import org.fortiss.tooling.base.ui.annotation.AnnotationEntry; import org.fortiss.tooling.base.ui.annotation.AnnotationEntry;
import org.fortiss.tooling.base.ui.annotation.IAnnotationValueService;
import org.fortiss.tooling.kernel.extension.data.ITopLevelElement; import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
import org.fortiss.tooling.kernel.service.IPersistencyService; import org.fortiss.tooling.kernel.service.IPersistencyService;
...@@ -224,21 +227,42 @@ public class CreateAnnotationInstanceColumn extends ViewerColumn { ...@@ -224,21 +227,42 @@ public class CreateAnnotationInstanceColumn extends ViewerColumn {
.getModelElement()); .getModelElement());
modelContext.runAsCommand(new Runnable() { modelContext.runAsCommand(new Runnable() {
@SuppressWarnings("unchecked")
@Override @Override
public void run() { public void run() {
try { try {
// Work around the fact that getSpecificationValue(null, // Populate new instance (in order to make the corresponding cells
// columnSpec.getClass(), instanceKey) would resolve // editable
// to the more specific getSpecificationValue(String, Class<? String value = "";
// extends IAnnotatedSpecification>, String) overload of the method, if(!columnSpec.eClass().getEStructuralFeatures().isEmpty()) {
// and thus would not work for maps whose value type is not String. EStructuralFeature dynamicInstanceFeature =
// columnSpec.eClass().getEStructuralFeatures().get(0);
// Hence, the entire instance map is retrieved here, and put() is
// called explicitly. // Annotations that can be dynamically instantiated are
((EMap<String, ?>)columnSpecAnnEntry // implemented using an appropriate EMap.
.getSpecificationValue(columnSpec.getClass())).put( if(dynamicInstanceFeature.getEType().getInstanceTypeName()
instanceKey, null); .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";
}
}
}
for(AnnotationEntry entry : IAnnotationValueService.INSTANCE
.getValues(columnSpecAnnEntry.getModelElement())) {
entry.setSpecificationValue(value, columnSpec.getClass(),
instanceKey);
}
// Inform others, e.g. the respective annotation view that a new // Inform others, e.g. the respective annotation view that a new
// instance of this annotation has been created. // instance of this annotation has been created.
......
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