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 f726191ae9fe1fc8d40744da92fabba2a8b75156..8ac0317d6c8572a4cea38b81d73a0530fcf2811a 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 @@ -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) { diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/AnnotationValueService.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/AnnotationValueService.java index 3298068222a600fbc03f7c40f1904a030de8545e..297003e087396fcfe5adbf2ae0ba1065e5698743 100644 --- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/AnnotationValueService.java +++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/AnnotationValueService.java @@ -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() { diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/IAnnotationValueService.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/IAnnotationValueService.java index 7eea279f0231fd884b4fb8b37a6a9d88d4370891..a9f4d7d464dc340f29b2ddb815ac039d55faa749 100644 --- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/IAnnotationValueService.java +++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/IAnnotationValueService.java @@ -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); } diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/AnnotationViewPartBase.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/AnnotationViewPartBase.java index 8dccf0c37bfbf07f68eb37537ed06ee0fd04e0c5..c57eee9bc8b1920e31a323486e637cf460f88980 100644 --- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/AnnotationViewPartBase.java +++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/AnnotationViewPartBase.java @@ -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 diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/generic/CreateAnnotationInstanceColumn.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/generic/CreateAnnotationInstanceColumn.java index 42226ae484c6356ddada6e41308998a08b88333f..c95f84e0ed17773e2bc824d0407b525b5b8ddf32 100644 --- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/generic/CreateAnnotationInstanceColumn.java +++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/generic/CreateAnnotationInstanceColumn.java @@ -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. diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/generic/GenericAnnotationView.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/generic/GenericAnnotationView.java index 9d587b92be919587260581d540393048154910d3..a039b0d044ce38528b2d66ed57b7342c34e8c3bc 100644 --- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/generic/GenericAnnotationView.java +++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/generic/GenericAnnotationView.java @@ -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}. */