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 */
017package org.apache.commons.collections4.map;
018
019import java.util.Comparator;
020import java.util.SortedMap;
021
022import org.apache.commons.collections4.Factory;
023import org.apache.commons.collections4.Transformer;
024
025/**
026 * Decorates another <code>SortedMap</code> to create objects in the map on demand.
027 * <p>
028 * When the {@link #get(Object)} method is called with a key that does not
029 * exist in the map, the factory is used to create the object. The created
030 * object will be added to the map using the requested key.
031 * <p>
032 * For instance:
033 * <pre>
034 * Factory&lt;Date&gt; factory = new Factory&lt;Date&gt;() {
035 *     public Date create() {
036 *         return new Date();
037 *     }
038 * }
039 * SortedMap&lt;String, Date&gt; lazy =
040 *     LazySortedMap.lazySortedMap(new HashMap&lt;String, Date&gt;(), factory);
041 * Date date = lazy.get("NOW");
042 * </pre>
043 *
044 * After the above code is executed, <code>date</code> will refer to
045 * a new <code>Date</code> instance. Furthermore, that <code>Date</code>
046 * instance is mapped to the "NOW" key in the map.
047 * <p>
048 * <strong>Note that LazySortedMap is not synchronized and is not thread-safe.</strong>
049 * If you wish to use this map from multiple threads concurrently, you must use
050 * appropriate synchronization. The simplest approach is to wrap this map
051 * using {@link java.util.Collections#synchronizedSortedMap}. This class may throw
052 * exceptions when accessed by concurrent threads without synchronization.
053 * <p>
054 * This class is Serializable from Commons Collections 3.1.
055 *
056 * @param <K> the type of the keys in this map
057 * @param <V> the type of the values in this map
058 * @since 3.0
059 */
060public class LazySortedMap<K,V> extends LazyMap<K,V> implements SortedMap<K,V> {
061
062    /** Serialization version */
063    private static final long serialVersionUID = 2715322183617658933L;
064
065    /**
066     * Factory method to create a lazily instantiated sorted map.
067     *
068     * @param <K>  the key type
069     * @param <V>  the value type
070     * @param map  the map to decorate, must not be null
071     * @param factory  the factory to use, must not be null
072     * @return a new lazy sorted map
073     * @throws NullPointerException if map or factory is null
074     * @since 4.0
075     */
076    public static <K, V> LazySortedMap<K, V> lazySortedMap(final SortedMap<K, V> map,
077                                                           final Factory<? extends V> factory) {
078        return new LazySortedMap<>(map, factory);
079    }
080
081    /**
082     * Factory method to create a lazily instantiated sorted map.
083     *
084     * @param <K>  the key type
085     * @param <V>  the value type
086     * @param map  the map to decorate, must not be null
087     * @param factory  the factory to use, must not be null
088     * @return a new lazy sorted map
089     * @throws NullPointerException if map or factory is null
090     * @since 4.0
091     */
092    public static <K, V> LazySortedMap<K, V> lazySortedMap(final SortedMap<K, V> map,
093                                                           final Transformer<? super K, ? extends V> factory) {
094        return new LazySortedMap<>(map, factory);
095    }
096
097    //-----------------------------------------------------------------------
098    /**
099     * Constructor that wraps (not copies).
100     *
101     * @param map  the map to decorate, must not be null
102     * @param factory  the factory to use, must not be null
103     * @throws NullPointerException if map or factory is null
104     */
105    protected LazySortedMap(final SortedMap<K,V> map, final Factory<? extends V> factory) {
106        super(map, factory);
107    }
108
109    /**
110     * Constructor that wraps (not copies).
111     *
112     * @param map  the map to decorate, must not be null
113     * @param factory  the factory to use, must not be null
114     * @throws NullPointerException if map or factory is null
115     */
116    protected LazySortedMap(final SortedMap<K,V> map, final Transformer<? super K, ? extends V> factory) {
117        super(map, factory);
118    }
119
120    //-----------------------------------------------------------------------
121    /**
122     * Gets the map being decorated.
123     *
124     * @return the decorated map
125     */
126    protected SortedMap<K,V> getSortedMap() {
127        return (SortedMap<K,V>) map;
128    }
129
130    //-----------------------------------------------------------------------
131    @Override
132    public K firstKey() {
133        return getSortedMap().firstKey();
134    }
135
136    @Override
137    public K lastKey() {
138        return getSortedMap().lastKey();
139    }
140
141    @Override
142    public Comparator<? super K> comparator() {
143        return getSortedMap().comparator();
144    }
145
146    @Override
147    public SortedMap<K,V> subMap(final K fromKey, final K toKey) {
148        final SortedMap<K,V> map = getSortedMap().subMap(fromKey, toKey);
149        return new LazySortedMap<>(map, factory);
150    }
151
152    @Override
153    public SortedMap<K,V> headMap(final K toKey) {
154        final SortedMap<K,V> map = getSortedMap().headMap(toKey);
155        return new LazySortedMap<>(map, factory);
156    }
157
158    @Override
159    public SortedMap<K,V> tailMap(final K fromKey) {
160        final SortedMap<K,V> map = getSortedMap().tailMap(fromKey);
161        return new LazySortedMap<>(map, factory);
162    }
163
164}