blob: 7944144ce299cec74c8f5b2e1f53e2778eb63e57 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008-2011 Chair for Applied Software Engineering,
* Technische Universitaet Muenchen.
* 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.emf.ecp.editor.mecontrols.melinkcontrol;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecp.common.commands.ECPCommand;
import org.eclipse.emf.ecp.common.model.ECPModelelementContext;
import org.eclipse.emf.ecp.common.util.OverlayImageDescriptor;
import org.eclipse.emf.ecp.editor.MESuggestedSelectionDialog;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.IItemPropertyDescriptor;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.PlatformUI;
/**
* An Action for adding reference links to a model element. <br/>
* It is mainly used in the {@link MEMultiLinkControl}.
*
* @author shterev
*/
public class AddReferenceAction extends ReferenceAction {
private static final String DIALOG_MESSAGE = "Enter model element name prefix or pattern (e.g. *Trun?)";
private final ECPModelelementContext context;
/**
* Command to add a new reference.
*
* @author helming
*/
private final class AddReferenceCommand extends ECPCommand {
public AddReferenceCommand(EObject eObject) {
super(eObject);
}
@Override
protected void doRun() {
if (!checkMultiplicity(false)) {
return;
}
EClass clazz = getReference().getEReferenceType();
Collection<EObject> allElements = context.getAllModelElementsbyClass(clazz, true);
allElements.remove(getModelElement());
Object object = getModelElement().eGet(getReference());
// don't provide facility to link instances that are already linked
EList<EObject> eList = filterAlreadyLinkedElements(allElements, object);
// don't show contained elements for inverse containment references
if (getReference().isContainer()) {
allElements.removeAll(getModelElement().eContents());
}
// take care of circular references
if (getReference().isContainment()) {
Iterator<EObject> iter = allElements.iterator();
while (iter.hasNext()) {
EObject me = iter.next();
if (EcoreUtil.isAncestor(me, getModelElement())) {
iter.remove();
}
}
}
MESuggestedSelectionDialog dlg = new MESuggestedSelectionDialog("Select Elements", DIALOG_MESSAGE, true,
getModelElement(), getReference(), allElements);
if (dlg.open() == Window.OK) {
if (getReference().isMany()) {
Object[] results = dlg.getResult();
ProgressMonitorDialog progressDialog = new ProgressMonitorDialog(PlatformUI.getWorkbench()
.getActiveWorkbenchWindow().getShell());
progressDialog.open();
progressDialog.getProgressMonitor().beginTask("Adding references...", results.length * 10);
List<EObject> list = new ArrayList<EObject>();
for (Object result : results) {
if (result instanceof EObject) {
list.add((EObject) result);
progressDialog.getProgressMonitor().worked(10);
}
}
eList.addAll(list);
progressDialog.getProgressMonitor().done();
progressDialog.close();
} else {
Object result = dlg.getFirstResult();
if (result instanceof EObject) {
getModelElement().eSet(getReference(), result);
}
}
}
}
@SuppressWarnings("unchecked")
private EList<EObject> filterAlreadyLinkedElements(Collection<EObject> allElements, Object object) {
EObject eObject;
EList<EObject> list = null;
if (getReference().isMany() && object instanceof EList) {
list = (EList<EObject>) object;
for (EObject ref : list) {
allElements.remove(ref);
}
} else if (!getReference().isMany() && object instanceof EObject) {
eObject = (EObject) object;
allElements.remove(eObject);
}
return list;
}
}
/**
* Default constructor.
*
* @param modelElement the source model element
* @param eReference the target reference
* @param descriptor the descriptor used to generate display content
* @param context the context of the model element
*/
public AddReferenceAction(EObject modelElement, EReference eReference, IItemPropertyDescriptor descriptor,
ECPModelelementContext context) {
this.setModelElement(modelElement);
this.setReference(eReference);
this.context = context;
Object obj = null;
if (!eReference.getEReferenceType().isAbstract()) {
obj = eReference.getEReferenceType().getEPackage().getEFactoryInstance()
.create(eReference.getEReferenceType());
}
ComposedAdapterFactory adapterFactory = new ComposedAdapterFactory(
ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
Image image = new AdapterFactoryLabelProvider(adapterFactory).getImage(obj);
adapterFactory.dispose();
String overlayString = "icons/link_overlay.png";
if (eReference.isContainment()) {
overlayString = "icons/containment_overlay.png";
}
ImageDescriptor addOverlay = org.eclipse.emf.ecp.common.Activator.getImageDescriptor(overlayString);
OverlayImageDescriptor imageDescriptor = new OverlayImageDescriptor(image, addOverlay,
OverlayImageDescriptor.LOWER_RIGHT);
setImageDescriptor(imageDescriptor);
String attribute = descriptor.getDisplayName(eReference);
// make singular attribute labels
if (attribute.endsWith("ies")) {
attribute = attribute.substring(0, attribute.length() - 3) + "y";
} else if (attribute.endsWith("s")) {
attribute = attribute.substring(0, attribute.length() - 1);
}
setToolTipText("Link " + attribute);
}
/**
* {@inheritDoc}
*/
@Override
public void run() {
new AddReferenceCommand(this.getModelElement()).run(true);
}
}