View Javadoc
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  
19  import java.io.IOException;
20  import java.io.ObjectInputStream;
21  import java.io.ObjectOutputStream;
22  import java.io.Serializable;
23  import java.util.Collection;
24  import java.util.Map;
25  import java.util.Set;
26  
27  import org.apache.commons.collections4.IterableMap;
28  import org.apache.commons.collections4.MapIterator;
29  import org.apache.commons.collections4.Unmodifiable;
30  import org.apache.commons.collections4.collection.UnmodifiableCollection;
31  import org.apache.commons.collections4.iterators.EntrySetMapIterator;
32  import org.apache.commons.collections4.iterators.UnmodifiableMapIterator;
33  import org.apache.commons.collections4.set.UnmodifiableSet;
34  
35  /**
36   * Decorates another <code>Map</code> to ensure it can't be altered.
37   * <p>
38   * This class is Serializable from Commons Collections 3.1.
39   * </p>
40   * <p>
41   * Attempts to modify it will result in an UnsupportedOperationException.
42   * </p>
43   *
44   * @param <K> the type of the keys in this map
45   * @param <V> the type of the values in this map
46   * @since 3.0
47   */
48  public final class UnmodifiableMap<K, V>
49          extends AbstractMapDecorator<K, V>
50          implements Unmodifiable, Serializable {
51  
52      /** Serialization version */
53      private static final long serialVersionUID = 2737023427269031941L;
54  
55      /**
56       * Factory method to create an unmodifiable map.
57       *
58       * @param <K>  the key type
59       * @param <V>  the value type
60       * @param map  the map to decorate, must not be null
61       * @return a new unmodifiable map
62       * @throws NullPointerException if map is null
63       * @since 4.0
64       */
65      public static <K, V> Map<K, V> unmodifiableMap(final Map<? extends K, ? extends V> map) {
66          if (map instanceof Unmodifiable) {
67              @SuppressWarnings("unchecked") // safe to upcast
68              final Map<K, V> tmpMap = (Map<K, V>) map;
69              return tmpMap;
70          }
71          return new UnmodifiableMap<>(map);
72      }
73  
74      //-----------------------------------------------------------------------
75      /**
76       * Constructor that wraps (not copies).
77       *
78       * @param map  the map to decorate, must not be null
79       * @throws NullPointerException if map is null
80       */
81      @SuppressWarnings("unchecked") // safe to upcast
82      private UnmodifiableMap(final Map<? extends K, ? extends V> map) {
83          super((Map<K, V>) map);
84      }
85  
86      //-----------------------------------------------------------------------
87      /**
88       * Write the map out using a custom routine.
89       *
90       * @param out  the output stream
91       * @throws IOException if an error occurs while writing to the stream
92       * @since 3.1
93       */
94      private void writeObject(final ObjectOutputStream out) throws IOException {
95          out.defaultWriteObject();
96          out.writeObject(map);
97      }
98  
99      /**
100      * Read the map in using a custom routine.
101      *
102      * @param in  the input stream
103      * @throws IOException if an error occurs while reading from the stream
104      * @throws ClassNotFoundException if an object read from the stream can not be loaded
105      * @since 3.1
106      */
107     @SuppressWarnings("unchecked")
108     private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
109         in.defaultReadObject();
110         map = (Map<K, V>) in.readObject();
111     }
112 
113     //-----------------------------------------------------------------------
114     @Override
115     public void clear() {
116         throw new UnsupportedOperationException();
117     }
118 
119     @Override
120     public V put(final K key, final V value) {
121         throw new UnsupportedOperationException();
122     }
123 
124     @Override
125     public void putAll(final Map<? extends K, ? extends V> mapToCopy) {
126         throw new UnsupportedOperationException();
127     }
128 
129     @Override
130     public V remove(final Object key) {
131         throw new UnsupportedOperationException();
132     }
133 
134     @Override
135     public MapIterator<K, V> mapIterator() {
136         if (map instanceof IterableMap) {
137             final MapIterator<K, V> it = ((IterableMap<K, V>) map).mapIterator();
138             return UnmodifiableMapIterator.unmodifiableMapIterator(it);
139         }
140         final MapIterator<K, V> it = new EntrySetMapIterator<>(map);
141         return UnmodifiableMapIterator.unmodifiableMapIterator(it);
142     }
143 
144     @Override
145     public Set<Map.Entry<K, V>> entrySet() {
146         final Set<Map.Entry<K, V>> set = super.entrySet();
147         return UnmodifiableEntrySet.unmodifiableEntrySet(set);
148     }
149 
150     @Override
151     public Set<K> keySet() {
152         final Set<K> set = super.keySet();
153         return UnmodifiableSet.unmodifiableSet(set);
154     }
155 
156     @Override
157     public Collection<V> values() {
158         final Collection<V> coll = super.values();
159         return UnmodifiableCollection.unmodifiableCollection(coll);
160     }
161 
162 }