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