001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.eclipse.aether.internal.impl.scope; 020 021import java.util.Objects; 022 023import org.eclipse.aether.collection.DependencyCollectionContext; 024import org.eclipse.aether.collection.DependencySelector; 025import org.eclipse.aether.graph.Dependency; 026 027import static java.util.Objects.requireNonNull; 028 029/** 030 * A dependency selector that excludes optional dependencies which occur beyond given level. 031 * <p> 032 * <em>Important note:</em> equals/hashCode must factor in starting state, as instances of this class 033 * (potentially differentially configured) are used now in session, but are kept in a set. 034 * 035 * @see Dependency#isOptional() 036 */ 037public final class OptionalDependencySelector implements DependencySelector { 038 /** 039 * Excludes optional dependencies always (from root). 040 */ 041 public static OptionalDependencySelector fromRoot() { 042 return from(1); 043 } 044 045 /** 046 * Excludes optional transitive dependencies of direct dependencies. 047 */ 048 public static OptionalDependencySelector fromDirect() { 049 return from(2); 050 } 051 052 /** 053 * Excludes optional transitive dependencies from given depth (1=root, 2=direct, 3=transitives of direct ones...). 054 */ 055 public static OptionalDependencySelector from(int applyFrom) { 056 if (applyFrom < 1) { 057 throw new IllegalArgumentException("applyFrom must be non-zero and positive"); 058 } 059 return new OptionalDependencySelector(Objects.hash(applyFrom), 0, applyFrom); 060 } 061 062 private final int seed; 063 private final int depth; 064 private final int applyFrom; 065 066 private OptionalDependencySelector(int seed, int depth, int applyFrom) { 067 this.seed = seed; 068 this.depth = depth; 069 this.applyFrom = applyFrom; 070 } 071 072 @Override 073 public boolean selectDependency(Dependency dependency) { 074 requireNonNull(dependency, "dependency cannot be null"); 075 return depth < applyFrom || !dependency.isOptional(); 076 } 077 078 @Override 079 public DependencySelector deriveChildSelector(DependencyCollectionContext context) { 080 requireNonNull(context, "context cannot be null"); 081 return new OptionalDependencySelector(seed, depth + 1, applyFrom); 082 } 083 084 @Override 085 public boolean equals(Object obj) { 086 if (this == obj) { 087 return true; 088 } else if (null == obj || !getClass().equals(obj.getClass())) { 089 return false; 090 } 091 092 OptionalDependencySelector that = (OptionalDependencySelector) obj; 093 return seed == that.seed && depth == that.depth && applyFrom == that.applyFrom; 094 } 095 096 @Override 097 public int hashCode() { 098 int hash = getClass().hashCode(); 099 hash = hash * 31 + seed; 100 hash = hash * 31 + depth; 101 hash = hash * 31 + applyFrom; 102 return hash; 103 } 104 105 @Override 106 public String toString() { 107 return String.format("%s(applied: %s)", this.getClass().getSimpleName(), depth >= applyFrom); 108 } 109}