View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections4.set;
18  
19  import java.util.Iterator;
20  import java.util.NavigableSet;
21  
22  import org.apache.commons.collections4.Transformer;
23  
24  /**
25   * Decorates another {@code NavigableSet} to transform objects that are added.
26   * <p>
27   * The add methods are affected by this class.
28   * Thus objects must be removed or searched for using their transformed form.
29   * For example, if the transformation converts Strings to Integers, you must
30   * use the Integer form to remove objects.
31   * </p>
32   *
33   * @param <E> the type of the elements in this set
34   * @since 4.1
35   */
36  public class TransformedNavigableSet<E> extends TransformedSortedSet<E> implements NavigableSet<E> {
37  
38      /** Serialization version */
39      private static final long serialVersionUID = 20150528L;
40  
41      /**
42       * Factory method to create a transforming navigable set that will transform
43       * existing contents of the specified navigable set.
44       * <p>
45       * If there are any elements already in the set being decorated, they
46       * will be transformed by this method.
47       * Contrast this with {@link #transformingNavigableSet(NavigableSet, Transformer)}.
48       *
49       * @param <E> the element type
50       * @param set  the set to decorate, must not be null
51       * @param transformer  the transformer to use for conversion, must not be null
52       * @return a new transformed {@link NavigableSet}
53       * @throws NullPointerException if set or transformer is null
54       */
55      public static <E> TransformedNavigableSet<E> transformedNavigableSet(final NavigableSet<E> set,
56              final Transformer<? super E, ? extends E> transformer) {
57  
58          final TransformedNavigableSet<E> decorated = new TransformedNavigableSet<>(set, transformer);
59          if (!set.isEmpty()) {
60              @SuppressWarnings("unchecked") // set is type E
61              final E[] values = (E[]) set.toArray(); // NOPMD - false positive for generics
62              set.clear();
63              for (final E value : values) {
64                  decorated.decorated().add(transformer.transform(value));
65              }
66          }
67          return decorated;
68      }
69  
70      /**
71       * Factory method to create a transforming navigable set.
72       * <p>
73       * If there are any elements already in the set being decorated, they
74       * are NOT transformed.
75       * Contrast this with {@link #transformedNavigableSet(NavigableSet, Transformer)}.
76       *
77       * @param <E> the element type
78       * @param set  the set to decorate, must not be null
79       * @param transformer  the transformer to use for conversion, must not be null
80       * @return a new transformed {@link NavigableSet}
81       * @throws NullPointerException if set or transformer is null
82       */
83      public static <E> TransformedNavigableSet<E> transformingNavigableSet(final NavigableSet<E> set,
84              final Transformer<? super E, ? extends E> transformer) {
85          return new TransformedNavigableSet<>(set, transformer);
86      }
87  
88      /**
89       * Constructor that wraps (not copies).
90       * <p>
91       * If there are any elements already in the set being decorated, they
92       * are NOT transformed.
93       *
94       * @param set  the set to decorate, must not be null
95       * @param transformer  the transformer to use for conversion, must not be null
96       * @throws NullPointerException if set or transformer is null
97       */
98      protected TransformedNavigableSet(final NavigableSet<E> set,
99                                        final Transformer<? super E, ? extends E> transformer) {
100         super(set, transformer);
101     }
102 
103     @Override
104     public E ceiling(final E e) {
105         return decorated().ceiling(e);
106     }
107 
108     /**
109      * Gets the decorated navigable set.
110      *
111      * @return the decorated navigable set
112      */
113     @Override
114     protected NavigableSet<E> decorated() {
115         return (NavigableSet<E>) super.decorated();
116     }
117 
118     @Override
119     public Iterator<E> descendingIterator() {
120         return decorated().descendingIterator();
121     }
122 
123     @Override
124     public NavigableSet<E> descendingSet() {
125         return transformingNavigableSet(decorated().descendingSet(), transformer);
126     }
127 
128     @Override
129     public E floor(final E e) {
130         return decorated().floor(e);
131     }
132 
133     @Override
134     public NavigableSet<E> headSet(final E toElement, final boolean inclusive) {
135         final NavigableSet<E> head = decorated().headSet(toElement, inclusive);
136         return transformingNavigableSet(head, transformer);
137     }
138 
139     @Override
140     public E higher(final E e) {
141         return decorated().higher(e);
142     }
143 
144     @Override
145     public E lower(final E e) {
146         return decorated().lower(e);
147     }
148 
149     @Override
150     public E pollFirst() {
151         return decorated().pollFirst();
152     }
153 
154     @Override
155     public E pollLast() {
156         return decorated().pollLast();
157     }
158 
159     @Override
160     public NavigableSet<E> subSet(final E fromElement, final boolean fromInclusive, final E toElement,
161             final boolean toInclusive) {
162         final NavigableSet<E> sub = decorated().subSet(fromElement, fromInclusive, toElement, toInclusive);
163         return transformingNavigableSet(sub, transformer);
164     }
165 
166     @Override
167     public NavigableSet<E> tailSet(final E fromElement, final boolean inclusive) {
168         final NavigableSet<E> tail = decorated().tailSet(fromElement, inclusive);
169         return transformingNavigableSet(tail, transformer);
170     }
171 
172 }