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.util.Iterator; 020import java.util.NavigableSet; 021 022import org.apache.commons.collections4.Transformer; 023 024/** 025 * Decorates another <code>NavigableSet</code> to transform objects that are added. 026 * <p> 027 * The add methods are affected by this class. 028 * Thus objects must be removed or searched for using their transformed form. 029 * For example, if the transformation converts Strings to Integers, you must 030 * use the Integer form to remove objects. 031 * 032 * @param <E> the type of the elements in this set 033 * @since 4.1 034 */ 035public class TransformedNavigableSet<E> extends TransformedSortedSet<E> implements NavigableSet<E> { 036 037 /** Serialization version */ 038 private static final long serialVersionUID = 20150528L; 039 040 /** 041 * Factory method to create a transforming navigable set. 042 * <p> 043 * If there are any elements already in the set being decorated, they 044 * are NOT transformed. 045 * Contrast this with {@link #transformedNavigableSet(NavigableSet, Transformer)}. 046 * 047 * @param <E> the element type 048 * @param set the set to decorate, must not be null 049 * @param transformer the transformer to use for conversion, must not be null 050 * @return a new transformed {@link NavigableSet} 051 * @throws NullPointerException if set or transformer is null 052 */ 053 public static <E> TransformedNavigableSet<E> transformingNavigableSet(final NavigableSet<E> set, 054 final Transformer<? super E, ? extends E> transformer) { 055 return new TransformedNavigableSet<>(set, transformer); 056 } 057 058 /** 059 * Factory method to create a transforming navigable set that will transform 060 * existing contents of the specified navigable set. 061 * <p> 062 * If there are any elements already in the set being decorated, they 063 * will be transformed by this method. 064 * Contrast this with {@link #transformingNavigableSet(NavigableSet, Transformer)}. 065 * 066 * @param <E> the element type 067 * @param set the set to decorate, must not be null 068 * @param transformer the transformer to use for conversion, must not be null 069 * @return a new transformed {@link NavigableSet} 070 * @throws NullPointerException if set or transformer is null 071 */ 072 public static <E> TransformedNavigableSet<E> transformedNavigableSet(final NavigableSet<E> set, 073 final Transformer<? super E, ? extends E> transformer) { 074 075 final TransformedNavigableSet<E> decorated = new TransformedNavigableSet<>(set, transformer); 076 if (set.size() > 0) { 077 @SuppressWarnings("unchecked") // set is type E 078 final E[] values = (E[]) set.toArray(); // NOPMD - false positive for generics 079 set.clear(); 080 for (final E value : values) { 081 decorated.decorated().add(transformer.transform(value)); 082 } 083 } 084 return decorated; 085 } 086 087 //----------------------------------------------------------------------- 088 /** 089 * Constructor that wraps (not copies). 090 * <p> 091 * If there are any elements already in the set being decorated, they 092 * are NOT transformed. 093 * 094 * @param set the set to decorate, must not be null 095 * @param transformer the transformer to use for conversion, must not be null 096 * @throws NullPointerException if set or transformer is null 097 */ 098 protected TransformedNavigableSet(final NavigableSet<E> set, 099 final Transformer<? super E, ? extends E> transformer) { 100 super(set, transformer); 101 } 102 103 /** 104 * Gets the decorated navigable set. 105 * 106 * @return the decorated navigable set 107 */ 108 @Override 109 protected NavigableSet<E> decorated() { 110 return (NavigableSet<E>) super.decorated(); 111 } 112 113 //----------------------------------------------------------------------- 114 115 @Override 116 public E lower(final E e) { 117 return decorated().lower(e); 118 } 119 120 @Override 121 public E floor(final E e) { 122 return decorated().floor(e); 123 } 124 125 @Override 126 public E ceiling(final E e) { 127 return decorated().ceiling(e); 128 } 129 130 @Override 131 public E higher(final E e) { 132 return decorated().higher(e); 133 } 134 135 @Override 136 public E pollFirst() { 137 return decorated().pollFirst(); 138 } 139 140 @Override 141 public E pollLast() { 142 return decorated().pollLast(); 143 } 144 145 @Override 146 public NavigableSet<E> descendingSet() { 147 return transformingNavigableSet(decorated().descendingSet(), transformer); 148 } 149 150 @Override 151 public Iterator<E> descendingIterator() { 152 return decorated().descendingIterator(); 153 } 154 155 @Override 156 public NavigableSet<E> subSet(final E fromElement, final boolean fromInclusive, final E toElement, 157 final boolean toInclusive) { 158 final NavigableSet<E> sub = decorated().subSet(fromElement, fromInclusive, toElement, toInclusive); 159 return transformingNavigableSet(sub, transformer); 160 } 161 162 @Override 163 public NavigableSet<E> headSet(final E toElement, final boolean inclusive) { 164 final NavigableSet<E> head = decorated().headSet(toElement, inclusive); 165 return transformingNavigableSet(head, transformer); 166 } 167 168 @Override 169 public NavigableSet<E> tailSet(final E fromElement, final boolean inclusive) { 170 final NavigableSet<E> tail = decorated().tailSet(fromElement, inclusive); 171 return transformingNavigableSet(tail, transformer); 172 } 173 174}