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<DependencyNode>( 0 );
74          aliases = relocations = Collections.emptyList();
75          repositories = Collections.emptyList();
76          context = "";
77          data = Collections.emptyMap();
78      }
79  
80      /**
81       * Creates a new root node with the specified artifact as its label. Note that the new node has no dependency, i.e.
82       * {@link #getDependency()} will return {@code null}. Put differently, the specified artifact will not be subject to
83       * dependency collection/resolution.
84       * 
85       * @param artifact The artifact to use as label for this node, may be {@code null}.
86       */
87      public DefaultDependencyNode( Artifact artifact )
88      {
89          this.artifact = artifact;
90          children = new ArrayList<DependencyNode>( 0 );
91          aliases = relocations = Collections.emptyList();
92          repositories = Collections.emptyList();
93          context = "";
94          data = Collections.emptyMap();
95      }
96  
97      /**
98       * Creates a mostly shallow clone of the specified node. The new node has its own copy of any custom data and
99       * initially no children.
100      * 
101      * @param node The node to copy, must not be {@code null}.
102      */
103     public DefaultDependencyNode( DependencyNode node )
104     {
105         dependency = node.getDependency();
106         artifact = node.getArtifact();
107         children = new ArrayList<DependencyNode>( 0 );
108         setAliases( node.getAliases() );
109         setRequestContext( node.getRequestContext() );
110         setManagedBits( node.getManagedBits() );
111         setRelocations( node.getRelocations() );
112         setRepositories( node.getRepositories() );
113         setVersion( node.getVersion() );
114         setVersionConstraint( node.getVersionConstraint() );
115         Map<?, ?> data = node.getData();
116         setData( data.isEmpty() ? null : new HashMap<Object, Object>( data ) );
117     }
118 
119     public List<DependencyNode> getChildren()
120     {
121         return children;
122     }
123 
124     public void setChildren( List<DependencyNode> children )
125     {
126         if ( children == null )
127         {
128             this.children = new ArrayList<DependencyNode>( 0 );
129         }
130         else
131         {
132             this.children = children;
133         }
134     }
135 
136     public Dependency getDependency()
137     {
138         return dependency;
139     }
140 
141     public Artifact getArtifact()
142     {
143         return artifact;
144     }
145 
146     public void setArtifact( Artifact artifact )
147     {
148         if ( dependency == null )
149         {
150             throw new IllegalStateException( "node does not have a dependency" );
151         }
152         dependency = dependency.setArtifact( artifact );
153         this.artifact = dependency.getArtifact();
154     }
155 
156     public List<? extends Artifact> getRelocations()
157     {
158         return relocations;
159     }
160 
161     /**
162      * Sets the sequence of relocations that was followed to resolve this dependency's artifact.
163      * 
164      * @param relocations The sequence of relocations, may be {@code null}.
165      */
166     public void setRelocations( List<? extends Artifact> relocations )
167     {
168         if ( relocations == null || relocations.isEmpty() )
169         {
170             this.relocations = Collections.emptyList();
171         }
172         else
173         {
174             this.relocations = relocations;
175         }
176     }
177 
178     public Collection<? extends Artifact> getAliases()
179     {
180         return aliases;
181     }
182 
183     /**
184      * Sets the known aliases for this dependency's artifact.
185      * 
186      * @param aliases The known aliases, may be {@code null}.
187      */
188     public void setAliases( Collection<? extends Artifact> aliases )
189     {
190         if ( aliases == null || aliases.isEmpty() )
191         {
192             this.aliases = Collections.emptyList();
193         }
194         else
195         {
196             this.aliases = aliases;
197         }
198     }
199 
200     public VersionConstraint getVersionConstraint()
201     {
202         return versionConstraint;
203     }
204 
205     /**
206      * Sets the version constraint that was parsed from the dependency's version declaration.
207      * 
208      * @param versionConstraint The version constraint for this node, may be {@code null}.
209      */
210     public void setVersionConstraint( VersionConstraint versionConstraint )
211     {
212         this.versionConstraint = versionConstraint;
213     }
214 
215     public Version getVersion()
216     {
217         return version;
218     }
219 
220     /**
221      * Sets the version that was selected for the dependency's target artifact.
222      * 
223      * @param version The parsed version, may be {@code null}.
224      */
225     public void setVersion( Version version )
226     {
227         this.version = version;
228     }
229 
230     public void setScope( String scope )
231     {
232         if ( dependency == null )
233         {
234             throw new IllegalStateException( "node does not have a dependency" );
235         }
236         dependency = dependency.setScope( scope );
237     }
238 
239     public void setOptional( Boolean optional )
240     {
241         if ( dependency == null )
242         {
243             throw new IllegalStateException( "node does not have a dependency" );
244         }
245         dependency = dependency.setOptional( optional );
246     }
247 
248     public int getManagedBits()
249     {
250         return managedBits;
251     }
252 
253     /**
254      * Sets a bit field indicating which attributes of this node were subject to dependency management.
255      * 
256      * @param managedBits The bit field indicating the managed attributes or {@code 0} if dependency management wasn't
257      *            applied.
258      */
259     public void setManagedBits( int managedBits )
260     {
261         this.managedBits = (byte) ( managedBits & 0x1F );
262     }
263 
264     public List<RemoteRepository> getRepositories()
265     {
266         return repositories;
267     }
268 
269     /**
270      * Sets the remote repositories from which this node's artifact shall be resolved.
271      * 
272      * @param repositories The remote repositories to use for artifact resolution, may be {@code null}.
273      */
274     public void setRepositories( List<RemoteRepository> repositories )
275     {
276         if ( repositories == null || repositories.isEmpty() )
277         {
278             this.repositories = Collections.emptyList();
279         }
280         else
281         {
282             this.repositories = repositories;
283         }
284     }
285 
286     public String getRequestContext()
287     {
288         return context;
289     }
290 
291     public void setRequestContext( String context )
292     {
293         this.context = ( context != null ) ? context : "";
294     }
295 
296     public Map<Object, Object> getData()
297     {
298         return data;
299     }
300 
301     public void setData( Map<Object, Object> data )
302     {
303         if ( data == null )
304         {
305             this.data = Collections.emptyMap();
306         }
307         else
308         {
309             this.data = data;
310         }
311     }
312 
313     public void setData( Object key, Object value )
314     {
315         requireNonNull( key, "key cannot be null" );
316 
317         if ( value == null )
318         {
319             if ( !data.isEmpty() )
320             {
321                 data.remove( key );
322 
323                 if ( data.isEmpty() )
324                 {
325                     data = Collections.emptyMap();
326                 }
327             }
328         }
329         else
330         {
331             if ( data.isEmpty() )
332             {
333                 data = new HashMap<Object, Object>( 1, 2 ); // nodes can be numerous so let's be space conservative
334             }
335             data.put( key, value );
336         }
337     }
338 
339     public boolean accept( DependencyVisitor visitor )
340     {
341         if ( visitor.visitEnter( this ) )
342         {
343             for ( DependencyNode child : children )
344             {
345                 if ( !child.accept( visitor ) )
346                 {
347                     break;
348                 }
349             }
350         }
351 
352         return visitor.visitLeave( this );
353     }
354 
355     @Override
356     public String toString()
357     {
358         Dependency dep = getDependency();
359         if ( dep == null )
360         {
361             return String.valueOf( getArtifact() );
362         }
363         return dep.toString();
364     }
365 
366 }