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 * https://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} 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 * Constructor that wraps (not copies).
76 *
77 * @param map The map to decorate, must not be null
78 * @throws NullPointerException if map is null
79 */
80 @SuppressWarnings("unchecked") // safe to upcast
81 private UnmodifiableMap(final Map<? extends K, ? extends V> map) {
82 super((Map<K, V>) map);
83 }
84
85 /**
86 * Always throws {@link UnsupportedOperationException}.
87 *
88 * @throws UnsupportedOperationException Always thrown.
89 */
90 @Override
91 public void clear() {
92 throw new UnsupportedOperationException();
93 }
94
95 @Override
96 public Set<Map.Entry<K, V>> entrySet() {
97 return UnmodifiableEntrySet.unmodifiableEntrySet(super.entrySet());
98 }
99
100 @Override
101 public Set<K> keySet() {
102 final Set<K> set = super.keySet();
103 return UnmodifiableSet.unmodifiableSet(set);
104 }
105
106 @Override
107 public MapIterator<K, V> mapIterator() {
108 if (map instanceof IterableMap) {
109 final MapIterator<K, V> it = ((IterableMap<K, V>) map).mapIterator();
110 return UnmodifiableMapIterator.unmodifiableMapIterator(it);
111 }
112 final MapIterator<K, V> it = new EntrySetMapIterator<>(map);
113 return UnmodifiableMapIterator.unmodifiableMapIterator(it);
114 }
115
116 /**
117 * Always throws {@link UnsupportedOperationException}.
118 *
119 * @param key Ignored.
120 * @param value Ignored.
121 * @throws UnsupportedOperationException Always thrown.
122 */
123 @Override
124 public V put(final K key, final V value) {
125 throw new UnsupportedOperationException();
126 }
127
128 /**
129 * Always throws {@link UnsupportedOperationException}.
130 *
131 * @param mapToCopy Ignored.
132 * @throws UnsupportedOperationException Always thrown.
133 */
134 @Override
135 public void putAll(final Map<? extends K, ? extends V> mapToCopy) {
136 throw new UnsupportedOperationException();
137 }
138
139 /**
140 * Deserializes the map in using a custom routine.
141 *
142 * @param in The input stream
143 * @throws IOException Thrown if an error occurs while reading from the stream
144 * @throws ClassNotFoundException if an object read from the stream cannot be loaded
145 * @since 3.1
146 */
147 @SuppressWarnings("unchecked")
148 private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
149 in.defaultReadObject();
150 map = (Map<K, V>) in.readObject();
151 }
152
153 /**
154 * Always throws {@link UnsupportedOperationException}.
155 *
156 * @param key Ignored.
157 * @throws UnsupportedOperationException Always thrown.
158 */
159 @Override
160 public V remove(final Object key) {
161 throw new UnsupportedOperationException();
162 }
163
164 @Override
165 public Collection<V> values() {
166 return UnmodifiableCollection.unmodifiableCollection(super.values());
167 }
168
169 /**
170 * Serializes this object to an ObjectOutputStream.
171 *
172 * @param out The target ObjectOutputStream.
173 * @throws IOException thrown when an I/O errors occur writing to the target stream.
174 * @since 3.1
175 */
176 private void writeObject(final ObjectOutputStream out) throws IOException {
177 out.defaultWriteObject();
178 out.writeObject(map);
179 }
180
181 }