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  
29  import org.eclipse.aether.artifact.Artifact;
30  import org.eclipse.aether.repository.RemoteRepository;
31  import org.eclipse.aether.version.Version;
32  import org.eclipse.aether.version.VersionConstraint;
33  
34  /**
35   * A node within a dependency graph.
36   */
37  public final class DefaultDependencyNode
38      implements DependencyNode
39  {
40  
41      private List<DependencyNode> children;
42  
43      private Dependency dependency;
44  
45      private Artifact artifact;
46  
47      private List<? extends Artifact> relocations;
48  
49      private Collection<? extends Artifact> aliases;
50  
51      private VersionConstraint versionConstraint;
52  
53      private Version version;
54  
55      private byte managedBits;
56  
57      private List<RemoteRepository> repositories;
58  
59      private String context;
60  
61      private Map<Object, Object> data;
62  
63      /**
64       * Creates a new node with the specified dependency.
65       * 
66       * @param dependency The dependency associated with this node, may be {@code null} for a root node.
67       */
68      public DefaultDependencyNode( Dependency dependency )
69      {
70          this.dependency = dependency;
71          artifact = ( dependency != null ) ? dependency.getArtifact() : null;
72          children = new ArrayList<DependencyNode>( 0 );
73          aliases = relocations = Collections.emptyList();
74          repositories = Collections.emptyList();
75          context = "";
76          data = Collections.emptyMap();
77      }
78  
79      /**
80       * Creates a new root node with the specified artifact as its label. Note that the new node has no dependency, i.e.
81       * {@link #getDependency()} will return {@code null}. Put differently, the specified artifact will not be subject to
82       * dependency collection/resolution.
83       * 
84       * @param artifact The artifact to use as label for this node, may be {@code null}.
85       */
86      public DefaultDependencyNode( Artifact artifact )
87      {
88          this.artifact = artifact;
89          children = new ArrayList<DependencyNode>( 0 );
90          aliases = relocations = Collections.emptyList();
91          repositories = Collections.emptyList();
92          context = "";
93          data = Collections.emptyMap();
94      }
95  
96      /**
97       * Creates a mostly shallow clone of the specified node. The new node has its own copy of any custom data and
98       * initially no children.
99       * 
100      * @param node The node to copy, must not be {@code null}.
101      */
102     public DefaultDependencyNode( DependencyNode node )
103     {
104         dependency = node.getDependency();
105         artifact = node.getArtifact();
106         children = new ArrayList<DependencyNode>( 0 );
107         setAliases( node.getAliases() );
108         setRequestContext( node.getRequestContext() );
109         setManagedBits( node.getManagedBits() );
110         setRelocations( node.getRelocations() );
111         setRepositories( node.getRepositories() );
112         setVersion( node.getVersion() );
113         setVersionConstraint( node.getVersionConstraint() );
114         Map<?, ?> data = node.getData();
115         setData( data.isEmpty() ? null : new HashMap<Object, Object>( data ) );
116     }
117 
118     public List<DependencyNode> getChildren()
119     {
120         return children;
121     }
122 
123     public void setChildren( List<DependencyNode> children )
124     {
125         if ( children == null )
126         {
127             this.children = new ArrayList<DependencyNode>( 0 );
128         }
129         else
130         {
131             this.children = children;
132         }
133     }
134 
135     public Dependency getDependency()
136     {
137         return dependency;
138     }
139 
140     public Artifact getArtifact()
141     {
142         return artifact;
143     }
144 
145     public void setArtifact( Artifact artifact )
146     {
147         if ( dependency == null )
148         {
149             throw new UnsupportedOperationException( "node does not have a dependency" );
150         }
151         dependency = dependency.setArtifact( artifact );
152         this.artifact = dependency.getArtifact();
153     }
154 
155     public List<? extends Artifact> getRelocations()
156     {
157         return relocations;
158     }
159 
160     /**
161      * Sets the sequence of relocations that was followed to resolve this dependency's artifact.
162      * 
163      * @param relocations The sequence of relocations, may be {@code null}.
164      */
165     public void setRelocations( List<? extends Artifact> relocations )
166     {
167         if ( relocations == null || relocations.isEmpty() )
168         {
169             this.relocations = Collections.emptyList();
170         }
171         else
172         {
173             this.relocations = relocations;
174         }
175     }
176 
177     public Collection<? extends Artifact> getAliases()
178     {
179         return aliases;
180     }
181 
182     /**
183      * Sets the known aliases for this dependency's artifact.
184      * 
185      * @param aliases The known aliases, may be {@code null}.
186      */
187     public void setAliases( Collection<? extends Artifact> aliases )
188     {
189         if ( aliases == null || aliases.isEmpty() )
190         {
191             this.aliases = Collections.emptyList();
192         }
193         else
194         {
195             this.aliases = aliases;
196         }
197     }
198 
199     public VersionConstraint getVersionConstraint()
200     {
201         return versionConstraint;
202     }
203 
204     /**
205      * Sets the version constraint that was parsed from the dependency's version declaration.
206      * 
207      * @param versionConstraint The version constraint for this node, may be {@code null}.
208      */
209     public void setVersionConstraint( VersionConstraint versionConstraint )
210     {
211         this.versionConstraint = versionConstraint;
212     }
213 
214     public Version getVersion()
215     {
216         return version;
217     }
218 
219     /**
220      * Sets the version that was selected for the dependency's target artifact.
221      * 
222      * @param version The parsed version, may be {@code null}.
223      */
224     public void setVersion( Version version )
225     {
226         this.version = version;
227     }
228 
229     public void setScope( String scope )
230     {
231         if ( dependency == null )
232         {
233             throw new UnsupportedOperationException( "node does not have a dependency" );
234         }
235         dependency = dependency.setScope( scope );
236     }
237 
238     public void setOptional( Boolean optional )
239     {
240         if ( dependency == null )
241         {
242             throw new UnsupportedOperationException( "node does not have a dependency" );
243         }
244         dependency = dependency.setOptional( optional );
245     }
246 
247     public int getManagedBits()
248     {
249         return managedBits;
250     }
251 
252     /**
253      * Sets a bit field indicating which attributes of this node were subject to dependency management.
254      * 
255      * @param managedBits The bit field indicating the managed attributes or {@code 0} if dependency management wasn't
256      *            applied.
257      */
258     public void setManagedBits( int managedBits )
259     {
260         this.managedBits = (byte) ( managedBits & 0x1F );
261     }
262 
263     public List<RemoteRepository> getRepositories()
264     {
265         return repositories;
266     }
267 
268     /**
269      * Sets the remote repositories from which this node's artifact shall be resolved.
270      * 
271      * @param repositories The remote repositories to use for artifact resolution, may be {@code null}.
272      */
273     public void setRepositories( List<RemoteRepository> repositories )
274     {
275         if ( repositories == null || repositories.isEmpty() )
276         {
277             this.repositories = Collections.emptyList();
278         }
279         else
280         {
281             this.repositories = repositories;
282         }
283     }
284 
285     public String getRequestContext()
286     {
287         return context;
288     }
289 
290     public void setRequestContext( String context )
291     {
292         this.context = ( context != null ) ? context : "";
293     }
294 
295     public Map<Object, Object> getData()
296     {
297         return data;
298     }
299 
300     public void setData( Map<Object, Object> data )
301     {
302         if ( data == null )
303         {
304             this.data = Collections.emptyMap();
305         }
306         else
307         {
308             this.data = data;
309         }
310     }
311 
312     public void setData( Object key, Object value )
313     {
314         if ( key == null )
315         {
316             throw new IllegalArgumentException( "key must not be null" );
317         }
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<Object, Object>( 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 }