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 }