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.apply(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 }