-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi all,

The javadocs in DefaultedMap is very inconsistent.  It speaks of factory
when a transformer is meant, it speaks of transformer when value is
meant and that sort of stuff.

Besides, it would be much cleaner to declare ‘value’ of type
Transformer, and create a transformer every time, except when one is
passed (the instanceof checks are wrong anyway), (I’d rename it to
transformer, too).

Even nicer would be to split up the constructor(s) into one that takes a
value, and one that takes a Transformer, no instanceof checks needed,
much cleaner code, generification is almost trivial :-)

I attached what I made of it, removing the generic markers gives a
perfectly legal 1.4 file.

Cheers, H.
- --
Hendrik Maryns
Herrenberger Straße 40
D-72070 Tübingen
+49707143783    (Deutschland fest)
+491753353494    (Deutschland Handy)
+32485470741    (België)

=================
www.lieverleven.be    (waarom zou ik hier toch naar verwijzen...)
http://aouw.org        De kunst van het stedelijke oorlogvoeren
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)

iD8DBQFErMQpBGFP0CTku6MRAnheAJ9CHhbUlXQ/xhdlQdFZLmAsSsi3rgCfdAYp
G2WkCErp39PI3mibC3Nch6E=
=YwE5
-----END PGP SIGNATURE-----
/*
 *  Copyright 2005 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.apache.commons.collections.map;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.collections.Factory;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.FactoryTransformer;

/**
 * Decorates another <code>Map</code> returning a default value if the map
 * does not contain the requested key.
 * <p>
 * When the [EMAIL PROTECTED] #get(Object)} method is called with a key that does not
 * exist in the map, this map will return the default value specified in
 * the constructor/factory. Only the get method is altered, so the
 * [EMAIL PROTECTED] Map#containsKey(Object)} can be used to determine if a key really
 * is in the map or not.
 * <p>
 * The defaulted value is not added to the map.
 * Compare this behaviour with [EMAIL PROTECTED] LazyMap}, which does add the value
 * to the map (via a Transformer).
 * <p>
 * For instance:
 * <pre>
 * Map map = new DefaultedMap("NULL");
 * Object obj = map.get("Surname");
 * // obj == "NULL"
 * </pre>
 * After the above code is executed the map is still empty.
 * <p>
 * <strong>Note that DefaultedMap is not synchronized and is not thread-safe.</strong>
 * If you wish to use this map from multiple threads concurrently, you must use
 * appropriate synchronization. The simplest approach is to wrap this map
 * using [EMAIL PROTECTED] java.util.Collections#synchronizedMap(Map)}. This class may throw 
 * exceptions when accessed by concurrent threads without synchronization.
 *
 * @since Commons Collections 3.2
 * @version $Revision: 1.7 $ $Date: 2005-11-21 22:52:57 +0000 (Mon, 21 Nov 2005) $
 * 
 * @author Stephen Colebourne
 * @author Rafael U.C. Afonso
 * @see LazyMap
 */
public class DefaultedMap<K,V>
        extends AbstractMapDecorator<K,V>
        implements Map<K,V>, Serializable {

    /** Serialization version */
    private static final long serialVersionUID = 19698628745827L;

    /** The transformer to use if the map does not contain a key */
    protected final Transformer<Object,V> transformer;

    //-----------------------------------------------------------------------
    /**
     * Factory method to create a defaulting map.
     * <p>
     * The value specified is returned when a missing key is found.
     * 
     * @param map  the map to decorate, must not be null
     * @param defaultValue  the default value to return when the key is not found
     * @throws IllegalArgumentException if map is null
     */
    @SuppressWarnings("unchecked")
    public static <K,V> Map<K,V> decorate(Map<K,V> map, V defaultValue) {
        if (defaultValue instanceof Transformer) {
            defaultValue = (V) ConstantTransformer.getInstance(defaultValue);
        }
        return new DefaultedMap<K,V>(map, defaultValue);
    }

    /**
     * Factory method to create a defaulting map.
     * <p>
     * The factory specified is called when a missing key is found.
     * The result will be returned as the result of the map get(key) method.
     * 
     * @param map  the map to decorate, must not be null
     * @param factory  the factory to use, must not be null
     * @throws IllegalArgumentException if map or factory is null
     */
    public static <K,V> Map<K,V> decorate(Map<K,V> map, Factory<V> factory) {
        if (factory == null) {
            throw new IllegalArgumentException("Factory must not be null");
        }
        return new DefaultedMap<K,V>(map, FactoryTransformer.getInstance(factory));
    }

    /**
     * Factory method to create a defaulting map.
     * <p>
     * The transformer specified is called when a missing key is found.
     * The key is passed to the transformer as the input, and the result
     * will be returned as the result of the map get(key) method.
     * 
     * @param map  the map to decorate, must not be null
     * @param transformer  the transformer to use, must not be null
     * @throws IllegalArgumentException if map or factory is null
     */
    public static <K,V> Map<K,V> decorate(Map<K,V> map, Transformer<Object,V> transformer) {
        if (transformer == null) {
           throw new IllegalArgumentException("Transformer must not be null");
       }
       return new DefaultedMap<K,V>(map, transformer);
    }

    //-----------------------------------------------------------------------
    /**
     * Constructs a new empty <code>DefaultedMap</code> that decorates
     * a <code>HashMap</code>.
     * <p>
     * The object passed in will be returned by the map whenever an
     * unknown key is requested.
     * 
     * @param defaultValue  the default value to return when the key is not found
     */
    public DefaultedMap(V defaultValue) {
        super(new HashMap<K,V>());
        this.transformer = ConstantTransformer.getInstance(defaultValue);
    }

    /**
     * Constructs a new empty <code>DefaultedMap</code> that decorates
     * a <code>HashMap</code>.
     * <p>
     * The object passed in will be returned by the map whenever an
     * unknown key is requested.
     * 
     * @param transformer  the transformer to use to create a value to return 
     *        when the key is not found
     */
    public DefaultedMap(Transformer<Object,V> transformer) {
        super(new HashMap<K,V>());
        this.transformer = transformer;
    }
    
    /**
     * Constructor that wraps (not copies).
     * 
     * @param map  the map to decorate, must not be null
     * @param value  the value to use
     * @throws IllegalArgumentException if map or value is null
     */
    protected DefaultedMap(Map<K,V> map, V value) {
        super(map);
        this.transformer = ConstantTransformer.getInstance(value);
    }

    /**
     * Constructor that wraps (not copies).
     * 
     * @param map  the map to decorate, must not be null
     * @param transformer  the transformer to use
     * @throws IllegalArgumentException if map or transformer is null
     */
    protected DefaultedMap(Map<K,V> map, Transformer<Object, V> transformer) {
        super(map);
        this.transformer = transformer;
    }

    //-----------------------------------------------------------------------
    /**
     * Write the map out using a custom routine.
     * 
     * @param out  the output stream
     * @throws IOException
     */
    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
        out.writeObject(map);
    }

    /**
     * Read the map in using a custom routine.
     * 
     * @param in  the input stream
     * @throws IOException
     * @throws ClassNotFoundException
     */
    @SuppressWarnings("unchecked")
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        map = (Map<K,V>) in.readObject();
    }

    //-----------------------------------------------------------------------
    @Override
    public V get(Object key) {
        // create value for key if key is not currently in the map
        if (map.containsKey(key) == false) {
            return transformer.transform(key);
        }
        return map.get(key);
    }

    // no need to wrap keySet, entrySet or values as they are views of
    // existing map entries - you can't do a map-style get on them.
}



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to