/** | |
* Copyright (c) 2009-2010 Thales Corporate Services S.A.S. | |
* This program and the accompanying materials | |
* are made available under the terms of the Eclipse Public License v2.0 | |
* which accompanies this distribution, and is available at | |
* https://www.eclipse.org/legal/epl-v2.0 | |
* | |
* SPDX-License-Identifier: EPL-2.0 | |
* | |
* Contributors: | |
* Thales Corporate Services S.A.S - initial API and implementation | |
*/ | |
package org.eclipse.egf.model.fcore.provider; | |
import java.util.ArrayList; | |
import java.util.Collection; | |
import org.eclipse.egf.common.helper.EMFHelper; | |
import org.eclipse.egf.core.fcore.IPlatformFcore; | |
import org.eclipse.egf.core.fcore.IPlatformFcoreProvider; | |
import org.eclipse.egf.core.platform.pde.IPlatformBundle; | |
import org.eclipse.egf.model.edit.EGFModelEditPlugin; | |
import org.eclipse.egf.model.fcore.FcoreFactory; | |
import org.eclipse.egf.model.fcore.FcorePackage; | |
import org.eclipse.egf.model.fcore.commands.resource.FcoreResourceAddCommand; | |
import org.eclipse.egf.model.fcore.commands.resource.ResourceFeatureAddCommand; | |
import org.eclipse.egf.model.fcore.commands.resource.ResourceMoveCommand; | |
import org.eclipse.egf.model.fcore.commands.resource.ResourceRemoveCommand; | |
import org.eclipse.egf.model.fcore.util.FcoreResourceImpl; | |
import org.eclipse.emf.common.command.Command; | |
import org.eclipse.emf.common.command.CompoundCommand; | |
import org.eclipse.emf.common.command.UnexecutableCommand; | |
import org.eclipse.emf.common.notify.AdapterFactory; | |
import org.eclipse.emf.common.notify.Notification; | |
import org.eclipse.emf.common.util.ResourceLocator; | |
import org.eclipse.emf.common.util.URI; | |
import org.eclipse.emf.common.util.UniqueEList; | |
import org.eclipse.emf.ecore.EClass; | |
import org.eclipse.emf.ecore.EObject; | |
import org.eclipse.emf.ecore.EStructuralFeature; | |
import org.eclipse.emf.ecore.resource.Resource; | |
import org.eclipse.emf.edit.command.AddCommand; | |
import org.eclipse.emf.edit.command.CommandParameter; | |
import org.eclipse.emf.edit.command.CreateChildCommand; | |
import org.eclipse.emf.edit.command.MoveCommand; | |
import org.eclipse.emf.edit.command.RemoveCommand; | |
import org.eclipse.emf.edit.domain.EditingDomain; | |
import org.eclipse.emf.edit.provider.IChildCreationExtender; | |
import org.eclipse.emf.edit.provider.ViewerNotification; | |
import org.eclipse.emf.edit.provider.resource.ResourceItemProvider; | |
/** | |
* @author Xavier Maysonnave | |
*/ | |
public class FcoreResourceItemProvider extends ResourceItemProvider { | |
protected ResourceChildCreationExtenderManager _resourceExtenderManager; | |
protected Collection<EClass> _roots; | |
/** | |
* This constructs an instance from a factory and a notifier. | |
*/ | |
public FcoreResourceItemProvider(AdapterFactory adapterFactory, ResourceChildCreationExtenderManager resourceExtenderManager) { | |
super(adapterFactory); | |
_resourceExtenderManager = resourceExtenderManager; | |
} | |
public Collection<EClass> getRoots() { | |
if (_roots == null) { | |
_roots = new UniqueEList<EClass>(); | |
_roots.add(FcorePackage.Literals.FACTORY_COMPONENT); | |
// Add roots defined by extenders | |
_roots.addAll(_resourceExtenderManager.getRoots()); | |
} | |
return _roots; | |
} | |
@Override | |
public Collection<?> getNewChildDescriptors(Object object, EditingDomain editingDomain, Object sibling) { | |
// Resource | |
FcoreResourceImpl resource = (FcoreResourceImpl) object; | |
// Build the collection of new child descriptors. | |
Collection<Object> newChildDescriptors = new ArrayList<Object>(); | |
collectNewChildDescriptors(newChildDescriptors, object); | |
// Add child descriptors contributed by extenders. | |
if (adapterFactory instanceof IChildCreationExtender) { | |
newChildDescriptors.addAll(((IChildCreationExtender) adapterFactory).getNewChildDescriptors(object, editingDomain)); | |
} | |
// If a sibling has been specified, add the best index possible to each CommandParameter. | |
if (sibling != null) { | |
// Unwrap | |
sibling = unwrap(sibling); | |
// Find the index of the sibling. | |
Collection<EObject> children = resource.getContents(); | |
// For each CommandParameter with a non-null, multi-valued structural feature... | |
int i = 0; | |
DESCRIPTORS_LOOP: for (Object descriptor : newChildDescriptors) { | |
if (descriptor instanceof CommandParameter) { | |
CommandParameter parameter = (CommandParameter) descriptor; | |
// Look for the sibling value or an equivalent in the new child's feature. | |
// If it is found, the child should immediately follow it. | |
i = 0; | |
for (Object innerObject : children) { | |
if (isEquivalentValue(sibling, innerObject)) { | |
parameter.index = i + 1; | |
continue DESCRIPTORS_LOOP; | |
} | |
++i; | |
} | |
} | |
} | |
} | |
return newChildDescriptors; | |
} | |
/** | |
* This adds to <code>newChildDescriptors</code>, a collection of new child | |
* descriptors. Typically, {@link org.eclipse.emf.edit.command.CommandParameter}s | |
* will be used as descriptors. This implementation adds nothing to the | |
* collection, but derived classes should override this method, invoking the | |
* superclass implementation and then adding to the collection. | |
*/ | |
@Override | |
protected void collectNewChildDescriptors(Collection<Object> newChildDescriptors, Object object) { | |
newChildDescriptors.add(createChildParameter(FcorePackage.Literals.FACTORY_COMPONENT, FcoreFactory.eINSTANCE.createFactoryComponent())); | |
} | |
/** | |
* This is a convenience method that creates a <code>CommandParameter</code> | |
* for a given parent feature and child object. | |
*/ | |
@Override | |
protected CommandParameter createChildParameter(Object feature, Object child) { | |
return new CommandParameter(null, feature, child); | |
} | |
/** | |
* This returns the label text for the adapted class. | |
*/ | |
@Override | |
public String getText(Object object) { | |
Resource resource = (Resource) object; | |
StringBuffer buffer = new StringBuffer(resource.getURI() == null ? "" : URI.decode(resource.getURI().toString())); //$NON-NLS-1$ | |
if (resource instanceof IPlatformFcoreProvider) { | |
IPlatformFcore fcore = ((IPlatformFcoreProvider) resource).getIPlatformFcore(); | |
if (fcore != null) { | |
IPlatformBundle platformBundle = fcore.getPlatformBundle(); | |
if (platformBundle.isTarget()) | |
buffer.append(" [Target]"); //$NON-NLS-1$ | |
else if (platformBundle.isRuntime()) | |
buffer.append(" [Runtime]"); //$NON-NLS-1$ | |
else | |
buffer.append(" [Workspace]"); //$NON-NLS-1$ | |
buffer.append(" ["); //$NON-NLS-1$ | |
buffer.append(platformBundle.getInstallLocation()); | |
buffer.append("]"); //$NON-NLS-1$ | |
} | |
} | |
return buffer.toString(); | |
} | |
/** | |
* This returns Fcore.gif. | |
*/ | |
@Override | |
public Object getImage(Object object) { | |
return URI.createURI(EGFModelEditPlugin.INSTANCE.getPluginResourceLocator().getImage("full/obj16/Fcore").toString()); //$NON-NLS-1$ | |
} | |
/** | |
* Return the resource locator for this item provider's resources. | |
*/ | |
@Override | |
public ResourceLocator getResourceLocator() { | |
return ((IChildCreationExtender) adapterFactory).getResourceLocator(); | |
} | |
/** | |
* This implements delegated command creation for the given object. | |
*/ | |
@Override | |
public Command createCommand(Object object, EditingDomain domain, Class<? extends Command> commandClass, CommandParameter commandParameter) { | |
// Commands should operate on the values, not their wrappers. If the command's values needed to be unwrapped, | |
// we'll back get a new CommandParameter. | |
CommandParameter oldCommandParameter = commandParameter; | |
commandParameter = unwrapCommandValues(commandParameter, commandClass); | |
Command result = UnexecutableCommand.INSTANCE; | |
if (commandParameter.owner instanceof FcoreResourceImpl) { | |
if (commandClass == RemoveCommand.class) { | |
result = createRemoveCommand(domain, (FcoreResourceImpl) commandParameter.owner, commandParameter.getCollection()); | |
} else if (commandClass == AddCommand.class) { | |
result = createAddCommand(domain, (FcoreResourceImpl) commandParameter.owner, commandParameter.getCollection(), commandParameter.getIndex()); | |
} else if (commandClass == MoveCommand.class) { | |
result = createMoveCommand(domain, (FcoreResourceImpl) commandParameter.owner, commandParameter.getValue(), commandParameter.getIndex()); | |
} else if (commandClass == CreateChildCommand.class) { | |
CommandParameter newChildParameter = (CommandParameter) commandParameter.getValue(); | |
result = createCreateChildCommand(domain, (FcoreResourceImpl) commandParameter.owner, newChildParameter.getEStructuralFeature(), newChildParameter.getValue(), newChildParameter.getIndex(), commandParameter.getCollection()); | |
} else { | |
return super.createCommand(object, domain, commandClass, commandParameter); | |
} | |
} else { | |
return super.createCommand(object, domain, commandClass, commandParameter); | |
} | |
// If necessary, get a command that replaces unwrapped values by their wrappers in the result and affected objects. | |
return wrapCommand(result, object, commandClass, commandParameter, oldCommandParameter); | |
} | |
/** | |
* This creates a primitive {@link org.eclipse.emf.edit.command.RemoveCommand}. | |
*/ | |
protected Command createRemoveCommand(EditingDomain domain, FcoreResourceImpl resource, Collection<?> collection) { | |
CompoundCommand removeCommand = new CompoundCommand(CompoundCommand.MERGE_COMMAND_ALL); | |
removeCommand.append(new ResourceRemoveCommand(domain, resource, collection)); | |
for (Object object : collection) { | |
EObject eObject = (EObject) object; | |
if (eObject.eContents().isEmpty() == false) { | |
removeCommand.append(domain.createCommand(RemoveCommand.class, new CommandParameter(eObject, null, eObject.eContents()))); | |
} | |
} | |
return removeCommand; | |
} | |
/** | |
* This creates a primitive {@link org.eclipse.emf.edit.command.AddCommand}. | |
*/ | |
protected Command createAddCommand(EditingDomain domain, FcoreResourceImpl resource, Collection<?> collection, int index) { | |
Collection<EClass> roots = getRoots(); | |
if (collection != null) { | |
for (Object object : collection) { | |
if (object instanceof EObject) { | |
EObject eObject = (EObject) object; | |
if (roots.contains(EMFHelper.solveAgainstStaticPackage(eObject.eClass())) == false) { | |
return UnexecutableCommand.INSTANCE; | |
} | |
} | |
} | |
return new FcoreResourceAddCommand(domain, resource, collection, index); | |
} | |
return UnexecutableCommand.INSTANCE; | |
} | |
/** | |
* This creates a primitive {@link org.eclipse.emf.edit.command.MoveCommand}. | |
*/ | |
protected Command createMoveCommand(EditingDomain domain, FcoreResourceImpl resource, Object value, int index) { | |
if (value instanceof EObject) { | |
Collection<EClass> roots = getRoots(); | |
EObject eObject = (EObject) value; | |
if (roots.contains(EMFHelper.solveAgainstStaticPackage(eObject.eClass()))) { | |
return new ResourceMoveCommand(domain, resource, value, index); | |
} | |
} | |
return UnexecutableCommand.INSTANCE; | |
} | |
/** | |
* This creates a primitive {@link org.eclipse.emf.edit.command.CreateChildCommand}. | |
*/ | |
protected Command createCreateChildCommand(EditingDomain domain, FcoreResourceImpl resource, EStructuralFeature feature, Object value, int index, Collection<?> collection) { | |
if (collection != null && collection.size() == 1) { | |
Object object = collection.iterator().next(); | |
if (object instanceof EObject) { | |
Collection<EClass> roots = getRoots(); | |
EObject eObject = (EObject) object; | |
if (roots.contains(EMFHelper.solveAgainstStaticPackage(eObject.eClass()))) { | |
return new ResourceFeatureAddCommand(domain, resource, feature, value, resource.getContents().indexOf(eObject) == CommandParameter.NO_INDEX ? CommandParameter.NO_INDEX : resource.getContents().indexOf(eObject) + 1); | |
} | |
} | |
} | |
return UnexecutableCommand.INSTANCE; | |
} | |
/** | |
* This handles notification by calling {@link #fireNotifyChanged(Notification) fireNotifyChanged}. | |
*/ | |
@Override | |
public void notifyChanged(Notification notification) { | |
switch (notification.getFeatureID(Resource.class)) { | |
case Resource.RESOURCE__URI: | |
// case Resource.RESOURCE__IS_MODIFIED: | |
// case Resource.RESOURCE__IS_TRACKING_MODIFICATION: | |
// case Resource.RESOURCE__RESOURCE_SET: | |
{ | |
fireNotifyChanged(new ViewerNotification(notification, notification.getNotifier(), false, true)); | |
return; | |
} | |
case Resource.RESOURCE__IS_LOADED: | |
case Resource.RESOURCE__CONTENTS: { | |
fireNotifyChanged(new ViewerNotification(notification, notification.getNotifier(), true, false)); | |
return; | |
} | |
} | |
super.notifyChanged(notification); | |
} | |
} |