/***************************************************************************** * Copyright (c) 2009 CEA LIST. * * 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: * Remi Schnekenburger (CEA LIST) remi.schnekenburger@cea.fr - Initial API and implementation * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Adapted code from the class diagram *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.profile.custom.policies; import java.util.Collection; import java.util.List; import java.util.Map; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.ecore.EAnnotation; import org.eclipse.emf.ecore.EObject; import org.eclipse.gef.GraphicalEditPart; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.papyrus.infra.emf.appearance.helper.VisualInformationPapyrusConstants; import org.eclipse.papyrus.uml.diagram.common.editpolicies.AbstractMaskManagedEditPolicy; import org.eclipse.papyrus.uml.diagram.common.helper.OperationLabelHelper; import org.eclipse.papyrus.uml.diagram.profile.custom.preferences.IPapyrusOperationPreferencesConstant; import org.eclipse.papyrus.uml.diagram.profile.part.UMLDiagramEditorPlugin; import org.eclipse.papyrus.uml.tools.utils.ICustomAppearence; import org.eclipse.uml2.uml.Operation; import org.eclipse.uml2.uml.Parameter; import org.eclipse.uml2.uml.Type; import org.eclipse.uml2.uml.UMLPackage; /** * Specific edit policy for label displaying stereotypes and their properties for edges representing * UML elements. */ public class OperationLabelEditPolicy extends AbstractMaskManagedEditPolicy { /** * Creates a new PropertyLabelEditPolicy */ public OperationLabelEditPolicy() { super(); } /** * {@inheritDoc} */ @Override public void addAdditionalListeners() { super.addAdditionalListeners(); Operation operation = getUMLElement(); // check host semantic element is not null if(operation == null) { return; } // adds a listener to the element itself, and to linked elements, like Type for(Parameter parameter : operation.getOwnedParameters()) { getDiagramEventBroker().addNotificationListener(parameter, this); // should also add this element as a listener of parameter type if(parameter.getType() != null) { getDiagramEventBroker().addNotificationListener(parameter.getType(), this); } } } /** * {@inheritDoc} */ public int getCurrentDisplayValue() { EAnnotation customeDisplayAnnotation = ((View)getHost().getModel()).getEAnnotation(VisualInformationPapyrusConstants.CUSTOM_APPEARENCE_ANNOTATION); int displayValue = getDefaultDisplayValue(); if(customeDisplayAnnotation != null) { displayValue = Integer.parseInt(customeDisplayAnnotation.getDetails().get(VisualInformationPapyrusConstants.CUSTOM_APPEARANCE_MASK_VALUE)); } else { // no specific information => look in preferences IPreferenceStore store = UMLDiagramEditorPlugin.getInstance().getPreferenceStore(); int displayValueTemp = store.getInt(IPapyrusOperationPreferencesConstant.OPERATION_LABEL_DISPLAY_PREFERENCE); if(displayValueTemp != 0) { displayValue = displayValueTemp; } } return displayValue; } /** * {@inheritDoc} */ public int getDefaultDisplayValue() { return ICustomAppearence.DEFAULT_UML_OPERATION; } /** * {@inheritDoc} */ public String getMaskLabel(int value) { return OperationLabelHelper.getInstance().getMaskLabel(value); } /** * {@inheritDoc} */ public Collection<String> getMaskLabels() { return OperationLabelHelper.getInstance().getMaskLabels(); } /** * {@inheritDoc} */ public Map<Integer, String> getMasks() { return OperationLabelHelper.getInstance().getMasks(); } /** * {@inheritDoc} */ public Collection<Integer> getMaskValues() { return OperationLabelHelper.getInstance().getMaskValues(); } /** * {@inheritDoc} */ public String getPreferencePageID() { return "org.eclipse.papyrus.uml.diagram.profile.custom.preferences.OperationPreferencePage"; //$NON-NLS-1$ } /** * Returns the {@link Operation} managed by this edit part. * * @return the {@link Operation} managed by this edit part. */ @Override public Operation getUMLElement() { return (Operation)super.getUMLElement(); } /** * {@inheritedDoc} */ @Override public void notifyChanged(Notification notification) { super.notifyChanged(notification); // change the label of the figure managed by the host edit part (managed by the parent edit // part in general...) // it must be changed only if: // - the annotation corresponding to the display of the stereotype changes // - the stereotype application list has changed Object object = notification.getNotifier(); Operation operation = getUMLElement(); if(object == null) { return; } if(object.equals(operation)) { notifyOperationChanged(operation, notification); } else if(isParameter(object)) { notifyParameterChanged(notification); } else if(isParameterType(object)) { notifyParameterTypeChanged(notification); } if(isMaskManagedAnnotation(object)) { refreshDisplay(); } if(isRemovedMaskManagedLabelAnnotation(object, notification)) { refreshDisplay(); } } /** * Checks if the given object is one of the parameter type of the operation * * @param object * the object to test * @return <code>true</code> if the object corresponds to the type of a parameter of the * operation */ protected boolean isParameterType(Object object) { if(!(object instanceof Type)) { return false; } for(Parameter parameter : getUMLElement().getOwnedParameters()) { if(object.equals(parameter.getType())) { return true; } } return false; } /** * Checks if the given object is one of the parameter of the operation * * @param object * the object to test * @return <code>true</code> if the object is a parameter of the operation */ protected boolean isParameter(Object object) { if(!(object instanceof Parameter)) { return false; } return getUMLElement().getOwnedParameters().contains(object); } /** * notifies that a parameter of the operation has changed. * * @param parameter * the {@link Parameter} that has changed * @param notification * the notification send when the element has been changed */ protected void notifyParameterChanged(Notification notification) { switch(notification.getFeatureID(Parameter.class)) { case UMLPackage.PARAMETER__NAME: case UMLPackage.PARAMETER__DEFAULT_VALUE: case UMLPackage.PARAMETER__DIRECTION: case UMLPackage.PARAMETER__IS_STREAM: case UMLPackage.PARAMETER__IS_ORDERED: case UMLPackage.PARAMETER__LOWER: case UMLPackage.PARAMETER__UPPER: case UMLPackage.PARAMETER__LOWER_VALUE: case UMLPackage.PARAMETER__UPPER_VALUE: refreshDisplay(); break; case UMLPackage.PARAMETER__TYPE: switch(notification.getEventType()) { // if it is added => adds listener to the type element case Notification.ADD: getDiagramEventBroker().addNotificationListener((EObject)notification.getNewValue(), this); refreshDisplay(); // if it is removed => removes listener from the type element break; case Notification.ADD_MANY: // should never happen if(notification.getNewValue() instanceof List<?>) { List<?> addedElements = (List<?>)notification.getNewValue(); for(Object addedElement : addedElements) { if(addedElement instanceof EObject) { getDiagramEventBroker().addNotificationListener((EObject)addedElement, this); } } } refreshDisplay(); break; case Notification.REMOVE: getDiagramEventBroker().removeNotificationListener((EObject)notification.getOldValue(), this); refreshDisplay(); break; case Notification.REMOVE_MANY: // should never happen if(notification.getOldValue() instanceof List<?>) { List<?> removedElements = (List<?>)notification.getOldValue(); for(Object removedElement : removedElements) { if(removedElement instanceof EObject) { getDiagramEventBroker().removeNotificationListener((EObject)removedElement, this); } } } refreshDisplay(); break; // if it is set, remove the old one and adds the new one. this is the method use when // the type is set or removed... case Notification.SET: if(notification.getNewValue() != null) { getDiagramEventBroker().addNotificationListener((EObject)notification.getNewValue(), this); } if(notification.getOldValue() != null) { getDiagramEventBroker().removeNotificationListener((EObject)notification.getOldValue(), this); } refreshDisplay(); default: break; } break; default: // does nothing in other cases break; } } /** * notifies that a parameter of the operation has changed. * * @param parameter * the {@link Parameter} that has changed * @param notification * the notification send when the element has been changed */ protected void notifyParameterTypeChanged(Notification notification) { // should be type.class, but seems to be a bug if this is put instead. switch(notification.getFeatureID(notification.getNotifier().getClass())) { case UMLPackage.TYPE__NAME: case UMLPackage.TYPE__TEMPLATE_PARAMETER: case UMLPackage.TYPE__VISIBILITY: refreshDisplay(); break; default: // does nothing in other cases break; } } /** * notifies that the the property has changed. * * @param operation * the operation that has changed * @param notification * the notification send when the element has been changed */ protected void notifyOperationChanged(Operation operation, Notification notification) { switch(notification.getFeatureID(Operation.class)) { case UMLPackage.OPERATION__NAME: case UMLPackage.OPERATION__VISIBILITY: case UMLPackage.OPERATION__IS_UNIQUE: case UMLPackage.OPERATION__REDEFINED_OPERATION: case UMLPackage.OPERATION__IS_ORDERED: case UMLPackage.OPERATION__LOWER: case UMLPackage.OPERATION__UPPER: case UMLPackage.OPERATION__IS_STATIC: refreshDisplay(); break; case UMLPackage.OPERATION__OWNED_PARAMETER: switch(notification.getEventType()) { // if it is added => adds listener to the type element case Notification.ADD: getDiagramEventBroker().addNotificationListener((EObject)notification.getNewValue(), this); refreshDisplay(); // if it is removed => removes listener from the type element break; case Notification.ADD_MANY: // should never happen if(notification.getNewValue() instanceof List<?>) { List<?> addedElements = (List<?>)notification.getNewValue(); for(Object addedElement : addedElements) { if(addedElement instanceof EObject) { getDiagramEventBroker().addNotificationListener((EObject)addedElement, this); } } } refreshDisplay(); break; case Notification.REMOVE: getDiagramEventBroker().removeNotificationListener((EObject)notification.getOldValue(), this); refreshDisplay(); break; case Notification.REMOVE_MANY: // should never happen if(notification.getOldValue() instanceof List<?>) { List<?> removedElements = (List<?>)notification.getOldValue(); for(Object removedElement : removedElements) { if(removedElement instanceof EObject) { getDiagramEventBroker().removeNotificationListener((EObject)removedElement, this); } } } refreshDisplay(); break; // if it is set, remove the old one and adds the new one. this is the method use when // the type is set or removed... case Notification.SET: if(notification.getNewValue() != null) { getDiagramEventBroker().addNotificationListener((EObject)notification.getNewValue(), this); } if(notification.getOldValue() != null) { getDiagramEventBroker().removeNotificationListener((EObject)notification.getOldValue(), this); } refreshDisplay(); default: break; } break; default: // does nothing in other cases break; } } /** * Refreshes the display of the edit part */ @Override public void refreshDisplay() { // calls the helper for this edit Part OperationLabelHelper.getInstance().refreshEditPartDisplay((GraphicalEditPart)getHost()); } /** * {@inheritDoc} */ @Override protected void removeAdditionalListeners() { super.removeAdditionalListeners(); Operation operation = getUMLElement(); // check host semantic element is not null if(operation == null) { return; } for(Parameter parameter : operation.getOwnedParameters()) { getDiagramEventBroker().removeNotificationListener(parameter, this); // remove parameter type listener if(parameter.getType() != null) { getDiagramEventBroker().removeNotificationListener(parameter.getType(), this); } } } }