1 | /* |
---|---|
2 | * Copyright (C) 2007-2010 JĂșlio Vilmar Gesser. |
3 | * Copyright (C) 2011, 2013-2020 The JavaParser Team. |
4 | * |
5 | * This file is part of JavaParser. |
6 | * |
7 | * JavaParser can be used either under the terms of |
8 | * a) the GNU Lesser General Public License as published by |
9 | * the Free Software Foundation, either version 3 of the License, or |
10 | * (at your option) any later version. |
11 | * b) the terms of the Apache License |
12 | * |
13 | * You should have received a copy of both licenses in LICENCE.LGPL and |
14 | * LICENCE.APACHE. Please refer to those files for details. |
15 | * |
16 | * JavaParser is distributed in the hope that it will be useful, |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
19 | * GNU Lesser General Public License for more details. |
20 | */ |
21 | |
22 | package com.github.javaparser.utils; |
23 | |
24 | import java.util.ArrayList; |
25 | import java.util.Collection; |
26 | import java.util.Iterator; |
27 | import java.util.List; |
28 | import java.util.ListIterator; |
29 | import java.util.stream.Collectors; |
30 | |
31 | import com.github.javaparser.ast.Node; |
32 | import com.github.javaparser.ast.visitor.GenericVisitor; |
33 | import com.github.javaparser.ast.visitor.Visitable; |
34 | import com.github.javaparser.ast.visitor.VoidVisitor; |
35 | |
36 | /** |
37 | * A list that overrides the equals and hashcode calculation of the added nodes |
38 | * by using another equals and hashcode visitor for those methods. |
39 | */ |
40 | public class VisitorList<N extends Node> implements List<N> { |
41 | |
42 | protected List<EqualsHashcodeOverridingFacade> innerList; |
43 | protected final GenericVisitor<Integer, Void> hashcodeVisitor; |
44 | protected final GenericVisitor<Boolean, Visitable> equalsVisitor; |
45 | |
46 | /** |
47 | * Pass the visitors to use for equals and hashcode. |
48 | */ |
49 | public VisitorList(GenericVisitor<Integer, Void> hashcodeVisitor, |
50 | GenericVisitor<Boolean, Visitable> equalsVisitor) { |
51 | this.hashcodeVisitor = hashcodeVisitor; |
52 | this.equalsVisitor = equalsVisitor; |
53 | innerList = new ArrayList<>(); |
54 | } |
55 | |
56 | @Override |
57 | public boolean add(N elem) { |
58 | return innerList.add(new EqualsHashcodeOverridingFacade(elem)); |
59 | } |
60 | |
61 | @Override |
62 | public void add(int index, N elem) { |
63 | innerList.add(index, new EqualsHashcodeOverridingFacade(elem)); |
64 | } |
65 | |
66 | @Override |
67 | public boolean addAll(Collection<? extends N> col) { |
68 | boolean modified = false; |
69 | for (N elem : col) |
70 | if (add(elem)) |
71 | modified = true; |
72 | return modified; |
73 | } |
74 | |
75 | @Override |
76 | public boolean addAll(int index, Collection<? extends N> col) { |
77 | if (col.isEmpty()) |
78 | return false; |
79 | for (N elem : col) { |
80 | if (index == size()) |
81 | add(elem); |
82 | else |
83 | add(index, elem); |
84 | index++; |
85 | } |
86 | return true; |
87 | } |
88 | |
89 | @Override |
90 | public void clear() { |
91 | innerList.clear(); |
92 | } |
93 | |
94 | @Override |
95 | public boolean contains(Object elem) { |
96 | return innerList.contains(new EqualsHashcodeOverridingFacade((N) elem)); |
97 | } |
98 | |
99 | @Override |
100 | public boolean containsAll(Collection<?> col) { |
101 | for (Object elem : col) |
102 | if (!contains(elem)) |
103 | return false; |
104 | return true; |
105 | } |
106 | |
107 | @Override |
108 | public N get(int index) { |
109 | return innerList.get(index).overridden; |
110 | } |
111 | |
112 | @Override |
113 | public int indexOf(Object elem) { |
114 | return innerList.indexOf(new EqualsHashcodeOverridingFacade((N) elem)); |
115 | } |
116 | |
117 | @Override |
118 | public boolean isEmpty() { |
119 | return innerList.isEmpty(); |
120 | } |
121 | |
122 | @Override |
123 | public Iterator<N> iterator() { |
124 | return new Iterator<N>() { |
125 | final Iterator<EqualsHashcodeOverridingFacade> itr = innerList.iterator(); |
126 | |
127 | @Override |
128 | public boolean hasNext() { |
129 | return itr.hasNext(); |
130 | } |
131 | |
132 | @Override |
133 | public N next() { |
134 | return itr.next().overridden; |
135 | } |
136 | |
137 | @Override |
138 | public void remove() { |
139 | itr.remove(); |
140 | } |
141 | }; |
142 | } |
143 | |
144 | @Override |
145 | public int lastIndexOf(Object elem) { |
146 | return innerList.lastIndexOf(new EqualsHashcodeOverridingFacade((N) elem)); |
147 | } |
148 | |
149 | @Override |
150 | public ListIterator<N> listIterator() { |
151 | return listIterator(0); |
152 | } |
153 | |
154 | @Override |
155 | public ListIterator<N> listIterator(int index) { |
156 | return new ListIterator<N>() { |
157 | final ListIterator<EqualsHashcodeOverridingFacade> itr = innerList.listIterator(index); |
158 | |
159 | @Override |
160 | public boolean hasNext() { |
161 | return itr.hasNext(); |
162 | } |
163 | |
164 | @Override |
165 | public N next() { |
166 | return itr.next().overridden; |
167 | } |
168 | |
169 | @Override |
170 | public void remove() { |
171 | itr.remove(); |
172 | } |
173 | |
174 | @Override |
175 | public void add(N elem) { |
176 | itr.add(new EqualsHashcodeOverridingFacade((N) elem)); |
177 | } |
178 | |
179 | @Override |
180 | public boolean hasPrevious() { |
181 | return itr.hasPrevious(); |
182 | } |
183 | |
184 | @Override |
185 | public int nextIndex() { |
186 | return itr.nextIndex(); |
187 | } |
188 | |
189 | @Override |
190 | public N previous() { |
191 | return itr.previous().overridden; |
192 | } |
193 | |
194 | @Override |
195 | public int previousIndex() { |
196 | return itr.previousIndex(); |
197 | } |
198 | |
199 | @Override |
200 | public void set(N elem) { |
201 | itr.set(new EqualsHashcodeOverridingFacade((N) elem)); |
202 | } |
203 | }; |
204 | } |
205 | |
206 | @Override |
207 | public boolean remove(Object elem) { |
208 | return innerList.remove(new EqualsHashcodeOverridingFacade((N) elem)); |
209 | } |
210 | |
211 | @Override |
212 | public N remove(int index) { |
213 | return innerList.remove(index).overridden; |
214 | } |
215 | |
216 | @Override |
217 | public boolean removeAll(Collection<?> col) { |
218 | boolean modified = false; |
219 | for (Object elem : col) |
220 | if (remove(elem)) |
221 | modified = true; |
222 | return modified; |
223 | } |
224 | |
225 | @Override |
226 | public boolean retainAll(Collection<?> col) { |
227 | int oldSize = size(); |
228 | clear(); |
229 | addAll((Collection<? extends N>) col); |
230 | return size() != oldSize; |
231 | } |
232 | |
233 | @Override |
234 | public N set(int index, N elem) { |
235 | return innerList.set(index, new EqualsHashcodeOverridingFacade((N) elem)).overridden; |
236 | } |
237 | |
238 | @Override |
239 | public int size() { |
240 | return innerList.size(); |
241 | } |
242 | |
243 | @Override |
244 | public List<N> subList(int fromIndex, int toIndex) { |
245 | return new VisitorList<N>(hashcodeVisitor, equalsVisitor) { |
246 | { |
247 | this.innerList = VisitorList.this.innerList.subList(fromIndex, toIndex); |
248 | } |
249 | }; |
250 | } |
251 | |
252 | @Override |
253 | public Object[] toArray() { |
254 | return innerList.stream().map(facade -> facade.overridden).collect(Collectors.toList()).toArray(); |
255 | } |
256 | |
257 | @Override |
258 | public <T> T[] toArray(T[] arr) { |
259 | return innerList.stream().map(facade -> facade.overridden).collect(Collectors.toList()).toArray(arr); |
260 | } |
261 | |
262 | @Override |
263 | public String toString() { |
264 | StringBuilder sb = new StringBuilder("["); |
265 | if (size() == 0) |
266 | return sb.append("]").toString(); |
267 | for (EqualsHashcodeOverridingFacade facade : innerList) { |
268 | sb.append(facade.overridden.toString() + ", "); |
269 | } |
270 | return sb.replace(sb.length() - 2, sb.length(), "]").toString(); |
271 | } |
272 | |
273 | private class EqualsHashcodeOverridingFacade implements Visitable { |
274 | private final N overridden; |
275 | |
276 | EqualsHashcodeOverridingFacade(N overridden) { |
277 | this.overridden = overridden; |
278 | } |
279 | |
280 | @Override |
281 | public <R, A> R accept(GenericVisitor<R, A> v, A arg) { |
282 | throw new AssertionError(); |
283 | } |
284 | |
285 | @Override |
286 | public <A> void accept(VoidVisitor<A> v, A arg) { |
287 | throw new AssertionError(); |
288 | } |
289 | |
290 | @Override |
291 | public final int hashCode() { |
292 | return overridden.accept(hashcodeVisitor, null); |
293 | } |
294 | |
295 | @Override |
296 | public boolean equals(final Object obj) { |
297 | if (obj == null || !(obj instanceof VisitorList.EqualsHashcodeOverridingFacade)) { |
298 | return false; |
299 | } |
300 | return overridden.accept(equalsVisitor, ((EqualsHashcodeOverridingFacade) obj).overridden); |
301 | } |
302 | } |
303 | } |
304 |
Members