//------------------------------------------------------------------------------
// 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.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
import org.eclipse.epf.common.utils.StrUtil;
import org.eclipse.epf.common.utils.Timer;
import org.eclipse.epf.common.utils.XMLUtil;
import org.eclipse.epf.library.LibraryPlugin;
import org.eclipse.epf.library.LibraryResources;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.configuration.ConfigurationHelper;
import org.eclipse.epf.library.edit.IFilter;
import org.eclipse.epf.library.edit.process.ComposedWPDescriptorWrapperItemProvider;
import org.eclipse.epf.library.edit.process.IBSItemProvider;
import org.eclipse.epf.library.edit.util.Comparators;
import org.eclipse.epf.library.edit.util.PredecessorList;
import org.eclipse.epf.library.edit.util.ProcessUtil;
import org.eclipse.epf.library.edit.util.Suppression;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.library.layout.ElementLayoutManager;
import org.eclipse.epf.library.layout.IElementLayout;
import org.eclipse.epf.library.layout.LayoutInfo;
import org.eclipse.epf.library.layout.diagram.DiagramInfo;
import org.eclipse.epf.library.layout.diagram.IActivityDiagramService;
import org.eclipse.epf.library.layout.util.XmlElement;
import org.eclipse.epf.library.prefs.BSColumn;
import org.eclipse.epf.library.prefs.PreferenceUtil;
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.CompositeRole;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.Process;
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.TeamProfile;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.WorkBreakdownElement;
import org.eclipse.epf.uma.WorkProductDescriptor;
import org.eclipse.epf.uma.ecore.util.OppositeFeature;
import org.eclipse.epf.uma.util.AssociationHelper;
import org.eclipse.osgi.util.NLS;


/**
 * The element layout for a Role.
 * 
 * @author Jinhua Xi
 * @author Kelvin Low
 * @since 1.0
 */
public class ActivityLayout extends AbstractProcessElementLayout {
	
	public static final String TAB_NAME_ACTIVITY_DESC = "Description"; //$NON-NLS-1$
	public static final String TAB_NAME_ACTIVITY_WBS = "WBS"; //$NON-NLS-1$
	public static final String TAB_NAME_ACTIVITY_TBS = "TBS"; //$NON-NLS-1$
	public static final String TAB_NAME_ACTIVITY_WPBS = "WPBS"; //$NON-NLS-1$
	
	//public static final String BRACE_REPLACEMENT = "_BR_";	 //$NON-NLS-1$
	//public static final String OPENBRACE_STRING = "\\{";	 //$NON-NLS-1$
	
	org.eclipse.epf.diagram.model.util.DiagramInfo userDiagramInfo = null;
	boolean debug = LibraryPlugin.getDefault().isDebugging();
	
	private TBSItemDetail itemDetail = new TBSItemDetail();
	
	public ActivityLayout() {
		super();
	}

	/**
	 * initialize the layout
	 */
	public void init(ElementLayoutManager layoutManager, MethodElement element) {
		
		// make sure the process is loaded
		// otherwise the process or process elements 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???????????
		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.loadAllProcesses(LibraryService.getInstance().getCurrentMethodLibrary());
		}
		
		super.__init(layoutManager, element);

		userDiagramInfo = new org.eclipse.epf.diagram.model.util.DiagramInfo((Activity)element);
		
	
		// setup the multi layout output
		// String file_desc = super.getFileName(ResourceHelper.FILE_EXT_HTML);		
		
		String file;
		
//		if (super.element.getGuid().startsWith("{"))
//		{
//			String newGuid = super.element.getGuid().replaceFirst( OPENBRACE_STRING, BRACE_REPLACEMENT );
//			file = super.element.getName() + newGuid.substring(0, newGuid.length()-1);
//		}
//		else
			//file = StrUtil.removeSpecialCharacters(super.element.getName()) + super.element.getGuid();
		
		file = getFileName(ResourceHelper.FILE_EXT_HTML);
		if (file != null ) {
			// replace ' and " with space
			file = file.replace('\'', ' ').replace('\"', ' ');
			
			setLayoutInfo(new LayoutInfo(
				TAB_NAME_ACTIVITY_DESC, "activity_desc.xsl", file + TABURL_SUFFIX_DESC, true)); //$NON-NLS-1$ 
			setLayoutInfo(new LayoutInfo(
				TAB_NAME_ACTIVITY_WPBS, "activity_wpbs.xsl", file + TABURL_SUFFIX_WPBS, false)); //$NON-NLS-1$ 
			setLayoutInfo(new LayoutInfo(
				TAB_NAME_ACTIVITY_TBS, "activity_tbs.xsl", file + TABURL_SUFFIX_TBS, false)); //$NON-NLS-1$ 
			setLayoutInfo(new LayoutInfo(
				TAB_NAME_ACTIVITY_WBS, "activity_wbs.xsl", file + TABURL_SUFFIX_WBS, false)); //$NON-NLS-1$ 
		} else {
			System.out.println("Error in ActivityLayout.init: no file for element " + super.element.getName()); //$NON-NLS-1$
		}
	}
	
	/**
	 * @see org.eclipse.epf.library.layout.IElementLayout#getXslUrl()
	 */
	public String getXslUrl() {
		// set the default tab url, the default tab will be set in publishing.
		// for browsing, use the TAB_NAME_ACTIVITY_WBS tab
		String tabName = getLayoutMgr().getValidator().getDefaultActivityTab();
		if ( tabName == null ) {
			tabName = TAB_NAME_ACTIVITY_WBS;
		}
		LayoutInfo info = getLayoutInfo(tabName);
		if ( info == null ) {
			info = getLayoutInfo(TAB_NAME_ACTIVITY_WBS);
		}	
		
		return info.layout_xsl;
	}
	
	private static final String TABURL_SUFFIX_DESC = "_desc" + ResourceHelper.FILE_EXT_HTML; //$NON-NLS-1$
	private static final String TABURL_SUFFIX_WPBS = "_wpbs" + ResourceHelper.FILE_EXT_HTML; //$NON-NLS-1$
	private static final String TABURL_SUFFIX_TBS = "_tbs" + ResourceHelper.FILE_EXT_HTML; //$NON-NLS-1$
	private static final String TABURL_SUFFIX_WBS = "_wbs" + ResourceHelper.FILE_EXT_HTML; //$NON-NLS-1$
	
	public static boolean isActivityTabUrl(String url) {
		
		if ( url == null || url.length() == 0 ) {
			return false;
		}
		
		return (url.endsWith(TABURL_SUFFIX_DESC) 
				|| url.endsWith(TABURL_SUFFIX_WPBS) 
				|| url.endsWith(TABURL_SUFFIX_TBS) 
				|| url.endsWith(TABURL_SUFFIX_WBS) );
		
	}
	/**
	 * override this method to collect the SupportingMaterials that are for user defined diagrams
	 */
	protected boolean acceptFeatureValue(EStructuralFeature feature, Object value) {
		
		if ( value instanceof SupportingMaterial ) {			
			return !userDiagramInfo.isDiagram( (SupportingMaterial)value );
		}
		else if ( value instanceof List )
		{
			List items = (List)value;
			int i = 0;
			while ( i < items.size() )
			{
				Object o = items.get(i);
				if ( (o instanceof SupportingMaterial) && userDiagramInfo.isDiagram((SupportingMaterial)o) ) {			
					items.remove(i);
				}
				else
				{
					i++;
				}
			}
		}
		
		return true;
	}
	
	/**
	 * @see org.eclipse.epf.library.layout.IElementLayout#getXmlElement(boolean)
	 */
	public XmlElement getXmlElement(boolean includeReferences) {
		
		String msg;
		Timer t = null;
		if ( debug ) {
			t = new Timer();	
			msg = "Generating layout xml for " + LibraryUtil.getTypeName(element)  //$NON-NLS-1$ 
				+ ", includeReferences = " + includeReferences; //$NON-NLS-1$
			System.out.println(msg);
		}
		

		XmlElement elementXml = super.getXmlElement();
		
		// load the attributes
		loadAttributes(elementXml);
		
//		// set the default tab url, the default tab will be set in publishing.
//		// for browsing, use the TAB_NAME_ACTIVITY_WBS tab
//		String tabName = getLayoutMgr().getValidator().getDefaultActivityTab();
//		if ( tabName == null ) {
//			tabName = TAB_NAME_ACTIVITY_WBS;
//		}
//		LayoutInfo linfo = getLayoutInfo(tabName);
//		if ( linfo == null ) {
//			linfo = getLayoutInfo(TAB_NAME_ACTIVITY_WBS);
//		}	
//		
//		elementXml.setAttribute("defaultTabUrl", linfo.fileName);
//		
		Process proc = getOwningProcess();
		
		// need to handle the supressed breakdown elements
		// use the Supress utility
		Suppression sup = getSuppression(proc);

//		// display name needs to be fixed, extended activity may need to get display name from the base
//		// DVT:  PNs of extended processes no picked up for publish (TCT 638)
//		ComposedAdapterFactory adapterFactory = layoutManager.getCBSAdapterFactory();
//		Object wrapper = sup.getObjectByPath(super.paths, adapterFactory);
//		if ( wrapper == null ) {
//			wrapper = super.element;
//		}
//
//		IBSItemProvider adapter = (IBSItemProvider) adapterFactory.adapt(
//				wrapper, ITreeItemContentProvider.class);
//
//		String displayName = ProcessUtil.getAttribute(element,
//				IBSItemProvider.COL_PRESENTATION_NAME, adapter);
//
//		elementXml.setAttribute("DisplayName", displayName); //$NON-NLS-1$
		
		if (!includeReferences) {
			return elementXml;
		}
		
		elementXml.setAttribute("ShowFullMethodContent", (layoutManager.getValidator().showExtraInfoForDescriptors()) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

		// get the tabs xml section
		XmlElement tabsXml = elementXml.newChild("tabs"); //$NON-NLS-1$
		for (Iterator it = layouts.iterator(); it.hasNext();) {
			LayoutInfo info = (LayoutInfo) it.next();
			tabsXml.newChild("tab") //$NON-NLS-1$
					.setAttribute("name", info.name) //$NON-NLS-1$
					.setAttribute("url", super.elementPath + info.fileName); //$NON-NLS-1$
		}

		// do it only when it's a process or it's not in publishing model
		// since in publishing, the iteration always start from process
		// for browsing, it can start in the middle 
		if ( !getLayoutMgr().isPublishingMode() || super.element instanceof org.eclipse.epf.uma.Process ) {
			getLayoutMgr().prepareAdaptorFactoriesForProcess(proc);
		}

		// load the copyright info
		loadCopyright(elementXml);

		// calculate other selected referecnes
		List features = LibraryUtil.getStructuralFeatures(element);
//		List properties = element.getInstanceProperties();
		if (features != null) {
			// get element references
			for (int i = 0; i < features.size(); i++) {
				EStructuralFeature feature = (EStructuralFeature) features
						.get(i);

				// skip the breakdown elements since we will build the breakdown
				// structure later
				if (feature == UmaPackage.eINSTANCE
						.getActivity_BreakdownElements()) {
					continue;
				}

				// Object value = element.get(i);
				EClassifier type = feature.getEType();
				if (!(type instanceof EClass)) {
					continue;
				}

				loadFeature(feature, elementXml, false);
			}
		}
		
		Collection oppositeProperties = new ArrayList(element.getOppositeFeatures());
		for (Iterator z= oppositeProperties.iterator(); z.hasNext(); )
		{
			OppositeFeature ofeature = (OppositeFeature) z.next();
			loadFeature(ofeature, elementXml, includeReferences);
		}
		
		if ( debug ) {
			t.stop();
			msg = t.getTime() + " mini seconds building Activity Descriotion xml for " + LibraryUtil.getTypeName(element)  ; //$NON-NLS-1$ 			
			System.out.println(msg);
			
			t.start();
		}

		buildWBS(elementXml, sup);
		if ( debug ) {
			t.stop();
			msg = t.getTime() + " mini seconds building WBS for " + LibraryUtil.getTypeName(element)  ; //$NON-NLS-1$ 			
			System.out.println(msg);
			
			t.start();
		}
		
		buildTBS(elementXml, sup);	
		
		if ( debug ) {
			t.stop();
			msg = t.getTime() + " mini seconds building TBS for " + LibraryUtil.getTypeName(element)  ; //$NON-NLS-1$ 			
			System.out.println(msg);
	
			t.start();
		}
		
		buildWPBS(elementXml, sup);
		
		if ( debug ) {
			t.stop();
			msg = t.getTime() + " mini seconds building WPBS for " + LibraryUtil.getTypeName(element)  ; //$NON-NLS-1$ 			
			System.out.println(msg);
			
			msg = t.getTotalTime() + " mini seconds building layout xml for " + LibraryUtil.getTypeName(element)  ; //$NON-NLS-1$ 			
			System.out.println(msg);
		}
		
		
//		// for test only
//		ProcessLayoutData data = new ProcessLayoutData(getOwningProcess().getGuid());
//		loadLayoutData(data, true, true, true);
		
		return elementXml;
	}

	private String getUserDiagramText(SupportingMaterial userDiagram)
	{
		// user defined diagram
		AbstractElementLayout l = new GeneralLayout();
		l.init(getLayoutMgr(), userDiagram.getPresentation());
		l.setContentTarget(element);
		EStructuralFeature feature = UmaPackage.eINSTANCE.getContentDescription_MainDescription();
		return (String)l.getAttributeFeatureValue(feature);		
	}
	
	private void setColumns(XmlElement parentXml, List cols) {
		XmlElement colsXml = parentXml.newChild("columns"); //$NON-NLS-1$
		for (Iterator it = cols.iterator(); it.hasNext(); ) {
			BSColumn col = (BSColumn)it.next();
			colsXml.newChild("column") //$NON-NLS-1$
				.setAttribute("id", col.id) //$NON-NLS-1$
				.setAttribute("label", col.label); //$NON-NLS-1$
		}
	}
	
	private void buildWBS(XmlElement elementXml, Suppression sup)
	{
		// build the breakdown structure tree
		XmlElement bs = elementXml
				.newChild("breakdown").setAttribute("name", "Work Breakdown Structure") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				.setAttribute("DisplayName", getDisplayName()); //$NON-NLS-1$

		// set the columns
		setColumns(bs, PreferenceUtil.getWBSColumns());
		
		// publish the consolidated view
		ComposedAdapterFactory adapterFactory = layoutManager
				.getCBSAdapterFactory();
		CompositeRoles crs = null; //new CompositeRoles(adapterFactory, (Activity) super.element);
		// if ( super.element instanceof Process )
		{
			ProcessUtil.updateIDs(adapterFactory, sup.getProcess());
		}

		ActivityLayoutSetting setting = new ActivityLayoutSetting(
				adapterFactory, crs, sup);

		// escape the quotes in the string sicne we set the string into javascript variables in the layout
		setting.escapeString = true;
		
		// set to only show task descriptors for sub-activities
		setting.showTaskOnly = true;
		
		// need to get the raw item provider from the adapter factory
		Object wrapper = sup.getObjectByPath(super.paths, adapterFactory);
		if ( wrapper == null ) {
			wrapper = super.element;
		} 
		
		if ( sup.isSuppressed(wrapper) ) {
			return;
		}
		
		ProcessElementItem elementItem = new ProcessElementItem(wrapper, super.element, super.elementProcessPath);
		iterate(elementItem, bs, setting);
		

		XmlElement diagrams = elementXml.newChild("diagrams"); //$NON-NLS-1$
		
		String diagramType;
		String imgFile;
		diagramType = ResourceHelper.DIAGRAM_TYPE_WORKFLOW;
		SupportingMaterial userDiagram = userDiagramInfo.getActivityDiagram();
		if ( userDiagramInfo.canPublishADImage() && (userDiagram != null) )
		{				
			diagrams.newChild("userdiagram") //$NON-NLS-1$
				.setAttribute("name", diagramType) //$NON-NLS-1$
				.setValue(getUserDiagramText(userDiagram));
		}
		else
		{
			org.eclipse.epf.diagram.model.util.DiagramInfo uddInfo = getRealizedUDD(sup, diagramType);
			boolean generatedDiagram = true;
			if(uddInfo != null){
				userDiagram = uddInfo.getActivityDiagram();
				if(uddInfo.canPublishADImage() && userDiagram != null){
					diagrams.newChild("userdiagram") //$NON-NLS-1$
					.setAttribute("name", diagramType) //$NON-NLS-1$
					.setValue(getUserDiagramText(userDiagram));
					generatedDiagram = false;
				}
			}
			
			if(generatedDiagram){
				imgFile = ResourceHelper.getDiagramFilePathName(element, diagramType);
				DiagramInfo diagram_workflow = generateDiagram(sup, diagramType, imgFile);	
				if (diagram_workflow != null
					&& diagram_workflow.getImageFileName() != null) {
				diagrams.newChild("diagram") //$NON-NLS-1$
						.setAttribute("name", ResourceHelper.DIAGRAM_TYPE_WORKFLOW) //$NON-NLS-1$
						.setAttribute("alt", getDiagramDisplayName(ResourceHelper.DIAGRAM_TYPE_WORKFLOW)) //$NON-NLS-1$
						//.setValue(diagram_workflow.getHTML());
						.addChild(diagram_workflow.getXmlElement());
				}
			}
		}
		
		diagramType = ResourceHelper.DIAGRAM_TYPE_ACTIVITY_DETAIL;
		userDiagram = userDiagramInfo.getActivityDetailDiagram();
		if ( userDiagramInfo.canPublishADDImage() && (userDiagram != null) )
		{				
			diagrams.newChild("userdiagram") //$NON-NLS-1$
				.setAttribute("name", diagramType) //$NON-NLS-1$
				.setValue(getUserDiagramText(userDiagram));
		}
		else
		{
			imgFile = ResourceHelper.getDiagramFilePathName(element, diagramType);
			DiagramInfo diagram_detail = generateDiagram(sup, diagramType, imgFile);	
			if (diagram_detail != null && diagram_detail.getImageFileName() != null) {
				diagrams
						.newChild("diagram") //$NON-NLS-1$
						.setAttribute("name", ResourceHelper.DIAGRAM_TYPE_ACTIVITY_DETAIL) //$NON-NLS-1$
						.setAttribute(
								"alt", getDiagramDisplayName(ResourceHelper.DIAGRAM_TYPE_ACTIVITY_DETAIL)) //$NON-NLS-1$
						//.setValue(diagram_detail.getHTML());
						.addChild(diagram_detail.getXmlElement());
			}
		}
		
		diagramType = ResourceHelper.DIAGRAM_TYPE_WP_DEPENDENCY;
		userDiagram = userDiagramInfo.getWPDDiagram();
		if ( userDiagramInfo.canPublishWPDImage() && (userDiagram != null) )
		{				
			diagrams.newChild("userdiagram") //$NON-NLS-1$
				.setAttribute("name", diagramType) //$NON-NLS-1$
				.setValue(getUserDiagramText(userDiagram));
		}
		else
		{
			imgFile = ResourceHelper.getDiagramFilePathName(element, diagramType);
			DiagramInfo diagram_wp = generateDiagram(sup, diagramType, imgFile);	
			if (diagram_wp != null && diagram_wp.getImageFileName() != null) {
				diagrams.newChild("diagram") //$NON-NLS-1$
						.setAttribute("name", ResourceHelper.DIAGRAM_TYPE_WP_DEPENDENCY) //$NON-NLS-1$
						.setAttribute(
								"alt", getDiagramDisplayName(ResourceHelper.DIAGRAM_TYPE_WP_DEPENDENCY)) //$NON-NLS-1$
						//.setValue(diagram_wp.getHTML());
						.addChild(diagram_wp.getXmlElement());
			}
		}
	}
	
	private String getDiagramDisplayName(String type) {
	
		String name = getDisplayName();
		if ( ResourceHelper.DIAGRAM_TYPE_WORKFLOW.equals(type) ) {
			return NLS.bind(LibraryResources.activityDiagramName, name);		
		} else if ( ResourceHelper.DIAGRAM_TYPE_ACTIVITY_DETAIL.equals(type) ) {
			return NLS.bind(LibraryResources.activityDetailDiagramName, name);		
		} else if ( ResourceHelper.DIAGRAM_TYPE_WP_DEPENDENCY.equals(type) ) {
			return NLS.bind(LibraryResources.wpDependencyDiagramName, name);		
		} else {
			return ""; //$NON-NLS-1$
		}
	}
	
//	private DiagramInfo generateDiagram(Suppression sup, String diagramType, String imgFile) {
//		
////		if ( "_o3nZoSFrEdqrX8YVzvtlIg,_jin2oCGGEdqMcovRzkCQow".equals(super.elementProcessPath) ) {
////			System.out.println("xx");
////		}
//		
//		DiagramInfo info = null;
//		ElementLayoutManager mgr = getLayoutMgr();
//		if (mgr != null) {
//			info = mgr.getCachedDiagramInfo(sup, diagramType, imgFile);
//			if (info != null) {
//				System.err.println("*** diagram generated: " + info.path + ",  file name: " + imgFile);
//
//				return info;
//			}
//		}
//		info = generateDiagram_(sup, diagramType, imgFile);
//		if ( info != null ) {
//			info.path = super.elementProcessPath;
//		}
//		
//		if (mgr != null) {
//			mgr.addCachedDiagramInfo(info, sup, diagramType, imgFile);
//		}
//		return info;
//	}
	
	private DiagramInfo generateDiagram(Suppression sup, String diagramType, String imgFile)
	{
		Timer timer = null;
		if (debug ){
			System.out.println("START: generating diagram " + imgFile);
			timer = new Timer();			
		}
		// generate diagram
		// show the activity diagrams
		IActivityDiagramService diagramService = layoutManager
				.getActivityDiagramService();
		DiagramInfo diagram = null;
		if (diagramService != null) {
			IFilter filter = layoutManager.getDiagramAdapterFactory().getFilter();
			
			// get the wrapper from the WBS adapter factory
			Object wrapper = sup.getObjectByPath(super.paths, layoutManager.getDiagramAdapterFactory());
			
			// Set the publishing mode
			boolean publishingmode = LibraryUtil.PUBLISH_MODE;
			LibraryUtil.PUBLISH_MODE = true;

			diagram = diagramService.saveDiagram(wrapper,
					imgFile,
					diagramType, filter, sup);
			
			// set back to 
			LibraryUtil.PUBLISH_MODE = publishingmode;
		}

		if ( timer != null ){
			timer.stop();	
			String msg = timer.getTime() + " mini seconds generating " + diagramType + " diagram"  ; //$NON-NLS-1$ //$NON-NLS-2$ 			
			System.out.println(msg);
			System.out.println("END: generating diagram " + imgFile);
		}
		
		return diagram;

	}
	
	private org.eclipse.epf.diagram.model.util.DiagramInfo getRealizedUDD(Suppression sup, String diagramType)
	{
		// generate diagram
		// show the activity diagrams
		IActivityDiagramService diagramService = layoutManager
				.getActivityDiagramService();
		if (diagramService != null) {
			IFilter filter = layoutManager.getDiagramAdapterFactory().getFilter();
			
			// get the wrapper from the WBS adapter factory
			Object wrapper = sup.getObjectByPath(super.paths, layoutManager.getDiagramAdapterFactory());

			Object realized = diagramService.getRealizedForUnmodified(wrapper, filter, sup);
			
			if(realized instanceof Activity){
				org.eclipse.epf.diagram.model.util.DiagramInfo uddInfo = new org.eclipse.epf.diagram.model.util.DiagramInfo(
						(Activity)realized);
				if(uddInfo.canPublishADImage()){
					return uddInfo; 
				}
			}
		}
		return null;
	}
	
	private void buildTBS(XmlElement elementXml, Suppression sup)
	{
		XmlElement bs = elementXml
		.newChild("breakdown").setAttribute("name", "Team Breakdown Structure") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		.setAttribute("DisplayName", getDisplayName()); //$NON-NLS-1$

		// set the columns
		setColumns(bs, PreferenceUtil.getTBSColumns());

		ComposedAdapterFactory adapterFactory = layoutManager.getTBSAdapterFactory();
		CompositeRoles crs = null; //new CompositeRoles(adapterFactory, (Activity) super.element);
		
		// roolup the layout
		IBSItemProvider provider = (IBSItemProvider) adapterFactory.adapt(
				super.element, ITreeItemContentProvider.class);
				
		// need to get the raw item provider from the adapter factory
		Object wrapper = sup.getObjectByPath(super.paths, adapterFactory);
		if ( wrapper == null ) {
			wrapper = super.element;
		}
		ProcessElementItem elementItem = new ProcessElementItem(wrapper, super.element, super.elementProcessPath);

		// collect all RoleDescriptors before rollup
		provider.setRolledUp(false);
		itemDetail.iterate(adapterFactory, wrapper);

		provider.setRolledUp(true);		
		ActivityLayoutSetting setting = new ActivityLayoutSetting(adapterFactory, crs, sup);
		setting.rollupRoles = true;
		setting.escapeString = true;

		iterate(elementItem, bs, setting);
	}
	
	private void buildWPBS(XmlElement elementXml, Suppression sup)
	{
		XmlElement bs = elementXml
		.newChild("breakdown").setAttribute("name", "Work Product Breakdown Structure") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		.setAttribute("DisplayName", getDisplayName()); //$NON-NLS-1$

		// set the columns
		setColumns(bs, PreferenceUtil.getWPBSColumns());

		ComposedAdapterFactory adapterFactory = layoutManager.getWPBSAdapterFactory();
		CompositeRoles crs = null; //new CompositeRoles(adapterFactory, (Activity) super.element);
		
		// roolup the layout
		IBSItemProvider provider = (IBSItemProvider) adapterFactory.adapt(super.element,
				ITreeItemContentProvider.class);
		provider.setRolledUp(true);
		
		ActivityLayoutSetting setting = new ActivityLayoutSetting(adapterFactory, crs, sup);
		setting.escapeString = true;

		// need to get the raw item provider from the adapter factory
		Object wrapper = sup.getObjectByPath(super.paths, adapterFactory);
		if ( wrapper == null ) {
			wrapper = super.element;
		}
		ProcessElementItem elementItem = new ProcessElementItem(wrapper, super.element, super.elementProcessPath);
		iterate(elementItem, bs, setting);

	}

	/**
	 * iterate the break down structure and build the xml document
	 * 
	 * @param parentItem
	 *            The object to iterate. It can be a breakdown element, or it's
	 *            adaptor
	 * @param parentXml
	 * @param adapterFactory
	 */
	private void iterate(ProcessElementItem parentItem, XmlElement parentXml,
			ActivityLayoutSetting setting) {
		iterate(parentItem, parentXml, setting, 0);
	}
	
	// level to expand all BWS activities to, 0 for the first level
	private static final int ACTIVITY_SHOW_LEVEL = 1;
	
	/**
	 * iterate the break down structure and build the xml document
	 * 
	 * @param parentItem
	 *            The object to iterate. It can be a breakdown element, or it's
	 *            adaptor
	 * @param parentXml
	 * @param adapterFactory
	 */
	private void iterate(ProcessElementItem parentItem, XmlElement parentXml,
			ActivityLayoutSetting setting, int actLevel) {
		ITreeItemContentProvider provider = null;
		Object parentObj = parentItem.rawItem;
			
		Timer timer = null;
		if (debug ){
			timer = new Timer();			
		}
		
		if (parentObj instanceof ITreeItemContentProvider) {
			provider = (ITreeItemContentProvider) parentObj;
		} else {
			provider = (ITreeItemContentProvider) setting.adapterFactory.adapt(
					parentObj, ITreeItemContentProvider.class);
		}

		// Either delegate the call or return nothing.
		if (provider != null) {
//			String displayName = ProcessUtil.getAttribute(parentObj,
//					IBSItemProvider.COL_PRESENTATION_NAME, provider);
//			parentXml.setAttribute("DisplayName", displayName); //$NON-NLS-1$

			//List uniqueList = new ArrayList();
			Collection items = provider.getChildren(parentObj);
			for (Iterator it = items.iterator(); it.hasNext();) {
				Object rawitem = it.next();

				MethodElement item = (MethodElement) LibraryUtil
						.unwrap(rawitem);

				if ( setting.showTaskOnly && (actLevel > ACTIVITY_SHOW_LEVEL)
						&& !(item instanceof Activity || item instanceof TaskDescriptor) ) {
					continue;
				}

				if ( item == null ) {
					continue;
				}
				
				// add the element to the reference list, 
				// this is for publishing only, for browsing, this call does nothing
				getLayoutMgr().getValidator().addReferencedElement(super.element, item);
				
				ProcessElementItem elementItem = new ProcessElementItem(rawitem, item, parentItem);

				// Process Publishing: Replace role descriptor
				// with composite role
				// if it contains the role descriptor during preview/publishing
				// so if this guy is a RoleDescrptor, find the composite role
				// descriptor within the scope
				// 
				if ((parentObj instanceof Activity && setting.crs != null)
						&& (item instanceof RoleDescriptor)) {
					CompositeRole cr = setting.crs.getCompositeRole(
							(Activity) parentObj, (RoleDescriptor) item);
					if (cr != null) {
						item = cr;
					}
				}

				XmlElement child = generateChildXml(elementItem, parentXml, setting);
					
				parentXml.addChild(child);
									
				// show only task task descriptors for sub activities in the tbs layout
				if ( setting.showTaskOnly && (actLevel > ACTIVITY_SHOW_LEVEL) && !(item instanceof Activity )) {
					// if act level > 0, only iterate the sub-activities
					continue;
				}
				
				// ineterate children, not just activity, any child in the
				// rawitem should be iterated,
				// such as the sub-artifacts
				iterate(elementItem, child, setting, 
						(item instanceof Activity) ? actLevel+1 : actLevel);				
			}
		}
		
		if ( timer != null ) {
			timer.stop();	
			if (timer.getTime() > 100) {
				String msg = timer.getTime() + " mini seconds iterating breakdown item " + LibraryUtil.getTypeName(parentItem.element)  ; //$NON-NLS-1$ 		
				System.out.println(msg);
			}
		}
	}

	private XmlElement generateChildXml(ProcessElementItem elementItem, XmlElement parentXml,
			ActivityLayoutSetting setting)
	{
		Timer timer = null;
		if (debug ){
			timer = new Timer();			
		}
		
		MethodElement item = elementItem.element;
		
		IElementLayout l = getLayout(elementItem);
	
		// lat the presentation to determine when to show
		// set generate the flag for browsing
		boolean isSupressed = setting.sup.isSuppressed(elementItem.rawItem);
		if ( isSupressed ) {
			itemDetail.addSuppressed(elementItem.element);
		}
		
		XmlElement child = l.getXmlElement(false);

		// we still generate the item even though it's suppressed, 
		// let the layout javascript to handle the show or hide
		// set the isSupressed flag for browsing model only,
		// for publishing, the flag will be geenrated and saved in a seperated js file
		// published html pages will get the isSupressed flag via javascript method.
		if ( !getLayoutMgr().isPublishingMode() )
		{
			child.setAttribute("isSupressed", (isSupressed ? "true" : "false") ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}
		
		IBSItemProvider adapter = null;
		if (elementItem.rawItem instanceof IBSItemProvider) {
			adapter = (IBSItemProvider) elementItem.rawItem;
		} else {
			adapter = (IBSItemProvider) setting.adapterFactory
					.adapt(elementItem.element, ITreeItemContentProvider.class);
			;
		}

		// get the index and predecessor indeces
		if (elementItem.element instanceof BreakdownElement) {
			String index = getIndex(adapter);
			
			String modelInfo = null;			
			if (adapter instanceof ComposedWPDescriptorWrapperItemProvider) {
				ComposedWPDescriptorWrapperItemProvider provider = (ComposedWPDescriptorWrapperItemProvider) adapter;
				modelInfo = provider.getAttribute(item, IBSItemProvider.COL_MODEL_INFO);
			} else {
				modelInfo = ProcessUtil.getAttribute(item,
						IBSItemProvider.COL_MODEL_INFO, adapter);
			}			
			
			String team = ProcessUtil.getAttribute(item,
					IBSItemProvider.COL_TEAMS, adapter);
			String prefix = ProcessUtil.getAttribute(item,
					IBSItemProvider.COL_PREFIX, adapter);			
			String isEventDriven = ProcessUtil.getAttribute(item,
					IBSItemProvider.COL_IS_EVENT_DRIVEN, adapter);
			String isOngoing = ProcessUtil.getAttribute(item,
					IBSItemProvider.COL_IS_ONGOING, adapter);
			String isOptional = ProcessUtil.getAttribute(item,
					IBSItemProvider.COL_IS_OPTIONAL, adapter);
			String isPlanned = ProcessUtil.getAttribute(item,
					IBSItemProvider.COL_IS_PLANNED, adapter);
			String isRepeatable = ProcessUtil.getAttribute(item,
					IBSItemProvider.COL_IS_REPEATABLE, adapter);
			String hasMultipleOccurrences = ProcessUtil
					.getAttribute(
							item,
							IBSItemProvider.COL_HAS_MULTIPLE_OCCURRENCES,
							adapter);
			
			String displayName = ProcessUtil.getAttribute(item,
					IBSItemProvider.COL_PRESENTATION_NAME, adapter);
			
			String mName = ProcessUtil.getAttribute(item,
					IBSItemProvider.COL_NAME, adapter);

			// for WBS layout we put the string into javascript variables
			// so need to escape the quotes " and '
			if ( setting.escapeString )
			{
				modelInfo = StrUtil.escape(modelInfo);
				displayName = XMLUtil.escape(displayName);
				mName = XMLUtil.escape(mName);
				
				// and the url
				// need an escaped url for javascript
				String jsEscapedUrl = StrUtil.escape(l.getUrl());
				child.setAttribute("Url", jsEscapedUrl); //$NON-NLS-1$

			}
			
			child.setAttribute("Index", index) //$NON-NLS-1$
					.setAttribute("ModelInfo", modelInfo) //$NON-NLS-1$
					.setAttribute("Team", team); //$NON-NLS-1$

			child.newChild("attribute").setAttribute("name", "prefix").setValue(prefix); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			
			child
					.newChild("attribute").setAttribute("name", "isEventDriven").setValue(isEventDriven); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 
			child
					.newChild("attribute").setAttribute("name", "isOngoing").setValue(isOngoing); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 
			child
					.newChild("attribute").setAttribute("name", "isOptional").setValue(isOptional); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 
			child
					.newChild("attribute").setAttribute("name", "isPlanned").setValue(isPlanned); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 
			child
					.newChild("attribute").setAttribute("name", "isRepeatable").setValue(isRepeatable); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 
			child
					.newChild("attribute").setAttribute("name", "hasMultipleOccurrences").setValue(hasMultipleOccurrences); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 

			child.setAttribute("DisplayName", displayName); //$NON-NLS-1$
			child.setAttribute("Name", mName); //$NON-NLS-1$
		}		

		if (item instanceof WorkProductDescriptor) {
			String entryState = adapter.getAttribute(item, IBSItemProvider.COL_ENTRY_STATE);
			String exitState = adapter.getAttribute(item, IBSItemProvider.COL_EXIT_STATE);
			String deliverable = adapter.getAttribute(item, IBSItemProvider.COL_DELIVERABLE);

			child.setAttribute("EntryState", entryState) //$NON-NLS-1$
					.setAttribute("ExitState", exitState) //$NON-NLS-1$
					.setAttribute("Deliverable", deliverable); //$NON-NLS-1$
		}

		if (item instanceof WorkBreakdownElement) {
			String predecessors = getPredecessors(adapter,
					setting.sup);
			child.setAttribute("Predecessors", predecessors); //$NON-NLS-1$
		}

		// if it's a task descriptor, get the steps
		if (item instanceof TaskDescriptor) {

			XmlElement stepsXml = child.newChild("Steps"); //$NON-NLS-1$
			TaskDescriptor td = (TaskDescriptor) item;
			List selSteps = td.getSelectedSteps();
			Task t = (Task) ConfigurationHelper
					.getCalculatedElement(td.getTask(),
							getLayoutMgr().getConfiguration());
			if (t != null) {
				List steps = ConfigurationHelper
						.calc0nFeatureValue(t, UmaPackage.eINSTANCE
								.getTask_Steps(), getLayoutMgr()
								.getElementRealizer());
				for (int i = 0; i < steps.size(); i++) {
					Object step = steps.get(i);
					boolean selected = selSteps.contains(step);
					stepsXml
							.newChild("Step") //$NON-NLS-1$
							.setAttribute(
									"index", Integer.toString(i)) //$NON-NLS-1$
							.setAttribute(
									"selected", selected ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				}
			}

		}

		// build the team profile tree.
		// This is a temporary replacement for the team breakdown
		// structure diagram
		if (item instanceof TeamProfile) {
			TeamProfile superTeam = ((TeamProfile)item).getSuperTeam();
			child.setAttribute("hasSuperTeam", (superTeam != null) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}

		// if role rollup is set, build the role sub tree
		if (setting.rollupRoles && item instanceof RoleDescriptor) {
			buildRoleRollup((RoleDescriptor) item, child, setting);
		}
		
		if ( timer != null ) {
			timer.stop();	
			if (timer.getTime() > 100) {
				String msg = timer.getTime() + " mini seconds generating xml for breakdown item " + LibraryUtil.getTypeName(elementItem.element)  ; //$NON-NLS-1$ 		
				System.out.println(msg);
			}
		}
		
		return child;
	}
	
	
	private void buildRoleRollup(RoleDescriptor roleItem, XmlElement parentXml,
			ActivityLayoutSetting setting) {
		Role r = roleItem.getRole();
		List descriptors = itemDetail.getDescriptors(r);
		if ( descriptors == null ) {
			descriptors = new ArrayList();
		}
		if ( !descriptors.contains(roleItem) ) {
			descriptors.add(roleItem);
		}
		
		List responsibleFor = new ArrayList();
		List modifies = new ArrayList();
		List primaryTasks = new ArrayList();
		List additionalTasks = new ArrayList();	
		List items;
		
		for ( Iterator it = descriptors.iterator(); it.hasNext(); ) {
			
			roleItem = (RoleDescriptor) it.next();
			
			items = ConfigurationHelper.calc0nFeatureValue(roleItem,
					UmaPackage.eINSTANCE.getRoleDescriptor_ResponsibleFor(), 
					getLayoutMgr().getElementRealizer());
			responsibleFor.addAll(items);
				
			items = ConfigurationHelper.calc0nFeatureValue(roleItem,
					UmaPackage.eINSTANCE.getRoleDescriptor_Modifies(), getLayoutMgr().getElementRealizer());
			modifies.addAll(items);
			
			items = ConfigurationHelper.calc0nFeatureValue(roleItem,
					AssociationHelper.RoleDescriptor_PrimaryTaskDescriptors,
					getLayoutMgr().getElementRealizer());
			primaryTasks.addAll(items);
			
			items = ConfigurationHelper.calc0nFeatureValue(roleItem,
					AssociationHelper.RoleDescriptor_AdditionalTaskDescriptors, 
					getLayoutMgr().getElementRealizer());
			additionalTasks.addAll(items);
		}
		
		Collections.sort(responsibleFor, Comparators.PRESENTATION_NAME_COMPARATOR);
		createRoleRollupNodes(parentXml, responsibleFor, TngUtil
				.getFeatureText(UmaPackage.eINSTANCE.getRoleDescriptor_ResponsibleFor()));

		Collections.sort(modifies, Comparators.PRESENTATION_NAME_COMPARATOR);
		createRoleRollupNodes(parentXml, modifies, TngUtil
				.getFeatureText(UmaPackage.eINSTANCE.getRoleDescriptor_Modifies()));

		Collections.sort(primaryTasks, Comparators.PRESENTATION_NAME_COMPARATOR);
		createRoleRollupNodes(parentXml, primaryTasks, 
				LibraryResources.ActivityLayout_primaryTasks_text); 

		Collections.sort(additionalTasks, Comparators.PRESENTATION_NAME_COMPARATOR);
		createRoleRollupNodes(parentXml, additionalTasks, 
				LibraryResources.ActivityLayout_additionalTasks_text); 

	}
	
	private void createRoleRollupNodes(XmlElement parentXml, List items,
			String info) {
		
		// 160188 - Published Team Allocation tab shows redundant information
		// only show one descriptor if more than one are linked to the same task or wp.
		// so keep the processed task and wp instead of the descriptors
		List processed = new ArrayList();
		MethodElement linked = null;
		for (Iterator it = items.iterator(); it.hasNext();) {
			MethodElement e = (MethodElement) it.next();
			linked = null;
			if ( e instanceof TaskDescriptor ) {
				linked = ((TaskDescriptor)e).getTask();
			} else if ( e instanceof WorkProductDescriptor ) {
				linked = ((WorkProductDescriptor)e).getWorkProduct();
			}
			if ( linked == null ) {
				linked = e;
			}
			
			if ( processed.contains(linked) ) {
				continue;
			}
			
			processed.add(linked);
			
			IElementLayout l = layoutManager.getLayout(e, true);
			XmlElement child = l.getXmlElement(false);
			child.setAttribute("ModelInfo", info); //$NON-NLS-1$
			parentXml.addChild(child);
		}

	}


	private String getIndex(IBSItemProvider adapter) {
		// IBSItemProvider adapter = (IBSItemProvider) factory.adapt(e,
		// ITreeItemContentProvider.class);;
		if (adapter != null) {
			int index = adapter.getId();
			if (index == 0) {
				return ""; //$NON-NLS-1$
			}
			return Integer.toString(index);
		}

		return ""; //$NON-NLS-1$
	}

	private String getPredecessors(IBSItemProvider adapter, Suppression sup) {
		// IBSItemProvider adapter = (IBSItemProvider) factory.adapt(e,
		// ITreeItemContentProvider.class);;
		if (adapter != null) {
			PredecessorList list = adapter.getPredecessors();
			if (list != null) {
				return list.toUnSuppressedString(sup, true);
			}
		}

		return ""; //$NON-NLS-1$
	}

	public class CompositeRoles {
		// a map of activity to CompositeRoleInfo
		Map itemMap = new HashMap();

		public CompositeRoles(ComposedAdapterFactory adapterFactory,
				Activity act) {
			scan(adapterFactory, null, act);
		}

		private CompositeRoleInfo getCompositeRoleInfo(Activity parent,
				Activity act) {
			CompositeRoleInfo info = (CompositeRoleInfo) itemMap.get(act);
			if (info == null) {
				info = new CompositeRoleInfo(parent, act);
				itemMap.put(act, info);
			}

			return info;
		}

		private void scan(ComposedAdapterFactory adapterFactory,
				Activity parent, Activity act) {
			ITreeItemContentProvider provider = (ITreeItemContentProvider) adapterFactory
					.adapt(act, ITreeItemContentProvider.class);
			if (provider != null) {
				Collection items = provider.getChildren(act);
				for (Iterator it = items.iterator(); it.hasNext();) {
					MethodElement item = (MethodElement) LibraryUtil.unwrap(it
							.next());
					if (item instanceof CompositeRole) {
						getCompositeRoleInfo(parent, act).addCompositeRole(
								(CompositeRole) item);
					} else if (item instanceof Activity) {
						scan(adapterFactory, act, (Activity) item);
					}
				}
			}
		}

		/**
		 * find the composite role for the role descriptor from the activity and
		 * it's parents, return null if not found
		 * 
		 * @param activity
		 * @param item
		 * @return RoleDescriptor
		 */
		private CompositeRole getCompositeRole(Activity activity,
				RoleDescriptor item) {
			// iterate the breakdown elements,
			// if there is a composite role that contains the role, return the
			// composite,
			// if not, find in the parent activity

			if (activity == null) {
				return null;
			}

			CompositeRole desc = null;
			CompositeRoleInfo info = (CompositeRoleInfo) itemMap.get(activity);
			if (info != null) {
				desc = info.getCompositeRole(item);
				if (desc != null) {
					return desc;
				}

				return getCompositeRole(info.getParentActivity(), item);
			}

			return null;
		}
	}

	public class CompositeRoleInfo {
		Activity parent;

		Activity owner;

		List items = new ArrayList();

		public CompositeRoleInfo(Activity parent, Activity owner) {
			this.parent = parent;
			this.owner = owner;
		}

		private void addCompositeRole(CompositeRole e) {
			if (!items.contains(e)) {
				items.add(e);
			}
		}

		private Activity getParentActivity() {
			return parent;
		}

		private CompositeRole getCompositeRole(RoleDescriptor item) {
			if (items.size() == 0) {
				return null;
			}

			Role r = item.getRole();
			for (Iterator it = items.iterator(); it.hasNext();) {
				CompositeRole cr = (CompositeRole) it.next();
				if (cr.getAggregatedRoles().contains(r)) {
					return cr;
				}
			}

			return null;
		}
	}

	public class ActivityLayoutSetting {
		public ComposedAdapterFactory adapterFactory;

		public CompositeRoles crs;

		public Suppression sup;

		boolean rollupRoles = false;

		public boolean escapeString = false;
		
		// set to show task only for sub activities
		// this only apply to CBS layout
		public boolean showTaskOnly = false;
		
		public ActivityLayoutSetting(ComposedAdapterFactory adapterFactory,
				CompositeRoles crs, Suppression sup) {
			this.adapterFactory = adapterFactory;
			this.crs = crs;
			this.sup = sup;

		}
	}

	public class TBSItemDetail {
		
		// record the suppressed items
		List suppressedItems = new ArrayList();
		
		// map of role to role descriptors
		Map roleDescriptorMap = new HashMap();
		
		public TBSItemDetail() {
			
		}
		
		public void addSuppressed(Object item) {
			if ( !suppressedItems.contains(item) ) {
				suppressedItems.add(item);
			}
		}
		
		public void iterate(ComposedAdapterFactory adapterFactory, Object parentObj) {
		
			ITreeItemContentProvider provider = null;
			if (parentObj instanceof ITreeItemContentProvider) {
				provider = (ITreeItemContentProvider) parentObj;
			} else {
				provider = (ITreeItemContentProvider) adapterFactory.adapt(
						parentObj, ITreeItemContentProvider.class);
			}

			// Either delegate the call or return nothing.
			if (provider == null) {
				return;
			}
				
			Collection items = provider.getChildren(parentObj);
			for (Iterator it = items.iterator(); it.hasNext();) {
				Object rawitem = it.next();

				MethodElement item = (MethodElement) LibraryUtil.unwrap(rawitem);
				if ( item instanceof RoleDescriptor ) {
					addRoleDescriptor( (RoleDescriptor)item );
				} else {
					iterate(adapterFactory, rawitem);
				}
			}
		}
		
		
		private void addRoleDescriptor(RoleDescriptor rdesc) {
			Role r = rdesc.getRole();
			if (r != null ) {
				List items = (List)roleDescriptorMap.get(r);
				if ( items == null ) {
					items = new ArrayList();
					roleDescriptorMap.put(r, items);
					if (debug ) {
						System.out.println("Added RoleDescriptor " + rdesc.getPresentationName()); //$NON-NLS-1$
					}
				}
				
				if ( !items.contains(rdesc) ) {
					items.add(rdesc);
				}
			}
		}
		
		public List getDescriptors(Role r) {
			return (List)roleDescriptorMap.get(r);
		}
	}
	
	/**
	 * load the process specific layout data for publishing.
	 * browsing does not need this since it's generated on the fly
	 * @param proc_data
	 */
	public void loadLayoutData(ProcessLayoutData proc_data, boolean loadWbs, boolean loadTbs, boolean loadWpbs)
	{
		Timer t = new Timer();		

		ActivityLayoutData act_data = proc_data.createActivityLauoutData(this.elementProcessPath);
		
		// iterate the breakdown structure and collect the info.
		Process proc = getOwningProcess();
		if ( proc == this.element ) {
			supCount = 0;
		}
		
		// need to handle the supressed breakdown elements
		// use the Supress utility
		Suppression sup = getSuppression(proc);

		// need to interate the 3 layout structure sicne their path is different
		if ( loadWbs ) {
			loadWBSLayoutData(act_data, sup);
		}
		
		if ( loadTbs ) {
			loadTBSLayoutData(act_data, sup);
		}
		
		if ( loadWpbs ) {
			loadWPBSLayoutData(act_data, sup);
		}
		
		if ( debug ) {
			t.stop();
			String msg = t.getTime()
					+ " mini-second(s) loading layout data for process " + LibraryUtil.getTypeName(proc) //$NON-NLS-1$ /
					+ ", activity: " + LibraryUtil.getTypeName(super.element); //$NON-NLS-1$ /			
			System.out.println(msg);
		}
	}
	
	private void loadWBSLayoutData(ActivityLayoutData act_data, Suppression sup)
	{
		// publish the consolidated view
		ComposedAdapterFactory adapterFactory = layoutManager
				.getCBSAdapterFactory();
		CompositeRoles crs = null; //new CompositeRoles(adapterFactory, (Activity) super.element);

		ActivityLayoutSetting setting = new ActivityLayoutSetting(
				adapterFactory, crs, sup);

		// need to get the raw item provider from the adapter factory
		Object wrapper = sup.getObjectByPath(super.paths, adapterFactory);
		if ( wrapper == null ) {
			wrapper = super.element;
		}
		ProcessElementItem elementItem = new ProcessElementItem(wrapper, super.element, super.elementProcessPath);
		iterateProcessItem(elementItem, act_data, setting, true, false, false);

//		// if there is no process-local supressed item, don't generate diagrams
		// no, this will not work, since the text color ofd the diagram is green, if use base, it's black.
		// so need to generate the diagram no matter what.
//		if ( !act_data.hasLocalSuppressed() )
//		{
//			return;
//		}
		
		String diagramType, imgFile;
		
		// make a short prefix for the file name
		String prefix = Integer.toHexString(super.elementProcessPath.hashCode());
		
		diagramType = ResourceHelper.DIAGRAM_TYPE_WORKFLOW;
		imgFile = ResourceHelper.getDiagramFilePathName(element, prefix + "_" + diagramType); //$NON-NLS-1$
		DiagramInfo diagram_workflow = generateDiagram(sup, diagramType, imgFile);	
		if (diagram_workflow != null
				&& diagram_workflow.getImageFileName() != null) {
			act_data.setActivityDiagramPath(diagram_workflow.getImageFileName());
		}
		
		diagramType = ResourceHelper.DIAGRAM_TYPE_ACTIVITY_DETAIL;
		imgFile = ResourceHelper.getDiagramFilePathName(element, prefix + "_" + diagramType); //$NON-NLS-1$
		DiagramInfo diagram_detail = generateDiagram(sup, diagramType, imgFile);	
		if (diagram_detail != null && diagram_detail.getImageFileName() != null) {
			act_data.setActivityDetailDiagramPath(diagram_detail.getImageFileName());
		}

		diagramType = ResourceHelper.DIAGRAM_TYPE_WP_DEPENDENCY;
		imgFile = ResourceHelper.getDiagramFilePathName(element, prefix + "_" + diagramType); //$NON-NLS-1$
		DiagramInfo diagram_wp = generateDiagram(sup, diagramType, imgFile);	
		if (diagram_wp != null && diagram_wp.getImageFileName() != null) {
			act_data.setWPDependencyDiagramPath(diagram_wp.getImageFileName());
		}

	}
	
	private void loadTBSLayoutData(ActivityLayoutData act_data, Suppression sup)
	{
		// publish the consolidated view
		ComposedAdapterFactory adapterFactory = layoutManager
				.getTBSAdapterFactory();
		CompositeRoles crs = null; //new CompositeRoles(adapterFactory, (Activity) super.element);

		// roolup the layout
		IBSItemProvider provider = (IBSItemProvider) adapterFactory.adapt(
				super.element, ITreeItemContentProvider.class);
		provider.setRolledUp(true);

		
		ActivityLayoutSetting setting = new ActivityLayoutSetting(
				adapterFactory, crs, sup);
		setting.rollupRoles = true;

		
		// need to get the raw item provider from the adapter factory
		Object wrapper = sup.getObjectByPath(super.paths, adapterFactory);
		if ( wrapper == null ) {
			wrapper = super.element;
		}
		ProcessElementItem elementItem = new ProcessElementItem(wrapper, super.element, super.elementProcessPath);
		iterateProcessItem(elementItem, act_data, setting, false, true, false);

	}
	
	private void loadWPBSLayoutData(ActivityLayoutData act_data, Suppression sup)
	{
		// publish the consolidated view
		ComposedAdapterFactory adapterFactory = layoutManager
				.getWPBSAdapterFactory();
		CompositeRoles crs = null; //new CompositeRoles(adapterFactory, (Activity) super.element);

		// roolup the layout
		IBSItemProvider provider = (IBSItemProvider) adapterFactory.adapt(
				super.element, ITreeItemContentProvider.class);
		provider.setRolledUp(true);
	
		ActivityLayoutSetting setting = new ActivityLayoutSetting(
				adapterFactory, crs, sup);

		
		// need to get the raw item provider from the adapter factory
		Object wrapper = sup.getObjectByPath(super.paths, adapterFactory);
		if ( wrapper == null ) {
			wrapper = super.element;
		}
		ProcessElementItem elementItem = new ProcessElementItem(wrapper, super.element, super.elementProcessPath);
		iterateProcessItem(elementItem, act_data, setting, false, false, true);

	}
	
	private static int supCount = 0;
	
	private void iterateProcessItem(ProcessElementItem parentItem, ActivityLayoutData act_data, 
			ActivityLayoutSetting setting, boolean loadWbs, boolean loadTbs, boolean loadWpbs) {
		
		//String msg = " --- iterate process item " + LibraryUtil.getTypeName(parentItem.element) + "[" + parentItem.path + "]" ; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 			
		//System.out.println(msg);

		ITreeItemContentProvider provider = null;
		Object parentObj = parentItem.rawItem;
		
		if (parentObj instanceof ITreeItemContentProvider) {
			provider = (ITreeItemContentProvider) parentObj;
		} else {
			provider = (ITreeItemContentProvider) setting.adapterFactory.adapt(
					parentObj, ITreeItemContentProvider.class);
		}

		// Either delegate the call or return nothing.
		if (provider != null) {
			Collection items = provider.getChildren(parentObj);
			for (Iterator it = items.iterator(); it.hasNext();) {
				Object rawitem = it.next();			
				
//				// lat the presentation to determine when to show
//				// set generate the flag for browsing
				boolean isSupressed = setting.sup.isSuppressed(rawitem);
				MethodElement item = (MethodElement) LibraryUtil
						.unwrap(rawitem);
								
				ProcessElementItem elementItem = new ProcessElementItem(rawitem, item, parentItem);

				if (debug && isSupressed ) {
					System.out.println("suppressed: " + ++supCount + " : "  //$NON-NLS-1$ //$NON-NLS-2$
							+ LibraryUtil.getTypeName(item) 
							+ ": " + elementItem.path); //$NON-NLS-1$
					
				}

				IElementLayout l = getLayout(elementItem);
				if ( l instanceof AbstractProcessElementLayout )
				{		
					if ( isSupressed )
					{
						String relPath = ((AbstractProcessElementLayout)l).getRelativeProcessPath();
						act_data.setSuppressed(relPath);
					} 
					else 
					{				
						// only iterate un-suppressed item
						// if the layout is an activity layout, collect the layout data for it
						if ( l instanceof ActivityLayout )
						{
							((ActivityLayout)l).loadLayoutData(act_data.getProcessLayoutData(), 
								 loadWbs, loadTbs, loadWpbs);
						}
						else
						{
							// ineterate children, not just activity, any child in the
							// rawitem should be iterated,
							// such as the sub-artifacts
							iterateProcessItem(elementItem, act_data, setting, loadWbs, loadTbs, loadWpbs);						
						}
					}
				}
			}
		}
	}	
	
	/**
	 * get all the linked tasks, roles, and workproducts for this activity and all it's breakdown elements, recursively.
	 * the element found are notified via IContentValidator.addReferencedElement()
	 * 
	 */
	public void findAllLinkedElements() {
		// iterate the breakdown structure and collect the info.
		Process proc = getOwningProcess();
		
		// need to handle the supressed breakdown elements
		// use the Supress utility
		Suppression sup = getSuppression(proc);

		// publish the consolidated view
		ComposedAdapterFactory adapterFactory = layoutManager
				.getCBSAdapterFactory();

		// need to get the raw item provider from the adapter factory
		Object wrapper = sup.getObjectByPath(super.paths, adapterFactory);
		if ( wrapper == null ) {
			wrapper = super.element;
		}
		
		getLayoutMgr().getValidator().addReferencedElement(null, super.element);

		iterateItemForLinkedElements(wrapper, adapterFactory, sup);
	}

	private void iterateItemForLinkedElements(Object parentObj, ComposedAdapterFactory adapterFactory, Suppression sup) {
		
		ITreeItemContentProvider provider = null;
		
		if (parentObj instanceof ITreeItemContentProvider) {
			provider = (ITreeItemContentProvider) parentObj;
		} else {
			provider = (ITreeItemContentProvider) adapterFactory.adapt(
					parentObj, ITreeItemContentProvider.class);
		}

		// Either delegate the call or return nothing.
		if (provider == null) {
			return;
		}
		
		Collection items = provider.getChildren(parentObj);
		for (Iterator it = items.iterator(); it.hasNext();) {
			Object rawitem = it.next();			
			
			if ( sup.isSuppressed(rawitem) ) {
				continue;
			}
			
			MethodElement item = (MethodElement) LibraryUtil
					.unwrap(rawitem);
			MethodElement e = null;
			if ( item instanceof TaskDescriptor ) {
				e = ((TaskDescriptor)item).getTask();
			} else if ( item instanceof RoleDescriptor ) {
				e = ((RoleDescriptor)item).getRole();
			} else if ( item instanceof WorkProductDescriptor ) {
				e = ((WorkProductDescriptor)item).getWorkProduct();
			} 
			
			if ( e != null ) {
				getLayoutMgr().getValidator().addReferencedElement(item, e);
			} 
				
			MethodElement parent = (MethodElement) LibraryUtil.unwrap(rawitem);
			getLayoutMgr().getValidator().addReferencedElement(parent, item);

			iterateItemForLinkedElements(rawitem, adapterFactory, sup);
		}
	}	
}
