Add AbstractInputCheckedMapDecorator
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/collections/trunk@131699 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
07a0f5c777
commit
486a169f5e
|
@ -19,7 +19,7 @@
|
|||
|
||||
<p>
|
||||
This release focusses on bug fixes and minor enhancements.
|
||||
No interface changes, or deprecations have occurred.
|
||||
No deprecations have occurred.
|
||||
|
||||
<hr />
|
||||
|
||||
|
@ -32,6 +32,7 @@ No interface changes, or deprecations have occurred.
|
|||
<li>MapBackedSet - Set created by decorating a map</li>
|
||||
<li>ReferenceIdentityMap - Similar to ReferenceMap, but matching keys and values by identity [26503]</li>
|
||||
<li>AbstractReferenceMap - New base class for reference maps [26503]</li>
|
||||
<li>AbstractInputCheckedMapDecorator - New base class for map decorators that validate or alter input</li>
|
||||
</ul>
|
||||
|
||||
<center><h3>ENHANCEMENTS</h3></center>
|
||||
|
|
|
@ -0,0 +1,270 @@
|
|||
/*
|
||||
* Copyright 2004 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.lang.reflect.Array;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.collections.iterators.AbstractIteratorDecorator;
|
||||
import org.apache.commons.collections.keyvalue.AbstractMapEntryDecorator;
|
||||
import org.apache.commons.collections.set.AbstractSetDecorator;
|
||||
|
||||
/**
|
||||
* An abstract base class that simplifies the task of creating map decorators.
|
||||
* <p>
|
||||
* The Map API is very difficult to decorate correctly, and involves implementing
|
||||
* lots of different classes. This class exists to provide a simpler API.
|
||||
* <p>
|
||||
* Special hook methods are provided that are called when objects are added to
|
||||
* the map. By overriding these methods, the input can be validated or manipulated.
|
||||
* In addition to the main map methods, the entrySet is also affected, which is
|
||||
* the hardest part of writing map implementations.
|
||||
*
|
||||
* @since Commons Collections 3.1
|
||||
* @version $Revision: 1.1 $ $Date: 2004/05/03 21:48:49 $
|
||||
*
|
||||
* @author Stephen Colebourne
|
||||
*/
|
||||
public class AbstractInputCheckedMapDecorator
|
||||
extends AbstractMapDecorator {
|
||||
|
||||
/**
|
||||
* Constructor only used in deserialization, do not use otherwise.
|
||||
*/
|
||||
protected AbstractInputCheckedMapDecorator() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that wraps (not copies).
|
||||
*
|
||||
* @param map the map to decorate, must not be null
|
||||
* @throws IllegalArgumentException if map is null
|
||||
*/
|
||||
protected AbstractInputCheckedMapDecorator(Map map) {
|
||||
super(map);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Hook method called when a key is being added to the map using
|
||||
* <code>put</code> or <code>putAll</code>.
|
||||
* <p>
|
||||
* An implementation may validate the key and throw an exception
|
||||
* or it may transform the key into another object.
|
||||
* The key may already exist in the map.
|
||||
* <p>
|
||||
* This implementation returns the input key.
|
||||
*
|
||||
* @param key the key to check
|
||||
* @throws UnsupportedOperationException if the map may not be changed by put/putAll
|
||||
* @throws IllegalArgumentException if the specified key is invalid
|
||||
* @throws ClassCastException if the class of the specified key is invalid
|
||||
* @throws NullPointerException if the specified key is null and nulls are invalid
|
||||
*/
|
||||
protected Object checkPutKey(Object key) {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook method called when a new value is being added to the map using
|
||||
* <code>put</code> or <code>putAll</code>.
|
||||
* <p>
|
||||
* An implementation may validate the value and throw an exception
|
||||
* or it may transform the value into another object.
|
||||
* <p>
|
||||
* This implementation returns the input value.
|
||||
*
|
||||
* @param value the value to check
|
||||
* @throws UnsupportedOperationException if the map may not be changed by put/putAll
|
||||
* @throws IllegalArgumentException if the specified value is invalid
|
||||
* @throws ClassCastException if the class of the specified value is invalid
|
||||
* @throws NullPointerException if the specified value is null and nulls are invalid
|
||||
*/
|
||||
protected Object checkPutValue(Object value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook method called when a value is being set using <code>setValue</code>.
|
||||
* <p>
|
||||
* An implementation may validate the value and throw an exception
|
||||
* or it may transform the value into another object.
|
||||
* <p>
|
||||
* This implementation returns the input value.
|
||||
*
|
||||
* @param value the value to check
|
||||
* @throws UnsupportedOperationException if the map may not be changed by setValue
|
||||
* @throws IllegalArgumentException if the specified value is invalid
|
||||
* @throws ClassCastException if the class of the specified value is invalid
|
||||
* @throws NullPointerException if the specified value is null and nulls are invalid
|
||||
*/
|
||||
protected Object checkSetValue(Object value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook method called to determine if <code>checkSetValue</code> has any effect.
|
||||
* <p>
|
||||
* An implementation should return false if the <code>checkSetValue</code> method
|
||||
* has no effect as this optimises the implementation.
|
||||
* <p>
|
||||
* This implementation returns <code>true</code>.
|
||||
*
|
||||
* @param value the value to check
|
||||
*/
|
||||
protected boolean isSetValueChecking() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks each element in the specified map, creating a new map.
|
||||
* <p>
|
||||
* This method is used by <code>putAll</code> to check all the elements
|
||||
* before adding them to the map.
|
||||
* <p>
|
||||
* This implementation builds a <code>LinkedMap</code> to preserve the order
|
||||
* of the input map.
|
||||
*
|
||||
* @param map the map to transform
|
||||
* @throws the transformed object
|
||||
*/
|
||||
protected Map checkMap(Map map) {
|
||||
Map result = new LinkedMap(map.size());
|
||||
for (Iterator it = map.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry entry = (Map.Entry) it.next();
|
||||
result.put(checkPutKey(entry.getKey()), checkPutValue(entry.getValue()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
public Object put(Object key, Object value) {
|
||||
key = checkPutKey(key);
|
||||
value = checkPutValue(value);
|
||||
return getMap().put(key, value);
|
||||
}
|
||||
|
||||
public void putAll(Map mapToCopy) {
|
||||
if (mapToCopy.size() == 0) {
|
||||
return;
|
||||
} else {
|
||||
mapToCopy = checkMap(mapToCopy);
|
||||
getMap().putAll(mapToCopy);
|
||||
}
|
||||
}
|
||||
|
||||
public Set entrySet() {
|
||||
if (isSetValueChecking()) {
|
||||
return new EntrySet(map.entrySet(), this);
|
||||
} else {
|
||||
return map.entrySet();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Implementation of an entry set that checks additions via setValue.
|
||||
*/
|
||||
static class EntrySet extends AbstractSetDecorator {
|
||||
|
||||
/** The parent map */
|
||||
private final AbstractInputCheckedMapDecorator parent;
|
||||
|
||||
protected EntrySet(Set set, AbstractInputCheckedMapDecorator parent) {
|
||||
super(set);
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public Iterator iterator() {
|
||||
return new EntrySetIterator(collection.iterator(), parent);
|
||||
}
|
||||
|
||||
public Object[] toArray() {
|
||||
Object[] array = collection.toArray();
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = new MapEntry((Map.Entry) array[i], parent);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public Object[] toArray(Object array[]) {
|
||||
Object[] result = array;
|
||||
if (array.length > 0) {
|
||||
// we must create a new array to handle multi-threaded situations
|
||||
// where another thread could access data before we decorate it
|
||||
result = (Object[]) Array.newInstance(array.getClass().getComponentType(), 0);
|
||||
}
|
||||
result = collection.toArray(result);
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = new MapEntry((Map.Entry) result[i], parent);
|
||||
}
|
||||
|
||||
// check to see if result should be returned straight
|
||||
if (result.length > array.length) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// copy back into input array to fulfil the method contract
|
||||
System.arraycopy(result, 0, array, 0, result.length);
|
||||
if (array.length > result.length) {
|
||||
array[result.length] = null;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of an entry set iterator that checks additions via setValue.
|
||||
*/
|
||||
static class EntrySetIterator extends AbstractIteratorDecorator {
|
||||
|
||||
/** The parent map */
|
||||
private final AbstractInputCheckedMapDecorator parent;
|
||||
|
||||
protected EntrySetIterator(Iterator iterator, AbstractInputCheckedMapDecorator parent) {
|
||||
super(iterator);
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public Object next() {
|
||||
Map.Entry entry = (Map.Entry) iterator.next();
|
||||
return new MapEntry(entry, parent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of a map entry that checks additions via setValue.
|
||||
*/
|
||||
static class MapEntry extends AbstractMapEntryDecorator {
|
||||
|
||||
/** The parent map */
|
||||
private final AbstractInputCheckedMapDecorator parent;
|
||||
|
||||
protected MapEntry(Map.Entry entry, AbstractInputCheckedMapDecorator parent) {
|
||||
super(entry);
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public Object setValue(Object value) {
|
||||
value = parent.checkSetValue(value);
|
||||
return entry.setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -19,15 +19,10 @@ import java.io.IOException;
|
|||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.collections.Predicate;
|
||||
import org.apache.commons.collections.collection.AbstractCollectionDecorator;
|
||||
import org.apache.commons.collections.iterators.AbstractIteratorDecorator;
|
||||
import org.apache.commons.collections.keyvalue.AbstractMapEntryDecorator;
|
||||
|
||||
/**
|
||||
* Decorates another <code>Map</code> to validate that additions
|
||||
|
@ -39,13 +34,13 @@ import org.apache.commons.collections.keyvalue.AbstractMapEntryDecorator;
|
|||
* This class is Serializable from Commons Collections 3.1.
|
||||
*
|
||||
* @since Commons Collections 3.0
|
||||
* @version $Revision: 1.9 $ $Date: 2004/04/09 10:36:01 $
|
||||
* @version $Revision: 1.10 $ $Date: 2004/05/03 21:48:49 $
|
||||
*
|
||||
* @author Stephen Colebourne
|
||||
* @author Paul Jack
|
||||
*/
|
||||
public class PredicatedMap
|
||||
extends AbstractMapDecorator
|
||||
extends AbstractInputCheckedMapDecorator
|
||||
implements Serializable {
|
||||
|
||||
/** Serialization version */
|
||||
|
@ -94,6 +89,13 @@ public class PredicatedMap
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a key value pair.
|
||||
*
|
||||
* @param key the key to validate
|
||||
* @param value the value to validate
|
||||
* @throws IllegalArgumentException if invalid
|
||||
*/
|
||||
protected void validate(Object key, Object value) {
|
||||
if (keyPredicate != null && keyPredicate.evaluate(key) == false) {
|
||||
throw new IllegalArgumentException("Cannot add key - Predicate rejected it");
|
||||
|
@ -129,6 +131,33 @@ public class PredicatedMap
|
|||
map = (Map) in.readObject();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// The validate method exists for backwards compatability - in an ideal
|
||||
// world, it wouldn't and the superclass methods checkPutKey/checkPutValue
|
||||
// would be overridden instead
|
||||
|
||||
/**
|
||||
* Override to validate an object set into the map via <code>setValue</code>.
|
||||
*
|
||||
* @param value the value to validate
|
||||
* @throws IllegalArgumentException if invalid
|
||||
*/
|
||||
protected Object checkSetValue(Object value) {
|
||||
if (valuePredicate.evaluate(value) == false) {
|
||||
throw new IllegalArgumentException("Cannot set value - Predicate rejected it");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override to only return true when there is a value transformer.
|
||||
*
|
||||
* @return true if a value predicate is in use
|
||||
*/
|
||||
protected boolean isSetValueChecking() {
|
||||
return (valuePredicate != null);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
public Object put(Object key, Object value) {
|
||||
validate(key, value);
|
||||
|
@ -146,104 +175,4 @@ public class PredicatedMap
|
|||
map.putAll(mapToCopy);
|
||||
}
|
||||
|
||||
public Set entrySet() {
|
||||
if (valuePredicate == null) {
|
||||
return map.entrySet();
|
||||
}
|
||||
return new PredicatedMapEntrySet(map.entrySet(), valuePredicate);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Implementation of an entry set that checks (predicates) additions.
|
||||
*/
|
||||
static class PredicatedMapEntrySet extends AbstractCollectionDecorator implements Set {
|
||||
|
||||
/** The predicate to use */
|
||||
private final Predicate valuePredicate;
|
||||
|
||||
protected PredicatedMapEntrySet(Set set, Predicate valuePred) {
|
||||
super(set);
|
||||
this.valuePredicate = valuePred;
|
||||
}
|
||||
|
||||
public Iterator iterator() {
|
||||
return new PredicatedMapEntrySetIterator(collection.iterator(), valuePredicate);
|
||||
}
|
||||
|
||||
public Object[] toArray() {
|
||||
Object[] array = collection.toArray();
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = new PredicatedMapEntry((Map.Entry) array[i], valuePredicate);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public Object[] toArray(Object array[]) {
|
||||
Object[] result = array;
|
||||
if (array.length > 0) {
|
||||
// we must create a new array to handle multi-threaded situations
|
||||
// where another thread could access data before we decorate it
|
||||
result = (Object[]) Array.newInstance(array.getClass().getComponentType(), 0);
|
||||
}
|
||||
result = collection.toArray(result);
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = new PredicatedMapEntry((Map.Entry) result[i], valuePredicate);
|
||||
}
|
||||
|
||||
// check to see if result should be returned straight
|
||||
if (result.length > array.length) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// copy back into input array to fulfil the method contract
|
||||
System.arraycopy(result, 0, array, 0, result.length);
|
||||
if (array.length > result.length) {
|
||||
array[result.length] = null;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of an entry set iterator.
|
||||
*/
|
||||
static class PredicatedMapEntrySetIterator extends AbstractIteratorDecorator {
|
||||
|
||||
/** The predicate to use */
|
||||
private final Predicate valuePredicate;
|
||||
|
||||
protected PredicatedMapEntrySetIterator(Iterator iterator, Predicate valuePredicate) {
|
||||
super(iterator);
|
||||
this.valuePredicate = valuePredicate;
|
||||
}
|
||||
|
||||
public Object next() {
|
||||
Map.Entry entry = (Map.Entry) iterator.next();
|
||||
return new PredicatedMapEntry(entry, valuePredicate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of a map entry that checks (predicates) additions.
|
||||
*/
|
||||
static class PredicatedMapEntry extends AbstractMapEntryDecorator {
|
||||
|
||||
/** The predicate to use */
|
||||
private final Predicate predicate;
|
||||
|
||||
protected PredicatedMapEntry(Map.Entry entry, Predicate valuePredicate) {
|
||||
super(entry);
|
||||
this.predicate = valuePredicate;
|
||||
}
|
||||
|
||||
public Object setValue(Object obj) {
|
||||
if (predicate != null && predicate.evaluate(obj) == false) {
|
||||
throw new IllegalArgumentException("Cannot set value - Predicate rejected it");
|
||||
}
|
||||
return entry.setValue(obj);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,16 +19,10 @@ import java.io.IOException;
|
|||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.collections.Transformer;
|
||||
import org.apache.commons.collections.collection.AbstractCollectionDecorator;
|
||||
import org.apache.commons.collections.iterators.AbstractIteratorDecorator;
|
||||
import org.apache.commons.collections.keyvalue.AbstractMapEntryDecorator;
|
||||
|
||||
/**
|
||||
* Decorates another <code>Map</code> to transform objects that are added.
|
||||
|
@ -41,12 +35,12 @@ import org.apache.commons.collections.keyvalue.AbstractMapEntryDecorator;
|
|||
* This class is Serializable from Commons Collections 3.1.
|
||||
*
|
||||
* @since Commons Collections 3.0
|
||||
* @version $Revision: 1.8 $ $Date: 2004/04/09 10:36:01 $
|
||||
* @version $Revision: 1.9 $ $Date: 2004/05/03 21:48:49 $
|
||||
*
|
||||
* @author Stephen Colebourne
|
||||
*/
|
||||
public class TransformedMap
|
||||
extends AbstractMapDecorator
|
||||
extends AbstractInputCheckedMapDecorator
|
||||
implements Serializable {
|
||||
|
||||
/** Serialization version */
|
||||
|
@ -117,6 +111,10 @@ public class TransformedMap
|
|||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// The transformKey/transformValue/transformMap methods exist for backwards
|
||||
// compatability - in an ideal world, they wouldn't and the superclass
|
||||
// methods checkPutKey/checkPutValue would be overridden instead
|
||||
|
||||
/**
|
||||
* Transforms a key.
|
||||
* <p>
|
||||
|
@ -156,7 +154,7 @@ public class TransformedMap
|
|||
* @throws the transformed object
|
||||
*/
|
||||
protected Map transformMap(Map map) {
|
||||
Map result = new HashMap(map.size());
|
||||
Map result = new LinkedMap(map.size());
|
||||
for (Iterator it = map.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry entry = (Map.Entry) it.next();
|
||||
result.put(transformKey(entry.getKey()), transformValue(entry.getValue()));
|
||||
|
@ -164,6 +162,25 @@ public class TransformedMap
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override to transform the value when using <code>setValue</code>.
|
||||
*
|
||||
* @param value the value to transform
|
||||
* @return the transformed value
|
||||
*/
|
||||
protected Object checkSetValue(Object value) {
|
||||
return valueTransformer.transform(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override to only return true when there is a value transformer.
|
||||
*
|
||||
* @return true if a value transformer is in use
|
||||
*/
|
||||
protected boolean isSetValueChecking() {
|
||||
return (valueTransformer != null);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
public Object put(Object key, Object value) {
|
||||
key = transformKey(key);
|
||||
|
@ -176,104 +193,4 @@ public class TransformedMap
|
|||
getMap().putAll(mapToCopy);
|
||||
}
|
||||
|
||||
public Set entrySet() {
|
||||
if (valueTransformer == null) {
|
||||
return map.entrySet();
|
||||
}
|
||||
return new TransformedMapEntrySet(map.entrySet(), valueTransformer);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Implementation of an entry set that uses a transforming map entry.
|
||||
*/
|
||||
static class TransformedMapEntrySet extends AbstractCollectionDecorator implements Set {
|
||||
|
||||
/** The transformer to use */
|
||||
private final Transformer valueTransformer;
|
||||
|
||||
protected TransformedMapEntrySet(Set set, Transformer valueTransformer) {
|
||||
super(set);
|
||||
this.valueTransformer = valueTransformer;
|
||||
}
|
||||
|
||||
public Iterator iterator() {
|
||||
return new TransformedMapEntrySetIterator(collection.iterator(), valueTransformer);
|
||||
}
|
||||
|
||||
public Object[] toArray() {
|
||||
Object[] array = collection.toArray();
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = new TransformedMapEntry((Map.Entry) array[i], valueTransformer);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public Object[] toArray(Object array[]) {
|
||||
Object[] result = array;
|
||||
if (array.length > 0) {
|
||||
// we must create a new array to handle multi-threaded situations
|
||||
// where another thread could access data before we decorate it
|
||||
result = (Object[]) Array.newInstance(array.getClass().getComponentType(), 0);
|
||||
}
|
||||
result = collection.toArray(result);
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = new TransformedMapEntry((Map.Entry) result[i], valueTransformer);
|
||||
}
|
||||
|
||||
// check to see if result should be returned straight
|
||||
if (result.length > array.length) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// copy back into input array to fulfil the method contract
|
||||
System.arraycopy(result, 0, array, 0, result.length);
|
||||
if (array.length > result.length) {
|
||||
array[result.length] = null;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of an entry set iterator.
|
||||
*/
|
||||
static class TransformedMapEntrySetIterator extends AbstractIteratorDecorator {
|
||||
|
||||
/** The transformer to use */
|
||||
private final Transformer valueTransformer;
|
||||
|
||||
protected TransformedMapEntrySetIterator(Iterator iterator, Transformer valueTransformer) {
|
||||
super(iterator);
|
||||
this.valueTransformer = valueTransformer;
|
||||
}
|
||||
|
||||
public Object next() {
|
||||
Map.Entry entry = (Map.Entry) iterator.next();
|
||||
return new TransformedMapEntry(entry, valueTransformer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of a map entry that transforms additions.
|
||||
*/
|
||||
static class TransformedMapEntry extends AbstractMapEntryDecorator {
|
||||
|
||||
/** The transformer to use */
|
||||
private final Transformer valueTransformer;
|
||||
|
||||
protected TransformedMapEntry(Map.Entry entry, Transformer valueTransformer) {
|
||||
super(entry);
|
||||
this.valueTransformer = valueTransformer;
|
||||
}
|
||||
|
||||
public Object setValue(Object object) {
|
||||
if (valueTransformer != null) {
|
||||
object = valueTransformer.transform(object);
|
||||
}
|
||||
return entry.setValue(object);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue