//------------------------------------------------------------------------------
// 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.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.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.process.IBSItemProvider;
import org.eclipse.epf.library.edit.util.ProcessUtil;
import org.eclipse.epf.library.edit.util.Suppression;
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.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.Discipline;
import org.eclipse.epf.uma.Guidance;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.epf.uma.MethodPackage;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.ProcessElement;
import org.eclipse.epf.uma.Role;
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;


/**
 * @author Shilpa Toraskar
 * @author Jinhua Xi
 * @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";

	// MethodConfiguration config;
	List bookmarks = new ArrayList();

	AdapterFactory adapterFactory;

	private static final Class ITreeItemContentProviderClass = ITreeItemContentProvider.class;

	protected IProgressMonitor monitor = null;

	protected EObjectComparator nameComparator = new EObjectComparator();
	
	/**
	 * constructor
	 * 
	 * @param builder HtmlBuilder
	 * @param options PublishOptions
	 */
	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 buildViews(IProgressMonitor monitor)
	{
		this.monitor = monitor;

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

		if (config != null)
		{
			// first of all, we need to load the libray,
			// otherwise, some relationships and opposite features are not
			// established
			monitor.subTask(PublishingResources.loadLibraryTask_name); 
			LibraryUtil.loadAll((MethodLibrary)config.eContainer());
			
			// 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, null, false);
			adapterFactory = TngAdapterFactory.INSTANCE.getConfigurationView_AdapterFactory(configFilter);

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

			// publish all the views in the configuration
			List views = config.getProcessViews();
			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 ( monitor.isCanceled() )
			{
				return null;
			}
		}			


		publishReferenceElements();
		
//		copyIconsForNonApplet();
		
		if ( monitor.isCanceled() )
		{
			return null;
		}
		
		// save published element urls
		saveElementUrls();
		
		return bookmarks;
	}	
	
	/**
	 * The process element closure is generated as follows:
	 * 
	 * 1. publish the selected processses, which brings in all the related process elements
	 * 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.
	 * 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
	 * 4. Make the final closure by including the following elements:
	 *     a. all published elements from step 1,2,3. 
	 *     b. all referenced Guidances from step 3
	 *     c. all Guidances of type Practice, RoadMap, Suporting Material, and Term Definition, in the configuration
	 *     d. all Content Categories that contains at least one element of type a, b, or c. and their parent categories
	 *
	 * 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 processes = options.getDeliverProcessList();
		if ( processes != null && processes.size() > 0 ) {
			for (Iterator it = processes.iterator(); it.hasNext(); ) {
				makeProcessClosure( (org.eclipse.epf.uma.Process)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;
				}
								
				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);
				}
			} 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);
					printLayoutScript(pd);
				} 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_millis);
			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.includeEmptyCategories || 
												b.getChildCount() > 0) {
											parent.addChild(b);
											discardEmptyCategory(cc, false);
										} else {
											discardEmptyCategory(cc, true);
										}
									} 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 {
						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 (canShow(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;
	}

	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();
			getHtmlBuilder().generateHtml(l);
			b = createBookmark(nodeName, EcoreUtil.generateUUID(), url, ICON_FOLDER,
					ICON_FOLDER, null);
			bm.addChild(b);
			if (createChildren) {
				buildItems(items, b);
			}
		}

		return 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.includeEmptyCategories && 
				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.generateLightWeightTree ) {
			
			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;
					}
	
					org.eclipse.epf.uma.Process proc = (org.eclipse.epf.uma.Process) it.next();
					Bookmark bmWorkflow = buildItem(proc, wfFolder, false);
					buildProcessSubTree(proc, proc, 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.includeEmptyCategories || bm.getChildCount() > 0) {
			parent.addChild(bm);
			discardEmptyCategory(element, false);
		} else {
			discardEmptyCategory(element, true);
		}
		
		return bm;
	}

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

		List items = calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getTool_ToolMentors());
		if (options.includeEmptyCategories || 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.generateLightWeightTree ) {
				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.generateLightWeightTree ) {
			// 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.generateLightWeightTree ) {
				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.generateLightWeightTree ) {
				Collections.sort(items, nameComparator);
				allItems.addAll(items);
			} else {
				createFolderBookmark(element, bm, PREFIX_Guidances, NODE_Guidances,
						items, true);
			}
		}
		
		if ( options.generateLightWeightTree ) {
			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.generateLightWeightTree ) {
				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.generateLightWeightTree ) {
			// 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.generateLightWeightTree ) {
				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.generateLightWeightTree ) {
			// 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.generateLightWeightTree ) {
				Collections.sort(items, nameComparator);
				allItems.addAll(items);
			} else {
				createFolderBookmark(element, bm, NODE_Guidances, items, true);
			}
		}

		if ( options.generateLightWeightTree ) {
			// 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.generateLightWeightTree ) {
				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.generateLightWeightTree ) {
				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.generateLightWeightTree ) {
					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.generateLightWeightTree ) {
			// 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.generateLightWeightTree ) {
				Collections.sort(items, nameComparator);
				allItems.addAll(items);
			} else {
				createFolderBookmark(element, bm, PREFIX_Guidances, NODE_Guidances,
						items, true);
			}
		}
		
		if ( options.generateLightWeightTree ) {
			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 (!(item instanceof Activity)) {
					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);

					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
				.getActivity_Checklists()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getActivity_Concepts()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getActivity_Examples()));
		items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE
				.getActivity_Guidelines()));

		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();
		
		elementUrls.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");
		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.getDescribableElement_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;
		}
	}
}
