diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/AnnotationInstantiationMigrationProvider.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/AnnotationInstantiationMigrationProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..70963c691e24b1eb2b21682838e726cff62f7803 --- /dev/null +++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/AnnotationInstantiationMigrationProvider.java @@ -0,0 +1,75 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2013 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; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.xml.type.AnyType; +import org.fortiss.tooling.base.model.element.IAnnotatedSpecification; +import org.fortiss.tooling.base.model.element.IModelElement; +import org.fortiss.tooling.kernel.extension.IMigrationProvider; +import org.fortiss.tooling.kernel.extension.data.ITopLevelElement; + +/** + * {@link IMigrationProvider} that ensures that all {@link IAnnotatedSpecification}s that have been + * registered for model element types in the current model are actually instantiated. + * + * This is required for new {@link IAnnotatedSpecification}s that have been registered after the + * creation of the model. + * + * @author barner + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: DB938B8077EEAFB9455F8A83BF92CD86 + */ +public class AnnotationInstantiationMigrationProvider implements IMigrationProvider { + + /** + * Set of models already processed during this run. The implementation of a predicate function + * if model migration is needed (for use in {@link #needMigration(ITopLevelElement, Map)} would + * be as complex as the migration itself. + */ + private Set<ITopLevelElement> processedModels = new HashSet<ITopLevelElement>(); + + /** {@inheritDoc} */ + @Override + public boolean needMigration(ITopLevelElement modelElement, + Map<EObject, AnyType> unknownFeatures) { + + return modelElement != null && modelElement.getRootModelElement() != null && + !processedModels.contains(modelElement); + } + + /** {@inheritDoc} */ + @Override + public void migrate(ITopLevelElement modelElement, Map<EObject, AnyType> unknownFeatures) { + processedModels.add(modelElement); + + for(Iterator<EObject> i = modelElement.getRootModelElement().eAllContents(); i.hasNext();) { + EObject eo = i.next(); + if(eo instanceof IModelElement) { + + // IAnnotationValueService.INSTANCE.instantiateAnnotations((IModelElement)eo); + } + } + } +} 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 297003e087396fcfe5adbf2ae0ba1065e5698743..a7c2b4151ded73eda07a8a3731dafded9f48708f 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 @@ -132,9 +132,66 @@ public class AnnotationValueService extends return valueProviderList; } + /** + * Prepares the {@link AnnotationEntry} for a given {@link IModelElement} and ensures that all + * {@link IAnnotatedSpecification}s are instantiated. + */ + private void prepareAnnotationEntry(final IModelElement element, AnnotationEntry entry, + final List<IAnnotationValueProvider<IAnnotatedSpecification>> registeredHandlers) { + for(IAnnotationValueProvider<IAnnotatedSpecification> annotationProvider : registeredHandlers) { + + IAnnotatedSpecification annotatedSpecification = + EcoreUtils.pickFirstInstanceOf(annotationProvider.getAnnotationClazz(), + element.getSpecifications()); + + // + // + // 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 + entry.addNewSpecification(annotationProvider, annotatedSpecification); + } + + } + /** {@inheritDoc} */ @Override - public AnnotationEntry getAnnotationEntry(final IModelElement element) { + public void instantiateAnnotations(final IModelElement element) { + getAnnotationEntry(element, false); + } + + /** + * Helper method that performs the actual work of {@link #getAnnotationEntry(IModelElement)} and + * {@link #instantiateAnnotations(IModelElement)}, i.e. that acquires (and potentially + * instantiates) annotations for model elements. + * + * @return {@link AnnotationEntry} for all {@link IAnnotatedSpecification}s of the given + * {@link IModelElement}. + */ + private AnnotationEntry + getAnnotationEntry(final IModelElement element, boolean wrapIntoCommand) { AnnotationEntry cachedResult = annotationEntryCache.get(element); if(cachedResult != null) { @@ -150,50 +207,17 @@ public class AnnotationValueService extends final AnnotationEntry result = new AnnotationEntry(element); if(registeredHandlers != null && !registeredHandlers.isEmpty()) { - KernelModelElementUtils.runAsCommand(element, new Runnable() { - - @Override - public void run() { - - for(IAnnotationValueProvider<IAnnotatedSpecification> annotationProvider : registeredHandlers) { - - 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); + if(wrapIntoCommand) { + KernelModelElementUtils.runAsCommand(element, new Runnable() { + + @Override + public void run() { + prepareAnnotationEntry(element, result, registeredHandlers); } - } - }); + }); + } else { + prepareAnnotationEntry(element, result, registeredHandlers); + } } annotationEntryCache.put(element, result); @@ -201,6 +225,12 @@ public class AnnotationValueService extends return result; } + /** {@inheritDoc} */ + @Override + public AnnotationEntry getAnnotationEntry(final IModelElement element) { + return getAnnotationEntry(element, true); + } + /** {@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 a9f4d7d464dc340f29b2ddb815ac039d55faa749..f94234ceaad0baf0ca1777adb435b5b79f76276f 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 @@ -19,6 +19,7 @@ package org.fortiss.tooling.base.ui.annotation; import org.fortiss.tooling.base.model.element.IAnnotatedSpecification; import org.fortiss.tooling.base.model.element.IModelElement; +import org.fortiss.tooling.kernel.utils.KernelModelElementUtils; /** * @@ -33,11 +34,30 @@ public interface IAnnotationValueService { public static final IAnnotationValueService INSTANCE = new AnnotationValueService(); /** + * <p> * 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. + * specialization does not exist for the given {@code modelElement} yet, it instantiated. + * </p> + * + * <p> + * This method uses + * {@link KernelModelElementUtils#runAsCommand(org.eclipse.emf.ecore.EObject, Runnable)} and + * hence is safe to be called from the GUI context. + * </p> */ - AnnotationEntry getAnnotationEntry(IModelElement element); + public AnnotationEntry getAnnotationEntry(IModelElement element); + + /** + * <p> + * If required, instantiate annotation for the given model element. + * </p> + * + * <p> + * <b>CAVEAT: </b>This method must be called from a context that allows the modification of the + * model. + * </p> + */ + public void instantiateAnnotations(IModelElement element); }