/*******************************************************************************
 * Copyright (c) 2005, 2008 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 API and implementation
 *	   David Schneider, david.schneider@unisys.com - [142500] WTP properties pages fonts don't follow Eclipse preferences
 *     Stefan Dimov, stefan.dimov@sap.com - bug 207826
 *******************************************************************************/
package org.eclipse.jst.j2ee.internal;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.jar.Manifest;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.URI;
import org.eclipse.jdt.core.ElementChangedEvent;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IElementChangedListener;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaElementDelta;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jem.util.logger.proxy.Logger;
import org.eclipse.jem.workbench.utility.JemProjectUtilities;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jst.j2ee.application.internal.operations.AddComponentToEnterpriseApplicationDataModelProvider;
import org.eclipse.jst.j2ee.application.internal.operations.ClassPathSelection;
import org.eclipse.jst.j2ee.application.internal.operations.ClasspathElement;
import org.eclipse.jst.j2ee.application.internal.operations.RemoveComponentFromEnterpriseApplicationDataModelProvider;
import org.eclipse.jst.j2ee.application.internal.operations.UpdateManifestDataModelProperties;
import org.eclipse.jst.j2ee.application.internal.operations.UpdateManifestDataModelProvider;
import org.eclipse.jst.j2ee.classpathdep.ClasspathDependencyUtil;
import org.eclipse.jst.j2ee.classpathdep.IClasspathDependencyConstants;
import org.eclipse.jst.j2ee.classpathdep.UpdateClasspathAttributeUtil;
import org.eclipse.jst.j2ee.classpathdep.IClasspathDependencyConstants.DependencyAttributeType;
import org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.ArchiveManifest;
import org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.ArchiveManifestImpl;
import org.eclipse.jst.j2ee.componentcore.J2EEModuleVirtualArchiveComponent;
import org.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyEnablement;
import org.eclipse.jst.j2ee.internal.common.ClasspathModel;
import org.eclipse.jst.j2ee.internal.common.ClasspathModelEvent;
import org.eclipse.jst.j2ee.internal.common.ClasspathModelListener;
import org.eclipse.jst.j2ee.internal.common.classpath.J2EEComponentClasspathUpdater;
import org.eclipse.jst.j2ee.internal.listeners.IValidateEditListener;
import org.eclipse.jst.j2ee.internal.listeners.ValidateEditListener;
import org.eclipse.jst.j2ee.internal.plugin.J2EEUIPlugin;
import org.eclipse.jst.j2ee.internal.project.J2EEProjectUtilities;
import org.eclipse.jst.j2ee.model.IEARModelProvider;
import org.eclipse.jst.j2ee.model.ModelProviderManager;
import org.eclipse.jst.javaee.application.Application;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.ModuleCoreNature;
import org.eclipse.wst.common.componentcore.UnresolveableURIException;
import org.eclipse.wst.common.componentcore.datamodel.properties.ICreateReferenceComponentsDataModelProperties;
import org.eclipse.wst.common.componentcore.internal.builder.DependencyGraphManager;
import org.eclipse.wst.common.componentcore.internal.impl.ModuleURIUtil;
import org.eclipse.wst.common.componentcore.internal.operation.RemoveReferenceComponentsDataModelProvider;
import org.eclipse.wst.common.componentcore.internal.util.ComponentUtilities;
import org.eclipse.wst.common.componentcore.internal.util.IModuleConstants;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualFile;
import org.eclipse.wst.common.componentcore.resources.IVirtualReference;
import org.eclipse.wst.common.frameworks.datamodel.DataModelFactory;
import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
import org.eclipse.wst.common.frameworks.datamodel.IDataModelOperation;
import org.eclipse.wst.common.frameworks.datamodel.IDataModelProvider;
import org.eclipse.wst.common.frameworks.internal.ui.WTPUIPlugin;
import org.eclipse.wst.common.frameworks.internal.ui.WorkspaceModifyComposedOperation;

/**
 * @author jialin
 * 
 * TODO To change the template for this generated type comment go to Window - Preferences - Java -
 * Code Style - Code Templates
 */
public class JARDependencyPropertiesPage implements IJ2EEDependenciesControl, IClasspathTableOwner, Listener, ClasspathModelListener, IElementChangedListener {

	protected final IProject project;
	protected final J2EEDependenciesPage propPage;
	protected IOException caughtManifestException;
	protected boolean isDirty;
	protected Text classPathText;
	protected Text componentNameText;
	protected ClasspathModel model;
	protected CCombo availableAppsCombo;
	protected ClasspathTableManager tableManager;
	protected IValidateEditListener validateEditListener;
	protected Label manifestLabel;
	protected Label enterpriseApplicationLabel;
	protected Label availableDependentJars;
	private final Display display;
	private boolean isDisposed = false;
	
	/**
	 * Constructor for JARDependencyPropertiesControl
	 */
	public JARDependencyPropertiesPage(final IProject project, final J2EEDependenciesPage page) {
		super();
		J2EEComponentClasspathUpdater.getInstance().pauseUpdates();
		this.project = project;
		this.propPage = page;
		this.display = propPage.getShell().getDisplay();
	}

	/**
	 * Returns false if page should not be displayed for the project.
	 */
	protected void initialize() {
		model = createClasspathModel();
		model.setProject(project);
		if (model.getComponent() != null) {
			model.addListener(this);
			updateModelManifest();
			initializeValidateEditListener();
		}
	}

	protected ClasspathModel createClasspathModel(){
		return new ClasspathModel(J2EEProjectUtilities.readManifest(project), false);
	}

	public void dispose() {
		isDisposed = true;
		JavaCore.removeElementChangedListener(this);
		J2EEComponentClasspathUpdater.getInstance().resumeUpdates();
	}

	private void updateModelManifest() {
		if (JemProjectUtilities.isBinaryProject(project) || model.getAvailableEARComponents().length == 0)
			return;
		
		IVirtualComponent component = ComponentCore.createComponent(project);
		if(component != null){
			IVirtualFile vManifest = component.getRootFolder().getFile(new Path(J2EEConstants.MANIFEST_URI));
			if(vManifest.exists()){
				IFile iManifest = vManifest.getUnderlyingFile();
				if(iManifest != null && iManifest.exists()){
					InputStream in = null;
					try {
						in = iManifest.getContents();
						ArchiveManifest mf = new ArchiveManifestImpl(new Manifest(in));
						model.primSetManifest(mf);
					} catch (CoreException e) {
						Logger.getLogger().logError(e);
						model.primSetManifest(new ArchiveManifestImpl());
					} catch (IOException iox) {
						Logger.getLogger().logError(iox);
						model.primSetManifest(new ArchiveManifestImpl());
						caughtManifestException = iox;
					} finally {
						if (in != null) {
							try {
								in.close();
							} catch (IOException weTried) {
								// Ignore
							}
						}
					}
				}
			}
		}
	}


	protected void initializeValidateEditListener() {
		validateEditListener = new ValidateEditListener(null, model);
		validateEditListener.setShell(propPage.getShell());
	}

	public void setVisible(boolean visible) {
		if (visible) {
			if (caughtManifestException != null && !model.isDirty()) {
				ManifestErrorPrompter.showManifestException(propPage.getShell(), ERROR_READING_MANIFEST_DIALOG_MESSAGE_PROP_PAGE, false, caughtManifestException);
			}
		}
	}

	/**
	 * Refreshes the ClasspathModel if the project classpath is changed.
	 */
	public void elementChanged(final ElementChangedEvent event) {
		if (event.getType() == ElementChangedEvent.POST_CHANGE && classpathChanged(event.getDelta())) {
			// trigger a recomputation and refresh for the currently selected EAR
			if (!isDisposed) {
				display.asyncExec (new Runnable () {
					public void run () {
						if (!isDisposed) {
							handleClasspathChange();
						}
					}
				});
			}
		}
	}
	
	/**
	 * Called to refresh the UI when the classpath changes
	 */
	protected void handleClasspathChange() {
		model.resetClassPathSelection();
		refresh();		
	}
	
	private boolean classpathChanged(final IJavaElementDelta delta) {
		final int kind = delta.getKind();
		if (kind == IJavaElementDelta.CHANGED) {
			final int flags = delta.getFlags();
			final IJavaElement element = delta.getElement();
			if (element instanceof IJavaModel) {
				if ((flags & IJavaElementDelta.F_CHILDREN) == IJavaElementDelta.F_CHILDREN) {
					final IJavaElementDelta[] children = delta.getChangedChildren();
					for (int i = 0; i < children.length; i++) {
						// check all of the IJavaProject children
						if (classpathChanged(children[i])) {
							return true;
						}
					}
				}
			} else if (element instanceof IJavaProject) {
				// check if we either have a direct indication of a classpath change or a delta on the
				// .classpath file (changes to classpath entry attributes only give us this...)
				final IJavaProject jproject = (IJavaProject) element;
				final IProject eventProject = jproject.getProject();
				if (eventProject.equals(project)) {
					if ((flags & IJavaElementDelta.F_CLASSPATH_CHANGED) != 0) {
						return true; 	
					}
					final IResourceDelta[] deltas = delta.getResourceDeltas();
					if (deltas != null) {
						for (int i = 0; i < deltas.length; i++) {
							if (deltas[i].getProjectRelativePath().toString().equals(".classpath")) { //$NON-NLS-1$
								return true;
							}
						}
					}
				}
			}
		}
		return false;
	}

	public Composite createContents(Composite parent) {
		initialize();
		Composite composite = createBasicComposite(parent);
		GridLayout layout = new GridLayout();
		layout.marginWidth = 0;
		layout.marginWidth = 0;
		composite.setLayout(layout);
		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
		if (model.getComponent() != null) {
			if (!isValidComponent())
				return composite;
			J2EEDependenciesPage.createDescriptionComposite(composite, ManifestUIResourceHandler.J2EE_Modules_Desc);
			createProjectLabelsGroup(composite);
			createListGroup(composite);
			createTextGroup(composite);
			refresh();
		}
	    Dialog.applyDialogFont(parent);
	    postCreateContents();
		return composite;
	}

	/**
	 * Called at the end of createContents().
	 */
	protected void postCreateContents() {
		// register this object as an IElementChangedListener so that it will react to user changes to the Java build path
		JavaCore.addElementChangedListener(this);	
	}
	
	/**
	 * @param comp
	 * @return
	 */
	protected Composite createBasicComposite(Composite comp) {
		Composite composite = new Composite(comp, SWT.NONE);
		GridLayout layout = new GridLayout();
		layout.marginWidth = 0;
		layout.marginWidth = 0;
		composite.setLayout(layout);
		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
		return composite;
	}

	protected boolean isValidComponent() {
		if (J2EEProjectUtilities.isEARProject(project)) {
			propPage.setErrorMessage(ManifestUIResourceHandler.EAR_Module_Dep_Error);
			return false;
		} else if (J2EEProjectUtilities.isStandaloneProject(model.getComponent().getProject())) {
			propPage.setErrorMessage(ClasspathModel.NO_EAR_MESSAGE);
			return false;
		}
		return true;
	}

	protected void createProjectLabelsGroup(Composite parent) {

		Composite labelsGroup = new Composite(parent, SWT.NONE);
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		labelsGroup.setLayout(layout);
		labelsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		/*
		 * Label label = new Label(labelsGroup, SWT.NONE);
		 * label.setText(ManifestUIResourceHandler.Project_name__UI_);
		 * 
		 * componentNameText = new Text(labelsGroup, SWT.BORDER); GridData data = new
		 * GridData(GridData.FILL_HORIZONTAL); componentNameText.setEditable(false);
		 * componentNameText.setLayoutData(data); componentNameText.setText(project.getName());
		 */

		createEnterpriseAppsControls(labelsGroup);

	}

	private void createEnterpriseAppsControls(Composite labelsGroup) {

		enterpriseApplicationLabel = new Label(labelsGroup, SWT.NONE);
		enterpriseApplicationLabel.setText(ManifestUIResourceHandler.EAR_Project_Name__UI__UI_);

		availableAppsCombo = new CCombo(labelsGroup, SWT.READ_ONLY | SWT.BORDER);
		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		availableAppsCombo.setLayoutData(gd);

		availableAppsCombo.addListener(SWT.Selection, this);

	}

	protected void createListGroup(Composite parent) {
		Composite listGroup = new Composite(parent, SWT.NONE);
		GridLayout layout = new GridLayout();
		layout.numColumns = 1;
		layout.marginWidth = 0;
		layout.marginHeight = 0;
		listGroup.setLayout(layout);
		GridData gData = new GridData(GridData.FILL_BOTH);
		gData.horizontalIndent = 5;
		listGroup.setLayoutData(gData);

		availableDependentJars = new Label(listGroup, SWT.NONE);
		gData = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
		availableDependentJars.setText(ManifestUIResourceHandler.Available_dependent_JARs__UI_);
		availableDependentJars.setLayoutData(gData);
		createTableComposite(listGroup);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.etools.j2ee.common.ui.classpath.IClasspathTableOwner#createGroup(org.eclipse.swt.widgets.Composite)
	 */
	public Group createGroup(Composite parent) {
		return new Group(parent, SWT.NULL);
	}

	protected void createTextGroup(Composite parent) {

		Composite textGroup = new Composite(parent, SWT.NONE);
		GridLayout layout = new GridLayout();
		layout.numColumns = 1;
		textGroup.setLayout(layout);
		textGroup.setLayoutData(new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL));

		createClassPathText(textGroup);

	}

	protected void createClassPathText(Composite textGroup) {

		manifestLabel = new Label(textGroup, SWT.NONE);
		manifestLabel.setText(ManifestUIResourceHandler.Manifest_Class_Path__UI_);

		classPathText = new Text(textGroup, SWT.BORDER | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
		GridData gData = new GridData(GridData.FILL_BOTH);
		gData.widthHint = 400;
		gData.heightHint = 100;
		classPathText.setLayoutData(gData);
		classPathText.setEditable(false);
	}

	protected void createTableComposite(Composite parent) {
		Composite composite = new Composite(parent, SWT.NONE);
		GridData gData = new GridData(GridData.FILL_BOTH);
		composite.setLayoutData(gData);
		tableManager = new ClasspathTableManager(this, model, validateEditListener);
		tableManager.fillComposite(composite);
	}

	/**
	 * @see IClasspathTableOwner#createAvailableJARsViewer(Composite)
	 */
	public CheckboxTableViewer createAvailableJARsViewer(Composite parent) {
		int flags = SWT.CHECK | SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI;

		Table table = new Table(parent, flags);
		CheckboxTableViewer availableJARsViewer = new CheckboxTableViewer(table);

		// set up table layout
		TableLayout tableLayout = new org.eclipse.jface.viewers.TableLayout();
		tableLayout.addColumnData(new ColumnWeightData(200, true));
		tableLayout.addColumnData(new ColumnWeightData(200, true));
		table.setLayout(tableLayout);
		table.setHeaderVisible(true);
		table.setLinesVisible(true);
		
		// do not create sorter otherwise order will go wrong
		//availableJARsViewer.setSorter(new ViewerSorter());
		
		// table columns
		TableColumn fileNameColumn = new TableColumn(table, SWT.NONE, 0);
		fileNameColumn.setText(ManifestUIResourceHandler.JAR_Module_UI_);
		fileNameColumn.setResizable(true);

		TableColumn projectColumn = new TableColumn(table, SWT.NONE, 1);
		projectColumn.setText(ManifestUIResourceHandler.Project_UI_);
		projectColumn.setResizable(true);
		tableLayout.layout(table, true);
		return availableJARsViewer;

	}

	/**
	 * @see IClasspathTableOwner#createButtonColumnComposite(Composite)
	 */
	public Composite createButtonColumnComposite(Composite parent) {
		Composite buttonColumn = new Composite(parent, SWT.NONE);
		GridLayout layout = new GridLayout();
		layout.numColumns = 1;
		layout.marginHeight = 0;
		layout.marginWidth = 0;
		buttonColumn.setLayout(layout);
		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_BEGINNING);
		buttonColumn.setLayoutData(data);
		return buttonColumn;
	}

	/**
	 * @see IClasspathTableOwner
	 */
	public Button primCreatePushButton(String label, Composite buttonColumn) {
		Button aButton = new Button(buttonColumn, SWT.PUSH);
		aButton.setText(label);
		return aButton;
	}

	/**
	 * @see IClasspathTableOwner
	 */
	public Button primCreateRadioButton(String label, Composite parent) {
		Button aButton = new Button(parent, SWT.RADIO);
		aButton.setText(label);
		return aButton;
	}

	/**
	 * @see Listener#handleEvent(Event)
	 */
	public void handleEvent(Event event) {
		if (event.widget == availableAppsCombo)
			availableAppsSelected(event);
	}

	protected void availableAppsSelected(Event event) {
		int index = availableAppsCombo.getSelectionIndex();
		model.selectEAR(index);
	}

	protected void populateApps() {
		IVirtualComponent[] components = model.getAvailableEARComponents();
		String[] values = new String[components.length];
		for (int i = 0; i < components.length; i++) {
			values[i] = components[i].getProject().getName();
		}
		if (availableAppsCombo != null) {
			availableAppsCombo.setItems(values);
			IVirtualComponent selected = model.getSelectedEARComponent();
			if (selected != null) {
				int index = Arrays.asList(components).indexOf(selected);
				availableAppsCombo.select(index);
			} else
				availableAppsCombo.clearSelection();
		}
	}

	protected void refresh() {
		populateApps();
		if (tableManager != null) {
			tableManager.refresh();
		}
		refreshText();
	}


	public void refreshText() {
		ClassPathSelection sel = model.getClassPathSelection();
		if (sel != null && classPathText != null)
			classPathText.setText(sel == null ? "" : sel.toString()); //$NON-NLS-1$
	}

	/**
	 * @see ClasspathModelListener#modelChanged(ClasspathModelEvent)
	 */
	public void modelChanged(ClasspathModelEvent evt) {
		if (evt.getEventType() == ClasspathModelEvent.CLASS_PATH_CHANGED) {
			isDirty = true;
			refreshText();
		} else if (evt.getEventType() == ClasspathModelEvent.EAR_PROJECT_CHANGED) {			
			tableManager.refresh();
		}
	}

	public void performDefaults() {
		model.resetClassPathSelection();
		refresh();
		isDirty = false;
		model.dispose();
	}

	public boolean performCancel() {
		model.dispose();
		return true;
	}

	/**
	 * @see org.eclipse.jface.preference.IPreferencePage#performOk()
	 */
	public boolean performOk() {
		if (!isDirty)
			return true;
		modifyEARBundledLibs();		
		WorkspaceModifyComposedOperation composed = new WorkspaceModifyComposedOperation(createManifestOperation());
		createClasspathAttributeUpdateOperation(composed, model.getClassPathSelection(), false);
		try {
			new ProgressMonitorDialog(propPage.getShell()).run(true, true, composed);
		} catch (InvocationTargetException ex) {
			String title = ManifestUIResourceHandler.An_internal_error_occurred_ERROR_;
			String msg = title;
			if (ex.getTargetException() != null && ex.getTargetException().getMessage() != null)
				msg = ex.getTargetException().getMessage();
			MessageDialog.openError(propPage.getShell(), title, msg);
			org.eclipse.jem.util.logger.proxy.Logger.getLogger().logError(ex);
			return false;
		} catch (InterruptedException e) {
			// cancelled
			return false;
		} finally {
			model.dispose();
		}
		isDirty = false;
		return true;
	}

	List getUnSelectedClassPathElementsForJ2EEDependency() {
		List unselectedForJ2EE = getUnSelectedClassPathSelection().getClasspathElements();

		List unselected = new ArrayList();
		if (model != null && model.getClassPathSelectionForWLPs() != null) {
			List wlpSelected = model.getClassPathSelectionForWLPs().getSelectedClasspathElements();

			java.util.Iterator it = unselectedForJ2EE.iterator();

			while (it.hasNext()) {
				ClasspathElement element = (ClasspathElement) it.next();
				java.util.Iterator wlpIterator = wlpSelected.iterator();
				boolean found = false;
				while (wlpIterator.hasNext()) {
					ClasspathElement wlpElement = (ClasspathElement) wlpIterator.next();
					String text = element.getText();
					int index = text.indexOf(".jar");
					if (index != -1) {
						text = text.substring(0, index);
						if (text.equals(wlpElement.getText())) {
							found = true;
							break;
						}
					}
				}
				if (!found) {
					if (!unselected.contains(element))
						unselected.add(element);
				}

			}
		}
		return unselected;
	}


	/**
	 * @deprecated don't use this method it will be deleted
	 * @return
	 */
	List getUnSelectedClassPathElementsForWebDependency() {
		List unselectedForWLP = getUnSelectedClassPathSelectionForWLPs().getClasspathElements();
		List unselected = new ArrayList();
		if (model != null && model.getClassPathSelection() != null) {
			List j2eeSelected = model.getClassPathSelection().getSelectedClasspathElements();
			java.util.Iterator it = unselectedForWLP.iterator();

			while (it.hasNext()) {
				ClasspathElement element = (ClasspathElement) it.next();
				java.util.Iterator j2eeIterator = j2eeSelected.iterator();
				boolean found = false;
				while (j2eeIterator.hasNext()) {
					ClasspathElement j2eeElement = (ClasspathElement) j2eeIterator.next();
					String text = j2eeElement.getText();
					int index = text.indexOf(".jar");
					if( index != -1 ){
						text = text.substring(0, index);
						if (element.getText().equals(text)) {
							found = true;
							break;
						}
					}
				}
				if (!found) {
					if (!unselected.contains(element))
						unselected.add(element);
				}

			}
		} else {
			unselected = unselectedForWLP;
		}
		return unselected;
	}

	/**
	 * DoNotUseMeThisWillBeDeletedPost15
	 * @return
	 */
	protected WorkspaceModifyComposedOperation createJ2EEComponentDependencyOperations() {
		WorkspaceModifyComposedOperation composedOp = null;
		List selected = getSelectedClassPathSelection().getClasspathElements();
		List unselected = getUnSelectedClassPathElementsForJ2EEDependency();

		List targetComponentsHandles = new ArrayList();
		for (int i = 0; i < selected.size(); i++) {
			ClasspathElement element = (ClasspathElement) selected.get(i);
			IVirtualComponent component = element.getComponent();
			if (null != component) {
				targetComponentsHandles.add(component);
			}
		}
		if (!targetComponentsHandles.isEmpty()) {
			composedOp = new WorkspaceModifyComposedOperation();
			composedOp.addRunnable(WTPUIPlugin.getRunnableWithProgress(ComponentUtilities.createReferenceComponentOperation(model.getComponent(), targetComponentsHandles)));
		}
		targetComponentsHandles = new ArrayList();
		for (int i = 0; i < unselected.size(); i++) {
			ClasspathElement element = (ClasspathElement) unselected.get(i);
			IProject elementProject = element.getProject();
			if (elementProject != null) {
				if (ModuleCoreNature.isFlexibleProject(elementProject)) {
					IVirtualComponent targetComp = ComponentCore.createComponent(elementProject);
					targetComponentsHandles.add(targetComp);
				}
			} else {
				URI archiveURI = element.getArchiveURI();
				if (archiveURI != null && !archiveURI.equals("")) { //$NON-NLS-1$
					String name = ""; //$NON-NLS-1$
					try {
						String type = ModuleURIUtil.getArchiveType(archiveURI);
						String tmpname = ModuleURIUtil.getArchiveName(archiveURI);
						name = type + IPath.SEPARATOR + tmpname;
					} catch (UnresolveableURIException e) {
						Logger.getLogger().logError(e.getMessage());
					}
					if (!name.equals("")) { //$NON-NLS-1$
						IVirtualReference ref = model.getComponent().getReference(name);
						if (ref != null) {
							IVirtualComponent referenced = ref.getReferencedComponent();
							targetComponentsHandles.add(referenced);
						}
					}
				}
			}
		}
		if (!targetComponentsHandles.isEmpty()) {
			if (composedOp == null)
				composedOp = new WorkspaceModifyComposedOperation();
			composedOp.addRunnable(WTPUIPlugin.getRunnableWithProgress(ComponentUtilities.removeReferenceComponentOperation(model.getComponent(), targetComponentsHandles)));
		}
		return composedOp;
	}


	/**
	 * This should be moved to the {@link WebLibDependencyPropertiesPage} because it is only used there.
	 * @return
	 */
	protected WorkspaceModifyComposedOperation createComponentDependencyOperations() {
		WorkspaceModifyComposedOperation composedOp = null;
		final ClassPathSelection selectedWLPs = getSelectedClassPathSelectionForWLPs();
		List selected = selectedWLPs.getClasspathElements();
		List unselected = getUnSelectedClassPathSelectionForWLPs().getClasspathElements();

		List targetComponentsHandles = new ArrayList();
		for (int i = 0; i < selected.size(); i++) {
			ClasspathElement element = (ClasspathElement) selected.get(i);
			if (element.isClasspathDependency() || element.isClasspathEntry()) {
				continue;
			}
			IProject elementProject = element.getProject();
			if (elementProject != null) {
				IVirtualComponent targetComp = ComponentCore.createComponent(elementProject);
				targetComponentsHandles.add(targetComp);
			}
		}
		if (!targetComponentsHandles.isEmpty()) {
			composedOp = new WorkspaceModifyComposedOperation();
			composedOp.addRunnable(WTPUIPlugin.getRunnableWithProgress(ComponentUtilities.createWLPReferenceComponentOperation(model.getComponent(), targetComponentsHandles)));
		}
		targetComponentsHandles = new ArrayList();
		for (int i = 0; i < unselected.size(); i++) {
			ClasspathElement element = (ClasspathElement) unselected.get(i);
			if (element.isClasspathDependency() || element.isClasspathEntry()) {
				continue;
			}
			IProject elementProject = element.getProject();
			if (elementProject != null) {
				if (ModuleCoreNature.isFlexibleProject(elementProject)) {
					IVirtualComponent targetComp = ComponentCore.createComponent(elementProject);
					targetComponentsHandles.add(targetComp);
				}
			} else {
				URI archiveURI = element.getArchiveURI();
				if (archiveURI != null && !archiveURI.equals("")) { //$NON-NLS-1$
					String name = ""; //$NON-NLS-1$
					try {
						String type = ModuleURIUtil.getArchiveType(archiveURI);
						String tmpname = ModuleURIUtil.getArchiveName(archiveURI);
						name = type + IPath.SEPARATOR + tmpname;
					} catch (UnresolveableURIException e) {
						Logger.getLogger().logError(e.getMessage());
					}
					if (!name.equals("")) { //$NON-NLS-1$
						IVirtualReference ref = model.getComponent().getReference(name);
						IVirtualComponent referenced = ref.getReferencedComponent();
						targetComponentsHandles.add(referenced);
					}
				}
			}
		}
		if (!targetComponentsHandles.isEmpty()) {
			if (composedOp == null) {
				composedOp = new WorkspaceModifyComposedOperation();
			}
			composedOp.addRunnable(WTPUIPlugin.getRunnableWithProgress(ComponentUtilities.removeWLPReferenceComponentOperation(model.getComponent(), targetComponentsHandles)));
		}

		if (composedOp == null) {
			composedOp = new WorkspaceModifyComposedOperation();
		}
		createClasspathAttributeUpdateOperation(composedOp, model.getClassPathSelectionForWLPs(), true);
		
		return composedOp;
	}

	protected WorkspaceModifyComposedOperation createFlexProjectOperations() {
		WorkspaceModifyComposedOperation composedOp = null;
		Object[] elements = tableManager.availableJARsViewer.getCheckedElements();
		for (int i = 0; i < elements.length; i++) {
			ClasspathElement element = (ClasspathElement) elements[i];
			IProject elementProject = element.getProject();
			try {
				if (elementProject != null && !elementProject.hasNature(IModuleConstants.MODULE_NATURE_ID)) {
					if (composedOp == null) {
						composedOp = new WorkspaceModifyComposedOperation();
					}
					composedOp.addRunnable(WTPUIPlugin.getRunnableWithProgress(J2EEProjectUtilities.createFlexJavaProjectForProjectOperation(elementProject, false)));
				}
			} catch (CoreException e) {
				Logger.getLogger().logError(e);
			}
		}
		return composedOp;
	}

	protected ClassPathSelection getUnSelectedClassPathSelectionForWLPs() {
		ClassPathSelection selection = new ClassPathSelection();
		Object[] checkedElements = tableManager.availableJARsViewer.getCheckedElements();
		List modelElements = model.getClassPathSelectionForWLPs().getClasspathElements();
		for (int i = 0; i < modelElements.size(); i++) {
			List checkedElementsList = Arrays.asList(checkedElements);
			if (!checkedElementsList.contains(modelElements.get(i))) {
				selection.getClasspathElements().add(modelElements.get(i));
			}
		}
		return selection;
	}

	private ClassPathSelection getSelectedClassPathSelection() {
		ClassPathSelection selection = new ClassPathSelection();
		Object[] checkedElements = tableManager.availableJARsViewer.getCheckedElements();
		for (int i = 0; i < checkedElements.length; i++) {
			selection.getClasspathElements().add(checkedElements[i]);
		}
		return selection;
	}

	protected ClassPathSelection getUnSelectedClassPathSelection() {
		ClassPathSelection selection = new ClassPathSelection();
		Object[] checkedElements = tableManager.availableJARsViewer.getCheckedElements();
		List modelElements = model.getClassPathSelection().getClasspathElements();
		for (int i = 0; i < modelElements.size(); i++) {
			List checkedElementsList = Arrays.asList(checkedElements);
			if (!checkedElementsList.contains(modelElements.get(i))) {
				selection.getClasspathElements().add(modelElements.get(i));
			}
		}
		return selection;
	}


	private ClassPathSelection getSelectedClassPathSelectionForWLPs() {
		ClassPathSelection selection = new ClassPathSelection();
		Object[] checkedElements = tableManager.availableJARsViewer.getCheckedElements();
		for (int i = 0; i < checkedElements.length; i++) {
			selection.getClasspathElements().add(checkedElements[i]);
		}
		return selection;
	}

	protected UpdateManifestOperation createManifestOperation() {
		return new UpdateManifestOperation(project.getName(), model.getClassPathSelection().toString(), true);
	}
	
	protected void createClasspathAttributeUpdateOperation(final WorkspaceModifyComposedOperation composedOp, final ClassPathSelection selection, final boolean isWebApp) {
		final boolean webLibsOnly = isWebApp && !ClasspathDependencyEnablement.isAllowClasspathComponentDependency();
		final Map selectedEntriesToRuntimePath = new HashMap();
		final Map unselectedEntriesToRuntimePath = new HashMap();
		final List elements = selection.getClasspathElements();
		for (int i = 0; i < elements.size(); i++) {
			final ClasspathElement element = (ClasspathElement) elements.get(i);
			if (element.isClasspathEntry()) {
				final IClasspathEntry entry = element.getClasspathEntry();
				final IClasspathAttribute attrib = ClasspathDependencyUtil.checkForComponentDependencyAttribute(entry, DependencyAttributeType.DEPENDENCY_OR_NONDEPENDENCY, webLibsOnly);
				boolean hasDepAttrib = false;
				if (attrib != null && attrib.getName().equals(IClasspathDependencyConstants.CLASSPATH_COMPONENT_DEPENDENCY)) {
					hasDepAttrib = true;
				}
				final IPath runtimePath = ClasspathDependencyUtil.getRuntimePath(attrib, isWebApp, ClasspathDependencyUtil.isClassFolderEntry(entry));
				if (element.isSelected()) {
					// only add if we don't already have the attribute
					if (!hasDepAttrib) {
						selectedEntriesToRuntimePath.put(entry, runtimePath);
					}
				} else {
					// only add if we already have the attribute
					if (hasDepAttrib) {
						unselectedEntriesToRuntimePath.put(entry, runtimePath);
					}
				}
			}
		}
		
		// if there are any attributes to add, create an operation to add all necessary attributes 
		if (!selectedEntriesToRuntimePath.isEmpty()) {
			IDataModelOperation op = UpdateClasspathAttributeUtil.createAddDependencyAttributesOperation(project.getName(), selectedEntriesToRuntimePath); 
			composedOp.addRunnable(WTPUIPlugin.getRunnableWithProgress(op));
		}
		// if there are any attributes to remove, create an operation to remove all necessary attributes
		if (!unselectedEntriesToRuntimePath.isEmpty()) {
			IDataModelOperation op = UpdateClasspathAttributeUtil.createRemoveDependencyAttributesOperation(project.getName(), unselectedEntriesToRuntimePath); 
			composedOp.addRunnable(WTPUIPlugin.getRunnableWithProgress(op));
		}
	}

	protected boolean isReadOnly() {
		return JemProjectUtilities.isBinaryProject(project) && (project.findMember(IModuleConstants.COMPONENT_FILE_PATH) == null) ;
	}
	
	protected void modifyEARBundledLibs() {
		List compsToUncheckList = tableManager.getCheckedLibsAsList();
		if (compsToUncheckList.size() == 0) return;
		Set allCompsToUncheck = new HashSet();
		Set allCompNamesToUncheck = new HashSet();		
		for (int i = 0; i < compsToUncheckList.size(); i++) {
			IVirtualComponent comp = (IVirtualComponent)compsToUncheckList.get(i);
			allCompsToUncheck.add(comp);
			if (comp instanceof J2EEModuleVirtualArchiveComponent) allCompNamesToUncheck.add(comp.getName());
		}
 		IProject[] ears = J2EEProjectUtilities.getReferencingEARProjects(project);
		for (int i = 0; i < ears.length; i++) {
			IEARModelProvider earModel = (IEARModelProvider)ModelProviderManager.getModelProvider(ears[i]);
			if (J2EEProjectUtilities.isJEEProject(ears[i])) {	
				IVirtualComponent earComponent = ComponentCore.createComponent(ears[i]);
				List listToUncheck = createListToUncheck(earComponent, allCompsToUncheck, allCompNamesToUncheck);
				if (listToUncheck.size() == 0) continue;
				removeModulesFromEAR(new NullProgressMonitor(), earComponent, listToUncheck);
				addModulesToEAR(new NullProgressMonitor(), earComponent, listToUncheck);
			}
		}			
	}
	//---------------------------------
	private IStatus removeModulesFromEAR(IProgressMonitor monitor, final IVirtualComponent earComponent, final List compsToUncheckList) {
		IStatus stat = IDataModelProvider.OK_STATUS;
		String libDir = ((Application)ModelProviderManager.getModelProvider(earComponent.getProject()).getModelObject()).getLibraryDirectory();
		libDir = (libDir == null) ? J2EEConstants.EAR_DEFAULT_LIB_DIR : libDir;
		Map dependentComps = getEARModuleDependencies(earComponent, compsToUncheckList);
		try {
			IDataModelOperation op = removeComponentFromEAROperation(earComponent, compsToUncheckList, libDir);
			op.execute(null, null);
			J2EEComponentClasspathUpdater.getInstance().queueUpdateEAR(earComponent.getProject());
			removeEARComponentDependencies(dependentComps);
		} catch (ExecutionException e) {
			Logger.getLogger().log(e);
		}
		return stat;
	}		
	
	
	private IStatus addModulesToEAR(IProgressMonitor monitor, final IVirtualComponent earComponent, final List compsToUncheckList) {
		IStatus stat = IDataModelProvider.OK_STATUS;
		try {
			IWorkspaceRunnable runnable = new IWorkspaceRunnable(){
				public void run(IProgressMonitor monitor) throws CoreException{
					execAddOp(monitor, compsToUncheckList, J2EEConstants.EAR_ROOT_DIR, earComponent);
				}
			};
			J2EEUIPlugin.getWorkspace().run(runnable, monitor);
		} catch (Exception e) {
			Logger.getLogger().log(e);
		}
		return IDataModelProvider.OK_STATUS;
	}

	private List createListToUncheck(IVirtualComponent earComponent, Set compsToUncheckList, Set compNamesToUncheck) {	
		LinkedList res = new LinkedList();
		IVirtualReference[] refs = earComponent.getReferences();
		for (int j = 0; j < refs.length; j++) {
			if (!refs[j].getRuntimePath().isRoot() &&
					(compsToUncheckList.contains(refs[j].getReferencedComponent()) ||
					compNamesToUncheck.contains(refs[j].getReferencedComponent().getName()))) {
				res.add(refs[j].getReferencedComponent());
			}		
		}
		return res;
	}	
		
	private void execAddOp(IProgressMonitor monitor, List list, String path, IVirtualComponent earComponent) throws CoreException {
		IDataModel dm = DataModelFactory.createDataModel(new AddComponentToEnterpriseApplicationDataModelProvider());
		
		dm.setProperty(ICreateReferenceComponentsDataModelProperties.SOURCE_COMPONENT, earComponent);					
		dm.setProperty(ICreateReferenceComponentsDataModelProperties.TARGET_COMPONENT_LIST, list);
		dm.setProperty(ICreateReferenceComponentsDataModelProperties.TARGET_COMPONENTS_DEPLOY_PATH, path);

		IStatus stat = dm.validateProperty(ICreateReferenceComponentsDataModelProperties.TARGET_COMPONENT_LIST);
		if (stat != IDataModelProvider.OK_STATUS)
			throw new CoreException(stat);
		try {
			dm.getDefaultOperation().execute(monitor, null);
		} catch (ExecutionException e) {
			Logger.getLogger().log(e);
		}		
	}
		
	
	protected IDataModelOperation removeComponentFromEAROperation(IVirtualComponent sourceComponent, List targetComponentsHandles, String dir) {
		IDataModel model = DataModelFactory.createDataModel(new RemoveComponentFromEnterpriseApplicationDataModelProvider());
		model.setProperty(ICreateReferenceComponentsDataModelProperties.SOURCE_COMPONENT, sourceComponent);
		List modHandlesList = (List) model.getProperty(ICreateReferenceComponentsDataModelProperties.TARGET_COMPONENT_LIST);
		modHandlesList.addAll(targetComponentsHandles);
		model.setProperty(ICreateReferenceComponentsDataModelProperties.TARGET_COMPONENT_LIST, modHandlesList);
        model.setProperty(ICreateReferenceComponentsDataModelProperties.TARGET_COMPONENTS_DEPLOY_PATH, dir);		
		return model.getDefaultOperation();
	}
	
	private Map getEARModuleDependencies(final IVirtualComponent earComponent, final List components) {
		final Map dependentComps = new HashMap();
		// get all current references to project within the scope of this EAR
		for (int i = 0; i < components.size(); i++) {
			
			final List compsForProject = new ArrayList();
			final IVirtualComponent comp = (IVirtualComponent) components.get(i);
			final IProject[] dependentProjects = DependencyGraphManager.getInstance().getDependencyGraph().getReferencingComponents(comp.getProject());
			for (int j = 0; j < dependentProjects.length; j++) {
				final IProject project = dependentProjects[j];
				// if this is an EAR, can skip
				if (J2EEProjectUtilities.isEARProject(project)) {
					continue;
				}
				final IVirtualComponent dependentComp = ComponentCore.createComponent(project);
				// ensure that the project's share an EAR
				final IProject[] refEARs = J2EEProjectUtilities.getReferencingEARProjects(project);
				boolean sameEAR = false;
				for (int k = 0; k < refEARs.length; k++) {
					if (refEARs[k].equals(earComponent.getProject())) {
						sameEAR = true;
						break;
					}
				}
				if (!sameEAR) {
					continue;
				}
				// if the dependency is a web lib dependency, can skip
				if (J2EEProjectUtilities.isDynamicWebProject(project)) {
					IVirtualReference ref = dependentComp.getReference(comp.getName());
					if (ref != null && ref.getRuntimePath().equals(new Path("/WEB-INF/lib"))) { //$NON-NLS-1$
						continue;
					}
				}
				compsForProject.add(dependentComp);
			}
			dependentComps.put(comp, compsForProject);
		}
		return dependentComps;
	}
	
	private void removeEARComponentDependencies(final Map dependentComps) throws ExecutionException {
		final Iterator targets = dependentComps.keySet().iterator();
		while (targets.hasNext()) {
			final IVirtualComponent target = (IVirtualComponent) targets.next();
			final List sources = (List) dependentComps.get(target);
			for (int i = 0; i < sources.size(); i++) {
				final IVirtualComponent source = (IVirtualComponent) sources.get(i);
				final IDataModel model = DataModelFactory.createDataModel(new RemoveReferenceComponentsDataModelProvider());
				model.setProperty(ICreateReferenceComponentsDataModelProperties.SOURCE_COMPONENT, source);
				final List modHandlesList = (List) model.getProperty(ICreateReferenceComponentsDataModelProperties.TARGET_COMPONENT_LIST);
				modHandlesList.add(target);
				model.setProperty(ICreateReferenceComponentsDataModelProperties.TARGET_COMPONENT_LIST, modHandlesList);
				model.getDefaultOperation().execute(null, null);
				// update the manifest
				removeManifestDependency(source, target);
			}
		}
	}

	private void removeManifestDependency(final IVirtualComponent source, final IVirtualComponent target) 
		throws ExecutionException {
		final String sourceProjName = source.getProject().getName();
		final String targetProjName = target.getProject().getName();
		final IProgressMonitor monitor = new NullProgressMonitor();
		final IFile manifestmf = J2EEProjectUtilities.getManifestFile(source.getProject());
		final ArchiveManifest mf = J2EEProjectUtilities.readManifest(source.getProject());
		if (mf == null)
			return;
		final IDataModel updateManifestDataModel = DataModelFactory.createDataModel(new UpdateManifestDataModelProvider());
		updateManifestDataModel.setProperty(UpdateManifestDataModelProperties.PROJECT_NAME, sourceProjName);
		updateManifestDataModel.setBooleanProperty(UpdateManifestDataModelProperties.MERGE, false);
		updateManifestDataModel.setProperty(UpdateManifestDataModelProperties.MANIFEST_FILE, manifestmf);
		String[] cp = mf.getClassPathTokenized();
		List cpList = new ArrayList();
		String cpToRemove = targetProjName + ".jar";//$NON-NLS-1$
		for (int i = 0; i < cp.length; i++) {
			if (!cp[i].equals(cpToRemove)) {
				cpList.add(cp[i]);
			}
		}
		updateManifestDataModel.setProperty(UpdateManifestDataModelProperties.JAR_LIST, cpList);
		updateManifestDataModel.getDefaultOperation().execute(monitor, null );
	}
	
}
