blob: b915f0ae05ec9c25db9468330ab46546f2386782 [file] [log] [blame]
//------------------------------------------------------------------------------
// 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;
}
}