blob: 3cf0ce297a79d9c95277dc07f1fdf611d60225dc [file] [log] [blame]
/*******************************************************************************
* Copyright 2011 Chair for Applied Software Engineering,
* Technische Universitaet Muenchen.
* All rights reserved. This program and the accompanying materials
* are made available under the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
******************************************************************************/
package org.eclipse.emf.emfstore.client.ui.views.changes;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.util.EMap;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.emfstore.client.ui.Activator;
import org.eclipse.emf.emfstore.common.IDisposable;
import org.eclipse.emf.emfstore.common.model.IdEObjectCollection;
import org.eclipse.emf.emfstore.common.model.ModelElementId;
import org.eclipse.emf.emfstore.common.model.ModelFactory;
import org.eclipse.emf.emfstore.common.model.util.ModelUtil;
import org.eclipse.emf.emfstore.server.model.provider.AbstractOperationCustomLabelProvider;
import org.eclipse.emf.emfstore.server.model.provider.CustomOperationLabelProviderManager;
import org.eclipse.emf.emfstore.server.model.versioning.ChangePackage;
import org.eclipse.emf.emfstore.server.model.versioning.operations.AbstractOperation;
import org.eclipse.emf.emfstore.server.model.versioning.operations.AttributeOperation;
import org.eclipse.emf.emfstore.server.model.versioning.operations.CompositeOperation;
import org.eclipse.emf.emfstore.server.model.versioning.operations.CreateDeleteOperation;
import org.eclipse.emf.emfstore.server.model.versioning.operations.MultiReferenceMoveOperation;
import org.eclipse.emf.emfstore.server.model.versioning.operations.MultiReferenceOperation;
import org.eclipse.emf.emfstore.server.model.versioning.operations.ReferenceOperation;
import org.eclipse.emf.emfstore.server.model.versioning.operations.SingleReferenceOperation;
import org.eclipse.emf.emfstore.server.model.versioning.operations.UnkownFeatureException;
import org.eclipse.emf.emfstore.server.model.versioning.operations.provider.AbstractOperationItemProvider;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.swt.graphics.Image;
/**
* A helper class for the visualization of change packages.
*
* @author koegel
* @author shterev
* @author emueller
*/
public class ChangePackageVisualizationHelper implements IDisposable {
private DefaultOperationLabelProvider defaultOperationLabelProvider;
private IdEObjectCollection collection;
private List<ChangePackage> changePackages;
private Map<String, EObject> idToEObjectMapofChangePackages;
/**
* Constructor.
*
* @param collection
* the {@link IdEObjectCollection} that is holding the EObjects that are going to be visualized
* as part of the change packages
* @param changePackages add changepackages in order to find deleted elements
*/
public ChangePackageVisualizationHelper(IdEObjectCollection collection, List<ChangePackage> changePackages) {
defaultOperationLabelProvider = new DefaultOperationLabelProvider();
this.collection = collection;
this.changePackages = changePackages;
}
/**
* Get the overlay image for an operation.
*
* @param operation
* the operation
* @return the ImageDescriptor
*/
public ImageDescriptor getOverlayImage(AbstractOperation operation) {
String overlay = null;
if (operation instanceof CreateDeleteOperation) {
CreateDeleteOperation op = (CreateDeleteOperation) operation;
if (op.isDelete()) {
overlay = "icons/delete_overlay.png";
} else {
overlay = "icons/add_overlay.png";
}
} else if (operation instanceof AttributeOperation) {
AttributeOperation op = (AttributeOperation) operation;
if (op.getNewValue() == null) {
overlay = "icons/delete_overlay.png";
} else if (op.getOldValue() == null) {
overlay = "icons/add_overlay.png";
} else {
overlay = "icons/modify_overlay.png";
}
} else if (operation instanceof SingleReferenceOperation) {
SingleReferenceOperation op = (SingleReferenceOperation) operation;
if (op.getNewValue() == null) {
overlay = "icons/delete_overlay.png";
} else {
overlay = "icons/link_overlay.png";
}
} else if (operation instanceof MultiReferenceOperation) {
MultiReferenceOperation op = (MultiReferenceOperation) operation;
if (op.getReferencedModelElements().size() > 0) {
overlay = "icons/link_overlay.png";
}
} else if (operation instanceof MultiReferenceMoveOperation) {
overlay = "icons/link_overlay.png";
} else {
overlay = "icons/modify_overlay.png";
}
ImageDescriptor overlayDescriptor = Activator.getImageDescriptor(overlay);
return overlayDescriptor;
}
/**
* Get an image for the operation.
*
* @param emfProvider
* the label provider
* @param operation
* the operation
* @return an image
*/
public Image getImage(ILabelProvider emfProvider, AbstractOperation operation) {
// check if a custom label provider can provide an image
Image image = getCustomOperationProviderLabel(operation);
if (image != null) {
return image;
}
return emfProvider.getImage(operation);
}
private Image getCustomOperationProviderLabel(AbstractOperation operation) {
AbstractOperationCustomLabelProvider customLabelProvider = CustomOperationLabelProviderManager.getInstance()
.getCustomLabelProvider(operation);
if (customLabelProvider != null) {
try {
return (Image) customLabelProvider.getImage(operation);
// BEGIN SUPRESS CATCH EXCEPTION
} catch (RuntimeException e) {
// END SUPRESS CATCH EXCEPTION
ModelUtil.logWarning("Image load from custom operation item provider failed!", e);
}
}
return null;
}
/**
* Returns a description for the given operation.
*
* @param op
* the operation to generate a description for
* @return the description for the given operation
*/
public String getDescription(AbstractOperation op) {
// check of a custom operation label provider can provide a label
AbstractOperationCustomLabelProvider customLabelProvider = CustomOperationLabelProviderManager.getInstance()
.getCustomLabelProvider(op);
if (customLabelProvider != null) {
return decorate(customLabelProvider, op);
}
if (op instanceof CompositeOperation) {
CompositeOperation compositeOperation = (CompositeOperation) op;
// artificial composite because of opposite ref, take description of
// main operation
if (compositeOperation.getMainOperation() != null) {
return getDescription(compositeOperation.getMainOperation());
}
}
return decorate(defaultOperationLabelProvider, op);
}
private String decorate(AbstractOperationCustomLabelProvider labelProvider, AbstractOperation op) {
String namesResolved = resolveIds(labelProvider, labelProvider.getDescription(op),
AbstractOperationItemProvider.NAME_TAG__SEPARATOR, op);
String allResolved = resolveIds(labelProvider, namesResolved,
AbstractOperationItemProvider.NAME_CLASS_TAG_SEPARATOR, op);
if (op instanceof ReferenceOperation) {
return resolveTypes(allResolved, (ReferenceOperation) op);
}
return allResolved;
}
private String resolveTypes(String unresolvedString, ReferenceOperation op) {
EObject modelElement = getModelElement(op.getModelElementId());
String type;
if (modelElement == null) {
type = "ModelElement";
} else {
try {
EStructuralFeature feature = op.getFeature(modelElement);
type = feature.getEType().getName();
} catch (UnkownFeatureException e) {
type = "ModelElement";
}
}
return unresolvedString.replace(AbstractOperationItemProvider.REFERENCE_TYPE_TAG_SEPARATOR, type);
}
private String resolveIds(AbstractOperationCustomLabelProvider labelProvider, String unresolvedString,
String devider, AbstractOperation op) {
String[] strings = unresolvedString.split(devider);
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < strings.length; i++) {
if (i % 2 == 1) {
ModelElementId modelElementId = ModelFactory.eINSTANCE.createModelElementId();
modelElementId.setId(strings[i]);
EObject modelElement = getModelElement(modelElementId);
if (modelElement != null) {
stringBuilder.append(labelProvider.getModelElementName(modelElement));
} else if (modelElement == null && op instanceof CreateDeleteOperation) {
CreateDeleteOperation createDeleteOp = (CreateDeleteOperation) op;
for (Map.Entry<EObject, ModelElementId> entry : createDeleteOp.getEObjectToIdMap()) {
if (entry.getValue().equals(modelElementId)) {
stringBuilder.append(labelProvider.getModelElementName(entry.getKey()));
break;
}
}
}
} else {
stringBuilder.append(strings[i]);
}
}
return stringBuilder.toString();
}
/**
* Get a model element instance from the project for the given id.
*
* @param modelElementId
* the id
* @return the model element instance
*/
public EObject getModelElement(ModelElementId modelElementId) {
EObject modelElement = collection.getModelElement(modelElementId);
if (modelElement == null && modelElementId != null) {
modelElement = getMeFromChangePackage(modelElementId);
}
return modelElement;
}
private EObject getMeFromChangePackage(ModelElementId modelElementId) {
for (ChangePackage cp : changePackages) {
EObject me = getMeFromOpsList(modelElementId, cp.getOperations());
if (me != null) {
return me;
}
}
return null;
}
private EObject getMeFromOpsList(ModelElementId modelElementId, List<AbstractOperation> operations) {
if (idToEObjectMapofChangePackages == null) {
idToEObjectMapofChangePackages = new LinkedHashMap<String, EObject>();
scanOperationsIntoCache(operations);
}
return idToEObjectMapofChangePackages.get(modelElementId.getId());
}
private void scanOperationsIntoCache(List<AbstractOperation> operations) {
for (AbstractOperation op : operations) {
if (op instanceof CreateDeleteOperation) {
EMap<EObject, ModelElementId> eObjectToIdMap = ((CreateDeleteOperation) op).getEObjectToIdMap();
for (EObject eObject : eObjectToIdMap.keySet()) {
idToEObjectMapofChangePackages.put(eObjectToIdMap.get(eObject).getId(), eObject);
}
} else if (op instanceof CompositeOperation) {
scanOperationsIntoCache(((CompositeOperation) op).getSubOperations());
}
}
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.common.IDisposable#dispose()
*/
public void dispose() {
defaultOperationLabelProvider.dispose();
collection = null;
}
}