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