1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.graph;
20
21 import java.util.AbstractSet;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.Iterator;
25 import java.util.LinkedHashSet;
26 import java.util.NoSuchElementException;
27 import java.util.Objects;
28 import java.util.Set;
29
30 import org.eclipse.aether.artifact.Artifact;
31
32 import static java.util.Objects.requireNonNull;
33
34
35
36
37
38 public final class Dependency {
39
40 private final Artifact artifact;
41
42 private final String scope;
43
44 private final Boolean optional;
45
46 private final Set<Exclusion> exclusions;
47
48
49
50
51
52
53
54 public Dependency(Artifact artifact, String scope) {
55 this(artifact, scope, false);
56 }
57
58
59
60
61
62
63
64
65 public Dependency(Artifact artifact, String scope, Boolean optional) {
66 this(artifact, scope, optional, null);
67 }
68
69
70
71
72
73
74
75
76
77 public Dependency(Artifact artifact, String scope, Boolean optional, Collection<Exclusion> exclusions) {
78 this(artifact, scope, Exclusions.copy(exclusions), optional);
79 }
80
81 private Dependency(Artifact artifact, String scope, Set<Exclusion> exclusions, Boolean optional) {
82
83 this.artifact = requireNonNull(artifact, "artifact cannot be null");
84 this.scope = (scope != null) ? scope : "";
85 this.optional = optional;
86 this.exclusions = exclusions;
87 }
88
89
90
91
92
93
94 public Artifact getArtifact() {
95 return artifact;
96 }
97
98
99
100
101
102
103
104 public Dependency setArtifact(Artifact artifact) {
105 if (this.artifact.equals(artifact)) {
106 return this;
107 }
108 return new Dependency(artifact, scope, exclusions, optional);
109 }
110
111
112
113
114
115
116 public String getScope() {
117 return scope;
118 }
119
120
121
122
123
124
125
126 public Dependency setScope(String scope) {
127 if (this.scope.equals(scope) || (scope == null && this.scope.isEmpty())) {
128 return this;
129 }
130 return new Dependency(artifact, scope, exclusions, optional);
131 }
132
133
134
135
136
137
138 public boolean isOptional() {
139 return Boolean.TRUE.equals(optional);
140 }
141
142
143
144
145
146
147
148 public Boolean getOptional() {
149 return optional;
150 }
151
152
153
154
155
156
157
158
159 public Dependency setOptional(Boolean optional) {
160 if (Objects.equals(this.optional, optional)) {
161 return this;
162 }
163 return new Dependency(artifact, scope, exclusions, optional);
164 }
165
166
167
168
169
170
171
172 public Collection<Exclusion> getExclusions() {
173 return exclusions;
174 }
175
176
177
178
179
180
181
182 public Dependency setExclusions(Collection<Exclusion> exclusions) {
183 if (hasEquivalentExclusions(exclusions)) {
184 return this;
185 }
186 return new Dependency(artifact, scope, optional, exclusions);
187 }
188
189 private boolean hasEquivalentExclusions(Collection<Exclusion> exclusions) {
190 if (exclusions == null || exclusions.isEmpty()) {
191 return this.exclusions.isEmpty();
192 }
193 if (exclusions instanceof Set) {
194 return this.exclusions.equals(exclusions);
195 }
196 return exclusions.size() >= this.exclusions.size()
197 && this.exclusions.containsAll(exclusions)
198 && exclusions.containsAll(this.exclusions);
199 }
200
201 @Override
202 public String toString() {
203 return getArtifact() + " (" + getScope() + (isOptional() ? "?" : "") + ")";
204 }
205
206 @Override
207 public boolean equals(Object obj) {
208 if (obj == this) {
209 return true;
210 } else if (obj == null || !getClass().equals(obj.getClass())) {
211 return false;
212 }
213
214 Dependency that = (Dependency) obj;
215
216 return Objects.equals(artifact, that.artifact)
217 && Objects.equals(scope, that.scope)
218 && Objects.equals(optional, that.optional)
219 && Objects.equals(exclusions, that.exclusions);
220 }
221
222 @Override
223 public int hashCode() {
224 int hash = 17;
225 hash = hash * 31 + artifact.hashCode();
226 hash = hash * 31 + scope.hashCode();
227 hash = hash * 31 + (optional != null ? optional.hashCode() : 0);
228 hash = hash * 31 + exclusions.size();
229 return hash;
230 }
231
232 private static class Exclusions extends AbstractSet<Exclusion> {
233
234 private final Exclusion[] exclusions;
235
236 public static Set<Exclusion> copy(Collection<Exclusion> exclusions) {
237 if (exclusions == null || exclusions.isEmpty()) {
238 return Collections.emptySet();
239 }
240 return new Exclusions(exclusions);
241 }
242
243 private Exclusions(Collection<Exclusion> exclusions) {
244 if (exclusions.size() > 1 && !(exclusions instanceof Set)) {
245 exclusions = new LinkedHashSet<>(exclusions);
246 }
247 this.exclusions = exclusions.toArray(new Exclusion[0]);
248 }
249
250 @Override
251 public Iterator<Exclusion> iterator() {
252 return new Iterator<Exclusion>() {
253
254 private int cursor = 0;
255
256 public boolean hasNext() {
257 return cursor < exclusions.length;
258 }
259
260 public Exclusion next() {
261 try {
262 Exclusion exclusion = exclusions[cursor];
263 cursor++;
264 return exclusion;
265 } catch (IndexOutOfBoundsException e) {
266 throw new NoSuchElementException();
267 }
268 }
269
270 public void remove() {
271 throw new UnsupportedOperationException();
272 }
273 };
274 }
275
276 @Override
277 public int size() {
278 return exclusions.length;
279 }
280 }
281 }