blob: c3942a51e09e56e940b2f69023848dc242362d0b [file] [log] [blame]
//------------------------------------------------------------------------------
// Copyright (c) 2005, 2008 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;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.util.InternalEList;
import org.eclipse.epf.library.configuration.ConfigurationData;
import org.eclipse.epf.library.configuration.ConfigurationHelper;
import org.eclipse.epf.library.configuration.DefaultElementRealizer;
import org.eclipse.epf.library.configuration.ElementRealizer;
import org.eclipse.epf.library.configuration.SupportingElementData;
import org.eclipse.epf.library.edit.configuration.PracticeSubgroupItemProvider;
import org.eclipse.epf.library.edit.process.ActivityWrapperItemProvider;
import org.eclipse.epf.library.edit.realization.IRealizationManager;
import org.eclipse.epf.library.edit.uma.MethodElementExt.MethodConfigurationExt;
import org.eclipse.epf.library.edit.util.LibraryEditUtil;
import org.eclipse.epf.library.edit.util.MethodConfigurationPropUtil;
import org.eclipse.epf.library.edit.util.MethodElementPropUtil;
import org.eclipse.epf.library.edit.util.MethodElementPropertyHelper;
import org.eclipse.epf.library.edit.util.PropUtil;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.library.layout.BrowsingLayoutSettings;
import org.eclipse.epf.library.layout.HtmlBuilder;
import org.eclipse.epf.library.layout.IElementLayout;
import org.eclipse.epf.library.layout.elements.AbstractElementLayout;
import org.eclipse.epf.library.layout.elements.AbstractProcessElementLayout;
import org.eclipse.epf.library.layout.elements.ElementLayoutExtender;
import org.eclipse.epf.library.layout.elements.SummaryPageLayout;
import org.eclipse.epf.library.persistence.ILibraryResourceSet;
import org.eclipse.epf.library.realization.RealizationManagerFactory;
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.BreakdownElement;
import org.eclipse.epf.uma.ContentCategory;
import org.eclipse.epf.uma.CustomCategory;
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.MethodPackage;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.Process;
import org.eclipse.epf.uma.ProcessComponent;
import org.eclipse.epf.uma.ProcessPackage;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.ecore.impl.MultiResourceEObject;
import org.eclipse.epf.uma.ecore.util.OppositeFeature;
import org.eclipse.epf.uma.util.Scope;
import org.eclipse.swt.SWT;
import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IPerspectiveListener;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
/**
* Delegate class used in ConfigurationHelper
*
* @author Weiping Lu
* @since 1.5
*/
public class ConfigHelperDelegate {
private boolean generateHtmlMode = false;
private boolean publishingMode = false;
private boolean authoringPerspective = false;
private MethodConfiguration config;
private boolean loadForBrowsingNeeded = true;
private boolean autoSyncedByBrowsing = false;
private Map<MethodElement, Set<CustomCategory>> dynamicCustomCategoriesMap;
public ConfigHelperDelegate() {
LibraryService.getInstance().addListener(libServiceListener);
IRealizationManager mgr = RealizationManagerFactory.getInstance().newRealizationManager(null);
LibraryEditUtil.getInstance().setDefaultRealizationManager(mgr);
}
protected boolean hasDynamicElements(CustomCategory cc) {
MethodElementProperty prop = MethodElementPropertyHelper.getProperty(
cc,
MethodElementPropertyHelper.CUSTOM_CATEGORY__INCLUDED_ELEMENTS);
return prop != null;
}
public void buildDynamicCustomCategoriesMap(MethodConfiguration config) {
try {
if (config == null) {
return;
}
ConfigurationHelper.getDelegate().loadUserDefinedType();
dynamicCustomCategoriesMap = new HashMap<MethodElement, Set<CustomCategory>>();
ElementRealizer realizer = DefaultElementRealizer.newElementRealizer(config);
Set<CustomCategory> set = new HashSet<CustomCategory>();
MethodElementPropUtil propUtil = MethodElementPropUtil.getMethodElementPropUtil();
for (MethodPlugin plugin : config.getMethodPluginSelection()) {
for (CustomCategory cc : TngUtil.getAllCustomCategories(plugin)) {
cc = (CustomCategory) ConfigurationHelper.getCalculatedElement(cc, realizer);
if (cc != null && hasDynamicElements(cc)) {
set.add(cc);
}
}
}
for (CustomCategory cc : set) {
for (MethodElement element : (List<MethodElement>) ConfigurationHelper
.calc0nFeatureValue(cc, UmaPackage.eINSTANCE
.getCustomCategory_CategorizedElements(), realizer)) {
Set<CustomCategory> ccSet = dynamicCustomCategoriesMap.get(element);
if (ccSet == null) {
ccSet = new HashSet<CustomCategory>();
dynamicCustomCategoriesMap.put(element, ccSet);
}
ccSet.add(cc);
}
}
} catch (Throwable e) {
LibraryPlugin.getDefault().getLogger().logError(e);
}
}
public void clearDynamicCustomCategoriesMap() {
dynamicCustomCategoriesMap = null;
}
public Set<CustomCategory> getDynamicCustomCategories(MethodElement element) {
return dynamicCustomCategoriesMap == null ? null : dynamicCustomCategoriesMap.get(element);
}
/**
* Test if pkg is a system package of plugin
* @param plugin
* @param pkg
* @return
*/
public boolean isSystemPackage(MethodPlugin plugin, MethodPackage pkg) {
return TngUtil.getAllSystemPackages(plugin).contains(pkg);
}
public void loadOppositeFeatures(ILibraryResourceSet resouceSet,
List<OppositeFeature> oppositeFeatures, MethodElement element) {
Set<String> GUIDs = new HashSet<String>();
GUIDs.add(element.getGuid());
resouceSet.loadOppositeFeatures(oppositeFeatures, GUIDs);
}
public boolean isOwnerSelected(MethodElement element,
MethodConfiguration config, boolean checkSubtracted) {
if (config instanceof Scope) {
return ((Scope)config).inScope(element);
}
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 || ConfigurationHelper.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"); //$NON-NLS-1$
}
}
}
}
// 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
&& !ConfigurationHelper.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
&& ConfigurationHelper.isGlobalPackage((MethodPackage) pkg)) {
MethodPlugin plugin = LibraryUtil.getMethodPlugin(pkg);
return ConfigurationHelper.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;
}
}
public void loadOppositeFeatures(Map map, List oppositeFeatures, Set deletedGUIDs) {
int max = oppositeFeatures.size() - 1;
if (max < 0) {
return;
}
Collection elements = new HashSet(map.values());
HashSet loadedElements = new HashSet();
while (!elements.isEmpty()) {
for (Iterator iter = elements.iterator(); iter.hasNext();) {
Object obj = iter.next();
if (obj instanceof MethodElement) {
MethodElement element = (MethodElement) obj;
MultiResourceEObject mrEObject = ((MultiResourceEObject) element);
for (int i = max; i > -1; i--) {
OppositeFeature oppositeFeature = ((OppositeFeature) oppositeFeatures
.get(i));
EStructuralFeature eFeature = oppositeFeature.getTargetFeature();
if (eFeature.getContainerClass().isInstance(element)) {
if (eFeature.isMany()) {
InternalEList list = (InternalEList) element
.eGet(eFeature);
if (!list.isEmpty()) {
boolean resolve = false;
check_resolve: for (Iterator iterator = list
.basicIterator(); iterator
.hasNext();) {
InternalEObject e = (InternalEObject) iterator
.next();
if (e.eIsProxy()) {
String guid = e.eProxyURI()
.fragment();
if (deletedGUIDs.contains(guid)) {
resolve = true;
break check_resolve;
}
}
}
if (resolve) {
Collection<Object> deletedElements = new HashSet<Object>();
for (Iterator iterator = list
.iterator(); iterator.hasNext();) {
Object o = iterator.next();
if(o instanceof MethodElement && deletedGUIDs.contains(((MethodElement) o).getGuid())) {
deletedElements.add(o);
}
}
for (Object e : deletedElements) {
if(oppositeFeature.isMany()) {
mrEObject.oppositeAdd(oppositeFeature, e);
}
else {
mrEObject.getOppositeFeatureMap().put(oppositeFeature, e);
}
}
}
}
} else {
Object value = element.eGet(eFeature, false);
if (value instanceof InternalEObject) {
InternalEObject e = (InternalEObject) value;
if (e.eIsProxy()) {
String guid = e.eProxyURI().fragment();
if (deletedGUIDs.contains(guid)) {
Object o = element.eGet(eFeature);
if(oppositeFeature.isMany()) {
mrEObject.oppositeAdd(oppositeFeature, o);
}
else {
mrEObject.getOppositeFeatureMap().put(oppositeFeature, o);
}
}
}
}
}
}
}
}
}
// gets the newly loaded elements to load their opposite features
//
loadedElements.addAll(elements);
elements = new HashSet(map.values());
elements.removeAll(loadedElements);
}
}
public String generateHtml(Object raw_element, HtmlBuilder htmlBuilder) {
ResourceHelper.birt_publishing = false;
loadForBrowsing(raw_element);
IElementLayout layout = null;
String file_url = "about:blank"; //$NON-NLS-1$
Object element = LibraryUtil.unwrap(raw_element);
try {
setGenerateHtmlMode(true);
if ( raw_element instanceof ActivityWrapperItemProvider ) {
ActivityWrapperItemProvider wrapper = (ActivityWrapperItemProvider)raw_element;
Object proc = wrapper.getTopItem();
if ( element instanceof MethodElement && proc instanceof org.eclipse.epf.uma.Process ) {
String path = AbstractProcessElementLayout.getPath(wrapper);
//System.out.println(topItem);
layout = htmlBuilder.getLayoutManager()
.createLayout((MethodElement)element,
(org.eclipse.epf.uma.Process)proc, path);
file_url = htmlBuilder.generateHtml(layout);
}
} else if (raw_element instanceof PracticeSubgroupItemProvider) {
PracticeSubgroupItemProvider provider = (PracticeSubgroupItemProvider) raw_element;
layout = new SummaryPageLayout(htmlBuilder.getLayoutManager(),
provider.getPractice(), provider.getPrefix(),
provider.getText(null), (List) provider.getChildren(null),
provider.getText(null));
((SummaryPageLayout) layout).setHtmlBuilder(htmlBuilder);
file_url = htmlBuilder.generateHtml(layout);
} else if (element instanceof MethodElement) {
file_url = htmlBuilder.generateHtml((MethodElement)element);
}
} finally {
setGenerateHtmlMode(false);
}
if ( file_url == null ) {
file_url = "about:blank"; //$NON-NLS-1$
}
// on linux, the file path need to be specified as file, otherwise it will be treated as url
// and casuign encoding/decoding issue
// Linux: Configuration names containing accented characters cannot be browsed.
else {
if (!SWT.getPlatform().equals("win32") && !file_url.startsWith("file://") && //$NON-NLS-1$ //$NON-NLS-2$
!file_url.equals("about:blank")) //$NON-NLS-1$
{
file_url = "file://" + file_url; //$NON-NLS-1$
}
// Bug 201335 - Refresh does not work correctly for process pages in browsing mode
// need to append the query string
if ( layout instanceof AbstractProcessElementLayout ) {
file_url += ((AbstractProcessElementLayout)layout).getQueryString();
}
}
ResourceHelper.birt_publishing = true;
return file_url;
}
//Should be overriden by sub classes
public ElementLayoutExtender newElementLayoutExtender(AbstractElementLayout layout) {
return null;
}
public void configViewRefreshNotified() {
}
public void debugDump(String msg) {
System.out.println("LD> " + getClass() + ".debugDump: " + msg); //$NON-NLS-1$//$NON-NLS-2$
}
public boolean isPublishingMode() {
return publishingMode;
}
public void setPublishingMode(boolean publishingMode) {
this.publishingMode = publishingMode;
}
public boolean isAuthoringPerspective() {
return authoringPerspective;
}
public void setAuthoringPerspective(boolean authoringPerspective) {
this.authoringPerspective = authoringPerspective;
}
public boolean isAuthoringMode() {
return isAuthoringPerspective();
}
private boolean supportingInAuthoringMode = false;
public boolean isSupportingInAuthoringMode() {
return supportingInAuthoringMode;
}
public void setSupportingInAuthoringMode(boolean supportingInAuthoringMode) {
this.supportingInAuthoringMode = supportingInAuthoringMode;
}
private IPerspectiveListener perspectiveListener;
private void addPerspectiveListener() {
if (perspectiveListener != null) {
return;
}
IWorkbenchWindow window = LibraryUtil.getActiveWorkbenchWindow();
if (window != null) {
perspectiveListener = new IPerspectiveListener() {
public void perspectiveActivated(IWorkbenchPage page,
IPerspectiveDescriptor desc) {
handleConfigOrPersepctiveChange();
}
public void perspectiveChanged(IWorkbenchPage page,
IPerspectiveDescriptor desc, String id) {
handleConfigOrPersepctiveChange();
}
};
window.addPerspectiveListener(perspectiveListener);
}
}
private ILibraryServiceListener libServiceListener = new LibraryServiceListener() {
public void configurationSet(MethodConfiguration newConfig) {
addPerspectiveListener();
if (config == newConfig) {
return;
}
handleConfigOrPersepctiveChange();
config = newConfig;
}
};
protected void loadForBrowsing(Object raw_element) {
if (!loadForBrowsingNeeded) {
return;
}
MethodConfiguration config = LibraryService.getInstance()
.getCurrentMethodConfiguration();
if (config != null && ! BrowsingLayoutSettings.INSTANCE.isIgnoreDynamicParents()) {
buildDynamicCustomCategoriesMap(config);
}
if (raw_element instanceof BreakdownElement
|| raw_element instanceof ActivityWrapperItemProvider) {
if (config == null) {
LibraryUtil.loadAll(LibraryService.getInstance()
.getCurrentMethodLibrary());
} else {
LibraryUtil.loadAllPlugins(config);
IRealizationManager mgr = getRealizationManager(config);
if (mgr != null) {
mgr.updateAllProcesseModels();
setAutoSyncedByBrowsing(true);
}
}
}
loadForBrowsingNeeded = false;
}
public IRealizationManager getRealizationManager(MethodConfiguration config) {
if (config == null || config instanceof Scope) {
return null;
}
IConfigurationManager configMgr = LibraryService.getInstance().getConfigurationManager(config);
return configMgr == null ? null : configMgr.getRealizationManager();
}
private void handleConfigOrPersepctiveChange() {
loadForBrowsingNeeded = true;
ConfigurationHelper.getDelegate().loadUserDefinedType();
clearDynamicCustomCategoriesMap();
}
//Check to see if a process can be converted to a config-free process
//To be overridden by sub-class
public boolean canBeConfigFree(Process proc) {
return true;
}
protected boolean isLoadForBrowsingNeeded() {
return loadForBrowsingNeeded;
}
public void setLoadForBrowsingNeeded(boolean loadForBrowsingNeeded) {
this.loadForBrowsingNeeded = loadForBrowsingNeeded;
}
public boolean isAutoSyncedByBrowsing() {
return autoSyncedByBrowsing;
}
public void setAutoSyncedByBrowsing(boolean autoSyncedByBrowsing) {
this.autoSyncedByBrowsing = autoSyncedByBrowsing;
}
public ConfigurationData getConfigurationData(MethodConfiguration config) {
if (config == null) {
return null;
}
IConfigurationManager configMgr = LibraryService.getInstance().getConfigurationManager(config);
ConfigurationData configData = configMgr == null ? null : configMgr.getConfigurationData();
if (configData == null) {
LibraryPlugin.getDefault().getLogger().logError("getConfigurationData() == null for: " + config.getName());//$NON-NLS-1$
}
return configData;
}
public SupportingElementData getSupportingElementData(MethodConfiguration config) {
if (config == null) {
return null;
}
IConfigurationManager configMgr = LibraryService.getInstance().getConfigurationManager(config);
return configMgr == null ? null : configMgr.getSupportingElementData();
}
//Make closure if conig stores any making closure info
//Return true if processed otherwise false
public boolean makeClosure(MethodConfiguration config) {
return false;
}
public void loadUserDefinedType() {
}
public boolean additionShowConfigSelectMenu(IWorkbenchPage activePage) {
return false;
}
public boolean filterOutEmptyCategories() {
if (isAuthoringMode()) {
return false;
}
if (isPublishingMode()) {
//Publishing logic does its own filter out, ok to return false here
return false;
}
return true;
}
public void fixupLoadCheckPackages(MethodLibrary lib) {
if (lib == null) {
return;
}
Map<MethodPlugin, Set<MethodPackage>> map = new HashMap<MethodPlugin, Set<MethodPackage>>();
for (MethodConfiguration config : lib.getPredefinedConfigurations()) {
fixupLoadCheckPackages(map, config);
}
}
public void fixupLoadCheckPackages(MethodConfiguration config) {
fixupLoadCheckPackages(null, config);
}
private void fixupLoadCheckPackages(
Map<MethodPlugin, Set<MethodPackage>> map,
MethodConfiguration config) {
MethodConfigurationPropUtil propUtil = MethodConfigurationPropUtil.getMethodConfigurationPropUtil();
MethodConfigurationExt ext = propUtil.getMethocConfigurationExt(config);
if (ext == null || ext.isLoadCheckPackagesCalled()) {
return;
}
ext.setLoadCheckPackagesCalled(true);
if (! needFixupLoadCheckPackages(config)) {
return;
}
if (map == null) {
map = new HashMap<MethodPlugin, Set<MethodPackage>>();
}
Set<MethodPackage> selectedPkgs = new HashSet<MethodPackage>(config.getMethodPackageSelection());
Set<MethodPackage> toAddCheckPkgs = new HashSet<MethodPackage>();
for (MethodPlugin plugin : config.getMethodPluginSelection()) {
Set<MethodPackage> loadCheckPkgs = map.get(plugin);
if (loadCheckPkgs == null) {
loadCheckPkgs = new HashSet<MethodPackage>();
map.put(plugin, loadCheckPkgs);
}
collectLoadCheckPkgs(plugin.getMethodPackages(), loadCheckPkgs);
toAddCheckPkgs.addAll(loadCheckPkgs);
}
Set<MethodPackage> doneSet = propUtil.getDoneLoadCheckPkgs(config);
toAddCheckPkgs.removeAll(doneSet);
Set<MethodPackage> handkedSet = new HashSet<MethodPackage>();
for (MethodPackage pkg : toAddCheckPkgs) {
if (handkedSet.add(pkg)) {
if (checkParentPackage(handkedSet, config, selectedPkgs, pkg,
toAddCheckPkgs)) {
addToConfig(config, selectedPkgs, pkg);
}
}
}
}
public boolean needFixupLoadCheckPackages(MethodConfiguration config) {
return config != null;
}
private void addToConfig(MethodConfiguration config,
Set<MethodPackage> selectedPkgs, MethodPackage pkg) {
config.getMethodPackageSelection().add(pkg);
selectedPkgs.add(pkg);
}
private boolean checkParentPackage(Set<MethodPackage> handkedSet, MethodConfiguration config, Set<MethodPackage> selectedPkgs, MethodPackage pkg, Set<MethodPackage> toAddCheckPkgs) {
EObject container = pkg.eContainer();
if (! (container instanceof MethodPackage)) {
return false;
}
MethodPackage parentPkg = (MethodPackage) container;
if (selectedPkgs.contains(parentPkg)) {
return true;
}
if (! toAddCheckPkgs.contains(parentPkg)) {
return false;
}
if (handkedSet.add(parentPkg)) {
if (checkParentPackage(handkedSet, config, selectedPkgs, parentPkg, toAddCheckPkgs)) {
addToConfig(config, selectedPkgs, parentPkg);
}
}
return false;
}
private void collectLoadCheckPkgs(List<MethodPackage> pkgList, Set<MethodPackage> loadCheckPkgs) {
PropUtil propUtil = PropUtil.getPropUtil();
for (MethodPackage pkg : pkgList) {
Boolean b = propUtil.getBooleanValue(pkg, PropUtil.Pkg_loadCheck);
if (b != null && b.booleanValue()) {
loadCheckPkgs.add(pkg);
}
collectLoadCheckPkgs(pkg.getChildPackages(), loadCheckPkgs);
}
}
public boolean isGenerateHtmlMode() {
return generateHtmlMode;
}
public void setGenerateHtmlMode(boolean generateHtmlMode) {
this.generateHtmlMode = generateHtmlMode;
}
public boolean browseOrPublishMode() {
return isPublishingMode() || isGenerateHtmlMode();
}
}