1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.collections4.map; 18 19 import java.util.Comparator; 20 import java.util.Map; 21 import java.util.SortedMap; 22 23 import org.apache.commons.collections4.Transformer; 24 25 /** 26 * Decorates another {@code SortedMap } to transform objects that are added. 27 * <p> 28 * The Map put methods and Map.Entry setValue method are affected by this class. 29 * Thus objects must be removed or searched for using their transformed form. 30 * For example, if the transformation converts Strings to Integers, you must 31 * use the Integer form to remove objects. 32 * </p> 33 * <p> 34 * <strong>Note that TransformedSortedMap is not synchronized and is not thread-safe.</strong> 35 * If you wish to use this map from multiple threads concurrently, you must use 36 * appropriate synchronization. The simplest approach is to wrap this map 37 * using {@link java.util.Collections#synchronizedSortedMap}. This class may throw 38 * exceptions when accessed by concurrent threads without synchronization. 39 * </p> 40 * <p> 41 * This class is Serializable from Commons Collections 3.1. 42 * </p> 43 * 44 * @param <K> the type of the keys in this map 45 * @param <V> the type of the values in this map 46 * @since 3.0 47 */ 48 public class TransformedSortedMap<K, V> 49 extends TransformedMap<K, V> 50 implements SortedMap<K, V> { 51 52 /** Serialization version */ 53 private static final long serialVersionUID = -8751771676410385778L; 54 55 /** 56 * Factory method to create a transforming sorted map that will transform 57 * existing contents of the specified map. 58 * <p> 59 * If there are any elements already in the map being decorated, they 60 * will be transformed by this method. 61 * Contrast this with {@link #transformingSortedMap(SortedMap, Transformer, Transformer)}. 62 * </p> 63 * 64 * @param <K> the key type 65 * @param <V> the value type 66 * @param map the map to decorate, must not be null 67 * @param keyTransformer the transformer to use for key conversion, null means no transformation 68 * @param valueTransformer the transformer to use for value conversion, null means no transformation 69 * @return a new transformed sorted map 70 * @throws NullPointerException if map is null 71 * @since 4.0 72 */ 73 public static <K, V> TransformedSortedMap<K, V> transformedSortedMap(final SortedMap<K, V> map, 74 final Transformer<? super K, ? extends K> keyTransformer, 75 final Transformer<? super V, ? extends V> valueTransformer) { 76 77 final TransformedSortedMap<K, V> decorated = 78 new TransformedSortedMap<>(map, keyTransformer, valueTransformer); 79 if (!map.isEmpty()) { 80 final Map<K, V> transformed = decorated.transformMap(map); 81 decorated.clear(); 82 decorated.decorated().putAll(transformed); // avoids double transformation 83 } 84 return decorated; 85 } 86 87 /** 88 * Factory method to create a transforming sorted map. 89 * <p> 90 * If there are any elements already in the map being decorated, they are NOT transformed. 91 * Contrast this with {@link #transformedSortedMap(SortedMap, Transformer, Transformer)}. 92 * </p> 93 * 94 * @param <K> the key type 95 * @param <V> the value type 96 * @param map the map to decorate, must not be null 97 * @param keyTransformer the predicate to validate the keys, null means no transformation 98 * @param valueTransformer the predicate to validate to values, null means no transformation 99 * @return a new transformed sorted map 100 * @throws NullPointerException if the map is null 101 * @since 4.0 102 */ 103 public static <K, V> TransformedSortedMap<K, V> transformingSortedMap(final SortedMap<K, V> map, 104 final Transformer<? super K, ? extends K> keyTransformer, 105 final Transformer<? super V, ? extends V> valueTransformer) { 106 return new TransformedSortedMap<>(map, keyTransformer, valueTransformer); 107 } 108 109 /** 110 * Constructor that wraps (not copies). 111 * <p> 112 * If there are any elements already in the collection being decorated, they 113 * are NOT transformed. 114 * </p> 115 * 116 * @param map the map to decorate, must not be null 117 * @param keyTransformer the predicate to validate the keys, null means no transformation 118 * @param valueTransformer the predicate to validate to values, null means no transformation 119 * @throws NullPointerException if the map is null 120 */ 121 protected TransformedSortedMap(final SortedMap<K, V> map, 122 final Transformer<? super K, ? extends K> keyTransformer, 123 final Transformer<? super V, ? extends V> valueTransformer) { 124 super(map, keyTransformer, valueTransformer); 125 } 126 127 @Override 128 public Comparator<? super K> comparator() { 129 return getSortedMap().comparator(); 130 } 131 132 @Override 133 public K firstKey() { 134 return getSortedMap().firstKey(); 135 } 136 137 /** 138 * Gets the map being decorated. 139 * 140 * @return the decorated map 141 */ 142 protected SortedMap<K, V> getSortedMap() { 143 return (SortedMap<K, V>) map; 144 } 145 146 @Override 147 public SortedMap<K, V> headMap(final K toKey) { 148 final SortedMap<K, V> map = getSortedMap().headMap(toKey); 149 return new TransformedSortedMap<>(map, keyTransformer, valueTransformer); 150 } 151 152 @Override 153 public K lastKey() { 154 return getSortedMap().lastKey(); 155 } 156 157 @Override 158 public SortedMap<K, V> subMap(final K fromKey, final K toKey) { 159 final SortedMap<K, V> map = getSortedMap().subMap(fromKey, toKey); 160 return new TransformedSortedMap<>(map, keyTransformer, valueTransformer); 161 } 162 163 @Override 164 public SortedMap<K, V> tailMap(final K fromKey) { 165 final SortedMap<K, V> map = getSortedMap().tailMap(fromKey); 166 return new TransformedSortedMap<>(map, keyTransformer, valueTransformer); 167 } 168 169 }