/*******************************************************************************
 * Copyright (c) 2003, 2005 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
 *******************************************************************************/
package org.eclipse.jst.j2ee.application.internal.operations;



import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.emf.common.util.URI;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jem.util.emf.workbench.ProjectUtilities;
import org.eclipse.jem.util.logger.proxy.Logger;
import org.eclipse.jst.j2ee.commonarchivecore.internal.Archive;
import org.eclipse.jst.j2ee.commonarchivecore.internal.CommonArchiveResourceHandler;
import org.eclipse.jst.j2ee.commonarchivecore.internal.Container;
import org.eclipse.jst.j2ee.commonarchivecore.internal.EARFile;
import org.eclipse.jst.j2ee.commonarchivecore.internal.exception.ManifestException;
import org.eclipse.jst.j2ee.commonarchivecore.internal.exception.OpenFailureException;
import org.eclipse.jst.j2ee.commonarchivecore.internal.impl.CommonarchiveFactoryImpl;
import org.eclipse.jst.j2ee.commonarchivecore.internal.strategy.LoadStrategy;
import org.eclipse.jst.j2ee.commonarchivecore.internal.strategy.ZipFileLoadStrategyImpl;
import org.eclipse.jst.j2ee.commonarchivecore.internal.util.ArchiveUtil;
import org.eclipse.jst.j2ee.componentcore.util.EARArtifactEdit;
import org.eclipse.jst.j2ee.internal.archive.operations.ComponentLoadStrategyImpl;
import org.eclipse.jst.j2ee.internal.archive.operations.EARComponentLoadStrategyImpl;
import org.eclipse.jst.j2ee.internal.project.J2EEProjectUtilities;
import org.eclipse.wst.common.componentcore.UnresolveableURIException;
import org.eclipse.wst.common.componentcore.internal.impl.ModuleURIUtil;
import org.eclipse.wst.common.componentcore.internal.util.ComponentUtilities;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualReference;



public class ClassPathSelection {
	protected Archive archive;
	protected IProject earProject;
	protected IVirtualComponent earComponent;
	protected List classpathElements;
	protected Map urisToElements;
	protected boolean modified;
	private String targetProjectName;
	protected Map ejbToClientJARs = null;
	protected Map clientToEJBJARs = null;
	public static final int FILTER_EJB_SERVER_JARS = 0;
	public static final int FILTER_EJB_CLIENT_JARS = 1;
	public static final int FILTER_NONE = 2;

	protected int filterLevel = 2;

	protected static Comparator comparator = new Comparator() {
		/**
		 * @see Comparator#compare(Object, Object)
		 */
		public int compare(Object o1, Object o2) {
			Archive a1 = (Archive) o1;
			Archive a2 = (Archive) o2;
			return a1.getURI().compareTo(a2.getURI());
		}
	};

	public ClassPathSelection(Archive anArchive, String targetProjectName, EARFile earFile) {
		super();
		archive = anArchive;
		this.targetProjectName = targetProjectName;
		initializeEARProject(earFile);
		initializeElements();
	}

	/**
	 * ClassPathSelection constructor comment.
	 */
	public ClassPathSelection(Archive anArchive, EARFile earFile) {
		super();
		archive = anArchive;
		initializeEARProject(earFile);
		initializeElements();
	}
	
	/**
	 * ClassPathSelection constructor comment.
	 */
	public ClassPathSelection() {
		super();
	}

	protected ClasspathElement createElement(Archive referencingArchive, Archive referencedArchive, String cpEntry) {
		ClasspathElement element = new ClasspathElement(referencingArchive);
		element.setValid(true);
				
		String uriString = referencedArchive.getURI();
		URI uri = URI.createURI(uriString);

		boolean hasAbsolutePath = uri.hasAbsolutePath();
		if( hasAbsolutePath ){
			uriString = uri.lastSegment();
		}
		
		//element.setText(referencedArchive.getURI());
		element.setText(uriString);
		element.setTargetArchive(referencedArchive);
		element.setEarProject(earProject);
		if( earComponent != null ){
			IContainer earConentFolder = earComponent.getRootFolder().getUnderlyingFolder();
			if( earConentFolder.getType() == IResource.FOLDER ){
				element.setEarContentFolder( earConentFolder.getName());
			}else {
				element.setEarContentFolder( "" );
			}
		}
	
		setProjectValues(element, referencedArchive);
		if (cpEntry != null)
			element.setValuesSelected(cpEntry);
		setType(element, referencedArchive);
		return element;
	}

	protected ClasspathElement createInvalidElement(String cpEntry) {
		ClasspathElement element = new ClasspathElement(archive);
		element.setValid(false);
		element.setSelected(true);
		element.setRelativeText(cpEntry);
		element.setText(cpEntry);
		element.setEarProject(earProject);
		setInvalidProject(element);
		return element;
	}
	
	public ClasspathElement createProjectElement(IProject project) {
		ClasspathElement element = new ClasspathElement(project);
		element.setValid(true);
		element.setSelected(true);
		element.setText(project.getName());
		element.setProject(project);
		addClasspathElement(element,element.getProjectName());
		return element;
	}
	
	public ClasspathElement createProjectElement(IProject project, boolean existingEntry ) {
		ClasspathElement element = new ClasspathElement(project);
		element.setValid(true);
		element.setSelected(existingEntry);
		element.setText(project.getName());
		element.setProject(project);
		addClasspathElement(element,element.getProjectName());
		return element;
	}
	
	
	public ClasspathElement createArchiveElement(URI uri, String name, String cpEntry) {
		ClasspathElement element = new ClasspathElement(uri);
		element.setValid(false);
		element.setRelativeText(name);
		if (cpEntry != null)
			element.setValuesSelected(cpEntry);		
		element.setText(name);
		element.setEarProject(earProject);
		return element;
	}	

	/**
	 * @param element
	 */
	private void setInvalidProject(ClasspathElement element) {
		IProject earProj = element.getEarProject();
		//IVirtualComponent[] component = ComponentUtilities.getComponent(earProj.getName());
		IVirtualComponent component = ComponentUtilities.getComponent(earProj.getName());
		EARArtifactEdit edit = null;
		try {
			edit = EARArtifactEdit.getEARArtifactEditForRead(component);
		if (edit != null) {
			String moduleName = element.getRelativeText();
			if(moduleName != null) {
				IVirtualComponent modComponent = edit.getModule(moduleName);
				if(modComponent != null) {
				IProject mappedProject = modComponent.getProject();
				element.setProject(mappedProject);
				}
			}
		}
	  } finally {
		  if(edit != null) {
			  edit.dispose();
		    edit = null;
		  }
	  }
	}

	/**
	 * Insert the method's description here. Creation date: (8/22/2001 1:17:21 PM)
	 * 
	 * @return java.util.List
	 */
	public java.util.List getClasspathElements() {
		if(classpathElements == null)
			classpathElements = new ArrayList();
		return classpathElements;
	}
	
	public java.util.List getSelectedClasspathElements() {
		ArrayList list = new ArrayList();
		Iterator it = getClasspathElements().iterator();
		while(it.hasNext()) {
			ClasspathElement element = (ClasspathElement)it.next();
			if( element.isSelected() ){
				list.add(element);
			}
		}
		return list;
	}	

	/**
	 * Adapter method to convert the manifest class path entries which map to a project to a list of
	 * classpath entries for a java build path
	 */
	protected IClasspathEntry[] getClasspathEntries(boolean filterSelected) {
		List result = new ArrayList();
		IClasspathEntry[] array = null;
		ClasspathElement element = null;
		if(classpathElements != null) {
		for (int i = 0; i < classpathElements.size(); i++) {
			element = (ClasspathElement) classpathElements.get(i);
			if (filterSelected && !element.isSelected())
				continue;
			array = ((ClasspathElement) classpathElements.get(i)).newClasspathEntries();
			if (array == null)
				continue;
			for (int j = 0; j < array.length; j++) {
				if (!result.contains(array[j]))
					result.add(array[j]);
			}
		}
		return (IClasspathEntry[]) result.toArray(new IClasspathEntry[result.size()]);
		}
		return null;
	}

	/**
	 * Adapter method to convert the manifest class path entries which map to a project to a list of
	 * classpath entries for a java build path
	 */
	public IClasspathEntry[] getClasspathEntriesForAll() {
		return getClasspathEntries(false);
	}

	/**
	 * Adapter method to convert the manifest class path entries which map to a project to a list of
	 * classpath entries for a java build path
	 */
	public IClasspathEntry[] getClasspathEntriesForSelected() {
		return getClasspathEntries(true);
	}

	protected EARFile getEARFile() {
		if (archive == null)
			return null;

		Container parent = archive.getContainer();
		if (parent != null && parent.isEARFile())
			return (EARFile) parent;
		return null;
	}

	protected static IProject getEARProject(Archive anArchive) {
		Container c = anArchive.getContainer();
		if (!c.isEARFile())
			return null;
		EARFile ear = (EARFile) c;
		LoadStrategy loader = ear.getLoadStrategy();
		if (!(loader instanceof EARComponentLoadStrategyImpl))
			return null;

		return ((EARComponentLoadStrategyImpl) loader).getComponent().getProject();
	}

	public Archive getArchive() {
		return archive;
	}

	protected IProject getProject(Archive anArchive) {
		LoadStrategy loader = anArchive.getLoadStrategy();
		if (loader instanceof ComponentLoadStrategyImpl)
			return ((ComponentLoadStrategyImpl) loader).getComponent().getProject();
		return null;
	}

	public String getText() {
		return archive.getURI();
	}

	protected Archive getArchive(String uri, List archives) {
		for (int i = 0; i < archives.size(); i++) {
			Archive anArchive = (Archive) archives.get(i);
			
			String archiveURIString = anArchive.getURI();
			URI archiveURI = URI.createURI(archiveURIString);
			boolean hasAbsolutePath = archiveURI.hasAbsolutePath();
			if( hasAbsolutePath ){
				archiveURIString = archiveURI.lastSegment();
			}
			if (archiveURIString.equals(uri))
				return anArchive;
		}
		return null;
	}

	protected void initializeElements() {
		ejbToClientJARs = J2EEProjectUtilities.collectEJBClientJARs(getEARFile());
		clientToEJBJARs = reverse(ejbToClientJARs);
		classpathElements = new ArrayList();
		urisToElements = new HashMap();
		String[] cp = new String[0];
		try {
			cp = archive.getManifest().getClassPathTokenized();
		} catch (ManifestException ex) {
			Logger.getLogger().logError(ex);
		}
		List archives = getEARFile().getArchiveFiles();
		Archive other = null;
		ClasspathElement element = null;
		for (int i = 0; i < cp.length; i++) {
			String cpEntry = cp[i];
			String uri = ArchiveUtil.deriveEARRelativeURI(cpEntry, archive);
			other = getArchive(uri, archives);
			if (other != null && ArchiveUtil.isValidDependency(other, archive)) {
				element = createElement(archive, other, cpEntry);
				archives.remove(other);
			} else {
				element = createInvalidElement(cpEntry);
				if (element.representsImportedJar()) {
					element.setValid(true);
					element.setProject(getProject(archive));
				}
				if (other != null)
					element.setProject(getProject(other));
				
				if( other == null ){
					//making a best guess for the project name
					if( element.getProject() == null ){
						int  index = cpEntry.indexOf(".jar"); //$NON-NLS-1$
						if( index > 0 ){
							String projectName = cpEntry.substring(0, index);
							IProject project = ProjectUtilities.getProject( projectName );
							if( project != null && project.exists() )
								element.setProject( project );
						}
					}
				}
			}
			addClasspathElement(element, uri);
		}
		Collections.sort(archives, comparator);
		//Anything that remains in the list of available archives that is valid should be
		//available for selection
		for (int i = 0; i < archives.size(); i++) {
			other = (Archive) archives.get(i);
			if (other != archive && ArchiveUtil.isValidDependency(other, archive)) {
				IProject project = getProject(other);
				if (null == targetProjectName || null == project || !project.getName().equals(targetProjectName)) {
					element = createElement(archive, other, null);
					element.setProject(getProject(other));
					addClasspathElement(element, other.getURI());
				}
			}
		}
		
		if( earComponent!= null){
			IVirtualReference[] newrefs = earComponent.getReferences();
			for( int i=0; i < newrefs.length; i++){
				IVirtualReference ref = newrefs[i];
				IVirtualComponent referencedComponent = ref.getReferencedComponent();
				boolean isBinary = referencedComponent.isBinary();
				if( isBinary ){
			         /**
			          * Warning clean-up 12/05/2005
			          */   
					//String uri = J2EEProjectUtilities.getResolvedPathForArchiveComponent(referencedComponent.getName()).toString();
					String unresolvedURI = "";
					try {
						unresolvedURI = ModuleURIUtil.getArchiveName(URI.createURI(ModuleURIUtil.getHandleString(referencedComponent)));
					} catch (UnresolveableURIException e) {
						e.printStackTrace();
					}
					URI archiveURI = URI.createURI(unresolvedURI);	
					
					boolean  alreadyInList = false;
					Iterator iter = getClasspathElements().iterator();
					while(iter.hasNext()){
						ClasspathElement tmpelement = (ClasspathElement)iter.next();
						if( tmpelement.getText().equals(archiveURI.lastSegment())){
							alreadyInList = true;
							break;
						}
					}
					
					if( !alreadyInList ){
						if( inManifest(cp, archiveURI.lastSegment())){
							element = createArchiveElement(URI.createURI(ModuleURIUtil.getHandleString(referencedComponent)), archiveURI.lastSegment(), archiveURI.lastSegment());
							addClasspathElement(element, unresolvedURI);
						}else{
							element = createArchiveElement(URI.createURI(ModuleURIUtil.getHandleString(referencedComponent)), archiveURI.lastSegment(), null);
							addClasspathElement(element, unresolvedURI);							
						}
					}
				}
			}
		}	
	}

	boolean inManifest(String[] cp, String archiveName ){
		boolean result = false;
		String cpEntry = "";
		for (int i = 0; i < cp.length; i++) {
			cpEntry = cp[i];
			if( archiveName.equals(cpEntry)){
				result = true;
			}
		}
		return result;
	}
		
	protected List loadClassPathArchives(){
        /**
         * Warning clean-up 12/05/2005
         */   
		//LoadStrategy loadStrat = archive.getLoadStrategy();
		
		List archives = new ArrayList();
		
		if( earComponent!= null){
			IVirtualReference[] newrefs = earComponent.getReferences();
			for( int i=0; i < newrefs.length; i++){
				IVirtualReference ref = newrefs[i];
				IVirtualComponent referencedComponent = ref.getReferencedComponent();
				boolean isBinary = referencedComponent.isBinary();
			
				if( isBinary ){
					String uri = J2EEProjectUtilities.getResolvedPathForArchiveComponent(referencedComponent.getName()).toString();
		
					try {
						ZipFileLoadStrategyImpl strat = createLoadStrategy(uri);
						Archive archive = null;
						try {
							archive = CommonarchiveFactoryImpl.getActiveFactory().primOpenArchive(strat, uri);
						} catch (OpenFailureException e) {
							// TODO Auto-generated catch block
							Logger.getLogger().logError(e);
						}

						archives.add(archive);
						
					} catch (FileNotFoundException e) {
						Logger.getLogger().logError(e);
					} catch (IOException e) {
						Logger.getLogger().logError(e);
					}
				}
				
			}
		}
		return archives;
	}
	
	Archive getClassPathArchive(String uri, List archives){
		for (int i = 0; i < archives.size(); i++) {
			Archive anArchive = (Archive) archives.get(i);
			
			String archiveURIString = anArchive.getURI();
			URI archiveURI = URI.createURI(archiveURIString);
			boolean hasAbsolutePath = archiveURI.hasAbsolutePath();
			if( hasAbsolutePath ){
				archiveURIString = archiveURI.lastSegment();
			}
			if (archiveURIString.equals(uri))
				return anArchive;
		}
		return null;
	}
	
	boolean  isClassPathArchive(String uri, List archives){
		for (int i = 0; i < archives.size(); i++) {
			Archive anArchive = (Archive) archives.get(i);
			
			String archiveURIString = anArchive.getURI();
			URI archiveURI = URI.createURI(archiveURIString);
	         /**
	          * Warning clean-up 12/05/2005
	          */   
			//boolean hasAbsolutePath = archiveURI.hasAbsolutePath();
			if( archiveURI.lastSegment().equals(uri) ){
				return true;
			}
		}
		return false;
	}	
	
	public ZipFileLoadStrategyImpl createLoadStrategy(String uri) throws FileNotFoundException, IOException {
		String filename = uri.replace('/', java.io.File.separatorChar);
		java.io.File file = new java.io.File(filename);
		if (!file.exists()) {
			throw new FileNotFoundException(CommonArchiveResourceHandler.getString(CommonArchiveResourceHandler.file_not_found_EXC_, (new Object[]{uri, file.getAbsolutePath()}))); // = "URI Name: {0}; File name: {1}"
		}
		if (file.isDirectory()) {
			throw new FileNotFoundException(CommonArchiveResourceHandler.getString(CommonArchiveResourceHandler.file_not_found_EXC_, (new Object[]{uri, file.getAbsolutePath()}))); // = "URI Name: {0}; File name: {1}"
		}
		return new org.eclipse.jst.j2ee.commonarchivecore.internal.strategy.ZipFileLoadStrategyImpl(file);
	}
	
	
	private void initializeEARProject(EARFile earFile) {
		LoadStrategy loadStrat = earFile.getLoadStrategy();
		if (loadStrat instanceof EARComponentLoadStrategyImpl){
			earComponent = ((EARComponentLoadStrategyImpl) loadStrat).getComponent();
			earProject = ((EARComponentLoadStrategyImpl) loadStrat).getComponent().getProject();
		}	
	}

	private void setType(ClasspathElement element, Archive other) {
		if (other == null)
			return;
		else if (clientToEJBJARs.containsKey(other))
			element.setJarType(ClasspathElement.EJB_CLIENT_JAR);
		else if (other.isEJBJarFile())
			element.setJarType(ClasspathElement.EJB_JAR);
	}

	/**
	 * @param localejbToClientJARs
	 * @return
	 */
	private Map reverse(Map localejbToClientJARs) {
		if (localejbToClientJARs == null || localejbToClientJARs.isEmpty())
			return Collections.EMPTY_MAP;
		Map result = new HashMap();
		Iterator iter = localejbToClientJARs.entrySet().iterator();
		while (iter.hasNext()) {
			Map.Entry entry = (Map.Entry) iter.next();
			result.put(entry.getValue(), entry.getKey());
		}
		return result;
	}

	public void addClasspathElement(ClasspathElement element, String uri) {
		getClasspathElements().add(element);
		getUrisToElements().put(uri, element);
		element.setParentSelection(this);
	}

	/**
	 * Insert the method's description here. Creation date: (8/22/2001 6:05:11 PM)
	 * 
	 * @return boolean
	 */
	public boolean isModified() {
		return modified;
	}

	/**
	 * Insert the method's description here. Creation date: (8/22/2001 6:05:11 PM)
	 * 
	 * @param newModified
	 *            boolean
	 */
	public void setModified(boolean newModified) {
		modified = newModified;
	}

	protected void setProjectValues(ClasspathElement element, Archive referencedArchive) {
		IProject p = getProject(referencedArchive);
		if (p == null)
			return;

		element.setProject(p);
		//Handle the imported jars in the project
		String[] cp = null;
		try {
			cp = referencedArchive.getManifest().getClassPathTokenized();
		} catch (ManifestException mfEx) {
			Logger.getLogger().logError(mfEx);
			cp = new String[]{};
		}
		List paths = new ArrayList(cp.length);
		for (int i = 0; i < cp.length; i++) {

			IFile file = null;
			try {
				file = p.getFile(cp[i]);
			} catch (IllegalArgumentException invalidPath) {
				continue;
			}
			if (file.exists())
				paths.add(file.getFullPath());
		}
		if (!paths.isEmpty())
			element.setImportedJarPaths(paths);
	}

	public String toString() {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < classpathElements.size(); i++) {
			ClasspathElement element = (ClasspathElement) classpathElements.get(i);
			if (element.isSelected()) {
				sb.append(element.getRelativeText());
				sb.append(" "); //$NON-NLS-1$
			}
		}
		//Remove the trailing space
		if (sb.length() > 0)
			sb.deleteCharAt(sb.length() - 1);
		return sb.toString();
	}

	public void setAllSelected(boolean selected) {
		setAllSelected(classpathElements, selected);
	}

	public void setAllSelected(List elements, boolean selected) {
		for (int i = 0; i < elements.size(); i++) {
			ClasspathElement elmt = (ClasspathElement) elements.get(i);
			elmt.setSelected(selected);
		}
	}

	/* borrowed code from jdt */
	protected List moveUp(List elements, List move) {
		int nElements = elements.size();
		List res = new ArrayList(nElements);
		Object floating = null;
		for (int i = 0; i < nElements; i++) {
			Object curr = elements.get(i);
			if (move.contains(curr)) {
				res.add(curr);
			} else {
				if (floating != null) {
					res.add(floating);
				}
				floating = curr;
			}
		}
		if (floating != null) {
			res.add(floating);
		}
		return res;
	}

	/* borrowed code from jdt */
	public void moveUp(List toMoveUp) {
		setModifiedIfAnySelected(toMoveUp);
		if (toMoveUp.size() > 0)
			classpathElements = moveUp(classpathElements, toMoveUp);
	}

	/* borrowed code from jdt */
	public void moveDown(List toMoveDown) {
		setModifiedIfAnySelected(toMoveDown);
		if (toMoveDown.size() > 0)
			classpathElements = reverse(moveUp(reverse(classpathElements), toMoveDown));

	}

	/* borrowed code from jdt */
	protected List reverse(List p) {
		List reverse = new ArrayList(p.size());
		for (int i = p.size() - 1; i >= 0; i--) {
			reverse.add(p.get(i));
		}
		return reverse;
	}

	public ClasspathElement getClasspathElement(String uri) {
		if (urisToElements == null)
			return null;
		return (ClasspathElement) urisToElements.get(uri);
	}

	public ClasspathElement getClasspathElement(IProject archiveProject) {
		if (archiveProject != null) {
			for (int i = 0; i < classpathElements.size(); i++) {
				ClasspathElement elmnt = (ClasspathElement) classpathElements.get(i);
				if (archiveProject.equals(elmnt.getProject()))
					return elmnt;
			}
		}
		return null;
	}

	public boolean hasDirectOrIndirectDependencyTo(IProject archiveProject) {
		ClasspathElement element = getClasspathElement(archiveProject);
		if (element == null)
			return false;
		Archive anArchive = null;
		if (element.isValid()) {
			try {
				anArchive = (Archive) getEARFile().getFile(element.getText());
			} catch (FileNotFoundException e) {
			}
		}
		return anArchive != null && archive.hasClasspathVisibilityTo(anArchive);
	}

	public boolean hasDirectOrIndirectDependencyTo(String jarName) {
		ClasspathElement element = getClasspathElement(jarName);
		if (element == null)
			return false;
		Archive anArchive = null;
		if (element.isValid()) {
			try {
				anArchive = (Archive) getEARFile().getFile(element.getText());
			} catch (FileNotFoundException e) {
			}
		}
		return anArchive != null && archive.hasClasspathVisibilityTo(anArchive);
	}


	public boolean isAnyJarSelected(int type) {
		if (classpathElements != null) {
			for (int i = 0; i < classpathElements.size(); i++) {
				ClasspathElement element = (ClasspathElement) classpathElements.get(i);
				if (element.getJarType() == type && element.isSelected())
					return true;
			}
		}
		return false;
	}


	public boolean isAnyEJBJarSelected() {
		return isAnyJarSelected(ClasspathElement.EJB_JAR);
	}



	public boolean isAnyEJBClientJARSelected() {
		return isAnyJarSelected(ClasspathElement.EJB_CLIENT_JAR);

	}

	/**
	 * @return
	 */
	public int getFilterLevel() {
		return filterLevel;
	}

	/**
	 * @param i
	 */
	public void setFilterLevel(int i) {
		filterLevel = i;
	}

	/**
	 * This method selects or deselects indivual elements based on the filter level, and
	 * additionally sets the filter level.
	 * 
	 * @param i
	 */
	public void selectFilterLevel(int level) {
		setFilterLevel(level);
		switch (level) {
			case FILTER_EJB_CLIENT_JARS :
				invertClientJARSelections(ClasspathElement.EJB_CLIENT_JAR);
				break;
			case FILTER_EJB_SERVER_JARS :
				invertClientJARSelections(ClasspathElement.EJB_JAR);
				break;
			default :
				break;
		}
	}

	public void invertClientJARSelection(IProject aProject, IProject opposite) {
		ClasspathElement element = getClasspathElement(aProject);
		ClasspathElement oppositeElement = (opposite == null ? null : getClasspathElement(opposite));
		if (element.isSelected())
			invertSelectionIfPossible(element, oppositeElement);
	}

	private void invertClientJARSelections(int elementType) {
		if (classpathElements == null)
			return;

		for (int i = 0; i < classpathElements.size(); i++) {
			ClasspathElement element = (ClasspathElement) classpathElements.get(i);
			if (element.getJarType() == elementType && element.isSelected()) {
				invertSelectionIfPossible(element, null);
			}
		}
	}

	/**
	 * @param element
	 * @param elementType
	 */
	private void invertSelectionIfPossible(ClasspathElement element, ClasspathElement opposite) {
		if (element == null)
			return;
		if (opposite == null)
			opposite = getOppositeElement(element);
		if (opposite != null) {
			opposite.setSelected(true);
			element.setSelected(false);
		}
	}

	/**
	 * If the element represents an EJB client JAR, returns the corresponding server JAR. If the
	 * element represents an EJB server JAR, returns the corresponding client JAR.
	 */
	public ClasspathElement getOppositeElement(ClasspathElement element) {
		String uri = element.getText();
		Archive target = element.getTargetArchive();
		if (uri == null || target == null)
			return null;
		Archive oppositeJAR = null;
		switch (element.getJarType()) {
			case (ClasspathElement.EJB_CLIENT_JAR) :
				oppositeJAR = (Archive) clientToEJBJARs.get(target);
				break;
			case (ClasspathElement.EJB_JAR) :
				oppositeJAR = (Archive) ejbToClientJARs.get(target);
				break;
			default :
				break;
		}
		if (oppositeJAR != null)
			return getClasspathElement(oppositeJAR.getURI());

		return null;
	}

	private void setModifiedIfAnySelected(List elements) {
		for (int i = 0; i < elements.size(); i++) {
			ClasspathElement element = (ClasspathElement) elements.get(i);
			if (element.isSelected())
				setModified(true);
		}
	}

	public boolean isMyClientJAR(ClasspathElement element) {
		if (element == null || ejbToClientJARs == null)
			return false;
		Archive myClientJar = (Archive) ejbToClientJARs.get(archive);
		return myClientJar != null && myClientJar == element.getTargetArchive();
	}

	public Map getUrisToElements() {
		if(urisToElements == null)
			urisToElements = new HashMap();
		return urisToElements;
	}

}
