/*****************************************************************************
* 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:
*
*
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.clazz.custom.helper;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.core.commands.operations.IUndoableOperation;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.emf.common.util.EList;
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.requests.ReconnectRequest;
import org.eclipse.gmf.runtime.common.core.command.CompositeCommand;
import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.common.core.command.ICompositeCommand;
import org.eclipse.gmf.runtime.diagram.core.commands.DeleteCommand;
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.GraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewRequest;
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.emf.commands.core.command.CompositeTransactionalCommand;
import org.eclipse.gmf.runtime.emf.core.util.EObjectAdapter;
import org.eclipse.gmf.runtime.emf.type.core.IHintedType;
import org.eclipse.gmf.runtime.notation.Edge;
import org.eclipse.gmf.runtime.notation.Node;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.uml.appearance.helper.UMLVisualInformationPapyrusConstant;
import org.eclipse.papyrus.uml.diagram.clazz.custom.command.ContainmentCircleViewCreateCommand;
import org.eclipse.papyrus.uml.diagram.clazz.custom.command.CustomCreateContainmentLinkCommand;
import org.eclipse.papyrus.uml.diagram.clazz.custom.command.CustomDropAppliedStereotypeCommand;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ClassEditPart;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ContainmentCircleEditPart;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ContainmentSubLinkEditPart;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ModelEditPartCN;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ModelEditPartTN;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.NestedClassForClassEditPart;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.PackageEditPart;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.PackageEditPartCN;
import org.eclipse.papyrus.uml.diagram.clazz.edit.policies.UMLBaseItemSemanticEditPolicy;
import org.eclipse.papyrus.uml.diagram.clazz.part.UMLVisualIDRegistry;
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.Element;
import org.eclipse.uml2.uml.PackageableElement;
import org.eclipse.uml2.uml.Stereotype;
public class ContainmentHelper extends ElementHelper {
protected static final String CREATE_CONTAINMENT = "Create Containment";
public static final String CONTAINMENT_CIRCLE_POSITION = "ContainmentCirclePosition";
/** The Constant CONNECTION_VIEW. */
public static final String KEY_CONNECTION_VIEW = "connection_view"; //$NON-NLS-1$
/**
* Instantiates a new containment class helper.
*
* @param editDomain
* the edit domain
*/
public ContainmentHelper(TransactionalEditingDomain editDomain) {
this.editDomain = editDomain;
}
/**
* Create a containment link view with the semantic transformation.
* This link can be created between two classes or between the node of the containment link with the targeted class or package
*
* @param createConnectionViewRequest
* the create connection view request
* @param command
* the command
*
* @return the containment element command
*/
public Command getCreateContainmentCommand(CreateConnectionViewRequest createConnectionViewRequest, Command command) {
CompositeCommand compoundCommand = new CompositeCommand(CREATE_CONTAINMENT);
IGraphicalEditPart sourceEditPart = (GraphicalEditPart)createConnectionViewRequest.getSourceEditPart();
View sourceView = (View)sourceEditPart.getModel();
EditPartViewer editPartViewer = (EditPartViewer)sourceEditPart.getViewer();
PreferencesHint preferencesHint = sourceEditPart.getDiagramPreferencesHint();
String linkHint = ((IHintedType)UMLElementTypes.Link_4022).getSemanticHint();
ConnectionViewDescriptor viewDescriptor = new ConnectionViewDescriptor(org.eclipse.papyrus.uml.diagram.clazz.providers.UMLElementTypes.Link_4022, ((IHintedType)org.eclipse.papyrus.uml.diagram.clazz.providers.UMLElementTypes.Link_4022).getSemanticHint(), sourceEditPart.getDiagramPreferencesHint());
View targetView = (View)createConnectionViewRequest.getTargetEditPart().getModel();
IAdaptable targetViewAdapter = new SemanticAdapter(null, targetView);
IAdaptable circleAdapter = null;
ContainmentCircleViewCreateCommand circleCommand = null;
deleteIncomingContainmentLinksFor(compoundCommand, targetView);
//detect if we draw a containment link between the node of containment and the target class or package
if(ContainmentCircleEditPart.VISUAL_ID == UMLVisualIDRegistry.getVisualID(sourceEditPart.getNotationView())) {
circleAdapter = new SemanticAdapter(null, sourceEditPart.getNotationView());
sourceView = (View)sourceEditPart.getParent().getModel();
} else {
//detect if we draw a containment link between two class or packages
circleCommand = new ContainmentCircleViewCreateCommand(createConnectionViewRequest, getEditingDomain(), sourceView, editPartViewer, preferencesHint);
compoundCommand.add(circleCommand);
if(createConnectionViewRequest.getLocation() != null) {
SetBoundsCommand setBoundsCommand = new SetBoundsCommand(getEditingDomain(), CONTAINMENT_CIRCLE_POSITION, (IAdaptable)circleCommand.getCommandResult().getReturnValue(), createConnectionViewRequest.getLocation());
compoundCommand.add(setBoundsCommand);
}
}
ICommand dashedLineCmd = new CustomCreateContainmentLinkCommand(getEditingDomain(), linkHint, sourceView, circleAdapter, targetViewAdapter, editPartViewer, preferencesHint, viewDescriptor, circleCommand);
compoundCommand.add(dashedLineCmd);
return new ICommandProxy(compoundCommand);
}
/**
* Delete all incoming link that go this node
*
* @param cc
* a composite command in which the behavior of deletion
* @param node
* where would like to remove all incoming containment link can not be null
*/
public void deleteIncomingContainmentLinksFor(CompositeCommand cc, View node) {
for(Object incomingLink : node.getTargetEdges()) {
Edge nextConnector = (Edge)incomingLink;
View nextConnectorSource = nextConnector.getSource();
if(isContainmentLink(nextConnector)) {
cc.add(new DeleteCommand(getEditingDomain(), nextConnector));
/* The containment circle node is deleted only if any other link is connected */
if(isContainmentCircle(nextConnectorSource) && nextConnectorSource.getSourceEdges().size() == 1) {
// Delete the containment circle
cc.add(new DeleteCommand(getEditingDomain(), nextConnectorSource));
}
}
}
}
/**
* Delete all outgoing link that come from this node
*
* @param cc
* a composite command in which the behavior of deletion
* @param node
* where would like to remove all outgoing containment link can not be null
*/
public void deleteOutgoingContainmentLinksFor(CompositeCommand cc, View node) {
for(Object nextChild : node.getVisibleChildren()) {
View circle = (View)nextChild;
if(isContainmentCircle(circle)) {
for(Object next : circle.getSourceEdges()) {
Edge outgoingLink = (Edge)next;
if(ContainmentHelper.isContainmentLink(outgoingLink)) {
cc.add(new DeleteCommand(getEditingDomain(), outgoingLink));
}
}
}
}
}
/**
* DragDrop the contained class from the modelexplorer to the diagram and from the compartment to the diagram.
*
* @param droppedElement
* the semantic class
* @param viewer
* the viewer
* @param diagramPreferencesHint
* the diagram preferences hint
* @param location
* the location
* @param containerView
* the container view
*
* @return the command
*/
public Command outlineDropContainedClass(PackageableElement droppedElement, EditPartViewer viewer, PreferencesHint diagramPreferencesHint, Point location, View containerView) {
return dropElementToDiagram(droppedElement, viewer, diagramPreferencesHint, location, containerView);
}
/**
* This method can be called in two cases:
* - a drop from the model explorer
* - a drop from the owner class to outside of this class
* when the contained link is not created in this case.
*
*
* @param droppedElement
* the dropped element <B> cannot be null</B>
* @param viewer
* the viewer <B> cannot be null</B>
* @param diagramPreferencesHint
* the diagram preferences hint <B> cannot be null</B>
* @param location
* the location <B> cannot be null</B>
* @param containerView
* the container view <B> cannot be null</B>
* @return the command
*/
public Command dropElementToDiagram(PackageableElement droppedElement, EditPartViewer viewer, PreferencesHint diagramPreferencesHint, Point location, View containerView) {
//0 what is the context of this call
//- drop from the model explorer
//- drop intra diagram form its container to outside of this class
// - the edit part of a the dropped element already exist?
EditPart droppedElementEditPart = findEditPartFor(viewer.getEditPartRegistry(), droppedElement);
//Is is contained into a class ?
Element owner = (Element)droppedElement.getOwner();
//the container editpart is the the class that can contained the dropped element.
//if it is not null we are in the context of drop intra diagram
GraphicalEditPart containerEditpart = null;
if(droppedElementEditPart != null) {
GraphicalEditPart parentEP = (GraphicalEditPart)droppedElementEditPart.getParent();
if(parentEP.resolveSemanticElement().equals(owner)) {
containerEditpart = parentEP;
}
}
CompositeCommand cc = new CompositeCommand("drop");
// in the context of a drop from the model explorer -> create only a view for this element
if(containerEditpart == null) {
dropElementToDiagram(cc, droppedElement, diagramPreferencesHint, location, containerView);
} else {
//in the case of a drop intra diagram, remove view from the container and it into the diagram
if(canHaveContainmentLink(droppedElementEditPart)) {
cc.add(new DeleteCommand(getEditingDomain(), (View)droppedElementEditPart.getModel()));
dropElementToDiagram(cc, droppedElement, diagramPreferencesHint, location, containerView);
}
}
return new ICommandProxy(cc);
}
/**
* dropped the dropped element into container view at a good location,
*
* @param cc
* the composite command, where the behavior will be add <B> cannot be null</B>
* @param droppedElement
* the semantic element to drop <B> cannot be null</B>
* @param diagramPreferencesHint
* <B> cannot be null</B>
* @param location
* location of the dropped element <B> cannot be null</B>
* @param containerView
* the container that will contain the view of the dropped element <B> cannot be null</B>
*/
protected void dropElementToDiagram(CompositeCommand cc, PackageableElement droppedElement, PreferencesHint diagramPreferencesHint, Point location, View containerView) {
ViewDescriptor droppedElementDescriptor = new ViewDescriptor(new EObjectAdapter(droppedElement), Node.class, null, ViewUtil.APPEND, false, diagramPreferencesHint);
CreateCommand containedNodeCreationCommand = new CreateCommand(this.editDomain, droppedElementDescriptor, containerView);
cc.add(containedNodeCreationCommand);
cc.add(new SetBoundsCommand(getEditingDomain(), "move", (IAdaptable)containedNodeCreationCommand.getCommandResult().getReturnValue(), new Point(location.x, location.y - 100)));
addStereotypeLabelToDroppedElement(cc, droppedElement, (IAdaptable)containedNodeCreationCommand.getCommandResult().getReturnValue());
}
/**
* TO DO: to investigate about the use of this code
* this method is used to display applied stereotype of the dropped element
*
* @param cc
* the command where the behavior will be add
* @param droppedElement
* the dropped element <B> cannot be null</B>
* @param createdEditPartAdapter
* a wrapper that contained the created view of the dropped element
*/
protected void addStereotypeLabelToDroppedElement(CompositeCommand cc, PackageableElement droppedElement, IAdaptable createdEditPartAdapter) {
if(droppedElement.getAppliedStereotypes().isEmpty()) {
return;
}
EList<Stereotype> stereotypeAppliedList = droppedElement.getAppliedStereotypes();
Iterator<Stereotype> stereotypeAppliedIterator = stereotypeAppliedList.iterator();
while(stereotypeAppliedIterator.hasNext()) {
Stereotype stereotype = (Stereotype)stereotypeAppliedIterator.next();
String profileApplied = "\"" + stereotype.getProfile() + "\"::";
cc.add(new CustomDropAppliedStereotypeCommand(this.editDomain, createdEditPartAdapter, profileApplied, UMLVisualInformationPapyrusConstant.STEREOTYPE_COMPARTMENT_LOCATION));
}
}
/**
*
* Checks if is reorient about the containment link.
*
* @param request
* a connection request
* @return true, if is reorient about the containment link
*/
public static boolean isReorientContainmentLink(ReconnectRequest request) {
int visualId = getVisualID(request);
return visualId == ContainmentSubLinkEditPart.VISUAL_ID;
}
/**
* TO DO: to investigate about the use of this code
* During the reconnection we need to add information about the view that is reconnected.
*
* @param request
* the request
* @return the reconnect request
*/
public static ReconnectRequest extendReorientTargetRequest(ReconnectRequest request) {
Object view = request.getConnectionEditPart().getModel();
if(view instanceof View) {
request.getExtendedData().put(ContainmentHelper.KEY_CONNECTION_VIEW, view);
}
return request;
}
/**
* TO DO: to investigate about the use of this code
* During the reconnection we need to add information about the view that is reconnected.
*
* @param request
* the request
* @return the reconnect request
*/
public static ReconnectRequest extendReorientSourceRequest(ReconnectRequest request) {
Object view = request.getConnectionEditPart().getModel();
if(view instanceof View) {
request.getExtendedData().put(ContainmentHelper.KEY_CONNECTION_VIEW, view);
}
return request;
}
/**
* Gets the visual id.
*
* @param request
* the request
* @return the visual id
*/
private static int getVisualID(ReconnectRequest request) {
Object id = request.getExtendedData().get(UMLBaseItemSemanticEditPolicy.VISUAL_ID_KEY);
return id instanceof Integer ? ((Integer)id).intValue() : -1;
}
/**
* Checks if is containment link.
*
* @param edge
* the edge
* @return true, if is containment link
*/
public static boolean isContainmentLink(Edge edge) {
return UMLVisualIDRegistry.getVisualID(edge) == ContainmentSubLinkEditPart.VISUAL_ID;
}
/**
* Checks if is containment node.
*
* @param view
* the notation view
* @return true, if is containment link
*/
public static boolean isContainmentCircle(View view) {
return UMLVisualIDRegistry.getVisualID(view) == ContainmentCircleEditPart.VISUAL_ID;
}
/**
* checks if the node contains several outgoing link.
*
* @param containmentCircle
* the node that show a contaiment link
* @return true if the coantaiment node is connected several link
*/
private static boolean circleHasOtherLinks(View containmentCircle) {
return containmentCircle.getSourceEdges().size() > 1;
}
/**
* Delete incoming containment link command.
*
* @param editingDomain
* the editing domain
* @param incomingLink
* the incoming link
* @return the i undoable operation
*/
public static IUndoableOperation deleteIncomingContainmentLinkCommand(TransactionalEditingDomain editingDomain, Edge incomingLink) {
CompositeTransactionalCommand cmd = new CompositeTransactionalCommand(editingDomain, "Delete Incoming Containment Link");
cmd.add(new DeleteCommand(editingDomain, incomingLink));
View containmentCircle = incomingLink.getSource();
if(!circleHasOtherLinks(containmentCircle)) {
cmd.add(new DeleteCommand(editingDomain, (View)containmentCircle));
}
return cmd;
}
/**
* Adds the delete incoming containment link view commands.
*
* @param editingDomain
* the editing domain
* @param targetNode
* the target node
* @param cmd
* the cmd
*/
public static void addDeleteIncomingContainmentLinkViewCommands(TransactionalEditingDomain editingDomain, View targetNode, ICompositeCommand cmd) {
for(Object next : targetNode.getTargetEdges()) {
Edge incomingLink = (Edge)next;
if(ContainmentHelper.isContainmentLink(incomingLink)) {
cmd.add(new DeleteCommand(editingDomain, incomingLink));
View containmentCircle = incomingLink.getSource();
if(!circleHasOtherLinks(containmentCircle)) {
cmd.add(new DeleteCommand(editingDomain, (View)containmentCircle));
}
}
}
}
/**
* Checks for incoming containment link.
*
* @param targetNode
* the target node
* @return true, if successful
*/
public static boolean hasIncomingContainmentLink(View targetNode) {
for(Object next : targetNode.getTargetEdges()) {
Edge incomingLink = (Edge)next;
if(ContainmentHelper.isContainmentLink(incomingLink)) {
return true;
}
}
return false;
}
/**
* Checks for outgoing containment link.
*
* @param targetNode
* the target node
* @return true, if successful
*/
public static boolean hasOutgoingContainmentLink(View targetNode) {
for(Object next : targetNode.getVisibleChildren()) {
View node = (View)next;
if(isContainmentCircle(node)) {
for(Object nextLink : node.getSourceEdges()) {
Edge outgoingLink = (Edge)nextLink;
if(ContainmentHelper.isContainmentLink(outgoingLink)) {
return true;
}
}
}
}
return false;
}
/**
* Adds the destroy outgoing containment links command.
*
* @param editingDomain
* the editing domain
* @param sourceNode
* the source node
* @param cmd
*
* the cmd
*/
public static void addDeleteOutgoingContainmentLinkViewCommands(TransactionalEditingDomain editingDomain, View sourceNode, ICompositeCommand cmd) {
for(Object child : sourceNode.getVisibleChildren()) {
if(ContainmentHelper.isContainmentCircle((View)child)) {
View circle = (View)child;
cmd.add(new DeleteCommand(editingDomain, circle));
for(Object next : circle.getSourceEdges()) {
Edge outgoingLink = (Edge)next;
if(ContainmentHelper.isContainmentLink(outgoingLink)) {
cmd.add(new DeleteCommand(editingDomain, outgoingLink));
//delete target view as it actually contained by the source object and will be deleted
cmd.add(new DeleteCommand(editingDomain, outgoingLink.getTarget()));
addDeleteOutgoingContainmentLinkViewCommands(editingDomain, outgoingLink.getTarget(), cmd);
}
}
}
}
}
/**
* look for a editpart from the semantic element
*
* @param editPartRegistry
* the map of editpart
* @param droppedElement
* the semantic element
* @return can return null if nothing is found
*/
public EditPart findEditPartFor(Map editPartRegistry, Element droppedElement) {
for(Object next : editPartRegistry.values()) {
EditPart currentEditPart = (EditPart)next;
if(canHaveContainmentLink(currentEditPart)) {
View currentView = (View)currentEditPart.getModel();
if(droppedElement.equals(currentView.getElement())) {
return currentEditPart;
}
}
}
return null;
}
private boolean canHaveContainmentLink(EditPart currentEditPart) {
return currentEditPart instanceof ClassEditPart || currentEditPart instanceof PackageEditPartCN || currentEditPart instanceof PackageEditPart || currentEditPart instanceof ModelEditPartTN || currentEditPart instanceof NestedClassForClassEditPart || currentEditPart instanceof ModelEditPartCN;
}
/**
* Move.
*
* @param objectToMove
* the object to move
* @param to
* the to
* @return true, if successful
*/
public boolean move(EObject objectToMove, EObject to) {
if(objectToMove instanceof org.eclipse.uml2.uml.Package) {
return movePackage((org.eclipse.uml2.uml.Package)objectToMove, to);
} else if(objectToMove instanceof org.eclipse.uml2.uml.Class) {
return moveClass((org.eclipse.uml2.uml.Class)objectToMove, to);
}
return false;
}
/**
* Move package.
*
* @param pakkage
* the pakkage
* @param to
* the to
* @return true, if successful
*/
private boolean movePackage(org.eclipse.uml2.uml.Package pakkage, EObject to) {
Element from = pakkage.getOwner();
if(to instanceof org.eclipse.uml2.uml.Package && from instanceof org.eclipse.uml2.uml.Package) {
doMovePackage(pakkage, (org.eclipse.uml2.uml.Package)from, (org.eclipse.uml2.uml.Package)to);
return true;
}
return false;
}
/**
* Move class.
*
* @param clazz
* the clazz
* @param to
* the to
* @return true, if successful
*/
private boolean moveClass(org.eclipse.uml2.uml.Class clazz, EObject to) {
Element from = clazz.getOwner();
if(from instanceof org.eclipse.uml2.uml.Class) {
org.eclipse.uml2.uml.Class fromClazz = (org.eclipse.uml2.uml.Class)from;
if(to instanceof org.eclipse.uml2.uml.Class) {
doMoveClass(clazz, fromClazz, (org.eclipse.uml2.uml.Class)to);
return true;
} else if(to instanceof org.eclipse.uml2.uml.Package) {
doMoveClass(clazz, fromClazz, (org.eclipse.uml2.uml.Package)to);
return true;
}
}
if(from instanceof org.eclipse.uml2.uml.Package) {
org.eclipse.uml2.uml.Package fromPackage = (org.eclipse.uml2.uml.Package)from;
if(to instanceof org.eclipse.uml2.uml.Class) {
doMoveClass(clazz, fromPackage, (org.eclipse.uml2.uml.Class)to);
return true;
} else if(to instanceof org.eclipse.uml2.uml.Package) {
doMoveClass(clazz, fromPackage, (org.eclipse.uml2.uml.Package)to);
return true;
}
}
return false;
}
/**
* Do move package.
*
* @param pakkage
* the pakkage
* @param from
* the from
* @param to
* the to
*/
private void doMovePackage(org.eclipse.uml2.uml.Package pakkage, org.eclipse.uml2.uml.Package from, org.eclipse.uml2.uml.Package to) {
from.getNestedPackages().remove(pakkage);
to.getNestedPackages().add(pakkage);
}
/**
* Do move class.
*
* @param clazz
* the clazz
* @param from
* the from
* @param to
* the to
*/
private void doMoveClass(org.eclipse.uml2.uml.Class clazz, org.eclipse.uml2.uml.Package from, org.eclipse.uml2.uml.Package to) {
from.getPackagedElements().remove(clazz);
to.getPackagedElements().add(clazz);
}
/**
* Do move class.
*
* @param clazz
* the clazz
* @param from
* the from
* @param to
* the to
*/
private void doMoveClass(org.eclipse.uml2.uml.Class clazz, org.eclipse.uml2.uml.Package from, org.eclipse.uml2.uml.Class to) {
from.getPackagedElements().remove(clazz);
to.getNestedClassifiers().add(clazz);
}
/**
* Do move class.
*
* @param clazz
* the clazz
* @param from
* the from
* @param to
* the to
*/
private void doMoveClass(org.eclipse.uml2.uml.Class clazz, org.eclipse.uml2.uml.Class from, org.eclipse.uml2.uml.Package to) {
from.getNestedClassifiers().remove(clazz);
to.getPackagedElements().add(clazz);
}
/**
* Do move class.
*
* @param clazz
* the clazz
* @param from
* the from
* @param to
* the to
*/
private void doMoveClass(org.eclipse.uml2.uml.Class clazz, org.eclipse.uml2.uml.Class from, org.eclipse.uml2.uml.Class to) {
from.getNestedClassifiers().remove(clazz);
to.getNestedClassifiers().add(clazz);
}
}