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

- Add AnnotationInstantiationMigrationProvider that augments loaded models...

- Add AnnotationInstantiationMigrationProvider that augments loaded models with annotations that have been added to the AF3 installation after the creation of the model.
- Note that:
  - It is still required to use AnnotationUtils.getAnnotation() to obtain (and potentially instantiate) an annotation. This is because annotations are only instantiated for newly added model elements if the annotation view is visible.
  - IMigrationProviders that convert old attribute values into annotations cannot rely on the fact that the annotation instance already exists (since the execution order of the IMigrationProviders is not defined). Hence, the need to use AnnotationUtils.getAnnotation(modelElement, clazz, false) to obtain (and potentially instantiate) an annotation (without wrapping the model access into a command, see #2010).
refs 1841
parent 37696eb5
No related branches found
No related tags found
No related merge requests found
/*--------------------------------------------------------------------------+
$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);
}
}
}
}
......@@ -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() {
......
......@@ -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);
}
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