View Javadoc
1   package org.eclipse.aether.util.graph.selector;
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.Arrays;
24  import java.util.Collection;
25  import java.util.HashSet;
26  import java.util.TreeSet;
27  
28  import org.eclipse.aether.collection.DependencyCollectionContext;
29  import org.eclipse.aether.collection.DependencySelector;
30  import org.eclipse.aether.graph.Dependency;
31  
32  /**
33   * A dependency selector that filters transitive dependencies based on their scope. Direct dependencies are always
34   * included regardless of their scope. <em>Note:</em> This filter does not assume any relationships between the scopes.
35   * In particular, the filter is not aware of scopes that logically include other scopes.
36   * 
37   * @see Dependency#getScope()
38   */
39  public final class ScopeDependencySelector
40      implements DependencySelector
41  {
42  
43      private final boolean transitive;
44  
45      private final Collection<String> included;
46  
47      private final Collection<String> excluded;
48  
49      /**
50       * Creates a new selector using the specified includes and excludes.
51       * 
52       * @param included The set of scopes to include, may be {@code null} or empty to include any scope.
53       * @param excluded The set of scopes to exclude, may be {@code null} or empty to exclude no scope.
54       */
55      public ScopeDependencySelector( Collection<String> included, Collection<String> excluded )
56      {
57          transitive = false;
58          this.included = clone( included );
59          this.excluded = clone( excluded );
60      }
61  
62      private static Collection<String> clone( Collection<String> scopes )
63      {
64          Collection<String> copy;
65          if ( scopes == null || scopes.isEmpty() )
66          {
67              // checking for null is faster than isEmpty()
68              copy = null;
69          }
70          else
71          {
72              copy = new HashSet<String>( scopes );
73              if ( copy.size() <= 2 )
74              {
75                  // contains() is faster for smallish array (sorted for equals()!)
76                  copy = new ArrayList<String>( new TreeSet<String>( copy ) );
77              }
78          }
79          return copy;
80      }
81  
82      /**
83       * Creates a new selector using the specified excludes.
84       * 
85       * @param excluded The set of scopes to exclude, may be {@code null} or empty to exclude no scope.
86       */
87      public ScopeDependencySelector( String... excluded )
88      {
89          this( null, ( excluded != null ) ? Arrays.asList( excluded ) : null );
90      }
91  
92      private ScopeDependencySelector( boolean transitive, Collection<String> included, Collection<String> excluded )
93      {
94          this.transitive = transitive;
95          this.included = included;
96          this.excluded = excluded;
97      }
98  
99      public boolean selectDependency( Dependency dependency )
100     {
101         if ( !transitive )
102         {
103             return true;
104         }
105 
106         String scope = dependency.getScope();
107         return ( included == null || included.contains( scope ) ) && ( excluded == null || !excluded.contains( scope ) );
108     }
109 
110     public DependencySelector deriveChildSelector( DependencyCollectionContext context )
111     {
112         if ( this.transitive || context.getDependency() == null )
113         {
114             return this;
115         }
116 
117         return new ScopeDependencySelector( true, included, excluded );
118     }
119 
120     @Override
121     public boolean equals( Object obj )
122     {
123         if ( this == obj )
124         {
125             return true;
126         }
127         else if ( null == obj || !getClass().equals( obj.getClass() ) )
128         {
129             return false;
130         }
131 
132         ScopeDependencySelector that = (ScopeDependencySelector) obj;
133         return transitive == that.transitive && eq( included, that.included ) && eq( excluded, that.excluded );
134     }
135 
136     private static <T> boolean eq( T o1, T o2 )
137     {
138         return ( o1 != null ) ? o1.equals( o2 ) : o2 == null;
139     }
140 
141     @Override
142     public int hashCode()
143     {
144         int hash = 17;
145         hash = hash * 31 + ( transitive ? 1 : 0 );
146         hash = hash * 31 + ( included != null ? included.hashCode() : 0 );
147         hash = hash * 31 + ( excluded != null ? excluded.hashCode() : 0 );
148         return hash;
149     }
150 
151 }