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.Map;
025import java.util.Set;
026
027import org.apache.commons.collections4.set.UnmodifiableSet;
028import org.apache.commons.collections4.OrderedMap;
029import org.apache.commons.collections4.OrderedMapIterator;
030import org.apache.commons.collections4.Unmodifiable;
031import org.apache.commons.collections4.collection.UnmodifiableCollection;
032import org.apache.commons.collections4.iterators.UnmodifiableOrderedMapIterator;
033
034/**
035 * Decorates another <code>OrderedMap</code> to ensure it can't be altered.
036 * <p>
037 * This class is Serializable from Commons Collections 3.1.
038 * <p>
039 * Attempts to modify it will result in an UnsupportedOperationException.
040 *
041 * @since 3.0
042 * @version $Id: UnmodifiableOrderedMap.html 972421 2015-11-14 20:00:04Z tn $
043 */
044public final class UnmodifiableOrderedMap<K, V> extends AbstractOrderedMapDecorator<K, V> implements
045        Unmodifiable, Serializable {
046
047    /** Serialization version */
048    private static final long serialVersionUID = 8136428161720526266L;
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 ordered map
057     * @throws IllegalArgumentException if map is null
058     * @since 4.0
059     */
060    public static <K, V> OrderedMap<K, V> unmodifiableOrderedMap(final OrderedMap<? extends K, ? extends V> map) {
061        if (map instanceof Unmodifiable) {
062            @SuppressWarnings("unchecked") // safe to upcast
063            final OrderedMap<K, V> tmpMap = (OrderedMap<K, V>) map;
064            return tmpMap;
065        }
066        return new UnmodifiableOrderedMap<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 UnmodifiableOrderedMap(final OrderedMap<? extends K, ? extends V> map) {
078        super((OrderedMap<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") // (1) should only fail if input stream is incorrect
103    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
104        in.defaultReadObject();
105        map = (Map<K, V>) in.readObject(); // (1)
106    }
107
108    //-----------------------------------------------------------------------
109    @Override
110    public OrderedMapIterator<K, V> mapIterator() {
111        final OrderedMapIterator<K, V> it = decorated().mapIterator();
112        return UnmodifiableOrderedMapIterator.unmodifiableOrderedMapIterator(it);
113    }
114
115    @Override
116    public void clear() {
117        throw new UnsupportedOperationException();
118    }
119
120    @Override
121    public V put(final K key, final V value) {
122        throw new UnsupportedOperationException();
123    }
124
125    @Override
126    public void putAll(final Map<? extends K, ? extends V> mapToCopy) {
127        throw new UnsupportedOperationException();
128    }
129
130    @Override
131    public V remove(final Object key) {
132        throw new UnsupportedOperationException();
133    }
134
135    @Override
136    public Set<Map.Entry<K, V>> entrySet() {
137        final Set<Map.Entry<K, V>> set = super.entrySet();
138        return UnmodifiableEntrySet.unmodifiableEntrySet(set);
139    }
140
141    @Override
142    public Set<K> keySet() {
143        final Set<K> set = super.keySet();
144        return UnmodifiableSet.unmodifiableSet(set);
145    }
146
147    @Override
148    public Collection<V> values() {
149        final Collection<V> coll = super.values();
150        return UnmodifiableCollection.unmodifiableCollection(coll);
151    }
152
153}