1 /*
  2  * Copyright (c) 2016, 2024, Oracle and/or its affiliates. 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 import java.util.AbstractList;
 25 import java.util.ArrayList;
 26 import java.util.Collection;
 27 import java.util.Collections;
 28 import java.util.HashMap;
 29 import java.util.Iterator;
 30 import java.util.LinkedHashMap;
 31 import java.util.List;
 32 import java.util.Map;
 33 import java.util.RandomAccess;
 34 import java.util.Spliterator;
 35 import java.util.function.Consumer;
 36 import java.util.function.Function;
 37 import java.util.function.Supplier;
 38 
 39 class SpliteratorLateBindingFailFastHelper {
 40 
 41     interface Source<T> {
 42         Spliterator<T> spliterator();
 43 
 44         void update();
 45 
 46         default boolean bindOnCharacteristics() {
 47             return false;
 48         }
 49     }
 50 
 51     static class IntSource<T> implements Source<Integer> {
 52         final T b;
 53         final Function<? super T, Spliterator.OfInt> toSpliterator;
 54         final Consumer<T> updater;
 55         final boolean bindOnCharacteristics;
 56 
 57         public IntSource(T b, Function<? super T, Spliterator.OfInt> toSpliterator,
 58                          Consumer<T> updater) {
 59             this(b, toSpliterator, updater, false);
 60         }
 61 
 62         public IntSource(T b, Function<? super T, Spliterator.OfInt> toSpliterator,
 63                          Consumer<T> updater, boolean bindOnCharacteristics) {
 64             this.b = b;
 65             this.toSpliterator = toSpliterator;
 66             this.updater = updater;
 67             this.bindOnCharacteristics = bindOnCharacteristics;
 68         }
 69 
 70         @Override
 71         public Spliterator.OfInt spliterator() {
 72             return toSpliterator.apply(b);
 73         }
 74 
 75         @Override
 76         public void update() {
 77             updater.accept(b);
 78         }
 79 
 80         @Override
 81         public boolean bindOnCharacteristics() {
 82             return bindOnCharacteristics;
 83         }
 84     }
 85 
 86     static class SpliteratorDataBuilder<T> {
 87         final List<Object[]> data;
 88 
 89         final T newValue;
 90 
 91         final List<T> exp;
 92 
 93         final Map<T, T> mExp;
 94 
 95         SpliteratorDataBuilder(List<Object[]> data, T newValue, List<T> exp) {
 96             this.data = data;
 97             this.newValue = newValue;
 98             this.exp = exp;
 99             this.mExp = createMap(exp);
100         }
101 
102         Map<T, T> createMap(List<T> l) {
103             Map<T, T> m = new LinkedHashMap<>();
104             for (T t : l) {
105                 m.put(t, t);
106             }
107             return m;
108         }
109 
110         void add(String description, Supplier<Source<?>> s) {
111             data.add(new Object[]{description, s});
112         }
113 
114         void addCollection(Function<Collection<T>, ? extends Collection<T>> f) {
115             class CollectionSource implements Source<T> {
116                 final Collection<T> c = f.apply(exp);
117 
118                 final Consumer<Collection<T>> updater;
119 
120                 CollectionSource(Consumer<Collection<T>> updater) {
121                     this.updater = updater;
122                 }
123 
124                 @Override
125                 public Spliterator<T> spliterator() {
126                     return c.spliterator();
127                 }
128 
129                 @Override
130                 public void update() {
131                     updater.accept(c);
132                 }
133             }
134 
135             String description = "new " + f.apply(Collections.<T>emptyList()).getClass().getName() + ".spliterator() ";
136             add(description + "ADD", () -> new CollectionSource(c -> c.add(newValue)));
137             add(description + "REMOVE", () -> new CollectionSource(c -> c.remove(c.iterator().next())));
138         }
139 
140         void addList(Function<Collection<T>, ? extends List<T>> l) {
141             addCollection(l);
142             addCollection(l.andThen(list -> list.subList(0, list.size())));
143         }
144 
145         void addMap(Function<Map<T, T>, ? extends Map<T, T>> mapConstructor) {
146             class MapSource<U> implements Source<U> {
147                 final Map<T, T> m = mapConstructor.apply(mExp);
148 
149                 final Collection<U> c;
150 
151                 final Consumer<Map<T, T>> updater;
152 
153                 MapSource(Function<Map<T, T>, Collection<U>> f, Consumer<Map<T, T>> updater) {
154                     this.c = f.apply(m);
155                     this.updater = updater;
156                 }
157 
158                 @Override
159                 public Spliterator<U> spliterator() {
160                     return c.spliterator();
161                 }
162 
163                 @Override
164                 public void update() {
165                     updater.accept(m);
166                 }
167             }
168 
169             Map<String, Consumer<Map<T, T>>> actions = new HashMap<>();
170             actions.put("ADD", m -> m.put(newValue, newValue));
171             actions.put("REMOVE", m -> m.remove(m.keySet().iterator().next()));
172 
173             String description = "new " + mapConstructor.apply(Collections.<T, T>emptyMap()).getClass().getName();
174             for (Map.Entry<String, Consumer<Map<T, T>>> e : actions.entrySet()) {
175                 add(description + ".keySet().spliterator() " + e.getKey(),
176                     () -> new MapSource<>(m -> m.keySet(), e.getValue()));
177                 add(description + ".values().spliterator() " + e.getKey(),
178                     () -> new MapSource<>(m -> m.values(), e.getValue()));
179                 add(description + ".entrySet().spliterator() " + e.getKey(),
180                     () -> new MapSource<>(m -> m.entrySet(), e.getValue()));
181             }
182         }
183     }
184 
185     static class AbstractRandomAccessListImpl<T> extends AbstractList<T> implements RandomAccess {
186         List<T> l;
187 
188         AbstractRandomAccessListImpl(Collection<T> c) {
189             this.l = new ArrayList<>(c);
190         }
191 
192         @Override
193         public boolean add(T value) {
194             modCount++;
195             return l.add(value);
196         }
197 
198         @Override
199         public Iterator<T> iterator() {
200             return l.iterator();
201         }
202 
203         @Override
204         public T get(int index) {
205             return l.get(index);
206         }
207 
208         @Override
209         public boolean remove(Object o) {
210             modCount++;
211             return l.remove(o);
212         }
213 
214         @Override
215         public int size() {
216             return l.size();
217         }
218 
219         @Override
220         public List<T> subList(int fromIndex, int toIndex) {
221             return l.subList(fromIndex, toIndex);
222         }
223     }
224 }