Author: mbenson Date: Mon Mar 9 22:48:07 2009 New Revision: 751894 URL: http://svn.apache.org/viewvc?rev=751894&view=rev Log: add splitmap package whose original goal is to provide a more versatile TransformedMap implementation
Added: commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/ commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/AbstractIterableGetMapDecorator.java (with props) commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/SplitMapUtils.java (with props) commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/TransformedMap.java (with props) commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/package.html (with props) commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/ commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/TestAll.java (with props) commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/TestSplitMapUtils.java (with props) commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/TestTransformedMap.java (with props) Modified: commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/TestAllPackages.java Added: commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/AbstractIterableGetMapDecorator.java URL: http://svn.apache.org/viewvc/commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/AbstractIterableGetMapDecorator.java?rev=751894&view=auto ============================================================================== --- commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/AbstractIterableGetMapDecorator.java (added) +++ commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/AbstractIterableGetMapDecorator.java Mon Mar 9 22:48:07 2009 @@ -0,0 +1,161 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.splitmap; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.collections.Get; +import org.apache.commons.collections.IterableGet; +import org.apache.commons.collections.MapIterator; +import org.apache.commons.collections.map.EntrySetToMapIteratorAdapter; + +/** + * {...@link IterableGet} that uses a {...@link Map}<K, V> for the {...@link Get}<K, V> + * implementation. + * + * @since Commons Collections 5 + * @TODO fix version + * @version $Revision$ $Date$ + * + * @author Matt Benson + */ +public class AbstractIterableGetMapDecorator<K, V> implements IterableGet<K, V> { + /** The map to decorate */ + protected transient Map<K, V> map; + + /** + * Create a new AbstractSplitMapDecorator. + * @param decorated the Map to decorate + */ + public AbstractIterableGetMapDecorator(Map<K, V> decorated) { + this.map = decorated; + } + + /** + * Gets the map being decorated. + * + * @return the decorated map + */ + protected Map<K, V> decorated() { + return map; + } + + /** + * {...@inheritdoc} + */ + public void clear() { + decorated().clear(); + } + + /** + * {...@inheritdoc} + */ + public boolean containsKey(Object key) { + return decorated().containsKey(key); + } + + /** + * {...@inheritdoc} + */ + public boolean containsValue(Object value) { + return decorated().containsValue(value); + } + + /** + * {...@inheritdoc} + */ + public Set<Map.Entry<K, V>> entrySet() { + return decorated().entrySet(); + } + + /** + * {...@inheritdoc} + */ + public V get(Object key) { + return decorated().get(key); + } + + /** + * {...@inheritdoc} + */ + public V remove(Object key) { + return decorated().remove(key); + } + + /** + * {...@inheritdoc} + */ + public boolean isEmpty() { + return decorated().isEmpty(); + } + + /** + * {...@inheritdoc} + */ + public Set<K> keySet() { + return decorated().keySet(); + } + + /** + * {...@inheritdoc} + */ + public int size() { + return decorated().size(); + } + + /** + * {...@inheritdoc} + */ + public Collection<V> values() { + return decorated().values(); + } + + /** + * Get a MapIterator over this Get. + * @return MapIterator<K, V> + */ + public MapIterator<K, V> mapIterator() { + return new EntrySetToMapIteratorAdapter<K, V>(entrySet()); + } + + /** + * {...@inheritdoc} + */ + public boolean equals(Object object) { + if (object == this) { + return true; + } + return decorated().equals(object); + } + + /** + * {...@inheritdoc} + */ + public int hashCode() { + return decorated().hashCode(); + } + + /** + * {...@inheritdoc} + */ + public String toString() { + return decorated().toString(); + } + +} Propchange: commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/AbstractIterableGetMapDecorator.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/AbstractIterableGetMapDecorator.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/SplitMapUtils.java URL: http://svn.apache.org/viewvc/commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/SplitMapUtils.java?rev=751894&view=auto ============================================================================== --- commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/SplitMapUtils.java (added) +++ commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/SplitMapUtils.java Mon Mar 9 22:48:07 2009 @@ -0,0 +1,233 @@ +package org.apache.commons.collections.splitmap; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.collections.Get; +import org.apache.commons.collections.IterableGet; +import org.apache.commons.collections.IterableMap; +import org.apache.commons.collections.MapIterator; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.collections.Put; +import org.apache.commons.collections.Unmodifiable; +import org.apache.commons.collections.collection.UnmodifiableCollection; +import org.apache.commons.collections.iterators.UnmodifiableMapIterator; +import org.apache.commons.collections.map.EntrySetToMapIteratorAdapter; +import org.apache.commons.collections.map.UnmodifiableEntrySet; +import org.apache.commons.collections.set.UnmodifiableSet; + +/** + * Utilities for working with "split maps:" objects that implement {...@link Put} + * and/or {...@link Get} but not {...@link Map}. + * + * @since Commons Collections 5 + * @TODO fix version + * @version $Revision$ $Date$ + * @see Get + * @see Put + * @author Matt Benson + */ +public class SplitMapUtils { + + /** + * <code>SplitMapUtils</code> should not normally be instantiated. + */ + public SplitMapUtils() { + } + + private static class WrappedGet<K, V> implements IterableMap<K, V>, Unmodifiable { + private Get<K, V> get; + + private WrappedGet(Get<K, V> get) { + this.get = get; + } + + public void clear() { + throw new UnsupportedOperationException(); + } + + public boolean containsKey(Object key) { + return get.containsKey(key); + } + + public boolean containsValue(Object value) { + return get.containsValue(value); + } + + public Set<java.util.Map.Entry<K, V>> entrySet() { + return UnmodifiableEntrySet.decorate(get.entrySet()); + } + + @Override + public boolean equals(Object arg0) { + if (arg0 == this) { + return true; + } + return arg0 instanceof WrappedGet && ((WrappedGet<?, ?>) arg0).get.equals(this.get); + } + + public V get(Object key) { + return get.get(key); + } + + @Override + public int hashCode() { + return ("WrappedGet".hashCode() << 4) | get.hashCode(); + } + + public boolean isEmpty() { + return get.isEmpty(); + } + + public Set<K> keySet() { + return UnmodifiableSet.decorate(get.keySet()); + } + + public V put(K key, V value) { + throw new UnsupportedOperationException(); + }; + + public void putAll(Map<? extends K, ? extends V> t) { + throw new UnsupportedOperationException(); + } + + public V remove(Object key) { + return get.remove(key); + } + + public int size() { + return get.size(); + } + + public Collection<V> values() { + return UnmodifiableCollection.decorate(get.values()); + } + + public MapIterator<K, V> mapIterator() { + MapIterator<K, V> it; + if (get instanceof IterableGet) { + it = ((IterableGet<K, V>) get).mapIterator(); + } else { + it = new EntrySetToMapIteratorAdapter<K, V>(get.entrySet()); + } + return UnmodifiableMapIterator.decorate(it); + } + } + + private static class WrappedPut<K, V> implements Map<K, V>, Put<K, V> { + private Put<K, V> put; + + private WrappedPut(Put<K, V> put) { + this.put = put; + } + + public void clear() { + put.clear(); + } + + public boolean containsKey(Object key) { + throw new UnsupportedOperationException(); + } + + public boolean containsValue(Object value) { + throw new UnsupportedOperationException(); + } + + public Set<java.util.Map.Entry<K, V>> entrySet() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + return obj instanceof WrappedPut && ((WrappedPut<?, ?>) obj).put.equals(this.put); + } + + public V get(Object key) { + throw new UnsupportedOperationException(); + } + + @Override + public int hashCode() { + return ("WrappedPut".hashCode() << 4) | put.hashCode(); + } + + public boolean isEmpty() { + throw new UnsupportedOperationException(); + } + + public Set<K> keySet() { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unchecked") + public V put(K key, V value) { + return (V) put.put(key, value); + }; + + public void putAll(Map<? extends K, ? extends V> t) { + put.putAll(t); + } + + public V remove(Object key) { + throw new UnsupportedOperationException(); + } + + public int size() { + throw new UnsupportedOperationException(); + } + + public Collection<V> values() { + throw new UnsupportedOperationException(); + } + } + + /** + * Get the specified {...@link Get} as an instance of {...@link IterableMap}. + * If <code>get</code> implements {...@link IterableMap} directly, no conversion will take place. + * If <code>get</code> implements {...@link Map} but not {...@link IterableMap} it will be decorated. + * Otherwise an {...@link Unmodifiable} {...@link IterableMap} will be returned. + * @param <K> + * @param <V> + * @param get to wrap, must not be null + * @return {...@link IterableMap} + */ + @SuppressWarnings("unchecked") + public static <K, V> IterableMap<K, V> readableMap(Get<K, V> get) { + if (get == null) { + throw new IllegalArgumentException("Get must not be null"); + } + if (get instanceof Map) { + return get instanceof IterableMap ? ((IterableMap<K, V>) get) : MapUtils + .iterableMap((Map<K, V>) get); + } + return new WrappedGet<K, V>(get); + } + + /** + * Get the specified {...@link Put} as an instanceof {...@link Map}. + * If <code>put</code> implements {...@link Map} directly, no conversion will take place. + * Otherwise a <em>write-only</em> {...@link Map} will be returned. On such a {...@link Map} + * it is recommended that the result of #put(K, V) be discarded as it likely will not + * match <code>V</code> at runtime. + * + * @param <K> + * @param <V> + * @param put to wrap, must not be null + * @return {...@link Map} + */ + @SuppressWarnings("unchecked") + public static <K, V> Map<K, V> writableMap(Put<K, V> put) { + if (put == null) { + throw new IllegalArgumentException("Put must not be null"); + } + if (put instanceof Map) { + return (Map<K, V>) put; + } + return new WrappedPut<K, V>(put); + } + +} Propchange: commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/SplitMapUtils.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/SplitMapUtils.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/TransformedMap.java URL: http://svn.apache.org/viewvc/commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/TransformedMap.java?rev=751894&view=auto ============================================================================== --- commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/TransformedMap.java (added) +++ commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/TransformedMap.java Mon Mar 9 22:48:07 2009 @@ -0,0 +1,208 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.splitmap; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Map; + +import org.apache.commons.collections.Put; +import org.apache.commons.collections.Transformer; +import org.apache.commons.collections.map.LinkedMap; + +/** + * Decorates another <code>Map</code> to transform objects that are added. + * <p> + * The Map put methods and Map.Entry setValue method are affected by this class. + * Thus objects must be removed or searched for using their transformed form. + * For example, if the transformation converts Strings to Integers, you must use + * the Integer form to remove objects. + * <p> + * <strong>Note that TransformedMap 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 {...@link java.util.Collections#synchronizedMap(Map)}. + * This class may throw exceptions when accessed by concurrent threads without + * synchronization. + * + * @since Commons Collections 5 + * @TODO fix version + * @version $Revision$ $Date$ + * + * @author Stephen Colebourne + * @author Matt Benson + */ +public class TransformedMap<J, K, U, V> extends AbstractIterableGetMapDecorator<K, V> implements + Put<J, U>, Serializable { + + /** Serialization version */ + private static final long serialVersionUID = 5966875321133456994L; + + /** The decorated map */ + private Map<K, V> decorated; + /** The transformer to use for the key */ + private final Transformer<? super J, ? extends K> keyTransformer; + /** The transformer to use for the value */ + private final Transformer<? super U, ? extends V> valueTransformer; + + /** + * Factory method to create a transforming map. + * <p> + * If there are any elements already in the map being decorated, they are + * NOT transformed. + * + * @param map the map to decorate, must not be null + * @param keyTransformer the transformer to use for key conversion, null + * means no transformation + * @param valueTransformer the transformer to use for value conversion, null + * means no transformation + * @throws IllegalArgumentException if map is null + */ + public static <J, K, U, V> TransformedMap<J, K, U, V> decorate(Map<K, V> map, + Transformer<? super J, ? extends K> keyTransformer, + Transformer<? super U, ? extends V> valueTransformer) { + return new TransformedMap<J, K, U, V>(map, keyTransformer, valueTransformer); + } + + //----------------------------------------------------------------------- + /** + * Constructor that wraps (not copies). + * <p> + * If there are any elements already in the collection being decorated, they + * are NOT transformed. + * + * @param map the map to decorate, must not be null + * @param keyTransformer the transformer to use for key conversion, null + * means no conversion + * @param valueTransformer the transformer to use for value conversion, null + * means no conversion + * @throws IllegalArgumentException if map is null + */ + protected TransformedMap(Map<K, V> map, Transformer<? super J, ? extends K> keyTransformer, + Transformer<? super U, ? extends V> valueTransformer) { + super(map); + if (keyTransformer == null) { + throw new IllegalArgumentException("keyTransformer cannot be null"); + } + this.keyTransformer = keyTransformer; + if (valueTransformer == null) { + throw new IllegalArgumentException("valueTransformer cannot be null"); + } + this.valueTransformer = valueTransformer; + } + + //----------------------------------------------------------------------- + /** + * 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(decorated); + } + + /** + * Read the map in using a custom routine. + * + * @param in the input stream + * @throws IOException + * @throws ClassNotFoundException + * @since Commons Collections 3.1 + */ + @SuppressWarnings("unchecked") + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + decorated = (Map) in.readObject(); + } + + //----------------------------------------------------------------------- + /** + * Transforms a key. + * <p> + * The transformer itself may throw an exception if necessary. + * + * @param object the object to transform + * @throws the transformed object + */ + protected K transformKey(J object) { + return keyTransformer.transform(object); + } + + /** + * Transforms a value. + * <p> + * The transformer itself may throw an exception if necessary. + * + * @param object the object to transform + * @throws the transformed object + */ + protected V transformValue(U object) { + return valueTransformer.transform(object); + } + + /** + * Transforms a map. + * <p> + * The transformer itself may throw an exception if necessary. + * + * @param map the map to transform + * @throws the transformed object + */ + @SuppressWarnings("unchecked") + protected Map<K, V> transformMap(Map<? extends J, ? extends U> map) { + if (map.isEmpty()) { + return (Map<K, V>) map; + } + Map<K, V> result = new LinkedMap<K, V>(map.size()); + + for (Map.Entry<? extends J, ? extends U> entry : map.entrySet()) { + result.put((K) transformKey(entry.getKey()), transformValue(entry.getValue())); + } + return result; + } + + /** + * Override to transform the value when using <code>setValue</code>. + * + * @param value the value to transform + * @return the transformed value + */ + protected V checkSetValue(U value) { + return valueTransformer.transform(value); + } + + //----------------------------------------------------------------------- + /** + * {...@inheritdoc} + */ + public V put(J key, U value) { + return decorated().put(transformKey(key), transformValue(value)); + } + + /** + * {...@inheritdoc} + */ + public void putAll(Map<? extends J, ? extends U> mapToCopy) { + decorated().putAll(transformMap(mapToCopy)); + } + + +} Propchange: commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/TransformedMap.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/TransformedMap.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/package.html URL: http://svn.apache.org/viewvc/commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/package.html?rev=751894&view=auto ============================================================================== --- commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/package.html (added) +++ commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/package.html Mon Mar 9 22:48:07 2009 @@ -0,0 +1,39 @@ +<!-- $Id$ --> + <!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You 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. + --> +<BODY> +<p>The "split map" concept is that of an object that implements +the {...@link org.apache.commons.collections.Put Put} and +...@link org.apache.commons.collections.Get Get} interfaces, +with <i>differing</i> generic types. This is like a pre-generics +...@link java.util.Map Map} whose input key/value constraints are +different than its output key/value constraints. While it would +be possible to declare a "split map" with matching input/output +key/value constraints, this would be a {...@link java.util.Map Map} +and would therefore make little sense (any Commons Collections +...@link java.util.Map Map} implementation will also implement +...@link org.apache.commons.collections.Put Put} and +...@link org.apache.commons.collections.Get Get} with matching +generic parameters). + +<p> +The following decorators are provided: +<ul> +<li>Transformed - transforms each element added +</ul> +</pre> +</BODY> Propchange: commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/splitmap/package.html ------------------------------------------------------------------------------ svn:eol-style = native Modified: commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/TestAllPackages.java URL: http://svn.apache.org/viewvc/commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/TestAllPackages.java?rev=751894&r1=751893&r2=751894&view=diff ============================================================================== --- commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/TestAllPackages.java (original) +++ commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/TestAllPackages.java Mon Mar 9 22:48:07 2009 @@ -41,7 +41,8 @@ org.apache.commons.collections.keyvalue.TestAll.class, org.apache.commons.collections.list.TestAll.class, org.apache.commons.collections.map.TestAll.class, - org.apache.commons.collections.set.TestAll.class + org.apache.commons.collections.set.TestAll.class, + org.apache.commons.collections.splitmap.TestAll.class }) public class TestAllPackages { } Added: commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/TestAll.java URL: http://svn.apache.org/viewvc/commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/TestAll.java?rev=751894&view=auto ============================================================================== --- commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/TestAll.java (added) +++ commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/TestAll.java Mon Mar 9 22:48:07 2009 @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.splitmap; + +import junit.framework.TestCase; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +/** + * Entry point for tests. + * + * @since Commons Collections 5 + * @TODO fix version + * @version $Revision$ $Date$ + * + * @author Stephen Colebourne + * @author Stephen Kestle + * @author Matt Benson + */ +...@runwith(Suite.class) +...@suiteclasses({ + TestSplitMapUtils.class, + TestTransformedMap.class +}) +public class TestAll extends TestCase { +} Propchange: commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/TestAll.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/TestAll.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/TestSplitMapUtils.java URL: http://svn.apache.org/viewvc/commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/TestSplitMapUtils.java?rev=751894&view=auto ============================================================================== --- commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/TestSplitMapUtils.java (added) +++ commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/TestSplitMapUtils.java Mon Mar 9 22:48:07 2009 @@ -0,0 +1,241 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.splitmap; + +import java.util.HashMap; +import java.util.Map; + +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.apache.commons.collections.BulkTest; +import org.apache.commons.collections.IterableMap; +import org.apache.commons.collections.MapIterator; +import org.apache.commons.collections.Put; +import org.apache.commons.collections.Transformer; +import org.apache.commons.collections.Unmodifiable; +import org.apache.commons.collections.functors.NOPTransformer; +import org.apache.commons.collections.map.HashedMap; + +/** + * Tests for {...@link TransformedMap} + * + * @since Commons Collections 5 + * @TODO fix version + * @version $Revision$ $Date$ + * + * @author Stephen Colebourne + * @author Matt Benson + */ +public class TestSplitMapUtils extends BulkTest { + private Map<String, Integer> backingMap; + private TransformedMap<String, String, String, Integer> transformedMap; + + private Transformer<String, Integer> stringToInt = new Transformer<String, Integer>() { + public Integer transform(String input) { + return Integer.valueOf(input); + } + }; + + public TestSplitMapUtils(String testName) { + super(testName); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + backingMap = new HashMap<String, Integer>(); + transformedMap = TransformedMap.decorate(backingMap, NOPTransformer.<String> getInstance(), + stringToInt); + for (int i = 0; i < 10; i++) { + transformedMap.put(String.valueOf(i), String.valueOf(i)); + } + } + + public static Test suite() { + return new TestSuite(TestSplitMapUtils.class); + } + + public static void main(String args[]) { + String[] testCaseName = { TestSplitMapUtils.class.getName() }; + junit.textui.TestRunner.main(testCaseName); + } + + // ----------------------------------------------------------------------- + + public void testReadableMap() { + final IterableMap<String, Integer> map = SplitMapUtils.readableMap(transformedMap); + + // basic + for (int i = 0; i < 10; i++) { + assertFalse(map.containsValue(String.valueOf(i))); + assertEquals(i, map.get(String.valueOf(i)).intValue()); + } + + // mapIterator + MapIterator<String, Integer> it = map.mapIterator(); + while (it.hasNext()) { + String k = it.next(); + assertEquals(k, it.getKey()); + assertEquals(Integer.valueOf(k), it.getValue()); + } + + // unmodifiable + assertTrue(map instanceof Unmodifiable); + + // check individual operations + int sz = map.size(); + + attemptPutOperation(new Runnable() { + public void run() { + map.clear(); + } + }); + + assertEquals(sz, map.size()); + + attemptPutOperation(new Runnable() { + public void run() { + map.put("foo", 100); + } + }); + + final HashMap<String, Integer> m = new HashMap<String, Integer>(); + m.put("foo", 100); + m.put("bar", 200); + m.put("baz", 300); + attemptPutOperation(new Runnable() { + public void run() { + map.putAll(m); + } + }); + + // equals, hashcode + IterableMap<String, Integer> other = SplitMapUtils.readableMap(transformedMap); + assertEquals(other, map); + assertEquals(other.hashCode(), map.hashCode()); + + // remove + for (int i = 0; i < 10; i++) { + assertEquals(i, map.remove(String.valueOf(i)).intValue()); + assertEquals(--sz, map.size()); + } + assertTrue(map.isEmpty()); + assertSame(map, SplitMapUtils.readableMap(map)); + } + + public void testAlreadyReadableMap() { + HashedMap<String, Integer> hashedMap = new HashedMap<String, Integer>(); + assertSame(hashedMap, SplitMapUtils.readableMap(hashedMap)); + } + + @SuppressWarnings("unchecked") + public void testWritableMap() { + final Map<String, String> map = SplitMapUtils.writableMap(transformedMap); + attemptGetOperation(new Runnable() { + public void run() { + map.get(null); + } + }); + attemptGetOperation(new Runnable() { + public void run() { + map.entrySet(); + } + }); + attemptGetOperation(new Runnable() { + public void run() { + map.keySet(); + } + }); + attemptGetOperation(new Runnable() { + public void run() { + map.values(); + } + }); + attemptGetOperation(new Runnable() { + public void run() { + map.size(); + } + }); + attemptGetOperation(new Runnable() { + public void run() { + map.isEmpty(); + } + }); + attemptGetOperation(new Runnable() { + public void run() { + map.containsKey(null); + } + }); + attemptGetOperation(new Runnable() { + public void run() { + map.containsValue(null); + } + }); + attemptGetOperation(new Runnable() { + public void run() { + map.remove(null); + } + }); + + // equals, hashcode + Map<String, String> other = SplitMapUtils.writableMap(transformedMap); + assertEquals(other, map); + assertEquals(other.hashCode(), map.hashCode()); + + // put + int sz = backingMap.size(); + assertFalse(backingMap.containsKey("foo")); + map.put("new", "66"); + assertEquals(++sz, backingMap.size()); + + // putall + Map<String, String> more = new HashMap<String, String>(); + more.put("foo", "77"); + more.put("bar", "88"); + more.put("baz", "99"); + map.putAll(more); + assertEquals(sz + more.size(), backingMap.size()); + + // clear + map.clear(); + assertTrue(backingMap.isEmpty()); + assertSame(map, SplitMapUtils.writableMap((Put<String, String>) map)); + } + + public void testAlreadyWritableMap() { + HashedMap<String, String> hashedMap = new HashedMap<String, String>(); + assertSame(hashedMap, SplitMapUtils.writableMap(hashedMap)); + } + + private void attemptGetOperation(Runnable r) { + attemptMapOperation("Put exposed as writable Map must not allow Get operations", r); + } + + private void attemptPutOperation(Runnable r) { + attemptMapOperation("Get exposed as writable Map must not allow Put operations", r); + } + + private void attemptMapOperation(String s, Runnable r) { + try { + r.run(); + fail(s); + } catch (UnsupportedOperationException e) { + } + } + +} Propchange: commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/TestSplitMapUtils.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/TestSplitMapUtils.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/TestTransformedMap.java URL: http://svn.apache.org/viewvc/commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/TestTransformedMap.java?rev=751894&view=auto ============================================================================== --- commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/TestTransformedMap.java (added) +++ commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/TestTransformedMap.java Mon Mar 9 22:48:07 2009 @@ -0,0 +1,134 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.splitmap; + +import java.math.BigInteger; +import java.util.HashMap; + +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.apache.commons.collections.BulkTest; +import org.apache.commons.collections.MapIterator; +import org.apache.commons.collections.Transformer; +import org.apache.commons.collections.functors.NOPTransformer; + +/** + * Tests for {...@link TransformedMap} + * + * @since Commons Collections 5 + * @TODO fix version, add Serialization tests + * @version $Revision$ $Date$ + * + * @author Stephen Colebourne + * @author Matt Benson + */ +public class TestTransformedMap extends BulkTest { + + private Transformer<Integer, String> intToString = new Transformer<Integer, String>() { + public String transform(Integer input) { + return String.valueOf(input); + }; + }; + + private Transformer<Object, Class<?>> objectToClass = new Transformer<Object, Class<?>>() { + public java.lang.Class<?> transform(Object input) { + return input == null ? null : input.getClass(); + } + }; + + private Transformer<String, Integer> stringToInt = new Transformer<String, Integer>() { + public Integer transform(String input) { + return Integer.valueOf(input); + } + }; + + public TestTransformedMap(String testName) { + super(testName); + } + + public static Test suite() { + return new TestSuite(TestTransformedMap.class); + } + + public static void main(String args[]) { + String[] testCaseName = { TestTransformedMap.class.getName() }; + junit.textui.TestRunner.main(testCaseName); + } + + // ----------------------------------------------------------------------- + @SuppressWarnings("unchecked") + public void testTransformedMap() { + TransformedMap<Integer, String, Object, Class<?>> map = TransformedMap.decorate( + new HashMap<String, Class<?>>(), intToString, objectToClass); + + Integer[] k = new Integer[] { 0, 1, 2, 3, 4, 5, 6 }; + Object[] v = new Object[] { "", new Object(), new HashMap(), 0, BigInteger.TEN, null, + new Object[0] }; + + assertEquals(0, map.size()); + for (int i = 0; i < k.length; i++) { + map.put(k[i], v[i]); + assertEquals(i + 1, map.size()); + assertTrue(map.containsKey(intToString.transform(k[i]))); + assertFalse(map.containsKey(k[i])); + assertTrue(map.containsValue(objectToClass.transform(v[i]))); + assertTrue(objectToClass.transform(v[i]) != v[i] ^ map.containsValue(v[i])); + assertEquals(objectToClass.transform(v[i]), map.get(intToString.transform(k[i]))); + } + + int sz = map.size(); + assertEquals(null, map.remove(k[0])); + assertEquals(sz, map.size()); + assertEquals(objectToClass.transform(v[0]), map.remove(intToString.transform(k[0]))); + assertEquals(--sz, map.size()); + + TransformedMap<String, String, String, Integer> map2 = TransformedMap.decorate( + new HashMap<String, Integer>(), NOPTransformer.<String> getInstance(), stringToInt); + assertEquals(0, map2.size()); + for (int i = 0; i < 6; i++) { + map2.put(String.valueOf(i), String.valueOf(i)); + assertEquals(i + 1, map2.size()); + assertTrue(map2.containsValue(i)); + assertFalse(map2.containsValue(String.valueOf(i))); + assertTrue(map2.containsKey(String.valueOf(i))); + assertEquals(i, map2.get(String.valueOf(i)).intValue()); + } + + int sz2 = map2.size(); + assertEquals(Integer.valueOf(0), map2.remove("0")); + assertEquals(--sz2, map2.size()); + } + + // ----------------------------------------------------------------------- + + public void testMapIterator() { + TransformedMap<String, String, String, Integer> map = TransformedMap.decorate( + new HashMap<String, Integer>(), NOPTransformer.<String> getInstance(), stringToInt); + assertEquals(0, map.size()); + for (int i = 0; i < 6; i++) { + map.put(String.valueOf(i), String.valueOf(i)); + } + + for (MapIterator<String, Integer> it = map.mapIterator(); it.hasNext();) { + String k = it.next(); + assertEquals(k, it.getKey()); + assertEquals(map.get(k), it.getValue()); + } + } + +} Propchange: commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/TestTransformedMap.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/splitmap/TestTransformedMap.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL