blob: afb76eb457b73d86c739de13e5aedebb00415e38 [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;
import java.io.File;
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 java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
import org.eclipse.epf.common.utils.FileUtil;
import org.eclipse.epf.common.utils.StrUtil;
import org.eclipse.epf.library.ILibraryManager;
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.DefaultElementRealizer;
import org.eclipse.epf.library.configuration.ElementRealizer;
import org.eclipse.epf.library.edit.IFilter;
import org.eclipse.epf.library.edit.TngAdapterFactory;
import org.eclipse.epf.library.edit.util.ConfigurableComposedAdapterFactory;
import org.eclipse.epf.library.edit.util.Suppression;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.library.layout.diagram.IActivityDiagramService;
import org.eclipse.epf.library.layout.elements.AbstractElementLayout;
import org.eclipse.epf.library.layout.elements.AbstractProcessElementLayout;
import org.eclipse.epf.library.layout.elements.GeneralLayout;
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.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.Process;
import org.eclipse.epf.uma.TaskDescriptor;
import org.eclipse.epf.uma.WorkBreakdownElement;
import org.eclipse.epf.uma.util.UmaUtil;
/**
* @author Jinhua Xi
* @since 1.0
*/
public class ElementLayoutManager {
private static final String PACKAGE_NAME = ElementLayoutManager.class
.getPackage().getName();
private static final String default_config_path = "noconfig"; //$NON-NLS-1$
private boolean isPublishingMode = false; // default to browsing mode
private String publish_dir = null;
private MethodConfiguration config = null;
private IActivityDiagramService diagramService = null;
// need to seperate the adapter factory form content and diagram
// diagram adaptor factory should not be rolled up
private LayoutAdapterFactory contentLayoutAdapterFactory = null;
private LayoutAdapterFactory diagramLayoutAdapterFactory = null;
// cache the suppression object for publishing model only
// map of proc guid to Suppresiion object
private Map supressionMap = null;
private IContentValidator validator = null;
private ElementRealizer realizer = null;
private Map<String, String> toRenamePluginFolderMap;
// the layout extensions. each extension is identified by the property id of the configuration
private Map<String, LayoutExtension> layoutExtensions = new HashMap<String, LayoutExtension>();
public boolean isPublishingMode()
{
return this.isPublishingMode;
}
public ElementLayoutManager() {
this(null, null, null, false);
buildPublishDir(null);
}
public ElementLayoutManager(MethodConfiguration config) {
this(config, null, null, false);
}
public ElementLayoutManager(MethodConfiguration config, String publishdir, IContentValidator validator, boolean isPublishingMode) {
this.validator = validator;
this.isPublishingMode = isPublishingMode;
if (config != null) {
this.config = config;
}
if (isPublishingMode) {
buildPublishDir(publishdir);
}
contentLayoutAdapterFactory = new LayoutAdapterFactory(this.config);
diagramLayoutAdapterFactory = new LayoutAdapterFactory(this.config);
// load the layout extensions for this configuration
loadLayoutExtensions();
}
private boolean publishDirBuilt = false;
public void buildPublishDir(String publishdir) {
if (publishDirBuilt) {
return;
}
publishDirBuilt = true;
if (publishdir == null) {
publishdir = LayoutResources.getDefaultPublishDir();
if (!publishdir.endsWith(File.separator)) {
publishdir += File.separator;
}
// also append the configuration path
if (this.config == null) {
publishdir += default_config_path;
} else {
String str = StrUtil.removeSpecialCharacters(this.config.getName());
if ( str == "" ) { //$NON-NLS-1$
str = Integer.toHexString(this.config.toString().hashCode());
}
publishdir += str;
}
}
setPublishDir(publishdir);
}
private void loadLayoutExtensions() {
if ( config == null ) {
return;
}
// load the layout extensions for this configuration
List props = config.getMethodElementProperty();
if ( props != null && props.size() > 0 ) {
for (Iterator itp = props.iterator(); itp.hasNext(); ) {
MethodElementProperty prop = (MethodElementProperty)itp.next();
String id = prop.getName();
LayoutExtension ext= LayoutExtensionFactory.getInstance().createExtension(id);
if ( ext != null ) {
ext.init(this);
layoutExtensions.put(id, ext);
}
}
}
}
/**
* Returns the content validator.
*/
public IContentValidator getValidator() {
if (validator == null) {
validator = new DefaultContentValidator(getPublishDir());
}
return validator;
}
public ElementRealizer getElementRealizer() {
if ( realizer == null ) {
realizer = DefaultElementRealizer.newElementRealizer(config);
realizer.setFilter(contentLayoutAdapterFactory.getFilter());
}
return realizer;
}
public void setElementRealizer(ElementRealizer realizer) {
this.realizer = realizer;
}
public ConfigurableComposedAdapterFactory getWBSAdapterFactory() {
return contentLayoutAdapterFactory.wbsAdapterFactory;
}
public ConfigurableComposedAdapterFactory getTBSAdapterFactory() {
return contentLayoutAdapterFactory.tbsAdapterFactory;
}
public ConfigurableComposedAdapterFactory getWPBSAdapterFactory() {
return contentLayoutAdapterFactory.wpbsAdapterFactory;
}
public ConfigurableComposedAdapterFactory getCBSAdapterFactory() {
return contentLayoutAdapterFactory.cbsAdapterFactory;
}
public ConfigurableComposedAdapterFactory getDiagramAdapterFactory() {
return diagramLayoutAdapterFactory.wbsAdapterFactory;
}
public void setActivityDiagramService(IActivityDiagramService diagramService) {
this.diagramService = diagramService;
}
public IActivityDiagramService getActivityDiagramService() {
return this.diagramService;
}
public Suppression getSuppression(Process proc)
{
Suppression sup = null;
if ( isPublishingMode)
{
if ( supressionMap == null )
{
supressionMap = new HashMap();
}
String guid = proc.getGuid();
sup = (Suppression)supressionMap.get(guid);
if ( sup == null )
{
sup = createSuppression(proc);
supressionMap.put(guid, sup);
}
}
else
{
sup = createSuppression(proc);
}
return sup;
}
public void prepareAdaptorFactoriesForProcess(Process proc)
{
// need to iterate the adaptor factory to generate the adaptor tree
prepareAdapterfactoryFor(getCBSAdapterFactory(), proc);
prepareAdapterfactoryFor(getTBSAdapterFactory(), proc);
prepareAdapterfactoryFor(getWBSAdapterFactory(), proc);
prepareAdapterfactoryFor(getWPBSAdapterFactory(), proc);
}
private void prepareAdapterfactoryFor(
ComposedAdapterFactory adapterFactory, Object obj) {
if (obj == null || adapterFactory == null) {
return;
}
ITreeItemContentProvider provider = null;
if (obj instanceof ITreeItemContentProvider) {
provider = (ITreeItemContentProvider) obj;
} else {
provider = (ITreeItemContentProvider) adapterFactory.adapt(obj,
ITreeItemContentProvider.class);
}
if (provider != null) {
Collection items = provider.getChildren(obj);
for (Iterator it = items.iterator(); it.hasNext();) {
Object rawitem = it.next();
MethodElement item = (MethodElement) LibraryUtil
.unwrap(rawitem);
if ((item instanceof Activity)) {
prepareAdapterfactoryFor(adapterFactory, rawitem);
}
}
}
}
private IElementLayout createLayout(MethodElement element) {
// if the element is an activity, we need to fined the path to the process
String path = null;
Process owningProc = null;
if ( element instanceof Activity )
{
Activity act = (Activity)element;
path = AbstractProcessElementLayout.getPath(act);
owningProc = TngUtil.getOwningProcess(act);
}
return createLayout(element, owningProc, path);
}
public IElementLayout createLayout(MethodElement element,
Process owningProc, String path) {
AbstractElementLayout layout = null;
String className;
if (ConfigurationHelper.isDescriptionElement(element)) {
className = "ContentDescription"; //$NON-NLS-1$
} else if (element instanceof Activity) {
className = "Activity"; //$NON-NLS-1$
} else if ((element instanceof WorkBreakdownElement)
&& !(element instanceof TaskDescriptor)) {
className = "WorkBreakdownElement"; //$NON-NLS-1$ // taskdescriptor has it's own layout
} else {
Class i[] = element.getClass().getInterfaces();
if (i != null && i.length == 1) {
className = i[0].getName();
} else {
className = element.getClass().getName();
}
int index = className.lastIndexOf("."); //$NON-NLS-1$
if (index >= 0) {
className = className.substring(index + 1);
}
}
className = PACKAGE_NAME + ".elements." + className + "Layout"; //$NON-NLS-1$ //$NON-NLS-2$
try {
Class c = Class.forName(className);
if (c != null) {
layout = (AbstractElementLayout) c.newInstance();
}
} catch (Exception ex) {
// ex.printStackTrace();
}
if (layout == null) {
// System.out.println("Layout class '" + className + "' for element
// '" + element.getName() + "' not defined. Use GeneralLayout");
layout = new GeneralLayout();
}
if (layout instanceof AbstractProcessElementLayout) {
((AbstractProcessElementLayout) layout).init(this, element,
owningProc, path);
} else {
layout.init(this, element);
}
return layout;
}
public IElementLayout getLayout(MethodElement element, boolean create) {
// String id = element.getGuid();
IElementLayout layout = null; // (IElementLayout)layoutMap.get(id);
if ((layout == null) && create) {
layout = createLayout(element);
// layoutMap.put(id, layout);
}
return layout;
}
private static final Pattern p_parameters = Pattern
.compile(
"\\?proc=(.*?)&path=(.*)?", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$
public IElementLayout getLayout(String url) {
Process owningProc = null;
String path = null;
Matcher m = p_parameters.matcher(url);
if (m.find()) {
String proc = m.group(1);
path = m.group(2);
ILibraryManager manager = LibraryService.getInstance()
.getCurrentLibraryManager();
if (manager != null) {
owningProc = (Process) manager.getMethodElement(
proc);
}
}
// MethodElement element = (MethodElement)urlMap.get(url);
MethodElement element = ResourceHelper.getElementFromFileName(url);
if (element != null) {
return createLayout(element, owningProc, path);
} else {
System.out.println("Can't find element for url '" + url + "'"); //$NON-NLS-1$ //$NON-NLS-2$
}
return null;
}
public static String getQueryString(String proc, String path) {
return "?" + ResourceHelper.URL_PARAMETER_PROCESS + "=" + proc + "&" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ ResourceHelper.URL_PARAMETER_PATH + "=" + path; //$NON-NLS-1$
}
public MethodConfiguration getConfiguration() {
return this.config;
}
public void setPublishDir(String path) {
this.publish_dir = path;
if ( !this.publish_dir.endsWith(File.separator) ) {
this.publish_dir += File.separator;
}
// initialize publishing site if needed
init_publishingSite();
}
public String getPublishDir() {
return this.publish_dir;
}
private void init_publishingSite() {
if ( BrowsingLayoutSettings.INSTANCE.needUpdate(publish_dir) ) {
// if ( LibraryPlugin.getDefault().isDebugging() ) {
System.out
.println("Begin initializing publishing site: " + publish_dir); //$NON-NLS-1$
// }
// copy the layout files from plugin layout to publishign site
LayoutResources.copyLayoutFiles(publish_dir);
if ( LibraryPlugin.getDefault().isDebugging() ) {
System.out.println("End initializing publishing site: " + publish_dir); //$NON-NLS-1$
}
}
}
// public void copyLibraryResources() {
// if ( LibraryPlugin.getDefault().isDebugging() ) {
// System.out
// .println("Begin copying library resources to publishing site: " + publish_dir); //$NON-NLS-1$
// }
//
// // copy library resources from library to publishing site
// File libRoot = new File(LibraryService.getInstance().getCurrentMethodLibraryPath());
// if (libRoot != null) {
// LayoutResources.copyDir(libRoot.getPath(), publish_dir);
// }
//
// if ( LibraryPlugin.getDefault().isDebugging() ) {
// System.out
// .println("End copying library resources to publishing site: " + publish_dir); //$NON-NLS-1$
// }
// }
public void clear() {
// layoutMap.clear();
diagramService = null;
if ( supressionMap != null )
{
supressionMap.clear();
}
layoutExtensions.clear();
layoutExtensions = null;
contentLayoutAdapterFactory.clear();
diagramLayoutAdapterFactory.clear();
if ( validator != null )
{
validator.dispose();
validator = null;
}
if ( realizer != null ) {
realizer.dispose();
realizer = null;
}
if ( contentLayoutAdapterFactory != null ) {
contentLayoutAdapterFactory.clear();
contentLayoutAdapterFactory = null;
}
if ( diagramLayoutAdapterFactory != null ) {
diagramLayoutAdapterFactory.clear();
diagramLayoutAdapterFactory = null;
}
toRenamePluginFolderMap = null;
}
public class LayoutAdapterFactory
{
public ConfigurableComposedAdapterFactory wbsAdapterFactory = null;
public ConfigurableComposedAdapterFactory tbsAdapterFactory = null;
public ConfigurableComposedAdapterFactory wpbsAdapterFactory = null;
public ConfigurableComposedAdapterFactory cbsAdapterFactory = null;
ProcessAdapterFactoryFilter configurator = null;
public LayoutAdapterFactory(MethodConfiguration methodConfig)
{
// create adapt factories
//
if(isPublishingMode()) {
wbsAdapterFactory = (ConfigurableComposedAdapterFactory) TngAdapterFactory.INSTANCE
.createPublishingWBSAdapterFactory();
tbsAdapterFactory = (ConfigurableComposedAdapterFactory) TngAdapterFactory.INSTANCE
.createPublishingTBSAdapterFactory();
wpbsAdapterFactory = (ConfigurableComposedAdapterFactory) TngAdapterFactory.INSTANCE
.createPublishingWPBSAdapterFactory();
cbsAdapterFactory = (ConfigurableComposedAdapterFactory) TngAdapterFactory.INSTANCE
.createPublishingCBSAdapterFactory();
}
else {
wbsAdapterFactory = (ConfigurableComposedAdapterFactory) TngAdapterFactory.INSTANCE
.createWBSComposedAdapterFactory();
tbsAdapterFactory = (ConfigurableComposedAdapterFactory) TngAdapterFactory.INSTANCE
.createTBSComposedAdapterFactory();
wpbsAdapterFactory = (ConfigurableComposedAdapterFactory) TngAdapterFactory.INSTANCE
.createWPBSComposedAdapterFactory();
cbsAdapterFactory = (ConfigurableComposedAdapterFactory) TngAdapterFactory.INSTANCE
.createProcessComposedAdapterFactory();
}
// set configuration filter
configurator = new ProcessAdapterFactoryFilter(methodConfig, this) {
@Override
public ElementRealizer getRealizer() {
ElementRealizer realizer = ElementLayoutManager.this.getElementRealizer();
if (realizer == null) {
realizer = super.getRealizer();
}
return realizer;
}
};
wbsAdapterFactory.setFilter(configurator);
tbsAdapterFactory.setFilter(configurator);
wpbsAdapterFactory.setFilter(configurator);
cbsAdapterFactory.setFilter(configurator);
}
public IFilter getFilter() {
return configurator;
}
public void clear()
{
if (wbsAdapterFactory != null) {
wbsAdapterFactory.setFilter(null);
wbsAdapterFactory.dispose();
wbsAdapterFactory = null;
}
if (tbsAdapterFactory != null) {
tbsAdapterFactory.setFilter(null);
tbsAdapterFactory.dispose();
tbsAdapterFactory = null;
}
if (wpbsAdapterFactory != null) {
wpbsAdapterFactory.setFilter(null);
wpbsAdapterFactory.dispose();
wpbsAdapterFactory = null;
}
if (cbsAdapterFactory != null) {
cbsAdapterFactory.setFilter(null);
cbsAdapterFactory.dispose();
cbsAdapterFactory = null;
}
if ( configurator != null ) {
configurator.dispose();
configurator = null;
}
}
}
private Suppression createSuppression(Process proc) {
// check if there are extensions
if ( layoutExtensions != null && layoutExtensions.size() > 0 ) {
for ( Iterator<LayoutExtension> it = layoutExtensions.values().iterator(); it.hasNext(); ) {
LayoutExtension ext = it.next();
Suppression sup = ext.getSuppression(proc);
if ( sup != null ) {
return sup;
}
}
}
return new Suppression(proc);
}
public void prepareElementPathAdjustment() {
String fChars = BrowsingLayoutSettings.INSTANCE.getForbiddenUrlChars();
if (fChars == null || fChars.trim().length() == 0) { //if flag is not set
return;
}
MethodConfiguration c = getConfiguration();
if (c == null) {
return;
}
toRenamePluginFolderMap = new HashMap<String, String>();
Set<String> usedNameSet = new HashSet<String>();
MethodLibrary lib = UmaUtil.getMethodLibrary(c);
for (MethodPlugin p : lib.getMethodPlugins()) {
usedNameSet.add(p.getName());
}
List<MethodPlugin> plugins = c.getMethodPluginSelection();
Set<String> forbidenChars = new HashSet<String>();
for (int i = 0; i < fChars.length(); i++) {
String str = String.valueOf((fChars.charAt(i)));
if (str.trim().length() > 0) {
forbidenChars.add(str);
}
}
for (MethodPlugin plugin : plugins) {
String name = plugin.getName();
String replacingName = getReplacingName(name, forbidenChars);
if (! name.equals(replacingName)) {
replacingName = getUniqueName(replacingName, usedNameSet);
usedNameSet.add(replacingName);
toRenamePluginFolderMap.put(plugin.getName(), replacingName);
}
}
if (toRenamePluginFolderMap.isEmpty()) {
toRenamePluginFolderMap = null;
}
}
private String getReplacingName(String name, Set<String> forbidenChars) {
StringBuffer b = new StringBuffer();
boolean modified = false;
for (int i = 0; i < name.length(); i++) {
String str = String.valueOf((name.charAt(i)));
if (forbidenChars.contains(str)) {
b.append("_"); //$NON-NLS-1$
modified = true;
} else {
b.append(str);
}
}
return modified ? b.toString() : name;
}
public String getAdjustedElementPath(String elementPath) {
if (toRenamePluginFolderMap == null) {
return elementPath;
}
String pluginName = getPluginName(elementPath);
if (pluginName == null) {
return elementPath;
}
String replacingPluginName = toRenamePluginFolderMap.get(pluginName);
if (replacingPluginName == null) {
return elementPath;
}
return elementPath.replaceFirst(pluginName, replacingPluginName);
}
private String getUniqueName(String name, Set<String> usedNameSet) {
String uniqueName = name;
int i = 0;
while(usedNameSet.contains(uniqueName)) {
i++;
uniqueName = name + i;
}
return uniqueName;
}
private String getPluginName(String elementPath) {
int ix = elementPath.indexOf("/");
if (ix > 0) {
return elementPath.substring(0, ix);
}
return null;
}
public String getAdjustedElementPathStringValue(String source) {
if (toRenamePluginFolderMap == null) {
return source;
}
boolean localDebug = false;
String str = getAdjustedElementPathStringValue(source, ResourceHelper.p_link_ref);
str = getAdjustedElementPathStringValue(str, ResourceHelper.p_area_ref);
if (localDebug) {
if (str != source) {
System.out.println("LD> original value: " + source); //$NON-NLS-1$
System.out.println(""); //$NON-NLS-1$
System.out.println("LD> modified value: " + str); //$NON-NLS-1$
}
System.out.println(""); //$NON-NLS-1$
}
return str;
}
private String getAdjustedElementPathStringValue(String source, Pattern pattern) {
boolean localDebug = false;
boolean modified = false;
StringBuffer sb = new StringBuffer();
Matcher m = pattern.matcher(source);
while (m.find()) {
String text = m.group();
String replacement = text;
Map attributeMap = ResourceHelper.getAttributesFromLink(pattern, text);
if (localDebug) {
System.out.println("LD> text: " + text); //$NON-NLS-1$
System.out.println("LD> attributeMap: " + attributeMap); //$NON-NLS-1$
}
String href = attributeMap == null ? null : (String) attributeMap.get(ResourceHelper.TAG_ATTR_HREF);
int ix0 = -1;
int ix1 = -1;
if (href != null) {
//example: href="./../../a.b.c.d.e/roles/new_role-1_BA944608.html"
// | |
// ix0 |
// ix1
ix0 = href.lastIndexOf("../"); //$NON-NLS-1$
if (ix0 > 0) {
ix0 += 3;
ix1 = href.substring(ix0).indexOf("/"); //$NON-NLS-1$
if (ix1 > 0) {
ix1 += ix0;
}
}
}
if (ix0 >= 0 && ix1 > ix0) {
String replaced = href.substring(ix0, ix1);
String replacing = toRenamePluginFolderMap.get(replaced);
if (replacing != null) {
replacement = text.replace(replaced, replacing);
if (localDebug) {
System.out.println("LD> replaced: " + replaced); //$NON-NLS-1$
System.out.println("LD> replacing: " + replacing); //$NON-NLS-1$
System.out.println(""); //$NON-NLS-1$
}
modified = true;
}
}
m.appendReplacement(sb, Matcher.quoteReplacement(replacement));
}
m.appendTail(sb);
return modified ? sb.toString() : source;
}
public void handlePluginFolderRename() {
if (toRenamePluginFolderMap == null) {
return;
}
String topDirStr = getPublishDir();
for (Map.Entry<String, String> entry : toRenamePluginFolderMap.entrySet()) {
File oldPluginFolder = new File(topDirStr, entry.getKey());
if (oldPluginFolder.isDirectory()) {
File newPluginFolder = new File(topDirStr, entry.getValue());
boolean b = oldPluginFolder.renameTo(newPluginFolder);
if (! b) {
FileUtil.copyDir(oldPluginFolder, newPluginFolder);
FileUtil.deleteAllFiles(oldPluginFolder.getAbsolutePath());
oldPluginFolder.delete();
}
}
}
}
}