SentinelStrategy.java revision 9c92f46280cf3943701e75349833c68b584992e2
1/* 2 * Copyright (C) 2013 DroidDriver committers 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package com.google.android.droiddriver.scroll; 17 18import com.google.android.droiddriver.UiElement; 19import com.google.common.base.Predicate; 20import com.google.common.base.Predicates; 21 22import java.util.List; 23 24/** 25 * Interface for determining whether scrolling is possible based on a sentinel. 26 */ 27public interface SentinelStrategy extends ScrollStepStrategy { 28 29 /** 30 * Gets sentinel based on {@link Predicate}. 31 */ 32 public static abstract class Getter { 33 protected final Predicate<? super UiElement> predicate; 34 protected final String description; 35 36 protected Getter(Predicate<? super UiElement> predicate, String description) { 37 this.predicate = predicate; 38 this.description = description; 39 } 40 41 /** 42 * Gets the sentinel, which must be an immediate child of {@code container} 43 * -- not a descendant. Note this could be null if {@code container} has not 44 * finished updating. 45 */ 46 public UiElement getSentinel(UiElement container) { 47 return getSentinel(container.getChildren(predicate)); 48 } 49 50 protected abstract UiElement getSentinel(List<? extends UiElement> children); 51 52 @Override 53 public String toString() { 54 return description; 55 } 56 } 57 58 /** 59 * Decorates an existing {@link Getter} by adding another {@link Predicate}. 60 */ 61 public static class MorePredicateGetter extends Getter { 62 private final Getter original; 63 64 public MorePredicateGetter(Getter original, Predicate<? super UiElement> extraPredicate, 65 String extraDescription) { 66 super(Predicates.and(original.predicate, extraPredicate), extraDescription 67 + original.description); 68 this.original = original; 69 } 70 71 @Override 72 protected UiElement getSentinel(List<? extends UiElement> children) { 73 return original.getSentinel(children); 74 } 75 } 76 77 /** 78 * Returns the first child as the sentinel. 79 */ 80 public static final Getter FIRST_CHILD_GETTER = 81 new Getter(Predicates.alwaysTrue(), "FIRST_CHILD") { 82 @Override 83 protected UiElement getSentinel(List<? extends UiElement> children) { 84 return children.isEmpty() ? null : children.get(0); 85 } 86 }; 87 /** 88 * Returns the last child as the sentinel. 89 */ 90 public static final Getter LAST_CHILD_GETTER = new Getter(Predicates.alwaysTrue(), "LAST_CHILD") { 91 @Override 92 protected UiElement getSentinel(List<? extends UiElement> children) { 93 return children.isEmpty() ? null : children.get(children.size() - 1); 94 } 95 }; 96 /** 97 * Returns the second last child as the sentinel. Useful when the activity 98 * always shows the last child as an anchor (for example a footer). 99 * <p> 100 * Sometimes uiautomatorviewer may not show the anchor as the last child, due 101 * to the reordering by layout described in {@link UiElement#getChildren}. 102 * This is not a problem with UiAutomationDriver because it sees the same as 103 * uiautomatorviewer does, but could be a problem with InstrumentationDriver. 104 * </p> 105 */ 106 public static final Getter SECOND_LAST_CHILD_GETTER = new Getter(Predicates.alwaysTrue(), 107 "SECOND_LAST_CHILD") { 108 @Override 109 protected UiElement getSentinel(List<? extends UiElement> children) { 110 return children.size() < 2 ? null : children.get(children.size() - 2); 111 } 112 }; 113 /** 114 * Returns the second child as the sentinel. Useful when the activity shows a 115 * fixed first child. 116 */ 117 public static final Getter SECOND_CHILD_GETTER = new Getter(Predicates.alwaysTrue(), 118 "SECOND_CHILD") { 119 @Override 120 protected UiElement getSentinel(List<? extends UiElement> children) { 121 return children.size() <= 1 ? null : children.get(1); 122 } 123 }; 124} 125