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