You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ch...@apache.org on 2017/07/11 17:55:40 UTC
[55/77] [abbrv] commons-collections git commit: add splitmap package
whose original goal is to provide a more versatile TransformedMap
implementation
add splitmap package whose original goal is to provide a more versatile TransformedMap implementation
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/collections/branches/collections_jdk5_branch@751894 13f79535-47bb-0310-9956-ffa450edef68
Project: http://git-wip-us.apache.org/repos/asf/commons-collections/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-collections/commit/87ac9390
Tree: http://git-wip-us.apache.org/repos/asf/commons-collections/tree/87ac9390
Diff: http://git-wip-us.apache.org/repos/asf/commons-collections/diff/87ac9390
Branch: refs/heads/collections_jdk5_branch
Commit: 87ac93908a02d75dab464f400b9d3887d3c0e04b
Parents: 86b30a0
Author: Matthew Jason Benson <mb...@apache.org>
Authored: Mon Mar 9 22:48:07 2009 +0000
Committer: Matthew Jason Benson <mb...@apache.org>
Committed: Mon Mar 9 22:48:07 2009 +0000
----------------------------------------------------------------------
.../AbstractIterableGetMapDecorator.java | 161 +++++++++++++
.../collections/splitmap/SplitMapUtils.java | 233 ++++++++++++++++++
.../collections/splitmap/TransformedMap.java | 208 ++++++++++++++++
.../commons/collections/splitmap/package.html | 39 +++
.../commons/collections/TestAllPackages.java | 3 +-
.../commons/collections/splitmap/TestAll.java | 42 ++++
.../collections/splitmap/TestSplitMapUtils.java | 241 +++++++++++++++++++
.../splitmap/TestTransformedMap.java | 134 +++++++++++
8 files changed, 1060 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/commons-collections/blob/87ac9390/src/java/org/apache/commons/collections/splitmap/AbstractIterableGetMapDecorator.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/commons/collections/splitmap/AbstractIterableGetMapDecorator.java b/src/java/org/apache/commons/collections/splitmap/AbstractIterableGetMapDecorator.java
new file mode 100644
index 0000000..d11e4c7
--- /dev/null
+++ b/src/java/org/apache/commons/collections/splitmap/AbstractIterableGetMapDecorator.java
@@ -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();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/commons-collections/blob/87ac9390/src/java/org/apache/commons/collections/splitmap/SplitMapUtils.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/commons/collections/splitmap/SplitMapUtils.java b/src/java/org/apache/commons/collections/splitmap/SplitMapUtils.java
new file mode 100644
index 0000000..f018dbf
--- /dev/null
+++ b/src/java/org/apache/commons/collections/splitmap/SplitMapUtils.java
@@ -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);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/commons-collections/blob/87ac9390/src/java/org/apache/commons/collections/splitmap/TransformedMap.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/commons/collections/splitmap/TransformedMap.java b/src/java/org/apache/commons/collections/splitmap/TransformedMap.java
new file mode 100644
index 0000000..4ef627f
--- /dev/null
+++ b/src/java/org/apache/commons/collections/splitmap/TransformedMap.java
@@ -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));
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/commons-collections/blob/87ac9390/src/java/org/apache/commons/collections/splitmap/package.html
----------------------------------------------------------------------
diff --git a/src/java/org/apache/commons/collections/splitmap/package.html b/src/java/org/apache/commons/collections/splitmap/package.html
new file mode 100644
index 0000000..464ae43
--- /dev/null
+++ b/src/java/org/apache/commons/collections/splitmap/package.html
@@ -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>
http://git-wip-us.apache.org/repos/asf/commons-collections/blob/87ac9390/src/test/org/apache/commons/collections/TestAllPackages.java
----------------------------------------------------------------------
diff --git a/src/test/org/apache/commons/collections/TestAllPackages.java b/src/test/org/apache/commons/collections/TestAllPackages.java
index 36a56f5..a67ca5a 100644
--- a/src/test/org/apache/commons/collections/TestAllPackages.java
+++ b/src/test/org/apache/commons/collections/TestAllPackages.java
@@ -41,7 +41,8 @@ import org.junit.runners.Suite.SuiteClasses;
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 {
}
http://git-wip-us.apache.org/repos/asf/commons-collections/blob/87ac9390/src/test/org/apache/commons/collections/splitmap/TestAll.java
----------------------------------------------------------------------
diff --git a/src/test/org/apache/commons/collections/splitmap/TestAll.java b/src/test/org/apache/commons/collections/splitmap/TestAll.java
new file mode 100644
index 0000000..c3e54a4
--- /dev/null
+++ b/src/test/org/apache/commons/collections/splitmap/TestAll.java
@@ -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 {
+}
http://git-wip-us.apache.org/repos/asf/commons-collections/blob/87ac9390/src/test/org/apache/commons/collections/splitmap/TestSplitMapUtils.java
----------------------------------------------------------------------
diff --git a/src/test/org/apache/commons/collections/splitmap/TestSplitMapUtils.java b/src/test/org/apache/commons/collections/splitmap/TestSplitMapUtils.java
new file mode 100644
index 0000000..c09cb5f
--- /dev/null
+++ b/src/test/org/apache/commons/collections/splitmap/TestSplitMapUtils.java
@@ -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) {
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/commons-collections/blob/87ac9390/src/test/org/apache/commons/collections/splitmap/TestTransformedMap.java
----------------------------------------------------------------------
diff --git a/src/test/org/apache/commons/collections/splitmap/TestTransformedMap.java b/src/test/org/apache/commons/collections/splitmap/TestTransformedMap.java
new file mode 100644
index 0000000..b77fa4c
--- /dev/null
+++ b/src/test/org/apache/commons/collections/splitmap/TestTransformedMap.java
@@ -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());
+ }
+ }
+
+}