View Javadoc
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 }