001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.eclipse.aether.resolution;
020
021import java.util.ArrayList;
022import java.util.Collection;
023import java.util.Collections;
024import java.util.List;
025import java.util.Map;
026
027import org.eclipse.aether.RepositorySystem;
028import org.eclipse.aether.artifact.Artifact;
029import org.eclipse.aether.graph.Dependency;
030import org.eclipse.aether.repository.ArtifactRepository;
031import org.eclipse.aether.repository.RemoteRepository;
032
033import static java.util.Objects.requireNonNull;
034
035/**
036 * The result from reading an artifact descriptor.
037 *
038 * @see RepositorySystem#readArtifactDescriptor(org.eclipse.aether.RepositorySystemSession, ArtifactDescriptorRequest)
039 */
040public final class ArtifactDescriptorResult {
041
042    private final ArtifactDescriptorRequest request;
043
044    private List<Exception> exceptions;
045
046    private List<Artifact> relocations;
047
048    private Collection<Artifact> aliases;
049
050    private Artifact artifact;
051
052    private ArtifactRepository repository;
053
054    private List<Dependency> dependencies;
055
056    private List<Dependency> managedDependencies;
057
058    private List<RemoteRepository> repositories;
059
060    private Map<String, Object> properties;
061
062    /**
063     * Creates a new result for the specified request.
064     *
065     * @param request The descriptor request, must not be {@code null}.
066     */
067    public ArtifactDescriptorResult(ArtifactDescriptorRequest request) {
068        this.request = requireNonNull(request, "artifact descriptor request cannot be null");
069        artifact = request.getArtifact();
070        exceptions = Collections.emptyList();
071        relocations = Collections.emptyList();
072        aliases = Collections.emptyList();
073        dependencies = Collections.emptyList();
074        managedDependencies = Collections.emptyList();
075        repositories = Collections.emptyList();
076        properties = Collections.emptyMap();
077    }
078
079    /**
080     * Gets the descriptor request that was made.
081     *
082     * @return The descriptor request, never {@code null}.
083     */
084    public ArtifactDescriptorRequest getRequest() {
085        return request;
086    }
087
088    /**
089     * Gets the exceptions that occurred while reading the artifact descriptor.
090     *
091     * @return The exceptions that occurred, never {@code null}.
092     */
093    public List<Exception> getExceptions() {
094        return exceptions;
095    }
096
097    /**
098     * Sets the exceptions that occurred while reading the artifact descriptor.
099     *
100     * @param exceptions The exceptions that occurred, may be {@code null}.
101     * @return This result for chaining, never {@code null}.
102     */
103    public ArtifactDescriptorResult setExceptions(List<Exception> exceptions) {
104        if (exceptions == null) {
105            this.exceptions = Collections.emptyList();
106        } else {
107            this.exceptions = exceptions;
108        }
109        return this;
110    }
111
112    /**
113     * Records the specified exception while reading the artifact descriptor.
114     *
115     * @param exception The exception to record, may be {@code null}.
116     * @return This result for chaining, never {@code null}.
117     */
118    public ArtifactDescriptorResult addException(Exception exception) {
119        if (exception != null) {
120            if (exceptions.isEmpty()) {
121                exceptions = new ArrayList<>();
122            }
123            exceptions.add(exception);
124        }
125        return this;
126    }
127
128    /**
129     * Gets the relocations that were processed to read the artifact descriptor. The returned list denotes the hops that
130     * lead to the final artifact coordinates as given by {@link #getArtifact()}.
131     *
132     * @return The relocations that were processed, never {@code null}.
133     */
134    public List<Artifact> getRelocations() {
135        return relocations;
136    }
137
138    /**
139     * Sets the relocations that were processed to read the artifact descriptor.
140     *
141     * @param relocations The relocations that were processed, may be {@code null}.
142     * @return This result for chaining, never {@code null}.
143     */
144    public ArtifactDescriptorResult setRelocations(List<Artifact> relocations) {
145        if (relocations == null) {
146            this.relocations = Collections.emptyList();
147        } else {
148            this.relocations = relocations;
149        }
150        return this;
151    }
152
153    /**
154     * Records the specified relocation hop while locating the artifact descriptor.
155     *
156     * @param artifact The artifact that got relocated, may be {@code null}.
157     * @return This result for chaining, never {@code null}.
158     */
159    public ArtifactDescriptorResult addRelocation(Artifact artifact) {
160        if (artifact != null) {
161            if (relocations.isEmpty()) {
162                relocations = new ArrayList<>();
163            }
164            relocations.add(artifact);
165        }
166        return this;
167    }
168
169    /**
170     * Gets the known aliases for this artifact. An alias denotes a different artifact with (almost) the same contents
171     * and can be used to mark a patched rebuild of some other artifact as such, thereby allowing conflict resolution to
172     * consider the patched and the original artifact as a conflict.
173     *
174     * @return The aliases of the artifact, never {@code null}.
175     */
176    public Collection<Artifact> getAliases() {
177        return aliases;
178    }
179
180    /**
181     * Sets the aliases of the artifact.
182     *
183     * @param aliases The aliases of the artifact, may be {@code null}.
184     * @return This result for chaining, never {@code null}.
185     */
186    public ArtifactDescriptorResult setAliases(Collection<Artifact> aliases) {
187        if (aliases == null) {
188            this.aliases = Collections.emptyList();
189        } else {
190            this.aliases = aliases;
191        }
192        return this;
193    }
194
195    /**
196     * Records the specified alias.
197     *
198     * @param alias The alias for the artifact, may be {@code null}.
199     * @return This result for chaining, never {@code null}.
200     */
201    public ArtifactDescriptorResult addAlias(Artifact alias) {
202        if (alias != null) {
203            if (aliases.isEmpty()) {
204                aliases = new ArrayList<>();
205            }
206            aliases.add(alias);
207        }
208        return this;
209    }
210
211    /**
212     * Gets the artifact whose descriptor was read. This can be a different artifact than originally requested in case
213     * relocations were encountered.
214     *
215     * @return The artifact after following any relocations, never {@code null}.
216     */
217    public Artifact getArtifact() {
218        return artifact;
219    }
220
221    /**
222     * Sets the artifact whose descriptor was read.
223     *
224     * @param artifact The artifact whose descriptor was read, may be {@code null}.
225     * @return This result for chaining, never {@code null}.
226     */
227    public ArtifactDescriptorResult setArtifact(Artifact artifact) {
228        this.artifact = artifact;
229        return this;
230    }
231
232    /**
233     * Gets the repository from which the descriptor was eventually resolved.
234     *
235     * @return The repository from which the descriptor was resolved or {@code null} if unknown.
236     */
237    public ArtifactRepository getRepository() {
238        return repository;
239    }
240
241    /**
242     * Sets the repository from which the descriptor was resolved.
243     *
244     * @param repository The repository from which the descriptor was resolved, may be {@code null}.
245     * @return This result for chaining, never {@code null}.
246     */
247    public ArtifactDescriptorResult setRepository(ArtifactRepository repository) {
248        this.repository = repository;
249        return this;
250    }
251
252    /**
253     * Gets the list of direct dependencies of the artifact.
254     *
255     * @return The list of direct dependencies, never {@code null}
256     */
257    public List<Dependency> getDependencies() {
258        return dependencies;
259    }
260
261    /**
262     * Sets the list of direct dependencies of the artifact.
263     *
264     * @param dependencies The list of direct dependencies, may be {@code null}
265     * @return This result for chaining, never {@code null}.
266     */
267    public ArtifactDescriptorResult setDependencies(List<Dependency> dependencies) {
268        if (dependencies == null) {
269            this.dependencies = Collections.emptyList();
270        } else {
271            this.dependencies = dependencies;
272        }
273        return this;
274    }
275
276    /**
277     * Adds the specified direct dependency.
278     *
279     * @param dependency The direct dependency to add, may be {@code null}.
280     * @return This result for chaining, never {@code null}.
281     */
282    public ArtifactDescriptorResult addDependency(Dependency dependency) {
283        if (dependency != null) {
284            if (dependencies.isEmpty()) {
285                dependencies = new ArrayList<>();
286            }
287            dependencies.add(dependency);
288        }
289        return this;
290    }
291
292    /**
293     * Gets the dependency management information.
294     *
295     * @return The dependency management information.
296     */
297    public List<Dependency> getManagedDependencies() {
298        return managedDependencies;
299    }
300
301    /**
302     * Sets the dependency management information.
303     *
304     * @param dependencies The dependency management information, may be {@code null}.
305     * @return This result for chaining, never {@code null}.
306     */
307    public ArtifactDescriptorResult setManagedDependencies(List<Dependency> dependencies) {
308        if (dependencies == null) {
309            this.managedDependencies = Collections.emptyList();
310        } else {
311            this.managedDependencies = dependencies;
312        }
313        return this;
314    }
315
316    /**
317     * Adds the specified managed dependency.
318     *
319     * @param dependency The managed dependency to add, may be {@code null}.
320     * @return This result for chaining, never {@code null}.
321     */
322    public ArtifactDescriptorResult addManagedDependency(Dependency dependency) {
323        if (dependency != null) {
324            if (managedDependencies.isEmpty()) {
325                managedDependencies = new ArrayList<>();
326            }
327            managedDependencies.add(dependency);
328        }
329        return this;
330    }
331
332    /**
333     * Gets the remote repositories listed in the artifact descriptor.
334     *
335     * @return The remote repositories listed in the artifact descriptor, never {@code null}.
336     */
337    public List<RemoteRepository> getRepositories() {
338        return repositories;
339    }
340
341    /**
342     * Sets the remote repositories listed in the artifact descriptor.
343     *
344     * @param repositories The remote repositories listed in the artifact descriptor, may be {@code null}.
345     * @return This result for chaining, never {@code null}.
346     */
347    public ArtifactDescriptorResult setRepositories(List<RemoteRepository> repositories) {
348        if (repositories == null) {
349            this.repositories = Collections.emptyList();
350        } else {
351            this.repositories = repositories;
352        }
353        return this;
354    }
355
356    /**
357     * Adds the specified remote repository.
358     *
359     * @param repository The remote repository to add, may be {@code null}.
360     * @return This result for chaining, never {@code null}.
361     */
362    public ArtifactDescriptorResult addRepository(RemoteRepository repository) {
363        if (repository != null) {
364            if (repositories.isEmpty()) {
365                repositories = new ArrayList<>();
366            }
367            repositories.add(repository);
368        }
369        return this;
370    }
371
372    /**
373     * Gets any additional information about the artifact in form of key-value pairs. <em>Note:</em> Regardless of their
374     * actual type, all property values must be treated as being read-only.
375     *
376     * @return The additional information about the artifact, never {@code null}.
377     */
378    public Map<String, Object> getProperties() {
379        return properties;
380    }
381
382    /**
383     * Sets any additional information about the artifact in form of key-value pairs.
384     *
385     * @param properties The additional information about the artifact, may be {@code null}.
386     * @return This result for chaining, never {@code null}.
387     */
388    public ArtifactDescriptorResult setProperties(Map<String, Object> properties) {
389        if (properties == null) {
390            this.properties = Collections.emptyMap();
391        } else {
392            this.properties = properties;
393        }
394        return this;
395    }
396
397    @Override
398    public String toString() {
399        return getArtifact() + " -> " + getDependencies();
400    }
401}