117342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin/* 217342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * Copyright (C) 2013 DroidDriver committers 317342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * 417342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * Licensed under the Apache License, Version 2.0 (the "License"); 517342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * you may not use this file except in compliance with the License. 617342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * You may obtain a copy of the License at 717342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * 817342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * http://www.apache.org/licenses/LICENSE-2.0 917342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * 1017342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * Unless required by applicable law or agreed to in writing, software 1117342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * distributed under the License is distributed on an "AS IS" BASIS, 1217342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1317342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * See the License for the specific language governing permissions and 1417342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * limitations under the License. 1517342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin */ 1617342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin 1717342a5115d7575d44a99fed9c7032e3ab316dccKevin Jinpackage com.google.android.droiddriver.finders; 1817342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin 1917342a5115d7575d44a99fed9c7032e3ab316dccKevin Jinimport android.text.TextUtils; 2017342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin 2117342a5115d7575d44a99fed9c7032e3ab316dccKevin Jinimport com.google.android.droiddriver.UiElement; 2217342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin 2317342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin/** 2417342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * Static utility methods pertaining to {@code Predicate} instances. 2517342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin */ 2617342a5115d7575d44a99fed9c7032e3ab316dccKevin Jinpublic final class Predicates { 2717342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin private Predicates() {} 2817342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin 2917342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin private static final Predicate<Object> ANY = new Predicate<Object>() { 3017342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin @Override 3117342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin public boolean apply(Object o) { 3217342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return true; 3317342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 3417342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin 3517342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin @Override 3617342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin public String toString() { 3717342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return "any"; 3817342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 3917342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin }; 4017342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin 4117342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin /** 4217342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * Returns a predicate that always evaluates to {@code true}. 4317342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin */ 4417342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin @SuppressWarnings("unchecked") 4517342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin public static <T> Predicate<T> any() { 4617342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return (Predicate<T>) ANY; 4717342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 4817342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin 4917342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin /** 50e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin * Returns a predicate that is the negation of the provided {@code predicate}. 51e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin */ 52e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin public static <T> Predicate<T> not(final Predicate<T> predicate) { 53e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return new Predicate<T>() { 54e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin @Override 55e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin public boolean apply(T input) { 56e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return !predicate.apply(input); 57e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 58e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin 59e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin @Override 60e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin public String toString() { 61e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return "not(" + predicate + ")"; 62e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 63e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin }; 64e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 65e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin 66e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin /** 67e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin * Returns a predicate that evaluates to {@code true} if both arguments 68e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin * evaluate to {@code true}. The arguments are evaluated in order, and 69e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin * evaluation will be "short-circuited" as soon as a false predicate is found. 70e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin */ 71e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin @SuppressWarnings("unchecked") 72e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin public static <T> Predicate<T> allOf(final Predicate<? super T> first, 73e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin final Predicate<? super T> second) { 74e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin if (first == null || first == ANY) { 75e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return (Predicate<T>) second; 76e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 77e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin if (second == null || second == ANY) { 78e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return (Predicate<T>) first; 79e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 80e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin 81e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return new Predicate<T>() { 82e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin @Override 83e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin public boolean apply(T input) { 84e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return first.apply(input) && second.apply(input); 85e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 86e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin 87e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin @Override 88e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin public String toString() { 89e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return "allOf(" + first + ", " + second + ")"; 90e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 91e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin }; 92e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 93e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin 94e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin /** 9517342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * Returns a predicate that evaluates to {@code true} if each of its 9617342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * components evaluates to {@code true}. The components are evaluated in 9717342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * order, and evaluation will be "short-circuited" as soon as a false 9817342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * predicate is found. 9917342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin */ 10017342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin public static <T> Predicate<T> allOf( 10117342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin @SuppressWarnings("unchecked") final Predicate<? super T>... components) { 10217342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return new Predicate<T>() { 10317342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin @Override 10417342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin public boolean apply(T input) { 10517342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin for (Predicate<? super T> each : components) { 10617342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin if (!each.apply(input)) { 10717342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return false; 10817342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 10917342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 11017342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return true; 11117342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 11217342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin 11317342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin @Override 11417342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin public String toString() { 11517342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return "allOf(" + TextUtils.join(", ", components) + ")"; 11617342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 11717342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin }; 11817342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 11917342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin 12017342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin /** 12117342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * Returns a predicate that evaluates to {@code true} if any one of its 12217342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * components evaluates to {@code true}. The components are evaluated in 12317342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * order, and evaluation will be "short-circuited" as soon as a true predicate 12417342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin * is found. 12517342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin */ 12617342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin public static <T> Predicate<T> anyOf( 12717342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin @SuppressWarnings("unchecked") final Predicate<? super T>... components) { 12817342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return new Predicate<T>() { 12917342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin @Override 13017342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin public boolean apply(T input) { 13117342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin for (Predicate<? super T> each : components) { 13217342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin if (each.apply(input)) { 13317342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return true; 13417342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 13517342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 13617342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return false; 13717342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 13817342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin 13917342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin @Override 14017342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin public String toString() { 14117342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return "anyOf(" + TextUtils.join(", ", components) + ")"; 14217342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 14317342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin }; 14417342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 14517342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin 146e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin /** 147e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin * Returns a predicate that evaluates to {@code true} on a {@link UiElement} 148e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin * if its {@code attribute} is {@code true}. 149e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin */ 150e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin public static Predicate<UiElement> attributeTrue(final Attribute attribute) { 151e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return new Predicate<UiElement>() { 152e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin @Override 153e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin public boolean apply(UiElement element) { 154e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin Boolean actual = element.get(attribute); 155e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return actual != null && actual; 156e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 157e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin 158e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin @Override 159e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin public String toString() { 160e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return String.format("{%s}", attribute); 161e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 162e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin }; 163e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 164e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin 165e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin /** 166e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin * Returns a predicate that evaluates to {@code true} on a {@link UiElement} 167e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin * if its {@code attribute} is {@code false}. 168e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin */ 169e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin public static Predicate<UiElement> attributeFalse(final Attribute attribute) { 170e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return new Predicate<UiElement>() { 171e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin @Override 172e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin public boolean apply(UiElement element) { 173e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin Boolean actual = element.get(attribute); 174e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return actual == null || !actual; 175e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 176e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin 177e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin @Override 178e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin public String toString() { 179e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return String.format("{not %s}", attribute); 180e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 181e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin }; 182e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 183e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin 184e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin /** 185e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin * Returns a predicate that evaluates to {@code true} on a {@link UiElement} 186e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin * if its {@code attribute} equals {@code expected}. 187e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin */ 188e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin public static Predicate<UiElement> attributeEquals(final Attribute attribute, 189e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin final Object expected) { 190e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return new Predicate<UiElement>() { 191e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin @Override 192e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin public boolean apply(UiElement element) { 193e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin Object actual = element.get(attribute); 194e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return actual == expected || (actual != null && actual.equals(expected)); 195e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 196e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin 197e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin @Override 198e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin public String toString() { 199e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return String.format("{%s=%s}", attribute, expected); 200e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 201e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin }; 202e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 203e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin 204e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin /** 205e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin * Returns a predicate that evaluates to {@code true} on a {@link UiElement} 206e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin * if its {@code attribute} matches {@code regex}. 207e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin */ 208e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin public static Predicate<UiElement> attributeMatches(final Attribute attribute, final String regex) { 209e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return new Predicate<UiElement>() { 210e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin @Override 211e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin public boolean apply(UiElement element) { 212e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin String actual = element.get(attribute); 213e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return actual != null && actual.matches(regex); 214e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 215e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin 216e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin @Override 217e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin public String toString() { 218e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return String.format("{%s matches %s}", attribute, regex); 219e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 220e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin }; 221e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 222e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin 223e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin /** 224e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin * Returns a predicate that evaluates to {@code true} on a {@link UiElement} 225e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin * if its {@code attribute} contains {@code substring}. 226e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin */ 227e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin public static Predicate<UiElement> attributeContains(final Attribute attribute, 228e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin final String substring) { 229e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return new Predicate<UiElement>() { 230e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin @Override 231e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin public boolean apply(UiElement element) { 232e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin String actual = element.get(attribute); 233e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return actual != null && actual.contains(substring); 234e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 235e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin 236e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin @Override 237e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin public String toString() { 238e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin return String.format("{%s contains %s}", attribute, substring); 239e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 240e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin }; 241e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin } 242e0ad7adf66e62e536a0ce66fcb099a3518cda010Kevin Jin 24317342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin public static Predicate<UiElement> withParent(final Predicate<? super UiElement> parentPredicate) { 24417342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return new Predicate<UiElement>() { 24517342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin @Override 24617342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin public boolean apply(UiElement element) { 24717342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin UiElement parent = element.getParent(); 24817342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return parent != null && parentPredicate.apply(parent); 24917342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 25017342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin 25117342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin @Override 25217342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin public String toString() { 25317342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return "withParent(" + parentPredicate + ")"; 25417342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 25517342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin }; 25617342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 25717342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin 25817342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin public static Predicate<UiElement> withAncestor( 25917342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin final Predicate<? super UiElement> ancestorPredicate) { 26017342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return new Predicate<UiElement>() { 26117342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin @Override 26217342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin public boolean apply(UiElement element) { 26317342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin UiElement parent = element.getParent(); 26417342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin while (parent != null) { 26517342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin if (ancestorPredicate.apply(parent)) { 26617342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return true; 26717342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 26817342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin parent = parent.getParent(); 26917342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 27017342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return false; 27117342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 27217342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin 27317342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin @Override 27417342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin public String toString() { 27517342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return "withAncestor(" + ancestorPredicate + ")"; 27617342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 27717342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin }; 27817342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 27917342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin 28017342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin public static Predicate<UiElement> withSibling(final Predicate<? super UiElement> siblingPredicate) { 28117342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return new Predicate<UiElement>() { 28217342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin @Override 28317342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin public boolean apply(UiElement element) { 28417342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin UiElement parent = element.getParent(); 28517342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin if (parent == null) { 28617342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return false; 28717342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 28817342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin for (UiElement sibling : parent.getChildren(UiElement.VISIBLE)) { 28917342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin if (sibling != element && siblingPredicate.apply(sibling)) { 29017342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return true; 29117342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 29217342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 29317342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return false; 29417342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 29517342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin 29617342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin @Override 29717342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin public String toString() { 29817342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return "withSibling(" + siblingPredicate + ")"; 29917342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 30017342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin }; 30117342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 30217342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin 30317342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin public static Predicate<UiElement> withChild(final Predicate<? super UiElement> childPredicate) { 30417342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return new Predicate<UiElement>() { 30517342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin @Override 30617342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin public boolean apply(UiElement element) { 30717342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin for (UiElement child : element.getChildren(UiElement.VISIBLE)) { 30817342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin if (childPredicate.apply(child)) { 30917342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return true; 31017342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 31117342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 31217342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return false; 31317342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 31417342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin 31517342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin @Override 31617342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin public String toString() { 31717342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin return "withChild(" + childPredicate + ")"; 31817342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 31917342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin }; 32017342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin } 32117342a5115d7575d44a99fed9c7032e3ab316dccKevin Jin} 322