1 /* 2 * Copyright (c) 2018 Google Inc. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @run junit DelegatingIteratorForEachRemaining 27 */ 28 29 package test.java.util.Collections; 30 31 import org.junit.Assert; 32 import org.junit.Test; 33 34 import java.util.Collection; 35 import java.util.Collections; 36 import java.util.HashMap; 37 import java.util.Iterator; 38 import java.util.Map; 39 import java.util.Objects; 40 import java.util.Set; 41 import java.util.Spliterator; 42 import java.util.function.BiConsumer; 43 import java.util.function.BiFunction; 44 import java.util.function.Consumer; 45 import java.util.function.Function; 46 import java.util.function.Predicate; 47 import java.util.stream.Stream; 48 49 public class DelegatingIteratorForEachRemaining { 50 51 static abstract class ForwardingIterator<E> implements Iterator<E> { 52 private final Iterator<E> delegate; 53 ForwardingIterator(Iterator<E> delegate)54 protected ForwardingIterator(Iterator<E> delegate) { 55 this.delegate = Objects.requireNonNull(delegate); 56 } 57 hasNext()58 @Override public boolean hasNext() { return delegate.hasNext(); } next()59 @Override public E next() { return delegate.next(); } remove()60 @Override public void remove() { delegate.remove(); } forEachRemaining(Consumer<? super E> action)61 @Override public void forEachRemaining(Consumer<? super E> action) { 62 delegate.forEachRemaining(action); 63 } 64 } 65 66 static final class ThrowingIterator<E> extends ForwardingIterator<E> { ThrowingIterator(Iterator<E> delegate)67 public ThrowingIterator(Iterator<E> delegate) { 68 super(delegate); 69 } 70 71 @Override forEachRemaining(Consumer<? super E> action)72 public void forEachRemaining(Consumer<? super E> action) { 73 throw new UnsupportedOperationException(); 74 } 75 } 76 77 static abstract class ForwardingSet<E> implements Set<E> { 78 private final Set<E> delegate; 79 ForwardingSet(Set<E> delegate)80 protected ForwardingSet(Set<E> delegate) { 81 this.delegate = Objects.requireNonNull(delegate); 82 } 83 size()84 @Override public int size() { return delegate.size(); } isEmpty()85 @Override public boolean isEmpty() { return delegate.isEmpty(); } contains(Object o)86 @Override public boolean contains(Object o) { return delegate.contains(o); } iterator()87 @Override public Iterator<E> iterator() { return delegate.iterator(); } toArray()88 @Override public Object[] toArray() { return delegate.toArray(); } toArray( T[] ts)89 @Override public <T> T[] toArray( T[] ts) { return delegate.toArray(ts); } add(E e)90 @Override public boolean add(E e) { return delegate.add(e); } remove(Object o)91 @Override public boolean remove(Object o) { return delegate.remove(o); } containsAll( Collection<?> c)92 @Override public boolean containsAll( Collection<?> c) { return delegate.containsAll(c); } addAll( Collection<? extends E> c)93 @Override public boolean addAll( Collection<? extends E> c) { return delegate.addAll(c); } retainAll( Collection<?> c)94 @Override public boolean retainAll( Collection<?> c) { return delegate.retainAll(c); } removeAll( Collection<?> c)95 @Override public boolean removeAll( Collection<?> c) { return delegate.removeAll(c); } clear()96 @Override public void clear() { delegate.clear(); } equals(Object o)97 @Override public boolean equals(Object o) { return delegate.equals(o); } hashCode()98 @Override public int hashCode() { return delegate.hashCode(); } spliterator()99 @Override public Spliterator<E> spliterator() { return delegate.spliterator(); } removeIf(Predicate<? super E> filter)100 @Override public boolean removeIf(Predicate<? super E> filter) { return delegate.removeIf(filter); } stream()101 @Override public Stream<E> stream() { return delegate.stream(); } parallelStream()102 @Override public Stream<E> parallelStream() { return delegate.parallelStream(); } forEach(Consumer<? super E> action)103 @Override public void forEach(Consumer<? super E> action) { delegate.forEach(action); } 104 } 105 106 static class ThrowingSet<E> extends ForwardingSet<E> { ThrowingSet(Set<E> delegate)107 public ThrowingSet(Set<E> delegate) { 108 super(delegate); 109 } 110 111 @Override iterator()112 public ThrowingIterator<E> iterator() { 113 return new ThrowingIterator<>(super.iterator()); 114 } 115 } 116 117 static abstract class ForwardingMap<K, V> implements Map<K, V> { 118 private final Map<K, V> delegate; 119 ForwardingMap(Map<K, V> delegate)120 public ForwardingMap(Map<K, V> delegate) { 121 this.delegate = delegate; 122 } 123 size()124 @Override public int size() { return delegate.size(); } isEmpty()125 @Override public boolean isEmpty() { return delegate.isEmpty(); } containsKey(Object o)126 @Override public boolean containsKey(Object o) { return delegate.containsKey(o); } containsValue(Object o)127 @Override public boolean containsValue(Object o) { return delegate.containsValue(o); } get(Object o)128 @Override public V get(Object o) { return delegate.get(o); } put(K k, V v)129 @Override public V put(K k, V v) { return delegate.put(k, v); } remove(Object o)130 @Override public V remove(Object o) { return delegate.remove(o); } putAll(Map<? extends K, ? extends V> map)131 @Override public void putAll(Map<? extends K, ? extends V> map) { delegate.putAll(map); } clear()132 @Override public void clear() { delegate.clear(); } keySet()133 @Override public Set<K> keySet() { return delegate.keySet(); } values()134 @Override public Collection<V> values() { return delegate.values(); } entrySet()135 @Override public Set<Entry<K, V>> entrySet() { return delegate.entrySet(); } equals(Object o)136 @Override public boolean equals(Object o) { return delegate.equals(o); } hashCode()137 @Override public int hashCode() { return delegate.hashCode(); } getOrDefault(Object key, V defaultValue)138 @Override public V getOrDefault(Object key, V defaultValue) { return delegate.getOrDefault(key, defaultValue); } forEach(BiConsumer<? super K, ? super V> action)139 @Override public void forEach(BiConsumer<? super K, ? super V> action) { delegate.forEach(action); } replaceAll(BiFunction<? super K, ? super V, ? extends V> function)140 @Override public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { delegate.replaceAll(function); } putIfAbsent(K key, V value)141 @Override public V putIfAbsent(K key, V value) { return delegate.putIfAbsent(key, value); } remove(Object key, Object value)142 @Override public boolean remove(Object key, Object value) { return delegate.remove(key, value); } replace(K key, V oldValue, V newValue)143 @Override public boolean replace(K key, V oldValue, V newValue) { return delegate.replace(key, oldValue, newValue); } replace(K key, V value)144 @Override public V replace(K key, V value) { return delegate.replace(key, value); } computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)145 @Override public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) { return delegate.computeIfAbsent(key, mappingFunction); } computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)146 @Override public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { return delegate.computeIfPresent(key, remappingFunction); } compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)147 @Override public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { return delegate.compute(key, remappingFunction); } merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction)148 @Override public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) { return delegate.merge(key, value, remappingFunction); } 149 } 150 151 static class ThrowingMap<K, V> extends ForwardingMap<K, V> { ThrowingMap(Map<K, V> delegate)152 public ThrowingMap(Map<K, V> delegate) { 153 super(delegate); 154 } 155 156 @Override entrySet()157 public ThrowingSet<Entry<K, V>> entrySet() { 158 return new ThrowingSet<>(super.entrySet()); 159 } 160 161 @Override keySet()162 public Set<K> keySet() { 163 return new ThrowingSet(super.keySet()); 164 } 165 } 166 assertThrowingIterator(Iterator<E> iterator)167 static<E> void assertThrowingIterator(Iterator<E> iterator) { 168 try { 169 iterator.forEachRemaining((entry) -> {}); 170 Assert.fail(); 171 } catch (UnsupportedOperationException expected) { 172 } 173 } 174 map()175 private static Map<String, Object> map() { 176 Map<String, Object> map = new HashMap<>(); 177 map.put("name", "Bill"); 178 map.put("age", 23); 179 return new ThrowingMap<>(map); 180 } 181 testUnwrapped()182 @Test public void testUnwrapped() { 183 assertThrowingIterator(map().entrySet().iterator()); 184 assertThrowingIterator(map().keySet().iterator()); 185 } 186 test_unmodifiableMap_entrySet()187 @Test public void test_unmodifiableMap_entrySet() { 188 assertThrowingIterator(Collections.unmodifiableMap(map()).entrySet().iterator()); 189 } 190 test_checkedMap_entrySet()191 @Test public void test_checkedMap_entrySet() { 192 assertThrowingIterator(Collections.checkedMap(map(), String.class, Object.class).entrySet().iterator()); 193 } 194 test_entrySet_checkedSet()195 @Test public void test_entrySet_checkedSet() { 196 Set<Map.Entry<String, Object>> entrySet = map().entrySet(); 197 Class clazz = entrySet.iterator().next().getClass(); 198 assertThrowingIterator(Collections.checkedSet(entrySet, clazz).iterator()); 199 } 200 } 201