package org.eclipse.uml2.diagram.clazz.action;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.gef.commands.UnexecutableCommand;
import org.eclipse.gmf.runtime.diagram.core.commands.DeleteCommand;
import org.eclipse.gmf.runtime.diagram.ui.actions.DiagramAction;
import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand;
import org.eclipse.gmf.runtime.emf.type.core.commands.CreateRelationshipCommand;
import org.eclipse.gmf.runtime.emf.type.core.commands.SetValueCommand;
import org.eclipse.gmf.runtime.emf.type.core.requests.CreateRelationshipRequest;
import org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.uml2.diagram.clazz.edit.commands.CreateAssociationViewCommand;
import org.eclipse.uml2.diagram.clazz.edit.parts.Property2EditPart;
import org.eclipse.uml2.diagram.clazz.edit.parts.Property3EditPart;
import org.eclipse.uml2.diagram.clazz.edit.parts.Property4EditPart;
import org.eclipse.uml2.diagram.clazz.edit.parts.Property5EditPart;
import org.eclipse.uml2.diagram.clazz.edit.parts.Property6EditPart;
import org.eclipse.uml2.diagram.clazz.edit.parts.Property7EditPart;
import org.eclipse.uml2.diagram.clazz.edit.parts.PropertyEditPart;
import org.eclipse.uml2.diagram.clazz.part.CustomMessages;
import org.eclipse.uml2.diagram.clazz.providers.UMLElementTypes;
import org.eclipse.uml2.uml.AggregationKind;
import org.eclipse.uml2.uml.Association;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Type;
import org.eclipse.uml2.uml.UMLPackage;
public class CreateAssociationFromProperty extends DiagramAction {
private static final String DISABLED_TEXT = CustomMessages.CreateAssociationFromProperty_disabled_text;
private final Property myOtherEnd;
public CreateAssociationFromProperty(IWorkbenchPage workbenchPage, Property sourceEnd) {
super(workbenchPage);
myOtherEnd = sourceEnd;
}
@Override
public void refresh() {
super.refresh();
updateText();
}
public CreateAssociationFromProperty(IWorkbenchPage workbenchPage) {
this(workbenchPage, null);
}
private void updateText() {
setText(DISABLED_TEXT);
if (myOtherEnd != null) {
String labelFormat = "{0}: {1}"; //$NON-NLS-1$
setText(NLS.bind(labelFormat, new Object[] { myOtherEnd.getClass_().getName(), myOtherEnd.getName() }));
return;
}
GraphicalEditPart propertyEditPart = getSelectedPropertyEditPart();
if (propertyEditPart != null) {
Property property = (Property) propertyEditPart.getNotationView().getElement();
if (property.getType() != null) {
setText(property.getType().getName());
}
}
}
@Override
protected Command getCommand() {
GraphicalEditPart propertyEditPart = getSelectedPropertyEditPart();
if (propertyEditPart == null) {
return UnexecutableCommand.INSTANCE;
}
GraphicalEditPart conjugatedEditPart = null;
if (myOtherEnd != null) {
conjugatedEditPart = (GraphicalEditPart) propertyEditPart.findEditPart(propertyEditPart.getRoot().getContents(), myOtherEnd);
}
TransactionalEditingDomain domain = propertyEditPart.getEditingDomain();
CompositeTransactionalCommand emfCommand = new CompositeTransactionalCommand(domain, CustomMessages.CreateAssociationFromProperty_create_association_command);
Property property = (Property) propertyEditPart.getNotationView().getElement();
Type associationSource = property.getClass_();
Type associationTarget = property.getType();
CreateRelationshipRequest semanticRequest = new CreateRelationshipRequest(associationSource, associationTarget, UMLElementTypes.Association_4005);
emfCommand.add(new CreateAssociationCommand(semanticRequest, myOtherEnd, property));
if (myOtherEnd != null && AggregationKind.COMPOSITE_LITERAL == property.getAggregation()) {
SetRequest fixOtherEndAggregation = new SetRequest(propertyEditPart.getEditingDomain(), //
myOtherEnd, UMLPackage.eINSTANCE.getProperty_Aggregation(), AggregationKind.NONE_LITERAL);
emfCommand.add(new SetValueCommand(fixOtherEndAggregation));
}
emfCommand.add(new DeleteCommand(propertyEditPart.getNotationView()));
if (conjugatedEditPart != null) {
emfCommand.add(new DeleteCommand(conjugatedEditPart.getNotationView()));
}
//first semantic changes in single transaction, then notation changes
CompoundCommand result = new CompoundCommand();
result.add(new ICommandProxy(emfCommand));
if (((GraphicalEditPart) propertyEditPart.getParent()).isCanonical()) {
result.add(new CreateAssociationViewCommand(propertyEditPart, associationSource, associationTarget, semanticRequest, getPreferencesHint()));
}
return result;
}
@Override
protected Request createTargetRequest() {
return null;
}
@Override
protected boolean isSelectionListener() {
return true;
}
@Override
public boolean isEnabled() {
// superclass realization is too heavy-weight in the simpliest cases
GraphicalEditPart propertyEditPart = getSelectedPropertyEditPart();
if (propertyEditPart == null) {
return false;
}
Property property = (Property) propertyEditPart.getNotationView().getElement();
Type associationTarget = property.getType();
if (associationTarget == null) {
return false;
}
return super.isEnabled();
}
private static class CreateAssociationCommand extends CreateRelationshipCommand {
private final Property myTargetEnd;
private Property mySourceEnd;
public CreateAssociationCommand(CreateRelationshipRequest request, Property sourceEnd, Property targetEnd) {
super(request);
mySourceEnd = sourceEnd;
myTargetEnd = targetEnd;
}
@Override
protected EObject doDefaultElementCreation() {
Type sourceType = (Type) getSource();
Package pakkage = sourceType.getNearestPackage();
Association association = (Association) pakkage.createOwnedType(null, UMLPackage.Literals.ASSOCIATION);
if (mySourceEnd == null) {
mySourceEnd = association.createOwnedEnd(null, sourceType);
}
association.getMemberEnds().add(mySourceEnd);
association.getMemberEnds().add(myTargetEnd);
return association;
}
}
private GraphicalEditPart getSelectedPropertyEditPart() {
for (Object next : getSelectedObjects()) {
if (oursPropertyEditParts.contains(next.getClass())) {
return (GraphicalEditPart) next;
}
}
return null;
}
private static final List<Class<?>> oursPropertyEditParts = new ArrayList<Class<?>>();
static {
oursPropertyEditParts.add(PropertyEditPart.class);
oursPropertyEditParts.add(Property2EditPart.class);
oursPropertyEditParts.add(Property3EditPart.class);
oursPropertyEditParts.add(Property4EditPart.class);
oursPropertyEditParts.add(Property5EditPart.class);
oursPropertyEditParts.add(Property6EditPart.class);
oursPropertyEditParts.add(Property7EditPart.class);
}
}