/***************************************************************************** * 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: * Patrick Tessier (CEA LIST) Patrick.tessier@cea.fr - Initial API and implementation * *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.clazz.custom.helper; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.draw2d.geometry.Point; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.gef.EditPart; import org.eclipse.gef.EditPartViewer; import org.eclipse.gef.commands.Command; import org.eclipse.gef.commands.UnexecutableCommand; import org.eclipse.gmf.runtime.common.core.command.CompositeCommand; import org.eclipse.gmf.runtime.common.core.command.ICommand; import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint; import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil; import org.eclipse.gmf.runtime.diagram.ui.commands.CreateCommand; import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy; import org.eclipse.gmf.runtime.diagram.ui.commands.SetBoundsCommand; import org.eclipse.gmf.runtime.diagram.ui.editparts.CompartmentEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewAndElementRequest; import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewRequest.ConnectionViewDescriptor; import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest.ViewDescriptor; import org.eclipse.gmf.runtime.diagram.ui.util.INotationType; import org.eclipse.gmf.runtime.emf.core.util.EObjectAdapter; import org.eclipse.gmf.runtime.emf.type.core.IHintedType; import org.eclipse.gmf.runtime.emf.type.core.commands.EditElementCommand; import org.eclipse.gmf.runtime.emf.type.core.requests.CreateElementRequest; import org.eclipse.gmf.runtime.notation.Node; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.papyrus.infra.widgets.toolbox.LookForElement; import org.eclipse.papyrus.uml.diagram.clazz.custom.command.AssociationClassViewCreateCommand; import org.eclipse.papyrus.uml.diagram.clazz.custom.command.CustomDeferredCreateConnectionViewCommand; import org.eclipse.papyrus.uml.diagram.clazz.custom.command.PropertyCommandForAssociation; import org.eclipse.papyrus.uml.diagram.clazz.edit.commands.PropertyForComponentCreateCommand; import org.eclipse.papyrus.uml.diagram.clazz.providers.ElementInitializers; import org.eclipse.papyrus.uml.diagram.clazz.providers.UMLElementTypes; import org.eclipse.papyrus.uml.diagram.common.commands.SemanticAdapter; import org.eclipse.papyrus.uml.diagram.common.helper.ElementHelper; import org.eclipse.uml2.uml.AssociationClass; import org.eclipse.uml2.uml.Package; import org.eclipse.uml2.uml.Property; import org.eclipse.uml2.uml.Type; import org.eclipse.uml2.uml.UMLFactory; import org.eclipse.uml2.uml.UMLPackage; /** * The Class AssociationClassHelper has in charge to create command to display or to drop an * associationclass */ public class AssociationClassHelper extends ElementHelper { public static EObject createAssociationClass(TransactionalEditingDomain domain, Type source, Type target, Package container) { AssociationClass association = UMLFactory.eINSTANCE.createAssociationClass(); // create target property CreateElementRequest request = new CreateElementRequest(domain, source, UMLElementTypes.Property_3002, UMLPackage.eINSTANCE.getStructuredClassifier_OwnedAttribute()); EditElementCommand c = new PropertyForComponentCreateCommand(request); try { c.execute(new NullProgressMonitor(), null); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } assert (c.getCommandResult() == null); assert (c.getCommandResult().getReturnValue() == null); Property targetProperty = (Property)c.getCommandResult().getReturnValue(); targetProperty.setType(target); targetProperty.setName(target.getName().toLowerCase()); targetProperty.setLower(1); targetProperty.setUpper(1); // create source property request = new CreateElementRequest(domain, association, UMLElementTypes.Property_3002, UMLPackage.eINSTANCE.getAssociation_OwnedEnd()); c = new PropertyCommandForAssociation(request); try { c.execute(new NullProgressMonitor(), null); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } assert (c.getCommandResult() == null); assert (c.getCommandResult().getReturnValue() == null); Property sourceProperty = (Property)c.getCommandResult().getReturnValue(); sourceProperty.setType(source); sourceProperty.setName(source.getName().toLowerCase()); sourceProperty.setLower(1); sourceProperty.setUpper(1); List<Property> memberEnds = association.getMemberEnds(); if((memberEnds.indexOf(((Property)sourceProperty)) >= 0)) { association.getMemberEnds().move(0, ((Property)sourceProperty)); } else { association.getMemberEnds().add(0, ((Property)sourceProperty)); } if((memberEnds.indexOf(((Property)targetProperty)) >= 0)) { association.getMemberEnds().move(1, ((Property)targetProperty)); } else { association.getMemberEnds().add(1, ((Property)targetProperty)); } container.getPackagedElements().add(association); ElementInitializers.getInstance().init_AssociationClass_2013(association); // //////////////////////////////////////////////////////////////////// return association; } /** * Instantiates a new association class helper. * * @param editDomain * the edit domain */ public AssociationClassHelper(TransactionalEditingDomain editDomain) { this.editDomain = editDomain; } /** * Drop association class. * * @param associationClass * the association class the semantic element * @param viewer * the viewer * @param diagramPreferencesHint * the diagram preferences hint * @param location * the location of the drop * @param containerView * the container view that will contain the associationClass views * * @return the command */ public Command dropAssociationClass(AssociationClass associationClass, EditPartViewer viewer, PreferencesHint diagramPreferencesHint, Point location, View containerView) { CompositeCommand cc = new CompositeCommand("drop"); // 0. Obtain list of property to display ArrayList<Property> endToDisplay = new ArrayList(associationClass.getMemberEnds()); GraphicalEditPart[] endEditPart = new GraphicalEditPart[associationClass.getMemberEnds().size()]; // 2. for each element create a graphical representation of the type and // finally the branch Iterator<Property> iteratorProp = endToDisplay.iterator(); int index = 0; while(iteratorProp.hasNext()) { // source editPart EditPart sourceEditPart = null; // end of the association end Property currentEnd = iteratorProp.next(); // look for if an editpart exist for this element Collection<EditPart> editPartSet = viewer.getEditPartRegistry().values(); Iterator<EditPart> editPartIterator = editPartSet.iterator(); while(editPartIterator.hasNext() && sourceEditPart == null) { EditPart currentEditPart = editPartIterator.next(); if((!(currentEditPart instanceof CompartmentEditPart)) && currentEditPart instanceof GraphicalEditPart && currentEnd.getType().equals(((GraphicalEditPart)currentEditPart).resolveSemanticElement())) { endEditPart[index] = (GraphicalEditPart)currentEditPart; } } index += 1; } // descriptor for the branch ConnectionViewDescriptor viewBranchDescriptor = new ConnectionViewDescriptor(UMLElementTypes.Association_4019, ((IHintedType)UMLElementTypes.Association_4019).getSemanticHint(), diagramPreferencesHint); // 2. creation of the associationClass Node without semantic element // creation of the node IAdaptable elementAdapter = new EObjectAdapter(associationClass); ViewDescriptor descriptor = new ViewDescriptor(elementAdapter, Node.class, null, ViewUtil.APPEND, false, diagramPreferencesHint); CreateCommand associationClassNodeCreationCommand = new CreateCommand(getEditingDomain(), descriptor, containerView); cc.compose(associationClassNodeCreationCommand); SetBoundsCommand setBoundsCommand = new SetBoundsCommand(getEditingDomain(), "move", (IAdaptable)associationClassNodeCreationCommand.getCommandResult().getReturnValue(), new Point(location.x, location.y - 100)); cc.compose(setBoundsCommand); IAdaptable sourceAdapter = null; IAdaptable targetAdapter = null; // 3. creation of the dashed line between the associationClass link // and associationClass Node // target if(endEditPart[0] == null) { // creation of the node ViewDescriptor _descriptor = new ViewDescriptor(new EObjectAdapter(endToDisplay.get(0)), Node.class, null, ViewUtil.APPEND, false, diagramPreferencesHint); // get the command and execute it. CreateCommand endNodeCreationCommand = new CreateCommand(getEditingDomain(), _descriptor, containerView); cc.compose(endNodeCreationCommand); setBoundsCommand = new SetBoundsCommand(getEditingDomain(), "move", (IAdaptable)endNodeCreationCommand.getCommandResult().getReturnValue(), new Point(location.x, location.y + 100)); cc.compose(setBoundsCommand); sourceAdapter = (IAdaptable)endNodeCreationCommand.getCommandResult().getReturnValue(); } else { sourceAdapter = new SemanticAdapter(null, endEditPart[0].getModel()); } if(endEditPart[1] == null) { // creation of the node ViewDescriptor _descriptor = new ViewDescriptor(new EObjectAdapter(endToDisplay.get(2)), Node.class, null, ViewUtil.APPEND, false, diagramPreferencesHint); // get the command and execute it. CreateCommand endNodeCreationCommand = new CreateCommand(getEditingDomain(), _descriptor, containerView); cc.compose(endNodeCreationCommand); setBoundsCommand = new SetBoundsCommand(getEditingDomain(), "move", (IAdaptable)endNodeCreationCommand.getCommandResult().getReturnValue(), new Point(location.x, location.y - 100)); cc.compose(setBoundsCommand); targetAdapter = (IAdaptable)endNodeCreationCommand.getCommandResult().getReturnValue(); } else { targetAdapter = new SemanticAdapter(null, endEditPart[1].getModel()); } // create association link ConnectionViewDescriptor viewDescriptor = new ConnectionViewDescriptor(UMLElementTypes.AssociationClass_4017, ((IHintedType)UMLElementTypes.AssociationClass_4017).getSemanticHint(), diagramPreferencesHint); // Creation of the associationLink CustomDeferredCreateConnectionViewCommand associationcClassLinkCommand = new CustomDeferredCreateConnectionViewCommand(getEditingDomain(), ((IHintedType)UMLElementTypes.AssociationClass_4017).getSemanticHint(), sourceAdapter, targetAdapter, viewer, diagramPreferencesHint, viewDescriptor, null); associationcClassLinkCommand.setElement(associationClass); cc.compose(associationcClassLinkCommand); // creation of the dashedLine ConnectionViewDescriptor dashedLineViewDescriptor = new ConnectionViewDescriptor(UMLElementTypes.Link_4016, ((IHintedType)UMLElementTypes.Link_4016).getSemanticHint(), diagramPreferencesHint); CustomDeferredCreateConnectionViewCommand dashedLineCmd = new CustomDeferredCreateConnectionViewCommand(getEditingDomain(), ((IHintedType)UMLElementTypes.Link_4016).getSemanticHint(), ((IAdaptable)associationcClassLinkCommand.getCommandResult().getReturnValue()), ((IAdaptable)associationClassNodeCreationCommand.getCommandResult().getReturnValue()), viewer, diagramPreferencesHint, dashedLineViewDescriptor, null); dashedLineCmd.setElement(associationClass); cc.compose(dashedLineCmd); return new ICommandProxy(cc); } /** * This method is used to produce a set of commands in charge of the creation of * AssociationClass. * * @param createConnectionViewAndElementRequest * the create connection view and element request * @param command * the command that is used to create the link associationClass * * @return the set of command to create an association Class */ public Command getAssociationClassElementCommand(CreateConnectionViewAndElementRequest createConnectionViewAndElementRequest, Command command) { if(command instanceof ICommandProxy) { if( createConnectionViewAndElementRequest.getSourceEditPart() instanceof GraphicalEditPart){ GraphicalEditPart sourceEditPart = (GraphicalEditPart)createConnectionViewAndElementRequest.getSourceEditPart(); // 1. calculus of the position of the associationClass node Point p = sourceEditPart.getFigure().getBounds().getTopRight().getCopy(); sourceEditPart.getFigure().translateToAbsolute(p); int edgeCount = sourceEditPart.getNotationView().getSourceEdges().size(); int offset = (edgeCount * 50) - 100; p = p.translate(100, offset); // 2. creation of the associationClass Node without semantic element GraphicalEditPart parent = (GraphicalEditPart)sourceEditPart.getParent(); AssociationClassViewCreateCommand assCommand = new AssociationClassViewCreateCommand(createConnectionViewAndElementRequest, getEditingDomain(), (View)parent.getModel(), (EditPartViewer)sourceEditPart.getViewer(), sourceEditPart.getDiagramPreferencesHint(), p); command = command.chain(new ICommandProxy(assCommand)); // 3. creation of the dashed line between the associationClass link // and associationClass Node // target IAdaptable associationClassLinkViewAdapter = (IAdaptable)(createConnectionViewAndElementRequest.getNewObject()); ConnectionViewDescriptor viewDescriptor = new ConnectionViewDescriptor(UMLElementTypes.Link_4016, ((INotationType)UMLElementTypes.Link_4016).getSemanticHint(), sourceEditPart.getDiagramPreferencesHint()); ICommand dashedLineCmd = new CustomDeferredCreateConnectionViewCommand(getEditingDomain(), ((IHintedType)UMLElementTypes.Link_4016).getSemanticHint(), associationClassLinkViewAdapter, null, sourceEditPart.getViewer(), sourceEditPart.getDiagramPreferencesHint(), viewDescriptor, assCommand); command = command.chain(new ICommandProxy(dashedLineCmd)); return command; } else{ return UnexecutableCommand.INSTANCE; } } return null; } }