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</code> 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.
43       * <p>
44       * If there are any elements already in the set being decorated, they
45       * are NOT transformed.
46       * Contrast this with {@link #transformedNavigableSet(NavigableSet, Transformer)}.
47       *
48       * @param <E> the element type
49       * @param set  the set to decorate, must not be null
50       * @param transformer  the transformer to use for conversion, must not be null
51       * @return a new transformed {@link NavigableSet}
52       * @throws NullPointerException if set or transformer is null
53       */
54      public static <E> TransformedNavigableSet<E> transformingNavigableSet(final NavigableSet<E> set,
55              final Transformer<? super E, ? extends E> transformer) {
56          return new TransformedNavigableSet<>(set, transformer);
57      }
58  
59      /**
60       * Factory method to create a transforming navigable set that will transform
61       * existing contents of the specified navigable set.
62       * <p>
63       * If there are any elements already in the set being decorated, they
64       * will be transformed by this method.
65       * Contrast this with {@link #transformingNavigableSet(NavigableSet, Transformer)}.
66       *
67       * @param <E> the element type
68       * @param set  the set to decorate, must not be null
69       * @param transformer  the transformer to use for conversion, must not be null
70       * @return a new transformed {@link NavigableSet}
71       * @throws NullPointerException if set or transformer is null
72       */
73      public static <E> TransformedNavigableSet<E> transformedNavigableSet(final NavigableSet<E> set,
74              final Transformer<? super E, ? extends E> transformer) {
75  
76          final TransformedNavigableSet<E> decorated = new TransformedNavigableSet<>(set, transformer);
77          if (set.size() > 0) {
78              @SuppressWarnings("unchecked") // set is type E
79              final E[] values = (E[]) set.toArray(); // NOPMD - false positive for generics
80              set.clear();
81              for (final E value : values) {
82                  decorated.decorated().add(transformer.transform(value));
83              }
84          }
85          return decorated;
86      }
87  
88      //-----------------------------------------------------------------------
89      /**
90       * Constructor that wraps (not copies).
91       * <p>
92       * If there are any elements already in the set being decorated, they
93       * are NOT transformed.
94       *
95       * @param set  the set to decorate, must not be null
96       * @param transformer  the transformer to use for conversion, must not be null
97       * @throws NullPointerException if set or transformer is null
98       */
99      protected TransformedNavigableSet(final NavigableSet<E> set,
100                                       final Transformer<? super E, ? extends E> transformer) {
101         super(set, transformer);
102     }
103 
104     /**
105      * Gets the decorated navigable set.
106      *
107      * @return the decorated navigable set
108      */
109     @Override
110     protected NavigableSet<E> decorated() {
111         return (NavigableSet<E>) super.decorated();
112     }
113 
114     //-----------------------------------------------------------------------
115 
116     @Override
117     public E lower(final E e) {
118         return decorated().lower(e);
119     }
120 
121     @Override
122     public E floor(final E e) {
123         return decorated().floor(e);
124     }
125 
126     @Override
127     public E ceiling(final E e) {
128         return decorated().ceiling(e);
129     }
130 
131     @Override
132     public E higher(final E e) {
133         return decorated().higher(e);
134     }
135 
136     @Override
137     public E pollFirst() {
138         return decorated().pollFirst();
139     }
140 
141     @Override
142     public E pollLast() {
143         return decorated().pollLast();
144     }
145 
146     @Override
147     public NavigableSet<E> descendingSet() {
148         return transformingNavigableSet(decorated().descendingSet(), transformer);
149     }
150 
151     @Override
152     public Iterator<E> descendingIterator() {
153         return decorated().descendingIterator();
154     }
155 
156     @Override
157     public NavigableSet<E> subSet(final E fromElement, final boolean fromInclusive, final E toElement,
158             final boolean toInclusive) {
159         final NavigableSet<E> sub = decorated().subSet(fromElement, fromInclusive, toElement, toInclusive);
160         return transformingNavigableSet(sub, transformer);
161     }
162 
163     @Override
164     public NavigableSet<E> headSet(final E toElement, final boolean inclusive) {
165         final NavigableSet<E> head = decorated().headSet(toElement, inclusive);
166         return transformingNavigableSet(head, transformer);
167     }
168 
169     @Override
170     public NavigableSet<E> tailSet(final E fromElement, final boolean inclusive) {
171         final NavigableSet<E> tail = decorated().tailSet(fromElement, inclusive);
172         return transformingNavigableSet(tail, transformer);
173     }
174 
175 }