| //------------------------------------------------------------------------------ |
| // Copyright (c) 2005, 2006 IBM Corporation and others. |
| // 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: |
| // IBM Corporation - initial implementation |
| //------------------------------------------------------------------------------ |
| package org.eclipse.epf.library.edit.command; |
| |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| |
| import org.eclipse.emf.common.command.AbstractCommand; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.epf.library.edit.ui.UserInteractionHelper; |
| import org.eclipse.epf.library.edit.util.Misc; |
| import org.eclipse.epf.library.edit.util.TngUtil; |
| import org.eclipse.epf.uma.ContentCategory; |
| import org.eclipse.epf.uma.ContentPackage; |
| import org.eclipse.epf.uma.CustomCategory; |
| import org.eclipse.epf.uma.MethodElement; |
| import org.eclipse.epf.uma.MethodPlugin; |
| import org.eclipse.epf.uma.UmaFactory; |
| import org.eclipse.epf.uma.VariabilityType; |
| import org.eclipse.epf.uma.ecore.impl.MultiResourceEObject; |
| import org.eclipse.epf.uma.ecore.util.OppositeFeature; |
| import org.eclipse.epf.uma.util.UmaUtil; |
| |
| /** |
| * This command is used to assign a method element to a category. If the category |
| * is in a base method plug-in of the element, this command will automatically |
| * create a contributor to the base category and assign the element to the |
| * contributing category. This is avoids modifying the base method plug-in. |
| * |
| * @author Phong Nguyen Le |
| * @since 1.0 |
| */ |
| public class AddToCategoryCommand extends AbstractCommand implements |
| IResourceAwareCommand { |
| |
| private ContentCategory category; |
| |
| private EStructuralFeature feature; |
| |
| private MethodElement element; |
| |
| private String[] categoryPkgPath; |
| |
| private boolean checkForExistingContributor; |
| |
| private ContentCategory usedCategory = null; |
| |
| private boolean createNewContributor = false; |
| |
| private ContentPackage categoryPkg; |
| |
| private Collection<Resource> modifiedResources; |
| |
| private Object oldOppositeFeatureValue; |
| |
| private List usedCategories; |
| |
| public AddToCategoryCommand(ContentCategory category, |
| MethodElement element, EStructuralFeature feature, |
| String[] categoryPkgPath, boolean checkForExistingContributor, |
| List usedCategories) { |
| this.category = category; |
| this.feature = feature; |
| this.element = element; |
| this.categoryPkgPath = categoryPkgPath; |
| this.checkForExistingContributor = checkForExistingContributor; |
| this.usedCategories = usedCategories; |
| } |
| |
| protected boolean prepare() { |
| // check if this operation will modify the element in opposite feature |
| // value |
| // |
| return UserInteractionHelper.checkModifyOpposite(category, feature, |
| element); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.emf.common.command.AbstractCommand#getLabel() |
| */ |
| public String getLabel() { |
| return "Add To Category"; //$NON-NLS-1$ |
| } |
| |
| private void prepareCategory() { |
| // create contributor for category if it is not in the same plugin with |
| // the element |
| // |
| MethodPlugin elementPlugin = UmaUtil.getMethodPlugin(element); |
| MethodPlugin categoryPlugin = UmaUtil.getMethodPlugin(category); |
| if (categoryPlugin != elementPlugin |
| && Misc.isBaseOf(categoryPlugin, elementPlugin, |
| new HashMap<String, Boolean>())) { |
| if (category.getVariabilityBasedOnElement() != null) { |
| throw new IllegalArgumentException( |
| "Could not add element to an extended category that is in a different plug-in: " + category); //$NON-NLS-1$ |
| } |
| if (!feature.isMany()) { |
| throw new UnsupportedOperationException(); |
| } |
| categoryPkg = UmaUtil.findContentPackage(elementPlugin, |
| categoryPkgPath); |
| ContentCategory contrib = null; |
| if (checkForExistingContributor) { |
| // look for the existing contributor for the category |
| // |
| contrib = TngUtil.findContributor(categoryPkg, category); |
| } |
| |
| if (contrib == null) { |
| createNewContributor = true; |
| } else { |
| usedCategory = contrib; |
| } |
| } else { |
| usedCategory = category; |
| } |
| } |
| |
| public void execute() { |
| prepareCategory(); |
| |
| modifiedResources = new HashSet<Resource>(); |
| |
| redo(); |
| } |
| |
| public void redo() { |
| if (createNewContributor) { |
| ContentCategory contrib = (ContentCategory) UmaFactory.eINSTANCE |
| .create(category.eClass()); |
| contrib.setVariabilityBasedOnElement(category); |
| contrib.setVariabilityType(VariabilityType.CONTRIBUTES); |
| categoryPkg.getContentElements().add(contrib); |
| usedCategory = contrib; |
| if (usedCategory instanceof CustomCategory) { |
| CustomCategory root = TngUtil.getRootCustomCategory(UmaUtil |
| .getMethodPlugin(usedCategory)); |
| List list = root.getCategorizedElements(); |
| list.add(usedCategory); |
| TngUtil.setDefaultName(root, (CustomCategory)usedCategory, category.getName()); |
| } else { |
| usedCategory.setName(category.getName()); |
| } |
| // set presentation name empty for new contributors |
| usedCategory.setPresentationName(""); |
| } |
| OppositeFeature oppositeFeature = OppositeFeature |
| .getOppositeFeature(feature); |
| MultiResourceEObject mrEObj = (MultiResourceEObject) element; |
| oldOppositeFeatureValue = mrEObj.getOppositeFeatureMap().get( |
| oppositeFeature); |
| if (feature.isMany()) { |
| Collection collection = (Collection) usedCategory.eGet(feature); |
| if (oldOppositeFeatureValue != null && !oppositeFeature.isMany()) { |
| if (oldOppositeFeatureValue != usedCategory) { |
| EObject oldOppVal = (EObject) oldOppositeFeatureValue; |
| ((Collection) oldOppVal.eGet(feature)).remove(element); |
| if (oldOppVal.eResource() != null) { |
| modifiedResources.add(oldOppVal.eResource()); |
| } |
| |
| collection.add(element); |
| } |
| } |
| if (!collection.contains(element)) { |
| collection.add(element); |
| } |
| } else { |
| if (oldOppositeFeatureValue != null && !oppositeFeature.isMany()) { |
| if (oldOppositeFeatureValue != usedCategory) { |
| EObject oldOppVal = (EObject) oldOppositeFeatureValue; |
| oldOppVal.eSet(feature, null); |
| if (oldOppVal.eResource() != null) { |
| modifiedResources.add(oldOppVal.eResource()); |
| } |
| } |
| } |
| if (usedCategory != oldOppositeFeatureValue) { |
| usedCategory.eSet(feature, element); |
| } |
| } |
| |
| if (usedCategory.eResource() != null) { |
| modifiedResources.add(usedCategory.eResource()); |
| } |
| if (usedCategories.contains(category)) { |
| usedCategories.remove(category); |
| } |
| } |
| |
| public void undo() { |
| OppositeFeature oppositeFeature = OppositeFeature |
| .getOppositeFeature(feature); |
| if (feature.isMany()) { |
| Collection collection = (Collection) usedCategory.eGet(feature); |
| collection.remove(element); |
| } else { |
| usedCategory.eSet(feature, null); |
| } |
| |
| // restore old value of the single-value opposite feature |
| // |
| if (!oppositeFeature.isMany() && oldOppositeFeatureValue != null |
| && oldOppositeFeatureValue != usedCategory) { |
| EObject oldOppVal = (EObject) oldOppositeFeatureValue; |
| if (feature.isMany()) { |
| ((Collection) oldOppVal.eGet(feature)).add(element); |
| } else { |
| oldOppVal.eSet(feature, element); |
| } |
| } |
| |
| if (createNewContributor) { |
| if (TngUtil.isEmpty(usedCategory)) { |
| MethodPlugin usedCategoryPlugin = UmaUtil.getMethodPlugin(usedCategory); |
| EcoreUtil.remove(usedCategory); |
| if (usedCategory instanceof CustomCategory) { |
| TngUtil.getRootCustomCategory(usedCategoryPlugin) |
| .getCategorizedElements().remove(usedCategory); |
| } |
| usedCategory = null; |
| } |
| } |
| if (!usedCategories.contains(category)) { |
| usedCategories.add(category); |
| } |
| |
| } |
| |
| public Collection<?> getAffectedObjects() { |
| return Collections.singletonList(usedCategory); |
| } |
| |
| public Collection<Resource> getModifiedResources() { |
| |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=146662 |
| // Below adding category's resource to modifiedResources is needed, |
| // because before executing command, need to verify if resource is mutable or not |
| // getModifiedResources() called before executing actual execute() in few cases. |
| // Useful in special cases like if resource is in version control. |
| // |
| if(modifiedResources == null) { |
| modifiedResources = new HashSet<Resource>(); |
| prepareCategory(); |
| if(usedCategory != null && usedCategory.eResource() != null) { |
| modifiedResources.add(usedCategory.eResource()); |
| } |
| if(createNewContributor && usedCategory == null && element != null) { |
| MethodPlugin plugin = UmaUtil.getMethodPlugin(element); |
| if(plugin != null && plugin.eResource() != null) { |
| modifiedResources.add(plugin.eResource()); |
| } |
| } |
| } |
| |
| if (modifiedResources == null) { |
| return Collections.emptyList(); |
| } |
| return modifiedResources; |
| } |
| |
| } |