View Javadoc
1   // =================== DO NOT EDIT THIS FILE ====================
2   //  Generated by Modello Velocity from model.vm
3   //  template, any modifications will be overwritten.
4   // ==============================================================
5   package org.apache.maven.api.model;
6   
7   import java.io.Serializable;
8   import java.util.ArrayList;
9   import java.util.Collection;
10  import java.util.Collections;
11  import java.util.HashMap;
12  import java.util.List;
13  import java.util.Map;
14  import java.util.Objects;
15  import java.util.Optional;
16  import java.util.Set;
17  import java.util.stream.Collectors;
18  import java.util.stream.Stream;
19  import org.apache.maven.api.annotations.Experimental;
20  import org.apache.maven.api.annotations.Generated;
21  import org.apache.maven.api.annotations.Immutable;
22  import org.apache.maven.api.annotations.Nonnull;
23  import org.apache.maven.api.annotations.NotThreadSafe;
24  import org.apache.maven.api.annotations.ThreadSafe;
25  
26  /**
27   * The {@code <dependency>} element contains information about a dependency
28   * of the project.
29   */
30  @Experimental
31  @Generated @ThreadSafe @Immutable
32  public class Dependency
33      implements Serializable, InputLocationTracker
34  {
35      /**
36       * The project group that produced the dependency, e.g.
37       * {@code org.apache.maven}.
38       */
39      final String groupId;
40      /**
41       * The unique id for an artifact produced by the project group, e.g.
42       * {@code maven-artifact}.
43       */
44      final String artifactId;
45      /**
46       * The version of the dependency, e.g. {@code 3.2.1}. Since Maven 2, this can also be
47       * specified as a range of versions.
48       */
49      final String version;
50      /**
51       * The type of dependency, that will be mapped to a file extension, an optional classifier, and a few other attributes.
52       * Some examples are {@code jar}, {@code war}, {@code ejb-client}
53       * and {@code test-jar}: see <a href="../maven-core/artifact-handlers.html">default
54       * artifact handlers</a> for a list. New types can be defined by extensions, so this is not a complete list.
55       */
56      final String type;
57      /**
58       * The classifier of the dependency. It is appended to
59       * the filename after the version. This allows:
60       * <ul>
61       * <li>referring to attached artifact, for example {@code sources} and {@code javadoc}:
62       * see <a href="../maven-core/artifact-handlers.html">default artifact handlers</a> for a list,</li>
63       * <li>distinguishing two artifacts
64       * that belong to the same POM but were built differently.
65       * For example, {@code jdk14} and {@code jdk15}.</li>
66       * </ul>
67       */
68      final String classifier;
69      /**
70       * The scope of the dependency - {@code compile}, {@code runtime},
71       * {@code test}, {@code system}, and {@code provided}. Used to
72       * calculate the various classpaths used for compilation, testing, and so on.
73       * It also assists in determining which artifacts to include in a distribution of
74       * this project. For more information, see
75       * <a href="https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html">the
76       * dependency mechanism</a>. The default scope is {@code compile}.
77       */
78      final String scope;
79      /**
80       * FOR SYSTEM SCOPE ONLY. Note that use of this property is <b>discouraged</b>
81       * and may be replaced in later versions. This specifies the path on the filesystem
82       * for this dependency.
83       * Requires an absolute path for the value, not relative.
84       * Use a property that gives the machine specific absolute path,
85       * e.g. {@code ${java.home}}.
86       */
87      final String systemPath;
88      /**
89       * Lists a set of artifacts that should be excluded from this dependency's
90       * artifact list when it comes to calculating transitive dependencies.
91       */
92      final List<Exclusion> exclusions;
93      /**
94       * Indicates the dependency is optional for use of this library. While the
95       * version of the dependency will be taken into account for dependency calculation if the
96       * library is used elsewhere, it will not be passed on transitively. Note: While the type
97       * of this field is {@code String} for technical reasons, the semantic type is actually
98       * {@code Boolean}. Default value is {@code false}.
99       */
100     final String optional;
101     /** Locations */
102     final Map<Object, InputLocation> locations;
103     /** Location tracking */
104     final InputLocation importedFrom;
105 
106     /**
107       * Constructor for this class, to be called from its subclasses and {@link Builder}.
108       * @see Builder#build()
109       */
110     protected Dependency(Builder builder) {
111         this.groupId = builder.groupId != null ? builder.groupId : (builder.base != null ? builder.base.groupId : null);
112         this.artifactId = builder.artifactId != null ? builder.artifactId : (builder.base != null ? builder.base.artifactId : null);
113         this.version = builder.version != null ? builder.version : (builder.base != null ? builder.base.version : null);
114         this.type = builder.type != null ? builder.type : (builder.base != null ? builder.base.type : null);
115         this.classifier = builder.classifier != null ? builder.classifier : (builder.base != null ? builder.base.classifier : null);
116         this.scope = builder.scope != null ? builder.scope : (builder.base != null ? builder.base.scope : null);
117         this.systemPath = builder.systemPath != null ? builder.systemPath : (builder.base != null ? builder.base.systemPath : null);
118         this.exclusions = ImmutableCollections.copy(builder.exclusions != null ? builder.exclusions : (builder.base != null ? builder.base.exclusions : null));
119         this.optional = builder.optional != null ? builder.optional : (builder.base != null ? builder.base.optional : null);
120         this.locations = builder.computeLocations();
121         this.importedFrom = builder.importedFrom;
122     }
123 
124     /**
125      * The project group that produced the dependency, e.g.
126      * {@code org.apache.maven}.
127      *
128      * @return a {@code String}
129      */
130     public String getGroupId() {
131         return this.groupId;
132     }
133 
134     /**
135      * The unique id for an artifact produced by the project group, e.g.
136      * {@code maven-artifact}.
137      *
138      * @return a {@code String}
139      */
140     public String getArtifactId() {
141         return this.artifactId;
142     }
143 
144     /**
145      * The version of the dependency, e.g. {@code 3.2.1}. Since Maven 2, this can also be
146      * specified as a range of versions.
147      *
148      * @return a {@code String}
149      */
150     public String getVersion() {
151         return this.version;
152     }
153 
154     /**
155      * The type of dependency, that will be mapped to a file extension, an optional classifier, and a few other attributes.
156      * Some examples are {@code jar}, {@code war}, {@code ejb-client}
157      * and {@code test-jar}: see <a href="../maven-core/artifact-handlers.html">default
158      * artifact handlers</a> for a list. New types can be defined by extensions, so this is not a complete list.
159      *
160      * @return a {@code String}
161      */
162     public String getType() {
163         return this.type;
164     }
165 
166     /**
167      * The classifier of the dependency. It is appended to
168      * the filename after the version. This allows:
169      * <ul>
170      * <li>referring to attached artifact, for example {@code sources} and {@code javadoc}:
171      * see <a href="../maven-core/artifact-handlers.html">default artifact handlers</a> for a list,</li>
172      * <li>distinguishing two artifacts
173      * that belong to the same POM but were built differently.
174      * For example, {@code jdk14} and {@code jdk15}.</li>
175      * </ul>
176      *
177      * @return a {@code String}
178      */
179     public String getClassifier() {
180         return this.classifier;
181     }
182 
183     /**
184      * The scope of the dependency - {@code compile}, {@code runtime},
185      * {@code test}, {@code system}, and {@code provided}. Used to
186      * calculate the various classpaths used for compilation, testing, and so on.
187      * It also assists in determining which artifacts to include in a distribution of
188      * this project. For more information, see
189      * <a href="https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html">the
190      * dependency mechanism</a>. The default scope is {@code compile}.
191      *
192      * @return a {@code String}
193      */
194     public String getScope() {
195         return this.scope;
196     }
197 
198     /**
199      * FOR SYSTEM SCOPE ONLY. Note that use of this property is <b>discouraged</b>
200      * and may be replaced in later versions. This specifies the path on the filesystem
201      * for this dependency.
202      * Requires an absolute path for the value, not relative.
203      * Use a property that gives the machine specific absolute path,
204      * e.g. {@code ${java.home}}.
205      *
206      * @return a {@code String}
207      */
208     public String getSystemPath() {
209         return this.systemPath;
210     }
211 
212     /**
213      * Lists a set of artifacts that should be excluded from this dependency's
214      * artifact list when it comes to calculating transitive dependencies.
215      *
216      * @return a {@code List<Exclusion>}
217      */
218     @Nonnull
219     public List<Exclusion> getExclusions() {
220         return this.exclusions;
221     }
222 
223     /**
224      * Indicates the dependency is optional for use of this library. While the
225      * version of the dependency will be taken into account for dependency calculation if the
226      * library is used elsewhere, it will not be passed on transitively. Note: While the type
227      * of this field is {@code String} for technical reasons, the semantic type is actually
228      * {@code Boolean}. Default value is {@code false}.
229      *
230      * @return a {@code String}
231      */
232     public String getOptional() {
233         return this.optional;
234     }
235 
236     /**
237      * Gets the location of the specified field in the input source.
238      */
239     public InputLocation getLocation(Object key) {
240         return locations.get(key);
241     }
242 
243     /**
244      * Gets the keys of the locations of the input source.
245      */
246     public Set<Object> getLocationKeys() {
247         return locations.keySet();
248     }
249 
250     protected Stream<Object> getLocationKeyStream() {
251         return locations.keySet().stream();
252     }
253 
254     /**
255      * Gets the input location that caused this model to be read.
256      */
257     public InputLocation getImportedFrom() {
258         return importedFrom;
259     }
260 
261     /**
262      * Creates a new builder with this object as the basis.
263      *
264      * @return a {@code Builder}
265      */
266     @Nonnull
267     public Builder with() {
268         return newBuilder(this);
269     }
270     /**
271      * Creates a new {@code Dependency} instance using the specified groupId.
272      *
273      * @param groupId the new {@code String} to use
274      * @return a {@code Dependency} with the specified groupId
275      */
276     @Nonnull
277     public Dependency withGroupId(String groupId) {
278         return newBuilder(this, true).groupId(groupId).build();
279     }
280     /**
281      * Creates a new {@code Dependency} instance using the specified artifactId.
282      *
283      * @param artifactId the new {@code String} to use
284      * @return a {@code Dependency} with the specified artifactId
285      */
286     @Nonnull
287     public Dependency withArtifactId(String artifactId) {
288         return newBuilder(this, true).artifactId(artifactId).build();
289     }
290     /**
291      * Creates a new {@code Dependency} instance using the specified version.
292      *
293      * @param version the new {@code String} to use
294      * @return a {@code Dependency} with the specified version
295      */
296     @Nonnull
297     public Dependency withVersion(String version) {
298         return newBuilder(this, true).version(version).build();
299     }
300     /**
301      * Creates a new {@code Dependency} instance using the specified type.
302      *
303      * @param type the new {@code String} to use
304      * @return a {@code Dependency} with the specified type
305      */
306     @Nonnull
307     public Dependency withType(String type) {
308         return newBuilder(this, true).type(type).build();
309     }
310     /**
311      * Creates a new {@code Dependency} instance using the specified classifier.
312      *
313      * @param classifier the new {@code String} to use
314      * @return a {@code Dependency} with the specified classifier
315      */
316     @Nonnull
317     public Dependency withClassifier(String classifier) {
318         return newBuilder(this, true).classifier(classifier).build();
319     }
320     /**
321      * Creates a new {@code Dependency} instance using the specified scope.
322      *
323      * @param scope the new {@code String} to use
324      * @return a {@code Dependency} with the specified scope
325      */
326     @Nonnull
327     public Dependency withScope(String scope) {
328         return newBuilder(this, true).scope(scope).build();
329     }
330     /**
331      * Creates a new {@code Dependency} instance using the specified systemPath.
332      *
333      * @param systemPath the new {@code String} to use
334      * @return a {@code Dependency} with the specified systemPath
335      */
336     @Nonnull
337     public Dependency withSystemPath(String systemPath) {
338         return newBuilder(this, true).systemPath(systemPath).build();
339     }
340     /**
341      * Creates a new {@code Dependency} instance using the specified exclusions.
342      *
343      * @param exclusions the new {@code Collection<Exclusion>} to use
344      * @return a {@code Dependency} with the specified exclusions
345      */
346     @Nonnull
347     public Dependency withExclusions(Collection<Exclusion> exclusions) {
348         return newBuilder(this, true).exclusions(exclusions).build();
349     }
350     /**
351      * Creates a new {@code Dependency} instance using the specified optional.
352      *
353      * @param optional the new {@code String} to use
354      * @return a {@code Dependency} with the specified optional
355      */
356     @Nonnull
357     public Dependency withOptional(String optional) {
358         return newBuilder(this, true).optional(optional).build();
359     }
360 
361     /**
362      * Creates a new {@code Dependency} instance.
363      * Equivalent to {@code newInstance(true)}.
364      * @see #newInstance(boolean)
365      *
366      * @return a new {@code Dependency}
367      */
368     @Nonnull
369     public static Dependency newInstance() {
370         return newInstance(true);
371     }
372 
373     /**
374      * Creates a new {@code Dependency} instance using default values or not.
375      * Equivalent to {@code newBuilder(withDefaults).build()}.
376      *
377      * @param withDefaults the boolean indicating whether default values should be used
378      * @return a new {@code Dependency}
379      */
380     @Nonnull
381     public static Dependency newInstance(boolean withDefaults) {
382         return newBuilder(withDefaults).build();
383     }
384 
385     /**
386      * Creates a new {@code Dependency} builder instance.
387      * Equivalent to {@code newBuilder(true)}.
388      * @see #newBuilder(boolean)
389      *
390      * @return a new {@code Builder}
391      */
392     @Nonnull
393     public static Builder newBuilder() {
394         return newBuilder(true);
395     }
396 
397     /**
398      * Creates a new {@code Dependency} builder instance using default values or not.
399      *
400      * @param withDefaults the boolean indicating whether default values should be used
401      * @return a new {@code Builder}
402      */
403     @Nonnull
404     public static Builder newBuilder(boolean withDefaults) {
405         return new Builder(withDefaults);
406     }
407 
408     /**
409      * Creates a new {@code Dependency} builder instance using the specified object as a basis.
410      * Equivalent to {@code newBuilder(from, false)}.
411      *
412      * @param from the {@code Dependency} instance to use as a basis
413      * @return a new {@code Builder}
414      */
415     @Nonnull
416     public static Builder newBuilder(Dependency from) {
417         return newBuilder(from, false);
418     }
419 
420     /**
421      * Creates a new {@code Dependency} builder instance using the specified object as a basis.
422      *
423      * @param from the {@code Dependency} instance to use as a basis
424      * @param forceCopy the boolean indicating if a copy should be forced
425      * @return a new {@code Builder}
426      */
427     @Nonnull
428     public static Builder newBuilder(Dependency from, boolean forceCopy) {
429         return new Builder(from, forceCopy);
430     }
431 
432     /**
433      * Builder class used to create Dependency instances.
434      * @see #with()
435      * @see #newBuilder()
436      */
437     @NotThreadSafe
438     public static class Builder
439     {
440         Dependency base;
441         String groupId;
442         String artifactId;
443         String version;
444         String type;
445         String classifier;
446         String scope;
447         String systemPath;
448         Collection<Exclusion> exclusions;
449         String optional;
450         Map<Object, InputLocation> locations;
451         InputLocation importedFrom;
452 
453         protected Builder(boolean withDefaults) {
454             if (withDefaults) {
455                 this.type = "jar";
456             }
457         }
458 
459         protected Builder(Dependency base, boolean forceCopy) {
460             if (forceCopy) {
461                 this.groupId = base.groupId;
462                 this.artifactId = base.artifactId;
463                 this.version = base.version;
464                 this.type = base.type;
465                 this.classifier = base.classifier;
466                 this.scope = base.scope;
467                 this.systemPath = base.systemPath;
468                 this.exclusions = base.exclusions;
469                 this.optional = base.optional;
470                 this.locations = base.locations;
471                 this.importedFrom = base.importedFrom;
472             } else {
473                 this.base = base;
474             }
475         }
476 
477         @Nonnull
478         public Builder groupId(String groupId) {
479             this.groupId = groupId;
480             return this;
481         }
482 
483         @Nonnull
484         public Builder artifactId(String artifactId) {
485             this.artifactId = artifactId;
486             return this;
487         }
488 
489         @Nonnull
490         public Builder version(String version) {
491             this.version = version;
492             return this;
493         }
494 
495         @Nonnull
496         public Builder type(String type) {
497             this.type = type;
498             return this;
499         }
500 
501         @Nonnull
502         public Builder classifier(String classifier) {
503             this.classifier = classifier;
504             return this;
505         }
506 
507         @Nonnull
508         public Builder scope(String scope) {
509             this.scope = scope;
510             return this;
511         }
512 
513         @Nonnull
514         public Builder systemPath(String systemPath) {
515             this.systemPath = systemPath;
516             return this;
517         }
518 
519         @Nonnull
520         public Builder exclusions(Collection<Exclusion> exclusions) {
521             this.exclusions = exclusions;
522             return this;
523         }
524 
525         @Nonnull
526         public Builder optional(String optional) {
527             this.optional = optional;
528             return this;
529         }
530 
531 
532         @Nonnull
533         public Builder location(Object key, InputLocation location) {
534             if (location != null) {
535                 if (!(this.locations instanceof HashMap)) {
536                     this.locations = this.locations != null ? new HashMap<>(this.locations) : new HashMap<>();
537                 }
538                 this.locations.put(key, location);
539             }
540             return this;
541         }
542 
543         @Nonnull
544         public Builder importedFrom(InputLocation importedFrom) {
545             this.importedFrom = importedFrom;
546             return this;
547         }
548 
549         @Nonnull
550         public Dependency build() {
551             // this method should not contain any logic other than creating (or reusing) an object in order to ease subclassing
552             if (base != null
553                     && (groupId == null || groupId == base.groupId)
554                     && (artifactId == null || artifactId == base.artifactId)
555                     && (version == null || version == base.version)
556                     && (type == null || type == base.type)
557                     && (classifier == null || classifier == base.classifier)
558                     && (scope == null || scope == base.scope)
559                     && (systemPath == null || systemPath == base.systemPath)
560                     && (exclusions == null || exclusions == base.exclusions)
561                     && (optional == null || optional == base.optional)
562             ) {
563                 return base;
564             }
565             return new Dependency(this);
566         }
567 
568         Map<Object, InputLocation> computeLocations() {
569             Map<Object, InputLocation> newlocs = locations != null ? locations : Map.of();
570             Map<Object, InputLocation> oldlocs = base != null ? base.locations : Map.of();
571             if (newlocs.isEmpty()) {
572                 return Map.copyOf(oldlocs);
573             }
574             if (oldlocs.isEmpty()) {
575                 return Map.copyOf(newlocs);
576             }
577             return Stream.concat(newlocs.entrySet().stream(), oldlocs.entrySet().stream())
578                     // Keep value from newlocs in case of duplicates
579                     .collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v1));
580         }
581     }
582 
583 
584             
585     public boolean isOptional() {
586         return (getOptional() != null) ? Boolean.parseBoolean(getOptional()) : false;
587     }
588 
589             
590           
591 
592             
593     /**
594      * @see java.lang.Object#toString()
595      */
596     public String toString() {
597         return "Dependency {groupId=" + getGroupId() + ", artifactId=" + getArtifactId() + ", version=" + getVersion() + ", type=" + getType() + "}";
598     }
599             
600           
601 
602             
603     private volatile String managementKey;
604 
605     /**
606      * @return the management key as {@code groupId:artifactId:type}
607      */
608     public String getManagementKey() {
609         if (managementKey == null) {
610             managementKey = (getGroupId() + ":" + getArtifactId() + ":" + getType() + (getClassifier() != null ? ":" + getClassifier() : "")).intern();
611         }
612         return managementKey;
613     }
614             
615           
616 }