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.io.IOException;
020import java.io.ObjectInputStream;
021import java.io.ObjectOutputStream;
022import java.io.Serializable;
023import java.util.Collection;
024import java.util.Comparator;
025import java.util.Map;
026import java.util.Set;
027import java.util.SortedMap;
028
029import org.apache.commons.collections4.set.UnmodifiableSet;
030import org.apache.commons.collections4.Unmodifiable;
031import org.apache.commons.collections4.collection.UnmodifiableCollection;
032
033/**
034 * Decorates another <code>SortedMap</code> to ensure it can't be altered.
035 * <p>
036 * This class is Serializable from Commons Collections 3.1.
037 * <p>
038 * Attempts to modify it will result in an UnsupportedOperationException.
039 *
040 * @since 3.0
041 * @version $Id: UnmodifiableSortedMap.html 887892 2013-11-24 13:43:45Z tn $
042 */
043public final class UnmodifiableSortedMap<K, V>
044        extends AbstractSortedMapDecorator<K, V>
045        implements Unmodifiable, Serializable {
046
047    /** Serialization version */
048    private static final long serialVersionUID = 5805344239827376360L;
049
050    /**
051     * Factory method to create an unmodifiable sorted map.
052     *
053     * @param <K>  the key type
054     * @param <V>  the value type
055     * @param map  the map to decorate, must not be null
056     * @return a new unmodifiable sorted map
057     * @throws IllegalArgumentException if map is null
058     * @since 4.0
059     */
060    public static <K, V> SortedMap<K, V> unmodifiableSortedMap(final SortedMap<K, ? extends V> map) {
061        if (map instanceof Unmodifiable) {
062            @SuppressWarnings("unchecked") // safe to upcast
063            final SortedMap<K, V> tmpMap = (SortedMap<K, V>) map;
064            return tmpMap;
065        }
066        return new UnmodifiableSortedMap<K, V>(map);
067    }
068
069    //-----------------------------------------------------------------------
070    /**
071     * Constructor that wraps (not copies).
072     *
073     * @param map  the map to decorate, must not be null
074     * @throws IllegalArgumentException if map is null
075     */
076    @SuppressWarnings("unchecked") // safe to upcast
077    private UnmodifiableSortedMap(final SortedMap<K, ? extends V> map) {
078        super((SortedMap<K, V>) map);
079    }
080
081    //-----------------------------------------------------------------------
082    /**
083     * Write the map out using a custom routine.
084     *
085     * @param out  the output stream
086     * @throws IOException
087     * @since 3.1
088     */
089    private void writeObject(final ObjectOutputStream out) throws IOException {
090        out.defaultWriteObject();
091        out.writeObject(map);
092    }
093
094    /**
095     * Read the map in using a custom routine.
096     *
097     * @param in  the input stream
098     * @throws IOException
099     * @throws ClassNotFoundException
100     * @since 3.1
101     */
102    @SuppressWarnings("unchecked")
103    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
104        in.defaultReadObject();
105        map = (Map<K, V>) in.readObject();
106    }
107
108    //-----------------------------------------------------------------------
109    @Override
110    public void clear() {
111        throw new UnsupportedOperationException();
112    }
113
114    @Override
115    public V put(final K key, final V value) {
116        throw new UnsupportedOperationException();
117    }
118
119    @Override
120    public void putAll(final Map<? extends K, ? extends V> mapToCopy) {
121        throw new UnsupportedOperationException();
122    }
123
124    @Override
125    public V remove(final Object key) {
126        throw new UnsupportedOperationException();
127    }
128
129    @Override
130    public Set<Map.Entry<K, V>> entrySet() {
131        return UnmodifiableEntrySet.unmodifiableEntrySet(super.entrySet());
132    }
133
134    @Override
135    public Set<K> keySet() {
136        return UnmodifiableSet.unmodifiableSet(super.keySet());
137    }
138
139    @Override
140    public Collection<V> values() {
141        return UnmodifiableCollection.unmodifiableCollection(super.values());
142    }
143
144    //-----------------------------------------------------------------------
145    @Override
146    public K firstKey() {
147        return decorated().firstKey();
148    }
149
150    @Override
151    public K lastKey() {
152        return decorated().lastKey();
153    }
154
155    @Override
156    public Comparator<? super K> comparator() {
157        return decorated().comparator();
158    }
159
160    @Override
161    public SortedMap<K, V> subMap(final K fromKey, final K toKey) {
162        return new UnmodifiableSortedMap<K, V>(decorated().subMap(fromKey, toKey));
163    }
164
165    @Override
166    public SortedMap<K, V> headMap(final K toKey) {
167        return new UnmodifiableSortedMap<K, V>(decorated().headMap(toKey));
168    }
169
170    @Override
171    public SortedMap<K, V> tailMap(final K fromKey) {
172        return new UnmodifiableSortedMap<K, V>(decorated().tailMap(fromKey));
173    }
174
175}