FileDocCategorySizeDatePackage
MapConstraint.javaAPI DocExample4124Sun Dec 14 22:47:38 GMT 2003oreilly.hcj.datamodeling.constraints

MapConstraint.java

/*
 *     file: MapConstraint.java
 *  package: oreilly.hcj.datamodeling.constraints
 *
 * This software is granted under the terms of the Common Public License,
 * CPL, which may be found at the following URL:
 * http://www-124.ibm.com/developerworks/oss/CPLv1.0.htm
 *
 * Copyright(c) 2003-2005 by the authors indicated in the @author tags.
 * All Rights are Reserved by the various authors.
 *
########## DO NOT EDIT ABOVE THIS LINE ########## */

package oreilly.hcj.datamodeling.constraints;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**  
 * Models a constraint on Map objects.
 * 
 * <p>
 * Objects of this class are immutable.
 * </p>
 *
 * @author <a href="mailto:worderisor@yahoo.com">Robert Simmons jr.</a>
 * @version $Revision: 1.1 $
 */
public class MapConstraint extends ObjectConstraint {
	/** Holds value of property keyType. */
	private Class keyType;

	/** Holds value of property valueClass. */
	private Class valueType;

	/** Holds value of property valueNullable. */
	private boolean valueNullable;

	/** 
	 * Creates a new instance of MapConstraint.
	 *
	 * @param name Contains the name of the constraint.
	 * @param optional Indicates if the property is optional.
	 * @param dataType The data type of the object being constrained.
	 * @param keyType Type to use for keys; null if it doesnt matter.
	 * @param valueType Type to use for values; null if it doesnt matter.
	 * @param valueNullable True if a value can be null for a key, otherwise false.
	 *
	 * @throws IllegalArgumentException If dataType isn't a subclass of Map.
	 *
	 * @see mirror.datamodel.constraints.Constraint
	 */
	public MapConstraint(final String name, final boolean optional, final Class dataType,
	                     final Class keyType, final Class valueType,
	                     final boolean valueNullable) {
		super(name, optional, dataType);

		if (!Map.class.isAssignableFrom(dataType)) {
			throw new IllegalArgumentException("The dataType must be a Map");  //$NON-NLS-1$
		}

		this.keyType = keyType;
		this.valueType = valueType;
		this.valueNullable = valueNullable;
	}

	/** 
	 * Getter for property keyType.
	 *
	 * @return Value of property keyType.
	 */
	public Class getKeyType() {
		return this.keyType;
	}

	/** 
	 * Getter for property valueNullable.
	 *
	 * @return Value of property valueNullable.
	 */
	public boolean isValueNullable() {
		return this.valueNullable;
	}

	/** 
	 * Getter for property valueClass.
	 *
	 * @return Value of property valueClass.
	 */
	public Class getValueType() {
		return this.valueType;
	}

	/** 
	 * Validate the given object against the constraint.
	 *
	 * @param obj The object to validate.
	 *
	 * @throws ConstraintException If the constraint is violated.
	 */
	public void validate(final Object obj) {
		if (obj == null) {
			throw new ConstraintException(ConstraintExceptionType.NULL_NOT_ALLOWED);
		}

		if (!getDataType()
		         .isAssignableFrom(obj.getClass())) {
			throw new ConstraintException(ConstraintExceptionType.INVALID_DATA_TYPE);
		}

		Map tgtMap = (Map)obj;

		if (tgtMap.isEmpty()) {
			if (!isOptional()) {
				throw new ConstraintException(ConstraintExceptionType.MAP_CANNOT_BE_EMPTY);
			}
		}

		Set keys = tgtMap.keySet();
		Iterator iter = keys.iterator();
		Object value = null;
		Object key = null;

		while (iter.hasNext()) {
			key = iter.next();

			if (keyType != null) {
				if (!(key.getClass().equals(keyType))) {
					throw new ConstraintException(ConstraintExceptionType.INVALID_COLLECTION_MEMBER);
				}
			}

			value = tgtMap.get(key);

			if (valueType != null) {
				if (value == null) {
					if (!valueNullable) {
						throw new ConstraintException(ConstraintExceptionType.MAP_CANNOT_HAVE_NULL_VALUE);
					}
				} else {
					if (!(value.getClass().equals(valueType))) {
						throw new ConstraintException(ConstraintExceptionType.MAP_CONTAINS_INVALID_VALUE);
					}
				}
			}
		}
	}
}

/* ########## End of File ########## */