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 }