blob: cde858a6eb5fa3c1e89c10f3463fddbfb171fc19 [file] [log] [blame]
package org.eclipse.m2m.internal.qvt.oml.editor.ui;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EParameter;
import org.eclipse.jface.text.ISynchronizable;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.IAnnotationModelExtension;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalEnvFactory;
import org.eclipse.m2m.internal.qvt.oml.compiler.CompiledUnit;
import org.eclipse.m2m.internal.qvt.oml.cst.MappingMethodCS;
import org.eclipse.m2m.internal.qvt.oml.cst.MappingModuleCS;
import org.eclipse.m2m.internal.qvt.oml.editor.ui.hovers.SignatureUtil;
import org.eclipse.m2m.internal.qvt.oml.expressions.ImperativeOperation;
import org.eclipse.ocl.utilities.UMLReflection;
import org.eclipse.osgi.util.NLS;
/**
* Manages the override indicators for the given QVT element and annotation model.
*/
class OverrideIndicatorManager implements IQVTReconcilingListener {
static final String ANNOTATION_TYPE = "org.eclipse.m2m.qvt.oml.ui.overrideIndicator"; //$NON-NLS-1$
private IAnnotationModel fAnnotationModel;
private Object fAnnotationModelLockObject;
private Annotation[] fOverrideAnnotations;
public OverrideIndicatorManager(IAnnotationModel annotationModel) {
if(annotationModel == null) {
throw new IllegalArgumentException();
}
fAnnotationModel = annotationModel;
fAnnotationModelLockObject = getLockObject(fAnnotationModel);
}
/**
* Returns the lock object for the given annotation model.
*
* @param annotationModel the annotation model
* @return the annotation model's lock object
*/
private Object getLockObject(IAnnotationModel annotationModel) {
if (annotationModel instanceof ISynchronizable) {
Object lock= ((ISynchronizable)annotationModel).getLockObject();
if (lock != null) {
return lock;
}
}
return annotationModel;
}
/**
* Updates the override and implements annotations based
* on the given compilation unit.
*
* @param unit the compilation unit
* @param progressMonitor the progress monitor
*/
protected void updateAnnotations(CompiledUnit unit, IProgressMonitor progressMonitor) {
if (progressMonitor.isCanceled()) {
return;
}
UMLReflection<?, EClassifier, EOperation, ?, ?, EParameter, ?, ?, ?, ?> uml =
QvtOperationalEnvFactory.INSTANCE.createEnvironment().getUMLReflection();
Map<Annotation, Position> annotationMap = new HashMap<Annotation, Position>(50);
for(MappingModuleCS moduleCS : unit.getUnitCST().getModules()) {
for(MappingMethodCS methodCS : moduleCS.getMethods()) {
if (progressMonitor.isCanceled()) {
return;
}
if(methodCS.getAst() instanceof ImperativeOperation) {
ImperativeOperation imperativeOperation = (ImperativeOperation) methodCS.getAst();
if(imperativeOperation.getOverridden() != null) {
String text = NLS.bind(Messages.OverrideAnnotationText, SignatureUtil.getOperationSignature(uml, imperativeOperation.getOverridden()));
Annotation annotation = new Annotation(ANNOTATION_TYPE, false, text);
Position position = new Position(methodCS.getStartOffset(), 1);
annotationMap.put(annotation, position);
}
}
}
}
if (progressMonitor.isCanceled()) {
return;
}
synchronized (fAnnotationModelLockObject) {
if (fAnnotationModel instanceof IAnnotationModelExtension) {
((IAnnotationModelExtension)fAnnotationModel).replaceAnnotations(fOverrideAnnotations, annotationMap);
} else {
removeAnnotations();
for(Map.Entry<Annotation, Position> mapEntry : annotationMap.entrySet()) {
fAnnotationModel.addAnnotation(mapEntry.getKey(), mapEntry.getValue());
}
}
fOverrideAnnotations = annotationMap.keySet().toArray(new Annotation[annotationMap.keySet().size()]);
}
}
/**
* Removes all override indicators from this manager's annotation model.
*/
private void removeAnnotations() {
if (fOverrideAnnotations == null) {
return;
}
synchronized (fAnnotationModelLockObject) {
if (fAnnotationModel instanceof IAnnotationModelExtension) {
((IAnnotationModelExtension)fAnnotationModel).replaceAnnotations(fOverrideAnnotations, null);
} else {
for (int i = 0, length = fOverrideAnnotations.length; i < length; i++) {
fAnnotationModel.removeAnnotation(fOverrideAnnotations[i]);
}
}
fOverrideAnnotations= null;
}
}
public void reconciled(CompiledUnit unit, IProgressMonitor monitor) {
updateAnnotations(unit, new NullProgressMonitor());
}
public void aboutToBeReconciled() {
// do nothing
}
}