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 *      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.apache.commons.collections4.bidimap;
018
019import java.util.Map;
020import java.util.Set;
021
022import org.apache.commons.collections4.OrderedBidiMap;
023import org.apache.commons.collections4.OrderedMapIterator;
024import org.apache.commons.collections4.Unmodifiable;
025import org.apache.commons.collections4.iterators.UnmodifiableOrderedMapIterator;
026import org.apache.commons.collections4.map.UnmodifiableEntrySet;
027import org.apache.commons.collections4.set.UnmodifiableSet;
028
029/**
030 * Decorates another {@link OrderedBidiMap} to ensure it can't be altered.
031 * <p>
032 * Attempts to modify it will result in an UnsupportedOperationException.
033 * </p>
034 *
035 * @param <K> the type of the keys in this map
036 * @param <V> the type of the values in this map
037 * @since 3.0
038 */
039public final class UnmodifiableOrderedBidiMap<K, V>
040        extends AbstractOrderedBidiMapDecorator<K, V> implements Unmodifiable {
041
042    /**
043     * Factory method to create an unmodifiable map.
044     * <p>
045     * If the map passed in is already unmodifiable, it is returned.
046     *
047     * @param <K> the key type
048     * @param <V> the value type
049     * @param map  the map to decorate, must not be null
050     * @return an unmodifiable OrderedBidiMap
051     * @throws NullPointerException if map is null
052     * @since 4.0
053     */
054    public static <K, V> OrderedBidiMap<K, V> unmodifiableOrderedBidiMap(
055            final OrderedBidiMap<? extends K, ? extends V> map) {
056        if (map instanceof Unmodifiable) {
057            @SuppressWarnings("unchecked") // safe to upcast
058            final OrderedBidiMap<K, V> tmpMap = (OrderedBidiMap<K, V>) map;
059            return tmpMap;
060        }
061        return new UnmodifiableOrderedBidiMap<>(map);
062    }
063
064    /** The inverse unmodifiable map */
065    private UnmodifiableOrderedBidiMap<V, K> inverse;
066
067    /**
068     * Constructor that wraps (not copies).
069     *
070     * @param map  the map to decorate, must not be null
071     * @throws NullPointerException if map is null
072     */
073    @SuppressWarnings("unchecked") // safe to upcast
074    private UnmodifiableOrderedBidiMap(final OrderedBidiMap<? extends K, ? extends V> map) {
075        super((OrderedBidiMap<K, V>) map);
076    }
077
078    @Override
079    public void clear() {
080        throw new UnsupportedOperationException();
081    }
082
083    @Override
084    public Set<Map.Entry<K, V>> entrySet() {
085        final Set<Map.Entry<K, V>> set = super.entrySet();
086        return UnmodifiableEntrySet.unmodifiableEntrySet(set);
087    }
088
089    @Override
090    public OrderedBidiMap<V, K> inverseBidiMap() {
091        return inverseOrderedBidiMap();
092    }
093
094    /**
095     * Gets an unmodifiable view of this map where the keys and values are reversed.
096     *
097     * @return an inverted unmodifiable bidirectional map
098     */
099    public OrderedBidiMap<V, K> inverseOrderedBidiMap() {
100        if (inverse == null) {
101            inverse = new UnmodifiableOrderedBidiMap<>(decorated().inverseBidiMap());
102            inverse.inverse = this;
103        }
104        return inverse;
105    }
106
107    @Override
108    public Set<K> keySet() {
109        final Set<K> set = super.keySet();
110        return UnmodifiableSet.unmodifiableSet(set);
111    }
112
113    @Override
114    public OrderedMapIterator<K, V> mapIterator() {
115        final OrderedMapIterator<K, V> it = decorated().mapIterator();
116        return UnmodifiableOrderedMapIterator.unmodifiableOrderedMapIterator(it);
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 K removeValue(final Object value) {
136        throw new UnsupportedOperationException();
137    }
138
139    @Override
140    public Set<V> values() {
141        final Set<V> set = super.values();
142        return UnmodifiableSet.unmodifiableSet(set);
143    }
144
145}