//------------------------------------------------------------------------------
// Copyright (c) 2005, 2007 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.publishing.services;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
import org.eclipse.epf.common.serviceability.DebugTrace;
import org.eclipse.epf.common.utils.FileUtil;
import org.eclipse.epf.common.utils.StrUtil;
import org.eclipse.epf.common.utils.Timer;
import org.eclipse.epf.library.configuration.ConfigurationFilter;
import org.eclipse.epf.library.configuration.ConfigurationHelper;
import org.eclipse.epf.library.edit.IFilter;
import org.eclipse.epf.library.edit.TngAdapterFactory;
import org.eclipse.epf.library.edit.configuration.PracticeSubgroupItemProvider;
import org.eclipse.epf.library.edit.process.IBSItemProvider;
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.Bookmark;
import org.eclipse.epf.library.layout.IElementLayout;
import org.eclipse.epf.library.layout.elements.ActivityLayout;
import org.eclipse.epf.library.layout.elements.ProcessElementItem;
import org.eclipse.epf.library.layout.elements.ProcessLayoutData;
import org.eclipse.epf.library.layout.elements.SummaryPageLayout;
import org.eclipse.epf.library.layout.util.XmlElement;
import org.eclipse.epf.library.util.LibraryUtil;
import org.eclipse.epf.publishing.PublishingPlugin;
import org.eclipse.epf.publishing.PublishingResources;
import org.eclipse.epf.publishing.util.PublishingUtil;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.Artifact;
import org.eclipse.epf.uma.ContentCategory;
import org.eclipse.epf.uma.DeliveryProcess;
import org.eclipse.epf.uma.Descriptor;
import org.eclipse.epf.uma.Discipline;
import org.eclipse.epf.uma.Guidance;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodPackage;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.Practice;
import org.eclipse.epf.uma.Process;
import org.eclipse.epf.uma.ProcessElement;
import org.eclipse.epf.uma.Role;
import org.eclipse.epf.uma.SupportingMaterial;
import org.eclipse.epf.uma.Task;
import org.eclipse.epf.uma.Tool;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.WorkProduct;
import org.eclipse.epf.uma.util.AssociationHelper;

/**
 * Builds the views defined for a method configuration.
 * 
 * @author Shilpa Toraskar
 * @author Jinhua Xi
 * @author Kelvin Low
 * @since 1.0
 */
public class ConfigurationViewBuilder extends AbstractViewBuilder {

	private static final String PREFIX_Reference_Workflows = "Reference_Workflows"; //$NON-NLS-1$

	private static final String PREFIX_Tasks = "Tasks"; //$NON-NLS-1$

	private static final String PREFIX_ResponsibleFor_Tasks = "Primarily_Performs"; //$NON-NLS-1$

	private static final String PREFIX_ParticipatesIn_Tasks = "Additionally_Performs"; //$NON-NLS-1$

	private static final String PREFIX_Performing_Roles = "Performing_Roles"; //$NON-NLS-1$
	
	private static final String PREFIX_Input_Work_Products = "Input_Work_Products"; //$NON-NLS-1$

	private static final String PREFIX_Output_Work_Products = "Output_Work_Products"; //$NON-NLS-1$

	private static final String PREFIX_Work_Products_Created = "Responsible_For"; //$NON-NLS-1$

	private static final String PREFIX_Work_Products_Modified = "Modifies"; //$NON-NLS-1$

	private static final String PREFIX_Responsible_Role = "Responsible_Role"; //$NON-NLS-1$

	private static final String PREFIX_Containing_Work_Product = "Containing_Work_Product"; //$NON-NLS-1$

	private static final String PREFIX_Contained_Work_Products = "Contained_Work_Products"; //$NON-NLS-1$

	private static final String PREFIX_Guidances = "Guidance"; //$NON-NLS-1$

	private static final String PREFIX_InputTo_Task = "Input_to"; //$NON-NLS-1$

	private static final String PREFIX_OutputOf_Task = "Output_from"; //$NON-NLS-1$

	private static final String ICON_FOLDER = DefaultNodeIconResources
			.getIconName("folder"); //$NON-NLS-1$

	private static final String NODE_Reference_Workflows = PublishingResources.referenceWorkflowsNode_text; //$NON-NLS-1$

	private static final String NODE_Tasks = PublishingResources.taskNode_text; //$NON-NLS-1$

	private static final String NODE_ResponsibleFor_Tasks = PublishingResources.primarilyPerformsNode_text; //$NON-NLS-1$

	private static final String NODE_ParticipatesIn_Tasks = PublishingResources.additionallyPerformsNode_text; //$NON-NLS-1$

	private static final String NODE_Performing_Roles = PublishingResources.performingRolesNode_text; //$NON-NLS-1$

	private static final String NODE_Input_Work_Products = PublishingResources.inputWorkProductsNode_text; //$NON-NLS-1$

	private static final String NODE_Output_Work_Products = PublishingResources.outputWorkProductsNode_text; //$NON-NLS-1$

	private static final String NODE_Work_Products_Created = PublishingResources.responsibleForNode_text; //$NON-NLS-1$

	private static final String NODE_Work_Products_Modified = PublishingResources.modifiesNode_text; //$NON-NLS-1$

	private static final String NODE_Responsible_Role = PublishingResources.responsibleRoleNode_text; //$NON-NLS-1$

	private static final String NODE_Containing_Work_Product = PublishingResources.containingWorkProductNode_text; //$NON-NLS-1$

	private static final String NODE_Contained_Work_Products = PublishingResources.containedWorkProductsNode_text; //$NON-NLS-1$

	private static final String NODE_Guidances = PublishingResources.guidanceNode_text; //$NON-NLS-1$

	private static final String NODE_InputTo_Task = PublishingResources.inputToNode_text; //$NON-NLS-1$

	private static final String NODE_OutputOf_Task = PublishingResources.outputFromNode_text; //$NON-NLS-1$

	private static final String PROCESS_LAYOUT_DATA_FILE = "/scripts/processElementData.js"; //$NON-NLS-1$

	private static final Class ITreeItemContentProviderClass = ITreeItemContentProvider.class;

	protected static boolean debug = PublishingPlugin.getDefault()
			.isDebugging();

	protected List<Bookmark> bookmarks = new ArrayList<Bookmark>();

	protected AdapterFactory adapterFactory;

	protected IProgressMonitor monitor = null;

	protected EObjectComparator nameComparator = new EObjectComparator();

	/**
	 * Creates a new instance.
	 */
	public ConfigurationViewBuilder(ISiteGenerator siteGenerator) {
		super(siteGenerator);
	}

	/**
	 * Build the views defined in the configuration and publish the related
	 * contents.
	 * 
	 * @param monitor
	 *            IProgressMonitor
	 * @return List a list of Bookmarks for the views
	 */
	public List<Bookmark> buildViews(IProgressMonitor monitor) {
		this.monitor = monitor;

		// System.out.println("Building views..."); //$NON-NLS-1$

		long startTime = 0L;

		if (config != null) {
			
// already done in PublishManager
//			// first of all, we need to load the library,
//			// otherwise, some relationships and opposite features are not
//			// established
//			monitor.subTask(PublishingResources.loadLibraryTask_name);
//			if (profiling) {
//				startTime = System.currentTimeMillis();
//			}
//			LibraryUtil.loadAll((MethodLibrary) config.eContainer());
//			if (profiling) {
//				DebugTrace.print(this, "buildViews", "LibraryUtil.loadAll: " //$NON-NLS-1$  //$NON-NLS-2$
//								+ (System.currentTimeMillis() - startTime)
//								+ " ms"); //$NON-NLS-1$
//			}

			// create a filter that does not discard the contributors.
			// so we get the contributors in to show in the navigation tree
			IFilter configFilter = new ConfigurationFilter(config, false);
			adapterFactory = TngAdapterFactory.INSTANCE
					.getConfigurationView_AdapterFactory(configFilter);

			if (options != null && options.isPublishProcess()) {
				makeProcessClosure();
			}

			// publish all the views in the configuration
			if (profiling) {
				startTime = System.currentTimeMillis();
			}
			List views = LibraryUtil.getValidViews(config);
			for (Iterator it = views.iterator(); it.hasNext();) {
				if (monitor.isCanceled()) {
					return null;
				}

				ContentCategory v = (ContentCategory) it.next();
				if (!ConfigurationHelper.canShow(v, config)) {
					continue;
				}

				Object element = LibraryUtil.unwrap(v);
				Bookmark b = createBookmark(this.monitor, element);

				if (v == config.getDefaultView()) {
					super.defaultView = b;
				}

				// iterate thru configuration to build the view
				iterate(v, b);
				if (b.getChildCount() > 0) {
					bookmarks.add(b);
				}
			}
			if (profiling) {
				System.out.println("Time taken to publish bookmarks: " //$NON-NLS-1$
						+ (System.currentTimeMillis() - startTime) + " ms"); //$NON-NLS-1$
			}

			if (monitor.isCanceled()) {
				return null;
			}
		}

		if (profiling) {
			startTime = System.currentTimeMillis();
		}
		publishReferenceElements();
		if (profiling) {
			DebugTrace.print(this, "publishReferenceElements", //$NON-NLS-1$
					(System.currentTimeMillis() - startTime) + " ms"); //$NON-NLS-1$
		}

		// copyIconsForNonApplet();

		if (monitor.isCanceled()) {
			return null;
		}

		// save published element urls
		if (profiling) {
			startTime = System.currentTimeMillis();
		}
		saveElementUrls();
		if (profiling) {
			DebugTrace.print(this, "saveElementUrls", //$NON-NLS-1$
					(System.currentTimeMillis() - startTime) + " ms"); //$NON-NLS-1$
		}

		return bookmarks;
	}

	/**
	 * The process element closure is generated as follows:
	 * <p>
	 * 1. publish the selected processses, which brings in all the related
	 * process elements
	 * <p>
	 * 2. publish all the referenced process elements from step 1, this brings
	 * in all the directly referenced content elements. make a first level
	 * closure to include the published elements and the referenced elements.
	 * Any direct references to any type of guidances are also in this closure.
	 * <p>
	 * 3. publish all the referened non-ContentCategory content elements from
	 * step 2. based on the first level closure. The purpose of the first level
	 * closure is to allow bring in guidances with valid element link and any
	 * other references such as a Task or Role, being linked with a missing
	 * element link. This again brings in all the direct references
	 * <p>
	 * 4.Make the final closure by including the following elements:
	 * <p>
	 * a. all published elements from step 1,2,3.
	 * <p>
	 * b. all referenced Guidances from step 3
	 * <p>
	 * c. all Guidances of type Practice, RoadMap, Suporting Material, and Term
	 * Definition, in the configuration
	 * <p>
	 * d. all Content Categories that contains at least one element of type a,
	 * b, or c. and their parent categories
	 * <p>
	 * The selected view is published based on the element closure defined
	 * above.
	 */
	private void makeProcessClosure() {
		monitor.subTask(PublishingResources.buildingProcessClosureTask_name);

		// publish the selected processes
		// need to build a closure of all the elements involved in the
		// processes
		List<Process> processes = options.getProcesses();
		if (processes != null && processes.size() > 0) {
			for (Iterator<Process> it = processes.iterator(); it.hasNext();) {
				makeProcessClosure(it.next());
				if (monitor.isCanceled()) {
					return;
				}
			}
		}

		// make the first level closure to include all the process elements and
		// it's referenced elements
		// any thing except Guidances and ContentCategories outside the closure
		// is filtered
		getValidator()
				.addClosureElements(getValidator().getPublishedElements());
		getValidator().addClosureElements(
				getValidator().getReferencedElements());

		// now publish all referenced elements, any direct references in the
		// process elements are
		// part of the closure
		// don't publish content categories for now since they might be empty
		// and discarded later
		List refs = new ArrayList(getValidator().getReferencedElements());
		for (Iterator it = refs.iterator(); it.hasNext();) {
			MethodElement e = (MethodElement) it.next();
			if (!(e instanceof ContentCategory)) {
				super.publish(monitor, e);

				// collect process specific layout info with suppression status
				// this will incldue the diagrams and the supression states of
				// each item under the current procee
				if (LibraryUtil.isProcess(e)) {
					publishProcessLayout((org.eclipse.epf.uma.Process) e);
				}

			}
		}

		// now, any referenced guidance should be in the closure,
		// so include them and make the final closure
		refs.clear();
		for (Iterator it = getValidator().getReferencedElements().iterator(); it
				.hasNext();) {
			MethodElement e = (MethodElement) it.next();
			if (e instanceof Guidance) {
				refs.add(e);
			}
		}

		if (refs.size() > 0) {
			getValidator().addClosureElements(refs);
		}

		// now all the published elements are the element closure, make the
		// final closure
		getValidator().makeElementClosure();
	}

	private void makeProcessClosure(org.eclipse.epf.uma.Process proc) {

		if (proc == null) {
			return;
		}

		if (ConfigurationHelper.canShow(proc, config)) {
			ActivityLayout l = new ActivityLayout();
			l.init(getLayoutMgr(), proc, proc, null);
			l.findAllLinkedElements();
		}

		if (monitor.isCanceled()) {
			return;
		}

		if (ConfigurationHelper.isExtender(proc)) {
			org.eclipse.epf.uma.Process baseProc = (org.eclipse.epf.uma.Process) proc
					.getVariabilityBasedOnElement();
			if (ConfigurationHelper.inConfig(baseProc, config)) {
				makeProcessClosure(baseProc);
			}
		}

	}

	private void publishReferenceElements() {
		// now process the referenced elements and publish the contents
		while (getValidator().getReferencedElements().size() > 0) {
			MethodElement e = (MethodElement) getValidator()
					.getReferencedElements().remove(0);

			try {
				if (monitor.isCanceled()) {
					return;
				}

				// references to method plugins and method packages can be
				// ignored
				if (e instanceof MethodPlugin || e instanceof MethodPackage) {
					continue;
				}

				long startTime = System.currentTimeMillis();

				super.publish(monitor, e);

				// collect process specific layout info with suppression status
				// this will incldue the diagrams and the supression states of
				// each item under the current procee
				if (LibraryUtil.isProcess(e)) {
					// long startTime1 = System.currentTimeMillis();
					publishProcessLayout((org.eclipse.epf.uma.Process) e);
					// long endTime1 = System.currentTimeMillis();
					// System.out.println("Published process " + e.getName() +
					// ": " + (endTime1 - startTime1) + " ms");
				}

				long endTime = System.currentTimeMillis();
				long timeTaken = endTime - startTime;
				if (timeTaken >= 5000) {
					System.out.println("Published " + e.getName() + ": " //$NON-NLS-1$ //$NON-NLS-2$
							+ timeTaken + " ms"); //$NON-NLS-1$
				}

			} catch (Exception ex) {
				ex.printStackTrace();
				getValidator().logError(e, "Error publishing element", ex); //$NON-NLS-1$
			}
		}
	}

	private void publishProcessLayout(final org.eclipse.epf.uma.Process e) {

		Runnable runnable = new Runnable() {
			public void run() {
				try {
					ActivityLayout layout = new ActivityLayout();
					layout.init(getLayoutMgr(),
							(org.eclipse.epf.uma.Process) e, null, null);
					ProcessLayoutData pd = new ProcessLayoutData(e.getGuid());
					layout.loadLayoutData(pd, true, true, true);
					printLayoutScript(pd);
					pd.clear();
				} catch (Exception e1) {
					getValidator()
							.logError(
									e,
									"Error publishing process specific layout data", e1); //$NON-NLS-1$
				}

			}
		};

		Timer timer = new Timer();
		try {

			// run the publishing and check the time, if timeout, terminate it
			Thread t = new Thread(runnable);
			t.start();
			t.join(TIMEOUT_INTERVAL);
			if (t.isAlive()) {
				// wait for the thread to die and log an error
				timer.stop();
				getValidator()
						.logInfo(
								e,
								"publishing process specific layout data takes " + timer.getTime() + " mini seconds already and is still not done yet ..."); //$NON-NLS-1$ //$NON-NLS-2$
				timer.start();
				t.join();
			}
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		} finally {
			timer.stop();
			getValidator()
					.logInfo(
							e,
							timer.getTotalTime()
									+ " mini seconds publishing process specific layout data"); //$NON-NLS-1$
		}

	}

	private void printLayoutScript(ProcessLayoutData data) {
		File outputFile = new File(getLayoutMgr().getPublishDir(),
				PROCESS_LAYOUT_DATA_FILE); //$NON-NLS-1$
		PrintWriter pw = null;
		try {
			// create a stream with append enabled
			FileOutputStream os = new FileOutputStream(outputFile, true);

			// create a write with utf-8 encoding
			OutputStreamWriter writer = new OutputStreamWriter(os, "utf-8"); //$NON-NLS-1$

			// create a print writer with auto flush
			pw = new PrintWriter(writer, true);
			data.print(pw);
		} catch (Exception e) {
			getValidator().logError("unable to save process layout data", e); //$NON-NLS-1$

		} finally {
			if (pw != null) {
				pw.flush();
				pw.close();
			}
		}

	}

	/**
	 * Iterate thru tuee
	 * 
	 * @param obj
	 * @param parent
	 */
	private void iterate(Object obj, Bookmark parent) {
		try {
			if (monitor.isCanceled()) {
				return;
			}

			// Get the adapter from the factory.
			ITreeItemContentProvider treeItemContentProvider = null;
			if (obj instanceof ITreeItemContentProvider) {
				treeItemContentProvider = (ITreeItemContentProvider) obj;
			} else {
				treeItemContentProvider = (ITreeItemContentProvider) adapterFactory
						.adapt(obj, ITreeItemContentProvider.class);
			}
		
			// Either delegate the call or return nothing.
			if (treeItemContentProvider != null) {
				Collection items = treeItemContentProvider.getChildren(obj);
				for (Iterator it = items.iterator(); it.hasNext();) {
					if (monitor.isCanceled()) {
						return;
					}

					// create bookmark
					Object itorObj = it.next();
					Object element = LibraryUtil.unwrap(itorObj);

					if ((element instanceof MethodElement)) {
						MethodElement me = (MethodElement) element;
						try {
							if (ConfigurationHelper.canShow(me, config)) {
								me = ConfigurationHelper
										.getCalculatedElement(me,
												getLayoutMgr()
														.getElementRealizer());
								if (me != null) {
									if (me instanceof Tool) {
										buildToolSubTree((Tool) me, parent);
									} else if (me instanceof Discipline) {
										buildDisciplineSubTree((Discipline) me,
												parent);
									}

									// else if (me instanceof DisciplineGrouping
									// || me instanceof Domain || me instanceof
									// WorkProductType
									// || me instanceof RoleSetGrouping || me
									// instanceof RoleSet )
									else if (me instanceof ContentCategory) {

										ContentCategory cc = (ContentCategory) me;

										// if the content category is empty,
										// don't add to the parent
										Bookmark b = createBookmark(
												this.monitor, cc);
										iterate(itorObj, b);
										if (options.isPublishEmptyCategories()
												|| b.getChildCount() > 0) {
											parent.addChild(b);
											discardEmptyCategory(cc, false);
										} else {
											discardEmptyCategory(cc, true);
										}
									} else {
										if (itorObj instanceof PracticeSubgroupItemProvider) {
											buildPracticeSubgroupTree(obj, parent,
													(PracticeSubgroupItemProvider) itorObj);
										} else {										
											Bookmark b = createBookmark(me, parent);
											if (!buildSubTree(itorObj, me, b)) {
												iterate(itorObj, b);
											}
										}
									}
								}
							}
						} catch (Exception e) {
							String message = "Error building navigation tree for " + LibraryUtil.getTypeName(me); //$NON-NLS-1$
							getHtmlBuilder().getValidator()
									.logError(message, e);
							e.printStackTrace();
						}
					} else {
						if (itorObj instanceof PracticeSubgroupItemProvider) {
							buildPracticeSubgroupTree(obj, parent, (PracticeSubgroupItemProvider) itorObj);
						} else {
							iterate(itorObj, parent);
						}
					}

				}
			}
		} catch (Exception e) {
			String message = "Error building navigation tree"; //$NON-NLS-1$
			getHtmlBuilder().getValidator().logError(message, e);

			e.printStackTrace();
		}
	}

	/**
	 * create a bookmark under the specified parent. If no parent is specified,
	 * 
	 * @param monitor
	 * @param element
	 * @param parent
	 * @return
	 */
	protected Bookmark createBookmark(Object element, Bookmark parent) {
		Bookmark b = createBookmark(this.monitor, element);
		if (parent == null) {
			bookmarks.add(b);
		} else {
			parent.addChild(b);
		}

		return b;
	}

	/**
	 * build the sub tree for the given element. return true if the element is
	 * handled, false otherwise
	 * 
	 * @param element
	 * @param bm
	 * @return boolean
	 */
	private boolean buildSubTree(Object obj, MethodElement element, Bookmark bm) {
		if (element instanceof Task) {
			buildTaskSubTree((Task) element, bm);
		} else if (element instanceof Role) {
			buildRoleSubTree((Role) element, bm);
		} else if (element instanceof WorkProduct) {
			buildWorkProductSubTree((WorkProduct) element, bm);
		} else if (LibraryUtil.isProcess(element)) {
			buildProcessSubTree(obj, (org.eclipse.epf.uma.Process) element, bm);
		} else {
			// System.out.println("Not handled: " + element);
			return false;
		}

		return true;
	}

	private void buildItems(List elements, Bookmark bm) {
		buildItems(elements, bm, false);
	}

	private void buildItems(List elements, Bookmark bm, boolean buildSubTree) {
		for (Iterator it = elements.iterator(); it.hasNext();) {
			if (monitor.isCanceled()) {
				return;
			}

			MethodElement element = (MethodElement) it.next();

			// filter away the containment child-element if any of the parent(s)
			// are in the list
			// 00384619 - Published site: Display of WPs under responsible role
			// if the container of the element is in the list, ignore it
			if (ConfigurationHelper.isContainmentElement(element)
					&& ConfigurationHelper.isContainerInList(element, elements,
							config)) {
				continue;
			}

			buildItem(element, bm, buildSubTree);
		}
	}

	private Bookmark buildItem(MethodElement element, Bookmark parent,
			boolean buildSubTree) {
		if (monitor.isCanceled()) {
			return null;
		}

		Bookmark b = null;

		// make sure the element is showable
		MethodElement e = ConfigurationHelper.getCalculatedElement(element,
				getLayoutMgr().getElementRealizer());
		if (isVisible(e)) {
			b = createBookmark(this.monitor, e);
			if (b == null) {
				return b;
			}

			parent.addChild(b);

			if (buildSubTree) {
				if (e instanceof Artifact) {
					buildContainedArtifactsSubTree((Artifact) e, b, true);
				}
			}
		}

		return b;
	}

//	/**
//	 * create the folder bookmark and it's children. generate the folder summary
//	 * page
//	 * 
//	 * @param element
//	 * @param bm
//	 * @param nodeName
//	 * @param items
//	 */
//
//	private Bookmark createFolderBookmark(MethodElement element, Bookmark bm,
//			String nodeName, List items, boolean createChildren) {
//		Bookmark b = null;
//		if (items.size() > 0) {
//			IElementLayout l = new SummaryPageLayout(getHtmlBuilder()
//					.getLayoutManager(), element, nodeName, items);
//			String url = l.getUrl();
//			getHtmlBuilder().generateHtml(l);
//			b = createBookmark(nodeName, EcoreUtil.generateUUID(), url,
//					ICON_FOLDER, ICON_FOLDER, null);
//			bm.addChild(b);
//			if (createChildren) {
//				buildItems(items, b);
//			}
//		}
//
//		return b;
//	}

	Set<String> summaryPagesGenerated = new HashSet<String>();
	
	private Bookmark createFolderBookmark(MethodElement element, Bookmark bm,
			String prefixName, String nodeName, List items,
			boolean createChildren) {
		Bookmark b = null;
		if (items.size() > 0) {
			IElementLayout l = new SummaryPageLayout(getHtmlBuilder()
					.getLayoutManager(), element, prefixName, nodeName, items);
			String url = l.getUrl();
			
			// don't regenerate the page
			// 200619 - Summary page html was generated multiple times when publishing
			if ( !summaryPagesGenerated.contains(url) ) {
				getHtmlBuilder().generateHtml(l);
				summaryPagesGenerated.add(url);
			}
			
			b = createBookmark(nodeName, EcoreUtil.generateUUID(), url,
					ICON_FOLDER, ICON_FOLDER, null);
			bm.addChild(b);
			if (createChildren) {
				buildItems(items, b);
			}
		}

		return b;
	}
	
	private void buildPracticeSubgroupTree(Object providerParent,
			Bookmark parent, PracticeSubgroupItemProvider provider) {
		Collection children = provider.getChildren(null);
		List items = children instanceof List ? (List) children
				: new ArrayList(children);

		if (items != null && items.size() > 0) {
			Practice practice = provider.getPractice();
			if (practice == null) {
				return;
			}

			IElementLayout l = new SummaryPageLayout(getHtmlBuilder()
					.getLayoutManager(), practice, provider.getText(null),
					provider.getText(null), items, provider.getText(null));
			String url = l.getUrl();

			if (!summaryPagesGenerated.contains(url)) {
				getHtmlBuilder().generateHtml(l);
				summaryPagesGenerated.add(url);
			}

			Bookmark b = createBookmark(provider.getText(null), EcoreUtil
					.generateUUID(), url, ICON_FOLDER, ICON_FOLDER, null);
			parent.addChild(b);
			this.iterate(provider, b);
		}

	}

	private Bookmark buildDisciplineSubTree(Discipline element, Bookmark parent) {
		String url = ""; //$NON-NLS-1$
		Bookmark b;

		// need to calculate the realized value of the feature
		List items_workflow = calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getDiscipline_ReferenceWorkflows());

		// Tasks in published site under Disciplines are in
		// random order
		// use the adaptor factory to get the childrens
		// List items_task = ConfigurationHelper.calc0nFeatureValue(element,
		// UmaPackage.eINSTANCE.getDiscipline_Tasks(), config);
		List items_task = new ArrayList();
		List item_subDisciplies = new ArrayList();
		ITreeItemContentProvider treeItemContentProvider = (ITreeItemContentProvider) adapterFactory
				.adapt(element, ITreeItemContentProvider.class);
		if (treeItemContentProvider != null) {
			Collection items = treeItemContentProvider.getChildren(element);
			for (Iterator it = items.iterator(); it.hasNext();) {
				if (monitor.isCanceled()) {
					return null;
				}

				// create bookmark
				Object itorObj = it.next();
				Object e = LibraryUtil.unwrap(itorObj);
				if ((e instanceof Task)) {
					MethodElement t = ConfigurationHelper.getCalculatedElement(
							(MethodElement) e, getLayoutMgr()
									.getElementRealizer());
					if (t != null) {
						items_task.add(t);
					}
				} else if (e instanceof Discipline) {
					MethodElement d = ConfigurationHelper.getCalculatedElement(
							(MethodElement) e, getLayoutMgr()
									.getElementRealizer());
					if (d != null) {
						item_subDisciplies.add(d);
					}

				}
			}
		}

		if (monitor.isCanceled()) {
			return null;
		}

		// all guidances
		List items_guidance = new ArrayList();
		items_guidance.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_Assets()));
		items_guidance.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_Checklists()));
		items_guidance.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_ConceptsAndPapers()));
		items_guidance.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_Examples()));
		items_guidance.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_Guidelines()));
		items_guidance.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_SupportingMaterials()));

		if (!options.isPublishEmptyCategories()
				&& items_workflow.size() + items_task.size()
						+ items_guidance.size() + item_subDisciplies.size() == 0) {
			// do nothing, don't show the folder
			discardEmptyCategory(element, true);
			return null;
		}

		if (monitor.isCanceled()) {
			return null;
		}

		// create the item bookmark
		// don't set to the parent yet. make sure it's not empty
		// need to check the sub-disciplines
		// 150984 - Publishing: Nested discipline is not display in the publish
		// page
		// Bookmark bm = createBookmark(element, parent);
		Bookmark bm = createBookmark(this.monitor, element);

		// sub-disciplines come first
		if (item_subDisciplies.size() > 0) {
			for (Iterator it = item_subDisciplies.iterator(); it.hasNext();) {
				Discipline d = (Discipline) it.next();
				buildDisciplineSubTree(d, bm);
			}
		}

		if (options.isPublishLightWeightTree()) {

			Collections.sort(items_workflow, nameComparator);
			Collections.sort(items_task, nameComparator);
			Collections.sort(items_guidance, nameComparator);

			buildItems(items_workflow, bm);
			buildItems(items_task, bm);
			buildItems(items_guidance, bm);
		} else {
			if (items_workflow.size() > 0) {
				Bookmark wfFolder = createFolderBookmark(element, bm,
						PREFIX_Reference_Workflows, NODE_Reference_Workflows,
						items_workflow, false);

				// Capability Patterns in treebrowser under
				// disciplines-reference workflows cannot be expanded
				for (Iterator it = items_workflow.iterator(); it.hasNext();) {
					if (monitor.isCanceled()) {
						return null;
					}

					// 179609 - Exception when assign activity as discipline's
					// referenced workflow
					// this is a model change, referenced workflow can be
					// Activity,
					// old model references Process
					Activity act = (Activity) it.next();
					Bookmark bmWorkflow = buildItem(act, wfFolder, false);
					buildActivitySubTree(act, act, bmWorkflow);
				}
			}

			if (monitor.isCanceled()) {
				return null;
			}

			if (items_task.size() > 0) {
				createFolderBookmark(element, bm, PREFIX_Tasks, NODE_Tasks,
						items_task, true);
			}

			if (monitor.isCanceled()) {
				return null;
			}

			if (items_guidance.size() > 0) {
				createFolderBookmark(element, bm, PREFIX_Guidances,
						NODE_Guidances, items_guidance, true);
			}
		}

		if (options.isPublishEmptyCategories() || bm.getChildCount() > 0) {
			parent.addChild(bm);
			discardEmptyCategory(element, false);
		} else {
			discardEmptyCategory(element, true);
		}

		return bm;
	}

	private void buildActivitySubTree(Object obj, Activity element, Bookmark bm) {
		if (monitor.isCanceled()) {
			return;
		}

		List items = new ArrayList();

		org.eclipse.epf.uma.Process proc = TngUtil.getOwningProcess(element);
		ProcessElementItem procItem = new ProcessElementItem(obj, element,
				element.getGuid());

		ComposedAdapterFactory adapterFactory = super.getLayoutMgr()
				.getWBSAdapterFactory();
		Suppression sup = new Suppression(proc);
		iterateActivity(procItem, bm, adapterFactory, sup);
	}

	private void buildToolSubTree(Tool element, Bookmark parent) {
		if (monitor.isCanceled()) {
			return;
		}

		List items = calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getTool_ToolMentors());
		if (options.isPublishEmptyCategories() || items.size() > 0) {
			Bookmark b = createBookmark(element, parent);
			buildItems(items, b);
			discardEmptyCategory(element, false);
		} else {
			discardEmptyCategory(element, true);
		}
	}

	private void buildTaskSubTree(Task element, Bookmark bm) {

		String url;
		Bookmark b;

		List allItems = new ArrayList();

		// performing roles
		List items = new ArrayList();
		Role r = (Role) calc01FeatureValue(element, UmaPackage.eINSTANCE
				.getTask_PerformedBy());
		if (r != null) {
			items.add(r);
		}
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getTask_AdditionallyPerformedBy()));

		if (items.size() > 0) {
			if (options.isPublishLightWeightTree()) {
				Collections.sort(items, nameComparator);
				allItems.addAll(items);
			} else {
				createFolderBookmark(element, bm, PREFIX_Performing_Roles,
						NODE_Performing_Roles, items, true);
			}
		}

		if (monitor.isCanceled()) {
			return;
		}

		if (!options.isPublishLightWeightTree()) {
			// input work products, need a summary page,
			items = new ArrayList();
			items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
					.getTask_MandatoryInput()));
			items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
					.getTask_OptionalInput()));

			if (items.size() > 0) {
				createFolderBookmark(element, bm, PREFIX_Input_Work_Products,
						NODE_Input_Work_Products, items, true);
			}

			if (monitor.isCanceled()) {
				return;
			}
		}

		// output work products, need a summary page, TODO
		items = calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getTask_Output());

		if (items.size() > 0) {
			if (options.isPublishLightWeightTree()) {
				Collections.sort(items, nameComparator);
				allItems.addAll(items);
			} else {
				createFolderBookmark(element, bm, PREFIX_Output_Work_Products,
						NODE_Output_Work_Products, items, true);
			}
		}

		if (monitor.isCanceled()) {
			return;
		}

		// all guidances
		items.clear();
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_Assets()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_Checklists()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_ConceptsAndPapers()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_Examples()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_Guidelines()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_SupportingMaterials()));
		// Object e = calc01FeatureValue(element, UmaPackage.eINSTANCE
		// .getTask_Estimate());
		// if (e != null) {
		// items.add(e);
		// }
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getTask_ToolMentors()));

		if (items.size() > 0) {
			if (options.isPublishLightWeightTree()) {
				Collections.sort(items, nameComparator);
				allItems.addAll(items);
			} else {
				createFolderBookmark(element, bm, PREFIX_Guidances,
						NODE_Guidances, items, true);
			}
		}

		if (options.isPublishLightWeightTree()) {
			buildItems(allItems, bm);
		}

	}

	private void buildRoleSubTree(Role element, Bookmark bm) {
		String url;
		Bookmark b;

		if (monitor.isCanceled()) {
			return;
		}

		List allItems = new ArrayList();

		// tasks, // need a general overview page, TODO
		// List items = AssociationHelper.getPrimaryTasks(element);
		List items = calc0nFeatureValue(element,
				AssociationHelper.Role_Primary_Tasks);
		if (items.size() > 0) {
			if (options.isPublishLightWeightTree()) {
				Collections.sort(items, nameComparator);
				allItems.addAll(items);
			} else {
				createFolderBookmark(element, bm, PREFIX_ResponsibleFor_Tasks,
						NODE_ResponsibleFor_Tasks, items, true);
			}
		}

		if (monitor.isCanceled()) {
			return;
		}

		if (!options.isPublishLightWeightTree()) {
			// secondary tasks
			items = calc0nFeatureValue(element,
					AssociationHelper.Role_Secondary_Tasks);
			if (items.size() > 0) {
				createFolderBookmark(element, bm, PREFIX_ParticipatesIn_Tasks,
						NODE_ParticipatesIn_Tasks, items, true);
			}
		}

		if (monitor.isCanceled()) {
			return;
		}

		// responsible for work products,
		items = calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getRole_ResponsibleFor());

		if (items.size() > 0) {
			if (options.isPublishLightWeightTree()) {
				Collections.sort(items, nameComparator);
				allItems.addAll(items);
			} else {
				b = createFolderBookmark(element, bm,
						PREFIX_Work_Products_Created,
						NODE_Work_Products_Created, items, false);
				buildItems(items, b, true);
			}
		}

		if (monitor.isCanceled()) {
			return;
		}

		if (!options.isPublishLightWeightTree()) {
			// modifies work products, need a summary page, TODO
			items = calc0nFeatureValue(element, UmaPackage.eINSTANCE
					.getRole_Modifies());
			if (items.size() > 0) {
				b = createFolderBookmark(element, bm,
						PREFIX_Work_Products_Modified,
						NODE_Work_Products_Modified, items, false);
				buildItems(items, b, true);
			}

			if (monitor.isCanceled()) {
				return;
			}
		}

		// all guidances
		items.clear();
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_Assets()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_Checklists()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_ConceptsAndPapers()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_Examples()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_Guidelines()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_SupportingMaterials()));

		if (items.size() > 0) {
			if (options.isPublishLightWeightTree()) {
				Collections.sort(items, nameComparator);
				allItems.addAll(items);
			} else {
				createFolderBookmark(element, bm, PREFIX_Guidances, NODE_Guidances, items, true);
			}
		}

		if (options.isPublishLightWeightTree()) {
			// light weight tree, no sub folders
			buildItems(allItems, bm);
		}
	}

	private void buildWorkProductSubTree(WorkProduct element, Bookmark bm) {
		List items;
		String url = ""; //$NON-NLS-1$
		// Bookmark b;

		if (monitor.isCanceled()) {
			return;
		}

		List allItems = new ArrayList();

		// performing roles, 0.1 reference element will be realized in buildItem
		// multiplicity change for opposite features
		// Role r = AssociationHelper.getResponsibleRole(element);
		items = calc0nFeatureValue(element,
				AssociationHelper.WorkProduct_ResponsibleRoles);
		if (items.size() > 0) {
			if (options.isPublishLightWeightTree()) {
				Collections.sort(items, nameComparator);
				allItems.addAll(items);
			} else {
				createFolderBookmark(element, bm, PREFIX_Responsible_Role,
						NODE_Responsible_Role, items, true);
			}
		}

		if (monitor.isCanceled()) {
			return;
		}

		// containing work products, need a summary page, TODO
		if (element instanceof Artifact) {

			if (!options.isPublishLightWeightTree()) {
				WorkProduct wp = ((Artifact) element).getContainerArtifact();
				// createBookmark(NODE_Containing_Work_Product,
				// NODE_Containing_Work_Product, url, "", ""); //$NON-NLS-1$
				// //$NON-NLS-2$
				if (wp != null) {
					items = new ArrayList();
					items.add(wp);
					createFolderBookmark(element, bm,
							PREFIX_Containing_Work_Product,
							NODE_Containing_Work_Product, items, true);
				}

				if (monitor.isCanceled()) {
					return;
				}
			}

			// contained work products, need a summary page, TODO
			// items = ((Artifact)element).getContainedArtifacts();
			items = calc0nFeatureValue(element, UmaPackage.eINSTANCE
					.getArtifact_ContainedArtifacts());

			// make sure the contained elements does not contain the container,
			// this is possible due to realization, say, the containing element
			// contribute to the container
			items.remove(element);

			if (items.size() > 0) {
				if (options.isPublishLightWeightTree()) {
					Collections.sort(items, nameComparator);
					allItems.addAll(items);
				} else {
					Bookmark b = createFolderBookmark(element, bm,
							PREFIX_Contained_Work_Products,
							NODE_Contained_Work_Products, items, false);

					// for each contained work product, create the nested sub
					// tree
					buildItems(items, b, true);
				}
			}
		}

		if (monitor.isCanceled()) {
			return;
		}

		if (!options.isPublishLightWeightTree()) {
			// input to tasks
			items = new ArrayList();
			items.addAll(calc0nFeatureValue(element,
					AssociationHelper.WorkProduct_MandatoryInputTo_Tasks));
			items.addAll(calc0nFeatureValue(element,
					AssociationHelper.WorkProduct_OptionalInputTo_Tasks));
			if (items.size() > 0) {
				createFolderBookmark(element, bm, PREFIX_InputTo_Task,
						NODE_InputTo_Task, items, true);
			}

			if (monitor.isCanceled()) {
				return;
			}

			// output from tasks
			items = calc0nFeatureValue(element,
					AssociationHelper.WorkProduct_OutputFrom_Tasks);
			if (items.size() > 0) {
				createFolderBookmark(element, bm, PREFIX_OutputOf_Task,
						NODE_OutputOf_Task, items, true);
			}

			if (monitor.isCanceled()) {
				return;
			}
		}

		// all guidances
		items = new ArrayList();
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_Assets()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_Checklists()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_ConceptsAndPapers()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_Examples()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_Guidelines()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_SupportingMaterials()));
		// Object e = calc01FeatureValue(element, UmaPackage.eINSTANCE
		// .getWorkProduct_Estimate());
		// if (e != null) {
		// items.add(e);
		// }
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getWorkProduct_Reports()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getWorkProduct_Templates()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getWorkProduct_ToolMentors()));

		if (items.size() > 0) {
			if (options.isPublishLightWeightTree()) {
				Collections.sort(items, nameComparator);
				allItems.addAll(items);
			} else {
				createFolderBookmark(element, bm, PREFIX_Guidances,
						NODE_Guidances, items, true);
			}
		}

		if (options.isPublishLightWeightTree()) {
			buildItems(allItems, bm);
		}
	}

	private void buildContainedArtifactsSubTree(Artifact element, Bookmark bm,
			boolean showGuidances) {
		if (monitor.isCanceled()) {
			return;
		}

		List items;
		String url = ""; //$NON-NLS-1$

		// contained work products, need a summary page, TODO
		// items = ((Artifact)element).getContainedArtifacts();
		items = calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getArtifact_ContainedArtifacts());

		// make sure the contained elements does not contain the container,
		// this is possible due to realization, say, the containing element
		// contribute to the container
		items.remove(element);

		if (monitor.isCanceled()) {
			return;
		}

		if (items.size() > 0) {
			// Bookmark b = createFolderBookmark(element, bm,
			// NODE_Contained_Work_Products, items, false);

			// for each contained work product, create the nested sub tree
			for (Iterator it = items.iterator(); it.hasNext();) {
				if (monitor.isCanceled()) {
					return;
				}

				Artifact e = (Artifact) it.next();
				buildItem(e, bm, true);
			}
		}

		if (!showGuidances) {
			return;
		}

		if (monitor.isCanceled()) {
			return;
		}

		// all guidances
		items = new ArrayList();
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_Assets()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_Checklists()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_ConceptsAndPapers()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_Examples()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_Guidelines()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getContentElement_SupportingMaterials()));
		// Object e = calc01FeatureValue(element, UmaPackage.eINSTANCE
		// .getWorkProduct_Estimate());
		// if (e != null) {
		// items.add(e);
		// }
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getWorkProduct_Reports()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getWorkProduct_Templates()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getWorkProduct_ToolMentors()));

		if (items.size() > 0) {
			// createFolderBookmark(element, bm, NODE_Guidances, items, true);
			buildItems(items, bm);
		}
	}

	/**
	 * iterate the break down structure and build the xml document
	 * 
	 * @param parentObj
	 *            The object to iterate. It can be a breakdown element, or it's
	 *            adaptor
	 * @param parentXml
	 * @param adapterFactory
	 */
	private void iterateActivity(ProcessElementItem parentItem,
			Bookmark parentBm, ComposedAdapterFactory adapterFactory,
			Suppression sup) {
		if (monitor.isCanceled()) {
			return;
		}

		ITreeItemContentProvider provider = null;
		Object parentObj = parentItem.rawItem;

		if (parentObj instanceof ITreeItemContentProvider) {
			provider = (ITreeItemContentProvider) parentObj;
		} else {
			provider = (ITreeItemContentProvider) adapterFactory.adapt(
					parentObj, ITreeItemContentProvider.class);
		}

		if (provider != null) {
			// String displayName = ProcessUtil.getAttribute(parentObj,
			// IBSItemProvider.COL_PRESENTATION_NAME, provider);
			// parentXml.setAttribute("DisplayName", displayName);

			Collection children = provider.getChildren(parentObj);
			for (Iterator it = children.iterator(); it.hasNext();) {
				if (monitor.isCanceled()) {
					return;
				}

				Object rawitem = it.next();
				if (sup.isSuppressed(rawitem)) {
					continue;
				}

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

				if (!options.showDescriptorsInNavigationTree
						&& (item instanceof Descriptor)) {
					continue;
				}

				ProcessElementItem elementItem = new ProcessElementItem(
						rawitem, item, parentItem);

				Bookmark child = buildItem(elementItem.element, parentBm, false);
				if (child != null) {
					// set the query string
					child.setQueryString(elementItem.getQueryString());

					IBSItemProvider adapter = null;
					if (rawitem instanceof IBSItemProvider) {
						adapter = (IBSItemProvider) rawitem;
					} else {
						adapter = (IBSItemProvider) adapterFactory.adapt(item,
								ITreeItemContentProvider.class);
						;
					}

					String displayName = ProcessUtil.getAttribute(item,
							IBSItemProvider.COL_PRESENTATION_NAME, adapter);
					child.setPresentationName(displayName);

					if (item instanceof Activity) {
						iterateActivity(elementItem, child, adapterFactory, sup);
					}
				}
			}
		}
	}

	private void buildProcessSubTree(Object obj,
			org.eclipse.epf.uma.Process element, Bookmark bm) {
		if (monitor.isCanceled()) {
			return;
		}

		List items = new ArrayList();

		ProcessElementItem procItem = new ProcessElementItem(obj, element,
				element.getGuid());

		ComposedAdapterFactory adapterFactory = super.getLayoutMgr()
				.getWBSAdapterFactory();
		Suppression sup = new Suppression(element);
		iterateActivity(procItem, bm, adapterFactory, sup);

		String url;
		Bookmark b;

		if (monitor.isCanceled()) {
			return;
		}

		// all guidances
		items = new ArrayList();
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getBreakdownElement_Checklists()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getBreakdownElement_Concepts()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getBreakdownElement_Examples()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getBreakdownElement_Guidelines()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getBreakdownElement_ReusableAssets()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getActivity_Roadmaps()));

		// need to include supporting materials as well
		// fix bug: supporting material served as user defined diagram should not 
		// show up in the navigation tree of a published process.	
		org.eclipse.epf.diagram.model.util.DiagramInfo userDiagramInfo = 
				new org.eclipse.epf.diagram.model.util.DiagramInfo(element);
		List v = calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getBreakdownElement_SupportingMaterials());
		for ( Iterator it = v.iterator(); it.hasNext(); ) {
			SupportingMaterial s = (SupportingMaterial)it.next();
			if ( !userDiagramInfo.isDiagram( (SupportingMaterial)s ) ) {
				items.add(s);
			}
		}

		if (element instanceof DeliveryProcess) {
			DeliveryProcess dp = (DeliveryProcess) element;
			items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
					.getDeliveryProcess_CommunicationsMaterials()));
			items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
					.getDeliveryProcess_EducationMaterials()));
		}

		if (items.size() > 0) {
			createFolderBookmark(element, bm, PREFIX_Guidances, NODE_Guidances,
					items, true);
		}
	}

	/**
	 * dispose the object
	 */
	public void dispose() {
		super.dispose();

		adapterFactory = null;
		nameComparator = null;
		bookmarks.clear();
		elementUrls.clear();
		summaryPagesGenerated.clear();
	}

	protected Set elementUrls = new HashSet();

	protected void elementPublished(IElementLayout layout, String htmlfile) {
		// only for process element for now
		// may cover all method elements later
		if (layout.getElement() instanceof ProcessElement) {
			ElementUrl url = new ElementUrl(layout.getElement().getGuid(),
					layout.getUrl(), layout.getDisplayName());
			elementUrls.add(url);
		}
	}

	private void saveElementUrls() {
		// save published element urls
		// need to escape the url and text since it will be assigned to a
		// javascript variable as literal
		XmlElement xml = new XmlElement("ElementUrls"); //$NON-NLS-1$
		for (Iterator it = elementUrls.iterator(); it.hasNext();) {
			ElementUrl url = (ElementUrl) it.next();
			xml.newChild("elementUrl", url.guid) //$NON-NLS-1$
					.setAttribute("text", StrUtil.escape(url.text)) //$NON-NLS-1$
					.setAttribute("url", StrUtil.escape(url.url)); //$NON-NLS-1$
		}

		// StringBuffer buffer = new StringBuffer();
		// buffer.append(XmlHelper.XML_HEADER).append(xml.toXml());
		// File f = new File(getLayoutMgr().getPublishDir(), "ElementUrls.xml");
		// //$NON-NLS-1$
		// FileUtil.writeUTF8File(f.getAbsolutePath(), buffer.toString());

		String html = PublishingUtil.getHtml(xml, "xsl/elementUrls.xsl"); //$NON-NLS-1$
		File f = new File(getLayoutMgr().getPublishDir(),
				PROCESS_LAYOUT_DATA_FILE); //$NON-NLS-1$
		FileUtil.writeUTF8File(f.getAbsolutePath(), html, true);
	}

	/**
	 * data structure to define url of an element
	 * 
	 * @author Jinhua Xi
	 * 
	 */
	public class ElementUrl {

		String guid;
		String url;
		String text;

		/**
		 * constructor
		 * 
		 * @param guid
		 *            String the guid of the element
		 * @param url
		 *            String the url of the element
		 * @param text
		 *            String the text alone with the url
		 */
		public ElementUrl(String guid, String url, String text) {
			this.guid = guid;
			this.url = url;
			this.text = text;
		}
	}

	class EObjectComparator implements Comparator {
		private EStructuralFeature pName = UmaPackage.eINSTANCE
				.getMethodElement_PresentationName();
		private EStructuralFeature name = UmaPackage.eINSTANCE
				.getNamedElement_Name();

		public EObjectComparator() {

		}

		public int compare(Object e1, Object e2) {
			if (e1 instanceof EObject && e2 instanceof EObject) {
				Object v1 = getValue(e1);
				Object v2 = getValue(e2);

				if (v1 == null && v2 == null) {
					return e1.toString().compareTo(e2.toString());
				} else if (v1 == null) {
					return -1;
				} else if (v2 == null) {
					return 1;
				} else {
					return v1.toString().compareTo(v2.toString());
				}
			} else {
				return e1.toString().compareTo(e2.toString());
			}
		}

		private Object getValue(Object e) {
			Object v = null;
			try {
				v = ((EObject) e).eGet(pName);
			} catch (Exception ex) {

			}
			;

			if (v == null || v.toString().length() == 0) {
				try {
					v = ((EObject) e).eGet(name);
				} catch (Exception ex) {

				}
				;
			}

			return v;
		}
	}
}
