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 com.github.javaparser.ast.Node; |
25 | import com.github.javaparser.ast.visitor.GenericVisitor; |
26 | import com.github.javaparser.ast.visitor.Visitable; |
27 | import com.github.javaparser.ast.visitor.VoidVisitor; |
28 | |
29 | import java.util.Collection; |
30 | import java.util.HashMap; |
31 | import java.util.Map; |
32 | import java.util.Set; |
33 | import java.util.stream.Collectors; |
34 | |
35 | /** |
36 | * A map that overrides the equals and hashcode calculation of the added nodes |
37 | * by using another equals and hashcode visitor for those methods. |
38 | */ |
39 | public class VisitorMap<N extends Node, V> implements Map<N, V> { |
40 | private final Map<EqualsHashcodeOverridingFacade, V> innerMap = new HashMap<>(); |
41 | private final GenericVisitor<Integer, Void> hashcodeVisitor; |
42 | private final GenericVisitor<Boolean, Visitable> equalsVisitor; |
43 | |
44 | /** |
45 | * Pass the visitors to use for equals and hashcode. |
46 | */ |
47 | public VisitorMap(GenericVisitor<Integer, Void> hashcodeVisitor, GenericVisitor<Boolean, Visitable> equalsVisitor) { |
48 | this.hashcodeVisitor = hashcodeVisitor; |
49 | this.equalsVisitor = equalsVisitor; |
50 | } |
51 | |
52 | @Override |
53 | public int size() { |
54 | return innerMap.size(); |
55 | } |
56 | |
57 | @Override |
58 | public boolean isEmpty() { |
59 | return innerMap.isEmpty(); |
60 | } |
61 | |
62 | @Override |
63 | public boolean containsKey(Object key) { |
64 | return innerMap.containsKey(new EqualsHashcodeOverridingFacade((N) key)); |
65 | } |
66 | |
67 | @Override |
68 | public boolean containsValue(Object value) { |
69 | return innerMap.containsValue(value); |
70 | } |
71 | |
72 | @Override |
73 | public V get(Object key) { |
74 | return innerMap.get(new EqualsHashcodeOverridingFacade((N) key)); |
75 | } |
76 | |
77 | @Override |
78 | public V put(N key, V value) { |
79 | return innerMap.put(new EqualsHashcodeOverridingFacade(key), value); |
80 | } |
81 | |
82 | private class EqualsHashcodeOverridingFacade implements Visitable { |
83 | private final N overridden; |
84 | |
85 | EqualsHashcodeOverridingFacade(N overridden) { |
86 | this.overridden = overridden; |
87 | } |
88 | |
89 | @Override |
90 | public <R, A> R accept(GenericVisitor<R, A> v, A arg) { |
91 | throw new AssertionError(); |
92 | } |
93 | |
94 | @Override |
95 | public <A> void accept(VoidVisitor<A> v, A arg) { |
96 | throw new AssertionError(); |
97 | } |
98 | |
99 | @Override |
100 | public final int hashCode() { |
101 | return overridden.accept(hashcodeVisitor, null); |
102 | } |
103 | |
104 | @Override |
105 | public boolean equals(final Object obj) { |
106 | if (obj == null || !(obj instanceof VisitorMap.EqualsHashcodeOverridingFacade)) { |
107 | return false; |
108 | } |
109 | return overridden.accept(equalsVisitor, ((EqualsHashcodeOverridingFacade) obj).overridden); |
110 | } |
111 | } |
112 | |
113 | @Override |
114 | public V remove(Object key) { |
115 | return innerMap.remove(new EqualsHashcodeOverridingFacade((N) key)); |
116 | } |
117 | |
118 | @Override |
119 | public void putAll(Map<? extends N, ? extends V> m) { |
120 | m.forEach(this::put); |
121 | } |
122 | |
123 | @Override |
124 | public void clear() { |
125 | innerMap.clear(); |
126 | } |
127 | |
128 | @Override |
129 | public Set<N> keySet() { |
130 | return innerMap.keySet().stream() |
131 | .map(k -> k.overridden) |
132 | .collect(Collectors.toSet()); |
133 | } |
134 | |
135 | @Override |
136 | public Collection<V> values() { |
137 | return innerMap.values(); |
138 | } |
139 | |
140 | @Override |
141 | public Set<Entry<N, V>> entrySet() { |
142 | return innerMap.entrySet().stream() |
143 | .map(e -> new HashMap.SimpleEntry<>(e.getKey().overridden, e.getValue())) |
144 | .collect(Collectors.toSet()); |
145 | } |
146 | } |
147 |
Members