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.util.filter;
020
021import java.util.Collection;
022import java.util.Collections;
023import java.util.LinkedHashSet;
024import java.util.List;
025import java.util.Set;
026
027import org.eclipse.aether.graph.DependencyFilter;
028import org.eclipse.aether.graph.DependencyNode;
029
030import static java.util.Objects.requireNonNull;
031
032/**
033 * A dependency filter that combines zero or more other filters using a logical {@code AND}. The resulting filter
034 * accepts a given dependency node if and only if all constituent filters accept it.
035 */
036public final class AndDependencyFilter implements DependencyFilter {
037
038    private final Set<DependencyFilter> filters = new LinkedHashSet<>();
039
040    /**
041     * Creates a new filter from the specified filters. Prefer {@link #newInstance(DependencyFilter, DependencyFilter)}
042     * if any of the input filters might be {@code null}.
043     *
044     * @param filters The filters to combine, may be {@code null} but must not contain {@code null} elements.
045     */
046    public AndDependencyFilter(DependencyFilter... filters) {
047        if (filters != null) {
048            Collections.addAll(this.filters, filters);
049        }
050    }
051
052    /**
053     * Creates a new filter from the specified filters.
054     *
055     * @param filters The filters to combine, may be {@code null} but must not contain {@code null} elements.
056     */
057    public AndDependencyFilter(Collection<DependencyFilter> filters) {
058        if (filters != null) {
059            this.filters.addAll(filters);
060        }
061    }
062
063    /**
064     * Creates a new filter from the specified filters.
065     *
066     * @param filter1 The first filter to combine, may be {@code null}.
067     * @param filter2 The second filter to combine, may be {@code null}.
068     * @return The combined filter or {@code null} if both filter were {@code null}.
069     */
070    public static DependencyFilter newInstance(DependencyFilter filter1, DependencyFilter filter2) {
071        if (filter1 == null) {
072            return filter2;
073        } else if (filter2 == null) {
074            return filter1;
075        }
076        return new AndDependencyFilter(filter1, filter2);
077    }
078
079    public boolean accept(DependencyNode node, List<DependencyNode> parents) {
080        requireNonNull(node, "node cannot be null");
081        requireNonNull(parents, "parents cannot be null");
082        for (DependencyFilter filter : filters) {
083            if (!filter.accept(node, parents)) {
084                return false;
085            }
086        }
087        return true;
088    }
089
090    @Override
091    public boolean equals(Object obj) {
092        if (this == obj) {
093            return true;
094        }
095
096        if (obj == null || !getClass().equals(obj.getClass())) {
097            return false;
098        }
099
100        AndDependencyFilter that = (AndDependencyFilter) obj;
101
102        return this.filters.equals(that.filters);
103    }
104
105    @Override
106    public int hashCode() {
107        int hash = getClass().hashCode();
108        hash = hash * 31 + filters.hashCode();
109        return hash;
110    }
111}