View Javadoc
1   package org.eclipse.aether.graph;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   * 
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   * 
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.Collections;
25  import java.util.HashMap;
26  import java.util.List;
27  import java.util.Map;
28  import static java.util.Objects.requireNonNull;
29  
30  import org.eclipse.aether.artifact.Artifact;
31  import org.eclipse.aether.repository.RemoteRepository;
32  import org.eclipse.aether.version.Version;
33  import org.eclipse.aether.version.VersionConstraint;
34  
35  /**
36   * A node within a dependency graph.
37   */
38  public final class DefaultDependencyNode
39      implements DependencyNode
40  {
41  
42      private List<DependencyNode> children;
43  
44      private Dependency dependency;
45  
46      private Artifact artifact;
47  
48      private List<? extends Artifact> relocations;
49  
50      private Collection<? extends Artifact> aliases;
51  
52      private VersionConstraint versionConstraint;
53  
54      private Version version;
55  
56      private byte managedBits;
57  
58      private List<RemoteRepository> repositories;
59  
60      private String context;
61  
62      private Map<Object, Object> data;
63  
64      /**
65       * Creates a new node with the specified dependency.
66       * 
67       * @param dependency The dependency associated with this node, may be {@code null} for a root node.
68       */
69      public DefaultDependencyNode( Dependency dependency )
70      {
71          this.dependency = dependency;
72          artifact = ( dependency != null ) ? dependency.getArtifact() : null;
73          children = new ArrayList<>( 0 );
74          aliases = Collections.emptyList();
75          relocations = Collections.emptyList();
76          repositories = Collections.emptyList();
77          context = "";
78          data = Collections.emptyMap();
79      }
80  
81      /**
82       * Creates a new root node with the specified artifact as its label. Note that the new node has no dependency, i.e.
83       * {@link #getDependency()} will return {@code null}. Put differently, the specified artifact will not be subject to
84       * dependency collection/resolution.
85       * 
86       * @param artifact The artifact to use as label for this node, may be {@code null}.
87       */
88      public DefaultDependencyNode( Artifact artifact )
89      {
90          this.artifact = artifact;
91          children = new ArrayList<>( 0 );
92          aliases = Collections.emptyList();
93          relocations = Collections.emptyList();
94          repositories = Collections.emptyList();
95          context = "";
96          data = Collections.emptyMap();
97      }
98  
99      /**
100      * Creates a mostly shallow clone of the specified node. The new node has its own copy of any custom data and
101      * initially no children.
102      * 
103      * @param node The node to copy, must not be {@code null}.
104      */
105     public DefaultDependencyNode( DependencyNode node )
106     {
107         dependency = node.getDependency();
108         artifact = node.getArtifact();
109         children = new ArrayList<>( 0 );
110         setAliases( node.getAliases() );
111         setRequestContext( node.getRequestContext() );
112         setManagedBits( node.getManagedBits() );
113         setRelocations( node.getRelocations() );
114         setRepositories( node.getRepositories() );
115         setVersion( node.getVersion() );
116         setVersionConstraint( node.getVersionConstraint() );
117         Map<?, ?> data = node.getData();
118         setData( data.isEmpty() ? null : new HashMap<>( data ) );
119     }
120 
121     public List<DependencyNode> getChildren()
122     {
123         return children;
124     }
125 
126     public void setChildren( List<DependencyNode> children )
127     {
128         if ( children == null )
129         {
130             this.children = new ArrayList<>( 0 );
131         }
132         else
133         {
134             this.children = children;
135         }
136     }
137 
138     public Dependency getDependency()
139     {
140         return dependency;
141     }
142 
143     public Artifact getArtifact()
144     {
145         return artifact;
146     }
147 
148     public void setArtifact( Artifact artifact )
149     {
150         if ( dependency == null )
151         {
152             throw new IllegalStateException( "node does not have a dependency" );
153         }
154         dependency = dependency.setArtifact( artifact );
155         this.artifact = dependency.getArtifact();
156     }
157 
158     public List<? extends Artifact> getRelocations()
159     {
160         return relocations;
161     }
162 
163     /**
164      * Sets the sequence of relocations that was followed to resolve this dependency's artifact.
165      * 
166      * @param relocations The sequence of relocations, may be {@code null}.
167      */
168     public void setRelocations( List<? extends Artifact> relocations )
169     {
170         if ( relocations == null || relocations.isEmpty() )
171         {
172             this.relocations = Collections.emptyList();
173         }
174         else
175         {
176             this.relocations = relocations;
177         }
178     }
179 
180     public Collection<? extends Artifact> getAliases()
181     {
182         return aliases;
183     }
184 
185     /**
186      * Sets the known aliases for this dependency's artifact.
187      * 
188      * @param aliases The known aliases, may be {@code null}.
189      */
190     public void setAliases( Collection<? extends Artifact> aliases )
191     {
192         if ( aliases == null || aliases.isEmpty() )
193         {
194             this.aliases = Collections.emptyList();
195         }
196         else
197         {
198             this.aliases = aliases;
199         }
200     }
201 
202     public VersionConstraint getVersionConstraint()
203     {
204         return versionConstraint;
205     }
206 
207     /**
208      * Sets the version constraint that was parsed from the dependency's version declaration.
209      * 
210      * @param versionConstraint The version constraint for this node, may be {@code null}.
211      */
212     public void setVersionConstraint( VersionConstraint versionConstraint )
213     {
214         this.versionConstraint = versionConstraint;
215     }
216 
217     public Version getVersion()
218     {
219         return version;
220     }
221 
222     /**
223      * Sets the version that was selected for the dependency's target artifact.
224      * 
225      * @param version The parsed version, may be {@code null}.
226      */
227     public void setVersion( Version version )
228     {
229         this.version = version;
230     }
231 
232     public void setScope( String scope )
233     {
234         if ( dependency == null )
235         {
236             throw new IllegalStateException( "node does not have a dependency" );
237         }
238         dependency = dependency.setScope( scope );
239     }
240 
241     public void setOptional( Boolean optional )
242     {
243         if ( dependency == null )
244         {
245             throw new IllegalStateException( "node does not have a dependency" );
246         }
247         dependency = dependency.setOptional( optional );
248     }
249 
250     public int getManagedBits()
251     {
252         return managedBits;
253     }
254 
255     /**
256      * Sets a bit field indicating which attributes of this node were subject to dependency management.
257      * 
258      * @param managedBits The bit field indicating the managed attributes or {@code 0} if dependency management wasn't
259      *            applied.
260      */
261     public void setManagedBits( int managedBits )
262     {
263         this.managedBits = (byte) ( managedBits & 0x1F );
264     }
265 
266     public List<RemoteRepository> getRepositories()
267     {
268         return repositories;
269     }
270 
271     /**
272      * Sets the remote repositories from which this node's artifact shall be resolved.
273      * 
274      * @param repositories The remote repositories to use for artifact resolution, may be {@code null}.
275      */
276     public void setRepositories( List<RemoteRepository> repositories )
277     {
278         if ( repositories == null || repositories.isEmpty() )
279         {
280             this.repositories = Collections.emptyList();
281         }
282         else
283         {
284             this.repositories = repositories;
285         }
286     }
287 
288     public String getRequestContext()
289     {
290         return context;
291     }
292 
293     public void setRequestContext( String context )
294     {
295         this.context = ( context != null ) ? context : "";
296     }
297 
298     public Map<Object, Object> getData()
299     {
300         return data;
301     }
302 
303     public void setData( Map<Object, Object> data )
304     {
305         if ( data == null )
306         {
307             this.data = Collections.emptyMap();
308         }
309         else
310         {
311             this.data = data;
312         }
313     }
314 
315     public void setData( Object key, Object value )
316     {
317         requireNonNull( key, "key cannot be null" );
318 
319         if ( value == null )
320         {
321             if ( !data.isEmpty() )
322             {
323                 data.remove( key );
324 
325                 if ( data.isEmpty() )
326                 {
327                     data = Collections.emptyMap();
328                 }
329             }
330         }
331         else
332         {
333             if ( data.isEmpty() )
334             {
335                 data = new HashMap<>( 1, 2 ); // nodes can be numerous so let's be space conservative
336             }
337             data.put( key, value );
338         }
339     }
340 
341     public boolean accept( DependencyVisitor visitor )
342     {
343         if ( visitor.visitEnter( this ) )
344         {
345             for ( DependencyNode child : children )
346             {
347                 if ( !child.accept( visitor ) )
348                 {
349                     break;
350                 }
351             }
352         }
353 
354         return visitor.visitLeave( this );
355     }
356 
357     @Override
358     public String toString()
359     {
360         Dependency dep = getDependency();
361         if ( dep == null )
362         {
363             return String.valueOf( getArtifact() );
364         }
365         return dep.toString();
366     }
367 
368 }