blob: a59e8e26c4eb7542b92f6f13d68e7df1dd523121 [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.configuration;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.epf.library.ILibraryManager;
import org.eclipse.epf.library.LibraryPlugin;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.LibraryServiceUtil;
import org.eclipse.epf.library.edit.util.CategorySortHelper;
import org.eclipse.epf.library.edit.util.SectionList;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.library.util.LibraryUtil;
import org.eclipse.epf.library.util.ResourceHelper;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.Artifact;
import org.eclipse.epf.uma.CapabilityPattern;
import org.eclipse.epf.uma.ContentCategory;
import org.eclipse.epf.uma.ContentDescription;
import org.eclipse.epf.uma.ContentElement;
import org.eclipse.epf.uma.CustomCategory;
import org.eclipse.epf.uma.DeliveryProcess;
import org.eclipse.epf.uma.DescribableElement;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.epf.uma.MethodPackage;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.Practice;
import org.eclipse.epf.uma.ProcessComponent;
import org.eclipse.epf.uma.ProcessPackage;
import org.eclipse.epf.uma.Role;
import org.eclipse.epf.uma.RoleDescriptor;
import org.eclipse.epf.uma.SupportingMaterial;
import org.eclipse.epf.uma.Task;
import org.eclipse.epf.uma.TaskDescriptor;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.VariabilityElement;
import org.eclipse.epf.uma.VariabilityType;
import org.eclipse.epf.uma.WorkProduct;
import org.eclipse.epf.uma.WorkProductDescriptor;
import org.eclipse.epf.uma.ecore.impl.MultiResourceEObject;
import org.eclipse.epf.uma.ecore.util.OppositeFeature;
import org.eclipse.epf.uma.util.AssociationHelper;
/**
* @author Jinhua Xi
* @author Phong Nguyen Le
* @since 1.0
*/
public class ConfigurationHelper {
public static final String ATTRIBUTE_VALUE_SEPERATOR = "<p/>"; //$NON-NLS-1$
private static boolean debug = LibraryPlugin.getDefault().isDebugging();
/**
* check if the element is a ContentDescription
*
* @param element {@link MethodElement}
* @return boolean
*/
public static boolean isDescriptionElement(MethodElement element) {
if ( element == null ) {
return false;
}
return (element instanceof ContentDescription || element.eContainer() instanceof ContentDescription);
}
/**
* check if the method pacj=kage is a global package
*
* @param pkg {@link MethodPackage}
* @return boolean
*/
public static boolean isGlobalPackage(MethodPackage pkg) {
if (pkg == null) {
if (debug) {
System.out
.println("ConfigurationHelper.isGlobalPackage: method package is null"); //$NON-NLS-1$
}
return false;
}
MethodPlugin p = LibraryUtil.getMethodPlugin(pkg);
if (p == null) {
if (debug) {
System.out
.println("ConfigurationHelper.isGlobalPackage: Unable to find method plug-in for " + pkg.getName() + ": " + pkg.getGuid()); //$NON-NLS-1$ //$NON-NLS-2$
}
return false;
}
return TngUtil.getAllSystemPackages(p).contains(pkg);
}
/**
* check if the element is in the configuration
*
* @param element
* @param config
* @return
*/
public static boolean inConfig(MethodElement element,
MethodConfiguration config) {
return inConfig(element, config, true);
}
/**
* check if the element is in the configuration
*
* @param element
* @param config
* @return
*/
public static boolean inConfig(MethodElement element,
MethodConfiguration config, boolean checkSubtracted) {
if (!isOwnerSelected(element, config, checkSubtracted)) {
return false;
}
// if the element is a repalcer, and it's base element has more than one
// replacer
// none of the replacers should be included into the configuration
if (element instanceof VariabilityElement) {
VariabilityElement ve = (VariabilityElement) element;
if (isReplacer(ve)) {
VariabilityElement base = ve.getVariabilityBasedOnElement();
if (inConfig(base, config)) {
// // Invalid hotspot created for locally replaced activity in activity diagram
// // this is because the activity has more than one local replacers
// // in version 7.0, local replacement is modeled the same way as nomal replacement
// // we need to ignore this checking for activity
// if ( element instanceof Activity ) {
// return true;
// }
for (Iterator it = AssociationHelper.getImmediateVarieties(
base).iterator(); it.hasNext();) {
VariabilityElement e = (VariabilityElement) it.next();
if ((e != element)
&& (e.getVariabilityType() == VariabilityType.REPLACES_LITERAL)
&& isOwnerSelected(e, config, checkSubtracted)) {
if (debug) {
System.out
.println("ConfigurationHelper.inConfig: Ignoring replacing element '" + LibraryUtil.getTypeName(element) + "' since its base element has more than one replacer in the configuration"); //$NON-NLS-1$ //$NON-NLS-2$
}
return false;
}
}
} else {
return false; // base must be in the configuration
}
}
}
return true;
}
private static boolean isOwnerSelected(MethodElement element,
MethodConfiguration config, boolean checkSubtracted) {
if (ConfigurationData.active) {
MethodLibrary library = LibraryServiceUtil.getMethodLibrary(config);
ILibraryManager libraryManager = library == null? null : LibraryService.getInstance().getLibraryManager(library);
if (libraryManager != null) {
return LibraryService.getInstance()
.getConfigurationManager(config)
.getConfigurationData()
.isOwnerSelected(element, checkSubtracted);
}
}
if (element == null) {
return false;
}
if (config == null || isDescriptionElement(element)) {
return true;
}
// since UMA 1.0.4, configuration can have added categories
// and subtracted categories. The order of filtering is:
// 1. any element in the subtracted categories should be excluded
// 2. any element in the added categories should be included
// 3. any element not in the selected package or plugin should be excluded.
if ( checkSubtracted ) {
// first check subtracted elements
List subtractedCategories = config.getSubtractedCategory();
if ( subtractedCategories.size() > 0 ) {
for ( Iterator it = subtractedCategories.iterator(); it.hasNext(); ) {
ContentCategory cc = (ContentCategory)it.next();
if ( cc == element ) {
return false;
}
// need to check all content category types and sub-categories
// we need to have an efficient algorithm for this checking.
// for now, only check the custom category's categorised elements
// TODO. Jinhua Xi, 11/27/2006
if ( cc instanceof CustomCategory ) {
if ( ((CustomCategory)cc).getCategorizedElements().contains(element) ) {
return false;
}
} else {
// TODO, not implemented yet
System.out.println("TODO, isOwnerSelected: not implemented yet");
}
}
}
}
// then check added categories
// TODO
// elements beyond configuration scope should be always visible
if ((element instanceof MethodLibrary)
|| (element instanceof MethodConfiguration)) {
return true;
} else if (element instanceof MethodPlugin) {
List plugins = config.getMethodPluginSelection();
return (plugins != null) && plugins.contains(element);
} else {
// if the ownerprocess can't show, can't accept
if (element instanceof Activity) {
Activity base = (Activity) ((Activity) element)
.getVariabilityBasedOnElement();
if (base != null && base != element) {
MethodElement owningProc = TngUtil.getOwningProcess(base);
if ( owningProc != null && owningProc != element
&& !inConfig(owningProc, config, checkSubtracted)) {
return false;
}
}
}
EObject pkg = LibraryUtil.getSelectable(element);
// accept global package if the plugin is in the configuration
if (pkg instanceof MethodPackage
&& isGlobalPackage((MethodPackage) pkg)) {
MethodPlugin plugin = LibraryUtil.getMethodPlugin(pkg);
return inConfig(plugin, config, checkSubtracted);
}
List pkgs = config.getMethodPackageSelection();
if (pkgs == null) {
return false;
}
// per Phong's request, for ProcessPackage, check the
// ProcessComponent parent instead
if (pkg instanceof ProcessPackage) {
while ((pkg != null) && !(pkg instanceof ProcessComponent)
&& !pkgs.contains(pkg)) {
pkg = pkg.eContainer();
}
}
// if package not selected, return false
if ((pkg == null) || !pkgs.contains(pkg)) {
return false;
}
return true;
}
}
/**
* is the element a contributor?
* @param element
* @return boolean
*/
public static boolean isContributor(VariabilityElement element) {
if (element == null || element.getVariabilityBasedOnElement() == null)
return false;
return element.getVariabilityType() == VariabilityType.CONTRIBUTES_LITERAL;
}
/**
* is the element a replacer?
* @param element
* @return boolean
*/
public static boolean isReplacer(VariabilityElement element) {
if (element == null || element.getVariabilityBasedOnElement() == null)
return false;
return element.getVariabilityType() == VariabilityType.REPLACES_LITERAL;
}
/**
* is the element a extend-replacer?
* @param element
* @return boolean
*/
public static boolean isExtendReplacer(VariabilityElement element) {
if (element == null || element.getVariabilityBasedOnElement() == null)
return false;
return element.getVariabilityType() == VariabilityType.EXTENDS_REPLACES_LITERAL;
}
/**
* is the element an extender?
* @param element
* @return boolean
*/
public static boolean isExtender(VariabilityElement element) {
if (element == null || element.getVariabilityBasedOnElement() == null)
return false;
return element.getVariabilityType() == VariabilityType.EXTENDS_LITERAL;
}
/**
* get the replacer of the element in the configuration. Only one replacer
* is allowed. If more than one replacer is found, then none of them will be
* returned.
*
* @param element
* VariabilityElement the element
* @param config
* MethodConfiguration
* @return VariabilityElement the replacer if there is one and ONLY one,
* null otherwise
*/
public static VariabilityElement getReplacer(VariabilityElement element,
MethodConfiguration config) {
VariabilityElement ve = null;
// this will get all replacers recursively. we only need the immediate
// ones
// for(Iterator iterator = TngUtil.getGeneralizers(element,
// VariabilityType.REPLACES_LITERAL); iterator.hasNext();)
for (Iterator it = AssociationHelper.getImmediateVarieties(element)
.iterator(); it.hasNext();) {
VariabilityElement e = (VariabilityElement) it.next();
if ( e == null || !inConfig(e, config) ) {
continue;
}
VariabilityType type = e.getVariabilityType();
if ( type == VariabilityType.REPLACES_LITERAL
|| type == VariabilityType.EXTENDS_REPLACES_LITERAL) {
if (ve != null) {
if (debug) {
System.out
.println("ConfigurationHelper.getReplacer: Replacer ignored for element '" + LibraryUtil.getTypeName(element) + "' since it has more than one replacerin the configuration"); //$NON-NLS-1$ //$NON-NLS-2$
}
return null; // if more than one replacer, return null
}
ve = e;
}
}
return ve;
}
/**
* get the immediate contributors of the element within the configuration.
* If a contributor has immediate replacer, it is repalced with the replacer
*
* @param element
* @param config
* @return
*/
public static List getContributors(VariabilityElement element,
MethodConfiguration config) {
List items = new ArrayList();
if ( element == null ) {
return items;
}
// This method get all contributors recursively,
// we only need the first level
// for (Iterator it = TngUtil.getContributors(element); it.hasNext(); )
for (Iterator it = AssociationHelper.getImmediateVarieties(element)
.iterator(); it.hasNext();) {
VariabilityElement e = (VariabilityElement) it.next();
if ((e != null)
&& (e.getVariabilityType() == VariabilityType.CONTRIBUTES_LITERAL)
&& inConfig(e, config)) {
VariabilityElement replacer = getReplacer(e, config);
if (replacer != null) {
items.add(replacer);
} else {
items.add(e);
}
}
}
return items;
}
public static boolean canShow(MethodElement element,
MethodConfiguration config) {
return canShow(element,config, true);
}
/**
* element can't show in the configuration tree if 1. the element is not in
* the configuration 2. the element is a contribution to another element 3.
* if the element is a replacer to a 3. the element has a replacement
* element in the configuration
*
* @param element
* @param config
* @return boolean
*/
public static boolean canShow(MethodElement element,
MethodConfiguration config, boolean checkSubtracted) {
if (element == null) {
return false;
}
if (!inConfig(element, config, checkSubtracted)) {
return false;
}
// // if it;s an activity, return since contributors are local contribution and needs to be shown
// if (element instanceof Activity) {
// return true;
// }
// /////////////////////////////////////////////////////////////////////////////////////////////////
// // this is not needed any more since the suppression state is determined by the activity adaptor factory
// // just leave it here for now since it does not hurt. take it away in next release
// Boolean supressed = element.getSuppressed();
// if (supressed != null && supressed.booleanValue() == true) {
// return false;
// }
// /////////////////////////////////////////////////////////////////////////////////////////////////
if (element instanceof VariabilityElement) {
VariabilityElement e = (VariabilityElement) element;
// if this is an extender, always show, even though it extends a
// contributor
if (isExtender(e)) {
return true;
}
if (isContributor(e) || getReplacer(e, config) != null) {
return false;
}
// for activity, don't show the ones that contains contributors
// the resaon for this is to simplify the logic.
// assuming that user uses this activity to contribute to other activities
// so that part should not be involved in the navigation
//
// Jinhua Xi, 07/14/06,
if ( (e instanceof Activity) && hasContributor((Activity)e) ) {
return false;
}
while ((e != null) && isReplacer(e)) {
e = (VariabilityElement) e.getVariabilityBasedOnElement();
if (isContributor(e)) {
return false;
}
}
}
return true;
}
/**
* get the name of the element in the configuration. 1. if it's a
* contributor, show the name of the base element 2. if it has a
* replacemenet, show the name of the replacement element
*
* @param element
* @param config
* @return String
*/
public static String getName(MethodElement element,
MethodConfiguration config) {
if (element instanceof VariabilityElement) {
VariabilityElement e = (VariabilityElement) element;
if (isContributor(e)) {
return getName(e.getVariabilityBasedOnElement(), config);
} else {
VariabilityElement rep = getReplacer(e, config);
if (rep != null) {
return getName(rep, config);
}
}
}
return element.getName();
}
/**
* get the presentation name for an element in the configuration
* @param element
* @param config
* @return String
*/
public static String getPresentationName(MethodElement element,
MethodConfiguration config) {
String name = (String) ConfigurationHelper.calcAttributeFeatureValue(
element, UmaPackage.eINSTANCE
.getDescribableElement_PresentationName(), config);
if (name == null || name.length() == 0) {
name = TngUtil.getPresentationName(element);
}
return name;
}
/**
* get the variability element owner. If the element is a
* VariabilityElement, return itself otherwise, find it's owner. For
* example, a ContentDescriotion object is ownered by a VariabilityElement
*
* @param e
* MethodElement
* @return VariabilityElement
*/
public static VariabilityElement getVariableOwner(MethodElement e) {
if (e instanceof VariabilityElement) {
return (VariabilityElement) e;
} else if (e instanceof ContentDescription) {
// return AssociationHelper.getOwner( (ContentDescription)e );
EObject eObj = e.eContainer();
if (eObj instanceof VariabilityElement) {
return (VariabilityElement) eObj;
}
}
return null;
}
/**
* check if the feature value is mergable or not
* @param feature
* @return boolean
*/
public static boolean isMergableAttribute(EStructuralFeature feature) {
if (!feature.getEType().getInstanceClassName().equals(
"java.lang.String")) //$NON-NLS-1$
{
return false;
}
// feature id is not globally unique, can't do a switch here
// compare the acture featrue instead
/*
* switch ( feature.getFeatureID() ) { case
* UmaPackage.METHOD_ELEMENT__GUID: case
* UmaPackage.METHOD_ELEMENT__NAME:
* Contributing a Unique ID for work product renders
* bad html // don't merge Unique ID: case
* UmaPackage.WORK_PRODUCT_DESCRIPTION__EXTERNAL_ID: return false; }
*/
if (feature == UmaPackage.eINSTANCE.getMethodElement_Guid()
|| feature == UmaPackage.eINSTANCE.getNamedElement_Name()
|| feature == UmaPackage.eINSTANCE
.getWorkProductDescription_ExternalId()
|| feature == UmaPackage.eINSTANCE.getDescribableElement_PresentationName()) {
return false;
}
return true;
}
/**
* is attribute feature value?
* @param feature
* @return boolean
*/
public static boolean isAttributeFeature(EStructuralFeature feature) {
return (feature.getEType() instanceof EAttribute);
}
/**
* is this a to-one feature?
* @param feature
* @return boolean
*/
public static boolean is01Feature(EStructuralFeature feature) {
return (feature.getEType() instanceof EClass) && !feature.isMany();
}
/**
* is this a to-many feature?
* @param feature
* @return boolean
*/
public static boolean is0nFeature(EStructuralFeature feature) {
return (feature.getEType() instanceof EClass) && feature.isMany();
}
/**
* calculate the value of the specified element and feature
*
* @param element
* @param feature
* @param config
* @param values
* The List of values of the feature. if the feature is a 0..1
* association, the List holds a single value if any for
* reference list feature, it's a list of references for
* attribute feature, it's a list of attribute values to be
* mergered for 0..1 association, the list may contain 1 value.
*/
// private static void calculateFeature(MethodElement element,
// EStructuralFeature feature, MethodConfiguration config,
// List values, ElementRealizer realizer) {
// calculateFeature(element, null, feature, config, values, realizer);
// }
private static void calculateFeature(MethodElement element,
MethodElement OwnerElement, EStructuralFeature feature,
MethodConfiguration config, FeatureValue values, ElementRealizer realizer) {
// make sure this is a valid feature
// for example, if an activity contributes to a Capability Pattern,
// some CapabilityPattern specific feature may not be a valid feature for the Activity
List features = element.getInstanceProperties();
if ( !features.contains(feature) ) {
return;
}
// EClassifier type = feature.getEType();
VariabilityElement ve = getVariableOwner((OwnerElement == null) ? element
: OwnerElement);
Object value = element.eGet(feature);
values.add(ve, value);
// if (is0nFeature(feature)) {
// if (value instanceof List) {
// for (Iterator it = ((List) value).iterator(); it.hasNext();) {
// MethodElement e = (MethodElement) it.next();
// // MethodElement ce = getCalculatedElement(e, config,
// // resolveContributor);
// MethodElement ce = realizer.realize(e);
//
// // calculated element can be null if it can't show
// if (ce != null && !values.contains(ce)) {
// values.add(ce);
// }
// }
// }
// } else if (value != null) {
// if (is01Feature(feature)) {
// // Rule: Outgoint to-one associations of contributor will be
// // ignored
// // if the base already has such an association
// // question: how about more than one contributors with the same
// // associations?
// // pick the first one?
// if (isContributor(ve)) {
// // no such association in the base, then add this one
// // if already have, maybe from another contributor, ignore
// // the rest
// if (values.size() == 0) {
// values.add(value);
// }
// } else {
// values.clear();
// values.add(value);
// }
// } else {
// // attribute merge
// if (!(value instanceof String)
// || value.toString().trim().length() > 0) {
// values.add(new FeatureValue(element, value));
// }
// }
// }
if (config == null) {
return;
}
// realize the variability relationship
if (ve == null) {
return;
}
// if ((ve instanceof ContentElement)
// && (feature == UmaPackage.eINSTANCE
// .getContentDescription_Sections())) {
// orderSections((ContentElement) ve, values);
// }
// // if mergable feature
// // presentation name doesn't take contribution
// // Processes: Contribution on extended activity is updating base activity's properties
// // activity contribution is a local contribution based on extend
// // should not be treated as contributor,
// boolean mergeable = !((element instanceof Activity)
// || (OwnerElement instanceof Activity) && (element instanceof ContentDescription)
// || (element.eContainer() instanceof Activity));
boolean mergeable = true;
if ( isAttributeFeature(feature) && !isMergableAttribute(feature) ) {
mergeable = false;
}
if ( mergeable ) {
// if the element has contributors in the configuration, get the
// reference properties
// if a contributor has replacer, it's replacer is used
List items = getContributors(ve, config);
if (items != null && items.size() > 0) {
for (Iterator it = items.iterator(); it.hasNext();) {
MethodElement e = (MethodElement) it.next();
MethodElement o = e; // the owner
// if the current element is a description,
// get the the description object of the contributor
if (element instanceof ContentDescription) {
e = ((DescribableElement) e).getPresentation();
}
calculateFeature(e, o, feature, config, values, realizer);
}
}
}
// if the element is an extended element, get the base element's
// properties if needed
boolean extendReplace = isExtendReplacer(ve) ||
ElementRealizer.isExtendReplaceEnabled() && isReplacer(ve);
boolean isExtender = isExtender(ve);
if (isExtender || extendReplace) {
boolean mergebase = false;
if (is0nFeature(feature)) {
mergebase = true;
if ( extendReplace
|| isExtender && ElementRealizer.ignoreBaseToManyAssociations()) {
mergebase = (values.size() == 0);
}
} else if (is01Feature(feature)) {
mergebase = (values.size() == 0);
} else {
mergebase = (isMergableAttribute(feature) && (values.size() == 0));
}
if (mergebase) {
// Authoring: Extending a base that has been
// replaced, does not extend the replacement
// need to get the realized element,
// the base element might be replaced by another one,
// or might be a contributor to another base
MethodElement e = ve.getVariabilityBasedOnElement();
if ( !extendReplace ) {
e= getCalculatedElement(e, config);
}
MethodElement o = e;
// if it's a containment feature, such as sub-artifacts
// the base should not be the container
// 162154 - Check circular references with parent-/sub-artifacts and practices/sub-practices
if ( isContainmentFeature(feature) ) {
List containers = getContainers(ve, config);
if (containers.contains(e) ) {
mergebase = false;
}
}
if (mergebase && (ve != e) && inConfig(e, config)) {
// if the current element is a description,
// get the the description object of the base
if (element instanceof ContentDescription) {
try {
e = ((DescribableElement) e).getPresentation();
} catch (Exception e1) {
e1.printStackTrace();
}
}
calculateFeature(e, o, feature, config, values, realizer);
// for extender, we need to re-sort the steps based on the
// extender defined order
if ((ve instanceof ContentElement)
&& (feature == UmaPackage.eINSTANCE
.getContentDescription_Sections())) {
orderSections((ContentElement) ve, (List)values.getValue());
}
}
}
}
}
/**
* calculate the reflist for the specified element and OppositeFeature
*
* @param element
* @param feature
* OppositeFeature
* @param realizer ElementRealizer
* @param values
* The List of values of the feature. for reference list feature,
* it's a list of references for attribute feature, it's a list
* of attribute values to be mergered
*/
private static void calculateOppositeFeature(MethodElement element,
OppositeFeature feature, ElementRealizer realizer, FeatureValue values) {
calculateOppositeFeature(element, feature, true, false, realizer, values);
}
/**
* calculate the reflist for the specified element and OppositeFeature
*
* @param element
* @param feature
* OppositeFeature
* @param realizer ElementRealizer
* @param values
* The List of values of the feature. for reference list feature,
* it's a list of references for attribute feature, it's a list
* of attribute values to be mergered
*/
private static void calculateOppositeFeature(MethodElement element,
OppositeFeature feature, boolean mergeReplacerBase, boolean mergeExtenderBase,
ElementRealizer realizer, FeatureValue values) {
// must be a MultiResourceEObject
if (!(element instanceof MultiResourceEObject)) {
return;
}
MethodConfiguration config = realizer.getConfiguration();
VariabilityElement ve = getVariableOwner(element);
Object value = ((MultiResourceEObject) element)
.getOppositeFeatureValue(feature);
values.add(ve, value);
if (element instanceof VariabilityElement && config != null) {
VariabilityElement ce = (VariabilityElement) element;
// if the element has contributors in the configuration, get the
// reference properties
List items = getContributors(ce, config);
if (items != null && items.size() > 0) {
for (Iterator it = items.iterator(); it.hasNext();) {
MethodElement e = (MethodElement) it.next();
calculateOppositeFeature(e, feature, mergeReplacerBase, mergeExtenderBase, realizer, values);
}
}
// if the element is a replacer of a base element,
// get the base element's properties
// only cover 01 or 0m references
// attributes can't be opposite feature
// replaced element does not show incoming
// relationships
// imcoming relationships are represented by opposite feature
// so keep the references to the base element
// Inconsistency between Published Work Product: Workload Analysis Page and Referenced Pages
// this is from the base of the extender.
// incoming associations from the base should be discarded for extenders
boolean mergebase = false;
boolean isExtender = isExtender(ce);
boolean isReplacer = isReplacer(ce);
if (isReplacer) {
mergebase = mergeReplacerBase && ((value instanceof List) || (values.size() == 0));
} else if (isExtender) {
mergebase = mergeExtenderBase;
}
if (mergebase) {
// resolve the base contributor to the base if i am not a
// replacer
// don't resolve the contributors to the base if i am a
// replacer,
// the call is coming from the base. So if resolve to base again
// will cause deadlock.
// don't resolve to the replacer since we need to carry down all
// the incoming 0n associations from base
// actually should resolve to replacer if i am not a replacer
// (i.e. i am an entender)
// this handles the senario: G2 replaces G1 and G3 extends G1
ElementRealizer realizer2 =
new DefaultElementRealizer(config, (!isReplacer), (!isReplacer));
MethodElement e = getCalculatedElement(ce
.getVariabilityBasedOnElement(), realizer2);
// if the base element resolved to null,
// this is because canShow() don't allow replaced element to show.
// we don't want to take the risk to fix ElementRealizer
// so fix here since 7.0.1_ifix1,
// Jinhua Xi, 4/17/06
if ( e == null ) {
e = ce.getVariabilityBasedOnElement();
}
if ((e != ce) && inConfig(e, config)) {
calculateOppositeFeature(e, feature, mergeReplacerBase, mergeExtenderBase, realizer, values);
}
}
}
}
/**
* calculate the elements in the list, and returns a new list of unique
* elements
*
* @param elements
* @param config
* @return List
*/
public static List getCalculatedElements(List elements,
MethodConfiguration config) {
return getCalculatedElements(elements, new DefaultElementRealizer(config) );
}
/**
* calculate the elements in the list, and returns a new list of unique
* elements
*
* @param elements
* @param realizer ElementRealizer
* @return List
*/
public static List getCalculatedElements(List elements, ElementRealizer realizer ) {
// calculate each element in the list and return a new list of elements
List values = new ArrayList();
for (Iterator it = elements.iterator(); it.hasNext();) {
MethodElement e = (MethodElement) it.next();
e = ConfigurationHelper.getCalculatedElement(e, realizer);
if ((e != null) && (!values.contains(e))) {
values.add(e);
}
}
return values;
}
/**
* calculate the element based on tle configuration. If nothing can be
* shown, return null.
*
* @param element
* @param config
* @return
*/
public static MethodElement getCalculatedElement(MethodElement element,
MethodConfiguration config) {
ElementRealizer realizer = new DefaultElementRealizer(config, true, true);
return getCalculatedElement(element, realizer);
}
public static MethodElement getCalculatedElement(MethodElement element,
ElementRealizer realizer) {
MethodElement e = element;
MethodElement e2;
while ((e2 = realizer.realize(e)) != e) {
e = e2;
}
return e;
}
/**
* get the calculated 0..1 feature value of the specipied element and
* feature
*
* @return MethodElement
*/
public static MethodElement calc01FeatureValue(MethodElement element,
EStructuralFeature feature, ElementRealizer realizer) {
return calc01FeatureValue(element, null, feature, realizer);
}
/**
* get the calculated 0..1 feature value of the specipied element and
* feature
*
* @return MethodElement
*/
public static MethodElement calc01FeatureValue(MethodElement element, MethodElement ownerElement,
EStructuralFeature feature, ElementRealizer realizer) {
// presentation object feature should never be realized. always keep
// it's own value
Object v = element.eGet(feature);
if (v instanceof ContentDescription) {
return (MethodElement) v;
}
ToOneFeatureValue values = new ToOneFeatureValue(element, ownerElement, feature, realizer);
calculateFeature(element, ownerElement, feature, realizer.getConfiguration(), values, realizer);
// if (values.size() > 0) {
// v = (MethodElement) values.get(0);
// if (v instanceof MethodElement) {
// return getCalculatedElement((MethodElement) v, realizer.getConfiguration());
// }
// }
return (MethodElement)values.getValue();
}
/**
* is this feature for containd children? such as artifact's contained artifact.
* @param feature
* @return boolean
*/
public static boolean isContainmentFeature(EStructuralFeature feature) {
return feature == UmaPackage.eINSTANCE.getArtifact_ContainedArtifacts()
|| feature == UmaPackage.eINSTANCE.getPractice_SubPractices();
}
/**
* check if the element allow contained element
* @param element
* @return boolean
*/
public static boolean isContainmentElement(Object element) {
return element instanceof Artifact || element instanceof Practice;
}
private static List getContainers(MethodElement element,
MethodConfiguration config) {
List items = new ArrayList();
EObject o = element;
while ((o != null) && ((o = o.eContainer()) != null)
&& o.getClass().isInstance(element)) {
if (o instanceof VariabilityElement) {
o = getCalculatedElement((VariabilityElement) o, config);
}
if ((o != null) && !items.contains(o)) {
items.add(o);
}
}
return items;
}
/**
* get the 01 opposite feature (if any) for the given feature. returns null
* if no such feature
*
* @param feature
* EStructuralFeature
* @return OppositeFeature the 01 opposite feature of the given feature,
* null if no such thing
*/
public static OppositeFeature get01OppositeFeature(
EStructuralFeature feature) {
// since 1.0m4, these are not 01 feature any more
// if (feature == UmaPackage.eINSTANCE.getDiscipline_Tasks()) {
// return AssociationHelper.Task_Discipline;
// } else if (feature == UmaPackage.eINSTANCE.getRole_ResponsibleFor()) {
// return AssociationHelper.WorkProduct_ResponsibleRole;
// }
// if ( feature == UmaPackage.eINSTANCE.getDomain_WorkProducts() ) {
// return AssociationHelper.WorkProduct_Domains;
// }
return null;
}
/**
* get the target feature for the opposite feature if the target feature is a to-One feature,
* otherwise, return null.
* @param oFeature
* @return EStructuralFeature
*/
public static EStructuralFeature get01Feature(OppositeFeature oFeature) {
if ( oFeature == AssociationHelper.Role_Primary_Tasks
|| oFeature == AssociationHelper.RoleDescriptor_PrimaryTaskDescriptors ) {
return oFeature.getTargetFeature();
}
return null;
}
/**
* get the calculated 0..n feature value of the specipied element, it's
* owner element and feature
*
* @param element {@link MethodElement}
* @param feature {@link EStructuralFeature}
* @param realizer {@link ElementRealizer}
* @return List a list of {@link MethodElement}
*/
public static List calc0nFeatureValue(MethodElement element,
EStructuralFeature feature, ElementRealizer realizer)
{
return calc0nFeatureValue(element, null, feature, realizer);
}
/**
* get the calculated 0..n feature value of the specipied element and
* feature. if the opposite feature on the other end is a to-one feature,
* the feature value item can't be in the value list unless it's opposite
* feature value is the current element. For example, for discipline_tasks,
* the tasks can be selected if and ONLY if the task's task_discipline
* opposite feature value is the current discipline
*
* @param element MethodElement
* @param ownerElement {@link MethodElement}
* @param feature {@link EStructuralFeature}
* @param realizer {@link ElementRealizer}
* @return List a list of {@link MethodElement}
*/
public static List calc0nFeatureValue(MethodElement element, MethodElement ownerElement,
EStructuralFeature feature, ElementRealizer realizer) {
List v = null;
MethodConfiguration config = realizer.getConfiguration();
// Wrong "modifies" information published in team allocation view for small configuration
// need to manually calculate the modify features
// can't rely on the uma model since that is not configuration specific.
// role modifies product means:
// role performs on tasks, and tasks produce workproducts as output
// so handle these scenarios as special cases
if ( element instanceof Role && feature == UmaPackage.eINSTANCE.getRole_Modifies() ) {
// List v2 = new ArrayList();
// calculateOppositeFeature(element, AssociationHelper.Role_Primary_Tasks, realizer, v2);
// if ( v2.size() > 0 ) {
// for (Iterator it = v2.iterator(); it.hasNext(); ) {
// MethodElement e = (MethodElement)it.next();
// calculateFeature(e, ownerElement, UmaPackage.eINSTANCE.getTask_Output(), config, v, realizer);
// }
// }
v = calcModifiedWorkProducts((Role)element, ownerElement, realizer);
}else if ( element instanceof RoleDescriptor && feature == UmaPackage.eINSTANCE.getRoleDescriptor_Modifies() ) {
// List v2 = new ArrayList();
// calculateOppositeFeature(element, AssociationHelper.RoleDescriptor_PrimaryTaskDescriptors, realizer, v2);
// if ( v2.size() > 0 ) {
// for (Iterator it = v2.iterator(); it.hasNext(); ) {
// MethodElement e = (MethodElement)it.next();
// calculateFeature(e, ownerElement, UmaPackage.eINSTANCE.getTaskDescriptor_Output(), config, v, realizer);
// }
// }
v = calcModifiedWorkProductDescriptors((RoleDescriptor)element, ownerElement, realizer);
} else {
ToManyFeatureValue fv = new ToManyFeatureValue(element, ownerElement, feature, realizer);
calculateFeature(element, ownerElement, feature, config, fv, realizer);
v = (List)fv.getValue();
}
List values = getCalculatedElements(v, realizer);
if (values.contains(element)) {
values.remove(element);
}
// * if the opposite feature on the other end is a to-one feature,
// * the feature value item can't be in the value list unless it's
// opposite feature value is the current element.
// * For example, for discipline_tasks, the tasks can be selected
// * if and ONLY if the task's task_discipline opposite feature value is
// the current discipline
OppositeFeature of = get01OppositeFeature(feature);
if (of != null) {
int i = 0;
while (i < values.size()) {
MethodElement o = (MethodElement) values.get(i);
// calculate it's opposite feature value, the value must be the
// given element
// otherwise, remove it
// note: don't use the current realizer
// use the default realizer since we need to realize the element in the default way
// 158924 - wrong categories in configuration view
// workaround to allow show/hide subtracted elements
DefaultElementRealizer r = new DefaultElementRealizer(config);
r.setShowSubtracted(realizer.showSubtracted());
MethodElement oo = calc01FeatureValue(o, of, r);
if (oo != element) {
values.remove(i);
} else {
i++;
}
}
}
// containment feature value should not contain the owner element or its
// parents
// for example, artifact_containedArtifacts should not be the artifact
// itself or its parents
if (isContainmentFeature(feature)) {
List containers = getContainers(element, config);
int i = 0;
while (i < values.size()) {
Object o = (Object) values.get(i);
if (o == element || containers.contains(o)) {
values.remove(i);
} else {
i++;
}
}
}
List returnList = realizer.realize(element, feature, values);
if ( element instanceof CustomCategory && feature == UmaPackage.eINSTANCE.getCustomCategory_CategorizedElements() ) {
returnList = CategorySortHelper.sortCategoryElements(element, returnList.toArray(), true);
}
// the following part might not be general to all cases
// so put it into the realizer
return returnList;
// // if the feature value is containment element such as artifact
// // the child element can't show if any of the parent(s) are in the list
// // Published site: Display of WPs under responsible role
// if (feature.isMany() && values.size() > 0
// && isContainmentElement(values.get(0))) {
// int i = 0;
// while (i < values.size()) {
// MethodElement o = (MethodElement) values.get(i);
//
// // if the container of the element is in the list, remove this
// // element from the list
// if (isContainerInList(o, values, config)) {
// values.remove(i);
// } else {
// i++;
// }
// }
// }
//
// // need to sort the concept and papers by type
// if ((feature == UmaPackage.eINSTANCE
// .getContentElement_ConceptsAndPapers())
// && (values.size() > 0)) {
// List papers = new ArrayList();
// int i = 0;
// while (i < values.size()) {
// Object o = values.get(i);
// if (o instanceof Whitepaper) {
// papers.add(o);
// values.remove(i);
// } else {
// i++;
// }
// }
//
// if (papers.size() > 0) {
// values.addAll(papers);
// }
// }
//
// return values;
}
/**
* check if the container of the element is in the list or not
*
* @param element
* @param items
* @param config
* @return
*/
public static boolean isContainerInList(MethodElement element, List items,
MethodConfiguration config) {
EObject o = element;
while ((o != null) && ((o = o.eContainer()) != null)
&& o.getClass().isInstance(element)) {
if (items.contains(o)) {
return true;
}
if (o instanceof VariabilityElement) {
o = getCalculatedElement((VariabilityElement) o, config);
}
if ((o != null) && items.contains(o)) {
return true;
}
}
return false;
}
/**
* get the calculated attribute feature value of the specipied element and
* feature
*
* @param element {@link MethodElement}
* @param feature {@link EStructuralFeature}
* @param config {@link MethodConfiguration}
* @return Object
*/
public static Object calcAttributeFeatureValue(MethodElement element,
EStructuralFeature feature, MethodConfiguration config) {
return calcAttributeFeatureValue(element, null, feature, config);
}
/**
* get the calculated attribute feature value of the specipied element and
* feature
*
* @param element MethodElement
* @param ownerElement {@link MethodElement}
* @param feature {@link EStructuralFeature}
* @param config {@link MethodConfiguration}
* @return Object
*/
public static Object calcAttributeFeatureValue(MethodElement element,
MethodElement ownerElement, EStructuralFeature feature,
MethodConfiguration config) {
if (isMergableAttribute(feature)) {
// merge the attribute values
ElementRealizer realizer = new DefaultElementRealizer(config);
AttributeFeatureValue values = new AttributeFeatureValue(element, ownerElement, feature, realizer);
calculateFeature(element, ownerElement, feature, config, values,
realizer);
// StringBuffer buffer = new StringBuffer();
// for (Iterator it = values.iterator(); it.hasNext();) {
// FeatureValue av = (FeatureValue) it.next();
// if (av.text == null || av.text.toString().length() == 0) {
// continue;
// }
//
// if (feature == UmaPackage.eINSTANCE
// .getDescribableElement_PresentationName()) {
// if (values.size() > 1) {
// // something wrong here, will not happen but put test
// // message here just in case
// if (debug) {
// System.out
// .println("ConfigurationHelper.calcAttributeFeatureValue: Presentation Name get more then one entry: " + LibraryUtil.getTypeName(element)); //$NON-NLS-1$
// }
// }
// return av.text;
// }
//
// if (buffer.length() > 0) {
// buffer.append(ATTRIBUTE_VALUE_SEPERATOR);
// }
//
// if (av.element == element) {
// buffer.append(av.text);
// } else {
// String contentPath = ResourceHelper
// .getElementPath((av.element instanceof ContentDescription) ? (MethodElement) av.element
// .eContainer()
// : av.element);
//
// String backPath = ResourceHelper
// .getBackPath((element instanceof ContentDescription) ? ((ownerElement != null) ? ownerElement
// : (MethodElement) element.eContainer())
// : element);
//
// buffer.append(ResourceHelper.fixContentUrlPath(av.text,
// contentPath, backPath));
// }
// }
//
// return buffer.toString();
return values.getValue();
}
return element.eGet(feature);
}
/**
* get the calculated 0..n opposite feature value of the specipied element
* and opposite feature
*
* @param element MethodElement
* @param feature {@link EStructuralFeature}
* @param realizer {@link ElementRealizer}
* @return List a list of {@link MethodElement}
*/
public static List calc0nFeatureValue(MethodElement element,
OppositeFeature feature, ElementRealizer realizer) {
return calc0nFeatureValue(element, feature, true, false, realizer);
}
/**
* get the calculated 0..n opposite feature value of the specipied element
* and opposite feature
*
* @param element MethodElement
* @param ownerElement {@link MethodElement}
* @param feature {@link OppositeFeature}
* @param mergeReplacerBase boolean
* @param mergeExtenderBase boolean
* @param realizer {@link ElementRealizer}
* @return List a list of {@link MethodElement}
*/
public static List calc0nFeatureValue(MethodElement element,
OppositeFeature feature, boolean mergeReplacerBase, boolean mergeExtenderBase, ElementRealizer realizer) {
ToManyOppositeFeatureValue values = new ToManyOppositeFeatureValue(element, feature, realizer);
calculateOppositeFeature(element, feature, mergeReplacerBase, mergeExtenderBase, realizer, values);
return (List)values.getValue();
}
/**
* get the calculated 0..1 feature value of the specipied element and
* opposite feature
* @param element {@link MethodElement}
* @param feature {@link OppositeFeature}
* @param realizer {@link ElementRealizer}
*
* @return MethodElement
*/
public static MethodElement calc01FeatureValue(MethodElement element,
OppositeFeature feature, ElementRealizer realizer) {
ToOneOppositeFeatureValue values = new ToOneOppositeFeatureValue(element, feature, realizer);
calculateOppositeFeature(element, feature, realizer, values);
// if (values.size() > 0) {
// return getCalculatedElement((MethodElement) values.get(0), realizer);
// }
//
// return null;
return (MethodElement)values.getValue();
}
/**
* order the sections
*
* @param element {@link ContentElement}
* @param values {@link List}
*/
public static void orderSections(ContentElement element, List values) {
String orderingGuide = element.getOrderingGuide();
if (orderingGuide == null || orderingGuide.trim().length() == 0) {
return;
}
SectionList slist = new SectionList(element,
SectionList.STEPS_FOR_ELEMENT_AND_PARENTS);
if (isSameList(values, slist)) {
values.clear();
values.addAll(slist);
return;
}
// otherwise, need to reorder the list
OrderedListComparator comp = new OrderedListComparator(new ArrayList(
values), slist);
TreeSet s = new TreeSet(comp);
s.addAll(values);
values.clear();
values.addAll(s);
}
private static boolean isSameList(List l1, List l2) {
if (l1.size() != l2.size()) {
return false;
}
for (Iterator it = l1.iterator(); it.hasNext();) {
Object o = it.next();
if (!l2.contains(o)) {
return false;
}
}
return true;
}
/**
* calculate the copyright of the element int he configuration. Rule: 1.
* contributors' copyright statment should be merged to the base 2. extended
* element inherites the copyrights from the base 3. replacer don't inherite
* the copyrights from the base 4. copyright elements should be unique, no
* duplicate entry
*
* @param element
* @param config
* @param values
*/
private static void calculateCopyright(MethodElement element,
MethodConfiguration config, List values) {
SupportingMaterial copyright = (SupportingMaterial) getCalculatedElement(
LibraryUtil.getCopyright(element), config);
if (copyright != null && !values.contains(copyright)) {
values.add(copyright);
}
VariabilityElement ve = getVariableOwner(element);
if (ve == null) {
return;
}
if (config == null) {
return;
}
// merge copyrights of contributors
List items = getContributors(ve, config);
if (items != null && items.size() > 0) {
for (Iterator it = items.iterator(); it.hasNext();) {
MethodElement e = (MethodElement) it.next();
calculateCopyright(e, config, values);
}
}
// if the element is an extended element, get the base element's
// copyright
// the base element's copyright should appear first
if (isExtender(ve)) {
// realize the base element first.
MethodElement e = getCalculatedElement(ve
.getVariabilityBasedOnElement(), config);
if ((ve != e) && inConfig(e, config)) {
List baseItems = new ArrayList();
calculateCopyright(e, config, baseItems);
// add the base items to the begining
if (baseItems.size() > 0) {
// Authoring: Duplicate copyrights when 2
// elements with the same coyright are extending each other
// remove the duplicate ones
int i = 0;
while (i < values.size()) {
if (baseItems.contains(values.get(i))) {
values.remove(i);
} else {
i++;
}
}
values.addAll(0, baseItems);
}
}
}
}
/**
* get the copyright text
*
* @param element {@link MethodElement}
* @param config {@link MethodConfiguration}
* @return String
*/
public static String getCopyrightText(MethodElement element,
MethodConfiguration config) {
StringBuffer copyrights = new StringBuffer();
List items = new ArrayList();
ConfigurationHelper.calculateCopyright(element, config, items);
if (items.size() > 0) {
SupportingMaterial copyright;
for (Iterator it = items.iterator(); it.hasNext();) {
copyright = (SupportingMaterial) it.next();
// Contributing support material does not show
// up in copy right
// need to resolve the feature value. can't just get the value,
// it may have contributors
// String statement =
// copyright.getPresentation().getMainDescription();
//
String statement = (String) calcAttributeFeatureValue(copyright
.getPresentation(), copyright, UmaPackage.eINSTANCE
.getContentDescription_MainDescription(), config);
if (statement != null && statement.length() > 0) {
// need to fix the content for relative links.
// since the link is a relative path to the
// SupportingMaterial location,
// need to convert to relative to the current element
// so re-calcuate the back path
// jxi, 06/28/05
String contentPath = ResourceHelper
.getElementPath(copyright);
String backPath = ResourceHelper.getBackPath(element);
statement = ResourceHelper.fixContentUrlPath(statement,
contentPath, backPath);
if (copyrights.length() > 0) {
copyrights.append("<p/>"); //$NON-NLS-1$
}
copyrights.append(statement);
}
}
}
return copyrights.toString();
}
/**
* Gets String attribute values of an activity
*
* @param e Activity or it's ContentDescription
* @param attrib
* @param config
* @return String
*/
public static String getActivityStringAttribute(MethodElement e, MethodElement ownerElement,
EAttribute attrib, MethodConfiguration config) {
if(!String.class.isAssignableFrom(attrib.getEAttributeType().getInstanceClass())) {
throw new IllegalArgumentException("The specified attribute is not of type String: " + attrib); //$NON-NLS-1$
}
Object str = null;
boolean isDesc;
VariabilityElement ve;
if ( e instanceof ContentDescription )
{
ve = (VariabilityElement) e.eContainer();
if ( ve == null ) {
ve = (VariabilityElement)ownerElement;
}
isDesc = true;
}
else if ( e instanceof VariabilityElement)
{
ve = (VariabilityElement)e;
isDesc = false;
} else {
str = e.eGet(attrib);
return (str==null) ? "" : str.toString();
}
if(attrib == UmaPackage.eINSTANCE.getMethodElement_Guid() || attrib == UmaPackage.eINSTANCE.getNamedElement_Name()) {
return (String)e.eGet(attrib);
}
VariabilityElement base = ve.getVariabilityBasedOnElement();
VariabilityType variabilityType = ve.getVariabilityType();
if( base != null && variabilityType == VariabilityType.LOCAL_CONTRIBUTION_LITERAL) {
// for local contribution, append the text to the base
Object strBase;
if ( isDesc ) {
str = ((DescribableElement)ve).getPresentation().eGet(attrib);
strBase = calcAttributeFeatureValue( ((DescribableElement)base).getPresentation(), base, attrib, config);
} else {
str = ve.eGet(attrib);
strBase = calcAttributeFeatureValue(base, null, attrib, config);
}
if ( strBase != null && strBase.toString().length() > 0 ) {
if ( str != null && str.toString().length() > 0 ) {
str = strBase + ATTRIBUTE_VALUE_SEPERATOR + str;
} else {
str = strBase;
}
}
} else {
str = calcAttributeFeatureValue(e, ve, attrib, config);
}
return (str==null) ? "" : str.toString();
// List values = new ArrayList();
// VariabilityElement base;
// VariabilityType variabilityType;
// boolean concat = attrib != UmaPackage.eINSTANCE.getDescribableElement_PresentationName();
// while(true) {
// base = ve.getVariabilityBasedOnElement();
// if(base == null) {
// Object str;
// if ( isDesc ) {
// str = ((DescribableElement)ve).getPresentation().eGet(attrib);
// } else {
// str = ve.eGet(attrib);
// }
// if(str == null || str.toString().length() == 0) {
// if(values.isEmpty()) {
// values.add(str);
// }
// }
// else {
// values.add(0, str);
// }
// break;
// }
// else if(base instanceof Activity) {
// Object str;
// if ( isDesc ) {
// str = ((DescribableElement)ve).getPresentation().eGet(attrib);
// } else {
// str = ve.eGet(attrib);
// }
//
// variabilityType = ve.getVariabilityType();
// if(variabilityType == VariabilityType.EXTENDS_LITERAL) {
// if(str == null || str.toString().length() == 0) {
// // use the value of the base
// //
// ve = base;
// }
// else {
// values.add(0, str);
// break;
// }
// }
// else if(variabilityType == VariabilityType.LOCAL_CONTRIBUTION_LITERAL) {
// if(str != null && str.toString().length() > 0) {
// // add to the list
// //
// values.add(0, str);
// if(!concat) {
// break;
// }
// }
// // go to the base
// ve = base;
// }
// else if(variabilityType == VariabilityType.LOCAL_REPLACEMENT_LITERAL) {
// values.add(0, str);
// break;
// }
// //TODO: handle CONTRIBUTES AND REPLACES
// }
// }
//
// if ( values.size() == 0 ) {
// return ""; //$NON-NLS-1$
// }
// else if ( values.size() ==1 ) {
// return (String)values.get(0);
// }
// else {
// StringBuffer buffer = new StringBuffer();
// for (Iterator it = values.iterator(); it.hasNext(); ) {
// if ( buffer.length() > 0 ) {
// buffer.append(ATTRIBUTE_VALUE_SEPERATOR);
// }
// buffer.append(it.next());
// }
// return buffer.toString();
// }
}
/**
* get all processes in the configuration
*
* @param config
* @return List
*/
public static List getAllProcesses(MethodConfiguration config) {
List processes = new ArrayList();
List plugins = config.getMethodPluginSelection();
for (Iterator it = plugins.iterator(); it.hasNext(); ) {
List items = TngUtil.getAllProcesses((MethodPlugin)it.next());
for ( Iterator itp = items.iterator(); itp.hasNext(); ) {
org.eclipse.epf.uma.Process p = (org.eclipse.epf.uma.Process)itp.next();
if ( canShow(p, config) && !processes.contains(p) ) {
processes.add(p);
}
}
}
return processes;
}
/**
* get all processes in the plugin and the configuration
*
* @param plugin
* @param config
* @return List
*/
public static List getAllProcesses(MethodPlugin plugin, MethodConfiguration config) {
List processes = new ArrayList();
List items = TngUtil.getAllProcesses(plugin);
for ( Iterator itp = items.iterator(); itp.hasNext(); ) {
org.eclipse.epf.uma.Process p = (org.eclipse.epf.uma.Process)itp.next();
if ( canShow(p, config) && !processes.contains(p) ) {
processes.add(p);
}
}
return processes;
}
/**
* get all delivery processes in the plugin and configuration
* @param plugin
* @param config
* @return List
*/
public static List getAllDeliveryProcesses(MethodPlugin plugin, MethodConfiguration config) {
List processes = new ArrayList();
List items = TngUtil.getAllProcesses(plugin);
for ( Iterator itp = items.iterator(); itp.hasNext(); ) {
org.eclipse.epf.uma.Process p = (org.eclipse.epf.uma.Process)itp.next();
if ( p instanceof DeliveryProcess ) {
if ( canShow(p, config) && !processes.contains(p) ) {
processes.add(p);
}
}
}
return processes;
}
/**
* get all CapabilityPatterns in the plugin and configuration
*
* @param plugin
* @param config
* @return List
*/
public static List getAllCapabilityPatterns(MethodPlugin plugin, MethodConfiguration config) {
List processes = new ArrayList();
List items = TngUtil.getAllProcesses(plugin);
for ( Iterator itp = items.iterator(); itp.hasNext(); ) {
org.eclipse.epf.uma.Process p = (org.eclipse.epf.uma.Process)itp.next();
if ( p instanceof CapabilityPattern ) {
if ( canShow(p, config) && !processes.contains(p) ) {
processes.add(p);
}
}
}
return processes;
}
/**
* calculate the work products modified by the specified role, in the configuration
*
* @param element Role
* @param ownerElement MethodElement the owner to accept the calculated value
* @param realizer
* @return List list of work products being modified by the role
*/
public static List calcModifiedWorkProducts(Role element, MethodElement ownerElement, ElementRealizer realizer) {
List v = new ArrayList();
OppositeFeature ofeature = AssociationHelper.Role_Primary_Tasks;
ToManyOppositeFeatureValue fv2 = new ToManyOppositeFeatureValue(element, ofeature, realizer);
calculateOppositeFeature(element, ofeature, realizer, fv2);
if ( fv2.size() > 0 ) {
List v2 = (List)fv2.getValue();
EStructuralFeature feature = UmaPackage.eINSTANCE.getTask_Output();
for (Iterator it = v2.iterator(); it.hasNext(); ) {
MethodElement e = (MethodElement)it.next();
ToManyFeatureValue fv = new ToManyFeatureValue(element, ownerElement, feature, realizer);
((List)fv.getValue()).addAll(v);
calculateFeature(e, ownerElement,
feature,
realizer.getConfiguration(), fv, realizer);
v = (List)fv.getValue();
}
}
return v;
}
/**
* calculate the work product descriptors modified by the specified role descriptor, in the configuration
*
* @param element RoleDescriptor
* @param ownerElement MethodElement the owner to accept the calculated value
* @param realizer
* @return List list of work product descriptors being modified by the role descriptor
*/
public static List calcModifiedWorkProductDescriptors(RoleDescriptor element, MethodElement ownerElement, ElementRealizer realizer) {
List v = new ArrayList();
OppositeFeature ofeature = AssociationHelper.RoleDescriptor_PrimaryTaskDescriptors;
ToManyOppositeFeatureValue fv2 = new ToManyOppositeFeatureValue(element, ofeature, realizer);
calculateOppositeFeature(element, ofeature, realizer, fv2);
if ( fv2.size() > 0 ) {
List v2 = (List)fv2.getValue();
EStructuralFeature feature = UmaPackage.eINSTANCE.getTaskDescriptor_Output();
for (Iterator it = v2.iterator(); it.hasNext(); ) {
MethodElement e = (MethodElement)it.next();
ToManyFeatureValue fv = new ToManyFeatureValue(element, ownerElement, feature, realizer);
((List)fv.getValue()).addAll(v);
calculateFeature(e, ownerElement,
feature,
realizer.getConfiguration(), fv, realizer);
v = (List)fv.getValue();
}
}
return v;
}
/**
* calculate the roles that modifies the specified work product in the configuration
* @param element WorkProduct
* @param realizer
* @return List the roles
*/
public static List calcModifyRoles(WorkProduct element, ElementRealizer realizer) {
List tasks = ConfigurationHelper.calc0nFeatureValue(
element,
AssociationHelper.WorkProduct_OutputFrom_Tasks,
realizer);
List modifyRoles = new ArrayList();
for (Iterator it = tasks.iterator(); it.hasNext(); ) {
Task t = (Task)it.next();
Role r = (Role)ConfigurationHelper.calc01FeatureValue(
t,
UmaPackage.eINSTANCE.getTask_PerformedBy(),
realizer);
if ( (r != null) && !modifyRoles.contains(r) ) {
modifyRoles.add(r);
}
}
return modifyRoles;
}
/**
* calculate the role descriptors that modifies the specified work product descriptor in the configuration
* @param element WorkProductDescriptor
* @param realizer
* @return List the role descriptors
*/
public static List calcModifyRoleDescriptors(WorkProductDescriptor element, ElementRealizer realizer) {
List taskDescriptors = ConfigurationHelper.calc0nFeatureValue(
element,
AssociationHelper.WorkProductDescriptor_OutputFrom_TaskDescriptors,
realizer);
List modifyRoles = new ArrayList();
for (Iterator it = taskDescriptors.iterator(); it.hasNext(); ) {
TaskDescriptor t = (TaskDescriptor)it.next();
RoleDescriptor r = (RoleDescriptor)ConfigurationHelper.calc01FeatureValue(
t,
UmaPackage.eINSTANCE.getTaskDescriptor_PerformedPrimarilyBy(),
realizer);
if ( (r != null) && !modifyRoles.contains(r) ) {
modifyRoles.add(r);
}
}
return modifyRoles;
}
/**
* check if the activity is a contributor
* or contains any sub-activities that are contributors
* @param element Activity
* @return boolean
*/
public static boolean hasContributor(Activity element) {
if ( isContributor(element)) {
return true;
}
for ( Iterator it = element.getBreakdownElements().iterator(); it.hasNext(); ) {
Object o = it.next();
if ( !(o instanceof Activity) ) {
continue;
}
if ( hasContributor( (Activity)o ) ) {
return true;
}
}
return false;
}
/**
* get the base processes for an {@link Activity} in the Configuration
* @param element
* @param config
* @return List
*/
public static List getBaseProcesses(Activity element, MethodConfiguration config) {
List value = new ArrayList();
getBaseProcesses(element, config, value);
return value;
}
/**
* get all base processes for an activity in the configuration
* @param element
* @param config
* @param value List the bases processes
*/
public static void getBaseProcesses(Activity element, MethodConfiguration config, List value) {
// get it's own base
if ( ConfigurationHelper.isExtender(element) ) {
Activity base = (Activity)element.getVariabilityBasedOnElement();
if ( base != null
&& !value.contains(base)
&& (base instanceof org.eclipse.epf.uma.Process) ) {
if ( canShow(base, config) ) {
value.add(base);
}
getBaseProcesses(base, config, value);
}
}
// if the sub-activities have base, process it
for ( Iterator it = element.getBreakdownElements().iterator(); it.hasNext(); ) {
Object o = it.next();
if ( o instanceof Activity ) {
getBaseProcesses((Activity)o, config, value);
}
}
}
}