org.eclipse.aether.graph.Dependency Maven / Gradle / Ivy
/*******************************************************************************
* 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.AbstractSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.NoSuchElementException;
import java.util.Set;
import org.eclipse.aether.artifact.Artifact;
/**
* A dependency to some artifact. Note: Instances of this class are immutable and the exposed mutators return
* new objects rather than changing the current instance.
*/
public final class Dependency
{
private final Artifact artifact;
private final String scope;
private final Boolean optional;
private final Set exclusions;
/**
* Creates a mandatory dependency on the specified artifact with the given scope.
*
* @param artifact The artifact being depended on, must not be {@code null}.
* @param scope The scope of the dependency, may be {@code null}.
*/
public Dependency( Artifact artifact, String scope )
{
this( artifact, scope, false );
}
/**
* Creates a dependency on the specified artifact with the given scope.
*
* @param artifact The artifact being depended on, must not be {@code null}.
* @param scope The scope of the dependency, may be {@code null}.
* @param optional A flag whether the dependency is optional or mandatory, may be {@code null}.
*/
public Dependency( Artifact artifact, String scope, Boolean optional )
{
this( artifact, scope, optional, null );
}
/**
* Creates a dependency on the specified artifact with the given scope and exclusions.
*
* @param artifact The artifact being depended on, must not be {@code null}.
* @param scope The scope of the dependency, may be {@code null}.
* @param optional A flag whether the dependency is optional or mandatory, may be {@code null}.
* @param exclusions The exclusions that apply to transitive dependencies, may be {@code null} if none.
*/
public Dependency( Artifact artifact, String scope, Boolean optional, Collection exclusions )
{
this( artifact, scope, Exclusions.copy( exclusions ), optional );
}
private Dependency( Artifact artifact, String scope, Set exclusions, Boolean optional )
{
// NOTE: This constructor assumes immutability of the provided exclusion collection, for internal use only
if ( artifact == null )
{
throw new IllegalArgumentException( "no artifact specified for dependency" );
}
this.artifact = artifact;
this.scope = ( scope != null ) ? scope : "";
this.optional = optional;
this.exclusions = exclusions;
}
/**
* Gets the artifact being depended on.
*
* @return The artifact, never {@code null}.
*/
public Artifact getArtifact()
{
return artifact;
}
/**
* Sets the artifact being depended on.
*
* @param artifact The artifact, must not be {@code null}.
* @return The new dependency, never {@code null}.
*/
public Dependency setArtifact( Artifact artifact )
{
if ( this.artifact.equals( artifact ) )
{
return this;
}
return new Dependency( artifact, scope, exclusions, optional );
}
/**
* Gets the scope of the dependency. The scope defines in which context this dependency is relevant.
*
* @return The scope or an empty string if not set, never {@code null}.
*/
public String getScope()
{
return scope;
}
/**
* Sets the scope of the dependency, e.g. "compile".
*
* @param scope The scope of the dependency, may be {@code null}.
* @return The new dependency, never {@code null}.
*/
public Dependency setScope( String scope )
{
if ( this.scope.equals( scope ) || ( scope == null && this.scope.length() <= 0 ) )
{
return this;
}
return new Dependency( artifact, scope, exclusions, optional );
}
/**
* Indicates whether this dependency is optional or not. Optional dependencies can be ignored in some contexts.
*
* @return {@code true} if the dependency is (definitively) optional, {@code false} otherwise.
*/
public boolean isOptional()
{
return Boolean.TRUE.equals( optional );
}
/**
* Gets the optional flag for the dependency. Note: Most clients will usually call {@link #isOptional()} to
* determine the optional flag, this method is for advanced use cases where three-valued logic is required.
*
* @return The optional flag or {@code null} if unspecified.
*/
public Boolean getOptional()
{
return optional;
}
/**
* Sets the optional flag for the dependency.
*
* @param optional {@code true} if the dependency is optional, {@code false} if the dependency is mandatory, may be
* {@code null} if unspecified.
* @return The new dependency, never {@code null}.
*/
public Dependency setOptional( Boolean optional )
{
if ( eq( this.optional, optional ) )
{
return this;
}
return new Dependency( artifact, scope, exclusions, optional );
}
/**
* Gets the exclusions for this dependency. Exclusions can be used to remove transitive dependencies during
* resolution.
*
* @return The (read-only) exclusions, never {@code null}.
*/
public Collection getExclusions()
{
return exclusions;
}
/**
* Sets the exclusions for the dependency.
*
* @param exclusions The exclusions, may be {@code null}.
* @return The new dependency, never {@code null}.
*/
public Dependency setExclusions( Collection exclusions )
{
if ( hasEquivalentExclusions( exclusions ) )
{
return this;
}
return new Dependency( artifact, scope, optional, exclusions );
}
private boolean hasEquivalentExclusions( Collection exclusions )
{
if ( exclusions == null || exclusions.isEmpty() )
{
return this.exclusions.isEmpty();
}
if ( exclusions instanceof Set )
{
return this.exclusions.equals( exclusions );
}
return exclusions.size() >= this.exclusions.size() && this.exclusions.containsAll( exclusions )
&& exclusions.containsAll( this.exclusions );
}
@Override
public String toString()
{
return String.valueOf( getArtifact() ) + " (" + getScope() + ( isOptional() ? "?" : "" ) + ")";
}
@Override
public boolean equals( Object obj )
{
if ( obj == this )
{
return true;
}
else if ( obj == null || !getClass().equals( obj.getClass() ) )
{
return false;
}
Dependency that = (Dependency) obj;
return artifact.equals( that.artifact ) && scope.equals( that.scope ) && eq( optional, that.optional )
&& exclusions.equals( that.exclusions );
}
private static boolean eq( T o1, T o2 )
{
return ( o1 != null ) ? o1.equals( o2 ) : o2 == null;
}
@Override
public int hashCode()
{
int hash = 17;
hash = hash * 31 + artifact.hashCode();
hash = hash * 31 + scope.hashCode();
hash = hash * 31 + ( optional != null ? optional.hashCode() : 0 );
hash = hash * 31 + exclusions.size();
return hash;
}
private static class Exclusions
extends AbstractSet
{
private final Exclusion[] exclusions;
public static Set copy( Collection exclusions )
{
if ( exclusions == null || exclusions.isEmpty() )
{
return Collections.emptySet();
}
return new Exclusions( exclusions );
}
private Exclusions( Collection exclusions )
{
if ( exclusions.size() > 1 && !( exclusions instanceof Set ) )
{
exclusions = new LinkedHashSet( exclusions );
}
this.exclusions = exclusions.toArray( new Exclusion[exclusions.size()] );
}
@Override
public Iterator iterator()
{
return new Iterator()
{
private int cursor = 0;
public boolean hasNext()
{
return cursor < exclusions.length;
}
public Exclusion next()
{
try
{
Exclusion exclusion = exclusions[cursor];
cursor++;
return exclusion;
}
catch ( IndexOutOfBoundsException e )
{
throw new NoSuchElementException();
}
}
public void remove()
{
throw new UnsupportedOperationException();
}
};
}
@Override
public int size()
{
return exclusions.length;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy