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 }