001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002-2006, Geotools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.util;
017:
018: // J2SE dependencies
019: import java.util.LinkedHashMap;
020:
021: // OpenGIS dependencies
022: import org.opengis.util.Cloneable;
023:
024: // Geotools dependencies
025: import org.geotools.resources.Utilities;
026: import org.geotools.resources.i18n.Errors;
027: import org.geotools.resources.i18n.ErrorKeys;
028:
029: /**
030: * Acts as a typed {@link java.util.Map} while we wait for Java 5.0.
031: *
032: * @since 2.1
033: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/metadata/src/main/java/org/geotools/util/CheckedHashMap.java $
034: * @version $Id: CheckedHashMap.java 22443 2006-10-27 20:47:22Z desruisseaux $
035: * @author Jody Garnett (Refractions Research)
036: * @author Martin Desruisseaux
037: *
038: * @todo Provides synchronization facility on arbitrary lock, for use with the metadata package.
039: * The lock would be the metadata that owns this collection. Be carefull to update the lock
040: * after a clone (this work may be done in {@code MetadataEntity.unmodifiable(Object)}).
041: */
042: public class CheckedHashMap extends LinkedHashMap implements Cloneable {
043: /**
044: * Serial version UID for compatibility with different versions.
045: */
046: private static final long serialVersionUID = -7777695267921872849L;
047:
048: /**
049: * The class type for keys.
050: */
051: private final Class keyType;
052:
053: /**
054: * The class type for values.
055: */
056: private final Class valueType;
057:
058: /**
059: * Constructs a map of the specified type.
060: *
061: * @param keyType The key type (should not be null).
062: * @param valueType The value type (should not be null).
063: */
064: public CheckedHashMap(final Class keyType, final Class valueType) {
065: this .keyType = keyType;
066: this .valueType = valueType;
067: ensureNonNull(keyType, "keyType");
068: ensureNonNull(valueType, "valueType");
069: }
070:
071: /**
072: * Ensure that the given argument is non-null.
073: */
074: private static void ensureNonNull(final Class type,
075: final String name) {
076: if (type == null) {
077: throw new NullPointerException(Errors.format(
078: ErrorKeys.NULL_ARGUMENT_$1, name));
079: }
080: }
081:
082: /**
083: * Checks the type of the specified object. The default implementation ensure
084: * that the object is assignable to the type specified at construction time.
085: *
086: * @param element the object to check, or {@code null}.
087: * @throws IllegalArgumentException if the specified element is not of the expected type.
088: */
089: private static void ensureValidType(final Object element,
090: final Class type) throws IllegalArgumentException {
091: if (element != null && !type.isInstance(element)) {
092: throw new IllegalArgumentException(Errors.format(
093: ErrorKeys.ILLEGAL_CLASS_$2, Utilities
094: .getShortClassName(element), Utilities
095: .getShortName(type)));
096: }
097: }
098:
099: /**
100: * Associates the specified value with the specified key in this map.
101: * If the map previously contained a mapping for this key, the old
102: * value is replaced.
103: *
104: * @param key key with which the specified value is to be associated.
105: * @param value value to be associated with the specified key.
106: * @return previous value associated with specified key, or {@code null}.
107: */
108: public Object put(final Object key, final Object value) {
109: ensureValidType(key, keyType);
110: ensureValidType(value, valueType);
111: return super.put(key, value);
112: }
113: }
|