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    }