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