wlu: enhanced process closure
diff --git a/1.5/plugins/org.eclipse.epf.library/src/org/eclipse/epf/library/layout/DefaultContentValidator.java b/1.5/plugins/org.eclipse.epf.library/src/org/eclipse/epf/library/layout/DefaultContentValidator.java
index 0e48447..7e26d2a 100644
--- a/1.5/plugins/org.eclipse.epf.library/src/org/eclipse/epf/library/layout/DefaultContentValidator.java
+++ b/1.5/plugins/org.eclipse.epf.library/src/org/eclipse/epf/library/layout/DefaultContentValidator.java
@@ -196,6 +196,10 @@
 	public boolean isDiscarded(MethodElement owner, Object feature, MethodElement e) {
 		return false;
 	}
+	
+	public boolean isDiscarded(MethodElement owner, Object feature, MethodElement e, MethodConfiguration config) {
+		return false;
+	}
 
 	public void dispose() {
 	}
diff --git a/1.5/plugins/org.eclipse.epf.library/src/org/eclipse/epf/library/layout/IContentValidator.java b/1.5/plugins/org.eclipse.epf.library/src/org/eclipse/epf/library/layout/IContentValidator.java
index cf1f483..522ec4f 100644
--- a/1.5/plugins/org.eclipse.epf.library/src/org/eclipse/epf/library/layout/IContentValidator.java
+++ b/1.5/plugins/org.eclipse.epf.library/src/org/eclipse/epf/library/layout/IContentValidator.java
@@ -140,6 +140,8 @@
 	 * @param e MethodElement the element to be checked
 	 */
 	public boolean isDiscarded(MethodElement owner, Object feature, MethodElement e);
+	
+	public boolean isDiscarded(MethodElement owner, Object feature, MethodElement e, MethodConfiguration config);
 
 	/**
 	 * set an discarded element
diff --git a/1.5/plugins/org.eclipse.epf.library/src/org/eclipse/epf/library/layout/LinkInfo.java b/1.5/plugins/org.eclipse.epf.library/src/org/eclipse/epf/library/layout/LinkInfo.java
index f2cd8ff..168302e 100644
--- a/1.5/plugins/org.eclipse.epf.library/src/org/eclipse/epf/library/layout/LinkInfo.java
+++ b/1.5/plugins/org.eclipse.epf.library/src/org/eclipse/epf/library/layout/LinkInfo.java
@@ -331,7 +331,7 @@
 					}
 				}
 
-				if (validator.isDiscarded(ownerElement, IContentValidator.elementUrlFeature, e)) {
+				if (validator.isDiscarded(ownerElement, IContentValidator.elementUrlFeature, e, config)) {
 					isMissingReference = true;
 					validator.logMissingReference(ownerElement, e);
 					e = null; // ignore the element since it's discarded
diff --git a/1.5/plugins/org.eclipse.epf.publishing/src/org/eclipse/epf/publishing/services/ConfigurationViewBuilder.java b/1.5/plugins/org.eclipse.epf.publishing/src/org/eclipse/epf/publishing/services/ConfigurationViewBuilder.java
index 20f2d16..8f47e80 100644
--- a/1.5/plugins/org.eclipse.epf.publishing/src/org/eclipse/epf/publishing/services/ConfigurationViewBuilder.java
+++ b/1.5/plugins/org.eclipse.epf.publishing/src/org/eclipse/epf/publishing/services/ConfigurationViewBuilder.java
@@ -373,7 +373,7 @@
 
 		// now all the published elements are the element closure, make the
 		// final closure
-		getValidator().makeElementClosure();
+		getValidator().makeElementClosure(config);
 	}
 
 	private void makeProcessClosure(org.eclipse.epf.uma.Process proc) {
diff --git a/1.5/plugins/org.eclipse.epf.publishing/src/org/eclipse/epf/publishing/services/ProcessPublishingContentValidator.java b/1.5/plugins/org.eclipse.epf.publishing/src/org/eclipse/epf/publishing/services/ProcessPublishingContentValidator.java
index a39ad22..a44a3cf 100644
--- a/1.5/plugins/org.eclipse.epf.publishing/src/org/eclipse/epf/publishing/services/ProcessPublishingContentValidator.java
+++ b/1.5/plugins/org.eclipse.epf.publishing/src/org/eclipse/epf/publishing/services/ProcessPublishingContentValidator.java
@@ -11,11 +11,16 @@
 package org.eclipse.epf.publishing.services;
 
 import java.io.PrintStream;
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
 import org.eclipse.epf.library.configuration.ConfigurationHelper;
 import org.eclipse.epf.library.util.LibraryUtil;
 import org.eclipse.epf.publishing.PublishingPlugin;
@@ -23,6 +28,7 @@
 import org.eclipse.epf.uma.ContentCategory;
 import org.eclipse.epf.uma.Descriptor;
 import org.eclipse.epf.uma.Guidance;
+import org.eclipse.epf.uma.MethodConfiguration;
 import org.eclipse.epf.uma.MethodElement;
 import org.eclipse.epf.uma.Practice;
 import org.eclipse.epf.uma.Roadmap;
@@ -86,7 +92,17 @@
 	 *  all the published and referenced elements are the element closure. 
 	 *  since they are all the elements referenced by the processes and their related process elements. 
 	 */
-	public void makeElementClosure() {
+	public void makeElementClosure(MethodConfiguration config) {
+		if (config != null && closureElements != null) {
+			List referencingElems = new ArrayList();
+			referencingElems.addAll(closureElements);
+			try {
+				addReferencesToClosure(referencingElems, config, new HashSet());
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+		}
+		
 		this.isFinalClosure = true;
 		
 		endClosureLog();
@@ -101,8 +117,88 @@
 		}
 	}
 	
+	private void addReferencesToClosure(Collection referencingElems,
+			MethodConfiguration config, Set processed) {
+		Set<MethodElement> referencedSet = new HashSet<MethodElement>();
+
+		for (Object obj : referencingElems) {
+			addReferencesToClosure(config, processed, referencedSet, obj);
+		}
+		if (! referencedSet.isEmpty()) {
+			addReferencesToClosure(referencedSet, config, processed);
+		}
+	}
+	
+	private void addReferencesToClosure(MethodConfiguration config, Set processed,
+			Set<MethodElement> referencedSet, Object obj) {
+		if (processed.contains(obj)) {
+			return;
+		}
+		if (obj instanceof MethodElement) {
+			addReferencesToClosure_(config, processed, referencedSet, (MethodElement) obj);
+		}
+		processed.add(obj);
+	}
+
+	private void addReferencesToClosure_(MethodConfiguration config, Set processed,
+			Set<MethodElement> referencedSet, MethodElement element) {
+		List properties = LibraryUtil.getStructuralFeatures(element);
+		for (EStructuralFeature f : (List<EStructuralFeature>) properties) {
+			if (!(f instanceof EReference)) {
+				continue;
+			}
+
+			EReference feature = (EReference) f;
+			if (feature.isContainer() || feature.isContainment()) {
+				continue;
+			}
+			List values = getValues(element, feature);
+			if (values == null) {
+				continue;
+			}
+			for (Object value : values) {
+				if (value instanceof MethodElement) {
+					MethodElement referenced = (MethodElement) value;
+					if (referenced instanceof ContentCategory) {
+						continue;
+					}
+					if (closureElements.contains(referenced)) {
+						continue;
+					}
+					if (processed.contains(referenced)) {
+						continue;
+					}
+					if (ConfigurationHelper.inConfig(referenced, config)) {
+						closureElements.add(referenced);
+						referencedSet.add(referenced);
+					}
+				}
+			}
+		}
+
+	}
+	
+	private List getValues(MethodElement element, EReference feature) {
+		Object value = element.eGet(feature);
+		if (value == null) {
+			return null;
+		}
+
+		List values = null;
+		if (feature.isMany() && value instanceof List) {
+			values = (List) value;
+		} else if (value instanceof MethodElement) {
+			values = new ArrayList();
+			values.add(value);
+		}
+		
+		return values;
+	}
+	
+	
 	/**
 	 * check if a closure is created or not.
+	 * 
 	 * @return boolean
 	 */
 	public boolean hasClosure() {
@@ -168,7 +264,10 @@
 	 * @see com.ibm.rmc.library.layout.IContentValidator#isDiscarded(org.eclipse.epf.uma.MethodElement, java.lang.Object, org.eclipse.epf.uma.MethodElement)
 	 */
 	public boolean isDiscarded(MethodElement owner, Object feature, MethodElement e) {
+		return isDiscarded(owner, feature, e, null);
+	}
 	
+	public boolean isDiscarded(MethodElement owner, Object feature, MethodElement e, MethodConfiguration config) {
 		if ( owner == null ) {
 			owner = defaultTarget;
 		} else if ( defaultTarget != null && owner != defaultTarget ) {
@@ -176,15 +275,16 @@
 			super.logWarning("Target mismatch" + LibraryUtil.getTypeName(owner) + "<--->" + LibraryUtil.getTypeName(defaultTarget)); //$NON-NLS-1$ //$NON-NLS-2$
 		}
 		
-		if ( super.isDiscarded(owner, feature, e) ) {
+		if ( super.isDiscarded(owner, feature, e, config) ) {
 			return true;
 		}
 		
 		boolean inCls = inClosure(e);
-		if (!inCls && feature == elementUrlFeature) {
+		if (!inCls && feature == elementUrlFeature && config != null) {
 			inCls = inClosure(owner);
 			if (inCls) {
 				closureElements.add(e);
+				addReferencesToClosure(Collections.singletonList(e), config, new HashSet());
 			}
 		}
 		if (!inCls && !isFinalClosure ) {
diff --git a/1.5/plugins/org.eclipse.epf.publishing/src/org/eclipse/epf/publishing/services/PublishingContentValidator.java b/1.5/plugins/org.eclipse.epf.publishing/src/org/eclipse/epf/publishing/services/PublishingContentValidator.java
index 8f81ae8..93bc541 100644
--- a/1.5/plugins/org.eclipse.epf.publishing/src/org/eclipse/epf/publishing/services/PublishingContentValidator.java
+++ b/1.5/plugins/org.eclipse.epf.publishing/src/org/eclipse/epf/publishing/services/PublishingContentValidator.java
@@ -145,10 +145,10 @@
 	// collect the elements referenced by the published contents so we can
 	// publish them
 	// this will be the elements to be published
-	protected List referencedElements = new ArrayList();
+	private List referencedElements = new ArrayList();
 
 	// published elements
-	protected List publishedElements = new ArrayList();
+	private List publishedElements = new ArrayList();
 
 	// this is the default target element for the content validator
 	// set this before publishing the element and set to null after the
@@ -555,7 +555,7 @@
 		if (e == null) {
 			return;
 		}
-
+								
 		// don't add discarded elements
 		if (isDiscarded(owner, null, e)) {
 			if (debug) {
@@ -698,7 +698,7 @@
 	 * make a closure
 	 * 
 	 */
-	public void makeElementClosure() {
+	public void makeElementClosure(MethodConfiguration config) {
 		// do nothing
 	}