/*******************************************************************************
 * Copyright (c) 2001, 2004 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.model.internal.validation;

import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;

import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.jem.java.ArrayType;
import org.eclipse.jem.java.Field;
import org.eclipse.jem.java.JavaClass;
import org.eclipse.jem.java.JavaHelpers;
import org.eclipse.jem.java.JavaPackage;
import org.eclipse.jem.java.JavaParameter;
import org.eclipse.jem.java.JavaRefFactory;
import org.eclipse.jem.java.JavaVisibilityKind;
import org.eclipse.jem.java.Method;
import org.eclipse.jem.util.logger.LogEntry;
import org.eclipse.jem.util.logger.proxy.Logger;
import org.eclipse.jst.j2ee.core.internal.plugin.J2EECorePlugin;
import org.eclipse.jst.j2ee.ejb.CMPAttribute;
import org.eclipse.jst.j2ee.ejb.CMRField;
import org.eclipse.jst.j2ee.ejb.CommonRelationshipRole;
import org.eclipse.jst.j2ee.ejb.ContainerManagedEntity;
import org.eclipse.jst.j2ee.ejb.EJBRelationshipRole;
import org.eclipse.jst.j2ee.ejb.EnterpriseBean;
import org.eclipse.jst.j2ee.ejb.Entity;
import org.eclipse.jst.j2ee.ejb.Query;
import org.eclipse.jst.j2ee.ejb.QueryMethod;
import org.eclipse.jst.j2ee.ejb.Session;
import org.eclipse.jst.j2ee.ejb.SessionType;
import org.eclipse.jst.j2ee.ejb.TransactionType;
import org.eclipse.jst.j2ee.ejb.internal.impl.LocalModelledPersistentAttributeFilter;
import org.eclipse.jst.j2ee.internal.J2EEVersionConstants;

/**
 * @version 	1.0
 * @author
 */
public final class ValidationRuleUtility {
	public static long method_and_field_counter = 0x1; // used by IMethodAndFieldConstants.java
	private static final String[] _reservedWords = new String[]{"SELECT", "FROM", "WHERE", "DISTINCT", "OBJECT", "NULL", "TRUE", "FALSE", "NOT", "AND", "OR", "BETWEEN", "LIKE", "IN", "AS", "UNKNOWN", "EMPTY", "MEMBER", "OF", "IS"}; //$NON-NLS-1$  //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-11$ //$NON-NLS-12$ //$NON-NLS-13$ //$NON-NLS-14$ //$NON-NLS-15$ //$NON-NLS-16$ //$NON-NLS-17$ //$NON-NLS-18$ //$NON-NLS-19$ //$NON-NLS-20$
	private static final String COMMA = ", "; //$NON-NLS-1$

	private static LogEntry logEntry = null;
	private static Logger logger = null;
	
	public static JavaClass getCMRFieldType(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, CMRField field) {
		CommonRelationshipRole role = field.getRole();
		if(!role.isMany()) {
			ContainerManagedEntity cmp = role.getTypeEntity();
			if(cmp == null) {
				return null;
			}
			
			JavaClass local = cmp.getLocalInterface();
			// If the user has made a mistake in ejb-jar.xml, and they are trying to make
			// a relationship to a cmp which does not have a local interface, an InvalidInputException
			// will be thrown. Let the DD validation catch that error; just return
			// when this happens.
			try {
				ValidationRuleUtility.isValidTypeHierarchy(cmp, local);
			}
			catch(InvalidInputException e) {
				return null;
			}
			return local;
		}
			// <cmr-field-type> is either a java.util.Collection or a java.util.Set (p. 464)
			return field.getCollectionType();
	}

	

	
	public static final boolean followsFinderExceptionRules(EnterpriseBean bean, Method method) throws InvalidInputException {
		return ValidationRuleUtility.throwsFinderException(bean, method);
	}

	public static final boolean followsObjectNotFoundExceptionRules(EnterpriseBean bean, Method method) throws InvalidInputException {
		JavaHelpers javaUtilEnumeration = ValidationRuleUtility.getType(ITypeConstants.CLASSNAME_JAVA_UTIL_ENUMERATION, bean);
		if(ValidationRuleUtility.isAssignableFrom(method.getReturnType(), javaUtilEnumeration)) {
			// Only single object finder and select methods may throw this exception
			return !ValidationRuleUtility.throwsObjectNotFoundException(bean, method);
		}
		
		JavaHelpers javaUtilCollection = ValidationRuleUtility.getType(ITypeConstants.CLASSNAME_JAVA_UTIL_COLLECTION, bean);
		if(ValidationRuleUtility.isAssignableFrom(method.getReturnType(), javaUtilCollection)) {
			// Only single object finder and select methods may throw this exception
			return !ValidationRuleUtility.throwsObjectNotFoundException(bean, method);
		}
		
		// It's a single finder/select method, so it can throw the exception, though it is not required to.
		return true;
	}

	/**
	 * If it exists, return the Method from the method list which has the given
	 * name and parameter types (in the same order as the array elements).
	 *
	 * This method is a duplicate of getMethodExtended(String, String[]).
	 * For performance reasons, the code was duplicated instead of converting the
	 * JavaParameter[] into a String[].
	 */
	private static Method getMethod(String name, JavaParameter[] parameterTypes, List methodList) {
		if(methodList == null) {
			return null;
		}
		
		Method method = null;
		JavaParameter[] params = null;
		boolean found = false;
	
		Iterator iterator = methodList.iterator();
		while(iterator.hasNext()) {
			method = (Method)iterator.next();
			
			if (method.getName().equals(name)) {
				params = method.listParametersWithoutReturn();
				
				if (params.length == parameterTypes.length) {
					found = true; //Maybe; we need more info
					
					for (int j = 0; j < params.length; j++) {
						//if any one of the parameters doesn't match then flip back to false
						JavaHelpers parm = ((JavaHelpers)params[j].getEType());
						JavaHelpers type = ((JavaHelpers)parameterTypes[j].getEType());
						if(!isSameType(parm, type)) {
							found = false;
							break;
						}
					}
					
					if (found) {
						return method;
					}
				}
			}
		}
		return null;
	}
	
	private static Method getMethod(String name, JavaHelpers[] parameterTypes, List methodList) {
		if(methodList == null) {
			return null;
		}
		
		Method method = null;
		JavaParameter[] params = null;
		boolean found = false;
	
		Iterator iterator = methodList.iterator();
		while(iterator.hasNext()) {
			method = (Method)iterator.next();
			
			if (method.getName().equals(name)) {
				params = method.listParametersWithoutReturn();
				
				if (params.length == parameterTypes.length) {
					found = true; //Maybe; we need more info
					
					for (int j = 0; j < params.length; j++) {
						//if any one of the parameters doesn't match then flip back to false
						JavaHelpers parm = ((JavaHelpers)params[j].getEType());
						JavaHelpers type = parameterTypes[j];
						if(!isSameType(parm, type)) {
							found = false;
							break;
						}
					}
					
					if (found) {
						return method;
					}
				}
			}
		}
		return null;
	}
	
	/**
	 * From JavaClass clazz, return a method, named methodNameToFind,
	 * which has exactly the same arguments as methodToMatch.
	 *
	 * If no method exists with that name and argument list, return null.
	 * 
	 * This method does not check the exceptions or return type.
	 */
	public static Method getMethod(Method methodToMatch, String methodNameToFind, List methodsExtendedList) {
		if(methodsExtendedList == null) {
			// It is not invalid to call this method with a null List. A null List
			// means that a type whose methods need to be searched doesn't exist,
			// such as searching a local view, but the bean has only a remote view.
			return null;
		}
		return getMethod(methodNameToFind, methodToMatch.listParametersWithoutReturn(), methodsExtendedList);
	}
	
	/**
	 * From JavaClass clazz, return a method, named methodNameToFind,
	 * which has exactly the same arguments as methodToMatch.
	 *
	 * If no method exists with that name and argument list, return null.
	 * 
	 * This method does not check the exceptions or return type.
	 */
	public static Method getMethodExtended(JavaClass clazz, Method methodToMatch, String methodNameToFind) throws InvalidInputException {
		if ((clazz == null) || (methodToMatch == null) || (methodNameToFind == null)) {
			return null;
		}

		return getMethodExtended(clazz, methodNameToFind, methodToMatch.listParametersWithoutReturn());
	}
	
	/**
	 * Get the method of this name and these parameters. It will look up the supertype hierarchy.
	 *
	 * This method is a duplicate of getMethodExtended(String, String[]).
	 * For performance reasons, the code was duplicated instead of converting the
	 * JavaParameter[] into a String[].
	 */
	public static Method getMethodExtended(JavaClass clazz, String methodName, JavaParameter[] parameterTypes) {
		if (clazz.isInterface()) {
			// Check the current class first. If the method has been overriden,
			// don't want to return the parent's method instead of the child's.
			return getMethodInterfaceExtended(clazz, methodName, parameterTypes);
		}
		// Check the current class first. If the method has been overriden,
		// don't want to return the parent's method instead of the child's.
		Method method = null;
		List methods = null;
		do {
			methods = clazz.getMethods();
			method = getMethod(methodName, parameterTypes, methods);
			if (method != null) {
				return method;
			}

			// else, search the parent	
			clazz = clazz.getSupertype();
		}
		while ((method == null) && (clazz != null));

		return null;
	}
	
	/**
	 * Get the method of this name and these parameters. It will look up the supertype hierarchy.
	 *
	 * This method is a duplicate of getMethodExtended(String, JavaParameter[]).
	 * For performance reasons, the code was duplicated instead of converting the
	 * JavaHelpers[] into a JavaParameter[].
	 */
	public static Method getMethodExtended(JavaClass clazz, String methodName, JavaHelpers[] parameterTypes) {
		return getMethodExtended(clazz, methodName, parameterTypes, null);
	}
	
	/**
	 * Get the method of this name and these parameters. It will look up the supertype hierarchy.
	 *
	 * This method is a duplicate of getMethodExtended(String, JavaParameter[]).
	 * For performance reasons, the code was duplicated instead of converting the
	 * JavaHelpers[] into a JavaParameter[].
	 * 
	 * If retType is null it means that the return type of the method doesn't need to be checked.
	 * Otherwise, check that the return type matches too.
	 */
	public static Method getMethodExtended(JavaClass clazz, String methodName, JavaHelpers[] parameterTypes, JavaHelpers retType) {
		if (clazz.isInterface()) {
			// Check the current class first. If the method has been overriden,
			// don't want to return the parent's method instead of the child's.
			return getMethodInterfaceExtended(clazz, methodName, parameterTypes);
		}
		// Check the current class first. If the method has been overriden,
		// don't want to return the parent's method instead of the child's.
		Method method = null;
		List methods = null;
		do {
			methods = clazz.getMethods();
			method = getMethod(methodName, parameterTypes, methods);
			if (method != null) {
				if(retType != null) {
					JavaHelpers methRetType = method.getReturnType();
					if(isAssignableFrom(methRetType, retType)) {
						return method;
					}
				}
				else {
					return method;
				}
			}

			// else, search the parent	
			clazz = clazz.getSupertype();
		}
		while ((method == null) && (clazz != null));

		return null;
	}
	
	/**
	 * Get the method of this name and these parameters. It will look up the supertype hierarchy.
	 *
	 * This method is a duplicate of getMethodInterfaceExtended(String, String[], JavaClass).
	 * For performance reasons, the code was duplicated instead of converting the
	 * JavaParameter[] into a String[].
	 */
	public static Method getMethodInterfaceExtended(JavaClass clazz, String methodName, JavaParameter[] parameterTypes) {
		if (clazz == null) {
			return null;
		}

		// Check the current class first. If the method has been overriden,
		// don't want to return the parent's method instead of the child's.
		Method method = getMethod(methodName, parameterTypes, clazz.getMethods());
		if (method != null) {
			return method;
		}
		// check parents
		List classesToCheck = clazz.getImplementsInterfaces();
		Iterator clazzIterator = classesToCheck.iterator();
		while (clazzIterator.hasNext()) {
			clazz = (JavaClass) clazzIterator.next();
			method = getMethodInterfaceExtended(clazz, methodName, parameterTypes);
			if (method != null) {
				return method;
			}
		}

		return null;
	}
	
	public static Method getMethodInterfaceExtended(JavaClass clazz, String methodName, JavaHelpers[] parameterTypes) {
		if (clazz == null) {
			return null;
		}

		// Check the current class first. If the method has been overriden,
		// don't want to return the parent's method instead of the child's.
		Method method = getMethod(methodName, parameterTypes, clazz.getMethods());
		if (method != null) {
			return method;
		}
		// check parents
		List classesToCheck = clazz.getImplementsInterfaces();
		Iterator clazzIterator = classesToCheck.iterator();
		while (clazzIterator.hasNext()) {
			clazz = (JavaClass) clazzIterator.next();
			method = getMethodInterfaceExtended(clazz, methodName, parameterTypes);
			if (method != null) {
				return method;
			}
		}

		return null;
	}

	/**
	 * Return an array of the exceptions thrown by method but not methodToMatch.
	 * If there are no such exceptions, return null. (Check the list of exceptions
	 * in the method for each exception, or a parent of the exception.)
	 */
	public static final Set getNotSubsetExceptions(EnterpriseBean bean, Method method, Method methodToMatch) {
		if((methodToMatch == null) || (method == null)) {
			return Collections.EMPTY_SET;
		}
		
		// All the exceptions defined in the throws clause of a method of the 
		// entity bean class must be included in the throws clause of the matching 
		// method of the home interface.
		//
		// Section 12.2.2
		// [15] A checked exception is one that is not a subclass of java.lang.RuntimeException
		// "Note that the javax.ejb.EJBException is a subclass of the java.lang.RuntimeException,
		// and therefore it does not have to be listed in the throws clauses of the business
		// methods."
		HashSet exceptions = new HashSet();
		List methToMatchExceptions = methodToMatch.getJavaExceptions();
		List foundMethExceptions = method.getJavaExceptions();
		for( int i = 0; i < foundMethExceptions.size(); i++ ) {
			JavaClass exc = (JavaClass)foundMethExceptions.get(i);
			if ( !isRuntimeException(exc, bean) && !isRemoteException(exc, bean) && !isExceptionInList(exc, methToMatchExceptions) ) {
				exceptions.add(exc);
			}
		}
	
		return exceptions;
	}
	
	/**
	 * Return an array of the exceptions thrown by method but not methodToMatch.
	 * If there are no such exceptions, return null. (Check the list of exceptions
	 * in the method for each exception, or a child of the exception.)
	 */
	public static final Set getNotSubsetSubtypeExceptions(EnterpriseBean bean, Method method, Method methodToMatch) {
		if((methodToMatch == null) || (method == null)) {
			return Collections.EMPTY_SET;
		}
		
		// All the exceptions defined in the throws clause of a method of the 
		// entity bean class must be included in the throws clause of the matching 
		// method of the home interface.
		//
		// Section 12.2.2
		// [15] A checked exception is one that is not a subclass of java.lang.RuntimeException
		// "Note that the javax.ejb.EJBException is a subclass of the java.lang.RuntimeException,
		// and therefore it does not have to be listed in the throws clauses of the business
		// methods."
		HashSet exceptions = new HashSet();
		List methToMatchExceptions = methodToMatch.getJavaExceptions();
		List foundMethExceptions = method.getJavaExceptions();
		for( int i = 0; i < foundMethExceptions.size(); i++ ) {
			JavaClass exc = (JavaClass)foundMethExceptions.get(i);
			if ( !isRuntimeException(exc, bean) && !isRemoteException(exc, bean) && !isSubtypeExceptionInList(exc, methToMatchExceptions) ) {
				exceptions.add(exc);
			}
		}
	
		return exceptions;
	}
	
	/**
	 * 	Exclude root home interface methods 
	 */
	public static boolean isEJBHomeMethod(EnterpriseBean bean, Method method) {
		return isSameType(bean, method.getContainingJavaClass(), ITypeConstants.CLASSNAME_JAVAX_EJB_EJBHOME);
	}
	
	/**
	 * 	Exclude root remote interface methods 
	 */
	public static boolean isEJBObjectMethod(EnterpriseBean bean, Method method) {
		return isSameType(bean, method.getContainingJavaClass(), ITypeConstants.CLASSNAME_JAVAX_EJB_EJBOBJECT);
	}
	
	/**
	 * Return true if the exception, or a parent of the exception, is in the list of exceptions.
	 */	
	public static final boolean isExceptionInList(JavaClass exc, List exceptionList) {
	       if((exc == null) || (exceptionList == null)) {
	              return false;
	       }
	       
	       if(!exc.isExistingType()) {
	              return false;
	       }
	       
	       Iterator iterator = exceptionList.iterator();
	       while(iterator.hasNext()) {
	              JavaClass exception = (JavaClass)iterator.next();
	              if(isAssignableFrom(exc, exception)) {
	                     // If there is a reflection problem, do not swallow the exception or a
	                     // faulty message may appear. (i.e., "exc" is not thrown by "foo" when it
	                     // really is but one of foo's exceptions wasn't reflected.
	                     return true;
	              }
	       }
	       return false;
	}
	
	/**
	 * Return true if the exception, or a child of the exception, is in the list of exceptions.
	 */	
	public static final boolean isSubtypeExceptionInList(JavaClass exc, List exceptionList) {
	       if((exc == null) || (exceptionList == null)) {
	              return false;
	       }
	       
	       if(!exc.isExistingType()) {
	              return false;
	       }
	       
	       Iterator iterator = exceptionList.iterator();
	       while(iterator.hasNext()) {
	              JavaClass exception = (JavaClass)iterator.next();
	              if(isAssignableFrom(exception, exc)) {
	                     // If there is a reflection problem, do not swallow the exception or a
	                     // faulty message may appear. (i.e., "exc" is not thrown by "foo" when it
	                     // really is but one of foo's exceptions wasn't reflected.
	                     return true;
	              }
	       }
	       return false;
	}

	/**
	 * Often, for validation messages, the validation message contains
	 * the name of a class. But, sometimes, the validation message is
	 * being generated because a class is null when it shouldn't be.
	 * This method is a helper method which makes the construction of
	 * the validation message a little less cluttered (i.e., instead
	 * of checking if the class is null before constructing the
	 * message, just call this method.)
	 */
	public static final String getQualifiedName(JavaHelpers helper) {
		if(helper == null) {
			return ""; //$NON-NLS-1$
		}
		return helper.getJavaName();
	}

	/**
	 * Return the method's parameters in a displayable format. e.g., if
	 * the method signature is "public Integer foo(String a, String b, String c)"
	 * then this method returns "String, String, String".
	 */	
	public static final String getParmsAsString(Method method) {
		if(method == null) {
			return ""; //$NON-NLS-1$
		}
		
		return getParmsAsString(method.listParametersWithoutReturn());
	}
	
	/**
	 * Return the parameters in a displayable format. 
	 * @see getParmsAsString(Method)
	 */
	public static final String getParmsAsString(JavaParameter[] parm) {
		if(parm.length == 0) {
			return ""; //$NON-NLS-1$
		}
		
		StringBuffer buffer = new StringBuffer();
		for(int i=0; i<parm.length; i++) {
			JavaHelpers type = parm[i].getJavaType();
			buffer.append(((type == null) ? "null" : type.getJavaName())); //$NON-NLS-1$
			buffer.append(COMMA);
		}
		return buffer.substring(0, buffer.length() - 2); // since "COMMA" is 2 char long, and the last COMMA isn't needed at the end, return everything up to but excluding the last COMMA
	}

	/**
	 * Return the parameters in a displayable format. 
	 * @see getParmsAsString(Method)
	 */
	public static final String getParmsAsString(JavaHelpers[] parm) {
		if(parm.length == 0) {
			return ""; //$NON-NLS-1$
		}
		
		StringBuffer buffer = new StringBuffer();
		for(int i=0; i<parm.length; i++) {
			JavaHelpers type = parm[i];
			buffer.append(((type == null) ? "null" : type.getJavaName())); //$NON-NLS-1$
			buffer.append(COMMA);
		}
		return buffer.substring(0, buffer.length() - 2); // since "COMMA" is 2 char long, and the last COMMA isn't needed at the end, return everything up to but excluding the last COMMA
	}
	
	/**
	 * Returns the name of the type, e.g. "com.ibm.foo.MyFoo"
	 * If the type is an array, the array type will be returned.
	 * e.g. if the type is java.lang.String[], java.lang.String[] will
	 * be returned, not the java.lang.String type.
	 */
	public static final JavaHelpers getType(EClassifier classifier) {
		if(classifier == null) {
			return null;
		}
	
		JavaHelpers type = ((JavaHelpers)classifier);
	
		return type;
	}

	/**
	 * javaClassName must be fully qualified
	 */
	public static JavaHelpers getType(String javaClassName, EnterpriseBean ejb) throws InvalidInputException {
		if((javaClassName == null)  || (javaClassName.equals("") || (ejb == null))) { //$NON-NLS-1$
			throw new InvalidInputException();
		}
	
		Resource resource = ejb.eResource();
		if(resource == null) {
			throw new InvalidInputException();
		}
	
		return getType(javaClassName, resource.getResourceSet());
	}
	
	/**
	 * javaClassName must be fully qualified
	 */
	public static JavaHelpers getType(String javaClassName, ResourceSet resourceSet) throws InvalidInputException {
		return getType(javaClassName, resourceSet, true);
	}
	
	/**
	 * javaClassName must be fully qualified
	 */
	public static JavaHelpers getType(String javaClassName, ResourceSet resourceSet, boolean throwExcIfNotValid) throws InvalidInputException {
		if((javaClassName == null)  || (javaClassName.equals("") || (resourceSet == null))) { //$NON-NLS-1$
			Logger aLogger = getMsgLogger();
			if(aLogger.isLoggingLevel(Level.FINEST)) {
				LogEntry entry = getLogEntry();
				entry.setSourceID("ValidationRuleUtility.getType(String, ResourceSet, boolean)"); //$NON-NLS-1$
				entry.setText("invalid parameter; javaClassName = {0} and resourceSet = {1}"); //$NON-NLS-1$
				entry.setTokens(new String[]{javaClassName, String.valueOf(resourceSet)});
				entry.appendStackTrace();
				aLogger.write(Level.FINEST, entry);
			}
			throw new InvalidInputException();
		}
	
		// If the class doesn't exist, it will be reflected
		JavaHelpers helper = JavaRefFactory.eINSTANCE.reflectType(javaClassName, resourceSet);
		if(throwExcIfNotValid) {
			isValidType(helper); // check that the type has been reflected properly
		}
		
		return helper;
	}
	
	/**
     * @return
     */
    private static LogEntry getLogEntry() {
		if(logEntry == null) {
		    logEntry = new LogEntry(IEJBValidatorConstants.BUNDLE_NAME);
		}
		logEntry.reset(); // reset the values so that we're not logging stale data
		return logEntry;
    }

    /**
     * @return
     */
    private static Logger getMsgLogger() {
        if(logger == null)
            logger = J2EECorePlugin.getPlugin().getMsgLogger();
        return logger;
    }

    public static final JavaHelpers getType(Field field) {
		if(field == null) {
			return null;
		}
		
		return (JavaHelpers)field.getEType();
	}
	
	/**
	 * Return true if the JavaClass passed in has the Method defined
	 * on it. Return false if the Method is defined on a supertype or 
	 * is not defined on the class at all.
	 */
	public static final boolean onClass(JavaClass clazz, Method method) {
		if((clazz == null) || (method == null)) {
			return false;
		}
		
		return clazz.equals(method.getJavaClass()); 
	}
	
	/**
	 * Return true if the JavaClass passed in has the Field defined
	 * on it. Return false if the Field is defined on a supertype or 
	 * is not defined on the class at all.
	 */
	public static final boolean onClass(JavaClass clazz, Field field) {
		if((clazz == null) || (field == null)) {
			return false;
		}
		
		return clazz.equals(field.getJavaClass()); 
	}
	
	public static final boolean isApplicationException(JavaClass exception, EnterpriseBean bean) {
		if(exception == null) {
			return false;
		}
		
		// Exempt EJBException from the application exception check because it'll drive users crazy to see 
		// it flagged as an application exception.
		try {
			if(ValidationRuleUtility.isSameType(exception, getType(ITypeConstants.CLASSNAME_JAVAX_EJB_EJBEXCEPTION, bean))) {
				return false;
			}
		}
		catch(InvalidInputException e) {
			// logged in getType()
			// if EJBException can't be found, then there's probably a system JAR missing
		}
		
		// 18.1.1 Application exceptions
		// An application exception is an exception defined in the throws clause of a method of the enterprise
		// Bean's home and component interfaces, other than the java.rmi.RemoteException.
		return !isRemoteException(exception, bean);
	}
	
	public static final boolean isRemoteMethod(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method) {
		try {
			JavaHelpers javaRmiRemote = ValidationRuleUtility.getType(ITypeConstants.CLASSNAME_JAVA_RMI_REMOTE, bean);
			if(isAssignableFrom(clazz, javaRmiRemote)) {
				return true;
			}
		}
		catch(InvalidInputException e) {
			return false;
		}
		
		return false;
	}
	
	public static final boolean isReservedWord(String name) {
		if(name == null) {
			return false;
		}
		
		String upperName = name.toUpperCase();
		for(int i=0; i<_reservedWords.length; i++) {
			if(upperName.equals(_reservedWords[i])) {
				return true;
			}
		}
		return false;
	}
	
	public static final boolean isRuntimeException(JavaClass clazz, EnterpriseBean bean) {
		if(clazz == null) {
			return false;
		}
		
		try {
			JavaHelpers runtimeExc = getType(ITypeConstants.CLASSNAME_JAVA_LANG_RUNTIMEEXCEPTION, bean);
			return isException(clazz, runtimeExc.getWrapper());
		}
		catch(InvalidInputException e) {
			return false;
		}
	}
	
	public static final boolean isRemoteException(JavaClass clazz, EnterpriseBean bean) {
		if(clazz == null) {
			return false;
		}
		
		try {
			JavaHelpers remoteExc = getType(ITypeConstants.CLASSNAME_JAVA_RMI_REMOTEEXCEPTION, bean);
			return isException(clazz, remoteExc.getWrapper());
		}
		catch(InvalidInputException e) {
			return false;
		}
	}

	/**
	 * Return true if the clazz is an instance of the exception.
	 */	
	public static final boolean isException(JavaClass clazz, JavaClass exception) {
		if((clazz == null) || (exception == null)) {
			return false;
		}
		
		return isAssignableFrom(clazz, exception);
	}
	
	/**
	 * Return true if the type is either java.util.Collection, or a type which inherits/extends java.util.Collection.
	 * The bean is needed to retrieve the java.util.Collection type.
	 */
	public static boolean isAssignableFromCollection(JavaHelpers type, EnterpriseBean bean) throws InvalidInputException {
		JavaHelpers javaUtilCollection = getType(ITypeConstants.CLASSNAME_JAVA_UTIL_COLLECTION, bean);
		return isAssignableFrom(type, javaUtilCollection);
	}
	
	/**
	 * Return true if the type is either java.util.Enumeration, or a type which inherits/extends java.util.Enumeration.
	 * The bean is needed to retrieve the java.util.Enumeration type.
	 */
	public static boolean isAssignableFromEnumeration(JavaHelpers type, EnterpriseBean bean) throws InvalidInputException {
		JavaHelpers javaUtilEnumeration = getType(ITypeConstants.CLASSNAME_JAVA_UTIL_ENUMERATION, bean);
		return isAssignableFrom(type, javaUtilEnumeration);
	}
	
	/**
	 * Return true if the type is either java.util.Set, or a type which inherits/extends java.util.Set.
	 * The bean is needed to retrieve the java.util.Set type.
	 */
	public static boolean isAssignableFromSet(JavaHelpers type, EnterpriseBean bean) throws InvalidInputException {
		JavaHelpers javaUtilSet = getType(ITypeConstants.CLASSNAME_JAVA_UTIL_SET, bean);
		return isAssignableFrom(type, javaUtilSet);
	}
	
	/**
	 * Returns true if the type is either the compare type, or inherits/extends the compare type.
	 */
	public static boolean isAssignableFrom(JavaHelpers type, JavaHelpers compareType) {
		if((type == null) || (compareType == null)) {
			return false;
		}
	
		if(type.isPrimitive() || compareType.isPrimitive()) {
			if(type.isPrimitive() && compareType.isPrimitive()) {
				return type.getPrimitive().equals(compareType.getPrimitive());
			}
			return false;
		}
		else if(type.isArray() && compareType.isArray()) {
			JavaClass classType = type.getWrapper();
			JavaClass classCompareType = compareType.getWrapper();
			if((classType == null) || (compareType == null)) {
				return false;
			}
			JavaHelpers finalType = ((ArrayType)classType).getFinalComponentType();
			JavaHelpers finalCompareType = ((ArrayType)classCompareType).getFinalComponentType();
			return isAssignableFrom(finalType, finalCompareType);
		}
		else {
			return compareType.getWrapper().isAssignableFrom(type.getWrapper());
		}
	}

	/**
	 * Return true if the given method is associated with a query element in ejb-jar.xml.
	 */
	public static final boolean isAssociatedWithQuery(ContainerManagedEntity cmp, Method method) {
		// Check method is associated with a query element in ejb-jar.xml.
		List queries = cmp.getQueries();
		Iterator iterator = queries.iterator();
		boolean found = false;
		while(iterator.hasNext()) {
			Query query = (Query)iterator.next();
			QueryMethod queryMethod = query.getQueryMethod();
			if(queryMethod == null) {
				// Let the EJBJarVRule report this
				continue;
			}
			
			if((queryMethod.getName() == null) || queryMethod.getName().equals("")) { //$NON-NLS-1$
				// Let the EJBJarVRule report this
				continue;
			}
			
			if(queryMethod.getName().equals(method.getName())) {
				found = true;
				break;
			}
		}
		
		return found;
	}
	
	public static final boolean isBeanManagedSession(EnterpriseBean bean) {
		if(bean == null) {
			return false;
		}
		
		if(bean.isEntity()) {
			return false;
		}
	
		return (((Session)bean).getTransactionType().getValue() == TransactionType.BEAN);
	}
	
	/**
	 * Return true if this method is the static initializer used for interfaces ("<clinit>")
	 */
	public static boolean isClinitMethod(EnterpriseBean bean, Method method) {
		if (method == null) {
			return false;
		}

		return method.getName().equals("<clinit>"); //$NON-NLS-1$
	}

	public static final boolean isJNDINamingContext(Field field) {
		return true;
	}
	
	/**
	 * Return true if the field is defined on java.lang.Object.
	 */
	public static boolean isJavaLangObjectField(EnterpriseBean bean, Field field) {
		return isSameType(bean, field.getContainingJavaClass(), ITypeConstants.CLASSNAME_JAVA_LANG_OBJECT);
	}
	
	/**
	 * Return true if the method is defined on named class.
	 */
	public static boolean isOwnedBy(EnterpriseBean bean, Method method, String className) {
		return isSameType(bean, method.getContainingJavaClass(), className);
	}
	
	/**
	 * Return true if given class is the same as the named class.
	 */
	public static boolean isSameType(EnterpriseBean bean, JavaClass owner, String className) {
		try {
			JavaHelpers helper = getType(className, bean);
			if(helper == null) {
				return false;
			}
			
			JavaClass object = helper.getWrapper();
			
			return isSameType(owner, object);
		}
		catch(InvalidInputException e) {
			return false;
		}
	}
	
	/**
	 * Return true if given class is the same as the named class.
	 */
	public static boolean isSameType(JavaHelpers owner, JavaHelpers object) {
		if(owner == null) {
			return false;
		}
		
		if(object == null) {
			return false;
		}
		
		if(owner.isPrimitive() && object.isPrimitive()) {
			// Both are JavaDataType
			return owner.getPrimitive().equals(object.getPrimitive());
		}
		else if(owner.isArray() && object.isArray()) {
			// Both are ArrayType
			ArrayType ownerArray = (ArrayType)owner;
			ArrayType objectArray = (ArrayType)object;
			return isSameType(ownerArray.getFinalComponentType(), objectArray.getFinalComponentType());
		}
		else if((owner.getWrapper() != null) && (object.getWrapper() != null)) {
			// Both are JavaClass
			return owner.getWrapper().equals(object.getWrapper());
		}
		else {
			// mismatching JavaHelpers type
			return false;
		}
	}
	
	/**
	 * Return true if the method is defined on java.lang.Object.
	 */
	public static boolean isJavaLangObjectMethod(EnterpriseBean bean, Method method) {
		return isSameType(bean, method.getContainingJavaClass(), ITypeConstants.CLASSNAME_JAVA_LANG_OBJECT);
	}
	
	public static final boolean isLegalRMI_IIOPInheritance(JavaClass clazz) {
		return true;
	}
	
	public static final boolean isLegalRMI_IIOPType(EnterpriseBean bean, JavaHelpers helper) throws InvalidInputException {
		if(helper == null) {
			return false;
		}
	
		return isSerializable(helper, bean);
	}
	
	public static final boolean isLocalType(EnterpriseBean bean, JavaHelpers type) {
		try {
			if(isSameType(type, getType(ITypeConstants.CLASSNAME_JAVA_LANG_OBJECT, bean))) {
				// If there's an undefined primary key (java.lang.Object), don't flag it as a local type.
				return false;
			}
		}
		catch(InvalidInputException e) {
			// Let the DD validation report this.
			return false;
		}
		
		if(isAssignableFrom(bean.getLocalInterface(), type)) {
			return true;
		}
		
		if(isAssignableFrom(bean.getLocalHomeInterface(), type)) {
			return true;
		}
		
		// Bit of a performance hack here.
		// Don't want to load and parse the entire EJBJar just to check if
		// this type is local, so assume that if the extends 
		// javax.ejb.EJBLocalHome or javax.ejb.EJBLocalObject, then it's local.
		try {
			JavaHelpers ejbLocalHome = getType(ITypeConstants.CLASSNAME_JAVAX_EJB_EJBLOCALHOME, bean);
			if(isAssignableFrom(ejbLocalHome, type)) {
				return true;
			}
		}
		catch(InvalidInputException exc) {
			// ignore and try other type
		}
		
		try {
			JavaHelpers ejbLocalObject = getType(ITypeConstants.CLASSNAME_JAVAX_EJB_EJBLOCALOBJECT, bean);
			if(isAssignableFrom(ejbLocalObject, type)) {
				return true;
			}
		}
		catch(InvalidInputException exc) {
			// ignore
		}
		
		return false;
	}
	

	
	public static final boolean usesUnknownPrimaryKey(EnterpriseBean bean) {
		if(bean.isContainerManagedEntity()) {
			return usesUnknownPrimaryKey((ContainerManagedEntity)bean);
		}
		return false;
	}
	
	public static final boolean usesUnknownPrimaryKey(ContainerManagedEntity cmp) {
		if(cmp == null) {
			return false;
		}
		
		try {
			if(isSameType(cmp.getPrimaryKey(), getType(ITypeConstants.CLASSNAME_JAVA_LANG_OBJECT, cmp))) {
				return true;
			}
		}
		catch(InvalidInputException e) {
			// If java.lang.Object can't be found, there's bigger problems than validating
			// it mistakenly
			return false;
		}

		if(cmp.getVersionID() == J2EEVersionConstants.EJB_2_0_ID) {
			List cmpFields = cmp.getFilteredFeatures(LocalModelledPersistentAttributeFilter.singleton());
			if(cmpFields != null && !cmpFields.isEmpty()) {
			Iterator iterator = cmpFields.iterator();
			while(iterator.hasNext()) {
				CMPAttribute attrib = (CMPAttribute)iterator.next();
				if(isUnknownPrimaryKey(attrib)) {
					return true;
				}
			}
		  }
		}
		return false;
	}
	
	public static final boolean isUnidirectionalRelationship(IEJBValidationContext vc, EJBRelationshipRole role) {
		// Page 131 of EJB 2.0:
		// A unidirectional relationship is implemented with a cmr-field on the entity bean instance from which
		// navigation can take place, and no related cmr-field on the entity bean instance that is the target of the
		// relationship. Unidirectional relationships are typically used when the Bean Provider wishes to restrict
		// the visibility of a relationship.
		Entity sourceEntity = role.getSource().getEntityBean();
		if(sourceEntity == null) {
			return false;
		}
		
		if(!sourceEntity.isContainerManagedEntity()) {
			return false;
		}
		
		CMRField sourceCMRField = role.getCmrField();
		if(sourceCMRField == null) {
			return false;
		}
		
		EJBRelationshipRole opposite = role.getOpposite();
		if(opposite == null) {
			return false;
		}
		
		CMRField oppositeCMRField = opposite.getCmrField();
		if(oppositeCMRField != null) {
			return false;
		}
		
		return true;
		
	}
	
	
	
	public static final boolean isUnknownPrimaryKey(CMPAttribute attrib) {
		if(attrib == null) {
			return false;
		}
		
		// Section 10.8.3
		// By definition, the deployer's generated CMP field's name is defined in the 
		// ContainerManagedEntity.WAS_GENERATED_STRING_FIELD constant.
		return ContainerManagedEntity.WAS_GENERATED_STRING_FIELD.equals(attrib.getName());
	}
	
	public static final boolean isPrimitivePrimaryKey(ContainerManagedEntity cmp) {
		if(cmp == null) {
			return false;
		}
	
		if((cmp.getPrimKeyField() != null) && !cmp.getPrimKeyField().eIsProxy()) {
			return true;
		}
	
		return false;
	}
	
	public static final boolean isPublic(Field field) {
		if ( field == null )
			return false;

		return (JavaVisibilityKind.PUBLIC_LITERAL == field.getJavaVisibility());
	}

	public static final boolean isPublic( Method method ) {
		if ( method == null )
			return false;

		return (JavaVisibilityKind.PUBLIC_LITERAL == method.getJavaVisibility());
	}

	/**
	 * Verifies that a given Class type is serializable.
	 *
	 * RMI 1.3 specification
	 * 2.6 Parameter Passing in Remote Method Invocation
	 * An argument to, or a return value from, a remote object can be any object that
	 * is serializable. This includes primitive types, remote objects, and non-remote
	 * objects that implement the java.io.Serializable interface.
	 */
	public static final boolean isSerializable(JavaHelpers cl, EnterpriseBean bean) throws InvalidInputException {
		if(cl == null) {
			// assume it's void
			return true;
		}
	
		// Check if the type reflected properly
		isValidType(cl);
		
		if ( cl.isPrimitive() ) {
			// JavaHelpers is a JavaDataType
			return true;
		}
		else if(cl.isArray()) {
			ArrayType array = (ArrayType)cl;
			if(array.isPrimitiveArray()) {
				return true;
			}
			// else, not primitive, so check its contents
			cl = array.getFinalComponentType();
		}
	
		JavaHelpers remote = getType(ITypeConstants.CLASSNAME_JAVA_RMI_REMOTE, bean);
		if(isAssignableFrom(cl, remote)) {
			return true;
		}
		
		JavaHelpers serial = getType(ITypeConstants.CLASSNAME_JAVA_IO_SERIALIZABLE, bean);
		return isAssignableFrom(cl, serial);
	}
	
	public static final boolean isStateful(EnterpriseBean bean) {
		if(bean == null) {
			return false;
		}
		
		if(bean.isEntity()) {
			return false;
		}
	
		return (((Session)bean).getSessionType().getValue() == SessionType.STATEFUL);
	}
	
	public static final boolean isStateless(EnterpriseBean bean) {
		if(bean == null) {
			return false;
		}
		
		if(bean.isEntity()) {
			return false;
		}
	
		return (((Session)bean).getSessionType().getValue() == SessionType.STATELESS);
	}
		
	public static boolean isUnnamedPackage(JavaPackage pkg) {
		if(pkg == null) {
			return true;
		}
		
		String pkgName = pkg.getName();
		return ((pkgName == null) || (pkgName.equals(""))); //$NON-NLS-1$
	}
	
	public static final boolean isValidJavaIdentifier(String name) {
		if(name == null) {
			return false;
		}
		
		char[] nameChar = name.toCharArray();
		if(nameChar.length < 1) {
			return false;
		}
		
		if(!Character.isJavaIdentifierStart(nameChar[0])) {
			return false;
		}
		boolean isValidJavaIdentifier = true;
		for(int i=1; i<nameChar.length; i++) {
			if(!Character.isJavaIdentifierPart(nameChar[i])) {
				isValidJavaIdentifier = false;
				break;
			}
		}
		return isValidJavaIdentifier;
	}
	
	/**
	 * 6.5.3 The optional SessionSynchronization interface
	 *...
	 * Only a stateful Session bean with container-managed transaction demarcation may 
	 * implement the SessionSynchronization interface.
	 *...
	 * There is no need for a Session bean with bean-managed transaction to rely on the 
	 * synchronization call backs because the bean is in control of the commit the bean 
	 * knows when the transaction is about to be committed and it knows the outcome of the 
	 * transaction commit.
	 *...
	 */
	public static final boolean isValidSessionTypeElement(Session session) {
		if(session == null) {
			return false;
		}
		
		// check syntax
		if(!session.isSetSessionType()) {
			return false;
		}
		
		if(session.getSessionType() == null) {
			return false;
		}
		
		if(session.getSessionType().getValue() == SessionType.STATEFUL) {
			return true;
		}
		
		if(session.getSessionType().getValue() == SessionType.STATELESS) {
			return true;
		}
	
		return false;
	}
	
	public static final boolean isValidTransactionTypeElement(Session sessionBean) {
		if(sessionBean == null) {
			return false;
		}
		
		if(!sessionBean.isSetTransactionType()) {
			return false;
		}
		
		if(sessionBean.getTransactionType() == null) {
			return false;
		}
		
		if(sessionBean.getTransactionType().getValue() == TransactionType.BEAN) {
			return true;
		}
		
		if(sessionBean.getTransactionType().getValue() == TransactionType.CONTAINER) {
			return true;
		}
	
		return false;	
	}
	
	/**
	 * If the type is not reflected properly, throw an InvalidInputException.
	 */
	public static final void isValidType(JavaHelpers type) throws InvalidInputException {
		if(type == null) {
			// Cheating here. Should technically access the MsgLogger from the IEJBValidationContext
			// type, but when I started changing this method and the isValidTypeHierarchy method,
			// I ended up changing 42 files because these two methods are called directly or
			// indirectly from almost everywhere. That was too much change, so I cheated.
			Logger aLogger = getMsgLogger();
			if(aLogger.isLoggingLevel(Level.FINEST)) {
				LogEntry entry = getLogEntry();
				entry.setSourceID("ValidationRuleUtility.isValidType"); //$NON-NLS-1$
				entry.setText("type is null"); //$NON-NLS-1$
				entry.appendStackTrace();
				aLogger.write(Level.FINEST, entry);
			}
			throw new InvalidInputException();
		}
	
		if(type.getWrapper() != null) {
			// check if the type reflected properly. If there's any compile errors, or references to unresolved
			// classes, can output some mistaken error messages.
			// e.g. class is not serializable
			JavaClass wrapper = type.getWrapper();
			if(type.isArray()) {
				ArrayType array = (ArrayType)type;
				isValidType(array.getFinalComponentType());
			}
			else {
				if(!wrapper.isExistingType()) {
					Logger aLogger = getMsgLogger();
					if(aLogger.isLoggingLevel(Level.FINEST)) {
						LogEntry entry = getLogEntry();
						entry.setSourceID("ValidationRuleUtility.isValidType"); //$NON-NLS-1$
						entry.setText("!wrapper.isExistingType(); type is " + wrapper.getJavaName()); //$NON-NLS-1$ 
						aLogger.write(Level.FINEST, entry);
					}
					throw new InvalidInputException(wrapper);
				}
			}
		}
	}
	
	/**
	 * If the type is not reflected properly, throw an InvalidInputException.
	 * This method, unlike isValidType, also checks every interface and class
	 * parent of the passed-in type.
	 */
	public static final void isValidTypeHierarchy(EnterpriseBean bean, JavaHelpers type) throws InvalidInputException {
		if(type == null) {
			// Cheating here. Should technically access the MsgLogger from the IEJBValidationContext
			// type, but when I started changing this method and the isValidType method,
			// I ended up changing 42 files because these two methods are called directly or
			// indirectly from almost everywhere. That was too much change, so I cheated.
			Logger aLogger = getMsgLogger();
			if(aLogger.isLoggingLevel(Level.FINEST)) {
				LogEntry entry = getLogEntry();
				entry.setSourceID("ValidationRuleUtility.isValidTypeHierarchy"); //$NON-NLS-1$
				entry.setText("type is null"); //$NON-NLS-1$
				entry.appendStackTrace();
				aLogger.write(Level.FINEST, entry);
			}
			throw new InvalidInputException();
		}
	
		// First, check this helper itself.
		isValidType(type);
		JavaHelpers javaLangObject = getType(ITypeConstants.CLASSNAME_JAVA_LANG_OBJECT, bean);
		if(isSameType(type, javaLangObject)) {
			return;
		}
		
		// If this helper exists, and is not java.lang.Object, then check every supertype.
		JavaClass classType = type.getWrapper();
		if(classType == null) {
			Logger aLogger = getMsgLogger();
			if(aLogger.isLoggingLevel(Level.FINEST)) {
				LogEntry entry = getLogEntry();
				entry.setSourceID("ValidationRuleUtility.isValidTypeHierarchy"); //$NON-NLS-1$
				entry.setText("type.getWrapper() returns null; type is " + type.getJavaName()); //$NON-NLS-1$
				aLogger.write(Level.FINEST, entry);
			}
			throw new InvalidInputException();
		}
	
		// Check the superclass. Since type is not java.lang.Object, there is at least
		// the java.lang.Object superclass.
		if(!classType.isInterface()) {
			JavaClass superType = classType.getSupertype();
			isValidTypeHierarchy(bean, superType);
		}
	
		// Check the superinterfaces, if they exist.
		List superInterfaces = classType.getImplementsInterfaces();
		if(superInterfaces != null) {
			Iterator iterator = superInterfaces.iterator();
			while(iterator.hasNext()) {
				JavaClass superIntf = (JavaClass)iterator.next();
				isValidTypeHierarchy(bean, superIntf);
			}
		}
	}
	
	/**
	 * RMI 1.3 page 6 section 2.4.1, 
	 *    A remote method declaration must include the exception java.rmi.RemoteException (or one
	 *    of its upserclasses such as java.io.IOException or java.lang.Exception) in its throws
	 *    clause, in addition to any application-specific exceptions (note that application 
	 *    specific exceptions do not have to extend java.rmi.RemoteException).
	 */
	public static final boolean throwsRemoteExceptionOrParent(EnterpriseBean bean, Method method) throws InvalidInputException {
		return throwsExceptionOrParent(bean, method, ITypeConstants.CLASSNAME_JAVA_RMI_REMOTEEXCEPTION);
	}

	/**
	 * Convenience method which checks if RemoteException (exactly, not Exception or IOException)
	 * is in the method signature.
	 */	
	public static final boolean doesNotThrowRemoteException(EnterpriseBean bean, Method method) throws InvalidInputException {
		return !throwsException(bean, method, ITypeConstants.CLASSNAME_JAVA_RMI_REMOTEEXCEPTION);
	}
	
	public static final boolean throwsObjectNotFoundException(EnterpriseBean bean, Method method) throws InvalidInputException {
		return throwsException(bean, method, ITypeConstants.CLASSNAME_JAVAX_EJB_OBJECTNOTFOUNDEXCEPTION);
	}
	
	public static final boolean throwsFinderException(EnterpriseBean bean, Method method) throws InvalidInputException {
		return throwsException(bean, method, ITypeConstants.CLASSNAME_JAVAX_EJB_FINDEREXCEPTION);
	}
	
	public static final boolean throwsCreateException(EnterpriseBean bean, Method method) throws InvalidInputException {
		return throwsException(bean, method, ITypeConstants.CLASSNAME_JAVAX_EJB_CREATEEXCEPTION);
	}
	
	public static final boolean throwsApplicationException(Method method, EnterpriseBean bean) {
		List exceptions = method.getJavaExceptions();
		if(exceptions.size() == 0) {
			return false;
		}
		
		// CHKJ2419 = {0} must be a subclass of java.lang.Exception. Read section 18.1.1, 18.2.1 of the EJB 2.0 specification.
		Iterator iterator = exceptions.iterator();
		while(iterator.hasNext()) {
			JavaClass exception = (JavaClass)iterator.next();
			
			if(isApplicationException(exception, bean)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Return true if the given method throws the named exception or a class which extends the named exception.
	 */	
	public static final boolean throwsException(EnterpriseBean bean, Method method, String exceptionName) throws InvalidInputException {
		if(method == null) {
			return false;
		}
		
		List exceptions = method.getJavaExceptions();
		Iterator iterator = exceptions.iterator();
		JavaClass exception = getType(exceptionName, bean).getWrapper();
		while(iterator.hasNext()) {
			JavaClass exc = (JavaClass)iterator.next();
			if(isAssignableFrom(exc, exception)) {
				return true;
			}
		}
		
		return false;
	}

	/**
	 * Return true if the method returns the named exception, an exception which extends the named exception, or one of the parents of the named exception (e.g. java.lang.Exception).
	 * Use this method if it needs to be detected that an exception can be thrown either directly or through something generic like java.lang.Exception.
	 */
	public static final boolean throwsExceptionOrParent(EnterpriseBean bean, Method method, String exceptionName) throws InvalidInputException {
		if(method == null) {
			return false;
		}
		
		JavaClass exception = getType(exceptionName, bean).getWrapper();

		List exceptions = method.getJavaExceptions();
		Iterator iterator = exceptions.iterator();
		while(iterator.hasNext()) {
			JavaClass exc = (JavaClass)iterator.next();
			if(isAssignableFrom(exc, exception)) {
				// Assignable from the named exception, e.g. RemoteException or a child of RemoteException
				return true;
			}
			
			if(isAssignableFrom(exception, exc)) {
				// The named exception is assignable from the method exception, e.g. java.lang.Exception
				return true;
			}
		}
		
		return false;
	}
	
	public static final boolean usesCollectionClass(EnterpriseBean bean, Method method) {
		if((bean == null) || (method == null)) {
			return false;
		}
		
		JavaParameter[] parms = method.listParametersWithoutReturn();
		if(parms != null) {
			for(int i=0; i<parms.length; i++) {
				JavaParameter parm = parms[i];
				try {
					if(isAssignableFromCollection(parm.getJavaType(), bean)) {
						return true;
					}
				}
				catch(InvalidInputException e) {
					// ignore and test next parm
					continue;
				}
			}
		}
		
		// Now check the return type
		try {
			if(isAssignableFromCollection(method.getReturnType(), bean)) {
				return true;
			}
		}
		catch(InvalidInputException e) {
			// ignore
		}
			
		return false;
	}

	public static final boolean usesLocalTypes(EnterpriseBean bean, Method method) {
		if((bean == null) || (method == null)) {
			return false;
		}
		
		JavaParameter[] parms = method.listParametersWithoutReturn();
		if(parms != null) {
			for(int i=0; i<parms.length; i++) {
				JavaParameter parm = parms[i];
				if(isLocalType(bean, parm.getJavaType())) {
					return true;
				}
			}
		}

		// Now check the return type
		if(isLocalType(bean, method.getReturnType())) {
			return true;
		}
			
		return false;
	}
}

