/*******************************************************************************
 * Copyright (c) 2001, 2006 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.text.MessageFormat;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;

import org.eclipse.core.resources.IProject;
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.emf.workbench.ProjectResourceSet;
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 HashMap helperMap = null;
	public static Map projectHelperMap =   Collections.synchronizedMap( new HashMap() );
	private static HashSet commonClassNames = 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();
		}

		JavaHelpers helper = null;
		if(commonClassNames == null || commonClassNames.isEmpty()) {
			initializeCommonClassNames();
		}
		if (commonClassNames.contains(javaClassName)) {
			ResourceSet rSet = resource.getResourceSet();
			ResourceSet set = resource == null ? null : resource.getResourceSet();
			IProject project = null;
			if (set instanceof ProjectResourceSet){
				project = ((ProjectResourceSet) set).getProject();
			}
			
			//helperMap = getHelperMap(rSet);
			//Object obj = getHelperMap(rSet).get(javaClassName);
			Object obj = getHelperMap(project).get(javaClassName);
			if (obj != null) 
				return (JavaHelpers) obj;
			 else {
				helper = getType(javaClassName,rSet);
				//getHelperMap(rSet).put(javaClassName, helper);
				getHelperMap(project).put(javaClassName, helper);
			}
		} else
			helper = getType(javaClassName, resource.getResourceSet());
		return helper;
	}
   
	  protected static HashMap getHelperMap(IProject  project){
		HashMap mapHelper = (HashMap)projectHelperMap.get( project ); 
		if( mapHelper == null ){
			mapHelper =  new HashMap();
			projectHelperMap.put(project, mapHelper);
		}
		helperMap = mapHelper;
		return mapHelper;
	}    
    
	private static void initializeCommonClassNames() {
		if(commonClassNames == null)
			commonClassNames = new HashSet();
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVA_IO_IOEXCEPTION);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVA_IO_SERIALIZABLE);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVA_LANG_OBJECT);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVA_LANG_EXCEPTION);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVA_LANG_RUNTIMEEXCEPTION);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVA_RMI_REMOTE);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVA_RMI_REMOTEEXCEPTION);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVA_UTIL_COLLECTION);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVA_UTIL_ENUMERATION);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVA_UTIL_SET);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVAX_EJB_CREATEEXCEPTION);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVAX_EJB_ENTITYBEAN);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVAX_EJB_EJBEXCEPTION);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVAX_EJB_EJBHOME);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVAX_EJB_EJBLOCALHOME);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVAX_EJB_EJBOBJECT);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVAX_EJB_EJBLOCALOBJECT);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVAX_EJB_ENTITYCONTEXT);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVAX_EJB_FINDEREXCEPTION);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVAX_EJB_MESSAGEDRIVENBEAN);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVAX_EJB_OBJECTNOTFOUNDEXCEPTION);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVAX_EJB_SESSIONBEAN);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVAX_EJB_SESSIONCONTEXT);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVAX_EJB_SESSIONSYNCHRONIZATION);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVAX_JMS_MESSAGE);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVAX_JMS_MESSAGELISTENER);
		commonClassNames.add(ITypeConstants.CLASSNAME_JAVAX_TRANSACTION_USERTRANSACTION);
	}
	
	/**
	 * 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$
				String text = "invalid parameter; javaClassName = {0} and resourceSet = {1}";
				//entry.setText("invalid parameter; javaClassName = {0} and resourceSet = {1}"); //$NON-NLS-1$
				//entry.setTokens(new String[]{javaClassName, String.valueOf(resourceSet)});
				String result = MessageFormat.format(text,
						 new String[]{javaClassName, String.valueOf(resourceSet)});
				entry.setText(result);
				
				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;
	}
}

