/******************************************************************************* * Copyright (c) 2008-2011 Chair for Applied Software Engineering, * Technische Universitaet Muenchen. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * shterev * emueller * koegel ******************************************************************************/ package org.eclipse.emf.emfstore.internal.client.ui.views.changes; import java.util.Map; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.emfstore.internal.client.ui.Activator; import org.eclipse.emf.emfstore.internal.client.ui.common.OperationCustomLabelProvider; import org.eclipse.emf.emfstore.internal.common.ExtensionRegistry; import org.eclipse.emf.emfstore.internal.common.model.ModelElementId; import org.eclipse.emf.emfstore.internal.common.model.ModelElementIdToEObjectMapping; import org.eclipse.emf.emfstore.internal.common.model.ModelFactory; import org.eclipse.emf.emfstore.internal.common.model.util.ModelUtil; import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.AbstractOperation; import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.AttributeOperation; import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.CompositeOperation; import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.CreateDeleteOperation; import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.MultiReferenceMoveOperation; import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.MultiReferenceOperation; import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.ReferenceOperation; import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.SingleReferenceOperation; import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.UnkownFeatureException; import org.eclipse.emf.emfstore.internal.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 { private static final String ICON_MODIFY_OVERLAY = "icons/modify_overlay.png"; //$NON-NLS-1$ private static final String ICON_ADD_OVERLAY = "icons/add_overlay.png"; //$NON-NLS-1$ private static final String ICON_DELETE_OVERLAY = "icons/delete_overlay.png"; //$NON-NLS-1$ private static final String ICON_LINK_OVERLAY = "icons/link_overlay.png"; //$NON-NLS-1$ private final ModelElementIdToEObjectMapping idToEObjectMapping; private OperationCustomLabelProvider customLabelProvider; /** * Constructor. * * @param idToEObjectMapping * the ID to EObject mapping that is holding the EObjects that are going to be visualized * as part of the change packages */ public ChangePackageVisualizationHelper(ModelElementIdToEObjectMapping idToEObjectMapping) { this.idToEObjectMapping = idToEObjectMapping; } /** * 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) { final CreateDeleteOperation op = (CreateDeleteOperation) operation; if (op.isDelete()) { overlay = ICON_DELETE_OVERLAY; } else { overlay = ICON_ADD_OVERLAY; } } else if (operation instanceof AttributeOperation) { final AttributeOperation op = (AttributeOperation) operation; if (op.getNewValue() == null) { overlay = ICON_DELETE_OVERLAY; } else if (op.getOldValue() == null) { overlay = ICON_ADD_OVERLAY; } else { overlay = ICON_MODIFY_OVERLAY; } } else if (operation instanceof SingleReferenceOperation) { final SingleReferenceOperation op = (SingleReferenceOperation) operation; if (op.getNewValue() == null) { overlay = ICON_DELETE_OVERLAY; } else { overlay = ICON_LINK_OVERLAY; } } else if (operation instanceof MultiReferenceOperation) { final MultiReferenceOperation op = (MultiReferenceOperation) operation; if (op.getReferencedModelElements().size() > 0) { overlay = ICON_LINK_OVERLAY; } } else if (operation instanceof MultiReferenceMoveOperation) { overlay = ICON_LINK_OVERLAY; } else { overlay = ICON_MODIFY_OVERLAY; } final 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 final Image image = getCustomOperationProviderLabel(operation); if (image != null) { return image; } return emfProvider.getImage(operation); } private Image getCustomOperationProviderLabel(AbstractOperation operation) { final OperationCustomLabelProvider customLabelProvider = getLabelProvider(); if (customLabelProvider != null) { try { return (Image) customLabelProvider.getImage(operation); // BEGIN SUPRESS CATCH EXCEPTION } catch (final RuntimeException e) { // END SUPRESS CATCH EXCEPTION ModelUtil.logWarning(Messages.ChangePackageVisualizationHelper_CustomOperationProvider_LoadImageFailed, e); } finally { customLabelProvider.dispose(); } } 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) { if (op instanceof CompositeOperation) { final CompositeOperation compositeOperation = (CompositeOperation) op; // artificial composite because of opposite ref, take description of // main operation if (compositeOperation.getMainOperation() != null) { return getDescription(compositeOperation.getMainOperation()); } } // check of a custom operation label provider can provide a label final OperationCustomLabelProvider customLabelProvider = getLabelProvider(); String decorate; try { decorate = decorate(customLabelProvider, op); return decorate; } finally { customLabelProvider.dispose(); } } private OperationCustomLabelProvider getLabelProvider() { if (customLabelProvider == null) { customLabelProvider = ExtensionRegistry.INSTANCE.get( OperationCustomLabelProvider.ID, OperationCustomLabelProvider.class, new DefaultOperationLabelProvider(), true); } return customLabelProvider; } private String decorate(OperationCustomLabelProvider labelProvider, AbstractOperation op) { final String namesResolved = resolveIds(labelProvider, labelProvider.getDescription(op), AbstractOperationItemProvider.NAME_TAG__SEPARATOR, op); final String allResolved = resolveIds(labelProvider, namesResolved, AbstractOperationItemProvider.NAME_CLASS_TAG_SEPARATOR, op); if (op instanceof ReferenceOperation) { return resolveTypes(allResolved, (ReferenceOperation) op); } if (op instanceof CompositeOperation && ((CompositeOperation) op).getMainOperation() != null && ((CompositeOperation) op).getMainOperation() instanceof ReferenceOperation) { return resolveTypes(allResolved, (ReferenceOperation) ((CompositeOperation) op).getMainOperation()); } return allResolved; } private String resolveTypes(String unresolvedString, ReferenceOperation op) { final EObject modelElement = getModelElement(op.getModelElementId()); String type; if (modelElement == null) { type = "ModelElement"; //$NON-NLS-1$ } else { try { final EStructuralFeature feature = op.getFeature(modelElement); type = feature.getEType().getName(); } catch (final UnkownFeatureException e) { type = "ModelElement"; //$NON-NLS-1$ } } return unresolvedString.replace(AbstractOperationItemProvider.REFERENCE_TYPE_TAG_SEPARATOR, type); } private String resolveIds(OperationCustomLabelProvider labelProvider, String unresolvedString, String devider, AbstractOperation op) { final String[] strings = unresolvedString.split(devider); final StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < strings.length; i++) { if (isOdd(i)) { final ModelElementId modelElementId = ModelFactory.eINSTANCE.createModelElementId(); modelElementId.setId(strings[i]); final EObject modelElement = getModelElement(modelElementId); if (modelElement != null) { stringBuilder.append(labelProvider.getModelElementName(modelElement)); } else if (op instanceof CreateDeleteOperation) { final CreateDeleteOperation createDeleteOp = (CreateDeleteOperation) op; for (final 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(); } private boolean isOdd(int i) { final int res = i % 2; return res == -1 || res == 1; } /** * 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) { return idToEObjectMapping.get(modelElementId); } /** * */ public void dispose() { if (customLabelProvider != null) { customLabelProvider.dispose(); } } }