/* * Copyright (C) 2013 DroidDriver committers * * Licensed 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 com.google.android.droiddriver.finders; import android.text.TextUtils; import com.google.android.droiddriver.UiElement; /** * Static utility methods pertaining to {@code Predicate} instances. */ public final class Predicates { private Predicates() {} private static final Predicate ANY = new Predicate() { @Override public boolean apply(Object o) { return true; } @Override public String toString() { return "any"; } }; /** * Returns a predicate that always evaluates to {@code true}. */ @SuppressWarnings("unchecked") public static Predicate any() { return (Predicate) ANY; } /** * Returns a predicate that is the negation of the provided {@code predicate}. */ public static Predicate not(final Predicate predicate) { return new Predicate() { @Override public boolean apply(T input) { return !predicate.apply(input); } @Override public String toString() { return "not(" + predicate + ")"; } }; } /** * Returns a predicate that evaluates to {@code true} if both arguments * evaluate to {@code true}. The arguments are evaluated in order, and * evaluation will be "short-circuited" as soon as a false predicate is found. */ @SuppressWarnings("unchecked") public static Predicate allOf(final Predicate first, final Predicate second) { if (first == null || first == ANY) { return (Predicate) second; } if (second == null || second == ANY) { return (Predicate) first; } return new Predicate() { @Override public boolean apply(T input) { return first.apply(input) && second.apply(input); } @Override public String toString() { return "allOf(" + first + ", " + second + ")"; } }; } /** * Returns a predicate that evaluates to {@code true} if each of its * components evaluates to {@code true}. The components are evaluated in * order, and evaluation will be "short-circuited" as soon as a false * predicate is found. */ public static Predicate allOf( @SuppressWarnings("unchecked") final Predicate... components) { return new Predicate() { @Override public boolean apply(T input) { for (Predicate each : components) { if (!each.apply(input)) { return false; } } return true; } @Override public String toString() { return "allOf(" + TextUtils.join(", ", components) + ")"; } }; } /** * Returns a predicate that evaluates to {@code true} if any one of its * components evaluates to {@code true}. The components are evaluated in * order, and evaluation will be "short-circuited" as soon as a true predicate * is found. */ public static Predicate anyOf( @SuppressWarnings("unchecked") final Predicate... components) { return new Predicate() { @Override public boolean apply(T input) { for (Predicate each : components) { if (each.apply(input)) { return true; } } return false; } @Override public String toString() { return "anyOf(" + TextUtils.join(", ", components) + ")"; } }; } /** * Returns a predicate that evaluates to {@code true} on a {@link UiElement} * if its {@code attribute} is {@code true}. */ public static Predicate attributeTrue(final Attribute attribute) { return new Predicate() { @Override public boolean apply(UiElement element) { Boolean actual = element.get(attribute); return actual != null && actual; } @Override public String toString() { return String.format("{%s}", attribute); } }; } /** * Returns a predicate that evaluates to {@code true} on a {@link UiElement} * if its {@code attribute} is {@code false}. */ public static Predicate attributeFalse(final Attribute attribute) { return new Predicate() { @Override public boolean apply(UiElement element) { Boolean actual = element.get(attribute); return actual == null || !actual; } @Override public String toString() { return String.format("{not %s}", attribute); } }; } /** * Returns a predicate that evaluates to {@code true} on a {@link UiElement} * if its {@code attribute} equals {@code expected}. */ public static Predicate attributeEquals(final Attribute attribute, final Object expected) { return new Predicate() { @Override public boolean apply(UiElement element) { Object actual = element.get(attribute); return actual == expected || (actual != null && actual.equals(expected)); } @Override public String toString() { return String.format("{%s=%s}", attribute, expected); } }; } /** * Returns a predicate that evaluates to {@code true} on a {@link UiElement} * if its {@code attribute} matches {@code regex}. */ public static Predicate attributeMatches(final Attribute attribute, final String regex) { return new Predicate() { @Override public boolean apply(UiElement element) { String actual = element.get(attribute); return actual != null && actual.matches(regex); } @Override public String toString() { return String.format("{%s matches %s}", attribute, regex); } }; } /** * Returns a predicate that evaluates to {@code true} on a {@link UiElement} * if its {@code attribute} contains {@code substring}. */ public static Predicate attributeContains(final Attribute attribute, final String substring) { return new Predicate() { @Override public boolean apply(UiElement element) { String actual = element.get(attribute); return actual != null && actual.contains(substring); } @Override public String toString() { return String.format("{%s contains %s}", attribute, substring); } }; } public static Predicate withParent(final Predicate parentPredicate) { return new Predicate() { @Override public boolean apply(UiElement element) { UiElement parent = element.getParent(); return parent != null && parentPredicate.apply(parent); } @Override public String toString() { return "withParent(" + parentPredicate + ")"; } }; } public static Predicate withAncestor( final Predicate ancestorPredicate) { return new Predicate() { @Override public boolean apply(UiElement element) { UiElement parent = element.getParent(); while (parent != null) { if (ancestorPredicate.apply(parent)) { return true; } parent = parent.getParent(); } return false; } @Override public String toString() { return "withAncestor(" + ancestorPredicate + ")"; } }; } public static Predicate withSibling(final Predicate siblingPredicate) { return new Predicate() { @Override public boolean apply(UiElement element) { UiElement parent = element.getParent(); if (parent == null) { return false; } for (UiElement sibling : parent.getChildren(UiElement.VISIBLE)) { if (sibling != element && siblingPredicate.apply(sibling)) { return true; } } return false; } @Override public String toString() { return "withSibling(" + siblingPredicate + ")"; } }; } public static Predicate withChild(final Predicate childPredicate) { return new Predicate() { @Override public boolean apply(UiElement element) { for (UiElement child : element.getChildren(UiElement.VISIBLE)) { if (childPredicate.apply(child)) { return true; } } return false; } @Override public String toString() { return "withChild(" + childPredicate + ")"; } }; } }