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