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  */
16 
17 package io.appium.droiddriver;
18 
19 import io.appium.droiddriver.exceptions.ElementNotFoundException;
20 import io.appium.droiddriver.finders.Finder;
21 
22 /**
23  * Interface for polling mechanism.
24  */
25 public interface Poller {
26   /**
27    * Interface for a callback to be invoked when {@link #pollFor} times out.
28    */
29   interface TimeoutListener {
30     /**
31      * Called when {@link #pollFor} times out. Should return quickly (no
32      * polling).
33      */
onTimeout(DroidDriver driver, Finder finder)34     void onTimeout(DroidDriver driver, Finder finder);
35   }
36 
37   /**
38    * Interface for a callback to be invoked when {@link #pollFor} polls.
39    */
40   interface PollingListener {
41     /**
42      * Called when {@link #pollFor} polls. Should return quickly (no polling).
43      */
onPolling(DroidDriver driver, Finder finder)44     void onPolling(DroidDriver driver, Finder finder);
45   }
46   /**
47    * Interface for removing a listener.
48    */
49   interface ListenerRemover {
50     /**
51      * A ListenerRemover that does nothing. Can be used as initial value for
52      * ListenerRemovers.
53      */
54     ListenerRemover NOP_LISTENER_REMOVER = new ListenerRemover() {
55       @Override
56       public void remove() {}
57     };
58 
59     /**
60      * Removes the associated listener.
61      */
remove()62     void remove();
63   }
64 
65   /**
66    * Used by Poller to check conditions.
67    *
68    * @param <T> type of the value returned by {@link #check}
69    */
70   interface ConditionChecker<T> {
71     /**
72      * Checks condition that overriding methods provide.
73      *
74      * @throws UnsatisfiedConditionException If the condition is not met
75      */
check(DroidDriver driver, Finder finder)76     T check(DroidDriver driver, Finder finder) throws UnsatisfiedConditionException;
77   }
78 
79   /** Thrown to indicate condition not met. Used in {@link ConditionChecker}. */
80   @SuppressWarnings("serial")
81   class UnsatisfiedConditionException extends Exception {
82   }
83 
84   /**
85    * A ConditionChecker that returns the matching {@link UiElement}.
86    */
87   ConditionChecker<UiElement> EXISTS = new ConditionChecker<UiElement>() {
88     @Override
89     public UiElement check(DroidDriver driver, Finder finder) throws UnsatisfiedConditionException {
90       try {
91         return driver.find(finder);
92       } catch (ElementNotFoundException e) {
93         throw new UnsatisfiedConditionException();
94       }
95     }
96 
97     @Override
98     public String toString() {
99       return "to appear";
100     }
101   };
102   /**
103    * A ConditionChecker that does not throw only if the matching
104    * {@link UiElement} is gone.
105    */
106   ConditionChecker<Void> GONE = new ConditionChecker<Void>() {
107     @Override
108     public Void check(DroidDriver driver, Finder finder) throws UnsatisfiedConditionException {
109       try {
110         // "find" does not call refreshUiElementTree, while "has" calls
111         driver.find(finder);
112         throw new UnsatisfiedConditionException();
113       } catch (ElementNotFoundException enfe) {
114         return null;
115       }
116     }
117 
118     @Override
119     public String toString() {
120       return "to disappear";
121     }
122   };
123 
124   /**
125    * Polls until {@code checker} does not throw
126    * {@link UnsatisfiedConditionException}, up to the default timeout.
127    *
128    * @return An object of type T returned by {@code checker}
129    */
pollFor(DroidDriver driver, Finder finder, ConditionChecker<T> checker)130   <T> T pollFor(DroidDriver driver, Finder finder, ConditionChecker<T> checker);
131 
132   /**
133    * Polls until {@code checker} does not throw
134    * {@link UnsatisfiedConditionException}, up to {@code timeoutMillis}.
135    *
136    * @return An object of type T returned by {@code checker}
137    */
pollFor(DroidDriver driver, Finder finder, ConditionChecker<T> checker, long timeoutMillis)138   <T> T pollFor(DroidDriver driver, Finder finder, ConditionChecker<T> checker, long timeoutMillis);
139 
140   /**
141    * Adds a {@link TimeoutListener}.
142    */
addListener(TimeoutListener timeoutListener)143   ListenerRemover addListener(TimeoutListener timeoutListener);
144 
145   /**
146    * Adds a {@link PollingListener}.
147    */
addListener(PollingListener pollingListener)148   ListenerRemover addListener(PollingListener pollingListener);
149 
150   /**
151    * Sets default timeoutMillis.
152    */
setTimeoutMillis(long timeoutMillis)153   void setTimeoutMillis(long timeoutMillis);
154 
155   /**
156    * @return default timeoutMillis
157    */
getTimeoutMillis()158   long getTimeoutMillis();
159 
160   /**
161    * Sets intervalMillis.
162    */
setIntervalMillis(long intervalMillis)163   void setIntervalMillis(long intervalMillis);
164 
165   /**
166    * @return intervalMillis
167    */
getIntervalMillis()168   long getIntervalMillis();
169 }
170