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

(I)AnnotationValueService:

 - List<AnnotationEntry> getValues(IModelElement element) --> AnnotationEntry getAnnotationEntry(IModelElement element);
 - The semantics of the method is change to return exactly the AnnotationEntry that contains the AnnotationValueProvider-to-IAnnotatedSpecification mapping for the given model element. In the old semantics, a list of all annotation entries for model elements that had the same type as the given model element have been returned.

AnnotationEntry:
 - add isEmpty()

Consequences:
 - Fix update bug of GenericAnnotationView when deleting model elements (stale rows used to stay in the view)
 - Performance improvement

TODO: The GenericAnnotationView is still very slow during the deletion of large sub-models (and probably also during addition e.g., because of c'n'p of large sub-models) 
refs 1841
parent 82bcc77e
No related branches found
No related tags found
No related merge requests found
......@@ -63,6 +63,14 @@ public final class AnnotationEntry {
}
/**
* Predicate if the given {@link AnnotationEntry} is empty, i.e. if it does not contain any
* {@link IAnnotatedSpecification}s.
*/
public boolean isEmpty() {
return specificationsList.isEmpty();
}
/** adds a new tuple {@link IAnnotationValueProvider} {@link IAnnotatedSpecification} */
public void addNewSpecification(IAnnotationValueProvider<IAnnotatedSpecification> provider,
IAnnotatedSpecification spec) {
......
......@@ -18,7 +18,6 @@ $Id$
package org.fortiss.tooling.base.ui.annotation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
......@@ -27,11 +26,9 @@ import java.util.Map;
import java.util.Queue;
import java.util.Set;
import org.eclipse.emf.ecore.EObject;
import org.fortiss.tooling.base.model.element.IAnnotatedSpecification;
import org.fortiss.tooling.base.model.element.IModelElement;
import org.fortiss.tooling.base.ui.annotation.valueprovider.IAnnotationValueProvider;
import org.fortiss.tooling.kernel.model.IProjectRootElement;
import org.fortiss.tooling.kernel.service.base.EObjectAwareServiceBase;
import org.fortiss.tooling.kernel.utils.EcoreUtils;
import org.fortiss.tooling.kernel.utils.KernelModelElementUtils;
......@@ -62,8 +59,8 @@ public class AnnotationValueService extends
new HashMap<Class<?>, List<IAnnotationValueProvider<IAnnotatedSpecification>>>();
/** Cache to lookup {@link AnnotationEntry}s for {@link IModelElement}s. */
Map<IModelElement, List<AnnotationEntry>> annotationEntryCache =
new HashMap<IModelElement, List<AnnotationEntry>>();
Map<IModelElement, AnnotationEntry> annotationEntryCache =
new HashMap<IModelElement, AnnotationEntry>();
/**
*
......@@ -137,70 +134,63 @@ public class AnnotationValueService extends
/** {@inheritDoc} */
@Override
public List<AnnotationEntry> getValues(final IModelElement element) {
public AnnotationEntry getAnnotationEntry(final IModelElement element) {
List<AnnotationEntry> cachedResult = annotationEntryCache.get(element);
AnnotationEntry cachedResult = annotationEntryCache.get(element);
if(cachedResult != null) {
return cachedResult;
}
if(element == null) {
return Collections.emptyList();
return null;
}
final List<IAnnotationValueProvider<IAnnotatedSpecification>> registeredHandlers =
getRegisteredHandlers(element.getClass());
final List<AnnotationEntry> result = new ArrayList<AnnotationEntry>();
final AnnotationEntry result = new AnnotationEntry(element);
if(registeredHandlers != null && !registeredHandlers.isEmpty()) {
KernelModelElementUtils.runAsCommand(element, new Runnable() {
@Override
public void run() {
EObject root = element;
while(!(root instanceof IProjectRootElement)) {
root = root.eContainer();
}
for(IAnnotationValueProvider<IAnnotatedSpecification> annotationProvider : registeredHandlers) {
List<? extends IModelElement> allChildren =
getAllChildren(root, element.getClass(), annotationProvider
.excludeModelElementTypeFromAnnotatedSpecification());
for(final IModelElement e : allChildren) {
IAnnotatedSpecification annotatedSpecification =
EcoreUtils.pickFirstInstanceOf(
annotationProvider.getAnnotationClazz(),
e.getSpecifications());
if(annotatedSpecification == null) {
try {
annotatedSpecification =
annotationProvider
.getAnnotatedSpecificationForModelElement(e);
} catch(Exception ex) {
System.out
.println("Error instantating new annotation: createAnnotatedSpecificationForModelElement() failed for " +
annotationProvider.getAnnotationClazz() + ".");
return;
}
}
for(IAnnotationValueProvider<IAnnotatedSpecification> annotationProvider : registeredHandlers) {
boolean add = true;
for(AnnotationEntry entry : result) {
if(entry.getModelElement().equals(e)) {
entry.addNewSpecification(annotationProvider,
annotatedSpecification);
add = false;
}
}
if(add) {
AnnotationEntry entry = new AnnotationEntry(e);
entry.addNewSpecification(annotationProvider,
annotatedSpecification);
result.add(entry);
IAnnotatedSpecification annotatedSpecification =
EcoreUtils.pickFirstInstanceOf(
annotationProvider.getAnnotationClazz(),
element.getSpecifications());
// If required, instantiate annotation for the given model element.
//
// TODO: This is a bad design choice because that way annotations are
// instantiated from the GUI context. This will have the consequence that
// new annotations types will not have been instantiated for elements of
// legacy models (i.e., models that have been created before the the new
// annotation has been added) until the model is opened and the
// corresponding elements are displayed in a view that makes use of this
// getValues() method
//
// This problem typically arises in IMigrationProviders, which run before
// the GUI. Hence, the only safe way to acquire an annotation for a model
// element is org.fortiss.tooling.base.utils.AnnotationUtils.getAnnotation()
// which will take care of the instantiation (if required).
if(annotatedSpecification == null) {
try {
annotatedSpecification =
annotationProvider
.getAnnotatedSpecificationForModelElement(element);
} catch(Exception ex) {
System.out
.println("Error instantating new annotation: createAnnotatedSpecificationForModelElement() failed for " +
annotationProvider.getAnnotationClazz() + ".");
return;
}
}
// Register annotation provider <-> annotation specification mapping
result.addNewSpecification(annotationProvider, annotatedSpecification);
}
}
});
......@@ -211,32 +201,6 @@ public class AnnotationValueService extends
return result;
}
/**
* Returns all children from element of the given type and filters out children of the given
* {@code modelElementTypesExcludedFromAnnotatedSpecification} list.
*/
private <S, T> List<? extends IModelElement> getAllChildren(EObject element,
Class<? extends IModelElement> type,
List<Class<? extends EObject>> modelElementTypesExcludedFromAnnotatedSpecification) {
List<? extends IModelElement> results = EcoreUtils.getChildrenWithType(element, type);
if(modelElementTypesExcludedFromAnnotatedSpecification != null) {
List<IModelElement> toRemove = new ArrayList<IModelElement>();
for(IModelElement modelElement : results) {
for(Class<?> c : modelElementTypesExcludedFromAnnotatedSpecification) {
if(c.isInstance(modelElement)) {
toRemove.add(modelElement);
break;
}
}
}
results.removeAll(toRemove);
}
return results;
}
/** {@inheritDoc} */
@Override
protected String getExtensionPointName() {
......
......@@ -17,8 +17,7 @@ $Id$
+--------------------------------------------------------------------------*/
package org.fortiss.tooling.base.ui.annotation;
import java.util.List;
import org.fortiss.tooling.base.model.element.IAnnotatedSpecification;
import org.fortiss.tooling.base.model.element.IModelElement;
/**
......@@ -33,7 +32,12 @@ public interface IAnnotationValueService {
/** Singleton instance */
public static final IAnnotationValueService INSTANCE = new AnnotationValueService();
/** Return the annotated values of the given element */
List<AnnotationEntry> getValues(IModelElement element);
/**
* Returns the {@link AnnotationEntry} for the given {@link IModelElement}. In case any of the
* {@link IAnnotatedSpecification}s registered for the corresponding {@link IModelElement}
* specialization does not exist for the given {@code modelElement} yet, it instantiated by this
* method.
*/
AnnotationEntry getAnnotationEntry(IModelElement element);
}
......@@ -169,6 +169,21 @@ public abstract class AnnotationViewPartBase extends ViewPart implements ISelect
return rootElement;
}
/**
* Adds an AnnotationEntry for a given {@code modelElement} to a list of
* {@code annotationEntries} in case the acquired annotation is not empty, i.e. if it
* contributes
* at least one {@link IAnnotatedSpecification}.
*/
private void addAnnotationEntry(Collection<AnnotationEntry> annotationEntries,
IModelElement modelElement) {
AnnotationEntry entry = IAnnotationValueService.INSTANCE.getAnnotationEntry(modelElement);
if(!entry.isEmpty()) {
annotationEntries.add(entry);
}
}
/**
* Update the {@link AnnotationViewPartBase}: delegate update of concrete view to
* {@link #update(Collection)}, and update model change listeners.
......@@ -196,13 +211,11 @@ public abstract class AnnotationViewPartBase extends ViewPart implements ISelect
// Collect all AnnotationEntries for the current root element and its offspring
if(rootElement instanceof IModelElement) {
annotationEntries.addAll(IAnnotationValueService.INSTANCE
.getValues((IModelElement)rootElement));
addAnnotationEntry(annotationEntries, (IModelElement)rootElement);
}
for(IModelElement childModelElement : EcoreUtils.getChildrenWithType(rootElement,
IModelElement.class)) {
annotationEntries.addAll(IAnnotationValueService.INSTANCE
.getValues(childModelElement));
addAnnotationEntry(annotationEntries, childModelElement);
}
// Cache annotation entries for the given root element
......
......@@ -257,12 +257,12 @@ public class CreateAnnotationInstanceColumn extends ViewerColumn {
}
for(AnnotationEntry entry : IAnnotationValueService.INSTANCE
.getValues(columnSpecAnnEntry.getModelElement())) {
AnnotationEntry entry =
IAnnotationValueService.INSTANCE
.getAnnotationEntry(columnSpecAnnEntry.getModelElement());
entry.setSpecificationValue(value, columnSpec.getClass(),
instanceKey);
}
entry.setSpecificationValue(value, columnSpec.getClass(),
instanceKey);
// Inform others, e.g. the respective annotation view that a new
// instance of this annotation has been created.
......
......@@ -272,12 +272,10 @@ public class GenericAnnotationView extends AnnotationViewPartBase {
super.update(modelElement);
// ensure that selected model element is visible in annotation view
for(AnnotationEntry annotation : IAnnotationValueService.INSTANCE.getValues(modelElement)) {
if(annotation.getModelElement() == modelElement) {
tableViewer.reveal(annotation);
break;
}
}
AnnotationEntry entry = IAnnotationValueService.INSTANCE.getAnnotationEntry(modelElement);
assert (entry.getModelElement() == modelElement);
tableViewer.reveal(entry);
}
/** Initializes the {@link AnnotationFilterWidget}. */
......
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