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