package org.eclipse.jst.j2ee.model.internal.validation;

/*
* Licensed Material - Property of IBM
* (C) Copyright IBM Corp. 2001 - All Rights Reserved.
* US Government Users Restricted Rights - Use, duplication or disclosure
* restricted by GSA ADP Schedule Contract with IBM Corp.
*/

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 org.eclipse.jem.java.Field;
import org.eclipse.jem.java.JavaClass;
import org.eclipse.jem.java.Method;
import org.eclipse.jst.j2ee.ejb.CMPAttribute;
import org.eclipse.jst.j2ee.ejb.ContainerManagedEntity;
import org.eclipse.jst.j2ee.ejb.EnterpriseBean;
import org.eclipse.wst.validation.internal.core.ValidationException;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;


/**
 * This class checks entity bean classes for errors or potential errors.
 * If any problems are found, an error, warning, or info marker is added to the task list.
 *
 * The following paragraph is taken from
 * Enterprise JavaBeans Specification ("Specification")
 * Version: 1.1
 * Status: Final Release
 * Release: 12/17/99
 * Copyright 1999 Sun Microsystems, Inc.
 * 901 San Antonio Road, Palo Alto, CA 94303, U.S.A.
 * All rights reserved.
 *
 *
 * All 9.2.X sections describe BMP requirements. (And the bulk of those
 * are implemented in ValidateKeyClass.)
 * If a CMP requirement is different than these, then the differences are
 * documented in 9.4.X sections.
 *
 * 9.4.7 primary key type
 *   - The container must be able to manipulate the primary key type. Therefore, 
 *     the primary key type for an entity bean with container-managed persistence 
 *     must follow the rules in this subsection, in addition to those specified in 
 *     Subsection 9.2.9.
 *
 *     There are two ways to specify a primary key class for an entity bean with container-managed persistence:
 *        - Primary key that maps to a single field in the entity bean class.
 *        - Primary key that maps to multiple fields in the entity bean class.
 *     The second method is necessary for implementing compound keys, and the first method is convenient for
 *     single-field keys. Without the first method, simple types such as String would have to be wrapped in a
 *     user-defined class.
 * 
 *     9.4.7.1 Primary key that maps to a single field in the entity bean class
 *     The Bean Provider uses the primkey-field element of the deployment descriptor to specify the
 *     container-managed field of the entity bean class that contains the primary key. The field's type must be
 *     the primary key type.
 *
 *     9.4.7.2 Primary key that maps to multiple fields in the entity bean class
 *     The primary key class must be public, and must have a public constructor with no parameters.
 *     All fields in the primary key class must be declared as public.
 *     The names of the fields in the primary key class must be a subset of the names of the container-managed
 *     fields. (This allows the container to extract the primary key fields from an instance's container-managed
 *     fields, and vice versa.)
 *...
 */
public class ValidateCMPKey extends AValidateKeyClass implements IMessagePrefixEjb11Constants {
	private boolean hasAConstructor = false;
	private boolean hasDefaultConstructor = false;
	private Set _beanFieldNames = new HashSet();

	private static final String MSSGID = ".eb"; // In messages, to identify which message version belongs to the BMP bean class, this id is used. //$NON-NLS-1$
	private static final String EXT = MSSGID + SPEC; // Extension to be used on non-method, non-field messages
	private static final String BEXT = MSSGID + ON_BASE + SPEC; // Extension to be used on a method/field message when the method/field is inherited from a base type
	private static final String MEXT = MSSGID + ON_THIS + SPEC; // Extension to be used on a method/field message when the method/field is implemented on the current type

	private static final Object ID = IValidationRuleList.EJB11_CMP_KEYCLASS;
	private static final Object[] DEPENDS_ON = new Object[]{IValidationRuleList.EJB11_CMP_BEANCLASS};
	private static final Map MESSAGE_IDS;
	
	static {
		MESSAGE_IDS = new HashMap();
		
		MESSAGE_IDS.put(CHKJ2001, new String[]{CHKJ2001+EXT});

		MESSAGE_IDS.put(CHKJ2019, new String[]{CHKJ2019+EXT});

		MESSAGE_IDS.put(CHKJ2020, new String[]{CHKJ2020+EXT});
		MESSAGE_IDS.put(CHKJ2021, new String[]{CHKJ2021+EXT});

		MESSAGE_IDS.put(CHKJ2205, new String[]{CHKJ2205+BEXT, CHKJ2205+MEXT});
		MESSAGE_IDS.put(CHKJ2206, new String[]{CHKJ2206+BEXT, CHKJ2206+MEXT}); // special case where the id is the same regardless of whether the method is inherited or not
		
//AValidateEJB method not used		MESSAGE_IDS.put(CHKJ2412, new String[]{CHKJ2412+BEXT, CHKJ2412+MEXT});
//AValidateEJB method not used		MESSAGE_IDS.put(CHKJ2413, new String[]{CHKJ2413+BEXT, CHKJ2413+MEXT});
//AValidateEJB method not used		MESSAGE_IDS.put(CHKJ2414, new String[]{CHKJ2414+BEXT, CHKJ2414+MEXT});

		MESSAGE_IDS.put(CHKJ2041, new String[]{CHKJ2041}); // special case. Shared by all types.
		MESSAGE_IDS.put(CHKJ2433, new String[]{CHKJ2433});
		MESSAGE_IDS.put(CHKJ2829, new String[]{CHKJ2829 + SPEC});
		MESSAGE_IDS.put(CHKJ2907, new String[]{CHKJ2907});
	}
	
	public void reset() {
		super.reset();
		_beanFieldNames.clear();
	}
	
	public final Map getMessageIds() {
		return MESSAGE_IDS;
	}
	
	public final Object[] getDependsOn() {
		return DEPENDS_ON;
	}
	
	public Object getTarget(Object parent, Object clazz) {
		if(parent == null) {
			return null;
		}
		
		ContainerManagedEntity cmp = (ContainerManagedEntity)parent;
		if(ValidationRuleUtility.isPrimitivePrimaryKey(cmp)) {
			return null; // do not validate a primitive primary key
		}
		
		return cmp.getPrimaryKey();
	}
	
	public final Object getId() {
		return ID;
	}

	/*
	 * 9.4.7.1 Primary key that maps to a single field in the entity bean class
	 *     The Bean Provider uses the primkey-field element of the deployment descriptor to specify the
	 *     container-managed field of the entity bean class that contains the primary key. The field's type must be
	 *     the primary key type.
	 *
	 * 9.4.7.2 Primary key that maps to multiple fields in the entity bean class
	 *     The primary key class must be public, and must have a public constructor with no parameters.
	 *     All fields in the primary key class must be declared as public.
	 *     The names of the fields in the primary key class must be a subset of the names of the container-managed
	 *     fields. (This allows the container to extract the primary key fields from an instance's container-managed
	 *     fields, and vice versa.)
	 */
	protected void buildFieldNameList(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz) {
		// Build up the list of field names to be used in the field validation.
		vc.terminateIfCancelled();

		ContainerManagedEntity cmp = (ContainerManagedEntity) bean;
		if (cmp == null) {
			// Let the class validation throw the exception
			return;
		}

		if (!ValidationRuleUtility.isPrimitivePrimaryKey(cmp)) {
			List attributes = cmp.getPersistentAttributes();
			CMPAttribute attribute = null;
			Iterator iterator = attributes.iterator();
			while (iterator.hasNext()) {
				attribute = (CMPAttribute) iterator.next();
				try {
					// These are different fields than the ones validated by this
					// valImpl class, so don't need to worry about duplicate reflection
					// warnings logged against the same object.
					ValidationRuleUtility.isValidType(attribute.getType());
					_beanFieldNames.add(attribute.getName());
				}
				catch (InvalidInputException e) {
					//TODO (Dan) Change to use the attribute directly and not the field.
					reflectionWarning(vc, bean, clazz , attribute.getField(), e);
				}
			}
		}
	}
	
	/**
	 * This method actually does the validation.
	 *
	 * 9.4.7.2 Primary key that maps to multiple fields in the entity bean class
	 *     The primary key class must be public, and must have a public constructor with no parameters.
	 *     All fields in the primary key class must be declared as public.
	 *     The names of the fields in the primary key class must be a subset of the names of the container-managed
	 *     fields. (This allows the container to extract the primary key fields from an instance's container-managed
	 *     fields, and vice versa.)
	 */
	public void primValidate(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Field field) throws InvalidInputException {
		// All fields in the primary key class must be declared as public.
		if (!ValidationRuleUtility.isPublic(field)) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2205, IEJBValidationContext.WARNING, bean, clazz, field, this);
			vc.addMessage(message);
		}

		// The names of the fields in the primary key class must be a subset of the names of the container-managed
		// fields. (This allows the container to extract the primary key fields from an instance's container-managed
		// fields, and vice versa.)
		ContainerManagedEntity cmp = (ContainerManagedEntity) bean;
		// Don't need to check if cmp is null, because this method is called only by validateFields(),
		// and validateFields() won't call this method if the bean is null.

		if (!_beanFieldNames.contains(field.getName())) {
			JavaClass ejbClass = cmp.getEjbClass();
			ValidationRuleUtility.isValidType(ejbClass);
			String[] msgParm = { cmp.getName(), cmp.getEjbClass().getName()};
			IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2206, IEJBValidationContext.WARNING, bean, clazz, field, msgParm, this);
			vc.addMessage(message);
		}
	}
	
	/**
	 * This method actually does the validation.
	 */
	public void primValidate(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method ejbMethod) throws InvalidInputException {
		// Can't invoke an abstract method
		// super.primValidate(ejbMethod);

		//Nothing to do.
	}
	
	/**
	 * Checks to see if @ejbMethod is one of the required methods.
	 */
	protected void primValidateExistence(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method ejbMethod) throws InvalidInputException {
		// Can't invoke an abstract method
		//super.validateExistence(ejbMethod);

		if (ejbMethod.isConstructor()) {
			// These booleans are used in the validateMethodExists() checks.
			hasAConstructor = true;
			if (ValidationRuleUtility.isPublic(ejbMethod) && (ejbMethod.listParametersWithoutReturn().length == 0)) {
				hasDefaultConstructor = true;
			}
		}
	}
	
	/**
	 * 9.4.7.2 Primary key that maps to multiple fields in the entity bean class
	 *     The primary key class must be public, and must have a public constructor with no parameters.
	 *     All fields in the primary key class must be declared as public.
	 *     The names of the fields in the primary key class must be a subset of the names of the container-managed
	 *     fields. (This allows the container to extract the primary key fields from an instance's container-managed
	 *     fields, and vice versa.)
	 */
	public void validateClass(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz) throws InvalidInputException {
		super.validateClass(vc, bean, clazz);

		vc.terminateIfCancelled();

		// The primary key class must be public
		if (!clazz.isPublic()) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb11Constants.CHKJ2020, IEJBValidationContext.ERROR, bean, clazz, new String[] { clazz.getQualifiedName()}, this);
			vc.addMessage(message);
		}

		buildFieldNameList(vc, bean, clazz);

		// Doesn't make sense to check for cmp key attributes if it's not a valid prim key field.
		// primary key must map to at least one field on the bean 
		ContainerManagedEntity cmp = (ContainerManagedEntity)bean;
		if(!ValidationRuleUtility.usesUnknownPrimaryKey(cmp)) {
			// primary key must map to at least one field on the bean 
			// But if it's an unknown key, there's no point checking java.lang.Object
			List primKeyFields = cmp.getKeyAttributes();
			if ((primKeyFields == null) || (primKeyFields.size() == 0)) {
				JavaClass primaryKey = cmp.getPrimaryKey(); // don't need to check MOFHelper.isValidType(primaryKey), because it's already been called in the validateDeploymentDescriptor method
				String beanName = (cmp.getName() == null) ? "null" : cmp.getName(); //$NON-NLS-1$
				IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2829, IEJBValidationContext.ERROR, bean, primaryKey, new String[] { primaryKey.getName(), beanName }, this);
				vc.addMessage(message);
			}
		}
	}
	
	/**
	 *  9.4.7.2 Primary key that maps to multiple fields in the entity bean class
	 *     The primary key class must be public, and must have a public constructor with no parameters.
	 */
	public void validateMethodExists(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz) throws InvalidInputException {
		super.validateMethodExists(vc, bean, clazz);

		// If the class has no constructors defined, Java inserts a public constructor with no arguments.
		// But if the class has at least one constructor defined, Java will not insert a constructor.
		if (!hasDefaultConstructor && hasAConstructor) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb11Constants.CHKJ2021, IEJBValidationContext.ERROR, bean, clazz, new String[] { clazz.getQualifiedName()}, this);
			vc.addMessage(message);
		}
	}
	/*
	 * @see IValidationRule#preValidate(IEJBValidationContext, Object, Object)
	 */
	public void preValidate(IEJBValidationContext vc, Object targetParent, Object target) throws ValidationCancelledException, ValidationException {
		super.preValidate(vc, targetParent, target);
		hasAConstructor = false;
		hasDefaultConstructor = false;
	}
}
