/*******************************************************************************
 * 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.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.eclipse.jem.java.Field;
import org.eclipse.jem.java.JavaClass;
import org.eclipse.jem.java.Method;
import org.eclipse.jst.j2ee.ejb.EnterpriseBean;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;


/**
 * Performs validation common to session and entity beans.
 */
public abstract class AValidateBean extends AValidateEJB {
	protected HashSet componentParents = null; // The JavaClass instances which are parents of this JavaClass instance, if this JavaClass instance is part of a component inheritance hierarchy.
	
	public AValidateBean() {
		componentParents = new HashSet();
	}
	
	public void reset() {
		super.reset();
		componentParents.clear();
	}
	
	protected void buildComponentParents(EnterpriseBean bean) {
		if (bean == null) {
			return;
		}
		EnterpriseBean supertype = getSuperType(bean);
		if (supertype == null) {
			return;
		}

		// check this CMP's supertype
		JavaClass thisEjbObject = bean.getEjbClass();
		JavaClass parentEjbObject = supertype.getEjbClass();

		// EJBObject a Xchild of parent EJBObject (X = child, grandchild, great-grandchild, etc.)
		if (ValidationRuleUtility.isAssignableFrom(thisEjbObject, parentEjbObject)) {
			componentParents.add(parentEjbObject);
		}
		buildComponentParents(supertype);
	}

	public final Object getTarget(Object parent, Object clazz) {
		if(parent == null) {
			return null;
		}

		return ((EnterpriseBean)parent).getEjbClass();
	}
	
	public final static List getRemoteHomeMethodsExtended(List[] methodsExtendedList) {
		return methodsExtendedList[0];
	}
	
	public final static List getRemoteComponentMethodsExtended(List[] methodsExtendedList) {
		return methodsExtendedList[1];
	}
	
	public final static List getBeanClassMethodsExtended(List[] methodsExtendedList) {
		return methodsExtendedList[2];
	}
	
	public final List[] getMethodsExtended(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz) {
		// A bean class needs the following classes' extended methods:
		//    1. home
		//    2. remote
		//    3. bean class (when searching for a matching ejbPostCreate method).
		// If a particular bean doesn't use a remote view or local view,
		// then the corresponding entry in the array will be null. 
		List[] result = new List[3];
		JavaClass remoteHome = bean.getHomeInterface();
		if(remoteHome != null) {
			result[0] = remoteHome.getMethodsExtended();
		}
		else {
			result[0] = null;
		}
		
		JavaClass remoteComponent = bean.getRemoteInterface();
		if(remoteComponent != null) {
			result[1] = remoteComponent.getMethodsExtended();
		}
		else {
			result[1] = null;
		}
		
		JavaClass beanClass = bean.getEjbClass();
		if(beanClass != null) {
			result[2] = beanClass.getMethodsExtended();
		}
		else {
			result[2] = null;
		}
		
		return result;
	}
	
	public final List[] getFieldsExtended(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz) {
		// Never check that a bean class' field is defined on another class
		// of the bean.
		return null;
	}
	

	
	/**
	 * For the check that the ejbCreate method has a matching create method on the home,
	 * this method, given the bean method, returns the corresponding home method.
	 *
	 * 6.10.6 Session bean's home interface
	 * The following are the requirements for the session bean's home interface:
	 *   - Each create method must be named "create", and it must match one of 
	 *     the ejbCreate methods defined in the session bean class. The matching 
	 *     ejbCreate method must have the same number and types of arguments. 
	 *     (Note that the return type is different.)
	 *   - All the exceptions defined in the throws clause of an ejbCreate method 
	 *     of the session bean class must be defined in the throws clause of the 
	 *     matching create method of the home interface.
	 *...
	 *
	 * 9.2.8 Entity bean's home interface
	 * The following are the requirements for the entity bean's home interface:
	 *   - Each create method must be named "create", and it must match one of the 
	 *     ejbCreate methods defined in the enterprise Bean class. The matching 
	 *     ejbCreate method must have the same number and types of its arguments. 
	 *     (Note that the return type is different.)
	 *   - All the exceptions defined in the throws clause of the matching ejbCreate 
	 *     and ejbPostCreate methods of the enterprise Bean class must be included in 
	 *     the throws clause of the matching create method of the home interface 
	 *     (i.e the set of exceptions defined for the create method must be a superset
	 *     of the union of exceptions defined for the ejbCreate and ejbPostCreate methods)
	 */
	public final Method getMatchingHomeCreateMethod(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method, List[] methodsExtendedLists) throws InvalidInputException {
		vc.terminateIfCancelled();
		
		if (method == null) {
			return null;
		}

		if (bean == null) {
			return null;
		}

		JavaClass homeIntf = bean.getHomeInterface();
		ValidationRuleUtility.isValidTypeHierarchy(bean, homeIntf);

		// check only the current class, not the parents in this case.
		// This method is used in the component inheritance hierarchy tests.
		return ValidationRuleUtility.getMethod(method, IMethodAndFieldConstants.METHODNAME_CREATE, homeIntf.getMethods());
	}
	
	/**
	 * For the check that the ejbCreate method has a matching create method on the home,
	 * this method, given the bean method, returns the corresponding home method.
	 *
	 * 6.10.6 Session bean's home interface
	 * The following are the requirements for the session bean's home interface:
	 *   - Each create method must be named "create", and it must match one of 
	 *     the ejbCreate methods defined in the session bean class. The matching 
	 *     ejbCreate method must have the same number and types of arguments. 
	 *     (Note that the return type is different.)
	 *   - All the exceptions defined in the throws clause of an ejbCreate method 
	 *     of the session bean class must be defined in the throws clause of the 
	 *     matching create method of the home interface.
	 *...
	 *
	 * 9.2.8 Entity bean's home interface
	 * The following are the requirements for the entity bean's home interface:
	 *   - Each create method must be named "create", and it must match one of the 
	 *     ejbCreate methods defined in the enterprise Bean class. The matching 
	 *     ejbCreate method must have the same number and types of its arguments. 
	 *     (Note that the return type is different.)
	 *   - All the exceptions defined in the throws clause of the matching ejbCreate 
	 *     and ejbPostCreate methods of the enterprise Bean class must be included in 
	 *     the throws clause of the matching create method of the home interface 
	 *     (i.e the set of exceptions defined for the create method must be a superset
	 *     of the union of exceptions defined for the ejbCreate and ejbPostCreate methods)
	 */
	public Method getMatchingHomeCreateMethodExtended(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method) throws InvalidInputException {
		vc. terminateIfCancelled();
		if (method == null) {
			return null;
		}

		if (bean == null) {
			return null;
		}

		JavaClass homeIntf = bean.getHomeInterface();
		ValidationRuleUtility.isValidTypeHierarchy(bean, homeIntf);

		return ValidationRuleUtility.getMethodExtended(homeIntf, method, IMethodAndFieldConstants.METHODNAME_CREATE);
	}
	
	/**
	 * Return the name of the parent which the bean must implement.
	 * For entity beans, it's javax.ejb.EntityBean.
	 * For session beans, it's javax.ejb.SessionBean.
	 */
	protected abstract String getParentName();
	
	/**
	 * Returns true if the method passed in is a business method.
	 *
	 * Although the EJB 1.1 spec implies that all non-framework methods are business methods,
	 * developers may create methods on the bean which are meant for internal use only. This
	 * method (isBusinessMethod) separates the "internal helper" methods from the business
	 * methods by checking if a corresponding method exists on the remote interface. If it
	 * does, consider this a business method. 
	 */
	public boolean isBusinessMethod(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method) throws InvalidInputException {
		vc.terminateIfCancelled();

		if (method == null) {
			return false;
		}
		String name = method.getName();

		if (isFrameworkMethod(name)) {
			return false;
		}

		if (method.isConstructor()) {
			return false;
		}

		// Check if there's a matching method on the remote interface.
		if (bean == null) {
			return false;
		}

		JavaClass remoteInterface = bean.getRemoteInterface();
		ValidationRuleUtility.isValidTypeHierarchy(bean, remoteInterface);
		Method remoteInterfaceMethod = ValidationRuleUtility.getMethodExtended(remoteInterface, name, method.listParametersWithoutReturn());
		if ((remoteInterfaceMethod == null) || (ValidationRuleUtility.isEJBObjectMethod(bean, remoteInterfaceMethod))) {
			// no matching method
			// filter out methods from javax.ejb.EJBObject
			return false;
		}

		return true;
	}
	
	/**
	 * Return true if the method passed in is inherited from a parent in a
	 * component inheritance hierarchy.
	 */
	protected boolean isComponentInherited(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method meth) throws InvalidInputException {
		if (componentParents == null) {
			// Not part of a component inheritance hierarchy
			return false;
		}

		return (componentParents.contains(meth.getContainingJavaClass()));
	}
	
	public boolean isFrameworkMethod(String name) {
		if (name == null) {
			return false;
		}
		else if (name.equals(IMethodAndFieldConstants.METHODNAME_EJBACTIVATE)) {
			return true;
		}
		else if (name.equals(IMethodAndFieldConstants.METHODNAME_EJBPASSIVATE)) {
			return true;
		}
		else if (name.equals(IMethodAndFieldConstants.METHODNAME_EJBREMOVE)) {
			return true;
		}
		else if (name.startsWith(IMethodAndFieldConstants.PREFIX_EJBFIND)) {
			return true;
		}
		else if (name.equals(IMethodAndFieldConstants.METHODNAME_EJBCREATE)) {
			return true;
		}
		else if (name.equals(IMethodAndFieldConstants.METHODNAME_EJBPOSTCREATE)) {
			return true;
		}
		else if (name.equals(IMethodAndFieldConstants.METHODNAME_FINALIZE)) {
			return true;
		}
		return false;

	}
	
	/**
	 * Return true if the field can, and should, be validated.
	 * Filter out faulty fields (i.e., null), and fields which
	 * belong to the base type, whatever that is. (e.g. java.lang.Object)
	 */
	protected boolean isValid(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Field field, List[] fieldsExtendedList) throws InvalidInputException {
		if (super.isValid(vc, bean, clazz, field, fieldsExtendedList)) {
			// exclude root object methods
			if (ValidationRuleUtility.isJavaLangObjectField(bean, field)) {
				return false;
			}
			return true;
		}
		return false;
	}
	
	/**
	 * Return true if the method can, and should, be validated.
	 * Filter out faulty methods (i.e., null), and methods which
	 * belong to the base type, whatever that is. (e.g. java.lang.Object)
	 */
	protected final boolean isValid(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method, List[] methodsExtendedList) throws InvalidInputException {
		if (super.isValid(vc, bean, clazz, method, methodsExtendedList)) {
			// exclude root object methods
			if (ValidationRuleUtility.isJavaLangObjectMethod(bean, method)) {
				return false;
			}
			else if (method.getName().equals(IMethodAndFieldConstants.METHODNAME_EJBCREATE)) {
				return isValidEjbCreateMethod(vc, bean, clazz, method, methodsExtendedList);
			}
			else if (method.getName().equals(IMethodAndFieldConstants.METHODNAME_EJBPOSTCREATE)) {
				return isValidEjbCreateMethod(vc, bean, clazz, method, methodsExtendedList);
			}
			else {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * Return true if the ejbCreate method passed in is not inherited 
	 * from a parent in a component inheritance hierarchy, or is inherited,
	 * but is also defined on this bean's home interface.
	 *
	 * This method is used to exclude ejbCreate methods which are inherited
	 * from a parent in a component inheritance hierarchy, and are not
	 * exposed anywhere on this bean class instance itself. (i.e., inherited,
	 * but never used.) Since we generate the code for these methods, we
	 * should not flag them as warnings.
	 */
	protected final boolean isValidEjbCreateMethod(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method meth, List[] methodsExtendedLists) throws InvalidInputException {
		boolean isValid = true;
		boolean isComp = isComponentInherited(vc, bean, clazz, meth);
		if (isComp) {
			Method homeMeth = getMatchingHomeCreateMethod(vc, bean, clazz, meth, methodsExtendedLists);
			if (homeMeth == null) {
				isValid = false;
			}
		}

		return isValid;
	}
	
	/**
	 * 18.1.2 Programming restrictions
	 *...
	 *    - An enterprise Bean must not use read/write static fields. Using read-only static fields is
	 *   allowed. Therefore, it is recommended that all static fields in the enterprise bean class be
	 *   declared as final.
	 *...
	 */
	public void primValidate(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Field field) throws InvalidInputException {
		//super.primValidate(ejbMethod);

		vc.terminateIfCancelled();

		validateStaticField(vc, bean, clazz, field);
	}
	
	/**
	 * 6.10.4 Business methods
	 * The session bean class may define zero or more business methods whose signatures must follow these rules:
	 * 		- The method names can be arbitrary, but they must not start with "ejb" to avoid conflicts with the callback methods used by the EJB architecture.
	 *
	 * 9.2.6 Business methods
	 *   - The entity bean class may define zero or more business methods whose signatures 
	 *     must follow these rules:
	 *        - The method names can be arbitrary, but they must not start with 'ejb' to 
	 *          avoid conflicts with the callback methods used by the EJB architecture.
	 */
	public void validateBusinessMethod(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method) throws InvalidInputException {
		// The method names can be arbitrary, but they must not start with "ejb" to avoid conflicts with the callback methods used by the EJB architecture.
		if (method.getName().startsWith(IMethodAndFieldConstants.PREFIX_EJB)) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2411, IEJBValidationContext.ERROR, bean, clazz, method, this);
			vc.addMessage(message);
		}

		// Section 6.10.5 (session), 9.2.7 (entity), declare that all exceptions declared
		// on the ejbCreate, ejbPostCreate methods must be defined in the throws clause of
		// the matching create of the remote interface.

		JavaClass remote = bean.getRemoteInterface();
		ValidationRuleUtility.isValidTypeHierarchy(bean, remote);

		Method remoteMethod = ValidationRuleUtility.getMethodExtended(remote, method, method.getName());
		if (remoteMethod == null) {
			// Then this method shouldn't have been called; unless the method exists on the remote, this bean method isn't a business method.
			return;
		}
		
		Set exceptions = ValidationRuleUtility.getNotSubsetExceptions(bean, method, remoteMethod);
		if (exceptions.size() > 0) {
			Iterator iterator = exceptions.iterator();
			while (iterator.hasNext()) {
				JavaClass exc = (JavaClass) iterator.next();
				IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb11Constants.CHKJ2432, IEJBValidationContext.ERROR, bean, clazz, method, new String[] { remote.getQualifiedName(), exc.getQualifiedName()}, this);
				vc.addMessage(message);
			}
		}
		
		validateMatchingMethodExceptions(vc, bean, clazz, method, bean.getRemoteInterface(), remoteMethod);
	}
	
	/**
	 * 6.10.2 Session bean class
	 * The following are the requirements for session bean class:
	 * 		- The class must implement, directly or indirectly, the javax.ejb.SessionBean 
	 *        interface.
	 * 		- The class must be defined as public, must not be final, and must not 
	 *        be abstract.
	 * 		- The class may, but is not required to, implement the session bean's 
	 *        remote interface [4] .
	 * 		- If the class is a stateful session bean, it may optionally implement 
	 *        the javax.ejb.SessionSynchronization interface.
	 * 		- The session bean class may have superclasses and/or superinterfaces. If the 
	 *        session bean has superclasses, then the business methods, the ejbCreate methods, 
	 *        the methods of the SessionBean interface, and the methods of the optional 
	 *        SessionSynchronization interface may be defined in the session bean class, 
	 *        or in any of its superclasses.
	 *
	 *...
	 * 9.2.2 Enterprise bean class
	 *   - The following are the requirements for an entity bean class:
	 *      - The class must implement, directly or indirectly, the javax.ejb.EntityBean interface.
	 *      - The class must be defined as public and must not be abstract.
	 *      - The class must not be defined as final.
	 *...
	 *   - The class may, but is not required to, implement the entity bean's remote interface [9]. 
	 *     If the class implements the entity bean's remote interface, the class must provide no-op 
	 *     implementations of the methods defined in the javax.ejb.EJBObject interface. The container 
	 *     will never invoke these methods on the bean instances at runtime.
	 *   - A no-op implementation of these methods is required to avoid 
	 *     defining the entity bean class as abstract.
	 *   - The entity bean class must implement the business methods, and the 
	 *     ejbCreate, ejbPostCreate, and ejbFind<METHOD> methods as described 
	 *     later in this section.
	 *   - The entity bean class may have superclasses and/or superinterfaces. 
	 *     If the entity bean has superclasses, the business methods, the 
	 *     ejbCreate and ejbPostCreate methods, the finder methods, and the
	 *     methods of the EntityBean interface may be implemented in the 
	 *     enterprise bean class or in any of its superclasses.
	 *   - The entity bean class is allowed to implement other methods (for 
	 *     example helper methods invoked internally by the business methods) 
	 *     in addition to the methods required by the EJB specification.
	 *...
	 */
	public void validateClass(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz) throws InvalidInputException {
		vc.terminateIfCancelled();

		buildComponentParents(bean);

		// The class must implement, directly or indirectly, the javax.ejb.EntityBean (for entity beans), 
		// or the javax.ejb.SessionBean (for session beans), interface.
		if (!ValidationRuleUtility.isAssignableFrom(clazz, ValidationRuleUtility.getType(getParentName(), bean))) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb11Constants.CHKJ2013, IEJBValidationContext.ERROR, bean, clazz, new String[] {clazz.getQualifiedName(), getParentName()}, this);
			vc.addMessage(message);
		}

		// For both entity and session beans, the class must be public.
		if (!clazz.isPublic()) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2022, IEJBValidationContext.ERROR, bean, clazz, new String[] { clazz.getQualifiedName()}, this);
			vc.addMessage(message);
		}

		// For both entity and session beans, the class must not be abstract.
		if (clazz.isAbstract()) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2014, IEJBValidationContext.ERROR, bean, clazz, new String[] { clazz.getQualifiedName()}, this);
			vc.addMessage(message);
		}

		// For both entity and session beans, the class must not be final.
		if (clazz.isFinal()) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2015, IEJBValidationContext.ERROR, bean, clazz, new String[] { clazz.getQualifiedName()}, this);
			vc.addMessage(message);
		}

		if (ValidationRuleUtility.isUnnamedPackage(clazz.getJavaPackage())) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2041, IEJBValidationContext.INFO, bean, clazz, this);
			vc.addMessage(message);
		}
		
		validateAppendixB(vc, bean, clazz);
	}
	
	/**
	 * 9.2.3 ejbCreate methods
	 *   - The entity bean class may define zero or more ejbCreate(...) methods whose signatures 
	 *     must follow these rules:
	 *       - The method name must be ejbCreate.
	 *       - The method must be declared as public.
	 *       - The method must not be declared as final or static.
	 *       - The return type must be the entity bean's primary key type.
	 *       - The method argument and return value types must be legal types for RMI-IIOP.
	 *       - The throws clause may define arbitrary application specific exceptions, 
	 *         including the javax.ejb.CreateException.
	 *       - Compatibility Note: EJB 1.0 allowed the ejbCreate method to throw the 
	 *         java.rmi.RemoteException to indicate a non-application exception. This 
	 *         practice is deprecated in EJB 1.1 -- an EJB 1.1 compliant enterprise bean 
	 *         should throw the javax.ejb.EJBException or another java.lang.RuntimeException
	 *         to indicate non-application exceptions to the Container (see Section 12.2.2).
	 *   - The entity object created by the ejbCreate method must have a unique primary key. 
	 *     This means that the primary key must be different from the primary keys of all 
	 *     the existing entity objects within the same home. The ejbCreate method should 
	 *     throw the DuplicateKeyException on an attempt to create an entity object with 
	 *     a duplicate primary key. However, it is legal to reuse the primary key of a
	 *     previously removed entity object.
	 *
	 * 9.2.8 Entity bean's home interface
	 * The following are the requirements for the entity bean's home interface:
	 *   - Each create method must be named "create", and it must match one of the 
	 *     ejbCreate methods defined in the enterprise Bean class. The matching 
	 *     ejbCreate method must have the same number and types of its arguments. 
	 *     (Note that the return type is different.)
	 *   - All the exceptions defined in the throws clause of the matching ejbCreate 
	 *     and ejbPostCreate methods of the enterprise Bean class must be included in 
	 *     the throws clause of the matching create method of the home interface 
	 *     (i.e the set of exceptions defined for the create method must be a superset
	 *     of the union of exceptions defined for the ejbCreate and ejbPostCreate methods)
	 *...
	 *
	 * 9.4.2 ejbCreate, ejbPostCreate
	 *...
	 *   - The ejbCreate(...) methods must be defined to return the primary key class type. 
	 *     The implementation of the ejbCreate(...) methods should be coded to return a null. 
	 *     The returned value is ignored by the Container.
	 *...
	 */
	public void validateEjbCreateMethod_homeDep(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method) throws InvalidInputException {
		vc.terminateIfCancelled();

		// The method which calls this method must have already tested that the method name is ejbCreate.
		if (method == null) {
			return;
		}

		Method createMethod = getMatchingHomeCreateMethodExtended(vc, bean, clazz, method);
		if (createMethod == null) {
			// Can't check the exceptions of a method which doesn't exist.
			return;
		}

		// Whether this is from a component inheritance or not, if the method exists on the
		// home, check that the method follows the spec.

		// Section 6.10.6 (session), 9.2.8 (entity), declare that all exceptions declared
		// on the ejbCreate, ejbPostCreate methods must be defined in the throws clause of
		// the matching create of the home interface.
		Set exceptions = ValidationRuleUtility.getNotSubsetExceptions(bean, method, createMethod);
		if (exceptions.size() > 0) {
			Iterator iterator = exceptions.iterator();
			while (iterator.hasNext()) {
				JavaClass exc = (JavaClass) iterator.next();
				IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb11Constants.CHKJ2420, IEJBValidationContext.ERROR, bean, clazz, method, new String[] { exc.getQualifiedName(), bean.getHomeInterface().getQualifiedName()}, this);
				vc.addMessage(message);
			}
		}

	}
	
	public void validateHelperMethod(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method) {
		//Default
	}
	
	public void validateNoRemoteException(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method, String messagePrefix) throws InvalidInputException {
		// EJB 2.0 added "throws InvalidInputException" above
		if (method == null) {
			return;
		}

		if(!ValidationRuleUtility.doesNotThrowRemoteException(bean, method)) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, messagePrefix, IEJBValidationContext.WARNING, bean, clazz, method, this);
			vc.addMessage(message);
		}

	}
	
	/**
	 * 18.1.2 Programming restrictions
	 *...
	 *    - An enterprise Bean must not use read/write static fields. Using read-only static fields is
	 *   allowed. Therefore, it is recommended that all static fields in the enterprise bean class be
	 *   declared as final.
	 *...
	 */
	protected void validateStaticField(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Field field) throws InvalidInputException {
		if (field == null) {
			return;
		}

		// An enterprise Bean must not use read/write static fields. Using read-only static fields is
		// allowed. Therefore, it is recommended that all static fields in the enterprise bean class be
		// declared as final.
		if (field.isStatic() && !field.isFinal()) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb11Constants.CHKJ2200, IEJBValidationContext.WARNING, bean, clazz, field, this);
			vc.addMessage(message);
		}
	}
	
	public void validateMatchingMethodExceptions(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method, JavaClass matchingClazz, Method matchingMethod) {
		// Every exception thrown on the bean class' method must be thrown on the component/home method
		/* Don't check for this here - let the home & component do it.
		Set exceptions = ValidationRuleUtility.getNotSubsetExceptions(bean, method, matchingMethod);
		Iterator eiterator = exceptions.iterator();
		while(eiterator.hasNext()) {
		}
		*/
		
		// Every exception thrown by the component/home method should be thrown or there may be compile errors
		Set exceptions = ValidationRuleUtility.getNotSubsetSubtypeExceptions(bean, matchingMethod, method);
		Iterator eiterator = exceptions.iterator();
		while(eiterator.hasNext()) {
			JavaClass exception = (JavaClass)eiterator.next();
			IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2456, IEJBValidationContext.WARNING, bean, clazz, method, new String[]{exception.getJavaName(), matchingClazz.getJavaName()}, this);
			vc.addMessage(message);
		}
	}
	
	protected void validateAppendixB(IEJBValidationContext vc, EnterpriseBean bean, JavaClass thisEjbObject) {
		// The Java inheritance structure must match the EJB inheritance structure.
		// e.g. if EJB B is a child of EJB A, then class B must be a child of class A.
		// B could be a grandchild (or great-grandchild or ...) of A.
		if(bean == null) {
			return;
		}
		EnterpriseBean supertype = getSuperType(bean);
		JavaClass parentEjbObject = null;
		if (supertype != null) {
			parentEjbObject = supertype.getEjbClass();

			// EJBObject a Xchild of parent EJBObject (X = child, grandchild, great-grandchild, etc.)
			try {
				ValidationRuleUtility.isValidType(thisEjbObject);
				ValidationRuleUtility.isValidType(parentEjbObject);
				if (!ValidationRuleUtility.isAssignableFrom(thisEjbObject, parentEjbObject)) {
					String[] msgParm = new String[] { thisEjbObject.getQualifiedName(), parentEjbObject.getQualifiedName()};
					IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2103, IEJBValidationContext.ERROR, bean, thisEjbObject, msgParm, this);
					vc.addMessage(message);
				}
			}
			catch (InvalidInputException e) {
				String[] msgParm = { e.getJavaClass().getQualifiedName(), bean.getName()};
				IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2849, IEJBValidationContext.WARNING, bean, msgParm, this);
				vc.addMessage(message);
			}
		}
		
//		validateAppendixB(vc, supertype, parentEjbObject);
	}
}
