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.collections.map;
18
19 import java.util.Comparator;
20 import java.util.Map;
21 import java.util.SortedMap;
22
23 import org.apache.commons.collections.Transformer;
24
25 /**
26 * Decorates another <code>SortedMap </code> 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 * <strong>Note that TransformedSortedMap is not synchronized and is not thread-safe.</strong>
34 * If you wish to use this map from multiple threads concurrently, you must use
35 * appropriate synchronization. The simplest approach is to wrap this map
36 * using {@link java.util.Collections#synchronizedSortedMap}. This class may throw
37 * exceptions when accessed by concurrent threads without synchronization.
38 * <p>
39 * This class is Serializable from Commons Collections 3.1.
40 *
41 * @since 3.0
42 * @version $Id: TransformedSortedMap.java 1435824 2013-01-20 11:41:17Z tn $
43 */
44 public class TransformedSortedMap<K, V>
45 extends TransformedMap<K, V>
46 implements SortedMap<K, V> {
47
48 /** Serialization version */
49 private static final long serialVersionUID = -8751771676410385778L;
50
51 /**
52 * Factory method to create a transforming sorted map.
53 * <p>
54 * If there are any elements already in the map being decorated, they are NOT transformed.
55 * Contrast this with {@link #transformedSortedMap(SortedMap, Transformer, Transformer)}.
56 *
57 * @param <K> the key type
58 * @param <V> the value type
59 * @param map the map to decorate, must not be null
60 * @param keyTransformer the predicate to validate the keys, null means no transformation
61 * @param valueTransformer the predicate to validate to values, null means no transformation
62 * @return a new transformed sorted map
63 * @throws IllegalArgumentException if the map is null
64 */
65 public static <K, V> TransformedSortedMap<K, V> transformingSortedMap(final SortedMap<K, V> map,
66 final Transformer<? super K, ? extends K> keyTransformer,
67 final Transformer<? super V, ? extends V> valueTransformer) {
68 return new TransformedSortedMap<K, V>(map, keyTransformer, valueTransformer);
69 }
70
71 /**
72 * Factory method to create a transforming sorted map that will transform
73 * existing contents of the specified map.
74 * <p>
75 * If there are any elements already in the map being decorated, they
76 * will be transformed by this method.
77 * Contrast this with {@link #transformingSortedMap(SortedMap, Transformer, Transformer)}.
78 *
79 * @param <K> the key type
80 * @param <V> the value type
81 * @param map the map to decorate, must not be null
82 * @param keyTransformer the transformer to use for key conversion, null means no transformation
83 * @param valueTransformer the transformer to use for value conversion, null means no transformation
84 * @return a new transformed sorted map
85 * @throws IllegalArgumentException if map is null
86 * @since 3.2
87 */
88 public static <K, V> TransformedSortedMap<K, V> transformedSortedMap(final SortedMap<K, V> map,
89 final Transformer<? super K, ? extends K> keyTransformer,
90 final Transformer<? super V, ? extends V> valueTransformer) {
91
92 final TransformedSortedMap<K, V> decorated =
93 new TransformedSortedMap<K, V>(map, keyTransformer, valueTransformer);
94 if (map.size() > 0) {
95 final Map<K, V> transformed = decorated.transformMap(map);
96 decorated.clear();
97 decorated.decorated().putAll(transformed); // avoids double transformation
98 }
99 return decorated;
100 }
101
102 //-----------------------------------------------------------------------
103 /**
104 * Constructor that wraps (not copies).
105 * <p>
106 * If there are any elements already in the collection being decorated, they
107 * are NOT transformed.</p>
108 *
109 * @param map the map to decorate, must not be null
110 * @param keyTransformer the predicate to validate the keys, null means no transformation
111 * @param valueTransformer the predicate to validate to values, null means no transformation
112 * @throws IllegalArgumentException if the map is null
113 */
114 protected TransformedSortedMap(final SortedMap<K, V> map,
115 final Transformer<? super K, ? extends K> keyTransformer,
116 final Transformer<? super V, ? extends V> valueTransformer) {
117 super(map, keyTransformer, valueTransformer);
118 }
119
120 //-----------------------------------------------------------------------
121 /**
122 * Gets the map being decorated.
123 *
124 * @return the decorated map
125 */
126 protected SortedMap<K, V> getSortedMap() {
127 return (SortedMap<K, V>) map;
128 }
129
130 //-----------------------------------------------------------------------
131 public K firstKey() {
132 return getSortedMap().firstKey();
133 }
134
135 public K lastKey() {
136 return getSortedMap().lastKey();
137 }
138
139 public Comparator<? super K> comparator() {
140 return getSortedMap().comparator();
141 }
142
143 public SortedMap<K, V> subMap(final K fromKey, final K toKey) {
144 final SortedMap<K, V> map = getSortedMap().subMap(fromKey, toKey);
145 return new TransformedSortedMap<K, V>(map, keyTransformer, valueTransformer);
146 }
147
148 public SortedMap<K, V> headMap(final K toKey) {
149 final SortedMap<K, V> map = getSortedMap().headMap(toKey);
150 return new TransformedSortedMap<K, V>(map, keyTransformer, valueTransformer);
151 }
152
153 public SortedMap<K, V> tailMap(final K fromKey) {
154 final SortedMap<K, V> map = getSortedMap().tailMap(fromKey);
155 return new TransformedSortedMap<K, V>(map, keyTransformer, valueTransformer);
156 }
157
158 }