/******************************************************************************* * Copyright (c) 2010, 2013 Sonatype, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Sonatype, Inc. - initial API and implementation *******************************************************************************/ package org.eclipse.aether.graph; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.aether.artifact.Artifact; import org.eclipse.aether.repository.RemoteRepository; import org.eclipse.aether.version.Version; import org.eclipse.aether.version.VersionConstraint; /** * A node within a dependency graph. */ public final class DefaultDependencyNode implements DependencyNode { private List children; private Dependency dependency; private Artifact artifact; private List relocations; private Collection aliases; private VersionConstraint versionConstraint; private Version version; private byte managedBits; private List repositories; private String context; private Map data; /** * Creates a new 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( 0 ); aliases = relocations = Collections.emptyList(); repositories = Collections.emptyList(); context = ""; data = Collections.emptyMap(); } /** * 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 ) { this.artifact = artifact; children = new ArrayList( 0 ); aliases = relocations = Collections.emptyList(); repositories = Collections.emptyList(); context = ""; data = Collections.emptyMap(); } /** * 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 ) { dependency = node.getDependency(); artifact = node.getArtifact(); children = new ArrayList( 0 ); setAliases( node.getAliases() ); setRequestContext( node.getRequestContext() ); setManagedBits( node.getManagedBits() ); setRelocations( node.getRelocations() ); setRepositories( node.getRepositories() ); setVersion( node.getVersion() ); setVersionConstraint( node.getVersionConstraint() ); Map data = node.getData(); setData( data.isEmpty() ? null : new HashMap( data ) ); } public List getChildren() { return children; } public void setChildren( List children ) { if ( children == null ) { this.children = new ArrayList( 0 ); } else { this.children = children; } } public Dependency getDependency() { return dependency; } public Artifact getArtifact() { return artifact; } public void setArtifact( Artifact artifact ) { if ( dependency == null ) { throw new UnsupportedOperationException( "node does not have a dependency" ); } dependency = dependency.setArtifact( artifact ); this.artifact = dependency.getArtifact(); } public List getRelocations() { return relocations; } /** * 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 relocations ) { if ( relocations == null || relocations.isEmpty() ) { this.relocations = Collections.emptyList(); } else { this.relocations = relocations; } } public Collection getAliases() { return aliases; } /** * Sets the known aliases for this dependency's artifact. * * @param aliases The known aliases, may be {@code null}. */ public void setAliases( Collection aliases ) { if ( aliases == null || aliases.isEmpty() ) { this.aliases = Collections.emptyList(); } else { this.aliases = aliases; } } public VersionConstraint getVersionConstraint() { return versionConstraint; } /** * 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 ) { this.versionConstraint = versionConstraint; } public Version getVersion() { return version; } /** * 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 ) { this.version = version; } public void setScope( String scope ) { if ( dependency == null ) { throw new UnsupportedOperationException( "node does not have a dependency" ); } dependency = dependency.setScope( scope ); } public void setOptional( Boolean optional ) { if ( dependency == null ) { throw new UnsupportedOperationException( "node does not have a dependency" ); } dependency = dependency.setOptional( optional ); } public int getManagedBits() { return managedBits; } /** * 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. */ public void setManagedBits( int managedBits ) { this.managedBits = (byte) ( managedBits & 0x1F ); } public List getRepositories() { return repositories; } /** * 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 repositories ) { if ( repositories == null || repositories.isEmpty() ) { this.repositories = Collections.emptyList(); } else { this.repositories = repositories; } } public String getRequestContext() { return context; } public void setRequestContext( String context ) { this.context = ( context != null ) ? context : ""; } public Map getData() { return data; } public void setData( Map data ) { if ( data == null ) { this.data = Collections.emptyMap(); } else { this.data = data; } } public void setData( Object key, Object value ) { if ( key == null ) { throw new IllegalArgumentException( "key must not be null" ); } if ( value == null ) { if ( !data.isEmpty() ) { data.remove( key ); if ( data.isEmpty() ) { data = Collections.emptyMap(); } } } else { if ( data.isEmpty() ) { data = new HashMap( 1, 2 ); // nodes can be numerous so let's be space conservative } data.put( key, value ); } } public boolean accept( DependencyVisitor visitor ) { if ( visitor.visitEnter( this ) ) { for ( DependencyNode child : children ) { if ( !child.accept( visitor ) ) { break; } } } return visitor.visitLeave( this ); } @Override public String toString() { Dependency dep = getDependency(); if ( dep == null ) { return String.valueOf( getArtifact() ); } return dep.toString(); } }