/* ====================================================================
 *
 * The ObjectStyle Group Software License, Version 1.0
 *
 * Copyright (c) 2005 - 2006 The ObjectStyle Group,
 * and individual authors of the software.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowlegement:
 *       "This product includes software developed by the
 *        ObjectStyle Group (http://objectstyle.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 *
 * 4. The names "ObjectStyle Group" and "Cayenne"
 *    must not be used to endorse or promote products derived
 *    from this software without prior written permission. For written
 *    permission, please contact andrus@objectstyle.org.
 *
 * 5. Products derived from this software may not be called "ObjectStyle"
 *    nor may "ObjectStyle" appear in their names without prior written
 *    permission of the ObjectStyle Group.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the ObjectStyle Group.  For more
 * information on the ObjectStyle Group, please see
 * <http://objectstyle.org/>.
 *
 */
package org.objectstyle.wolips.core.resources.types.project;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.core.JavaCore;
import org.objectstyle.wolips.baseforplugins.util.WOLipsNatureUtils;
import org.objectstyle.wolips.core.CorePlugin;
import org.objectstyle.wolips.core.resources.internal.build.AntApplicationNature;
import org.objectstyle.wolips.core.resources.internal.build.AntFrameworkNature;
import org.objectstyle.wolips.core.resources.internal.types.AbstractResourceAdapter;
import org.objectstyle.wolips.core.resources.types.IPBDotProjectOwner;
import org.objectstyle.wolips.core.resources.types.file.IPBDotProjectAdapter;
import org.objectstyle.wolips.core.resources.types.folder.IBuildAdapter;
import org.objectstyle.wolips.core.resources.types.folder.IDotApplicationAdapter;
import org.objectstyle.wolips.core.resources.types.folder.IDotFrameworkAdapter;
import org.objectstyle.wolips.core.resources.types.folder.IProductAdapter;
import org.objectstyle.wolips.core.resources.types.folder.IWoprojectAdapter;
import org.objectstyle.wolips.variables.BuildProperties;
import org.objectstyle.wolips.variables.VariablesPlugin;

public class ProjectAdapter extends AbstractResourceAdapter implements IPBDotProjectOwner {
	private IProject _underlyingProject;

	private boolean _isFramework;

	/**
	 * Comment for <code>BuilderNotFound</code>
	 */
	public static final int BuilderNotFound = -1;

	protected static final String TARGET_BUILDER_ID = "org.objectstyle.wolips.targetbuilder.targetbuilder";

	protected static final String INCREMENTAL_BUILDER_ID = "org.objectstyle.wolips.incrementalbuilder";

	private static final String ANT_BUILDER_ID = "org.objectstyle.wolips.antbuilder";

	public ProjectAdapter(IProject project, boolean isFramework) {
		super(project);
		this._underlyingProject = project;
		this._isFramework = isFramework;
	}

	public IProject getUnderlyingProject() {
		return this._underlyingProject;
	}

	public String getBundleName() {
		// This is not really right ... if your project name differs from your framework name,
		// this will choke, but it's currently consistent with how dynamic framework resolution
		// works, and until that is changed over to use this method, we're stuck with it.
		return getUnderlyingProject().getName();
	}
	
	/**
	 * Returns true if this project is a Maven project.
	 * 
	 * @return true if this project is a Maven project
	 */
	public boolean isMaven() {
		return WOLipsNatureUtils.isMavenNature(getUnderlyingProject());
	}
	
	public boolean isFramework() {
		return this._isFramework;
	}

	public boolean isApplication() {
		return !this.isFramework();
	}

	public IPBDotProjectAdapter getPBDotProjectAdapter() {
		IContainer underlyingContainer = this.getUnderlyingProject();
		IResource pbDotProjectResource = underlyingContainer.getFile(new Path(IPBDotProjectAdapter.FILE_NAME));
		IPBDotProjectAdapter pbDotProjectAdapter = (IPBDotProjectAdapter) pbDotProjectResource.getAdapter(IPBDotProjectAdapter.class);
		return pbDotProjectAdapter;
	}

	public IWoprojectAdapter getWoprojectAdapter() {
		IContainer underlyingContainer = this.getUnderlyingProject();
		IFolder wprojectFolder = null;
		IWoprojectAdapter wprojectAdapter = null;
		wprojectFolder = underlyingContainer.getFolder(new Path(IWoprojectAdapter.FOLDER_NAME));
		if (wprojectFolder.exists()) {
			wprojectAdapter = (IWoprojectAdapter) wprojectFolder.getAdapter(IWoprojectAdapter.class);
			if (wprojectAdapter != null) {
				return wprojectAdapter;
			}
		}
		wprojectFolder = underlyingContainer.getFolder(new Path(IWoprojectAdapter.FOLDER_NAME_DEPRECATED));
		if (wprojectFolder.exists()) {
			wprojectAdapter = (IWoprojectAdapter) wprojectFolder.getAdapter(IWoprojectAdapter.class);
		}
		return wprojectAdapter;

	}

	public IPBDotProjectOwner getPBDotProjectOwner(IResource resource) {
		if (resource == this.getUnderlyingProject()) {
			return this;
		}
		return super.getPBDotProjectOwner(resource);
	}

	public IPBDotProjectOwner getPBDotProjectOwner() {
		return this;
	}

	public boolean hasParentPBDotProjectAdapter() {
		return false;
	}

	private IFolder getBuildFolder() {
		// :TODO what if we have both folder
		IResource resource = this.getUnderlyingProject().getFolder(IBuildAdapter.FILE_NAME_DIST);
		if (resource.exists() && resource instanceof IFolder) {
			return (IFolder) resource;
		}
		resource = this.getUnderlyingProject().getFolder(IBuildAdapter.FILE_NAME_BUILD);
		if (resource.exists() && resource instanceof IFolder) {
			return (IFolder) resource;
		}
		return null;
	}

	public IBuildAdapter getBuildAdapter() {
		IResource resource = this.getBuildFolder();
		if (resource == null) {
			return null;
		}
		return (IBuildAdapter) resource.getAdapter(IBuildAdapter.class);
	}

	public IDotApplicationAdapter getDotApplicationAdapter() {
		IResource resource = this.getUnderlyingProject().getFolder(this.getUnderlyingResource().getProject().getName() + "." + IDotApplicationAdapter.FILE_NAME_EXTENSION);
		return (IDotApplicationAdapter) resource.getAdapter(IDotApplicationAdapter.class);
	}

	public IDotFrameworkAdapter getDotFrameworkAdapter() {
		IResource resource = this.getUnderlyingProject().getFolder(this.getUnderlyingResource().getProject().getName() + "." + IDotFrameworkAdapter.FILE_NAME_EXTENSION);
		return (IDotFrameworkAdapter) resource.getAdapter(IDotFrameworkAdapter.class);
	}

	public IProductAdapter getProductAdapter() {
		if (isFramework()) {
			return this.getDotFrameworkAdapter();
		}
		return this.getDotApplicationAdapter();
	}

	/**
	 * Installs the target builder.
	 * 
	 * @param position
	 * @throws CoreException
	 */
	public void installTargetBuilder(int position) throws CoreException {
		if (!this.isTargetBuilderInstalled())
			this.installBuilderAtPosition(ProjectAdapter.TARGET_BUILDER_ID, position, null);
	}

	/**
	 * Removes the target builder.
	 * 
	 * @return postion of TargetBuilder if not found
	 *         IBuilderAccessor.BuilderNotFoundwill be returned.
	 * @throws CoreException
	 */
	public int removeTargetBuilder() throws CoreException {
		if (!this.isTargetBuilderInstalled())
			return ProjectAdapter.BuilderNotFound;
		int returnValue = this.positionForBuilder(ProjectAdapter.TARGET_BUILDER_ID);
		this.removeBuilder(ProjectAdapter.TARGET_BUILDER_ID);
		return returnValue;
	}

	/**
	 * Installs the ant builder.
	 * 
	 * @throws CoreException
	 */
	public void installAntBuilder() throws CoreException {
		if (!this.isAntBuilderInstalled())
			this.installBuilder(ProjectAdapter.ANT_BUILDER_ID);
	}

	/**
	 * Removes the ant builder.
	 * 
	 * @throws CoreException
	 */
	public void removeAntBuilder() throws CoreException {
		if (this.isAntBuilderInstalled())
			this.removeBuilder(ProjectAdapter.ANT_BUILDER_ID);
	}

	/**
	 * Installs the incremetal builder.
	 * 
	 * @throws CoreException
	 */
	public void installIncrementalBuilder() throws CoreException {
		if (!this.isIncrementalBuilderInstalled())
			this.installBuilder(ProjectAdapter.INCREMENTAL_BUILDER_ID);
	}

	/**
	 * Removes the incremental builder.
	 * 
	 * @throws CoreException
	 */
	public void removeIncrementalBuilder() throws CoreException {
		if (this.isIncrementalBuilderInstalled())
			this.removeBuilder(ProjectAdapter.INCREMENTAL_BUILDER_ID);
	}

	/**
	 * Installs the java builder.
	 * 
	 * @throws CoreException
	 */
	public void installJavaBuilder() throws CoreException {
		if (!this.isJavaBuilderInstalled())
			this.installBuilder(JavaCore.BUILDER_ID);
	}

	/**
	 * Installs the java builder.
	 * 
	 * @param position
	 * @throws CoreException
	 */
	public void installJavaBuilder(int position) throws CoreException {
		if (!this.isJavaBuilderInstalled())
			this.installBuilderAtPosition(JavaCore.BUILDER_ID, position, null);
	}

	/**
	 * Removes the incremental builder.
	 * 
	 * @return postion of JavaBuilder if not found
	 *         IBuilderAccessor.BuilderNotFoundwill be returned.
	 * @throws CoreException
	 */
	public int removeJavaBuilder() throws CoreException {
		if (!this.isJavaBuilderInstalled())
			return ProjectAdapter.BuilderNotFound;
		int returnValue = this.positionForBuilder(JavaCore.BUILDER_ID);
		this.removeBuilder(JavaCore.BUILDER_ID);
		return returnValue;
	}

	/**
	 * @return Return true if the target builder is installed.
	 */
	public boolean isTargetBuilderInstalled() {
		return this.isBuilderInstalled(ProjectAdapter.TARGET_BUILDER_ID);
	}

	/**
	 * @return Return true if the ant builder is installed.
	 */
	public boolean isAntBuilderInstalled() {
		return this.isBuilderInstalled(ProjectAdapter.ANT_BUILDER_ID);
	}

	/**
	 * @return Return true if the incremental builder is installed.
	 */
	public boolean isIncrementalBuilderInstalled() {
		return this.isBuilderInstalled(ProjectAdapter.INCREMENTAL_BUILDER_ID);
	}

	/**
	 * @return Return true if the java builder is installed.
	 */
	public boolean isJavaBuilderInstalled() {
		return this.isBuilderInstalled(JavaCore.BUILDER_ID);
	}

	/**
	 * @return The builer args.
	 */
	public Map getBuilderArgs() {
		Map result = null;
		try {
			IProjectDescription desc = this.getUnderlyingProject().getDescription();
			List cmdList = Arrays.asList(desc.getBuildSpec());
			Iterator iter = cmdList.iterator();
			while (iter.hasNext()) {
				ICommand cmd = (ICommand) iter.next();
				if (this.isWOLipsBuilder(cmd.getBuilderName())) {
					result = cmd.getArguments();
					break;
				}
			}
		} catch (Exception up) {
			// if anything went wrong, we simply don't have any args (yet)
			// might wanna log the exception, though
		}
		if (null == result) {
			// this doesn't exist pre-JDK1.3, is that a problem?
			result = Collections.EMPTY_MAP;
			// result = new HashMap();
		}
		return (result);
	}

	/**
	 * @param name
	 *            Name of a build command
	 * @return boolean whether this is one of ours
	 */
	private boolean isWOLipsBuilder(String name) {
		return (name.equals(ProjectAdapter.INCREMENTAL_BUILDER_ID) || name.equals(ProjectAdapter.ANT_BUILDER_ID));
	}

	/**
	 * Method removeJavaBuilder.
	 * 
	 * @param aBuilder
	 * @throws CoreException
	 */
	private void removeBuilder(String aBuilder) throws CoreException {
		IProjectDescription desc = null;
		ICommand[] coms = null;
		ArrayList<ICommand> comList = null;
		List<ICommand> tmp = null;
		ICommand[] newCom = null;
		try {
			desc = this.getUnderlyingProject().getDescription();
			coms = desc.getBuildSpec();
			comList = new ArrayList<ICommand>();
			tmp = Arrays.asList(coms);
			comList.addAll(tmp);
			boolean foundJBuilder = false;
			for (int i = 0; i < comList.size(); i++) {
				if ((comList.get(i)).getBuilderName().equals(aBuilder)) {
					comList.remove(i);
					foundJBuilder = true;
				}
			}
			if (foundJBuilder) {
				newCom = new ICommand[comList.size()];
				for (int i = 0; i < comList.size(); i++) {
					newCom[i] = comList.get(i);
				}
				desc.setBuildSpec(newCom);
				this.getUnderlyingProject().setDescription(desc, null);
			}
		} finally {
			desc = null;
			coms = null;
			comList = null;
			tmp = null;
			newCom = null;
		}
	}

	/**
	 * Method installBuilder.
	 * 
	 * @param aBuilder
	 * @throws CoreException
	 */
	private void installBuilder(String aBuilder) throws CoreException {
		IProjectDescription desc = null;
		ICommand[] coms = null;
		ICommand[] newIc = null;
		ICommand command = null;
		try {
			desc = this.getUnderlyingProject().getDescription();
			coms = desc.getBuildSpec();
			boolean foundJBuilder = false;
			for (int i = 0; i < coms.length; i++) {
				if (coms[i].getBuilderName().equals(aBuilder)) {
					foundJBuilder = true;
				}
			}
			if (!foundJBuilder) {
				command = desc.newCommand();
				command.setBuilderName(aBuilder);
				newIc = new ICommand[coms.length + 1];
				System.arraycopy(coms, 0, newIc, 0, coms.length);
				newIc[coms.length] = command;
				desc.setBuildSpec(newIc);
				this.getUnderlyingProject().setDescription(desc, null);
			}
		} finally {
			desc = null;
			coms = null;
			newIc = null;
			command = null;
		}
	}

	/**
	 * Method isBuilderInstalled.
	 * 
	 * @param anID
	 * @return boolean
	 */
	private boolean isBuilderInstalled(String anID) {
		try {
			ICommand[] nids = this.getUnderlyingProject().getDescription().getBuildSpec();
			for (int i = 0; i < nids.length; i++) {
				if (nids[i].getBuilderName().equals(anID))
					return true;
			}
		} catch (Exception anException) {
			CorePlugin.getDefault().log(anException);
			return false;
		}
		return false;
	}

	/**
	 * Method positionForBuilder.
	 * 
	 * @param aBuilder
	 * @return int
	 * @throws CoreException
	 */
	private int positionForBuilder(String aBuilder) throws CoreException {
		IProjectDescription desc = null;
		ICommand[] coms = null;
		try {
			desc = this.getUnderlyingProject().getDescription();
			coms = desc.getBuildSpec();
			for (int i = 0; i < coms.length; i++) {
				if (coms[i].getBuilderName().equals(aBuilder))
					return i;
			}
		} finally {
			desc = null;
			coms = null;
		}
		return BuilderNotFound;
	}

	/**
	 * Method installBuilderAtPosition.
	 * 
	 * @param aBuilder
	 * @param installPos
	 * @param arguments
	 * @throws CoreException
	 */
	private void installBuilderAtPosition(String aBuilder, int installPos, Map arguments) throws CoreException {
		if (installPos == ProjectAdapter.BuilderNotFound) {
			CorePlugin.getDefault()

			.log("Somebody tries to install builder: " + aBuilder + " at an illegal position. This may happen if the removed builder does not exist.");
			return;
		}
		IProjectDescription desc = this.getUnderlyingProject().getDescription();
		ICommand[] coms = desc.getBuildSpec();
		Map args = arguments;
		if (args == null)
			args = new HashMap();
		for (int i = 0; i < coms.length; i++) {
			if (coms[i].getBuilderName().equals(aBuilder) && coms[i].getArguments().equals(args))
				return;
		}
		ICommand[] newIc = null;
		ICommand command = desc.newCommand();
		command.setBuilderName(aBuilder);
		command.setArguments(args);
		newIc = new ICommand[coms.length + 1];
		if (installPos <= 0) {
			System.arraycopy(coms, 0, newIc, 1, coms.length);
			newIc[0] = command;
		} else if (installPos >= coms.length) {
			System.arraycopy(coms, 0, newIc, 0, coms.length);
			newIc[coms.length] = command;
		} else {
			System.arraycopy(coms, 0, newIc, 0, installPos);
			newIc[installPos] = command;
			System.arraycopy(coms, installPos, newIc, installPos + 1, coms.length - installPos);
		}
		desc.setBuildSpec(newIc);
		this.getUnderlyingProject().setDescription(desc, null);
	}

	/**
	 * @return null if the project is not an application othewise invokes the
	 *         same method on ProjectAdapter
	 */
	public IPath getWorkingDir() throws CoreException {
		IPath path = null;
		IContainer workingDirFolder = getWorkingDirFolder();
		if (workingDirFolder != null && workingDirFolder.exists()) {
			path = workingDirFolder.getLocation();
		}
		return path;
	}

	protected boolean mockBundlesEnabled() {
		return Platform.getPreferencesService().getBoolean("org.objectstyle.wolips.preferences", "org.objectstyle.wolips.preference.MockBundleEnabled", true, null);
	}
	
	/**
	 * @return null if the project is not an application otherwise invokes the
	 *         same method on ProjectAdapter
	 */
	public IContainer getWorkingDirFolder() throws CoreException {
		IContainer workingDirFolder;
		IProject project = this.getUnderlyingProject();
		BuildProperties buildProperties = (BuildProperties)project.getAdapter(BuildProperties.class);
		if (buildProperties.getWOVersion().isAtLeastVersion(5, 6) || !mockBundlesEnabled()) {
			workingDirFolder = project;
		} else {
			if (this.isAntBuilderInstalled() || (WOLipsNatureUtils.getNature(project) instanceof AntApplicationNature)) {
				workingDirFolder = this.getUnderlyingProject().getFolder(IBuildAdapter.FILE_NAME_DIST);
			} else {
				workingDirFolder = this.getUnderlyingProject().getFolder(IBuildAdapter.FILE_NAME_BUILD);
			}
			if (workingDirFolder != null && workingDirFolder.exists()) {
				IFolder woaFolder = null;
				IResource[] members = workingDirFolder.members();
				for (int i = 0; woaFolder == null && i < members.length; i++) {
					IResource member = members[i];
					if (member.getType() == IResource.FOLDER && member.getName().endsWith(".woa")) {
						woaFolder = (IFolder) member;
					}
				}
				if (woaFolder != null && woaFolder.exists()) {
					workingDirFolder = woaFolder;
				} else {
					workingDirFolder = null;
				}
			} else {
				workingDirFolder = null;
			}
		}
		return workingDirFolder;
	}

	public IPath getWOJavaArchive() throws CoreException {
		IPath path = null;
		IProject project = this.getUnderlyingProject();
		BuildProperties buildProperties = (BuildProperties)project.getAdapter(BuildProperties.class);
		if (buildProperties.getWOVersion().isAtLeastVersion(5, 6) || !mockBundlesEnabled()) {
			path = this.getUnderlyingProject().getLocation();
		} else {
			IResource resource = null;
			String projectName = project.getName();
			// String projectNameLC = projectName.toLowerCase();
			// I'd rather use the knowledge from the IncrementalNature, but
			// that fragment is not
			// visible here (so I can't use the class, I think) [hn3000]
			if (this.isFramework()) {
				if (this.isAntBuilderInstalled() || (WOLipsNatureUtils.getNature(project) instanceof AntFrameworkNature)) {
					resource = getJar("dist/", ".framework/");
					if (!resource.exists())
						resource = getJar("", ".framework/");
				} else if (this.isIncrementalBuilderInstalled()) {
					resource = this.getUnderlyingProject().getFolder("build/" + projectName + ".framework/Resources/Java");
				}
				if (resource != null && resource.exists()) {
					path = resource.getLocation();
				} else {
					IPath externalBuildRoot = VariablesPlugin.getDefault().getProjectVariables(_underlyingProject).getExternalBuildRoot();
					if (externalBuildRoot != null) {
						path = externalBuildRoot.append(projectName + ".framework/Resources/Java/" + projectName + ".jar");
					}
				}
			} else if (this.isApplication()) { // must be application
				IContainer wdFolder = getWorkingDirFolder();
				if (wdFolder != null && wdFolder.exists()) {
					IFolder javaFolder = wdFolder.getFolder(new Path("Contents/Resources/Java"));
					if (this.isAntBuilderInstalled() || (WOLipsNatureUtils.getNature(project) instanceof AntApplicationNature)) {
						resource = javaFolder.findMember(wdFolder.getName().substring(0, wdFolder.getName().length() - 4).toLowerCase() + ".jar");
						if (!resource.exists())
							resource = getJar("", ".woa/Contents/");
					} else if (this.isIncrementalBuilderInstalled()) {
						resource = javaFolder;
					}
				}
				if (resource != null && (resource.exists())) {
					path = resource.getLocation();
				} else {
					IPath externalBuildRoot = VariablesPlugin.getDefault().getProjectVariables(_underlyingProject).getExternalBuildRoot();
					if (externalBuildRoot != null) {
						path = externalBuildRoot.append(projectName + ".woa/Contents/Resources/Java/" + projectName + ".jar");
					}
				}
			}
		}
		return path;
	}

	private IResource getJar(String prefix, String postfix) {
		IResource result = null;
		String projectName = this.getUnderlyingProject().getName();
		result = this.getUnderlyingProject().getFile(prefix + projectName + postfix + "Resources/Java/" + projectName + ".jar");
		if (result == null || !result.exists()) {
			result = this.getUnderlyingProject().getFile(prefix + projectName + postfix + "Resources/Java/" + projectName.toLowerCase() + ".jar");
		}
		return result;
	}

	public BuildProperties getBuildProperties() {
		return (BuildProperties) _underlyingProject.getAdapter(BuildProperties.class);
	}
	
	/**
	 * Returns true if the given resource will be considered a resource to WebObjects.
	 * 
	 * @param resource the resource to test
	 * @return true if the given resource will be considered a resource to WebObjects
	 */
	public boolean isResource(IResource resource) {
		IProjectPatternsets patternsets = (IProjectPatternsets)getUnderlyingProject().getAdapter(IProjectPatternsets.class);
		boolean isResource = patternsets.matchesResourcesPattern(resource);
		return isResource;
	}
	
	/**
	 * Returns true if a file in the given container will be considered a resource to WebObjects.
	 * 
	 * @param container the container to test
	 * @return true if a file in the given container will be considered a resource to WebObjects
	 */
	public boolean isResourceContainer(IContainer container) {
		return isResource(container.getFolder(new Path("Random.eomodeld")));
	}
	
	/**
	 * Returns the default folder to use for storing Resources (like EOModels). Currently this
	 * is just a best-guess.
	 * 
	 * @return the default folder to use for storing Resources
	 */
	public IContainer getDefaultResourcesFolder() {
		IProject project = getUnderlyingProject();
		IContainer resourcesFolder = project.getFolder("Resources");
		if (!resourcesFolder.exists()) {
			if (isMaven()) {
				resourcesFolder = project.getFolder(new Path("src/main/resources"));
				if (!resourcesFolder.exists()) {
					resourcesFolder = project;
				}
			}
			else {
				resourcesFolder = project;
			}
		}
		return resourcesFolder;
	}
	
	/**
	 * Returns true if a file in the given container will be considered a component to WebObjects.
	 * 
	 * @param container the container to test
	 * @return true if a file in the given container will be considered a component to WebObjects
	 */
	public boolean isComponentsContainer(IContainer container) {
		return isResource(container.getFolder(new Path("Random.wo")));
	}
	
	/**
	 * Returns the default folder to use for storing Components. Currently this
	 * is just a best-guess.
	 * 
	 * @return the default folder to use for storing Components
	 */
	public IContainer getDefaultComponentsFolder() {
		IProject project = getUnderlyingProject();
		IContainer componentsFolder = project.getFolder("Components");
		if (!componentsFolder.exists()) {
			if (isMaven()) {
				componentsFolder = project.getFolder(new Path("src/main/components"));
				if (!componentsFolder.exists()) {
					componentsFolder = project;
				}
			}
			else {
				componentsFolder = project;
			}
		}
		return componentsFolder;
	}
}
