/*******************************************************************************
 * 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.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.JavaHelpers;
import org.eclipse.jem.java.Method;
import org.eclipse.jst.j2ee.ejb.EnterpriseBean;
import org.eclipse.wst.validation.internal.core.IMessage;
import org.eclipse.wst.validation.internal.core.ValidationException;


/**
 * @version 	1.0
 * @author
 */
public abstract class ABeanClassVRule extends ATypeVRule implements IEJBType {
	protected final static long[] BASE_TYPES = new long[]{ITypeConstants.JAVA_LANG_OBJECT};
	protected final static int MESSAGE_REMOTE_EXCEPTION_SEVERITY = IValidationContext.WARNING; // Deprecated use of RemoteException.
	
	public long[] getBaseTypes() {
		return BASE_TYPES;
	}
	
	public Object getTarget(Object parent, Object clazz) {
		if(parent == null) {
			return null;
		}
		
		return ((EnterpriseBean)parent).getEjbClass();
	}
	
	public long getDefaultMethodType() {
		return HELPER;
	}
	
	public void validate(IValidationContext vc, EnterpriseBean bean, JavaClass clazz) throws ValidationCancelledException, InvalidInputException, ValidationException {
		if(!followAbstractRules(clazz)) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2014, IValidationContext.WARNING, bean, clazz, this);
			vc.addMessage(message);
		}
		
		if(!followPublicRules(clazz)) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2022, IValidationContext.WARNING, bean, clazz, this);
			vc.addMessage(message);
		}

		if(!followFinalRules(clazz)) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2015, IValidationContext.WARNING, bean, clazz, this);
			vc.addMessage(message);
		}
		
		validateAppendixB(vc, bean, clazz);
	}
	
	public final static List getRemoteHomeMethodsExtended(List[] methodsExtendedList) {
		return methodsExtendedList[0];
	}
	
	public final static List getLocalHomeMethodsExtended(List[] methodsExtendedList) {
		return methodsExtendedList[1];
	}
	
	public final static List getRemoteComponentMethodsExtended(List[] methodsExtendedList) {
		return methodsExtendedList[2];
	}
	
	public final static List getLocalComponentMethodsExtended(List[] methodsExtendedList) {
		return methodsExtendedList[3];
	}
	
	public final static List getBeanClassMethodsExtended(List[] methodsExtendedList) {
		return methodsExtendedList[4];
	}
	
	public final List[] getMethodsExtended(IValidationContext vc, EnterpriseBean bean, JavaClass clazz) {
		// A bean class needs the following classes' extended methods:
		//    1. remote home
		//    2. local home
		//    3. remote component
		//    4. local component
		//    5. 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[5];
		JavaClass remoteHome = bean.getHomeInterface();
		if(remoteHome != null) {
			result[0] = remoteHome.getMethodsExtended();
		}
		else {
			result[0] = null;
		}
		
		JavaClass localHome = bean.getLocalHomeInterface();
		if(localHome != null) {
			result[1] = localHome.getMethodsExtended();
		}
		else {
			result[1] = null;
		}
		
		JavaClass remoteComponent = bean.getRemoteInterface();
		if(remoteComponent != null) {
			result[2] = remoteComponent.getMethodsExtended();
		}
		else {
			result[2] = null;
		}
		
		JavaClass localComponent = bean.getLocalInterface();
		if(localComponent != null) {
			result[3] = localComponent.getMethodsExtended();
		}
		else {
			result[3] = null;
		}
		
		JavaClass beanClass = bean.getEjbClass();
		if(beanClass != null) {
			result[4] = beanClass.getMethodsExtended();
		}
		else {
			result[4] = null;
		}
		
		return result;
	}
	
	public final List[] getFieldsExtended(IValidationContext vc, EnterpriseBean bean, JavaClass clazz) {
		// Never check that a bean class' field is defined on another class
		// of the bean.
		return null;
	}
	
	protected abstract boolean shouldBeFinal(JavaClass clazz);
	protected abstract boolean shouldBePublic(JavaClass clazz);
	protected abstract boolean shouldBeAbstract(JavaClass clazz);
	protected abstract boolean shouldValidateTransientField();
	protected abstract JavaHelpers getEjbCreateReturnType(EnterpriseBean bean, Method method) throws InvalidInputException;
	protected abstract String getEjbCreateReturnTypeName(EnterpriseBean bean, Method method) throws InvalidInputException;
	public abstract String getMatchingHomeMethodName(IValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method, List[] methodsExtendedList);
	
	public String getMatchingEjbHomeMethodName(IValidationContext vc, Method method) {
		// Section number stating this name convention?
		String methodName = method.getName();
		// Strip the "ejbHome" off, strip off the next character, and replace that character with a lowercase version of that character
		StringBuffer buffer = new StringBuffer(Character.toLowerCase(methodName.charAt(0)));
		buffer.append(method.getName().substring(8));
		return buffer.toString();
	}
	
	public String getMatchingEjbCreateMethodName(IValidationContext vc, Method method) {
		StringBuffer buffer = new StringBuffer(IMethodAndFieldConstants.PREFIX_C);
		// Strip the "ejbC" off of "create" and replace with "c"
		buffer.append(method.getName().substring(4));
		return buffer.toString();
	}

	public String getMatchingEjbPostCreateMethodName(IValidationContext vc, Method method) {
		StringBuffer buffer = new StringBuffer(IMethodAndFieldConstants.PREFIX_C);
		// Strip the "ejbPostC" off of "create" and replace with "c"
		buffer.append(method.getName().substring(8));
		return buffer.toString();
	}
	
	
	
	public String getMatchingEjbFindMethodName(IValidationContext vc, Method method) {
		StringBuffer buffer = new StringBuffer(IMethodAndFieldConstants.PREFIX_F);
		// Strip the "ejbF" off of "ejbFind" and replace with "f"
		buffer.append(method.getName().substring(4));
		return buffer.toString();
	}
	
	public String getMatchingBusinessMethodName(IValidationContext vc, Method method) {
		return method.getName();
	}
	
	/*
	 * The given method is not supposed to have a matching method.
	 */
	public String getNoMatchingMethodName(IValidationContext vc, Method method) {
		return null; // not supposed to have a matching method
	}

	public final boolean followFinalRules(JavaClass clazz) {
		if(shouldBeFinal(clazz)) {
			return clazz.isFinal();
		}
		return !clazz.isFinal();
	}
	
	public final boolean followPublicRules(JavaClass clazz) {
		if(shouldBePublic(clazz)) {
			return clazz.isPublic();
		}
		return !clazz.isPublic();
	}
	
	public final boolean followAbstractRules(JavaClass clazz) {
		if(shouldBeAbstract(clazz)) {
			return clazz.isAbstract();
		}
		return !clazz.isAbstract();
	}
	
	
	public void validateEjbCreateMethod(IValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method, List[] methodsExtendedLists) throws ValidationCancelledException, InvalidInputException, ValidationException {
		if(!ValidationRuleUtility.isPublic(method)) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2421, IValidationContext.WARNING, bean, clazz, method, this);
			vc.addMessage(message);
		}

		if(method.isFinal()) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2422, IValidationContext.WARNING, bean, clazz, method, this);
			vc.addMessage(message);
		}

		if(method.isStatic()) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2423, IValidationContext.WARNING, bean, clazz, method, this);
			vc.addMessage(message);
		}

		JavaHelpers retType = getEjbCreateReturnType(bean, method);
		if((retType == null) || (!ValidationRuleUtility.isAssignableFrom(method.getReturnType(), retType))) {
			String retTypeName = (retType == null) ? getEjbCreateReturnTypeName(bean, method) : retType.getJavaName();
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2424, IValidationContext.WARNING, bean, clazz, method, new String[]{retTypeName}, this);
			vc.addMessage(message);
		}

		validateRMI_IIOPTypeRules(vc, bean, clazz, method, methodsExtendedLists, true);

		if(validateEjbCreateMethodExceptions()) {
			if(!followRemoteExceptionRules(bean, method)) {
				IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2503_ejbCreate, IValidationContext.WARNING, bean, clazz, method, this);
				vc.addMessage(message);
			}
		}
	}
	
	public boolean validateEjbCreateMethodExceptions() {
		return true;
	}
	
	public void validateEjbPostCreateMethod(IValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method) throws ValidationCancelledException, InvalidInputException, ValidationException {
		if(!ValidationRuleUtility.isPublic(method)) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2426, IValidationContext.WARNING, bean, clazz, method, this);
			vc.addMessage(message);
		}

		if(method.isFinal()) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2427, IValidationContext.WARNING, bean, clazz, method, this);
			vc.addMessage(message);
		}

		if(method.isStatic()) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2428, IValidationContext.WARNING, bean, clazz, method, this);
			vc.addMessage(message);
		}

		if(!method.isVoid()) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2505_ejbPostCreate, IValidationContext.WARNING, bean, clazz, method, this);
			vc.addMessage(message);
		}

		if(!followRemoteExceptionRules(bean, method)) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2503_ejbPostCreate, IValidationContext.WARNING, bean, clazz, method, this);
			vc.addMessage(message);
		}
	}
	
	public final void validateEjbHomeMethod(IValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method, List[] methodsExtendedLists) throws ValidationCancelledException, InvalidInputException, ValidationException {
		if(!ValidationRuleUtility.isPublic(method)) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2431, IValidationContext.WARNING, bean, clazz, method, this);
			vc.addMessage(message);
		}

		if(method.isStatic()) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2439, IValidationContext.WARNING, bean, clazz, method, this);
			vc.addMessage(message);
		}

		validateRMI_IIOPTypeRules(vc, bean, clazz, method, methodsExtendedLists, true);

		if(!followRemoteExceptionRules(bean, method)) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2503_ejbHome, IValidationContext.WARNING, bean, clazz, method, this);
			vc.addMessage(message);
		}
		
		// "ejbHome" is 7 characters
		// method will follow the convention, "ejbHome" + Char.toUpper(0) + substring(1), so reverse that convention here
		StringBuffer buffer = new StringBuffer();
		buffer.append(Character.toLowerCase(method.getName().charAt(7))); // put the character back into lower-case
		buffer.append(method.getName().substring(8)); // substring starts at the character following "ejbHome" and the first character -- substring is 0 indexed
		String methodToMatchName = buffer.toString();
		
		Method matchingRemoteHomeMethod = ValidationRuleUtility.getMethod(method, methodToMatchName, getRemoteHomeMethodsExtended(methodsExtendedLists));
		if(matchingRemoteHomeMethod != null) {
			return;
		}
		
		Method matchingLocalHomeMethod = ValidationRuleUtility.getMethod(method, methodToMatchName, getLocalHomeMethodsExtended(methodsExtendedLists));
		if(matchingLocalHomeMethod != null) {
			return;
		}
		
		IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2430, IValidationContext.INFO, bean, clazz, method, new String[]{methodToMatchName}, this);
		vc.addMessage(message);
	}
	
	public final void validateBusinessMethod(IValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method, List[] methodsExtendedLists) throws ValidationCancelledException, InvalidInputException, ValidationException {
		// IWAD4048 = Business methods must not start with "ejb". Read section 7.10.4 of the EJB 2.0 specification.
		// IWAD4201 = This method name must not start with "ejb". Read section 10.6.8 of the EJB 2.0 specification.
		// IWAD4317 = The method name must not start with "ejb". Read section 12.2.7 of the EJB 2.0 specification.
		if(method.getName().startsWith(IMethodAndFieldConstants.PREFIX_EJB)) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2411, IValidationContext.WARNING, bean, clazz, method, this);		
			vc.addMessage(message);
		}
		
		// IWAD4049 = This method must be public. Read section 7.10.4 of the EJB 2.0 specification.
		// IWAD4202 = This method must be public. Read section 10.6.8 of the EJB 2.0 specification.
		// IWAD4318 = The method must be public. Read section 12.2.7 of the EJB 2.0 specification.
		if(!ValidationRuleUtility.isPublic(method)) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2441, IValidationContext.WARNING, bean, clazz, method, this);		
			vc.addMessage(message);
		}
		
		// IWAD4050 = This method must not be final. Read section 7.10.4 of the EJB 2.0 specification.
		// IWAD4203 = This method must not be final. Read section 10.6.8 of the EJB 2.0 specification.
		// IWAD4319 = The method must not be final. Read section 12.2.7 of the EJB 2.0 specification.
		if(method.isFinal()) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2442, IValidationContext.WARNING, bean, clazz, method, this);		
			vc.addMessage(message);
		}
		
		// IWAD4051 = This method must not be static. Read section 7.10.4 of the EJB 2.0 specification.
		// IWAD4204 = This method must not be static. Read section 10.6.8 of the EJB 2.0 specification.
		// IWAD4320 = The method must not be static. Read section 12.2.7 of the EJB 2.0 specification.
		if(method.isStatic()) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2443, IValidationContext.WARNING, bean, clazz, method, this);		
			vc.addMessage(message);
		}
		
		// IWAD4052 = {0} must be a legal RMI-IIOP type. Read section 7.10.4 of the EJB 2.0 specification.
		// IWAD4205 = {0} must be a legal RMI-IIOP type. Read section 10.6.8 of the EJB 2.0 specification.
		// IWAD4321 = {0} must be a legal type for RMI-IIOP. Read section 12.2.7 of the EJB 2.0 specification.
		validateRMI_IIOPTypeRules(vc, bean, clazz, method, methodsExtendedLists, true);
		
		// IWAD4053 = This method cannot throw java.rmi.RemoteException. Read section 7.10.4, 18.3.8, 18.6 of the EJB 2.0 specification.
		// IWAD4206 = This method must not throw java.rmi.RemoteException. Read section 10.6.8, 18.3.8, 18.6 of the EJB 2.0 specification.
		// IWAD4322 = This method must not throw java.rmi.RemoteException. Read section 12.2.7, 18.3.8, 18.6 of the EJB 2.0 specification.
		if(!followRemoteExceptionRules(bean, method)) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2503_bus, getMessageRemoteExceptionSeverity(), bean, clazz, method, this);		
			vc.addMessage(message);
		}
		
		validateMatchingComponentMethod(vc, bean, clazz, method, methodsExtendedLists);
	}

	public void validateEjbRemoveMethod(IValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method) throws ValidationCancelledException, InvalidInputException, ValidationException {
		// IWAD4402 = This method must be public. Read section 15.7.5 of the EJB 2.0 specification.
		if(!ValidationRuleUtility.isPublic(method)) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2492, IValidationContext.WARNING, bean, clazz, method, this);		
			vc.addMessage(message);
		}
		
		// IWAD4403 = This method must not be final. Read section 15.7.5 of the EJB 2.0 specification.
		if(method.isFinal()) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2493, IValidationContext.WARNING, bean, clazz, method, this);		
			vc.addMessage(message);
		}
		
		// IWAD4404 = This method must not be static. Read section 15.7.5 of the EJB 2.0 specification.
		if(method.isStatic()) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2494, IValidationContext.WARNING, bean, clazz, method, this);
			vc.addMessage(message);
		}
	
		// IWAD4405 = This method must return void. Read section 15.7.5 of the EJB 2.0 specification.
		if(!method.isVoid()) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2505_ejbRemove, IValidationContext.WARNING, bean, clazz, method, this);
			vc.addMessage(message);
		}
	}
	
	/*
	 * @see IClassVRule#validate(IValidationContext, JavaClass, Field)
	 */
	public void validate(IValidationContext vc, EnterpriseBean bean, JavaClass clazz, Field field, List[] fieldExtendedLists) throws ValidationCancelledException, InvalidInputException, ValidationException {
		// IWAD4024 = A transient field should not be the {0} type. Read section 7.4.1 of the EJB 2.0 specification.
		// IWAD4025 = Transient fields are discouraged. Read section 7.4.1 of the EJB 2.0 specification.
		// IWAD4115 = {0} must not be defined in this class. Read section 10.3.1 of the EJB 2.0 specification.
		// IWAD4259 = <cmp-field> field must be the {0} type. Read section 11.2.1 of the EJB 2.0 specification.
		// IWAD4260 = <cmr-field> field must be the {0} type. Read section 11.2.1 of the EJB 2.0 specification.
		if(shouldValidateTransientField()) {
			validateTransientField(vc, bean, clazz, field);
		}
	}
	
	public void validateTransientField(IValidationContext vc, EnterpriseBean bean, JavaClass clazz, Field field) throws ValidationCancelledException, InvalidInputException, ValidationException {
		// By default do nothing
	}
	
	public long getFieldType(EnterpriseBean bean, JavaClass clazz, Field field) {
		if(field == null) {
			return EXCLUDED_FIELD;
		}
		else if(field.getName().equals(IMethodAndFieldConstants.FIELDNAME_SERIALVERSIONUID)) {
			return SERIALVERSIONUID;
		}
		else {
			return OTHER_FIELD;
		}	
	}

	public void validateMatchingMethodExceptions(IValidationContext 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, IMessagePrefixEjb20Constants.CHKJ2456, IValidationContext.WARNING, bean, clazz, method, new String[]{exception.getJavaName(), matchingClazz.getJavaName()}, this);
			vc.addMessage(message);
		}
	}
	
	public final void validateMatchingHomeMethod(IValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method, List[] methodsExtendedLists) {
		Method remoteMethod = ValidationRuleUtility.getMethod(method, getMatchingHomeMethodName(vc, bean, clazz, method, methodsExtendedLists), getRemoteHomeMethodsExtended(methodsExtendedLists));
		if(remoteMethod != null) {
			validateMatchingMethodExceptions(vc, bean, clazz, method, bean.getHomeInterface(), remoteMethod);
		}
		
		Method localMethod = ValidationRuleUtility.getMethod(method, getMatchingHomeMethodName(vc, bean, clazz, method, methodsExtendedLists), getLocalHomeMethodsExtended(methodsExtendedLists));
		if(localMethod != null) {
			validateMatchingMethodExceptions(vc, bean, clazz, method, bean.getLocalHomeInterface(), localMethod);
		}
	}
	
	public final void validateMatchingComponentMethod(IValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method, List[] methodsExtendedLists) {
		Method remoteMethod = ValidationRuleUtility.getMethod(method, method.getName(), getRemoteComponentMethodsExtended(methodsExtendedLists));
		if(remoteMethod != null) {
			validateMatchingMethodExceptions(vc, bean, clazz, method, bean.getRemoteInterface(), remoteMethod);
		}
		
		Method localMethod = ValidationRuleUtility.getMethod(method, method.getName(), getLocalComponentMethodsExtended(methodsExtendedLists));
		if(localMethod != null) {
			validateMatchingMethodExceptions(vc, bean, clazz, method, bean.getLocalInterface(), localMethod);
		}
	}

	protected void validateAppendixB(IValidationContext 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, IMessagePrefixEjb20Constants.CHKJ2103, IValidationContext.ERROR, bean, thisEjbObject, msgParm, this);
					vc.addMessage(message);
				}
			}
			catch (InvalidInputException e) {
				String[] msgParm = { e.getJavaClass().getQualifiedName(), bean.getName()};
				IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb20Constants.CHKJ2849, IValidationContext.WARNING, bean, msgParm, this);
				vc.addMessage(message);
			}
		}
	}

	public final boolean followRemoteExceptionRules(EnterpriseBean bean, Method method) throws InvalidInputException, ValidationCancelledException {
		// must not throw RemoteException
		return ValidationRuleUtility.doesNotThrowRemoteException(bean, method);
	}
}
