blob: 8086cedde8b6b0065ab4e2e51482ad2a571c4f63 [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.layout.elements;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.epf.common.utils.FileUtil;
import org.eclipse.epf.common.utils.NetUtil;
import org.eclipse.epf.common.utils.StrUtil;
import org.eclipse.epf.library.ILibraryResourceManager;
import org.eclipse.epf.library.LibraryPlugin;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.configuration.ConfigurationHelper;
import org.eclipse.epf.library.configuration.ElementRealizer;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.library.layout.ElementLayoutManager;
import org.eclipse.epf.library.layout.ElementPropertyProviderManager;
import org.eclipse.epf.library.layout.IElementLayout;
import org.eclipse.epf.library.layout.LayoutInfo;
import org.eclipse.epf.library.layout.LayoutResources;
import org.eclipse.epf.library.layout.util.XmlElement;
import org.eclipse.epf.library.persistence.ILibraryResourceSet;
import org.eclipse.epf.library.util.LibraryUtil;
import org.eclipse.epf.library.util.ResourceHelper;
import org.eclipse.epf.persistence.MultiFileXMISaveImpl;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.BreakdownElement;
import org.eclipse.epf.uma.Checklist;
import org.eclipse.epf.uma.Concept;
import org.eclipse.epf.uma.ContentDescription;
import org.eclipse.epf.uma.ContentElement;
import org.eclipse.epf.uma.CustomCategory;
import org.eclipse.epf.uma.DescribableElement;
import org.eclipse.epf.uma.Descriptor;
import org.eclipse.epf.uma.Example;
import org.eclipse.epf.uma.Guideline;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodElementProperty;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.ReusableAsset;
import org.eclipse.epf.uma.Roadmap;
import org.eclipse.epf.uma.Role;
import org.eclipse.epf.uma.SupportingMaterial;
import org.eclipse.epf.uma.Task;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.VariabilityElement;
import org.eclipse.epf.uma.VariabilityType;
import org.eclipse.epf.uma.Whitepaper;
import org.eclipse.epf.uma.WorkOrder;
import org.eclipse.epf.uma.WorkProduct;
import org.eclipse.epf.uma.WorkProductDescriptor;
import org.eclipse.epf.uma.ecore.util.OppositeFeature;
import org.eclipse.epf.uma.util.AssociationHelper;
import org.eclipse.epf.uma.util.UmaUtil;
/**
* The abstract layout for all Method Elements.
*
* @author Jinhua Xi
* @author Kelvin Low
* @author Weiping Lu
* @sicne 1.0
*/
public abstract class AbstractElementLayout implements IElementLayout {
public static boolean processDescritorsNewOption = false;
public static final String TAG_REFERENCE = "reference"; //$NON-NLS-1$
public static final String TAG_REFERENCELIST = "referenceList"; //$NON-NLS-1$
protected ElementLayoutManager layoutManager;
protected MethodElement element;
protected MethodElement ownerElement;
protected String url = null;
// element element path relative to the publishing root
protected String elementPath = ""; //$NON-NLS-1$
// the back up path to reath the publishing root
protected String backPath = ""; //$NON-NLS-1$
// map of layout file to the output file extention, if the element has more
// than one layout output
protected List layouts = null;
protected MethodElement targetElement = null;
protected boolean showElementLink = true;
protected boolean debug = LibraryPlugin.getDefault().isDebugging();
public AbstractElementLayout() {
}
/**
* if the element's content is target for another element, set it here. for
* example, step content cat target for a Task or a task descriptor
* copyright content can target to different elements.
*
* The purpose of this is that the system will fix the links in the content
* to relative to the target element.
*/
public void setContentTarget(MethodElement targetElement) {
this.targetElement = targetElement;
}
/**
* need to set the owner of the current layout element. In most cases this
* should be the eContainer of the element. This is needed because in some
* situation the element does not have an owner when the object is created.
* For example, the ContentDescription object's eContiner is null if the
* content file is not saved.
*
* @param owner
* MethodElement
*/
public void setElementOwner(MethodElement owner) {
this.ownerElement = owner;
}
/**
* @deprecated
*/
public void setShowElementLink(boolean show) {
this.showElementLink = show;
}
/**
* initialize the layout with the element layout manager and the element.
* @param layoutManager ElementLayoutManager
* @param element MethodElement
*/
public abstract void init(ElementLayoutManager layoutManager,
MethodElement element);
protected void __init(ElementLayoutManager layoutManager,
MethodElement element) {
this.layoutManager = layoutManager;
this.element = element;
if (!ConfigurationHelper.isDescriptionElement(element)) {
if ( !(element instanceof MethodConfiguration) ) {
// make sure the element is loaded with the correct container
// otherwise the element may not have a valid container
// and thus the element content path can't be determined
// this is just a workaround. should we have a better way to make sure the elements are loaded correctly???????????
// 160441 - Missing template files when publish configuration
MethodPlugin plugin = LibraryUtil.getMethodPlugin(element);
if ( plugin == null || plugin.eContainer() == null) {
// this should not happen in publishing mode since the whole library is already loaded
if ( debug && getLayoutMgr().isPublishingMode() ) {
System.out.println("Error: Element without a valid container: " + LibraryUtil.getTypeName(element)); //$NON-NLS-1$
}
LibraryUtil.getMethodPlugins(LibraryService.getInstance().getCurrentMethodLibrary());
}
}
buildPath();
this.url = elementPath + getFileName(ResourceHelper.FILE_EXT_HTML);
}
// this is a workaround.
// we need to pass parameters in the file url,
// however, if the file does not exist, the parameters is not passed over in browsing
// so create a dummy file
if (!this.layoutManager.isPublishingMode() && !(
element instanceof ContentDescription
|| element.eContainer() instanceof ContentDescription
|| element instanceof MethodConfiguration) )
{
try {
String html_file = this.layoutManager.getPublishDir() + this.getFilePath() + getFileName(ResourceHelper.FILE_EXT_HTML);
File f = new File(html_file);
if ( !f.exists() )
{
f.getParentFile().mkdirs();
f.createNewFile();
}
} catch (IOException e) {
e.printStackTrace();
}
}
preloadOppositefeatures();
}
private void preloadOppositefeatures() {
// make sure the processes are loaded before calculating the feature
// otherwise the opposite feature map is not populated
// fine for publishing since the whole library is loaded already
// special handling for browsing
// load the opposite feature specifically
if ( getLayoutMgr().isPublishingMode() ) {
return;
}
//OppositeFeature of;
Resource res = element.eResource();
if ( res == null ) {
return;
}
ResourceSet resSet = res.getResourceSet();
if ( !(resSet instanceof ILibraryResourceSet) ) {
return;
}
List<OppositeFeature> oppositeFeatures = new ArrayList<OppositeFeature>();
if ( this.element instanceof Role ) {
oppositeFeatures.add(AssociationHelper.Role_RoleDescriptors);
} else if ( this.element instanceof Task ) {
oppositeFeatures.add(AssociationHelper.Task_TaskDescriptors);
} else if ( this.element instanceof WorkProduct ) {
oppositeFeatures.add(AssociationHelper.WorkProduct_WorkProductDescriptors);
} else if ( this.element instanceof Checklist ) {
oppositeFeatures.add(AssociationHelper.Checklist_BreakdownElements);
} else if ( this.element instanceof Concept || this.element instanceof Whitepaper ) {
oppositeFeatures.add(AssociationHelper.Concept_BreakdownElements);
} else if ( this.element instanceof Checklist ) {
oppositeFeatures.add(AssociationHelper.Checklist_BreakdownElements);
} else if ( this.element instanceof Example ) {
oppositeFeatures.add(AssociationHelper.Example_BreakdownElements);
} else if ( this.element instanceof Guideline ) {
oppositeFeatures.add(AssociationHelper.Guideline_BreakdownElements);
} else if ( this.element instanceof ReusableAsset ) {
oppositeFeatures.add(AssociationHelper.ReusableAsset_BreakdownElements);
} else if ( this.element instanceof Roadmap ) {
oppositeFeatures.add(AssociationHelper.Roadmap_Activites);
} else if ( this.element instanceof SupportingMaterial ) {
oppositeFeatures.add(AssociationHelper.SupportingMaterial_BreakdownElements);
}
if ( oppositeFeatures.size() > 0 ) {
ConfigurationHelper.getDelegate().loadOppositeFeatures(
(ILibraryResourceSet) resSet, oppositeFeatures, element);
}
}
protected void setLayoutInfo(LayoutInfo info) {
if (layouts == null) {
layouts = new ArrayList();
}
layouts.add(info);
}
/**
* return a list of LayoutInfo objects
*
* @return a list of LayoutInfo objects
*/
public List getLayouts() {
return layouts;
}
/**
* get layout by name
*
* @param name
* @return LayoutInfo
*/
public LayoutInfo getLayoutInfo(String name) {
if ( layouts == null || layouts.size() == 0 ) {
return null;
}
for (Iterator it = layouts.iterator(); it.hasNext(); ) {
LayoutInfo info = (LayoutInfo)it.next();
if ( info.name.equals(name) ) {
return info;
}
}
return null;
}
/**
* @see org.eclipse.epf.library.layout.IElementLayout#getLayoutMgr()
*/
public ElementLayoutManager getLayoutMgr() {
return this.layoutManager;
}
/**
* @see org.eclipse.epf.library.layout.IElementLayout#getElement()
*/
public MethodElement getElement() {
return element;
}
/**
* @see org.eclipse.epf.library.layout.IElementLayout#getType()
*/
public String getType() {
return element.getType().getName();
}
/**
* @see org.eclipse.epf.library.layout.IElementLayout#getName()
*/
public String getName() {
return element.getName();
}
/**
* @see org.eclipse.epf.library.layout.IElementLayout#getDisplayName()
*/
public String getDisplayName() {
// [Bug 196399] P-name is not inherited from its base element in an extending element
return ConfigurationHelper.getPresentationName(element, getLayoutMgr().getConfiguration());
}
/**
* @see org.eclipse.epf.library.layout.IElementLayout#getId()
*/
public String getId() {
return element.getGuid();
}
/**
* @see org.eclipse.epf.library.layout.IElementLayout#getUrl()
*/
public String getUrl() {
return url;
}
/**
* @see org.eclipse.epf.library.layout.IElementLayout#getBackPath()
*/
public String getBackPath() {
return backPath;
}
/**
* @see org.eclipse.epf.library.layout.IElementLayout#getFilePath()
*/
public String getFilePath() {
return elementPath;
}
/**
* Returns the file path relative to another element. This is the
* relativeTo.backpath + this.elementpath.
*
* @see org.eclipse.epf.library.layout.IElementLayout#getFilePath(IElementLayout)
*/
public String getFilePath(IElementLayout relativeTo) {
return relativeTo.getBackPath() + this.getFilePath();
}
/**
* Returns the file name with the given extension.
*
* @see org.eclipse.epf.library.layout.IElementLayout#getFileName(String)
*/
public String getFileName(String ext) {
return ResourceHelper.getFileName(element, ext);
}
/**
* @see org.eclipse.epf.library.layout.IElementLayout#getXslUrl()
*/
public String getXslUrl() {
if (element instanceof ContentElement) {
return LayoutResources.getXslUri(getType().toLowerCase(),
"contentelement"); //$NON-NLS-1$
} else {
return LayoutResources.getXslUri(getType().toLowerCase(), null);
}
}
private void buildPath() {
// this is <plugin>/<element type>/
elementPath = ""; //$NON-NLS-1$
backPath = "./"; //$NON-NLS-1$
if ( !(element instanceof MethodConfiguration || element instanceof MethodLibrary) )
{
String path = ResourceHelper.getElementPath(element);
if ( path != null ) {
elementPath = path.replace(File.separatorChar, '/');
backPath = ResourceHelper.getBackPath(element);
}
}
}
/**
* check if the html content generated from this xsl file needs to be scanned or not
* scan the content is for identifying element references in the content and copy over resource files
* in some cases we don't need to scan the content, for example, the activity breakdown structure
*
* @param xslUrl the xsl that html is generated from, null for the default xsl layout
* @return boolean
*/
public boolean needContentScan(String xslUrl)
{
// by default all contents are scanned
return true;
}
/**
* get the layout for a child element of this element
* ActivityElementLayout should override this method to create layout with node path
* @param child
* @return IElementLayout
*/
protected IElementLayout getChildLayout(MethodElement child)
{
return layoutManager.getLayout(child, true);
}
protected void processChild(Object feature, XmlElement parent, MethodElement e,
boolean includeReferences) {
if (e != null) {
IElementLayout l = getChildLayout(e);
if (l != null) {
// don't include the references of the refereced elements,
// otherwise, may cause deadlock
boolean isContent = (e instanceof MethodElement)
&& ConfigurationHelper
.isDescriptionElement((MethodElement) e);
if (isContent) {
if (targetElement != null) {
l.setContentTarget(targetElement);
}
l.setElementOwner(element);
}
XmlElement childXmlElement = l.getXmlElement(includeReferences);
parent.addChild(childXmlElement);
processGrandChild(feature, e, l, childXmlElement);
}
}
}
protected void processChild(Object feature, XmlElement parent, List items,
boolean includeReferences) {
if (items != null && items.size() > 0) {
for (Iterator it = items.iterator(); it.hasNext();) {
Object e = it.next();
if (e instanceof MethodElement) {
MethodElement me = (MethodElement) e;
e = ConfigurationHelper.getCalculatedElement(me,
layoutManager.getConfiguration());
if (e != null) {
IElementLayout l = getChildLayout(me);
if (l != null) {
// don't include the references of the refereced
// elements, otherwise, may cause deadlock
XmlElement childXmlElement = l.getXmlElement(ConfigurationHelper
.isDescriptionElement(me) ? true
: includeReferences);
parent.addChild(childXmlElement);
processGrandChild(feature, me, l, childXmlElement);
}
}
} else {
processNonMethodElementInProcessChild(e, feature, parent, includeReferences);
}
}
}
}
protected void processNonMethodElementInProcessChild(
Object nonMethodElementChild, Object feature, XmlElement parent,
boolean includeReferences) {
}
protected void processGrandChild(Object feature,
MethodElement childElememt, IElementLayout childLayout,
XmlElement childXmlElement) {
}
/**
* calculate the to-many references
* @param elementXml XmlElement
* @param includeReferences boolean
*/
public void calculate0nReferences(XmlElement elementXml,
boolean includeReferences) {
// referenceMap.clear();
List features = LibraryUtil.getStructuralFeatures(element);
// List properties = element.getInstanceProperties();
if (features != null) {
// get all string type attributes
for (int i = 0; i < features.size(); i++) {
EStructuralFeature feature = (EStructuralFeature) features
.get(i);
if (feature.isMany()) {
loadFeature(feature, elementXml, includeReferences);
}
}
}
}
protected XmlElement getXmlElement() {
XmlElement elementXml = new XmlElement("Element") //$NON-NLS-1$
.setAttribute("Id", getId()) //$NON-NLS-1$
.setAttribute("Type", getType()) //$NON-NLS-1$
.setAttribute("TypeName", TngUtil.getTypeText(element)) //$NON-NLS-1$
.setAttribute("Name", getName()) //$NON-NLS-1$
.setAttribute("BackPath", getBackPath()) //$NON-NLS-1$
.setAttribute("ShapeiconUrl", getShapeiconUrl()) //$NON-NLS-1$
.setAttribute("DisplayName", getDisplayName()); //$NON-NLS-1$
if ( showElementLink ) {
elementXml.setAttribute("Url", getUrl()); //$NON-NLS-1$
}
return elementXml;
}
/**
* load the attributes
* @param elementXml XmlElement
*/
public void loadAttributes(XmlElement elementXml) {
boolean isActivityAttribute = (element instanceof Activity)
|| (element instanceof ContentDescription)
&& (element.eContainer() instanceof Activity || ownerElement instanceof Activity);
List features = LibraryUtil.getStructuralFeatures(element);
// List properties = element.getInstanceProperties();
if (features != null) {
// get all string type attributes
for (int i = 0; i < features.size(); i++) {
EStructuralFeature p = (EStructuralFeature) features.get(i);
if (!(p instanceof EAttribute) ) {
continue;
}
EAttribute attrib = (EAttribute)p;
String name = p.getName();
Object value;
if (name.equals("presentationName")) //$NON-NLS-1$
{
// value = TngUtil.getPresentationName(element);
value = ConfigurationHelper.getPresentationName(element,
layoutManager.getConfiguration());
} else if( isActivityAttribute && String.class.isAssignableFrom(attrib.getEAttributeType().getInstanceClass())) {
// for activity, the way to merge attribute from base is different
value = ConfigurationHelper.getActivityStringAttribute(element, ownerElement, attrib, getLayoutMgr().getConfiguration());
} else {
value = getAttributeFeatureValue(p);
}
// escape Brief Description into HTML entities
if (name.equals("briefDescription") && value instanceof String) { //$NON-NLS-1$
MultiFileXMISaveImpl.MyEscape myEscape = new MultiFileXMISaveImpl.MyEscape();
value = myEscape.convert((String)value);
value = StrUtil.convertNewlinesToHTML((String)value);
}
elementXml
.newChild("attribute").setAttribute("name", name).setValue((value == null) ? "" : value.toString()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
// Get the singleton of the ElementPropertyProviderManager and have it add any additional attributes as needed
ElementPropertyProviderManager.getInstance().loadAdditionalElementProperties(element, elementXml);
}
}
/**
* get the attribute feature value and merge the text, fix url referneces, etc.
* @param feature EStructuralFeature
* @return Object
*/
public Object getAttributeFeatureValue(EStructuralFeature feature) {
Object value = ConfigurationHelper.calcAttributeFeatureValue(element,
ownerElement, feature, layoutManager.getConfiguration());
// now if the target is set and is different from the element or the
// element's owner
// then fix the content
if ((targetElement != null) && (value != null)
&& (value.toString().length() > 0)) {
String contentPath = ResourceHelper
.getElementPath((element instanceof ContentDescription) ?
((ownerElement==null) ? (MethodElement) element.eContainer() : ownerElement)
: element);
String backPath = ResourceHelper
.getBackPath((targetElement instanceof ContentDescription) ? (MethodElement) targetElement
.eContainer()
: targetElement);
value = ResourceHelper.fixContentUrlPath(value.toString(),
contentPath, backPath);
}
return value;
}
/**
* load the copyright text
* @param elementXml XmlElement
*/
public void loadCopyright(XmlElement elementXml) {
// List items = new ArrayList();
// ConfigurationHelper.calculateCopyright(element,
// layoutManager.getConfiguration(), items);
// if ( items.size() > 0 )
// {
// SupportingMaterial copyright;
// StringBuffer copyrights = new StringBuffer();
// for ( Iterator it = items.iterator(); it.hasNext(); )
// {
// copyright = (SupportingMaterial) it.next();
// String statement = copyright.getPresentation().getMainDescription();
//
// // 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);
// copyrights.append(statement);
// }
//
// elementXml.newChild("copyright").setValue(copyrights.toString());
// //$NON-NLS-1$
// }
String copyright = ConfigurationHelper.getCopyrightText(element,
layoutManager.getConfiguration());
if (copyright != null && copyright.length() > 0) {
elementXml.newChild("copyright").setValue(copyright); //$NON-NLS-1$
}
}
/**
* calculate the to-one reference
* @param elementXml XmlElement
* @param includeReferences boolean
*/
public void calculate01References(XmlElement elementXml,
boolean includeReferences) {
List features = LibraryUtil.getStructuralFeatures(element);
// List properties = element.getInstanceProperties();
if (features != null) {
// get element references
for (int i = 0; i < features.size(); i++) {
EStructuralFeature p = (EStructuralFeature) features.get(i);
// Object value = element.get(i);
EClassifier type = p.getEType();
if (!(type instanceof EClass) || p.isMany()) {
continue;
}
loadFeature(p, elementXml, includeReferences);
}
}
}
/**
* load the non-attribute feature
*
* @param feature
* @param elementXml
* @param includeReferences
*/
public void loadFeature(EStructuralFeature feature, XmlElement elementXml,
boolean includeReferences) {
getFeatureValue(feature, elementXml, includeReferences);
}
/**
* load the non-attribute feature
*
* @param feature
* @param elementXml
* @param includeReferences
*/
public Object getFeatureValue(EStructuralFeature feature, XmlElement elementXml,
boolean includeReferences) {
if (!(feature.getEType() instanceof EClass)) {
return null;
}
String name = feature.getName();
if (!feature.isMany()) {
MethodElement e = ConfigurationHelper.calc01FeatureValue(element, ownerElement,
feature, layoutManager.getElementRealizer());
// Browsing stops working when a role is set to
// replaced another role
// for replacer, the base will be evaluated to the replacer
// and causing deadlock
if (e != null && e != element) {
boolean showDetail = (ConfigurationHelper
.isDescriptionElement(e)
/*
* || (p ==
* UmaPackage.eINSTANCE.getMethodUnit_CopyrightStatement())
*/) ? true : includeReferences;
if ( acceptFeatureValue(feature, e) ) {
if ( elementXml != null ) {
processChild(feature, elementXml
.newChild(TAG_REFERENCE).setAttribute("name", name), e, showDetail); //$NON-NLS-1$
}
return e;
} else {
return null;
}
}
} else if (feature.isMany()) {
List pv = calc0nFeatureValue(element, ownerElement, feature,
layoutManager.getElementRealizer());
if ( acceptFeatureValue(feature, pv) ) {
if ( elementXml != null ) {
addReferences(feature, elementXml, name, pv);
}
return pv;
} else {
return null;
}
}
return null;
}
protected List calc0nFeatureValue(MethodElement element, MethodElement ownerElement,
EStructuralFeature feature, ElementRealizer realizer) {
return ConfigurationHelper.calc0nFeatureValue(element, ownerElement, feature,
layoutManager.getElementRealizer());
}
/**
* load the non-attribute feature
*
* @param feature
* @param elementXml
* @param includeReferences
*/
public void loadFeature(OppositeFeature feature, XmlElement elementXml,
boolean includeReferences) {
String name = feature.getName();
if (!feature.isMany()) {
MethodElement e = ConfigurationHelper.calc01FeatureValue(element,
feature, layoutManager.getElementRealizer());
// Browsing stops working when a role is set to
// replaced another role
// for replacer, the base will be evaluated to the replacer
// and causing deadlock
if (e != null && e != element) {
boolean showDetail = (ConfigurationHelper
.isDescriptionElement(e)
/*
* || (p ==
* UmaPackage.eINSTANCE.getMethodUnit_CopyrightStatement())
*/) ? true : includeReferences;
if ( acceptFeatureValue(feature, e) )
{
processChild(feature,
elementXml
.newChild(TAG_REFERENCE).setAttribute("name", name), e, showDetail); //$NON-NLS-1$
}
}
} else if (feature.isMany()) {
List pv = calc0nFeatureValue(element, feature,
layoutManager.getElementRealizer());
if ( acceptFeatureValue(feature, pv) && pv.size() > 0) {
addReferences(feature, elementXml, name, pv);
}
}
}
protected List calc0nFeatureValue(MethodElement element,
OppositeFeature feature, ElementRealizer realizer) {
return ConfigurationHelper.calc0nFeatureValue(element, feature,
layoutManager.getElementRealizer());
}
/**
* load references for the element
* @param elementXml XmlElement
* @param includeReferences boolean
*/
public void loadReferences(XmlElement elementXml, boolean includeReferences) {
List features = LibraryUtil.getStructuralFeatures(element);
// List properties = element.getInstanceProperties();
if (features != null) {
for (int i = 0; i < features.size(); i++) {
EStructuralFeature feature = (EStructuralFeature) features
.get(i);
if (feature.getEType() instanceof EClass) {
loadFeature(feature, elementXml, includeReferences);
}
}
}
Collection oppositeProperties = new ArrayList(element.getOppositeFeatures());
for (Iterator z= oppositeProperties.iterator(); z.hasNext(); )
{
OppositeFeature ofeature = (OppositeFeature) z.next();
loadFeature(ofeature, elementXml, includeReferences);
}
//elementXml.setAttribute("ShowFullMethodContent", (layoutManager.getValidator().showExtraInfoForDescriptors()) ? "true" : "false");
}
/**
* add the reference layout to the result
* @param feature Object
* @param elementXml XmlElement
* @param referenceName String
* @param element MethodElement
*/
public void addReference(Object feature, XmlElement elementXml, String referenceName,
MethodElement element) {
processChild(feature,
elementXml
.newChild(TAG_REFERENCE).setAttribute("name", referenceName), element, false); //$NON-NLS-1$
}
/**
* add references to the layout
* @param feature
* @param elementXml
* @param referenceName
* @param items
*/
public void addReferences(Object feature, XmlElement elementXml, String referenceName,
List items) {
processChild(feature,
elementXml
.newChild(TAG_REFERENCELIST).setAttribute("name", referenceName), items, false); //$NON-NLS-1$
}
/**
* @see org.eclipse.epf.library.layout.IElementLayout#getXmlElement(boolean)
*/
public XmlElement getXmlElement(boolean includeReferences) {
XmlElement elementXml = getXmlElement();
// load the references
if (includeReferences) {
// load the copyright info
loadCopyright(elementXml);
// load the attributes
loadAttributes(elementXml);
loadReferences(elementXml, false);
}
return elementXml;
}
/**
* some layout need to have the feature values for further processing. So
* this method will be called when a feature is calculated in this abstract
* class
*
* @param name
* @param value
*/
protected boolean acceptFeatureValue(EStructuralFeature feature, Object value) {
return true;
}
protected boolean acceptFeatureValue(OppositeFeature feature, Object value) {
if ( feature == AssociationHelper.DescribableElement_CustomCategories) {
if ( value instanceof CustomCategory ) {
return getPublishCategoryProperty((MethodElement)value);
} else if ( value instanceof List) {
List items = (List)value;
int i = 0;
while ( i < items.size() ) {
MethodElement e = (MethodElement)items.get(i);
if ( !getPublishCategoryProperty(e) ) {
items.remove(i);
} else {
i++;
}
}
return true;
}
}
return true;
}
private boolean getPublishCategoryProperty(MethodElement e) {
MethodElementProperty prop = TngUtil.getPublishCategoryProperty(e);
if ( prop == null ) {
return false;
}
String v = prop.getValue();
if ( v == null || !v.toString().equals("true") ) { //$NON-NLS-1$
return false;
}
return true;
}
/**
* @see org.eclipse.epf.library.layout.IElementLayout#getShapeiconUrl()
*/
public String getShapeiconUrl() {
URI uri = null;
String imageUrl;
// String imageFile;
VariabilityElement uriInheritingBase = null;
if (element instanceof DescribableElement) {
uri = ((DescribableElement) element).getShapeicon();
if (uri == null && element instanceof VariabilityElement) {
VariabilityElement[] uriInheritingBases = new VariabilityElement[1];
uri = ConfigurationHelper.getInheritingUri(
(DescribableElement) element, uri, uriInheritingBases,
getLayoutMgr().getConfiguration(), 1);
uriInheritingBase = uriInheritingBases[0];
}
}
MethodElement element1 = uriInheritingBase == null ? element : uriInheritingBase;
ILibraryResourceManager resMgr = ResourceHelper.getResourceMgr(element1);
if (uri == null || resMgr == null ) {
imageUrl = getDefaultShapeiconUrl();
} else {
imageUrl = NetUtil.decodedFileUrl(uri.toString());
}
// need to copy the image file if it's not in the default directory
if (!imageUrl.startsWith("images/")) //$NON-NLS-1$
{
// From EPF 1.2, shapeIcon/nodeIcon stores uri relative to plugin path.
// Below section of code is necessary to append plugin name to shapeIcon/nodeIcon uri.
MethodPlugin plugin = UmaUtil.getMethodPlugin(element1);
if(plugin != null){
if(!imageUrl.startsWith(plugin.getName()) ){
// String pluginPath = ResourceHelper.getPluginPath(element);
// File file = new File(pluginPath + File.separator+ imageUrl);
// imageUrl = NetUtil.encodeFileURL(FileUtil.getRelativePath(file,
// new File(libRoot)));
imageUrl = NetUtil.encodeFileURL(plugin.getName() + "/" + imageUrl); //$NON-NLS-1$
}
}
if ( resMgr != null ) {
// need decoded URL for file ops
String decodedImageUrl = NetUtil.decodedFileUrl(imageUrl);
File source = new File(resMgr.resolve(element1, decodedImageUrl));
File dest = new File(getLayoutMgr().getPublishDir(), decodedImageUrl);
FileUtil.copyFile(source, dest);
}
}
return imageUrl;
}
/**
* @see org.eclipse.epf.library.layout.IElementLayout#getNodeiconUrl()
*/
public String getNodeiconUrl() {
return ""; //$NON-NLS-1$
}
public String getDefaultShapeiconUrl() {
return LayoutResources.getDefaultShapeiconUrl(element.getType()
.getName().toLowerCase());
}
/**
* @see org.eclipse.epf.library.layout.IElementLayout#getDiagramiconUrl()
*/
public String getDiagramiconUrl() {
return "icons/" + element.getType().getName() + ".gif"; //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* this is a shared method to load the work order of the work breakdown
* element. will be used by all work breakdown elemnt layout.
*
* @param elementXml
* XmlElement the parent xml element to load the work order
* layout
*/
protected void loadWorkOrder(XmlElement elementXml) {
EStructuralFeature feature = UmaPackage.eINSTANCE
.getWorkBreakdownElement_LinkToPredecessor();
List items = ConfigurationHelper.calc0nFeatureValue(element, feature,
layoutManager.getElementRealizer());
XmlElement predecessorXml = elementXml
.newChild(TAG_REFERENCELIST).setAttribute("name", feature.getName()); //$NON-NLS-1$
if (items != null && items.size() > 0) {
for (Iterator it = items.iterator(); it.hasNext();) {
WorkOrder wo = (WorkOrder) it.next();
MethodElement me = (MethodElement) ConfigurationHelper
.calc01FeatureValue(wo, UmaPackage.eINSTANCE
.getWorkOrder_Pred(), layoutManager
.getElementRealizer());
if (me != null) {
IElementLayout l = getChildLayout(me);
if (l != null) {
predecessorXml.addChild(l.getXmlElement(false));
}
}
}
}
}
/**
* show the descriptors of the method element
* @param descriptors
*/
protected void processDescriptors(XmlElement elementXml) {
// 180583 - Pub options to allow adding (when publishing) all descriptors under a method element in form of their path
if ( !getLayoutMgr().getValidator().showRelatedDescriptors() ) {
return;
}
// show the role descriptors referencing this role
OppositeFeature of = null;
if ( this.element instanceof Role ) {
of = AssociationHelper.Role_RoleDescriptors;
} else if ( this.element instanceof Task ) {
of = AssociationHelper.Task_TaskDescriptors;
} else if ( this.element instanceof WorkProduct ) {
of = AssociationHelper.WorkProduct_WorkProductDescriptors;
}
List descriptors = ConfigurationHelper.calc0nFeatureValue(
this.element, of,
layoutManager.getElementRealizer());
// create a element nodes for cescriptor list
XmlElement descListXml = elementXml.newChild(TAG_REFERENCELIST).setAttribute("name", "descriptors"); //$NON-NLS-1$ //$NON-NLS-2$
addDescriptors(descriptors, descListXml);
}
private void addDescriptors(List descriptors, XmlElement descListXml) {
for (int i = 0; i < descriptors.size(); i++ ) {
Descriptor desc = (Descriptor)descriptors.get(i);
List parents = __getSuperActivities(desc);
addDescriptor(descListXml, desc, parents, true);
}
}
private void addDescriptor(XmlElement descListXml, Descriptor desc, List parents, boolean topLevelCall) {
IElementLayout layout = getChildLayout(desc);
XmlElement descXml = layout.getXmlElement(false);
descListXml.addChild(descXml);
//Show entry/exist state values
if (desc instanceof WorkProductDescriptor && layout instanceof AbstractElementLayout) {
AbstractElementLayout aLayout = (AbstractElementLayout) layout;
EAttribute att;
String value;
att = UmaPackage.eINSTANCE.getWorkProductDescriptor_ActivityEntryState();
value = (String) aLayout.getAttributeFeatureValue(att);
if (value != null && value.length() > 0) {
descXml
.newChild("attribute").setAttribute(att.getName(), value); //$NON-NLS-1$
}
att = UmaPackage.eINSTANCE.getWorkProductDescriptor_ActivityExitState();
value = (String) aLayout.getAttributeFeatureValue(att);
if (value != null && value.length() > 0) {
descXml
.newChild("attribute").setAttribute(att.getName(), value); //$NON-NLS-1$
}
}
boolean toProcessExtendedActs = processDescritorsNewOption
&& topLevelCall;
Set<Activity> processedExtendedActSet = null;
Set<Activity> allLocalActSet = null;
if (toProcessExtendedActs) {
processedExtendedActSet = new HashSet<Activity>();
allLocalActSet = getAllLocalActSet(parents);
}
// List parents = __getSuperActivities(desc);
for (int p = 0; p < parents.size(); p++) {
Activity act = (Activity) parents.get(p);
layout = getChildLayout(act);
XmlElement actXml = layout.getXmlElement(false);
descXml.addChild(actXml);
if (toProcessExtendedActs) {
processExtendedAct(desc, descListXml, parents, p, act,
processedExtendedActSet, allLocalActSet);
}
}
}
private Set getAllLocalActSet(List<Activity> bases) {
MethodConfiguration config = getLayoutMgr().getConfiguration();
Set ret = new HashSet<Activity>();
for (Activity act: bases) {
ret.addAll(ConfigurationHelper.getLocalContributersAndReplacers(act, config));
}
return ret;
}
private void processExtendedAct(Descriptor desc, XmlElement descListXml,
List parents, int p, Activity act,
Set<Activity> processedExtendedActSet,
Set<Activity> allLocalActSet) {
MethodConfiguration config = getLayoutMgr().getConfiguration();
List actExtenders = ConfigurationHelper.getExtenders(act, config);
if (!actExtenders.isEmpty()) {
for (Object obj : actExtenders) {
Activity extAct = (Activity) obj;
if (processedExtendedActSet.contains(extAct)) {
continue;
}
processedExtendedActSet.add(extAct);
List<Activity> extenderParents = __getSuperActivities(extAct);
extenderParents.add(extAct);
boolean toAdd = true;
if (p < parents.size() - 1) {
Activity superAct = extAct;
for (int pp = p + 1; pp < parents.size(); pp++) {
Activity parent = (Activity) parents.get(pp);
parent = checkLocalAct(allLocalActSet, superAct, parent);
if (parent != null) {
extenderParents.add(parent);
} else {
toAdd = false;
break;
}
}
}
if (toAdd) {
addDescriptor(descListXml, desc, extenderParents, false);
}
}
}
}
//1. return locally contributing act if superAct has a BE locally contributing to parent
//2. return null if if superAct has a BE locally replacing parent
//3. return parent otherwise
private Activity checkLocalAct(Set<Activity> allLocalActSet, Activity superAct,
Activity parent) {
for (BreakdownElement be : superAct
.getBreakdownElements()) {
if (be instanceof Activity) {
Activity actBe = (Activity) be;
if (allLocalActSet.contains(be) &&
parent == actBe.getVariabilityBasedOnElement()) {
if (actBe.getVariabilityType() == VariabilityType.LOCAL_REPLACEMENT) {
return null;
}
if (actBe.getVariabilityType() == VariabilityType.LOCAL_CONTRIBUTION) {
return actBe;
}
}
}
}
return parent;
}
private List __getSuperActivities(BreakdownElement element) {
List items = new ArrayList();
// build the parent nodes
BreakdownElement parent = element.getSuperActivities();
while ( parent != null ) {
// need to realize the activity, so that we get the correct link and parent links
// 204745 - wrong process usage path for contributing activities
parent = (BreakdownElement)ConfigurationHelper.getCalculatedElement(parent, layoutManager.getElementRealizer());
if ( parent == null ) {
break;
}
items.add(0, parent);
if (LibraryUtil.isProcess(parent) ) {
break;
}
parent = parent.getSuperActivities();
}
return items;
}
protected boolean isBreakdownElement_Guidances(EStructuralFeature feature) {
UmaPackage umaPkg = UmaPackage.eINSTANCE;
if (feature == umaPkg.getBreakdownElement_Checklists()) {
return true;
}
if (feature == umaPkg.getBreakdownElement_Concepts()) {
return true;
}
if (feature == umaPkg.getBreakdownElement_Examples()) {
return true;
}
if (feature == umaPkg.getBreakdownElement_Guidelines()) {
return true;
}
if (feature == umaPkg.getBreakdownElement_ReusableAssets()) {
return true;
}
if (feature == umaPkg.getBreakdownElement_SupportingMaterials()) {
return true;
}
return false;
}
}