View Javadoc
1   /*
2    * Licensed under the Apache License, Version 2.0 (the "License");
3    * you may not use this file except in compliance with the License.
4    * You may obtain a copy of the License at
5    *
6    * http://www.apache.org/licenses/LICENSE-2.0
7    *
8    * Unless required by applicable law or agreed to in writing, software
9    * distributed under the License is distributed on an "AS IS" BASIS,
10   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11   * See the License for the specific language governing permissions and
12   * limitations under the License.
13   */
14  
15  package org.basepom.mojo.dvc;
16  
17  import static com.google.common.base.Preconditions.checkNotNull;
18  import static com.google.common.base.Preconditions.checkState;
19  
20  import java.util.Objects;
21  import java.util.Optional;
22  
23  import com.google.common.annotations.VisibleForTesting;
24  import com.google.common.base.Joiner;
25  import com.google.common.base.MoreObjects;
26  import com.google.common.collect.ImmutableList;
27  import org.apache.maven.RepositoryUtils;
28  import org.apache.maven.artifact.Artifact;
29  import org.apache.maven.project.MavenProject;
30  import org.eclipse.aether.graph.Dependency;
31  import org.eclipse.aether.graph.DependencyNode;
32  
33  /**
34   * A qualified name for a dependency or artifact. This is everything but a version.
35   */
36  public final class QualifiedName
37          implements Comparable<QualifiedName> {
38  
39      private final String groupId;
40      private final String artifactId;
41      private final String type;
42      private final String classifier;
43  
44      public static QualifiedName fromDependencyNode(final DependencyNode dependencyNode) {
45          checkNotNull(dependencyNode, "dependency is null");
46          return fromArtifact(RepositoryUtils.toArtifact(dependencyNode.getArtifact()));
47      }
48  
49      public static QualifiedName fromDependency(final Dependency dependency) {
50          checkNotNull(dependency, "dependency is null");
51          return fromArtifact(RepositoryUtils.toArtifact(dependency.getArtifact()));
52      }
53  
54      public static QualifiedName fromArtifact(final Artifact artifact) {
55          checkNotNull(artifact, "artifact is null");
56  
57          return new QualifiedName(artifact.getGroupId(),
58                  artifact.getArtifactId(),
59                  artifact.getType(),
60                  artifact.getClassifier());
61      }
62  
63      public static QualifiedName fromProject(final MavenProject project) {
64          checkNotNull(project, "project is null");
65  
66          return new QualifiedName(project.getGroupId(),
67                  project.getArtifactId(),
68                  null,
69                  null);
70      }
71  
72      @VisibleForTesting
73      QualifiedName(String groupId, String artifactId, String type, String classifier) {
74          this.groupId = checkNotNull(groupId, "groupId is null");
75          this.artifactId = checkNotNull(artifactId, "artifactId is null");
76          this.type = type;
77          this.classifier = classifier;
78  
79          checkState(classifier == null || type != null, "Classifier must be null if type is null");
80      }
81  
82      public String getGroupId() {
83          return groupId;
84      }
85  
86      public String getArtifactId() {
87          return artifactId;
88      }
89  
90      public Optional<String> getType() {
91          return Optional.ofNullable(type);
92      }
93  
94      public Optional<String> getClassifier() {
95          return Optional.ofNullable(classifier);
96      }
97  
98      /**
99       * @return True if this qualified name refers to a test artifact.
100      */
101     public boolean hasTests() {
102         return getType().map(t -> t.equals("test-jar")).orElse(false)
103                 || (getClassifier().map(c -> c.equals("tests")).orElse(false) && getType().map(t -> t.equals("jar")).orElse(false));
104     }
105 
106     /**
107      * @return The full name (group, artifact, type, classifier). Normalizes any test jar to be group:artifact:jar:tests.
108      */
109     public String getFullName() {
110         ImmutableList.Builder<String> builder = ImmutableList.builder();
111         builder.add(getGroupId()).add(getArtifactId());
112 
113         getType().ifPresent(t -> builder.add(t));
114         getClassifier().ifPresent(t -> builder.add(t));
115         return Joiner.on(':').join(builder.build());
116     }
117 
118     /**
119      * @return The short name (group, artifact, optional classifier). Skips absent classifiers. Normalizes test jars to `tests` classifier.
120      */
121     public String getShortName() {
122         String result = Joiner.on(':').skipNulls()
123                 .join(getGroupId(),
124                         getArtifactId());
125 
126         String classifier = hasTests() ? "tests" : getClassifier().orElse("");
127 
128         if (!classifier.isEmpty()) {
129             result = result + " (" + classifier + ")";
130         }
131 
132         return result;
133     }
134 
135     public int length() {
136         return getShortName().length();
137     }
138 
139     public String getMinimalName() {
140         return Joiner.on(':')
141                 .join(getGroupId(), getArtifactId());
142     }
143 
144     @Override
145     public boolean equals(final Object o) {
146         if (this == o) {
147             return true;
148         }
149         if (o == null || getClass() != o.getClass()) {
150             return false;
151         }
152         QualifiedName that = (QualifiedName) o;
153         if (Objects.equals(groupId, that.groupId)
154                 && Objects.equals(artifactId, that.artifactId)) {
155 
156             // Two test artifacts test equal
157             if (hasTests() && ((QualifiedName) o).hasTests()) {
158                 return true;
159             }
160 
161             return Objects.equals(getType().orElse("jar"), that.getType().orElse("jar"))
162                     && Objects.equals(getClassifier().orElse(""), that.getClassifier().orElse(""));
163         }
164 
165         return false;
166     }
167 
168     @Override
169     public int hashCode() {
170         if (hasTests()) {
171             return Objects.hash(groupId, artifactId, "test-jar", "tests");
172         } else {
173             return Objects.hash(groupId, artifactId, getType().orElse("jar"), getClassifier().orElse(""));
174         }
175     }
176 
177     @Override
178     public String toString() {
179         return MoreObjects.toStringHelper(this)
180                 .add("groupId", groupId)
181                 .add("artifactId", artifactId)
182                 .add("type", type)
183                 .add("classifier", classifier)
184                 .toString();
185     }
186 
187     @Override
188     public int compareTo(final QualifiedName other) {
189         if (other == null) {
190             return 1;
191         } else if (other == this || equals(other)) {
192             return 0;
193         } else {
194             return getMinimalName().compareTo(other.getMinimalName());
195         }
196     }
197 }