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.set;
018
019import java.io.IOException;
020import java.io.ObjectInputStream;
021import java.io.ObjectOutputStream;
022import java.util.Collection;
023import java.util.Iterator;
024import java.util.NavigableSet;
025import java.util.SortedSet;
026import java.util.function.Predicate;
027
028import org.apache.commons.collections4.Unmodifiable;
029import org.apache.commons.collections4.iterators.UnmodifiableIterator;
030
031/**
032 * Decorates another {@code NavigableSet} to ensure it can't be altered.
033 * <p>
034 * Attempts to modify it will result in an UnsupportedOperationException.
035 * </p>
036 *
037 * @param <E> the type of the elements in this set
038 * @since 4.1
039 */
040public final class UnmodifiableNavigableSet<E>
041        extends AbstractNavigableSetDecorator<E>
042        implements Unmodifiable {
043
044    /** Serialization version */
045    private static final long serialVersionUID = 20150528L;
046
047    /**
048     * Factory method to create an unmodifiable set.
049     *
050     * @param <E> the element type
051     * @param set  the set to decorate, must not be null
052     * @return a new unmodifiable {@link NavigableSet}
053     * @throws NullPointerException if set is null
054     */
055    public static <E> NavigableSet<E> unmodifiableNavigableSet(final NavigableSet<E> set) {
056        if (set instanceof Unmodifiable) {
057            return set;
058        }
059        return new UnmodifiableNavigableSet<>(set);
060    }
061
062    /**
063     * Constructor that wraps (not copies).
064     *
065     * @param set  the set to decorate, must not be null
066     * @throws NullPointerException if set is null
067     */
068    private UnmodifiableNavigableSet(final NavigableSet<E> set) {
069        super(set);
070    }
071
072    @Override
073    public boolean add(final E object) {
074        throw new UnsupportedOperationException();
075    }
076
077    @Override
078    public boolean addAll(final Collection<? extends E> coll) {
079        throw new UnsupportedOperationException();
080    }
081
082    @Override
083    public void clear() {
084        throw new UnsupportedOperationException();
085    }
086
087    @Override
088    public Iterator<E> descendingIterator() {
089        return UnmodifiableIterator.unmodifiableIterator(decorated().descendingIterator());
090    }
091
092    // NavigableSet
093    @Override
094    public NavigableSet<E> descendingSet() {
095        return unmodifiableNavigableSet(decorated().descendingSet());
096    }
097
098    @Override
099    public SortedSet<E> headSet(final E toElement) {
100        final SortedSet<E> head = decorated().headSet(toElement);
101        return UnmodifiableSortedSet.unmodifiableSortedSet(head);
102    }
103
104    @Override
105    public NavigableSet<E> headSet(final E toElement, final boolean inclusive) {
106        final NavigableSet<E> head = decorated().headSet(toElement, inclusive);
107        return unmodifiableNavigableSet(head);
108    }
109
110    @Override
111    public Iterator<E> iterator() {
112        return UnmodifiableIterator.unmodifiableIterator(decorated().iterator());
113    }
114
115    /**
116     * @since 4.5
117     */
118    @Override
119    public E pollFirst() {
120        throw new UnsupportedOperationException();
121    }
122
123    /**
124     * @since 4.5
125     */
126    @Override
127    public E pollLast() {
128        throw new UnsupportedOperationException();
129    }
130
131    /**
132     * Read the collection in using a custom routine.
133     *
134     * @param in  the input stream
135     * @throws IOException if an error occurs while reading from the stream
136     * @throws ClassNotFoundException if an object read from the stream can not be loaded
137     */
138    @SuppressWarnings("unchecked") // (1) should only fail if input stream is incorrect
139    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
140        in.defaultReadObject();
141        setCollection((Collection<E>) in.readObject()); // (1)
142    }
143
144    @Override
145    public boolean remove(final Object object) {
146        throw new UnsupportedOperationException();
147    }
148
149    @Override
150    public boolean removeAll(final Collection<?> coll) {
151        throw new UnsupportedOperationException();
152    }
153
154    /**
155     * @since 4.4
156     */
157    @Override
158    public boolean removeIf(final Predicate<? super E> filter) {
159        throw new UnsupportedOperationException();
160    }
161
162    @Override
163    public boolean retainAll(final Collection<?> coll) {
164        throw new UnsupportedOperationException();
165    }
166
167    @Override
168    public NavigableSet<E> subSet(final E fromElement, final boolean fromInclusive, final E toElement,
169            final boolean toInclusive) {
170        final NavigableSet<E> sub = decorated().subSet(fromElement, fromInclusive, toElement, toInclusive);
171        return unmodifiableNavigableSet(sub);
172    }
173
174    // SortedSet
175    @Override
176    public SortedSet<E> subSet(final E fromElement, final E toElement) {
177        final SortedSet<E> sub = decorated().subSet(fromElement, toElement);
178        return UnmodifiableSortedSet.unmodifiableSortedSet(sub);
179    }
180
181    @Override
182    public SortedSet<E> tailSet(final E fromElement) {
183        final SortedSet<E> tail = decorated().tailSet(fromElement);
184        return UnmodifiableSortedSet.unmodifiableSortedSet(tail);
185    }
186
187    @Override
188    public NavigableSet<E> tailSet(final E fromElement, final boolean inclusive) {
189        final NavigableSet<E> tail = decorated().tailSet(fromElement, inclusive);
190        return unmodifiableNavigableSet(tail);
191    }
192
193    /**
194     * Write the collection out using a custom routine.
195     *
196     * @param out  the output stream
197     * @throws IOException if an error occurs while writing to the stream
198     */
199    private void writeObject(final ObjectOutputStream out) throws IOException {
200        out.defaultWriteObject();
201        out.writeObject(decorated());
202    }
203
204}