API: Added methods 'getParent' and 'getDepth' to interface 'DependencyNode'.
To more easily support bottom-up graph traversals in addition to top-down.
diff --git a/aether-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java b/aether-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java
index 66a60c6..a2ffd0c 100644
--- a/aether-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java
+++ b/aether-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java
@@ -8,9 +8,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -38,6 +38,8 @@
implements DependencyNode
{
+ private DependencyNode parent;
+
private List<DependencyNode> children;
private Dependency dependency;
@@ -61,30 +63,26 @@
private Map<Object, Object> data;
/**
- * Creates a new node with the specified dependency.
- *
+ * Creates a new root node with the specified dependency.
+ *
* @param dependency The dependency associated with this node, may be {@code null} for a root node.
*/
public DefaultDependencyNode( Dependency dependency )
{
- this.dependency = dependency;
- artifact = ( dependency != null ) ? dependency.getArtifact() : null;
- children = new ArrayList<DependencyNode>( 0 );
- aliases = relocations = Collections.emptyList();
- repositories = Collections.emptyList();
- context = "";
- data = Collections.emptyMap();
+ this( null, dependency );
}
/**
* Creates a new root node with the specified artifact as its label. Note that the new node has no dependency, i.e.
* {@link #getDependency()} will return {@code null}. Put differently, the specified artifact will not be subject to
* dependency collection/resolution.
- *
+ *
* @param artifact The artifact to use as label for this node, may be {@code null}.
*/
public DefaultDependencyNode( Artifact artifact )
{
+ super();
+ this.parent = null;
this.artifact = artifact;
children = new ArrayList<DependencyNode>( 0 );
aliases = relocations = Collections.emptyList();
@@ -96,11 +94,13 @@
/**
* Creates a mostly shallow clone of the specified node. The new node has its own copy of any custom data and
* initially no children.
- *
+ *
* @param node The node to copy, must not be {@code null}.
*/
public DefaultDependencyNode( DependencyNode node )
{
+ super();
+ parent = node.getParent();
dependency = node.getDependency();
artifact = node.getArtifact();
children = new ArrayList<DependencyNode>( 0 );
@@ -115,6 +115,37 @@
setData( data.isEmpty() ? null : new HashMap<Object, Object>( data ) );
}
+ /**
+ * Creates a new node with the specified dependency.
+ *
+ * @param parent The parent node of the node or {@code null}.
+ * @param dependency The dependency associated with this node, may be {@code null} for a root node.
+ *
+ * @since 1.2
+ */
+ public DefaultDependencyNode( DependencyNode parent, Dependency dependency )
+ {
+ super();
+ this.parent = parent;
+ this.dependency = dependency;
+ artifact = ( dependency != null ) ? dependency.getArtifact() : null;
+ children = new ArrayList<DependencyNode>( 0 );
+ aliases = relocations = Collections.emptyList();
+ repositories = Collections.emptyList();
+ context = "";
+ data = Collections.emptyMap();
+ }
+
+ public long getDepth()
+ {
+ return this.getParent() != null ? this.getParent().getDepth() + 1L : 0L;
+ }
+
+ public DependencyNode getParent()
+ {
+ return this.parent;
+ }
+
public List<DependencyNode> getChildren()
{
return children;
@@ -159,7 +190,7 @@
/**
* Sets the sequence of relocations that was followed to resolve this dependency's artifact.
- *
+ *
* @param relocations The sequence of relocations, may be {@code null}.
*/
public void setRelocations( List<? extends Artifact> relocations )
@@ -181,7 +212,7 @@
/**
* Sets the known aliases for this dependency's artifact.
- *
+ *
* @param aliases The known aliases, may be {@code null}.
*/
public void setAliases( Collection<? extends Artifact> aliases )
@@ -203,7 +234,7 @@
/**
* Sets the version constraint that was parsed from the dependency's version declaration.
- *
+ *
* @param versionConstraint The version constraint for this node, may be {@code null}.
*/
public void setVersionConstraint( VersionConstraint versionConstraint )
@@ -218,7 +249,7 @@
/**
* Sets the version that was selected for the dependency's target artifact.
- *
+ *
* @param version The parsed version, may be {@code null}.
*/
public void setVersion( Version version )
@@ -251,9 +282,9 @@
/**
* Sets a bit field indicating which attributes of this node were subject to dependency management.
- *
+ *
* @param managedBits The bit field indicating the managed attributes or {@code 0} if dependency management wasn't
- * applied.
+ * applied.
*/
public void setManagedBits( int managedBits )
{
@@ -267,7 +298,7 @@
/**
* Sets the remote repositories from which this node's artifact shall be resolved.
- *
+ *
* @param repositories The remote repositories to use for artifact resolution, may be {@code null}.
*/
public void setRepositories( List<RemoteRepository> repositories )
diff --git a/aether-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java b/aether-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java
index 2551043..da30124 100644
--- a/aether-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java
+++ b/aether-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java
@@ -8,9 +8,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -34,7 +34,7 @@
* discover multiple paths leading to the same node instance unless the input graph is known to be a duplicate-free
* tree. <em>Note:</em> Unless otherwise noted, implementation classes are not thread-safe and dependency nodes should
* not be mutated by concurrent threads.
- *
+ *
* @noimplement This interface is not intended to be implemented by clients.
* @noextend This interface is not intended to be extended by clients.
*/
@@ -43,52 +43,70 @@
/**
* A bit flag indicating the dependency version was subject to dependency management
- *
+ *
* @see #getManagedBits()
*/
int MANAGED_VERSION = 0x01;
/**
* A bit flag indicating the dependency scope was subject to dependency management
- *
+ *
* @see #getManagedBits()
*/
int MANAGED_SCOPE = 0x02;
/**
* A bit flag indicating the optional flag was subject to dependency management
- *
+ *
* @see #getManagedBits()
*/
int MANAGED_OPTIONAL = 0x04;
/**
* A bit flag indicating the artifact properties were subject to dependency management
- *
+ *
* @see #getManagedBits()
*/
int MANAGED_PROPERTIES = 0x08;
/**
* A bit flag indicating the exclusions were subject to dependency management
- *
+ *
* @see #getManagedBits()
*/
int MANAGED_EXCLUSIONS = 0x10;
/**
+ * Gets the depth of the node.
+ *
+ * @return The depth of the node.
+ *
+ * @since 1.2
+ */
+ long getDepth();
+
+ /**
+ * Gets the parent node of this node.
+ *
+ * @return The parent node of this node or {@code null}, if this node is the root of the graph.
+ *
+ * @since 1.2
+ */
+ DependencyNode getParent();
+
+ /**
* Gets the child nodes of this node. To conserve memory, dependency nodes with equal dependencies may share the
* same child list instance. Hence clients mutating the child list need to be aware that these changes might affect
* more than this node. Where this is not desired, the child list should be copied before mutation if the client
* cannot be sure whether it might be shared with other nodes in the graph.
- *
+ *
* @return The child nodes of this node, never {@code null}.
*/
List<DependencyNode> getChildren();
/**
* Sets the child nodes of this node.
- *
+ *
* @param children The child nodes, may be {@code null}
*/
void setChildren( List<DependencyNode> children );
@@ -97,7 +115,7 @@
* Gets the dependency associated with this node. <em>Note:</em> For dependency graphs that have been constructed
* without a root dependency, this method will yield {@code null} when invoked on the graph's root node. The root
* node of such graphs may however still have a label as returned by {@link #getArtifact()}.
- *
+ *
* @return The dependency or {@code null} if none.
*/
Dependency getDependency();
@@ -106,7 +124,7 @@
* Gets the artifact associated with this node. If this node is associated with a dependency, this is equivalent to
* {@code getDependency().getArtifact()}. Otherwise the artifact merely provides a label for this node in which case
* the artifact must not be subjected to dependency collection/resolution.
- *
+ *
* @return The associated artifact or {@code null} if none.
*/
Artifact getArtifact();
@@ -115,14 +133,14 @@
* Updates the artifact of the dependency after resolution. The new artifact must have the same coordinates as the
* original artifact. This method may only be invoked if this node actually has a dependency, i.e. if
* {@link #getDependency()} is not null.
- *
+ *
* @param artifact The artifact satisfying the dependency, must not be {@code null}.
*/
void setArtifact( Artifact artifact );
/**
* Gets the sequence of relocations that was followed to resolve the artifact referenced by the dependency.
- *
+ *
* @return The (read-only) sequence of relocations, never {@code null}.
*/
List<? extends Artifact> getRelocations();
@@ -131,21 +149,21 @@
* Gets the known aliases for this dependency's artifact. An alias can be used to mark a patched rebuild of some
* other artifact as such, thereby allowing conflict resolution to consider the patched and the original artifact as
* a conflict.
- *
+ *
* @return The (read-only) set of known aliases, never {@code null}.
*/
Collection<? extends Artifact> getAliases();
/**
* Gets the version constraint that was parsed from the dependency's version declaration.
- *
+ *
* @return The version constraint for this node or {@code null}.
*/
VersionConstraint getVersionConstraint();
/**
* Gets the version that was selected for the dependency's target artifact.
- *
+ *
* @return The parsed version or {@code null}.
*/
Version getVersion();
@@ -153,7 +171,7 @@
/**
* Sets the scope of the dependency. This method may only be invoked if this node actually has a dependency, i.e. if
* {@link #getDependency()} is not null.
- *
+ *
* @param scope The scope, may be {@code null}.
*/
void setScope( String scope );
@@ -161,14 +179,14 @@
/**
* Sets the optional flag of the dependency. This method may only be invoked if this node actually has a dependency,
* i.e. if {@link #getDependency()} is not null.
- *
+ *
* @param optional The optional flag, may be {@code null}.
*/
void setOptional( Boolean optional );
/**
* Gets a bit field indicating which attributes of this node were subject to dependency management.
- *
+ *
* @return A bit field containing any of the bits {@link #MANAGED_VERSION}, {@link #MANAGED_SCOPE},
* {@link #MANAGED_OPTIONAL}, {@link #MANAGED_PROPERTIES} and {@link #MANAGED_EXCLUSIONS} if the
* corresponding attribute was set via dependency management.
@@ -177,21 +195,21 @@
/**
* Gets the remote repositories from which this node's artifact shall be resolved.
- *
+ *
* @return The (read-only) list of remote repositories to use for artifact resolution, never {@code null}.
*/
List<RemoteRepository> getRepositories();
/**
* Gets the request context in which this dependency node was created.
- *
+ *
* @return The request context, never {@code null}.
*/
String getRequestContext();
/**
* Sets the request context in which this dependency node was created.
- *
+ *
* @param context The context, may be {@code null}.
*/
void setRequestContext( String context );
@@ -200,14 +218,14 @@
* Gets the custom data associated with this dependency node. Clients of the repository system can use this data to
* annotate dependency nodes with domain-specific information. Note that the returned map is read-only and
* {@link #setData(Object, Object)} needs to be used to update the custom data.
- *
+ *
* @return The (read-only) key-value mappings, never {@code null}.
*/
Map<?, ?> getData();
/**
* Sets the custom data associated with this dependency node.
- *
+ *
* @param data The new custom data, may be {@code null}.
*/
void setData( Map<Object, Object> data );
@@ -215,7 +233,7 @@
/**
* Associates the specified dependency node data with the given key. <em>Note:</em> This method must not be called
* while {@link #getData()} is being iterated.
- *
+ *
* @param key The key under which to store the data, must not be {@code null}.
* @param value The data to associate with the key, may be {@code null} to remove the mapping.
*/
@@ -223,7 +241,7 @@
/**
* Traverses this node and potentially its children using the specified visitor.
- *
+ *
* @param visitor The visitor to call back, must not be {@code null}.
* @return {@code true} to visit siblings nodes of this node as well, {@code false} to skip siblings.
*/
diff --git a/aether-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultDependencyCollector.java b/aether-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultDependencyCollector.java
index 62a8ff2..4fb8374 100644
--- a/aether-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultDependencyCollector.java
+++ b/aether-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultDependencyCollector.java
@@ -8,9 +8,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -431,8 +431,8 @@
if ( cycleNode.getDependency() != null )
{
DefaultDependencyNode child =
- createDependencyNode( relocations, preManaged, rangeResult, version, d, descriptorResult,
- cycleNode );
+ createDependencyNode( node, relocations, preManaged, rangeResult, version, d,
+ descriptorResult, cycleNode );
node.getChildren().add( child );
continue;
}
@@ -456,7 +456,7 @@
getRemoteRepositories( rangeResult.getRepository( version ), repositories );
DefaultDependencyNode child =
- createDependencyNode( relocations, preManaged, rangeResult, version, d,
+ createDependencyNode( node, relocations, preManaged, rangeResult, version, d,
descriptorResult.getAliases(), repos, args.request.getRequestContext() );
node.getChildren().add( child );
@@ -475,7 +475,7 @@
List<RemoteRepository> repos =
getRemoteRepositories( rangeResult.getRepository( version ), repositories );
DefaultDependencyNode child =
- createDependencyNode( relocations, preManaged, rangeResult, version, d, null, repos,
+ createDependencyNode( node, relocations, preManaged, rangeResult, version, d, null, repos,
args.request.getRequestContext() );
node.getChildren().add( child );
}
@@ -560,13 +560,14 @@
return descriptorResult;
}
- private static DefaultDependencyNode createDependencyNode( List<Artifact> relocations,
+ private static DefaultDependencyNode createDependencyNode( DependencyNode parent,
+ List<Artifact> relocations,
PremanagedDependency preManaged,
VersionRangeResult rangeResult, Version version,
Dependency d, Collection<Artifact> aliases,
List<RemoteRepository> repos, String requestContext )
{
- DefaultDependencyNode child = new DefaultDependencyNode( d );
+ DefaultDependencyNode child = new DefaultDependencyNode( parent, d );
preManaged.applyTo( child );
child.setRelocations( relocations );
child.setVersionConstraint( rangeResult.getVersionConstraint() );
@@ -577,15 +578,18 @@
return child;
}
- private static DefaultDependencyNode createDependencyNode( List<Artifact> relocations,
+ private static DefaultDependencyNode createDependencyNode( DependencyNode parent,
+ List<Artifact> relocations,
PremanagedDependency preManaged,
VersionRangeResult rangeResult, Version version,
Dependency d, ArtifactDescriptorResult descriptorResult,
DependencyNode cycleNode )
{
DefaultDependencyNode child =
- createDependencyNode( relocations, preManaged, rangeResult, version, d, descriptorResult.getAliases(),
- cycleNode.getRepositories(), cycleNode.getRequestContext() );
+ createDependencyNode( parent, relocations, preManaged, rangeResult, version, d,
+ descriptorResult.getAliases(), cycleNode.getRepositories(),
+ cycleNode.getRequestContext() );
+
child.setChildren( cycleNode.getChildren() );
return child;
}
diff --git a/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java b/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java
index 7976487..e4deefb 100644
--- a/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java
+++ b/aether-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java
@@ -8,9 +8,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -46,7 +46,7 @@
/**
* Creates a dependency graph from a text description. <h2>Definition</h2> Each (non-empty) line in the input defines
* one node of the resulting graph:
- *
+ *
* <pre>
* line ::= (indent? ("(null)" | node | reference))? comment?
* comment ::= "#" rest-of-line
@@ -55,7 +55,7 @@
* node ::= coords (range)? space (scope("<" premanagedScope)?)? space "optional"? space ("relocations=" coords ("," coords)*)? ("(" id ")")?
* coords ::= groupId ":" artifactId (":" extension (":" classifier)?)? ":" version
* </pre>
- *
+ *
* The special token {@code (null)} may be used to indicate an "empty" root node with no dependency.
* <p>
* If {@code indent} is empty, the line defines the root node. Only one root node may be defined. The level is
@@ -64,7 +64,7 @@
* The {@code ^id} syntax allows to reuse a previously built node to share common sub graphs among different parent
* nodes.
* <h2>Example</h2>
- *
+ *
* <pre>
* gid:aid:ver
* +- gid:aid2:ver scope
@@ -72,7 +72,7 @@
* +- gid:aid4:ext:ver scope
* \- ^id1 # reuse previous node
* </pre>
- *
+ *
* <h2>Multiple definitions in one resource</h2>
* <p>
* By using {@link #parseMultiResource(String)}, definitions divided by a line beginning with "---" can be read from the
@@ -83,12 +83,12 @@
* {@link #DependencyGraphParser(String, Collection)}). Every '%s' in the definition will be substituted by the next
* String in the defined substitutions.
* <h3>Example</h3>
- *
+ *
* <pre>
* parser.setSubstitutions( "foo", "bar" );
* String def = "gid:%s:ext:ver\n" + "+- gid:%s:ext:ver";
* </pre>
- *
+ *
* The first node will have "foo" as its artifact id, the second node (child to the first) will have "bar" as its
* artifact id.
*/
@@ -103,7 +103,7 @@
/**
* Create a parser with the given prefix and the given substitution strings.
- *
+ *
* @see DependencyGraphParser#parseResource(String)
*/
public DependencyGraphParser( String prefix, Collection<String> substitutions )
@@ -115,7 +115,7 @@
/**
* Create a parser with the given prefix.
- *
+ *
* @see DependencyGraphParser#parseResource(String)
*/
public DependencyGraphParser( String prefix )
@@ -338,7 +338,7 @@
{
DefaultArtifact artifact = new DefaultArtifact( def.coords, def.properties );
Dependency dependency = new Dependency( artifact, def.scope, def.optional );
- node = new DefaultDependencyNode( dependency );
+ node = new DefaultDependencyNode( parent, dependency );
int managedBits = 0;
if ( def.premanagedScope != null )
{