001package org.eclipse.aether.collection;
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.Collections;
024import java.util.List;
025
026import org.eclipse.aether.RepositorySystem;
027import org.eclipse.aether.RequestTrace;
028import org.eclipse.aether.artifact.Artifact;
029import org.eclipse.aether.graph.Dependency;
030import org.eclipse.aether.repository.RemoteRepository;
031
032/**
033 * A request to collect the transitive dependencies and to build a dependency graph from them. There are three ways to
034 * create a dependency graph. First, only the root dependency can be given. Second, a root dependency and direct
035 * dependencies can be specified in which case the specified direct dependencies are merged with the direct dependencies
036 * retrieved from the artifact descriptor of the root dependency. And last, only direct dependencies can be specified in
037 * which case the root node of the resulting graph has no associated dependency.
038 * 
039 * @see RepositorySystem#collectDependencies(org.eclipse.aether.RepositorySystemSession, CollectRequest)
040 */
041public final class CollectRequest
042{
043
044    private Artifact rootArtifact;
045
046    private Dependency root;
047
048    private List<Dependency> dependencies = Collections.emptyList();
049
050    private List<Dependency> managedDependencies = Collections.emptyList();
051
052    private List<RemoteRepository> repositories = Collections.emptyList();
053
054    private String context = "";
055
056    private RequestTrace trace;
057
058    /**
059     * Creates an uninitialized request.
060     */
061    public CollectRequest()
062    {
063        // enables default constructor
064    }
065
066    /**
067     * Creates a request with the specified properties.
068     * 
069     * @param root The root dependency whose transitive dependencies should be collected, may be {@code null}.
070     * @param repositories The repositories to use for the collection, may be {@code null}.
071     */
072    public CollectRequest( Dependency root, List<RemoteRepository> repositories )
073    {
074        setRoot( root );
075        setRepositories( repositories );
076    }
077
078    /**
079     * Creates a new request with the specified properties.
080     * 
081     * @param root The root dependency whose transitive dependencies should be collected, may be {@code null}.
082     * @param dependencies The direct dependencies to merge with the direct dependencies from the root dependency's
083     *            artifact descriptor.
084     * @param repositories The repositories to use for the collection, may be {@code null}.
085     */
086    public CollectRequest( Dependency root, List<Dependency> dependencies, List<RemoteRepository> repositories )
087    {
088        setRoot( root );
089        setDependencies( dependencies );
090        setRepositories( repositories );
091    }
092
093    /**
094     * Creates a new request with the specified properties.
095     * 
096     * @param dependencies The direct dependencies of some imaginary root, may be {@code null}.
097     * @param managedDependencies The dependency management information to apply to the transitive dependencies, may be
098     *            {@code null}.
099     * @param repositories The repositories to use for the collection, may be {@code null}.
100     */
101    public CollectRequest( List<Dependency> dependencies, List<Dependency> managedDependencies,
102                           List<RemoteRepository> repositories )
103    {
104        setDependencies( dependencies );
105        setManagedDependencies( managedDependencies );
106        setRepositories( repositories );
107    }
108
109    /**
110     * Gets the root artifact for the dependency graph.
111     * 
112     * @return The root artifact for the dependency graph or {@code null} if none.
113     */
114    public Artifact getRootArtifact()
115    {
116        return rootArtifact;
117    }
118
119    /**
120     * Sets the root artifact for the dependency graph. This must not be confused with {@link #setRoot(Dependency)}: The
121     * root <em>dependency</em>, like any other specified dependency, will be subject to dependency
122     * collection/resolution, i.e. should have an artifact descriptor and a corresponding artifact file. The root
123     * <em>artifact</em> on the other hand is only used as a label for the root node of the graph in case no root
124     * dependency was specified. As such, the configured root artifact is ignored if {@link #getRoot()} does not return
125     * {@code null}.
126     * 
127     * @param rootArtifact The root artifact for the dependency graph, may be {@code null}.
128     * @return This request for chaining, never {@code null}.
129     */
130    public CollectRequest setRootArtifact( Artifact rootArtifact )
131    {
132        this.rootArtifact = rootArtifact;
133        return this;
134    }
135
136    /**
137     * Gets the root dependency of the graph.
138     * 
139     * @return The root dependency of the graph or {@code null} if none.
140     */
141    public Dependency getRoot()
142    {
143        return root;
144    }
145
146    /**
147     * Sets the root dependency of the graph.
148     * 
149     * @param root The root dependency of the graph, may be {@code null}.
150     * @return This request for chaining, never {@code null}.
151     */
152    public CollectRequest setRoot( Dependency root )
153    {
154        this.root = root;
155        return this;
156    }
157
158    /**
159     * Gets the direct dependencies.
160     * 
161     * @return The direct dependencies, never {@code null}.
162     */
163    public List<Dependency> getDependencies()
164    {
165        return dependencies;
166    }
167
168    /**
169     * Sets the direct dependencies. If both a root dependency and direct dependencies are given in the request, the
170     * direct dependencies from the request will be merged with the direct dependencies from the root dependency's
171     * artifact descriptor, giving higher priority to the dependencies from the request.
172     * 
173     * @param dependencies The direct dependencies, may be {@code null}.
174     * @return This request for chaining, never {@code null}.
175     */
176    public CollectRequest setDependencies( List<Dependency> dependencies )
177    {
178        if ( dependencies == null )
179        {
180            this.dependencies = Collections.emptyList();
181        }
182        else
183        {
184            this.dependencies = dependencies;
185        }
186        return this;
187    }
188
189    /**
190     * Adds the specified direct dependency.
191     * 
192     * @param dependency The dependency to add, may be {@code null}.
193     * @return This request for chaining, never {@code null}.
194     */
195    public CollectRequest addDependency( Dependency dependency )
196    {
197        if ( dependency != null )
198        {
199            if ( this.dependencies.isEmpty() )
200            {
201                this.dependencies = new ArrayList<>();
202            }
203            this.dependencies.add( dependency );
204        }
205        return this;
206    }
207
208    /**
209     * Gets the dependency management to apply to transitive dependencies.
210     * 
211     * @return The dependency management to apply to transitive dependencies, never {@code null}.
212     */
213    public List<Dependency> getManagedDependencies()
214    {
215        return managedDependencies;
216    }
217
218    /**
219     * Sets the dependency management to apply to transitive dependencies. To clarify, this management does not apply to
220     * the direct dependencies of the root node.
221     * 
222     * @param managedDependencies The dependency management, may be {@code null}.
223     * @return This request for chaining, never {@code null}.
224     */
225    public CollectRequest setManagedDependencies( List<Dependency> managedDependencies )
226    {
227        if ( managedDependencies == null )
228        {
229            this.managedDependencies = Collections.emptyList();
230        }
231        else
232        {
233            this.managedDependencies = managedDependencies;
234        }
235        return this;
236    }
237
238    /**
239     * Adds the specified managed dependency.
240     * 
241     * @param managedDependency The managed dependency to add, may be {@code null}.
242     * @return This request for chaining, never {@code null}.
243     */
244    public CollectRequest addManagedDependency( Dependency managedDependency )
245    {
246        if ( managedDependency != null )
247        {
248            if ( this.managedDependencies.isEmpty() )
249            {
250                this.managedDependencies = new ArrayList<>();
251            }
252            this.managedDependencies.add( managedDependency );
253        }
254        return this;
255    }
256
257    /**
258     * Gets the repositories to use for the collection.
259     * 
260     * @return The repositories to use for the collection, never {@code null}.
261     */
262    public List<RemoteRepository> getRepositories()
263    {
264        return repositories;
265    }
266
267    /**
268     * Sets the repositories to use for the collection.
269     * 
270     * @param repositories The repositories to use for the collection, may be {@code null}.
271     * @return This request for chaining, never {@code null}.
272     */
273    public CollectRequest setRepositories( List<RemoteRepository> repositories )
274    {
275        if ( repositories == null )
276        {
277            this.repositories = Collections.emptyList();
278        }
279        else
280        {
281            this.repositories = repositories;
282        }
283        return this;
284    }
285
286    /**
287     * Adds the specified repository for collection.
288     * 
289     * @param repository The repository to collect dependency information from, may be {@code null}.
290     * @return This request for chaining, never {@code null}.
291     */
292    public CollectRequest addRepository( RemoteRepository repository )
293    {
294        if ( repository != null )
295        {
296            if ( this.repositories.isEmpty() )
297            {
298                this.repositories = new ArrayList<>();
299            }
300            this.repositories.add( repository );
301        }
302        return this;
303    }
304
305    /**
306     * Gets the context in which this request is made.
307     * 
308     * @return The context, never {@code null}.
309     */
310    public String getRequestContext()
311    {
312        return context;
313    }
314
315    /**
316     * Sets the context in which this request is made.
317     * 
318     * @param context The context, may be {@code null}.
319     * @return This request for chaining, never {@code null}.
320     */
321    public CollectRequest setRequestContext( String context )
322    {
323        this.context = ( context != null ) ? context : "";
324        return this;
325    }
326
327    /**
328     * Gets the trace information that describes the higher level request/operation in which this request is issued.
329     * 
330     * @return The trace information about the higher level operation or {@code null} if none.
331     */
332    public RequestTrace getTrace()
333    {
334        return trace;
335    }
336
337    /**
338     * Sets the trace information that describes the higher level request/operation in which this request is issued.
339     * 
340     * @param trace The trace information about the higher level operation, may be {@code null}.
341     * @return This request for chaining, never {@code null}.
342     */
343    public CollectRequest setTrace( RequestTrace trace )
344    {
345        this.trace = trace;
346        return this;
347    }
348
349    @Override
350    public String toString()
351    {
352        return getRoot() + " -> " + getDependencies() + " < " + getRepositories();
353    }
354
355}