1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.rat.utils;
20
21 import java.io.PrintWriter;
22 import java.util.Collection;
23 import java.util.Comparator;
24 import java.util.Iterator;
25 import java.util.SortedSet;
26 import java.util.Spliterator;
27 import java.util.function.Consumer;
28 import java.util.function.Function;
29 import java.util.function.Predicate;
30 import java.util.stream.Stream;
31
32 import org.apache.rat.api.RatException;
33
34
35
36
37
38 public class ReportingSet<T> implements SortedSet<T> {
39
40 private final SortedSet<T> delegate;
41
42 private Options duplicateOption = Options.IGNORE;
43
44 private Log.Level duplicateLogLevel = Log.Level.WARN;
45
46 private Function<T, String> duplicateFmt = t -> String.format("Duplicate %s detected %s", t.getClass(), t);
47
48 public enum Options { OVERWRITE, IGNORE, FAIL }
49
50
51
52
53
54 public ReportingSet(final SortedSet<T> delegate) {
55 this.delegate = delegate;
56 }
57
58
59
60
61
62
63 public ReportingSet<T> setMsgFormat(final Function<T, String> msgFmt) {
64 duplicateFmt = msgFmt;
65 return this;
66 }
67
68
69
70
71
72
73
74 public ReportingSet<T> setDuplicateOption(final Options state) {
75 this.duplicateOption = state;
76 return this;
77 }
78
79
80
81
82
83
84
85 public ReportingSet<T> setLogLevel(final Log.Level level) {
86 this.duplicateLogLevel = level;
87 return this;
88 }
89
90 private ReportingSet<T> sameConfig(final SortedSet<T> delegate) {
91 ReportingSet<T> result = delegate instanceof ReportingSet ? (ReportingSet<T>) delegate : new ReportingSet<>(delegate);
92 return result.setDuplicateOption(this.duplicateOption).setLogLevel(this.duplicateLogLevel);
93 }
94
95
96
97
98
99
100 public boolean addIfNotPresent(final T e) {
101 return add(false, e);
102 }
103
104 @Override
105 public boolean add(final T e) {
106 return add(true, e);
107 }
108
109
110
111
112
113
114
115 private boolean add(final boolean reportDup, final T e) {
116 if (delegate.contains(e)) {
117 String msg = ReportingSet.this.duplicateFmt.apply(e);
118 if (reportDup) {
119 msg = String.format("%s (action: %s)", msg, duplicateOption);
120 DefaultLog.getInstance().log(duplicateLogLevel, msg);
121 new RatException("just for trace").printStackTrace(new PrintWriter(DefaultLog.getInstance().asWriter()));
122 DefaultLog.getInstance().warn(new RatException("just for trace"));
123 }
124 return switch (duplicateOption) {
125 case FAIL -> throw new IllegalArgumentException(msg);
126 case IGNORE -> false;
127 case OVERWRITE -> {
128 delegate.remove(e);
129 yield delegate.add(e);
130 }
131 };
132 }
133 return delegate.add(e);
134 }
135
136 @Override
137 public boolean addAll(final Collection<? extends T> c) {
138 boolean updated = false;
139 for (T e : c) {
140 updated |= add(e);
141 }
142 return updated;
143 }
144
145 public boolean addAllIfNotPresent(final Collection<? extends T> c) {
146 boolean updated = false;
147 for (T e : c) {
148 updated |= addIfNotPresent(e);
149 }
150 return updated;
151 }
152
153 @Override
154 public void clear() {
155 delegate.clear();
156 }
157
158 @Override
159 public Comparator<? super T> comparator() {
160 return delegate.comparator();
161 }
162
163 @Override
164 public boolean contains(final Object o) {
165 return delegate.contains(o);
166 }
167
168 @Override
169 public boolean containsAll(final Collection<?> c) {
170 return delegate.containsAll(c);
171 }
172
173 @Override
174 public boolean equals(final Object o) {
175 return delegate.equals(o);
176 }
177
178 @Override
179 public T first() {
180 return delegate.first();
181 }
182
183 @Override
184 public void forEach(final Consumer<? super T> action) {
185 delegate.forEach(action);
186 }
187
188 @Override
189 public int hashCode() {
190 return delegate.hashCode();
191 }
192
193 @Override
194 public ReportingSet<T> headSet(final T toElement) {
195 return sameConfig(delegate.headSet(toElement));
196 }
197
198 @Override
199 public boolean isEmpty() {
200 return delegate.isEmpty();
201 }
202
203 @Override
204 public Iterator<T> iterator() {
205 return delegate.iterator();
206 }
207
208 @Override
209 public T last() {
210 return delegate.last();
211 }
212
213 @Override
214 public Stream<T> parallelStream() {
215 return delegate.parallelStream();
216 }
217
218 @Override
219 public boolean remove(final Object o) {
220 return delegate.remove(o);
221 }
222
223 @Override
224 public boolean removeAll(final Collection<?> c) {
225 return delegate.removeAll(c);
226 }
227
228 @Override
229 public boolean removeIf(final Predicate<? super T> filter) {
230 return delegate.removeIf(filter);
231 }
232
233 @Override
234 public boolean retainAll(final Collection<?> c) {
235 return delegate.retainAll(c);
236 }
237
238 @Override
239 public int size() {
240 return delegate.size();
241 }
242
243 @Override
244 public Spliterator<T> spliterator() {
245 return delegate.spliterator();
246 }
247
248 @Override
249 public Stream<T> stream() {
250 return delegate.stream();
251 }
252
253 @Override
254 public ReportingSet<T> subSet(final T fromElement, final T toElement) {
255 return sameConfig(delegate.subSet(fromElement, toElement));
256 }
257
258 @Override
259 public ReportingSet<T> tailSet(final T fromElement) {
260 return sameConfig(delegate.tailSet(fromElement));
261 }
262
263 @Override
264 public Object[] toArray() {
265 return delegate.toArray();
266 }
267
268 @Override
269 public <T> T[] toArray(final T[] a) {
270 return delegate.toArray(a);
271 }
272 }