TransformedSortedMap.java

  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. import java.util.Comparator;
  19. import java.util.Map;
  20. import java.util.SortedMap;

  21. import org.apache.commons.collections4.Transformer;

  22. /**
  23.  * Decorates another {@code SortedMap } to transform objects that are added.
  24.  * <p>
  25.  * The Map put methods and Map.Entry setValue method are affected by this class.
  26.  * Thus objects must be removed or searched for using their transformed form.
  27.  * For example, if the transformation converts Strings to Integers, you must
  28.  * use the Integer form to remove objects.
  29.  * </p>
  30.  * <p>
  31.  * <strong>Note that TransformedSortedMap is not synchronized and is not thread-safe.</strong>
  32.  * If you wish to use this map from multiple threads concurrently, you must use
  33.  * appropriate synchronization. The simplest approach is to wrap this map
  34.  * using {@link java.util.Collections#synchronizedSortedMap}. This class may throw
  35.  * exceptions when accessed by concurrent threads without synchronization.
  36.  * </p>
  37.  * <p>
  38.  * This class is Serializable from Commons Collections 3.1.
  39.  * </p>
  40.  *
  41.  * @param <K> the type of the keys in this map
  42.  * @param <V> the type of the values in this map
  43.  * @since 3.0
  44.  */
  45. public class TransformedSortedMap<K, V>
  46.         extends TransformedMap<K, V>
  47.         implements SortedMap<K, V> {

  48.     /** Serialization version */
  49.     private static final long serialVersionUID = -8751771676410385778L;

  50.     /**
  51.      * Factory method to create a transforming sorted map that will transform
  52.      * existing contents of the specified map.
  53.      * <p>
  54.      * If there are any elements already in the map being decorated, they
  55.      * will be transformed by this method.
  56.      * Contrast this with {@link #transformingSortedMap(SortedMap, Transformer, Transformer)}.
  57.      * </p>
  58.      *
  59.      * @param <K>  the key type
  60.      * @param <V>  the value type
  61.      * @param map  the map to decorate, must not be null
  62.      * @param keyTransformer  the transformer to use for key conversion, null means no transformation
  63.      * @param valueTransformer  the transformer to use for value conversion, null means no transformation
  64.      * @return a new transformed sorted map
  65.      * @throws NullPointerException if map is null
  66.      * @since 4.0
  67.      */
  68.     public static <K, V> TransformedSortedMap<K, V> transformedSortedMap(final SortedMap<K, V> map,
  69.             final Transformer<? super K, ? extends K> keyTransformer,
  70.             final Transformer<? super V, ? extends V> valueTransformer) {

  71.         final TransformedSortedMap<K, V> decorated =
  72.                 new TransformedSortedMap<>(map, keyTransformer, valueTransformer);
  73.         if (!map.isEmpty()) {
  74.             final Map<K, V> transformed = decorated.transformMap(map);
  75.             decorated.clear();
  76.             decorated.decorated().putAll(transformed);  // avoids double transformation
  77.         }
  78.         return decorated;
  79.     }

  80.     /**
  81.      * Factory method to create a transforming sorted map.
  82.      * <p>
  83.      * If there are any elements already in the map being decorated, they are NOT transformed.
  84.      * Contrast this with {@link #transformedSortedMap(SortedMap, Transformer, Transformer)}.
  85.      * </p>
  86.      *
  87.      * @param <K>  the key type
  88.      * @param <V>  the value type
  89.      * @param map  the map to decorate, must not be null
  90.      * @param keyTransformer  the predicate to validate the keys, null means no transformation
  91.      * @param valueTransformer  the predicate to validate to values, null means no transformation
  92.      * @return a new transformed sorted map
  93.      * @throws NullPointerException if the map is null
  94.      * @since 4.0
  95.      */
  96.     public static <K, V> TransformedSortedMap<K, V> transformingSortedMap(final SortedMap<K, V> map,
  97.             final Transformer<? super K, ? extends K> keyTransformer,
  98.             final Transformer<? super V, ? extends V> valueTransformer) {
  99.         return new TransformedSortedMap<>(map, keyTransformer, valueTransformer);
  100.     }

  101.     /**
  102.      * Constructor that wraps (not copies).
  103.      * <p>
  104.      * If there are any elements already in the collection being decorated, they
  105.      * are NOT transformed.
  106.      * </p>
  107.      *
  108.      * @param map  the map to decorate, must not be null
  109.      * @param keyTransformer  the predicate to validate the keys, null means no transformation
  110.      * @param valueTransformer  the predicate to validate to values, null means no transformation
  111.      * @throws NullPointerException if the map is null
  112.      */
  113.     protected TransformedSortedMap(final SortedMap<K, V> map,
  114.             final Transformer<? super K, ? extends K> keyTransformer,
  115.             final Transformer<? super V, ? extends V> valueTransformer) {
  116.         super(map, keyTransformer, valueTransformer);
  117.     }

  118.     @Override
  119.     public Comparator<? super K> comparator() {
  120.         return getSortedMap().comparator();
  121.     }

  122.     @Override
  123.     public K firstKey() {
  124.         return getSortedMap().firstKey();
  125.     }

  126.     /**
  127.      * Gets the map being decorated.
  128.      *
  129.      * @return the decorated map
  130.      */
  131.     protected SortedMap<K, V> getSortedMap() {
  132.         return (SortedMap<K, V>) map;
  133.     }

  134.     @Override
  135.     public SortedMap<K, V> headMap(final K toKey) {
  136.         final SortedMap<K, V> map = getSortedMap().headMap(toKey);
  137.         return new TransformedSortedMap<>(map, keyTransformer, valueTransformer);
  138.     }

  139.     @Override
  140.     public K lastKey() {
  141.         return getSortedMap().lastKey();
  142.     }

  143.     @Override
  144.     public SortedMap<K, V> subMap(final K fromKey, final K toKey) {
  145.         final SortedMap<K, V> map = getSortedMap().subMap(fromKey, toKey);
  146.         return new TransformedSortedMap<>(map, keyTransformer, valueTransformer);
  147.     }

  148.     @Override
  149.     public SortedMap<K, V> tailMap(final K fromKey) {
  150.         final SortedMap<K, V> map = getSortedMap().tailMap(fromKey);
  151.         return new TransformedSortedMap<>(map, keyTransformer, valueTransformer);
  152.     }

  153. }