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 *      https://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.multimap;
018
019import java.util.Collection;
020import java.util.Map;
021import java.util.Map.Entry;
022import java.util.Set;
023
024import org.apache.commons.collections4.MapIterator;
025import org.apache.commons.collections4.MultiSet;
026import org.apache.commons.collections4.MultiValuedMap;
027import org.apache.commons.collections4.Unmodifiable;
028import org.apache.commons.collections4.collection.UnmodifiableCollection;
029import org.apache.commons.collections4.iterators.UnmodifiableMapIterator;
030import org.apache.commons.collections4.map.UnmodifiableMap;
031import org.apache.commons.collections4.multiset.UnmodifiableMultiSet;
032import org.apache.commons.collections4.set.UnmodifiableSet;
033
034/**
035 * Decorates another {@link MultiValuedMap} to ensure it can't be altered.
036 * <p>
037 * Attempts to modify it will result in an UnsupportedOperationException.
038 * </p>
039 *
040 * @param <K> The type of key elements
041 * @param <V> The type of value elements
042 * @since 4.1
043 */
044public final class UnmodifiableMultiValuedMap<K, V>
045        extends AbstractMultiValuedMapDecorator<K, V> implements Unmodifiable {
046
047    /** Serialization version */
048    private static final long serialVersionUID = 20150612L;
049
050    /**
051     * Factory method to create an unmodifiable MultiValuedMap.
052     * <p>
053     * If the map passed in is already unmodifiable, it is returned.
054     * </p>
055     *
056     * @param <K> The type of key elements
057     * @param <V> The type of value elements
058     * @param map  The map to decorate, may not be null
059     * @return An unmodifiable MultiValuedMap
060     * @throws NullPointerException if map is null
061     */
062    @SuppressWarnings("unchecked")
063    public static <K, V> UnmodifiableMultiValuedMap<K, V> unmodifiableMultiValuedMap(
064            final MultiValuedMap<? extends K, ? extends V> map) {
065        if (map instanceof Unmodifiable) {
066            return (UnmodifiableMultiValuedMap<K, V>) map;
067        }
068        return new UnmodifiableMultiValuedMap<>(map);
069    }
070
071    /**
072     * Constructor that wraps (not copies).
073     *
074     * @param map  The MultiValuedMap to decorate, may not be null
075     * @throws NullPointerException if the map is null
076     */
077    @SuppressWarnings("unchecked")
078    private UnmodifiableMultiValuedMap(final MultiValuedMap<? extends K, ? extends V> map) {
079        super((MultiValuedMap<K, V>) map);
080    }
081
082    @Override
083    public Map<K, Collection<V>> asMap() {
084        return UnmodifiableMap.unmodifiableMap(decorated().asMap());
085    }
086
087    /**
088     * Always throws {@link UnsupportedOperationException}.
089     *
090     * @throws UnsupportedOperationException Always thrown.
091     */
092    @Override
093    public void clear() {
094        throw new UnsupportedOperationException();
095    }
096
097    @Override
098    public Collection<Entry<K, V>> entries() {
099        return UnmodifiableCollection.unmodifiableCollection(decorated().entries());
100    }
101
102    @Override
103    public Collection<V> get(final K key) {
104        return UnmodifiableCollection.unmodifiableCollection(decorated().get(key));
105    }
106
107    @Override
108    public MultiSet<K> keys() {
109        return UnmodifiableMultiSet.unmodifiableMultiSet(decorated().keys());
110    }
111
112    @Override
113    public Set<K> keySet() {
114        return UnmodifiableSet.unmodifiableSet(decorated().keySet());
115    }
116
117    /**
118     * {@inheritDoc}
119     * <p>
120     * The returned map iterator's {@link MapIterator#setValue(Object)} method is not supported
121     * and will throw an {@link UnsupportedOperationException}.
122     * </p>
123     */
124    @Override
125    public MapIterator<K, V> mapIterator() {
126        return UnmodifiableMapIterator.unmodifiableMapIterator(decorated().mapIterator());
127    }
128
129    /**
130     * Always throws {@link UnsupportedOperationException}.
131     *
132     * @param key Ignored.
133     * @throws UnsupportedOperationException Always thrown.
134     */
135    @Override
136    public boolean put(final K key, final V value) {
137        throw new UnsupportedOperationException();
138    }
139
140    /**
141     * Always throws {@link UnsupportedOperationException}.
142     *
143     * @param key Ignored.
144     * @param values Ignored.
145     * @throws UnsupportedOperationException Always thrown.
146     */
147    @Override
148    public boolean putAll(final K key, final Iterable<? extends V> values) {
149        throw new UnsupportedOperationException();
150    }
151
152    /**
153     * Always throws {@link UnsupportedOperationException}.
154     *
155     * @param map Ignored.
156     * @throws UnsupportedOperationException Always thrown.
157     */
158    @Override
159    public boolean putAll(final Map<? extends K, ? extends V> map) {
160        throw new UnsupportedOperationException();
161    }
162
163    /**
164     * Always throws {@link UnsupportedOperationException}.
165     *
166     * @param map Ignored.
167     * @throws UnsupportedOperationException Always thrown.
168     */
169    @Override
170    public boolean putAll(final MultiValuedMap<? extends K, ? extends V> map) {
171        throw new UnsupportedOperationException();
172    }
173
174    /**
175     * Always throws {@link UnsupportedOperationException}.
176     *
177     * @param key Ignored.
178     * @throws UnsupportedOperationException Always thrown.
179     */
180    @Override
181    public Collection<V> remove(final Object key) {
182        throw new UnsupportedOperationException();
183    }
184
185    /**
186     * Always throws {@link UnsupportedOperationException}.
187     *
188     * @param key Ignored.
189     * @param item Ignored.
190     * @throws UnsupportedOperationException Always thrown.
191     */
192    @Override
193    public boolean removeMapping(final Object key, final Object item) {
194        throw new UnsupportedOperationException();
195    }
196
197    @Override
198    public Collection<V> values() {
199        return UnmodifiableCollection.unmodifiableCollection(decorated().values());
200    }
201
202}