Skip to content

Commit 0768be8

Browse files
Proof-of-concept of write-reporting collection wrappers
1 parent 9450572 commit 0768be8

File tree

8 files changed

+2483
-0
lines changed

8 files changed

+2483
-0
lines changed
Lines changed: 334 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,334 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.ingest;
11+
12+
import java.util.Collection;
13+
import java.util.Comparator;
14+
import java.util.Iterator;
15+
import java.util.List;
16+
import java.util.ListIterator;
17+
import java.util.Spliterator;
18+
import java.util.function.Consumer;
19+
import java.util.function.IntFunction;
20+
import java.util.function.Predicate;
21+
import java.util.function.UnaryOperator;
22+
import java.util.stream.Stream;
23+
24+
import static java.util.Objects.requireNonNull;
25+
26+
/**
27+
* {@link List} implementation for use in {@link WriteReportingWrapper}. This reports write mutations directly on this list, or on derived
28+
* objects such as those returned by calling {@link #iterator} or {@link #subList}. It does <strong>not</strong> report mutations on
29+
* elements contained within the list — although the caller may populate the wrapped list with elements which report their own mutations.
30+
*/
31+
class WriteReportingList<E> implements List<E> {
32+
33+
private final List<E> delegate;
34+
private final Consumer<String> reporter;
35+
private final String label;
36+
37+
WriteReportingList(List<E> delegate, Consumer<String> reporter, String label) {
38+
this.delegate = requireNonNull(delegate);
39+
this.reporter = requireNonNull(reporter);
40+
this.label = label;
41+
}
42+
43+
@Override
44+
public int size() {
45+
return delegate.size();
46+
}
47+
48+
@Override
49+
public boolean isEmpty() {
50+
return delegate.isEmpty();
51+
}
52+
53+
@Override
54+
public boolean contains(Object o) {
55+
return delegate.contains(o);
56+
}
57+
58+
@Override
59+
public Iterator<E> iterator() {
60+
return new WriteReportingIterator(delegate.iterator());
61+
}
62+
63+
@Override
64+
public void forEach(Consumer<? super E> action) {
65+
delegate.forEach(action);
66+
}
67+
68+
@Override
69+
public Object[] toArray() {
70+
return delegate.toArray();
71+
}
72+
73+
@Override
74+
public <E1> E1[] toArray(E1[] a) {
75+
return delegate.toArray(a);
76+
}
77+
78+
@Override
79+
public <E1> E1[] toArray(IntFunction<E1[]> generator) {
80+
return delegate.toArray(generator);
81+
}
82+
83+
@Override
84+
public boolean add(E t) {
85+
reporter.accept(label + ".add(E)");
86+
return delegate.add(t);
87+
}
88+
89+
@Override
90+
public boolean remove(Object o) {
91+
reporter.accept(label + ".remove(Object)");
92+
return delegate.remove(o);
93+
}
94+
95+
@Override
96+
public boolean containsAll(Collection<?> c) {
97+
return delegate.containsAll(c);
98+
}
99+
100+
@Override
101+
public boolean addAll(Collection<? extends E> c) {
102+
reporter.accept(label + ".addAll(Collection<? extends E>)");
103+
return delegate.addAll(c);
104+
}
105+
106+
@Override
107+
public boolean addAll(int index, Collection<? extends E> c) {
108+
reporter.accept(label + ".addAll(int, Collection<? extends E>)");
109+
return delegate.addAll(index, c);
110+
}
111+
112+
@Override
113+
public boolean removeAll(Collection<?> c) {
114+
reporter.accept(label + ".removeAll(Collection<?>)");
115+
return delegate.removeAll(c);
116+
}
117+
118+
@Override
119+
public boolean removeIf(Predicate<? super E> filter) {
120+
reporter.accept(label + ".removeIf(Predicate<? super E>)");
121+
return delegate.removeIf(filter);
122+
}
123+
124+
@Override
125+
public boolean retainAll(Collection<?> c) {
126+
reporter.accept(label + ".retainAll(Collection<?>)");
127+
return delegate.retainAll(c);
128+
}
129+
130+
@Override
131+
public void replaceAll(UnaryOperator<E> operator) {
132+
reporter.accept(label + ".replaceAll(UnaryOperator<E>)");
133+
delegate.replaceAll(operator);
134+
}
135+
136+
@Override
137+
public void sort(Comparator<? super E> c) {
138+
reporter.accept(label + ".sort(Comparator<? super E>)");
139+
delegate.sort(c);
140+
}
141+
142+
@Override
143+
public void clear() {
144+
reporter.accept(label + ".clear()");
145+
delegate.clear();
146+
}
147+
148+
@Override
149+
public E get(int index) {
150+
return delegate.get(index);
151+
}
152+
153+
@Override
154+
public E set(int index, E element) {
155+
reporter.accept(label + ".set(int, E)");
156+
return delegate.set(index, element);
157+
}
158+
159+
@Override
160+
public void add(int index, E element) {
161+
reporter.accept(label + ".add(int, E)");
162+
delegate.add(index, element);
163+
}
164+
165+
@Override
166+
public E remove(int index) {
167+
reporter.accept(label + ".remove(index)");
168+
return delegate.remove(index);
169+
}
170+
171+
@Override
172+
public int indexOf(Object o) {
173+
return delegate.indexOf(o);
174+
}
175+
176+
@Override
177+
public int lastIndexOf(Object o) {
178+
return delegate.lastIndexOf(o);
179+
}
180+
181+
@Override
182+
public ListIterator<E> listIterator() {
183+
return new WriteReportingListIterator(delegate.listIterator());
184+
}
185+
186+
@Override
187+
public ListIterator<E> listIterator(int index) {
188+
return new WriteReportingListIterator(delegate.listIterator(index));
189+
}
190+
191+
@Override
192+
public List<E> subList(int fromIndex, int toIndex) {
193+
return new WriteReportingList<>(delegate.subList(fromIndex, toIndex), reporter, label + ".subList(int, int)");
194+
}
195+
196+
@Override
197+
public Spliterator<E> spliterator() {
198+
return delegate.spliterator();
199+
}
200+
201+
@Override
202+
public Stream<E> stream() {
203+
return delegate.stream();
204+
}
205+
206+
@Override
207+
public Stream<E> parallelStream() {
208+
return delegate.parallelStream();
209+
}
210+
211+
@Override
212+
public void addFirst(E t) {
213+
reporter.accept(label + ".addFirst(E)");
214+
delegate.addFirst(t);
215+
}
216+
217+
@Override
218+
public void addLast(E t) {
219+
reporter.accept(label + ".addLast(E)");
220+
delegate.addLast(t);
221+
}
222+
223+
@Override
224+
public E getFirst() {
225+
return delegate.getFirst();
226+
}
227+
228+
@Override
229+
public E getLast() {
230+
return delegate.getLast();
231+
}
232+
233+
@Override
234+
public E removeFirst() {
235+
reporter.accept(label + ".removeFirst()");
236+
return delegate.removeFirst();
237+
}
238+
239+
@Override
240+
public E removeLast() {
241+
reporter.accept(label + ".removeLast()");
242+
return delegate.removeLast();
243+
}
244+
245+
@Override
246+
public List<E> reversed() {
247+
return new WriteReportingList<>(delegate.reversed(), reporter, label + ".reversed()");
248+
}
249+
250+
@Override
251+
public boolean equals(Object o) {
252+
return delegate.equals(o);
253+
}
254+
255+
@Override
256+
public int hashCode() {
257+
return delegate.hashCode();
258+
}
259+
260+
@Override
261+
public String toString() {
262+
return delegate.toString();
263+
}
264+
265+
private class WriteReportingIterator implements Iterator<E> {
266+
267+
protected final Iterator<E> iteratorDelegate;
268+
269+
WriteReportingIterator(Iterator<E> iteratorDelegate) {
270+
this.iteratorDelegate = iteratorDelegate;
271+
}
272+
273+
@Override
274+
public boolean hasNext() {
275+
return iteratorDelegate.hasNext();
276+
}
277+
278+
@Override
279+
public E next() {
280+
return iteratorDelegate.next();
281+
}
282+
283+
@Override
284+
public void remove() {
285+
reporter.accept(label + ".iterator()...remove()");
286+
iteratorDelegate.remove();
287+
}
288+
289+
@Override
290+
public void forEachRemaining(Consumer<? super E> action) {
291+
iteratorDelegate.forEachRemaining(action);
292+
}
293+
}
294+
295+
private class WriteReportingListIterator extends WriteReportingIterator implements ListIterator<E> {
296+
297+
// N.B. This constructor means we can safely downcast iteratorDelegate to ListIterator<E>:
298+
WriteReportingListIterator(ListIterator<E> iteratorDelegate) {
299+
super(iteratorDelegate);
300+
}
301+
302+
@Override
303+
public boolean hasPrevious() {
304+
return ((ListIterator<E>) iteratorDelegate).hasPrevious();
305+
}
306+
307+
@Override
308+
public E previous() {
309+
return ((ListIterator<E>) iteratorDelegate).previous();
310+
}
311+
312+
@Override
313+
public int nextIndex() {
314+
return ((ListIterator<E>) iteratorDelegate).nextIndex();
315+
}
316+
317+
@Override
318+
public int previousIndex() {
319+
return ((ListIterator<E>) iteratorDelegate).previousIndex();
320+
}
321+
322+
@Override
323+
public void set(E t) {
324+
reporter.accept(label + ".listIterator()...set(E)");
325+
((ListIterator<E>) iteratorDelegate).set(t);
326+
}
327+
328+
@Override
329+
public void add(E t) {
330+
reporter.accept(label + ".listIterator()...add(E)");
331+
((ListIterator<E>) iteratorDelegate).add(t);
332+
}
333+
}
334+
}

0 commit comments

Comments
 (0)