| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * https://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| package org.apache.ivy.core.module.id; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.ivy.plugins.matcher.MapMatcher; |
| import org.apache.ivy.util.Checks; |
| import org.apache.ivy.util.Message; |
| import org.apache.ivy.util.filter.Filter; |
| import org.apache.ivy.util.filter.NoFilter; |
| |
| /** |
| * A list of module specific rules. |
| * <p> |
| * This class defines a list of module specific rules. For each module only one rule apply, |
| * sometimes none. |
| * </p> |
| * <p> |
| * To know which rule to apply, they are configured using matchers. So you can define a rule |
| * applying to all module from one particular organization, or to all modules with a revisions |
| * matching a pattern, and so on. |
| * </p> |
| * <p> |
| * Rules condition are evaluated in order, so the first matching rule is returned. |
| * </p> |
| * <p> |
| * Rules themselves can be represented by any object, depending on the purpose of the rule (define |
| * which resolver to use, which TTL in cache, ...) |
| * </p> |
| * |
| * @param <T> a type parameter |
| */ |
| public class ModuleRules<T> { |
| |
| private Map<MapMatcher, T> rules = new LinkedHashMap<>(); |
| |
| private MatcherLookup matcherLookup = new MatcherLookup(); |
| |
| /** |
| * Constructs an empty ModuleRules. |
| */ |
| public ModuleRules() { |
| } |
| |
| private ModuleRules(Map<MapMatcher, T> rules) { |
| this.rules = new LinkedHashMap<>(rules); |
| for (MapMatcher matcher : rules.keySet()) { |
| matcherLookup.add(matcher); |
| } |
| } |
| |
| /** |
| * Defines a new rule for the given condition. |
| * |
| * @param condition |
| * the condition for which the rule should be applied. Must not be <code>null</code>. |
| * @param rule |
| * the rule to apply. Must not be <code>null</code>. |
| */ |
| public void defineRule(MapMatcher condition, T rule) { |
| Checks.checkNotNull(condition, "condition"); |
| Checks.checkNotNull(rule, "rule"); |
| |
| rules.put(condition, rule); |
| matcherLookup.add(condition); |
| } |
| |
| /** |
| * Returns the rule object matching the given {@link ModuleId}, or <code>null</code> if no rule |
| * applies. |
| * |
| * @param mid |
| * the {@link ModuleId} to search the rule for. Must not be <code>null</code>. |
| * @return the rule object matching the given {@link ModuleId}, or <code>null</code> if no rule |
| * applies. |
| * @see #getRule(ModuleId, Filter) |
| */ |
| public T getRule(ModuleId mid) { |
| return getRule(mid, NoFilter.<T> instance()); |
| } |
| |
| /** |
| * Returns the rules objects matching the given {@link ModuleId}, or an empty array if no rule |
| * applies. |
| * |
| * @param mid |
| * the {@link ModuleId} to search the rule for. Must not be <code>null</code>. |
| * @return an array of rule objects matching the given {@link ModuleId}. |
| */ |
| public List<T> getRules(ModuleId mid) { |
| return getRules(mid.getAttributes(), NoFilter.<T> instance()); |
| } |
| |
| /** |
| * Returns the rule object matching the given {@link ModuleRevisionId}, or <code>null</code> if |
| * no rule applies. |
| * |
| * @param mrid |
| * the {@link ModuleRevisionId} to search the rule for. Must not be <code>null</code> |
| * . |
| * @return the rule object matching the given {@link ModuleRevisionId}, or <code>null</code> if |
| * no rule applies. |
| * @see #getRule(ModuleRevisionId, Filter) |
| */ |
| public T getRule(ModuleRevisionId mrid) { |
| return getRule(mrid, NoFilter.<T> instance()); |
| } |
| |
| /** |
| * Returns the rule object matching the given {@link ModuleId} and accepted by the given |
| * {@link Filter}, or <code>null</code> if no rule applies. |
| * |
| * @param mid |
| * the {@link ModuleRevisionId} to search the rule for. Must not be <code>null</code> |
| * . |
| * @param filter |
| * the filter to use to filter the rule to return. The {@link Filter#accept(Object)} |
| * method will be called only with rule objects matching the given {@link ModuleId}, |
| * and the first rule object accepted by the filter will be returned. Must not be |
| * <code>null</code>. |
| * @return the rule object matching the given {@link ModuleId}, or <code>null</code> if no rule |
| * applies. |
| * @see #getRule(ModuleRevisionId, Filter) |
| */ |
| public T getRule(ModuleId mid, Filter<T> filter) { |
| Checks.checkNotNull(mid, "mid"); |
| return getRule(mid.getAttributes(), filter); |
| } |
| |
| /** |
| * Returns the rule object matching the given {@link ModuleRevisionId} and accepted by the given |
| * {@link Filter}, or <code>null</code> if no rule applies. |
| * |
| * @param mrid |
| * the {@link ModuleRevisionId} to search the rule for. Must not be <code>null</code> |
| * . |
| * @param filter |
| * the filter to use to filter the rule to return. The {@link Filter#accept(Object)} |
| * method will be called only with rule objects matching the given |
| * {@link ModuleRevisionId}, and the first rule object accepted by the filter will be |
| * returned. Must not be <code>null</code>. |
| * @return the rule object matching the given {@link ModuleRevisionId}, or <code>null</code> if |
| * no rule applies. |
| * @see #getRule(ModuleRevisionId) |
| */ |
| public T getRule(ModuleRevisionId mrid, Filter<T> filter) { |
| Checks.checkNotNull(mrid, "mrid"); |
| Checks.checkNotNull(filter, "filter"); |
| Map<String, String> moduleAttributes = mrid.getAttributes(); |
| return getRule(moduleAttributes, filter); |
| } |
| |
| private T getRule(Map<String, String> moduleAttributes, Filter<T> filter) { |
| for (MapMatcher midm : matcherLookup.get(moduleAttributes)) { |
| T rule = rules.get(midm); |
| if (filter.accept(rule)) { |
| return rule; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the rules object matching the given {@link ModuleRevisionId} and accepted by the |
| * given {@link Filter}, or an empty array if no rule applies. |
| * |
| * @param mrid |
| * the {@link ModuleRevisionId} to search the rule for. Must not be <code>null</code> |
| * . |
| * @param filter |
| * the filter to use to filter the rule to return. The {@link Filter#accept(Object)} |
| * method will be called only with rule objects matching the given |
| * {@link ModuleRevisionId}. Must not be <code>null</code>. |
| * @return an array of rule objects matching the given {@link ModuleRevisionId}. |
| */ |
| public List<T> getRules(ModuleRevisionId mrid, Filter<T> filter) { |
| Checks.checkNotNull(mrid, "mrid"); |
| Checks.checkNotNull(filter, "filter"); |
| Map<String, String> moduleAttributes = mrid.getAttributes(); |
| return getRules(moduleAttributes, filter); |
| } |
| |
| private List<T> getRules(Map<String, String> moduleAttributes, Filter<T> filter) { |
| List<T> matchingRules = new ArrayList<>(); |
| for (MapMatcher midm : matcherLookup.get(moduleAttributes)) { |
| T rule = rules.get(midm); |
| if (filter.accept(rule)) { |
| matchingRules.add(rule); |
| } |
| } |
| return matchingRules; |
| } |
| |
| /** |
| * Dump the list of rules to {@link Message#debug(String)} |
| * |
| * @param prefix |
| * the prefix to use for each line dumped |
| */ |
| public void dump(String prefix) { |
| if (rules.isEmpty()) { |
| Message.debug(prefix + "NONE"); |
| return; |
| } |
| for (Map.Entry<MapMatcher, T> entry : rules.entrySet()) { |
| MapMatcher midm = entry.getKey(); |
| T rule = entry.getValue(); |
| Message.debug(prefix + midm + " -> " + rule); |
| } |
| } |
| |
| /** |
| * Returns an unmodifiable view of all the rules defined on this ModuleRules. |
| * <p> |
| * The rules are returned in a Map where they keys are the MapMatchers matching the rules |
| * object, and the values are the rules object themselves. |
| * </p> |
| * |
| * @return an unmodifiable view of all the rules defined on this ModuleRules. |
| */ |
| public Map<MapMatcher, T> getAllRules() { |
| return Collections.unmodifiableMap(rules); |
| } |
| |
| public ModuleRules<T> clone() { |
| return new ModuleRules<>(rules); |
| } |
| } |