001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.collections.map;
018
019 import java.util.Comparator;
020 import java.util.Map;
021 import java.util.SortedMap;
022
023 import org.apache.commons.collections.Transformer;
024
025 /**
026 * Decorates another <code>SortedMap </code> to transform objects that are added.
027 * <p>
028 * The Map put methods and Map.Entry setValue method are affected by this class.
029 * Thus objects must be removed or searched for using their transformed form.
030 * For example, if the transformation converts Strings to Integers, you must
031 * use the Integer form to remove objects.
032 * <p>
033 * <strong>Note that TransformedSortedMap is not synchronized and is not thread-safe.</strong>
034 * If you wish to use this map from multiple threads concurrently, you must use
035 * appropriate synchronization. The simplest approach is to wrap this map
036 * using {@link java.util.Collections#synchronizedSortedMap}. This class may throw
037 * exceptions when accessed by concurrent threads without synchronization.
038 * <p>
039 * This class is Serializable from Commons Collections 3.1.
040 *
041 * @since Commons Collections 3.0
042 * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
043 *
044 * @author Stephen Colebourne
045 */
046 public class TransformedSortedMap
047 extends TransformedMap
048 implements SortedMap {
049
050 /** Serialization version */
051 private static final long serialVersionUID = -8751771676410385778L;
052
053 /**
054 * Factory method to create a transforming sorted map.
055 * <p>
056 * If there are any elements already in the map being decorated, they
057 * are NOT transformed.
058 * Constrast this with {@link #decorateTransform}.
059 *
060 * @param map the map to decorate, must not be null
061 * @param keyTransformer the predicate to validate the keys, null means no transformation
062 * @param valueTransformer the predicate to validate to values, null means no transformation
063 * @throws IllegalArgumentException if the map is null
064 */
065 public static SortedMap decorate(SortedMap map, Transformer keyTransformer, Transformer valueTransformer) {
066 return new TransformedSortedMap(map, keyTransformer, valueTransformer);
067 }
068
069 /**
070 * Factory method to create a transforming sorted map that will transform
071 * existing contents of the specified map.
072 * <p>
073 * If there are any elements already in the map being decorated, they
074 * will be transformed by this method.
075 * Constrast this with {@link #decorate}.
076 *
077 * @param map the map to decorate, must not be null
078 * @param keyTransformer the transformer to use for key conversion, null means no transformation
079 * @param valueTransformer the transformer to use for value conversion, null means no transformation
080 * @throws IllegalArgumentException if map is null
081 * @since Commons Collections 3.2
082 */
083 public static SortedMap decorateTransform(SortedMap map, Transformer keyTransformer, Transformer valueTransformer) {
084 TransformedSortedMap decorated = new TransformedSortedMap(map, keyTransformer, valueTransformer);
085 if (map.size() > 0) {
086 Map transformed = decorated.transformMap(map);
087 decorated.clear();
088 decorated.getMap().putAll(transformed); // avoids double transformation
089 }
090 return decorated;
091 }
092
093 //-----------------------------------------------------------------------
094 /**
095 * Constructor that wraps (not copies).
096 * <p>
097 * If there are any elements already in the collection being decorated, they
098 * are NOT transformed.</p>
099 *
100 * @param map the map to decorate, must not be null
101 * @param keyTransformer the predicate to validate the keys, null means no transformation
102 * @param valueTransformer the predicate to validate to values, null means no transformation
103 * @throws IllegalArgumentException if the map is null
104 */
105 protected TransformedSortedMap(SortedMap map, Transformer keyTransformer, Transformer valueTransformer) {
106 super(map, keyTransformer, valueTransformer);
107 }
108
109 //-----------------------------------------------------------------------
110 /**
111 * Gets the map being decorated.
112 *
113 * @return the decorated map
114 */
115 protected SortedMap getSortedMap() {
116 return (SortedMap) map;
117 }
118
119 //-----------------------------------------------------------------------
120 public Object firstKey() {
121 return getSortedMap().firstKey();
122 }
123
124 public Object lastKey() {
125 return getSortedMap().lastKey();
126 }
127
128 public Comparator comparator() {
129 return getSortedMap().comparator();
130 }
131
132 public SortedMap subMap(Object fromKey, Object toKey) {
133 SortedMap map = getSortedMap().subMap(fromKey, toKey);
134 return new TransformedSortedMap(map, keyTransformer, valueTransformer);
135 }
136
137 public SortedMap headMap(Object toKey) {
138 SortedMap map = getSortedMap().headMap(toKey);
139 return new TransformedSortedMap(map, keyTransformer, valueTransformer);
140 }
141
142 public SortedMap tailMap(Object fromKey) {
143 SortedMap map = getSortedMap().tailMap(fromKey);
144 return new TransformedSortedMap(map, keyTransformer, valueTransformer);
145 }
146
147 }