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.Comparator;
25 import java.util.Map;
26 import java.util.Set;
27 import java.util.SortedMap;
28
29 import org.apache.commons.collections4.Unmodifiable;
30 import org.apache.commons.collections4.collection.UnmodifiableCollection;
31 import org.apache.commons.collections4.set.UnmodifiableSet;
32
33 /**
34 * Decorates another {@code SortedMap} to ensure it can't be altered.
35 * <p>
36 * This class is Serializable from Commons Collections 3.1.
37 * </p>
38 * <p>
39 * Attempts to modify it will result in an UnsupportedOperationException.
40 * </p>
41 *
42 * @param <K> The type of the keys in this map
43 * @param <V> The type of the values in this map
44 * @since 3.0
45 */
46 public final class UnmodifiableSortedMap<K, V>
47 extends AbstractSortedMapDecorator<K, V>
48 implements Unmodifiable, Serializable {
49
50 /** Serialization version */
51 private static final long serialVersionUID = 5805344239827376360L;
52
53 /**
54 * Factory method to create an unmodifiable sorted map.
55 *
56 * @param <K> the key type
57 * @param <V> the value type
58 * @param map The map to decorate, must not be null
59 * @return A new unmodifiable sorted map
60 * @throws NullPointerException if map is null
61 * @since 4.0
62 */
63 public static <K, V> SortedMap<K, V> unmodifiableSortedMap(final SortedMap<K, ? extends V> map) {
64 if (map instanceof Unmodifiable) {
65 @SuppressWarnings("unchecked") // safe to upcast
66 final SortedMap<K, V> tmpMap = (SortedMap<K, V>) map;
67 return tmpMap;
68 }
69 return new UnmodifiableSortedMap<>(map);
70 }
71
72 /**
73 * Constructor that wraps (not copies).
74 *
75 * @param map The map to decorate, must not be null
76 * @throws NullPointerException if map is null
77 */
78 @SuppressWarnings("unchecked") // safe to upcast
79 private UnmodifiableSortedMap(final SortedMap<K, ? extends V> map) {
80 super((SortedMap<K, V>) map);
81 }
82
83 /**
84 * Always throws {@link UnsupportedOperationException}.
85 *
86 * @throws UnsupportedOperationException Always thrown.
87 */
88 @Override
89 public void clear() {
90 throw new UnsupportedOperationException();
91 }
92
93 @Override
94 public Comparator<? super K> comparator() {
95 return decorated().comparator();
96 }
97
98 @Override
99 public Set<Map.Entry<K, V>> entrySet() {
100 return UnmodifiableEntrySet.unmodifiableEntrySet(super.entrySet());
101 }
102
103 @Override
104 public K firstKey() {
105 return decorated().firstKey();
106 }
107
108 @Override
109 public SortedMap<K, V> headMap(final K toKey) {
110 return new UnmodifiableSortedMap<>(decorated().headMap(toKey));
111 }
112
113 @Override
114 public Set<K> keySet() {
115 return UnmodifiableSet.unmodifiableSet(super.keySet());
116 }
117
118 @Override
119 public K lastKey() {
120 return decorated().lastKey();
121 }
122
123 /**
124 * Always throws {@link UnsupportedOperationException}.
125 *
126 * @param key Ignored.
127 * @param value Ignored.
128 * @throws UnsupportedOperationException Always thrown.
129 */
130 @Override
131 public V put(final K key, final V value) {
132 throw new UnsupportedOperationException();
133 }
134
135 /**
136 * Always throws {@link UnsupportedOperationException}.
137 *
138 * @param mapToCopy Ignored.
139 * @throws UnsupportedOperationException Always thrown.
140 */
141 @Override
142 public void putAll(final Map<? extends K, ? extends V> mapToCopy) {
143 throw new UnsupportedOperationException();
144 }
145
146 /**
147 * Deserializes the map in using a custom routine.
148 *
149 * @param in The input stream
150 * @throws IOException Thrown if an error occurs while reading from the stream
151 * @throws ClassNotFoundException if an object read from the stream cannot be loaded
152 * @since 3.1
153 */
154 @SuppressWarnings("unchecked")
155 private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
156 in.defaultReadObject();
157 map = (Map<K, V>) in.readObject();
158 }
159
160 /**
161 * Always throws {@link UnsupportedOperationException}.
162 *
163 * @param key Ignored.
164 * @throws UnsupportedOperationException Always thrown.
165 */
166 @Override
167 public V remove(final Object key) {
168 throw new UnsupportedOperationException();
169 }
170
171 @Override
172 public SortedMap<K, V> subMap(final K fromKey, final K toKey) {
173 return new UnmodifiableSortedMap<>(decorated().subMap(fromKey, toKey));
174 }
175
176 @Override
177 public SortedMap<K, V> tailMap(final K fromKey) {
178 return new UnmodifiableSortedMap<>(decorated().tailMap(fromKey));
179 }
180
181 @Override
182 public Collection<V> values() {
183 return UnmodifiableCollection.unmodifiableCollection(super.values());
184 }
185
186 /**
187 * Serializes this object to an ObjectOutputStream.
188 *
189 * @param out The target ObjectOutputStream.
190 * @throws IOException thrown when an I/O errors occur writing to the target stream.
191 * @since 3.1
192 */
193 private void writeObject(final ObjectOutputStream out) throws IOException {
194 out.defaultWriteObject();
195 out.writeObject(map);
196 }
197
198 }