001/*-------------------------------------------------------------------------+
002|                                                                          |
003| Copyright 2005-2011 The ConQAT Project                                   |
004|                                                                          |
005| Licensed under the Apache License, Version 2.0 (the "License");          |
006| you may not use this file except in compliance with the License.         |
007| 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.conqat.lib.commons.collections;
018
019import java.io.Serializable;
020import java.util.Collections;
021import java.util.Map;
022
023/**
024 * This is a wrapper for a {@link Map} prohibiting all calls which would modify
025 * its contents. As the construction of this class is performed in constant time
026 * it is prefered over copying the map (which takes linear time). Using this
027 * class is also preferred to using the <code>unmodifiableX()</code> in class
028 * {@link Collections} as they return the collection base type that does not
029 * signal, that the object ist unmodifiable. Using the classes in this package
030 * makes unmodifiability more explicit.
031 * <p>
032 * All prohibited methods throw an {@link UnsupportedOperationException}. The
033 * class is nearly the same as the one returned by
034 * {@link Collections#unmodifiableMap(Map)}, but by making it a public class we
035 * can make the return value of some methods more explicit.
036 * <p>
037 * This map is serializable if the wrapped map is serializable.
038 */
039public class UnmodifiableMap<K, V> implements Map<K, V>, Serializable {
040
041        /** Version used for serialization. */
042        private static final long serialVersionUID = 1;
043
044        /** The underlying map. */
045        private final Map<K, V> map;
046
047        /**
048         * Creates a new unmodifiable map from another map. All modifications to the
049         * underlying map will directly be visible in this wrapper.
050         */
051        public UnmodifiableMap(Map<K, V> m) {
052                if (m == null) {
053                        throw new IllegalArgumentException("Underlying map may not be null!");
054                }
055                this.map = m;
056        }
057
058        /** {@inheritDoc} */
059        @Override
060        public boolean isEmpty() {
061                return map.isEmpty();
062        }
063
064        /** {@inheritDoc} */
065        @Override
066        public int size() {
067                return map.size();
068        }
069
070        /** {@inheritDoc} */
071        @Override
072        public boolean containsKey(Object key) {
073                return map.containsKey(key);
074        }
075
076        /** {@inheritDoc} */
077        @Override
078        public boolean containsValue(Object value) {
079                return map.containsValue(value);
080        }
081
082        /** {@inheritDoc} */
083        @Override
084        public V get(Object key) {
085                return map.get(key);
086        }
087
088        /** {@inheritDoc} */
089        @Override
090        public UnmodifiableSet<K> keySet() {
091                return new UnmodifiableSet<K>(map.keySet());
092        }
093
094        /** {@inheritDoc} */
095        @Override
096        public UnmodifiableCollection<V> values() {
097                return new UnmodifiableCollection<V>(map.values());
098        }
099
100        /** {@inheritDoc} */
101        @Override
102        public UnmodifiableSet<java.util.Map.Entry<K, V>> entrySet() {
103                return new UnmodifiableSet<java.util.Map.Entry<K, V>>(map.entrySet());
104        }
105
106        /** Operation is not supported. */
107        @Override
108        public void clear() {
109                throw new UnsupportedOperationException();
110        }
111
112        /** Operation is not supported. */
113        @Override
114        public V put(K arg0, V arg1) {
115                throw new UnsupportedOperationException();
116        }
117
118        /** Operation is not supported. */
119        @Override
120        public void putAll(Map<? extends K, ? extends V> arg0) {
121                throw new UnsupportedOperationException();
122        }
123
124        /** Operation is not supported. */
125        @Override
126        public V remove(Object arg0) {
127                throw new UnsupportedOperationException();
128        }
129
130        /**
131         * Returns a string representation of this map.
132         */
133        @Override
134        public String toString() {
135                return map.toString();
136        }
137
138        /** {@inheritDoc} */
139        @Override
140        public boolean equals(Object obj) {
141                if (this == obj) {
142                        return true;
143                }
144                if (obj instanceof UnmodifiableMap<?, ?>) {
145                        return map.equals(((UnmodifiableMap<?, ?>) obj).map);
146                }
147                return map.equals(obj);
148        }
149
150        /** {@inheritDoc} */
151        @Override
152        public int hashCode() {
153                return map.hashCode();
154        }
155}