/* * 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 * * http://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.tools.ant.types; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; import java.util.stream.Stream; import org.apache.tools.ant.BuildException; /** * EnumeratedAttribute for quantifier comparisons. Evaluates a * <code>boolean[]</code> or raw <code>true</code> and <code>false</code> * counts. Accepts the following values:<ul> * <li>"all"</li> - none <code>false</code> * <li>"each"</li> - none <code>false</code> * <li>"every"</li> - none <code>false</code> * <li>"any"</li> - at least one <code>true</code> * <li>"some"</li> - at least one <code>true</code> * <li>"one"</li> - exactly one <code>true</code> * <li>"majority"</li> - more <code>true</code> than <code>false</code> * <li>"most"</li> - more <code>true</code> than <code>false</code> * <li>"none"</li> - none <code>true</code> * </ul> * @since Ant 1.7 */ public class Quantifier extends EnumeratedAttribute { private static final String[] VALUES = Stream.of(Predicate.values()).map(Predicate::getNames) .flatMap(Collection::stream).toArray(String[]::new); /** ALL instance */ public static final Quantifier ALL = new Quantifier(Predicate.ALL); /** ANY instance */ public static final Quantifier ANY = new Quantifier(Predicate.ANY); /** ONE instance */ public static final Quantifier ONE = new Quantifier(Predicate.ONE); /** MAJORITY instance */ public static final Quantifier MAJORITY = new Quantifier(Predicate.MAJORITY); /** NONE instance */ public static final Quantifier NONE = new Quantifier(Predicate.NONE); private enum Predicate { ALL("all", "each", "every") { @Override boolean eval(int t, int f) { return f == 0; } }, ANY("any", "some") { @Override boolean eval(int t, int f) { return t > 0; } }, ONE("one") { @Override boolean eval(int t, int f) { return t == 1; } }, MAJORITY("majority", "most") { @Override boolean eval(int t, int f) { return t > f; } }, NONE("none") { @Override boolean eval(int t, int f) { return t == 0; } }; static Predicate get(String name) { return Stream.of(values()).filter(p -> p.names.contains(name)) .findFirst() .orElseThrow(() -> new IllegalArgumentException(name)); } final Set<String> names; Predicate(String primaryName, String... additionalNames) { Set<String> names = new LinkedHashSet<>(); names.add(primaryName); Collections.addAll(names, additionalNames); this.names = Collections.unmodifiableSet(names); } Set<String> getNames() { return names; } abstract boolean eval(int t, int f); } /** * Default constructor. */ public Quantifier() { } /** * Construct a new Quantifier with the specified value. * @param value the EnumeratedAttribute value. */ public Quantifier(String value) { setValue(value); } private Quantifier(Predicate impl) { setValue(impl.getNames().iterator().next()); } /** * Return the possible values. * @return String[] of EnumeratedAttribute values. */ @Override public String[] getValues() { return VALUES; } /** * Evaluate a <code>boolean<code> array. * @param b the <code>boolean[]</code> to evaluate. * @return true if the argument fell within the parameters of this Quantifier. */ public boolean evaluate(boolean[] b) { int t = 0; for (int i = 0; i < b.length; i++) { if (b[i]) { t++; } } return evaluate(t, b.length - t); } /** * Evaluate integer <code>true</code> vs. <code>false</code> counts. * @param t the number of <code>true</code> values. * @param f the number of <code>false</code> values. * @return true if the arguments fell within the parameters of this Quantifier. */ public boolean evaluate(int t, int f) { int index = getIndex(); if (index == -1) { throw new BuildException("Quantifier value not set."); } return Predicate.get(VALUES[index]).eval(t, f); } }