package org.eclipse.papyrus.uml.diagram.sequence.edit.policies;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.core.listener.NotificationListener;
import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
import org.eclipse.gmf.runtime.diagram.ui.editparts.LabelEditPart;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.papyrus.infra.core.services.ServiceException;
import org.eclipse.papyrus.infra.core.utils.ServiceUtilsForActionHandlers;
import org.eclipse.papyrus.infra.emf.appearance.helper.VisualInformationPapyrusConstants;
import org.eclipse.papyrus.infra.gmfdiag.common.editpolicies.IMaskManagedLabelEditPolicy;
import org.eclipse.papyrus.uml.diagram.common.editpolicies.AbstractMaskManagedEditPolicy;
import org.eclipse.papyrus.uml.diagram.common.helper.StereotypedElementLabelHelper;
import org.eclipse.papyrus.uml.diagram.sequence.part.UMLDiagramEditorPlugin;
import org.eclipse.papyrus.uml.diagram.sequence.preferences.MessagePreferencePage;
import org.eclipse.papyrus.uml.diagram.sequence.util.CommandHelper;
import org.eclipse.papyrus.uml.tools.utils.ICustomAppearence;
import org.eclipse.papyrus.uml.tools.utils.MultiplicityElementUtil;
import org.eclipse.papyrus.uml.tools.utils.NamedElementUtil;
import org.eclipse.papyrus.uml.tools.utils.ParameterUtil;
import org.eclipse.papyrus.uml.tools.utils.PropertyUtil;
import org.eclipse.papyrus.uml.tools.utils.TypeUtil;
import org.eclipse.papyrus.uml.tools.utils.TypedElementUtil;
import org.eclipse.papyrus.uml.tools.utils.ValueSpecificationUtil;
import org.eclipse.uml2.uml.Constraint;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Message;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Operation;
import org.eclipse.uml2.uml.Parameter;
import org.eclipse.uml2.uml.ParameterDirectionKind;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Signal;
import org.eclipse.uml2.uml.Type;
import org.eclipse.uml2.uml.UMLPackage;
import org.eclipse.uml2.uml.ValueSpecification;
public class MessageLabelEditPolicy extends AbstractMaskManagedEditPolicy {
public static interface ICustomMessageLabel{
}
private DefaultValueListener defaultValueListener;
/**
* Refreshes the display of the edit part
*/
@Override
public void refreshDisplay() {
// calls the helper for this edit Part
ConnectionEditPart lp = (ConnectionEditPart)getHost();
List children = lp.getChildren();
for(Object p : children)
if(p instanceof ICustomMessageLabel){
MessageLabelHelper.getInstance().refreshEditPartDisplay((GraphicalEditPart)p);
}
}
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(MessagePreferencePage.LABEL_DISPLAY_PREFERENCE);
if(displayValueTemp != 0) {
displayValue = displayValueTemp;
}
}
return displayValue;
}
public int getDefaultDisplayValue() {
return MessagePreferencePage.DEFAULT_LABEL_DISPLAY;
}
public String getMaskLabel(int value) {
return MessageLabelHelper.getInstance().getMaskLabel(value);
}
public Collection<String> getMaskLabels() {
return MessageLabelHelper.getInstance().getMaskLabels();
}
public Map<Integer, String> getMasks() {
return MessageLabelHelper.getInstance().getMasks();
}
public Collection<Integer> getMaskValues() {
return MessageLabelHelper.getInstance().getMaskValues();
}
public String getPreferencePageID() {
return "org.eclipse.papyrus.uml.diagram.sequence.preferences.MessagePreferencePage";
}
@Override
public Message getUMLElement() {
if(hostSemanticElement instanceof Message)
return ((Message)hostSemanticElement);
return null;
}
@Override
public void addAdditionalListeners() {
super.addAdditionalListeners();
this.defaultValueListener = new DefaultValueListener();
Message e = getUMLElement();
// check host semantic element is not null
if(e == null || e.getSignature() == null) {
return;
}
NamedElement sig = e.getSignature();
if(sig instanceof Operation){
Operation operation = (Operation)sig;
getDiagramEventBroker().addNotificationListener(operation, this);
// adds a listener to the element itself, and to linked elements, like Type
for(Parameter parameter : operation.getOwnedParameters()) {
getDiagramEventBroker().addNotificationListener(parameter, this);
getDiagramEventBroker().addNotificationListener(parameter.getDefaultValue(), defaultValueListener);
// should also add this element as a listener of parameter type
getDiagramEventBroker().addNotificationListener(parameter.getType(), this);
}
}else if(sig instanceof Signal){
Signal signal = (Signal)sig;
getDiagramEventBroker().addNotificationListener(signal, this);
for(Property property : signal.getOwnedAttributes()) {
getDiagramEventBroker().addNotificationListener(property, this);
getDiagramEventBroker().addNotificationListener(property.getDefaultValue(), defaultValueListener);
// should also add this element as a listener of parameter type
getDiagramEventBroker().addNotificationListener(property.getType(), this);
}
}
EList<ValueSpecification> argments = e.getArguments();
for(ValueSpecification v : argments)
if(v instanceof EObject) {
getDiagramEventBroker().addNotificationListener((EObject)v, this);
}
}
@Override
protected void removeAdditionalListeners() {
super.removeAdditionalListeners();
Message e = getUMLElement();
// check host semantic element is not null
if(e == null || e.getSignature() == null) {
return;
}
NamedElement sig = e.getSignature();
if(sig instanceof Operation){
Operation operation = (Operation)sig;
getDiagramEventBroker().removeNotificationListener(operation, this);
for(Parameter parameter : operation.getOwnedParameters()) {
getDiagramEventBroker().removeNotificationListener(parameter, this);
getDiagramEventBroker().removeNotificationListener(parameter.getDefaultValue(), defaultValueListener);
// remove parameter type listener
getDiagramEventBroker().removeNotificationListener(parameter.getType(), this);
}
}else if(sig instanceof Signal){
Signal signal = (Signal)sig;
getDiagramEventBroker().removeNotificationListener(signal, this);
for(Property property : signal.getOwnedAttributes()) {
getDiagramEventBroker().removeNotificationListener(property, this);
getDiagramEventBroker().removeNotificationListener(property.getDefaultValue(), defaultValueListener);
// remove parameter type listener
getDiagramEventBroker().removeNotificationListener(property.getType(), this);
}
}
EList<ValueSpecification> argments = e.getArguments();
for(ValueSpecification v : argments)
if(v instanceof EObject) {
getDiagramEventBroker().removeNotificationListener((EObject)v, this);
}
}
@Override
public void notifyChanged(Notification notification) {
super.notifyChanged(notification);
final Object object = notification.getNotifier();
Message e = getUMLElement();
/* apex improved start */
if (e == null) {
return;
}
/* apex improved end */
/* apex replaced
// check host semantic element is not null
if(e == null || e.getSignature() == null) {
return;
}
*/
/* apex added start */
if (UMLPackage.eINSTANCE.getNamedElement_Name().equals(notification.getFeature())) {
refreshDisplay();
} else if (UMLPackage.eINSTANCE.getMessage_Signature().equals(notification.getFeature())) {
if (notification.getNewValue() instanceof NamedElement) {
NamedElement ne = (NamedElement)notification.getNewValue();
getDiagramEventBroker().addNotificationListener(ne, this);
}
if (notification.getOldValue() instanceof NamedElement) {
NamedElement ne = (NamedElement)notification.getOldValue();
getDiagramEventBroker().removeNotificationListener(ne, this);
}
refreshDisplay();
}
/* apex added end */
if(UMLPackage.Literals.MESSAGE__ARGUMENT.equals( notification.getFeature())){
parameterListChange(notification);
return;
}else if(e.getArguments().contains(object)){
refreshDisplay();
return;
}
NamedElement sig = e.getSignature();
if(sig instanceof Operation){
Operation operation = (Operation)sig;
if(object.equals(operation)) {
notifyOperationChanged(operation, notification);
} else if(isParameter(object, operation)) {
notifyParameterChanged(notification);
} else if(isParameterType(object, operation)) {
notifyTypeChanged(notification);
}
}else if(sig instanceof Signal){
Signal signal = (Signal)sig;
if(object.equals(signal)) {
notifySignalChanged(signal, notification);
}else if(isProperty(object, signal)) {
notifyPropertyChanged(notification);
}else if(isPropertyType(object, signal)) {
notifyTypeChanged(notification);
}else if(object instanceof ValueSpecification){
Element own = ((ValueSpecification)object).getOwner();
if(isProperty(own, signal)){
refreshDisplay(); // may be default value
}
}
}
if(isMaskManagedAnnotation(object) ){
refreshDisplay();
}else if(isRemovedMaskManagedLabelAnnotation(object, notification)) {
refreshDisplay();
}
}
class DefaultValueListener implements NotificationListener{
public void notifyChanged(Notification notification) {
refreshDisplay();
}
}
private void notifyPropertyChanged(Notification notification) {
switch(notification.getFeatureID(Property.class)) {
case UMLPackage.PROPERTY__DEFAULT_VALUE: // set or unset default value
if(notification.getOldValue() instanceof EObject)
getDiagramEventBroker().removeNotificationListener((EObject)notification.getOldValue(), defaultValueListener);
if(notification.getNewValue() instanceof EObject)
getDiagramEventBroker().addNotificationListener((EObject)notification.getNewValue(), defaultValueListener);
refreshDisplay();
break;
case UMLPackage.PROPERTY__NAME:
case UMLPackage.PROPERTY__IS_ORDERED:
case UMLPackage.PROPERTY__LOWER:
case UMLPackage.PROPERTY__UPPER:
case UMLPackage.PROPERTY__LOWER_VALUE:
case UMLPackage.PROPERTY__UPPER_VALUE:
refreshDisplay();
break;
case UMLPackage.PROPERTY__TYPE:
parameterListChange(notification);
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 notifyParameterChanged(Notification notification) {
switch(notification.getFeatureID(Parameter.class)) {
case UMLPackage.PARAMETER__DEFAULT_VALUE:
if(notification.getOldValue() instanceof EObject)
getDiagramEventBroker().removeNotificationListener((EObject)notification.getOldValue(), defaultValueListener);
if(notification.getNewValue() instanceof EObject)
getDiagramEventBroker().addNotificationListener((EObject)notification.getNewValue(), defaultValueListener);
refreshDisplay();
break;
case UMLPackage.PARAMETER__NAME:
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:
parameterListChange(notification);
break;
default:
// does nothing in other cases
break;
}
}
protected void parameterListChange(Notification notification) {
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:
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:
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;
}
}
/**
* 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 notifyTypeChanged(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:
parameterListChange(notification);
break;
default:
// does nothing in other cases
break;
}
}
private void notifySignalChanged(Signal signal, Notification notification) {
switch(notification.getFeatureID(Signal.class)) {
case UMLPackage.SIGNAL__NAME:
case UMLPackage.SIGNAL__VISIBILITY:
refreshDisplay();
break;
case UMLPackage.SIGNAL__OWNED_ATTRIBUTE:
parameterListChange(notification);
break;
default:
// does nothing in other cases
break;
}
}
/**
* Checks if the given object is one of the parameter type of the operation
*
* @param object
* the object to test
* @param operation
* @return <code>true</code> if the object corresponds to the type of a parameter of the
* operation
*/
protected boolean isParameterType(Object object, Operation operation) {
if(!(object instanceof Type)) {
return false;
}
for(Parameter parameter : operation.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
* @param operation
* @return <code>true</code> if the object is a parameter of the operation
*/
protected boolean isParameter(Object object, Operation operation) {
if(!(object instanceof Parameter)) {
return false;
}
return operation.getOwnedParameters().contains(object);
}
private boolean isPropertyType(Object object, Signal signal) {
if(!(object instanceof Type)) {
return false;
}
for(Property property :signal.getOwnedAttributes()) {
if(object.equals(property.getType())) {
return true;
}
}
return false;
}
private boolean isProperty(Object object, Signal signal) {
if(!(object instanceof Property)) {
return false;
}
return signal.getOwnedAttributes().contains(object);
}
static class MessageLabelHelper extends StereotypedElementLabelHelper{
/**
* singelton instance
*/
private static MessageLabelHelper labelHelper;
/** Map for masks */
protected final Map<Integer, String> masks = new HashMap<Integer, String>(11);
protected MessageLabelHelper() {
// initialize the map
masks.put(ICustomAppearence.DISP_VISIBILITY, "Visibility");
masks.put(ICustomAppearence.DISP_NAME, "Name");
masks.put(ICustomAppearence.DISP_PARAMETER_NAME, "Parameters Name");
masks.put(ICustomAppearence.DISP_PARAMETER_DIRECTION, "Parameters Direction");
masks.put(ICustomAppearence.DISP_PARAMETER_TYPE, "Parameters Type");
masks.put(ICustomAppearence.DISP_RT_TYPE, "Return Type");
masks.put(ICustomAppearence.DISP_PARAMETER_MULTIPLICITY, "Parameters Multiplicity");
masks.put(ICustomAppearence.DISP_PARAMETER_DEFAULT, "Parameters Default Value");
masks.put(ICustomAppearence.DISP_DERIVE, "Parameters Value");
masks.put(ICustomAppearence.DISP_PARAMETER_MODIFIERS, "Parameters Modifiers");
masks.put(ICustomAppearence.DISP_MOFIFIERS, "Modifiers");
}
/**
* Returns the singleton instance of this class
*
* @return the singleton instance.
*/
public static MessageLabelHelper getInstance() {
if(labelHelper == null) {
labelHelper = new MessageLabelHelper();
}
return labelHelper;
}
public Message getUMLElement(GraphicalEditPart editPart) {
EObject e = ((View)editPart.getModel()).getElement();
if(e instanceof Message)
return ((Message)e);
return null;
}
protected String elementLabel(GraphicalEditPart editPart) {
if(editPart instanceof LabelEditPart)
editPart = (GraphicalEditPart)editPart.getParent();
int displayValue = MessagePreferencePage.DEFAULT_LABEL_DISPLAY;
IMaskManagedLabelEditPolicy policy = (IMaskManagedLabelEditPolicy)editPart.getEditPolicy(IMaskManagedLabelEditPolicy.MASK_MANAGED_LABEL_EDIT_POLICY);
if(policy != null) {
displayValue = policy.getCurrentDisplayValue();
}
Message e = getUMLElement(editPart);
NamedElement signature = e.getSignature();
if(signature instanceof Operation) {
return OperationUtil.getCustomLabel(e, (Operation)signature, displayValue);
}else if(signature instanceof Signal) {
return SignalUtil.getCustomLabel(e, (Signal)signature, displayValue);
} else if(signature != null) {
return signature.getName();
}
return e.getName();
}
public String getMaskLabel(int value) {
return masks.get(value);
}
public Collection<String> getMaskLabels() {
return masks.values();
}
public Map<Integer, String> getMasks() {
return masks;
}
public Set<Integer> getMaskValues() {
return masks.keySet();
}
}
static public class SignalUtil {
private static String getCustomPropertyLabel(Message e, Property property, int style) {
StringBuffer buffer = new StringBuffer();
// visibility
buffer.append(" ");
if((style & ICustomAppearence.DISP_VISIBILITY) != 0) {
buffer.append(NamedElementUtil.getVisibilityAsSign(property));
}
// derived property
if((style & ICustomAppearence.DISP_DERIVE) != 0) {
if(property.isDerived()) {
buffer.append("/");
}
}
// name
if((style & ICustomAppearence.DISP_PARAMETER_NAME) != 0) {
buffer.append(" ");
buffer.append(property.getName());
}
if((style & ICustomAppearence.DISP_PARAMETER_TYPE) != 0) {
// type
if(property.getType() != null) {
buffer.append(": " + property.getType().getName());
} else {
buffer.append(": " + TypeUtil.UNDEFINED_TYPE_NAME);
}
}
if((style & ICustomAppearence.DISP_MULTIPLICITY) != 0) {
// multiplicity -> do not display [1]
String multiplicity = MultiplicityElementUtil.getMultiplicityAsString(property);
buffer.append(multiplicity);
}
if((style & ICustomAppearence.DISP_DERIVE) != 0) {
String value = getValue(e, property);
if(value != null){
if((style & ICustomAppearence.DISP_PARAMETER_NAME) != 0 || (style & ICustomAppearence.DISP_PARAMETER_TYPE) != 0)
buffer.append(" = ");
buffer.append(value);
}
}else if((style & ICustomAppearence.DISP_PARAMETER_DEFAULT) != 0) {
// default value
if(property.getDefault() != null) {
if((style & ICustomAppearence.DISP_PARAMETER_NAME) != 0 || (style & ICustomAppearence.DISP_PARAMETER_TYPE) != 0)
buffer.append(" = ");
buffer.append(property.getDefault());
}
}
if((style & ICustomAppearence.DISP_MOFIFIERS) != 0) {
boolean multiLine = ((style & ICustomAppearence.DISP_MULTI_LINE) != 0);
// property modifiers
String modifiers = PropertyUtil.getModifiersAsString(property, multiLine);
if(!modifiers.equals("")) {
if(multiLine) {
buffer.append("\n");
}
if (!buffer.toString().endsWith(" ")){
buffer.append(" ");
}
buffer.append(modifiers);
}
}
return buffer.toString();
}
private static String getValue(Message e, Property property) {
EList<ValueSpecification> arguments = e.getArguments();
for(ValueSpecification v : arguments)
if(v.getName().equals(property.getName())){
return ValueSpecificationUtil.getSpecificationValue(v);
}
return null;
}
/**
* return the custom label of the signal, given UML2 specification and a custom style.
* @param e
*
* @param style
* the integer representing the style of the label
*
* @return the string corresponding to the label of the signal
*/
public static String getCustomLabel(Message e, Signal signal, int style) {
StringBuffer buffer = new StringBuffer();
buffer.append(" "); // adds " " first for correct display considerations
// visibility
if((style & ICustomAppearence.DISP_VISIBILITY) != 0) {
buffer.append(NamedElementUtil.getVisibilityAsSign(signal));
}
// name
if((style & ICustomAppearence.DISP_NAME) != 0) {
buffer.append(" ");
buffer.append(signal.getName());
}
//
// parameters : '(' parameter-list ')'
buffer.append("(");
buffer.append(getPropertiesAsString(e, signal, style));
buffer.append(")");
return buffer.toString();
}
/**
* Returns signal properties as a string, the label is customized using a bit mask
*
* @return a string containing all properties separated by commas
*/
private static String getPropertiesAsString(Message e, Signal signal, int style) {
StringBuffer propertiesString = new StringBuffer();
boolean firstProperty = true;
for(Property property : signal.getOwnedAttributes()) {
// get the label for this property
String propertyString = getCustomPropertyLabel(e, property, style);
if(!propertyString.trim().equals("")) {
if(!firstProperty) {
propertiesString.append(", ");
}
propertiesString.append(propertyString);
firstProperty = false;
}
}
return propertiesString.toString();
}
}
static class OperationUtil {
public static String getCustomLabel(Message e, Parameter parameter, int style) {
StringBuffer buffer = new StringBuffer();
// visibility
buffer.append(" ");
if((style & ICustomAppearence.DISP_VISIBILITY) != 0) {
buffer.append(NamedElementUtil.getVisibilityAsSign(parameter));
}
// direction property
if((style & ICustomAppearence.DISP_PARAMETER_DIRECTION) != 0) {
buffer.append(" ");
buffer.append(parameter.getDirection().getLiteral());
}
// name
if((style & ICustomAppearence.DISP_PARAMETER_NAME) != 0) {
buffer.append(" ");
buffer.append(parameter.getName());
}
if((style & ICustomAppearence.DISP_PARAMETER_TYPE) != 0) {
// type
if(parameter.getType() != null) {
buffer.append(": " + parameter.getType().getName());
} else {
buffer.append(": " + TypeUtil.UNDEFINED_TYPE_NAME);
}
}
if((style & ICustomAppearence.DISP_PARAMETER_MULTIPLICITY) != 0) {
// multiplicity -> do not display [1]
String multiplicity = MultiplicityElementUtil.getMultiplicityAsString(parameter);
buffer.append(multiplicity);
}
if((style & ICustomAppearence.DISP_DERIVE) != 0) {
String value = getValue(e, parameter);
if(value != null){
if((style & ICustomAppearence.DISP_PARAMETER_NAME) != 0 || (style & ICustomAppearence.DISP_PARAMETER_TYPE) != 0)
buffer.append(" = ");
buffer.append(value);
}
}else if((style & ICustomAppearence.DISP_PARAMETER_DEFAULT) != 0) {
// default value
if(parameter.getDefault() != null) {
if((style & ICustomAppearence.DISP_PARAMETER_NAME) != 0 || (style & ICustomAppearence.DISP_PARAMETER_TYPE) != 0)
buffer.append(" = ");
buffer.append(parameter.getDefault());
}
}
if((style & ICustomAppearence.DISP_MOFIFIERS) != 0) {
boolean multiLine = ((style & ICustomAppearence.DISP_MULTI_LINE) != 0);
// property modifiers
String modifiers = ParameterUtil.getModifiersAsString(parameter, multiLine);
if(!modifiers.equals("")) {
if(multiLine) {
buffer.append("\n");
}
buffer.append(modifiers);
}
}
return buffer.toString();
}
private static String getValue(Message e, Parameter parameter) {
EList<ValueSpecification> arguments = e.getArguments();
for(ValueSpecification v : arguments)
if(v.getName().equals(parameter.getName())){
return ValueSpecificationUtil.getSpecificationValue(v);
}
return null;
}
public static String getCustomLabel(Message e, Operation operation, int style) {
StringBuffer buffer = new StringBuffer();
buffer.append(" "); // adds " " first for correct display considerations
// visibility
if((style & ICustomAppearence.DISP_VISIBILITY) != 0) {
buffer.append(NamedElementUtil.getVisibilityAsSign(operation));
}
// name
if((style & ICustomAppearence.DISP_NAME) != 0) {
buffer.append(" ");
buffer.append(operation.getName());
}
//
// parameters : '(' parameter-list ')'
buffer.append("(");
buffer.append(getParametersAsString(e, operation, style));
buffer.append(")");
// return type
if((style & ICustomAppearence.DISP_RT_TYPE) != 0) {
buffer.append(getReturnTypeAsString(operation, style));
}
// modifiers
if((style & ICustomAppearence.DISP_MOFIFIERS) != 0) {
String modifiers = getModifiersAsString(operation);
if(!modifiers.equals("")) {
buffer.append("{");
buffer.append(modifiers);
buffer.append("}");
}
}
return buffer.toString();
}
/**
* Returns operation modifiers as string, separated with comma.
*
* @return a string containing the modifiers
*/
private static String getModifiersAsString(Operation operation) {
StringBuffer buffer = new StringBuffer();
boolean needsComma = false;
// Return parameter modifiers
Parameter returnParameter = OperationUtil.getReturnParameter(operation);
if(returnParameter != null) {
// non unique parameter
if(!returnParameter.isUnique()) {
buffer.append("nonunique");
needsComma = true;
}
// return parameter has ordered values
if(returnParameter.isOrdered()) {
if(needsComma) {
buffer.append(", ");
}
buffer.append("ordered");
needsComma = true;
}
}
// is the operation a query ?
if(operation.isQuery()) {
if(needsComma) {
buffer.append(", ");
}
buffer.append("query");
needsComma = true;
}
// is the operation redefining another operation ?
Iterator<Operation> it = operation.getRedefinedOperations().iterator();
while(it.hasNext()) {
Operation currentOperation = it.next();
if(needsComma) {
buffer.append(", ");
}
buffer.append("redefines ");
buffer.append(currentOperation.getName());
needsComma = true;
}
// has the operation a constraint ?
Iterator<Constraint> it2 = operation.getOwnedRules().iterator();
while(it2.hasNext()) {
Constraint constraint = it2.next();
if(needsComma) {
buffer.append(", ");
}
if(constraint.getSpecification() != null) {
buffer.append(constraint.getSpecification().stringValue());
}
needsComma = true;
}
return buffer.toString();
}
/**
* Returns return parameter label as a string, string parametrized with a style mask.
*
* @param style
* the mask that indicates which element to display
* @return a string containing the return parameter type
*/
private static String getReturnTypeAsString(Operation operation, int style) {
boolean displayType = ((style & ICustomAppearence.DISP_RT_TYPE) != 0);
boolean displayMultiplicity = ((style & ICustomAppearence.DISP_RT_MULTIPLICITY) != 0);
StringBuffer label = new StringBuffer("");
// Retrieve the return parameter (assume to be unique if defined)
Parameter returnParameter = getReturnParameter(operation);
// Create the string for the return type
if(returnParameter == null) {
// no-operation: label = ""
} else if(!displayType && !displayMultiplicity) {
// no-operation: label = ""
} else {
label.append(": ");
if(displayType) {
label.append(TypedElementUtil.getTypeAsString(returnParameter));
}
if(displayMultiplicity) {
label.append(MultiplicityElementUtil.getMultiplicityAsString(returnParameter));
}
}
return label.toString();
}
/**
* Gives the return parameter for this operation, or <code>null</code> if none exists.
*
* @return the return parameter of the operation or <code>null</code>
*/
private static Parameter getReturnParameter(Operation operation) {
// Retrieve the return parameter (assume to be unique if defined)
Parameter returnParameter = null;
Iterator<Parameter> it = operation.getOwnedParameters().iterator();
while((returnParameter == null) && (it.hasNext())) {
Parameter parameter = it.next();
if(parameter.getDirection().equals(ParameterDirectionKind.RETURN_LITERAL)) {
returnParameter = parameter;
}
}
return returnParameter;
}
/**
* Returns operation parameters as a string, the label is customized using a bit mask
* @param e
*
* @return a string containing all parameters separated by commas
*/
private static String getParametersAsString(Message e, Operation operation, int style) {
StringBuffer paramString = new StringBuffer();
Iterator<Parameter> paramIterator = operation.getOwnedParameters().iterator();
boolean firstParameter = true;
while(paramIterator.hasNext()) {
Parameter parameter = paramIterator.next();
// Do not include return parameters
if(!parameter.getDirection().equals(ParameterDirectionKind.RETURN_LITERAL)) {
// get the label for this parameter
String parameterString = getCustomLabel(e, parameter, style);
if (!parameterString.trim().equals("")) {
if (!firstParameter) {
paramString.append(", ");
}
paramString.append(parameterString);
firstParameter = false;
}
}
}
return paramString.toString();
}
}
}