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.trie;
018
019import java.io.Serializable;
020import java.util.Collection;
021import java.util.Collections;
022import java.util.Comparator;
023import java.util.Map;
024import java.util.Objects;
025import java.util.Set;
026import java.util.SortedMap;
027
028import org.apache.commons.collections4.OrderedMapIterator;
029import org.apache.commons.collections4.Trie;
030import org.apache.commons.collections4.Unmodifiable;
031import org.apache.commons.collections4.iterators.UnmodifiableOrderedMapIterator;
032import org.apache.commons.collections4.map.UnmodifiableEntrySet;
033
034/**
035 * An unmodifiable {@link Trie}.
036 *
037 * @param <K> The type of the keys in this map
038 * @param <V> The type of the values in this map
039 * @since 4.0
040 */
041public class UnmodifiableTrie<K, V> implements Trie<K, V>, Serializable, Unmodifiable {
042
043    /** Serialization version */
044    private static final long serialVersionUID = -7156426030315945159L;
045
046    /**
047     * Factory method to create an unmodifiable trie.
048     *
049     * @param <K>  the key type
050     * @param <V>  the value type
051     * @param trie  The trie to decorate, must not be null
052     * @return A new unmodifiable trie
053     * @throws NullPointerException if trie is null
054     */
055    public static <K, V> Trie<K, V> unmodifiableTrie(final Trie<K, ? extends V> trie) {
056        if (trie instanceof Unmodifiable) {
057            @SuppressWarnings("unchecked") // safe to upcast
058            final Trie<K, V> tmpTrie = (Trie<K, V>) trie;
059            return tmpTrie;
060        }
061        return new UnmodifiableTrie<>(trie);
062    }
063
064    /**
065     * The delegate Trie.
066     */
067    private final Trie<K, V> delegate;
068
069    /**
070     * Constructor that wraps (not copies).
071     *
072     * @param trie  The trie to decorate, must not be null
073     * @throws NullPointerException if trie is null
074     */
075    public UnmodifiableTrie(final Trie<K, ? extends V> trie) {
076        @SuppressWarnings("unchecked") // safe to upcast
077        final Trie<K, V> tmpTrie = (Trie<K, V>) Objects.requireNonNull(trie, "trie");
078        this.delegate = tmpTrie;
079    }
080
081    /**
082     * Always throws {@link UnsupportedOperationException}.
083     *
084     * @throws UnsupportedOperationException Always thrown.
085     */
086    @Override
087    public void clear() {
088        throw new UnsupportedOperationException();
089    }
090
091    @Override
092    public Comparator<? super K> comparator() {
093        return delegate.comparator();
094    }
095
096    @Override
097    public boolean containsKey(final Object key) {
098        return delegate.containsKey(key);
099    }
100
101    @Override
102    public boolean containsValue(final Object value) {
103        return delegate.containsValue(value);
104    }
105
106    @Override
107    public Set<Entry<K, V>> entrySet() {
108        return UnmodifiableEntrySet.unmodifiableEntrySet(delegate.entrySet());
109    }
110
111    @Override
112    public boolean equals(final Object obj) {
113        return delegate.equals(obj);
114    }
115
116    @Override
117    public K firstKey() {
118        return delegate.firstKey();
119    }
120
121    @Override
122    public V get(final Object key) {
123        return delegate.get(key);
124    }
125
126    @Override
127    public int hashCode() {
128        return delegate.hashCode();
129    }
130
131    @Override
132    public SortedMap<K, V> headMap(final K toKey) {
133        return Collections.unmodifiableSortedMap(delegate.headMap(toKey));
134    }
135
136    @Override
137    public boolean isEmpty() {
138        return delegate.isEmpty();
139    }
140
141    @Override
142    public Set<K> keySet() {
143        return Collections.unmodifiableSet(delegate.keySet());
144    }
145
146    @Override
147    public K lastKey() {
148        return delegate.lastKey();
149    }
150
151    @Override
152    public OrderedMapIterator<K, V> mapIterator() {
153        final OrderedMapIterator<K, V> it = delegate.mapIterator();
154        return UnmodifiableOrderedMapIterator.unmodifiableOrderedMapIterator(it);
155    }
156
157    @Override
158    public K nextKey(final K key) {
159        return delegate.nextKey(key);
160    }
161
162    @Override
163    public SortedMap<K, V> prefixMap(final K key) {
164        return Collections.unmodifiableSortedMap(delegate.prefixMap(key));
165    }
166
167    @Override
168    public K previousKey(final K key) {
169        return delegate.previousKey(key);
170    }
171
172    /**
173     * Always throws {@link UnsupportedOperationException}.
174     *
175     * @param key Ignored.
176     * @param value Ignored.
177     * @throws UnsupportedOperationException Always thrown.
178     */
179    @Override
180    public V put(final K key, final V value) {
181        throw new UnsupportedOperationException();
182    }
183
184    /**
185     * Always throws {@link UnsupportedOperationException}.
186     *
187     * @param m Ignored.
188     * @throws UnsupportedOperationException Always thrown.
189     */
190    @Override
191    public void putAll(final Map<? extends K, ? extends V> m) {
192        throw new UnsupportedOperationException();
193    }
194
195    /**
196     * Always throws {@link UnsupportedOperationException}.
197     *
198     * @param key Ignored.
199     * @throws UnsupportedOperationException Always thrown.
200     */
201    @Override
202    public V remove(final Object key) {
203        throw new UnsupportedOperationException();
204    }
205
206    @Override
207    public int size() {
208        return delegate.size();
209    }
210
211    @Override
212    public SortedMap<K, V> subMap(final K fromKey, final K toKey) {
213        return Collections.unmodifiableSortedMap(delegate.subMap(fromKey, toKey));
214    }
215
216    @Override
217    public SortedMap<K, V> tailMap(final K fromKey) {
218        return Collections.unmodifiableSortedMap(delegate.tailMap(fromKey));
219    }
220
221    @Override
222    public String toString() {
223        return delegate.toString();
224    }
225
226    @Override
227    public Collection<V> values() {
228        return Collections.unmodifiableCollection(delegate.values());
229    }
230
231}