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
174b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinpackage io.appium.droiddriver.base;
18cddda72410c992a12db61cef26713b498e31fea4Thanh Le
191e9f07f4cb681fb142202113caedba35737a83efKevin Jinimport android.util.Log;
201e9f07f4cb681fb142202113caedba35737a83efKevin Jin
214b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport io.appium.droiddriver.DroidDriver;
224b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport io.appium.droiddriver.Poller;
234b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport io.appium.droiddriver.UiElement;
244b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport io.appium.droiddriver.actions.InputInjector;
254b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport io.appium.droiddriver.exceptions.ElementNotFoundException;
264b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport io.appium.droiddriver.exceptions.TimeoutException;
274b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport io.appium.droiddriver.finders.ByXPath;
284b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport io.appium.droiddriver.finders.Finder;
294b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport io.appium.droiddriver.util.Logs;
30cddda72410c992a12db61cef26713b498e31fea4Thanh Le
31cddda72410c992a12db61cef26713b498e31fea4Thanh Le/**
327c8b54f99e678a1b40b98fc3069217877ec5199cKevin Jin * Base DroidDriver that implements the common operations.
33cddda72410c992a12db61cef26713b498e31fea4Thanh Le */
3474676fdd3c8a9e599eddd13bea56898674d9916aKevin Jinpublic abstract class BaseDroidDriver<R, E extends BaseUiElement<R, E>> implements DroidDriver {
35cddda72410c992a12db61cef26713b498e31fea4Thanh Le
36985b3bff6691575b23da83c3e7cfd8552b6f4c55Kevin Jin  private Poller poller = new DefaultPoller();
3774676fdd3c8a9e599eddd13bea56898674d9916aKevin Jin  private E rootElement;
3821a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin
39b75721c8fc51bd5678f5a8d0df9a1e868d69aa12Kevin Jin  @Override
407576fbbba2bf515908b45293b7156b5bfe088938Kevin Jin  public UiElement find(Finder finder) {
411e9f07f4cb681fb142202113caedba35737a83efKevin Jin    Logs.call(Log.VERBOSE, this, "find", finder);
42e4de29ac873c9e0ffaec34832dcc8b120850d8f7Kevin Jin    return finder.find(getRootElement());
437576fbbba2bf515908b45293b7156b5bfe088938Kevin Jin  }
447576fbbba2bf515908b45293b7156b5bfe088938Kevin Jin
45985b3bff6691575b23da83c3e7cfd8552b6f4c55Kevin Jin  @Override
467576fbbba2bf515908b45293b7156b5bfe088938Kevin Jin  public boolean has(Finder finder) {
47985b3bff6691575b23da83c3e7cfd8552b6f4c55Kevin Jin    try {
48e4de29ac873c9e0ffaec34832dcc8b120850d8f7Kevin Jin      refreshUiElementTree();
497576fbbba2bf515908b45293b7156b5bfe088938Kevin Jin      find(finder);
50985b3bff6691575b23da83c3e7cfd8552b6f4c55Kevin Jin      return true;
51985b3bff6691575b23da83c3e7cfd8552b6f4c55Kevin Jin    } catch (ElementNotFoundException enfe) {
52985b3bff6691575b23da83c3e7cfd8552b6f4c55Kevin Jin      return false;
53985b3bff6691575b23da83c3e7cfd8552b6f4c55Kevin Jin    }
546a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin  }
55cddda72410c992a12db61cef26713b498e31fea4Thanh Le
566a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin  @Override
577576fbbba2bf515908b45293b7156b5bfe088938Kevin Jin  public boolean has(Finder finder, long timeoutMillis) {
586a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin    try {
59f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin      getPoller().pollFor(this, finder, Poller.EXISTS, timeoutMillis);
606a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin      return true;
616a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin    } catch (TimeoutException e) {
626a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin      return false;
636a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin    }
646a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin  }
656a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin
666a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin  @Override
677576fbbba2bf515908b45293b7156b5bfe088938Kevin Jin  public UiElement on(Finder finder) {
687576fbbba2bf515908b45293b7156b5bfe088938Kevin Jin    Logs.call(this, "on", finder);
69f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin    return getPoller().pollFor(this, finder, Poller.EXISTS);
70cddda72410c992a12db61cef26713b498e31fea4Thanh Le  }
71cddda72410c992a12db61cef26713b498e31fea4Thanh Le
72cddda72410c992a12db61cef26713b498e31fea4Thanh Le  @Override
73ce3d103d2784040f32d1a97b848d58a1c9592a15Kevin Jin  public void checkExists(Finder finder) {
74ce3d103d2784040f32d1a97b848d58a1c9592a15Kevin Jin    Logs.call(this, "checkExists", finder);
75f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin    getPoller().pollFor(this, finder, Poller.EXISTS);
766a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin  }
776a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin
786a6c19d612923a0350ab46898df513c66bac2d66Kevin Jin  @Override
79ce3d103d2784040f32d1a97b848d58a1c9592a15Kevin Jin  public void checkGone(Finder finder) {
80ce3d103d2784040f32d1a97b848d58a1c9592a15Kevin Jin    Logs.call(this, "checkGone", finder);
81f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin    getPoller().pollFor(this, finder, Poller.GONE);
82cddda72410c992a12db61cef26713b498e31fea4Thanh Le  }
83cddda72410c992a12db61cef26713b498e31fea4Thanh Le
84cddda72410c992a12db61cef26713b498e31fea4Thanh Le  @Override
85cddda72410c992a12db61cef26713b498e31fea4Thanh Le  public Poller getPoller() {
86cddda72410c992a12db61cef26713b498e31fea4Thanh Le    return poller;
87cddda72410c992a12db61cef26713b498e31fea4Thanh Le  }
88cddda72410c992a12db61cef26713b498e31fea4Thanh Le
89cddda72410c992a12db61cef26713b498e31fea4Thanh Le  @Override
90cddda72410c992a12db61cef26713b498e31fea4Thanh Le  public void setPoller(Poller poller) {
91cddda72410c992a12db61cef26713b498e31fea4Thanh Le    this.poller = poller;
92cddda72410c992a12db61cef26713b498e31fea4Thanh Le  }
936316362de61fca700d7d5a455ad5c0ac9717c365Kevin Jin
9474676fdd3c8a9e599eddd13bea56898674d9916aKevin Jin  public abstract InputInjector getInjector();
9521a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin
9674676fdd3c8a9e599eddd13bea56898674d9916aKevin Jin  protected abstract E newRootElement();
9721a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin
9874676fdd3c8a9e599eddd13bea56898674d9916aKevin Jin  /**
9974676fdd3c8a9e599eddd13bea56898674d9916aKevin Jin   * Returns a new UiElement of type {@code E}.
10074676fdd3c8a9e599eddd13bea56898674d9916aKevin Jin   */
10174676fdd3c8a9e599eddd13bea56898674d9916aKevin Jin  protected abstract E newUiElement(R rawElement, E parent);
10274676fdd3c8a9e599eddd13bea56898674d9916aKevin Jin
10374676fdd3c8a9e599eddd13bea56898674d9916aKevin Jin  public E getRootElement() {
10421a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin    if (rootElement == null) {
105e4de29ac873c9e0ffaec34832dcc8b120850d8f7Kevin Jin      refreshUiElementTree();
10621a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin    }
10721a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin    return rootElement;
10821a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin  }
10921a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin
110e4de29ac873c9e0ffaec34832dcc8b120850d8f7Kevin Jin  @Override
111e4de29ac873c9e0ffaec34832dcc8b120850d8f7Kevin Jin  public void refreshUiElementTree() {
11274676fdd3c8a9e599eddd13bea56898674d9916aKevin Jin    rootElement = newRootElement();
11321a0001e2426644dd68e6140b5873ebaeafcc3dcKevin Jin  }
1146316362de61fca700d7d5a455ad5c0ac9717c365Kevin Jin
1156316362de61fca700d7d5a455ad5c0ac9717c365Kevin Jin  @Override
1166316362de61fca700d7d5a455ad5c0ac9717c365Kevin Jin  public boolean dumpUiElementTree(String path) {
117985b3bff6691575b23da83c3e7cfd8552b6f4c55Kevin Jin    Logs.call(this, "dumpUiElementTree", path);
1186316362de61fca700d7d5a455ad5c0ac9717c365Kevin Jin    return ByXPath.dumpDom(path, getRootElement());
1196316362de61fca700d7d5a455ad5c0ac9717c365Kevin Jin  }
120cddda72410c992a12db61cef26713b498e31fea4Thanh Le}
121