1cddda72410c992a12db61cef26713b498e31fea4Thanh Le/*
2cddda72410c992a12db61cef26713b498e31fea4Thanh Le * Copyright (C) 2013 DroidDriver committers
3cddda72410c992a12db61cef26713b498e31fea4Thanh Le *
4cddda72410c992a12db61cef26713b498e31fea4Thanh Le * Licensed under the Apache License, Version 2.0 (the "License");
5cddda72410c992a12db61cef26713b498e31fea4Thanh Le * you may not use this file except in compliance with the License.
6cddda72410c992a12db61cef26713b498e31fea4Thanh Le * You may obtain a copy of the License at
7cddda72410c992a12db61cef26713b498e31fea4Thanh Le *
8cddda72410c992a12db61cef26713b498e31fea4Thanh Le *      http://www.apache.org/licenses/LICENSE-2.0
9cddda72410c992a12db61cef26713b498e31fea4Thanh Le *
10cddda72410c992a12db61cef26713b498e31fea4Thanh Le * Unless required by applicable law or agreed to in writing, software
11cddda72410c992a12db61cef26713b498e31fea4Thanh Le * distributed under the License is distributed on an "AS IS" BASIS,
12cddda72410c992a12db61cef26713b498e31fea4Thanh Le * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cddda72410c992a12db61cef26713b498e31fea4Thanh Le * See the License for the specific language governing permissions and
14cddda72410c992a12db61cef26713b498e31fea4Thanh Le * limitations under the License.
15cddda72410c992a12db61cef26713b498e31fea4Thanh Le */
16cddda72410c992a12db61cef26713b498e31fea4Thanh Le
17cddda72410c992a12db61cef26713b498e31fea4Thanh Lepackage com.google.android.droiddriver.base;
18cddda72410c992a12db61cef26713b498e31fea4Thanh Le
19cddda72410c992a12db61cef26713b498e31fea4Thanh Leimport com.google.android.droiddriver.DroidDriver;
20cddda72410c992a12db61cef26713b498e31fea4Thanh Leimport com.google.android.droiddriver.Poller;
21cddda72410c992a12db61cef26713b498e31fea4Thanh Leimport com.google.android.droiddriver.UiElement;
2274676fdd3c8a9e599eddd13bea56898674d9916aKevin Jinimport com.google.android.droiddriver.actions.InputInjector;
237b1b7d4561b60f8b3bcd7c2d592454dd7bfef619Kevin Jinimport com.google.android.droiddriver.exceptions.ElementNotFoundException;
246a6c19d612923a0350ab46898df513c66bac2d66Kevin Jinimport com.google.android.droiddriver.exceptions.TimeoutException;
257576fbbba2bf515908b45293b7156b5bfe088938Kevin Jinimport com.google.android.droiddriver.finders.ByXPath;
267576fbbba2bf515908b45293b7156b5bfe088938Kevin Jinimport com.google.android.droiddriver.finders.Finder;
276316362de61fca700d7d5a455ad5c0ac9717c365Kevin Jinimport com.google.android.droiddriver.util.Logs;
28cddda72410c992a12db61cef26713b498e31fea4Thanh Le
29cddda72410c992a12db61cef26713b498e31fea4Thanh Le/**
307c8b54f99e678a1b40b98fc3069217877ec5199cKevin Jin * Base DroidDriver that implements the common operations.
31cddda72410c992a12db61cef26713b498e31fea4Thanh Le */
3274676fdd3c8a9e599eddd13bea56898674d9916aKevin Jinpublic abstract class BaseDroidDriver<R, E extends BaseUiElement<R, E>> implements DroidDriver {
33cddda72410c992a12db61cef26713b498e31fea4Thanh Le
34985b3bff6691575b23da83c3e7cfd8552b6f4c55Kevin Jin  private Poller poller = new DefaultPoller();
3574676fdd3c8a9e599eddd13bea56898674d9916aKevin Jin  private E rootElement;
3621a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin
37b75721c8fc51bd5678f5a8d0df9a1e868d69aa12Kevin Jin  @Override
387576fbbba2bf515908b45293b7156b5bfe088938Kevin Jin  public UiElement find(Finder finder) {
397576fbbba2bf515908b45293b7156b5bfe088938Kevin Jin    Logs.call(this, "find", finder);
40e4de29ac873c9e0ffaec34832dcc8b120850d8f7Kevin Jin    return finder.find(getRootElement());
417576fbbba2bf515908b45293b7156b5bfe088938Kevin Jin  }
427576fbbba2bf515908b45293b7156b5bfe088938Kevin Jin
43985b3bff6691575b23da83c3e7cfd8552b6f4c55Kevin Jin  @Override
447576fbbba2bf515908b45293b7156b5bfe088938Kevin Jin  public boolean has(Finder finder) {
45985b3bff6691575b23da83c3e7cfd8552b6f4c55Kevin Jin    try {
46e4de29ac873c9e0ffaec34832dcc8b120850d8f7Kevin Jin      refreshUiElementTree();
477576fbbba2bf515908b45293b7156b5bfe088938Kevin Jin      find(finder);
48985b3bff6691575b23da83c3e7cfd8552b6f4c55Kevin Jin      return true;
49985b3bff6691575b23da83c3e7cfd8552b6f4c55Kevin Jin    } catch (ElementNotFoundException enfe) {
50985b3bff6691575b23da83c3e7cfd8552b6f4c55Kevin Jin      return false;
51985b3bff6691575b23da83c3e7cfd8552b6f4c55Kevin Jin    }
526a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin  }
53cddda72410c992a12db61cef26713b498e31fea4Thanh Le
546a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin  @Override
557576fbbba2bf515908b45293b7156b5bfe088938Kevin Jin  public boolean has(Finder finder, long timeoutMillis) {
566a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin    try {
57f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin      getPoller().pollFor(this, finder, Poller.EXISTS, timeoutMillis);
586a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin      return true;
596a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin    } catch (TimeoutException e) {
606a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin      return false;
616a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin    }
626a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin  }
636a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin
646a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin  @Override
657576fbbba2bf515908b45293b7156b5bfe088938Kevin Jin  public UiElement on(Finder finder) {
667576fbbba2bf515908b45293b7156b5bfe088938Kevin Jin    Logs.call(this, "on", finder);
67f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin    return getPoller().pollFor(this, finder, Poller.EXISTS);
68cddda72410c992a12db61cef26713b498e31fea4Thanh Le  }
69cddda72410c992a12db61cef26713b498e31fea4Thanh Le
70cddda72410c992a12db61cef26713b498e31fea4Thanh Le  @Override
71ce3d103d2784040f32d1a97b848d58a1c9592a15Kevin Jin  public void checkExists(Finder finder) {
72ce3d103d2784040f32d1a97b848d58a1c9592a15Kevin Jin    Logs.call(this, "checkExists", finder);
73f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin    getPoller().pollFor(this, finder, Poller.EXISTS);
746a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin  }
756a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin
766a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin  @Override
77ce3d103d2784040f32d1a97b848d58a1c9592a15Kevin Jin  public void checkGone(Finder finder) {
78ce3d103d2784040f32d1a97b848d58a1c9592a15Kevin Jin    Logs.call(this, "checkGone", finder);
79f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin    getPoller().pollFor(this, finder, Poller.GONE);
80cddda72410c992a12db61cef26713b498e31fea4Thanh Le  }
81cddda72410c992a12db61cef26713b498e31fea4Thanh Le
82cddda72410c992a12db61cef26713b498e31fea4Thanh Le  @Override
83cddda72410c992a12db61cef26713b498e31fea4Thanh Le  public Poller getPoller() {
84cddda72410c992a12db61cef26713b498e31fea4Thanh Le    return poller;
85cddda72410c992a12db61cef26713b498e31fea4Thanh Le  }
86cddda72410c992a12db61cef26713b498e31fea4Thanh Le
87cddda72410c992a12db61cef26713b498e31fea4Thanh Le  @Override
88cddda72410c992a12db61cef26713b498e31fea4Thanh Le  public void setPoller(Poller poller) {
89cddda72410c992a12db61cef26713b498e31fea4Thanh Le    this.poller = poller;
90cddda72410c992a12db61cef26713b498e31fea4Thanh Le  }
916316362de61fca700d7d5a455ad5c0ac9717c365Kevin Jin
9274676fdd3c8a9e599eddd13bea56898674d9916aKevin Jin  public abstract InputInjector getInjector();
9321a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin
9474676fdd3c8a9e599eddd13bea56898674d9916aKevin Jin  protected abstract E newRootElement();
9521a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin
9674676fdd3c8a9e599eddd13bea56898674d9916aKevin Jin  /**
9774676fdd3c8a9e599eddd13bea56898674d9916aKevin Jin   * Returns a new UiElement of type {@code E}.
9874676fdd3c8a9e599eddd13bea56898674d9916aKevin Jin   */
9974676fdd3c8a9e599eddd13bea56898674d9916aKevin Jin  protected abstract E newUiElement(R rawElement, E parent);
10074676fdd3c8a9e599eddd13bea56898674d9916aKevin Jin
10174676fdd3c8a9e599eddd13bea56898674d9916aKevin Jin  public E getRootElement() {
10221a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin    if (rootElement == null) {
103e4de29ac873c9e0ffaec34832dcc8b120850d8f7Kevin Jin      refreshUiElementTree();
10421a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin    }
10521a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin    return rootElement;
10621a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin  }
10721a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin
108e4de29ac873c9e0ffaec34832dcc8b120850d8f7Kevin Jin  @Override
109e4de29ac873c9e0ffaec34832dcc8b120850d8f7Kevin Jin  public void refreshUiElementTree() {
11074676fdd3c8a9e599eddd13bea56898674d9916aKevin Jin    rootElement = newRootElement();
11121a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin  }
1126316362de61fca700d7d5a455ad5c0ac9717c365Kevin Jin
1136316362de61fca700d7d5a455ad5c0ac9717c365Kevin Jin  @Override
1146316362de61fca700d7d5a455ad5c0ac9717c365Kevin Jin  public boolean dumpUiElementTree(String path) {
115985b3bff6691575b23da83c3e7cfd8552b6f4c55Kevin Jin    Logs.call(this, "dumpUiElementTree", path);
1166316362de61fca700d7d5a455ad5c0ac9717c365Kevin Jin    return ByXPath.dumpDom(path, getRootElement());
1176316362de61fca700d7d5a455ad5c0ac9717c365Kevin Jin  }
118cddda72410c992a12db61cef26713b498e31fea4Thanh Le}
119