| // *************************************************************************************************************************** |
| // * 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.juneau.assertions; |
| |
| import static org.apache.juneau.assertions.AssertionPredicate.*; |
| import static org.apache.juneau.common.internal.ArgUtils.*; |
| import static org.apache.juneau.common.internal.StringUtils.*; |
| |
| import java.text.*; |
| import java.util.*; |
| import java.util.function.*; |
| import java.util.regex.*; |
| |
| import org.apache.juneau.common.internal.*; |
| import org.apache.juneau.cp.*; |
| |
| /** |
| * Predefined {@link AssertionPredicate} objects. |
| * |
| * <p> |
| * Typically used wherever predicates are allowed for testing of {@link Assertion} objects such as... |
| * <ul> |
| * <li>{@link FluentObjectAssertion#is(Predicate)} |
| * <li>{@link FluentArrayAssertion#is(Predicate...)} |
| * <li>{@link FluentPrimitiveArrayAssertion#is(Predicate...)} |
| * <li>{@link FluentListAssertion#isEach(Predicate...)} |
| * </ul> |
| * |
| * <h5 class='section'>Example:</h5> |
| * <p class='bjava'> |
| * <jc>// Asserts that a list contains te specified values.</jc> |
| * List<Object> <jv>myList</jv> = AList.<jsm>of</jsm>(...); |
| * <jsm>assertList</jsm>(<jv>myList</jv>) |
| * .is(<jsm>eq</jsm>(<js>"foo"</js>), <jsm>any</jsm>(), <jsm>match</jsm>(<js>"bar*"</js>)); |
| * </p> |
| * |
| * <h5 class='section'>See Also:</h5> |
| * <ul> |
| * <li class='link'><a class="doclink" href="../../../../index.html#ja.Overview">Overview > juneau-assertions > Overview</a> |
| * </ul> |
| */ |
| public class AssertionPredicates { |
| |
| private static Function<Object,String> TYPENAME = x -> x == null ? null : x.getClass().getName(); |
| |
| private static final Messages MESSAGES = Messages.of(AssertionPredicates.class, "Messages"); |
| private static final String |
| MSG_valueWasNull = MESSAGES.getString("valueWasNull"), |
| MSG_valueWasNotNull = MESSAGES.getString("valueWasNotNull"), |
| MSG_valueDidNotMatchExpected = MESSAGES.getString("valueDidNotMatchExpected"), |
| MSG_valueDidNotContainExpected = MESSAGES.getString("valueDidNotContainExpected"), |
| MSG_valueUnexpectedlyMatched = MESSAGES.getString("valueUnexpectedlyMatched"), |
| MSG_valueWasNotExpectedType = MESSAGES.getString("valueWasNotExpectedType"), |
| MSG_valueDidNotMatchPattern = MESSAGES.getString("valueDidNotMatchPattern"); |
| |
| /** |
| * Predicate that always returns <jk>true</jk>. |
| * |
| * <p> |
| * Note that this typically has the same affect as a <jk>null</jk> predicate. |
| * |
| * @param <T> The object type being tested. |
| * @return A new predicate. |
| */ |
| public static final <T> AssertionPredicate<T> any() { |
| return test(x -> true, null); |
| } |
| |
| /** |
| * Predicate that returns <jk>true</jk> if the tested value is not null. |
| * |
| * <p> |
| * Assertion error message is <js>"Value was null."</js>. |
| * |
| * @param <T> The object type being tested. |
| * @return A new predicate. |
| */ |
| public static final <T> AssertionPredicate<T> notNull() { |
| return test(x -> x != null, MSG_valueWasNull); |
| } |
| |
| /** |
| * Predicate that returns <jk>true</jk> if the tested value is null. |
| * |
| * <p> |
| * Assertion error message is <js>"Value was not null."</js>. |
| * |
| * @param <T> The object type being tested. |
| * @return A new predicate. |
| */ |
| public static final <T> AssertionPredicate<T> isNull() { |
| return test(x -> x == null, MSG_valueWasNotNull); |
| } |
| |
| /** |
| * Predicate that returns <jk>true</jk> if the tested value equals the specified value. |
| * |
| * <p> |
| * Uses standard Java equality for testing. |
| * |
| * <p> |
| * Assertion error message is <js>"Value did not match expected. Expected='{0}', Actual='{1}'."</js>. |
| * |
| * @param <T> The object type being tested. |
| * @param value The specified value. |
| * @return A new predicate. |
| */ |
| public static final <T> AssertionPredicate<T> eq(Object value) { |
| return test(x -> Objects.equals(x, value), MSG_valueDidNotMatchExpected, value, VALUE); |
| } |
| |
| /** |
| * Predicate that returns <jk>true</jk> if the tested value converted to a string matches the specified value. |
| * |
| * <p> |
| * Assertion error message is <js>"Value did not match expected. Expected='{0}', Actual='{1}'."</js>. |
| * |
| * @param <T> The object type being tested. |
| * @param value The specified value. |
| * @return A new predicate. |
| */ |
| public static final <T> AssertionPredicate<T> eq(String value) { |
| return test(x -> Objects.equals(stringify(x), value), MSG_valueDidNotMatchExpected, value, VALUE); |
| } |
| |
| /** |
| * Predicate that returns <jk>true</jk> if the tested value does not match the specified value. |
| * |
| * <p> |
| * Assertion error message is <js>"Value unexpectedly matched. Value='{0}'."</js>. |
| * |
| * @param <T> The object type being tested. |
| * @param value The specified value. |
| * @return A new predicate. |
| */ |
| public static final <T> AssertionPredicate<T> ne(Object value) { |
| return test(x -> ! Objects.equals(x, value), MSG_valueUnexpectedlyMatched, VALUE); |
| } |
| |
| /** |
| * Predicate that returns <jk>true</jk> if the tested value converted to a string does not match the specified value. |
| * |
| * <p> |
| * Assertion error message is <js>"Value unexpectedly matched. Value='{0}'."</js>. |
| * |
| * @param <T> The object type being tested. |
| * @param value The specified value. |
| * @return A new predicate. |
| */ |
| public static final <T> AssertionPredicate<T> ne(String value) { |
| return test(x -> ! Objects.equals(stringify(x), value), MSG_valueUnexpectedlyMatched, VALUE); |
| } |
| |
| /** |
| * Predicate that returns <jk>true</jk> if the tested value converted to a string does not match the specified value ignoring case. |
| * |
| * <p> |
| * Assertion error message is <js>"Value did not match expected. Expected='{0}', Actual='{1}'."</js>. |
| * |
| * @param <T> The object type being tested. |
| * @param value The specified value. |
| * @return A new predicate. |
| */ |
| public static final <T> AssertionPredicate<T> eqic(String value) { |
| return test(x -> StringUtils.eqic(stringify(x), value), MSG_valueDidNotMatchExpected, value, VALUE); |
| } |
| |
| /** |
| * Predicate that returns <jk>true</jk> if the tested value converted to a string contains the specified substring. |
| * |
| * <p> |
| * Assertion error message is <js>"Value did not contain expected. Expected='{0}', Actual='{1}'."</js>. |
| * |
| * @param <T> The object type being tested. |
| * @param value The specified value. |
| * @return A new predicate. |
| */ |
| public static final <T> AssertionPredicate<T> contains(String value) { |
| return test(x -> StringUtils.contains(stringify(x), value), MSG_valueDidNotContainExpected, value, VALUE); |
| } |
| |
| /** |
| * Predicate that returns <jk>true</jk> if the tested value is the specified or child type. |
| * |
| * <p> |
| * Assertion error message is <js>"Value was not expected type. Expected='{0}', Actual='{1}'."</js>. |
| * |
| * @param <T> The object type being tested. |
| * @param type The specified type. |
| * @return A new predicate. |
| */ |
| public static final <T> AssertionPredicate<T> type(Class<?> type) { |
| assertArgNotNull("type", type); |
| return test(x -> x != null && type.isAssignableFrom(x.getClass()), MSG_valueWasNotExpectedType, type, TYPENAME); |
| } |
| |
| /** |
| * Predicate that returns <jk>true</jk> if the tested value is exactly specified type. |
| * |
| * <p> |
| * Assertion error message is <js>"Value was not expected type. Expected='{0}', Actual='{1}'."</js>. |
| * |
| * @param <T> The object type being tested. |
| * @param type The specified type. |
| * @return A new predicate. |
| */ |
| public static final <T> AssertionPredicate<T> exactType(Class<?> type) { |
| assertArgNotNull("type", type); |
| return test(x -> x != null && x.getClass().equals(type), MSG_valueWasNotExpectedType, type, TYPENAME); |
| } |
| |
| /** |
| * Predicate that returns <jk>true</jk> if the tested value converted to a string matches the specified match pattern. |
| * |
| * <p> |
| * Match pattern can contain the <js>"*"</js> meta-character. |
| * |
| * <p> |
| * Assertion error message is <js>"Value did not match pattern. Pattern='{0}', Actual='{1}'."</js>. |
| * |
| * @param <T> The object type being tested. |
| * @param value The specified value. |
| * @return A new predicate. |
| */ |
| public static final <T> AssertionPredicate<T> match(String value) { |
| assertArgNotNull("value", value); |
| Pattern p = StringUtils.getMatchPattern(value); |
| return test(x -> x != null && p.matcher(stringify(x)).matches(), MSG_valueDidNotMatchPattern, value, VALUE); |
| } |
| |
| /** |
| * Predicate that returns <jk>true</jk> if the tested value converted to a string matches the specified regular expression. |
| * |
| * <p> |
| * Assertion error message is <js>"Value did not match pattern. Pattern='{0}', Actual='{1}'."</js>. |
| * |
| * @param <T> The object type being tested. |
| * @param expression The regular expression to match. |
| * @return A new predicate. |
| */ |
| public static final <T> AssertionPredicate<T> regex(String expression) { |
| assertArgNotNull("expression", expression); |
| Pattern p = Pattern.compile(expression); |
| return test(x -> x != null && p.matcher(stringify(x)).matches(), MSG_valueDidNotMatchPattern, expression, VALUE); |
| } |
| |
| /** |
| * Predicate that returns <jk>true</jk> if the tested value converted to a string matches the specified regular expression. |
| * |
| * <p> |
| * Assertion error message is <js>"Value did not match pattern. Pattern='{0}', Actual='{1}'."</js>. |
| * |
| * @param <T> The object type being tested. |
| * @param expression The regular expression to match. |
| * @param flags Match flags, a bit mask that may include: |
| * <ul> |
| * <li>{@link Pattern#CASE_INSENSITIVE CASE_INSENSITIVE} |
| * <li>{@link Pattern#MULTILINE MULTILINE} |
| * <li>{@link Pattern#DOTALL DOTALL} |
| * <li>{@link Pattern#UNICODE_CASE UNICODE_CASE} |
| * <li>{@link Pattern#CANON_EQ CANON_EQ} |
| * <li>{@link Pattern#UNIX_LINES UNIX_LINES} |
| * <li>{@link Pattern#LITERAL LITERAL} |
| * <li>{@link Pattern#UNICODE_CHARACTER_CLASS UNICODE_CHARACTER_CLASS} |
| * <li>{@link Pattern#COMMENTS COMMENTS} |
| * @return A new predicate. |
| */ |
| public static final <T> AssertionPredicate<T> regex(String expression, int flags) { |
| assertArgNotNull("expression", expression); |
| Pattern p = Pattern.compile(expression, flags); |
| return test(x -> x != null && p.matcher(stringify(x)).matches(), MSG_valueDidNotMatchPattern, expression, VALUE); |
| } |
| |
| /** |
| * Predicate that returns <jk>true</jk> if the tested value converted to a string matches the specified regular expression. |
| * |
| * <p> |
| * Assertion error message is <js>"Value did not match pattern. Pattern='{0}', Actual='{1}'."</js>. |
| * |
| * @param <T> The object type being tested. |
| * @param value The regular expression to match. |
| * @return A new predicate. |
| */ |
| public static final <T> AssertionPredicate<T> regex(Pattern value) { |
| assertArgNotNull("value", value); |
| return test(x -> x != null && value.matcher(stringify(x)).matches(), MSG_valueDidNotMatchPattern, value.pattern(), VALUE); |
| } |
| |
| /** |
| * Predicate that wraps another predicate. |
| * |
| * <p> |
| * If the predicate extends from {@link AssertionPredicate}, the assertion error |
| * message is <js>"Value did not pass test."</js> followed by the inner assertion error. |
| * Otherwise the message is <js>"Value did not pass test. Value='{0}'."</js> |
| * |
| * @param <T> The object type being tested. |
| * @param predicate The predicate to run. |
| * @return A new predicate. |
| */ |
| public static final <T> AssertionPredicate<T> test(Predicate<T> predicate) { |
| return new AssertionPredicate<>(predicate, null); |
| } |
| |
| /** |
| * Predicate that wraps another predicate. |
| * |
| * <p> |
| * If the message specified is <jk>null</jk> and the predicate extends from {@link AssertionPredicate}, the assertion error |
| * message is <js>"Value did not pass test."</js> followed by the inner assertion error. |
| * Otherwise the message is <js>"Value did not pass test. Value='{0}'."</js> |
| * |
| * @param <T> The object type being tested. |
| * @param predicate The predicate to run. |
| * @param msg |
| * The error message if predicate fails. |
| * <br>Supports {@link MessageFormat}-style arguments. |
| * @param args |
| * Optional message arguments. |
| * <br>Can contain {@code #VALUE} to specify the value itself as an argument. |
| * <br>Can contain {@link Function functions} to apply to the tested value. |
| * @return A new predicate. |
| */ |
| public static final <T> AssertionPredicate<T> test(Predicate<T> predicate, String msg, Object...args) { |
| return new AssertionPredicate<>(predicate, msg, args); |
| } |
| |
| /** |
| * Combines the specified predicates into a singled AND'ed predicate. |
| * |
| * <p> |
| * Assertion error message is <js>"Predicate test #x failed."</js> followed by |
| * the inner failed message if the failed predicate extends from {@link AssertionPredicate}. |
| * |
| * @param <T> The predicate type. |
| * @param predicates The predicates to combine. |
| * @return The combined predicates. |
| */ |
| @SafeVarargs |
| public static final <T> AssertionPredicate<T> and(Predicate<T>...predicates) { |
| return new AssertionPredicate.And<>(predicates); |
| } |
| |
| /** |
| * Combines the specified predicates into a singled OR'ed predicate. |
| * |
| * <p> |
| * Assertion error message is <js>"No predicate tests passed."</js>. |
| * |
| * @param <T> The predicate type. |
| * @param predicates The predicates to combine. |
| * @return The combined predicates. |
| */ |
| @SafeVarargs |
| public static final <T> AssertionPredicate<T> or(Predicate<T>...predicates) { |
| return new AssertionPredicate.Or<>(predicates); |
| } |
| |
| /** |
| * Negates the specified predicate. |
| * |
| * <p> |
| * Assertion error message is <js>"Predicate test unexpectedly passed."</js>. |
| * |
| * @param <T> The predicate type. |
| * @param predicate The predicate to negate. |
| * @return The combined predicates. |
| */ |
| public static final <T> AssertionPredicate<T> not(Predicate<T> predicate) { |
| return new AssertionPredicate.Not<>(predicate); |
| } |
| } |