/***************************************************************************** * Copyright (c) 2010 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: * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation *****************************************************************************/ package org.eclipse.papyrus.uml.tools.databinding; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.edit.domain.EditingDomain; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.gmf.runtime.common.core.command.CompositeCommand; import org.eclipse.gmf.runtime.common.core.command.ICommand; import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyElementRequest; import org.eclipse.gmf.runtime.emf.type.core.requests.IEditCommandRequest; import org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest; import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper; import org.eclipse.papyrus.infra.emf.databinding.EMFObservableList; import org.eclipse.papyrus.infra.services.edit.service.ElementEditServiceUtils; import org.eclipse.papyrus.infra.services.edit.service.IElementEditService; /** * An ObservableList used to edit collections of EObjects through * Papyrus commands * * @author Camille Letavernier * */ @SuppressWarnings("unchecked") public class PapyrusObservableList extends EMFObservableList { /** * * Constructor. * * @param wrappedList * The list to be edited when #commit() is called * @param domain * The editing domain on which the commands will be executed * @param source * The EObject from which the list will be retrieved * @param feature * The feature from which the list will be retrieved */ public PapyrusObservableList(List<?> wrappedList, EditingDomain domain, EObject source, EStructuralFeature feature) { super(wrappedList, domain, source, feature); } /** * @return the IElementEditService used to retrieve the command */ protected IElementEditService getProvider() { return ElementEditServiceUtils.getCommandProvider(source); } /** * Creates an EMF command from a GMF request, with the given IElementEditService * * @param provider * @param requests * @return * The EMF command corresponding to the given request */ protected Command getCommandFromRequests(IElementEditService provider, Collection<? extends IEditCommandRequest> requests) { if(requests.size() == 1) { return new GMFtoEMFCommandWrapper(provider.getEditCommand(requests.iterator().next())); } CompositeCommand cc = new CompositeCommand("Edit list"); for(IEditCommandRequest request : requests) { ICommand cmd = provider.getEditCommand(request); cc.add(cmd); } return new GMFtoEMFCommandWrapper(cc); } /** * {@inheritDoc} */ @Override public Command getAddCommand(int index, Object value) { IElementEditService provider = getProvider(); if(provider != null) { List<Object> values = new LinkedList<Object>(this); values.add(index, value); return getCommandFromRequests(provider, getRequests(values, null)); } return super.getAddCommand(index, value); } /** * {@inheritDoc} */ @Override public Command getAddCommand(Object value) { IElementEditService provider = getProvider(); if(provider != null) { List<Object> values = new LinkedList<Object>(this); values.add(value); return getCommandFromRequests(provider, getRequests(values, null)); } return super.getAddCommand(value); } /** * {@inheritDoc} */ @Override public Command getAddAllCommand(Collection<?> values) { IElementEditService provider = getProvider(); if(provider != null) { List<Object> result = new LinkedList<Object>(this); result.addAll(values); return getCommandFromRequests(provider, getRequests(result, null)); } return super.getAddAllCommand(values); } /** * {@inheritDoc} */ @Override public Command getAddAllCommand(int index, Collection<?> values) { IElementEditService provider = getProvider(); if(provider != null) { List<Object> result = new LinkedList<Object>(this); result.addAll(index, values); return getCommandFromRequests(provider, getRequests(result, null)); } return super.getAddAllCommand(index, values); } /** * {@inheritDoc} */ @Override public Command getClearCommand() { IElementEditService provider = getProvider(); if(provider != null) { return getCommandFromRequests(provider, getRequests(Collections.EMPTY_LIST, new LinkedList<Object>(this))); } return super.getClearCommand(); } /** * {@inheritDoc} */ @Override public Command getRemoveCommand(int index) { IElementEditService provider = getProvider(); if(provider != null) { List<Object> values = new LinkedList<Object>(this); Object o = values.remove(index); return getCommandFromRequests(provider, getRequests(values, Collections.singletonList(o))); } return null; } /** * {@inheritDoc} */ @Override public Command getRemoveCommand(final Object value) { IElementEditService provider = getProvider(); if(provider != null) { List<Object> values = new LinkedList<Object>(this); values.remove(value); return getCommandFromRequests(provider, getRequests(values, Collections.singletonList(value))); } return super.getRemoveCommand(value); } /** * {@inheritDoc} */ @Override public Command getRemoveAllCommand(Collection<?> values) { IElementEditService provider = getProvider(); if(provider != null) { List<Object> result = new LinkedList<Object>(this); result.removeAll(values); return getCommandFromRequests(provider, getRequests(result, values)); } return super.getRemoveAllCommand(values); } /** * {@inheritDoc} */ @Override public List<Command> getMoveCommands(int oldIndex, int newIndex) { IElementEditService provider = getProvider(); if(provider != null) { List<Object> values = new LinkedList<Object>(this); Object result = values.remove(oldIndex); values.add(newIndex, result); return Collections.singletonList(getCommandFromRequests(provider, getRequests(values, null))); } return super.getMoveCommands(oldIndex, newIndex); } /** * {@inheritDoc} */ @Override public Command getSetCommand(int index, Object value) { IElementEditService provider = getProvider(); if(provider != null) { List<Object> values = new LinkedList<Object>(this); Object oldElem = values.set(index, value); return getCommandFromRequests(provider, getRequests(values, Collections.singletonList(oldElem))); } return super.getSetCommand(index, value); } /** * Compute the requests * * @param newValues * the new list that will be set as a value of the observed feature * @param removedValues * if element has been removed from the list put it there : it handles destroy of elements if the observed feature is a containment * @return */ protected Collection<? extends IEditCommandRequest> getRequests(List<Object> newValues, Collection<?> removedValues) { LinkedList<IEditCommandRequest> requests = new LinkedList<IEditCommandRequest>(); if(feature instanceof EReference && ((EReference)feature).isContainment() && removedValues != null) { for(Object o : removedValues) { if(o instanceof EObject) { requests.add(new DestroyElementRequest((TransactionalEditingDomain)editingDomain, (EObject)o, false)); } } } requests.add(new SetRequest((TransactionalEditingDomain)editingDomain, source, feature, newValues)); return requests; } }