1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.basepom.mojo.duplicatefinder.artifact;
15
16 import java.util.Objects;
17
18 import com.google.common.base.Joiner;
19 import com.google.common.base.MoreObjects;
20 import java.util.Optional;
21 import com.google.common.collect.ImmutableList;
22 import org.apache.maven.artifact.Artifact;
23 import org.apache.maven.artifact.versioning.ArtifactVersion;
24 import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
25 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
26 import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
27 import org.apache.maven.artifact.versioning.VersionRange;
28 import org.apache.maven.model.Dependency;
29
30 import static com.google.common.base.Preconditions.checkNotNull;
31
32 public class MavenCoordinates {
33
34 private final String artifactId;
35 private final String groupId;
36 private final Optional<? extends ArtifactVersion> version;
37 private final Optional<VersionRange> versionRange;
38 private final String type;
39 private final Optional<String> classifier;
40
41 public MavenCoordinates(final Dependency dependency) throws InvalidVersionSpecificationException {
42 checkNotNull(dependency, "dependency is null");
43
44 this.artifactId = checkNotNull(dependency.getArtifactId(), "artifactId for dependency '%s' is null", dependency);
45 this.groupId = checkNotNull(dependency.getGroupId(), "groupId for dependency '%s' is null", dependency);
46
47 final String version = dependency.getVersion();
48 this.version = Optional.ofNullable(version).map(DefaultArtifactVersion::new);
49
50 if (this.version.isPresent()) {
51 this.versionRange = Optional.of(VersionRange.createFromVersionSpec(version));
52 } else {
53 this.versionRange = Optional.empty();
54 }
55
56 final String type = dependency.getType();
57 final String classifier = dependency.getClassifier();
58 if ("test-jar".equals(type)) {
59 this.classifier = Optional.of(MoreObjects.firstNonNull(classifier, "tests"));
60 this.type = "jar";
61 } else {
62 this.type = MoreObjects.firstNonNull(type, "jar");
63 this.classifier = Optional.ofNullable(classifier);
64 }
65 }
66
67 public MavenCoordinates(final Artifact artifact) throws OverConstrainedVersionException {
68 checkNotNull(artifact, "artifact is null");
69
70 this.artifactId = checkNotNull(artifact.getArtifactId(), "artifactId for artifact '%s' is null", artifact);
71 this.groupId = checkNotNull(artifact.getGroupId(), "groupId for artifact '%s' is null", artifact);
72 this.versionRange = Optional.ofNullable(artifact.getVersionRange());
73
74 if (this.versionRange.isPresent()) {
75 this.version = Optional.ofNullable(artifact.getSelectedVersion());
76 } else {
77 final String version = artifact.getBaseVersion();
78 this.version = Optional.ofNullable(version).map(DefaultArtifactVersion::new);
79 }
80
81 final String type = artifact.getType();
82 final String classifier = artifact.getClassifier();
83 if ("test-jar".equals(type)) {
84 this.classifier = Optional.of(MoreObjects.firstNonNull(classifier, "tests"));
85 this.type = "jar";
86 } else {
87 this.type = MoreObjects.firstNonNull(type, "jar");
88 this.classifier = Optional.ofNullable(classifier);
89 }
90 }
91
92 public String getArtifactId() {
93 return artifactId;
94 }
95
96 public String getGroupId() {
97 return groupId;
98 }
99
100 public Optional<? extends ArtifactVersion> getVersion() {
101 return version;
102 }
103
104 public Optional<VersionRange> getVersionRange() {
105 return versionRange;
106 }
107
108 public String getType() {
109 return type;
110 }
111
112 public Optional<String> getClassifier() {
113 return classifier;
114 }
115
116 public boolean matches(final Artifact artifact) throws OverConstrainedVersionException {
117 return matches(new MavenCoordinates(artifact));
118 }
119
120 public boolean matches(final MavenCoordinates other) {
121 if (!(Objects.equals(getGroupId(), other.getGroupId())
122 && Objects.equals(getArtifactId(), other.getArtifactId())
123 && Objects.equals(getType(), other.getType()))) {
124 return false;
125 }
126
127
128
129 if (getClassifier().isPresent()) {
130 if (!Objects.equals(getClassifier().get(), other.getClassifier().orElse(null))) {
131 return false;
132 }
133 }
134
135
136 if (!getVersionRange().isPresent() && !getVersion().isPresent()) {
137 return true;
138 }
139
140
141
142
143 if (!other.getVersion().isPresent()) {
144 return false;
145 }
146
147
148 if (getVersionRange().isPresent()) {
149
150 final ArtifactVersion recommendedVersion = getVersionRange().get().getRecommendedVersion();
151 if (recommendedVersion != null) {
152
153 return Objects.equals(recommendedVersion, other.getVersion().orElse(null));
154 }
155
156
157 if (getVersionRange().get().containsVersion(other.getVersion().get())) {
158 return true;
159 }
160 }
161
162
163 return Objects.equals(getVersion().orElse(null), other.getVersion().orElse(null));
164 }
165
166 @Override
167 public int hashCode() {
168 return Objects.hash(groupId, artifactId, classifier, type);
169 }
170
171 @Override
172 public boolean equals(final Object other) {
173 if (other == null || other.getClass() != this.getClass()) {
174 return false;
175 }
176 if (other == this) {
177 return true;
178 }
179
180 MavenCoordinates that = (MavenCoordinates) other;
181
182 return Objects.equals(this.groupId, that.groupId)
183 && Objects.equals(this.artifactId, that.artifactId)
184 && Objects.equals(this.classifier, that.classifier)
185 && Objects.equals(this.type, that.type);
186 }
187
188 @Override
189 public String toString() {
190 final ImmutableList.Builder<String> builder = ImmutableList.builder();
191
192 builder.add(getGroupId());
193 builder.add(getArtifactId());
194
195 if (getVersion().isPresent()) {
196 builder.add(getVersion().get().toString());
197 } else {
198 builder.add("<any>");
199 }
200
201 builder.add(getType());
202 builder.add(getClassifier().orElse("<any>"));
203 return Joiner.on(':').join(builder.build());
204 }
205 }