UiSelector.java revision a46ac3504426564954292b13380120e8cc6b1527
1e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu/*
2e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Copyright (C) 2012 The Android Open Source Project
3e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu *
4e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Licensed under the Apache License, Version 2.0 (the "License");
5e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * you may not use this file except in compliance with the License.
6e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * You may obtain a copy of the License at
7e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu *
8e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu *      http://www.apache.org/licenses/LICENSE-2.0
9e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu *
10e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Unless required by applicable law or agreed to in writing, software
11e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * distributed under the License is distributed on an "AS IS" BASIS,
12e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * See the License for the specific language governing permissions and
14e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * limitations under the License.
15e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */
16e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
17e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhupackage com.android.uiautomator.core;
18e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
19e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.util.SparseArray;
20e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.view.accessibility.AccessibilityNodeInfo;
21e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
22e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu/**
23e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * This class provides the mechanism for tests to describe the UI elements they
24e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * intend to target. A UI element has many properties associated with it such as
253d50587be8ff021369c90554d814839335b445b0Adam Momtaz * text value, content-description, class name and multiple state information like
263d50587be8ff021369c90554d814839335b445b0Adam Momtaz * selected, enabled, checked etc. Additionally UiSelector allows targeting of UI
273d50587be8ff021369c90554d814839335b445b0Adam Momtaz * elements within a specific display hierarchies to distinguish similar elements
283d50587be8ff021369c90554d814839335b445b0Adam Momtaz * based in the hierarchies they're in.
29e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */
304ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtazpublic class UiSelector {
31e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_NIL = 0;
32e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_TEXT = 1;
33e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_START_TEXT = 2;
34e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_CONTAINS_TEXT = 3;
35e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_CLASS = 4;
36e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_DESCRIPTION = 5;
37e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_START_DESCRIPTION = 6;
38e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_CONTAINS_DESCRIPTION = 7;
39e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_INDEX = 8;
40e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_INSTANCE = 9;
41e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_ENABLED = 10;
42e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_FOCUSED = 11;
43e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_FOCUSABLE = 12;
44e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_SCROLLABLE = 13;
45e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_CLICKABLE = 14;
46e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_CHECKED = 15;
47e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_SELECTED = 16;
48e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_ID = 17;
49e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_PACKAGE_NAME = 18;
50e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_CHILD = 19;
51e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_CONTAINER = 20;
52e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_PATTERN = 21;
53e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_PARENT = 22;
54e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_COUNT = 23;
55e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
56e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    private SparseArray<Object> mSelectorAttributes = new SparseArray<Object>();
57e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
584ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector() {
59e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
60e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
613d50587be8ff021369c90554d814839335b445b0Adam Momtaz    UiSelector(UiSelector selector) {
623d50587be8ff021369c90554d814839335b445b0Adam Momtaz        mSelectorAttributes = selector.cloneSelector().mSelectorAttributes;
63e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
64e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
653d50587be8ff021369c90554d814839335b445b0Adam Momtaz    protected UiSelector cloneSelector() {
664ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz        UiSelector ret = new UiSelector();
67e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        ret.mSelectorAttributes = mSelectorAttributes.clone();
683d50587be8ff021369c90554d814839335b445b0Adam Momtaz        if(hasChildSelector())
693d50587be8ff021369c90554d814839335b445b0Adam Momtaz            ret.mSelectorAttributes.put(SELECTOR_CHILD, new UiSelector(getChildSelector()));
703d50587be8ff021369c90554d814839335b445b0Adam Momtaz        if(hasParentSelector())
713d50587be8ff021369c90554d814839335b445b0Adam Momtaz            ret.mSelectorAttributes.put(SELECTOR_PARENT, new UiSelector(getParentSelector()));
723d50587be8ff021369c90554d814839335b445b0Adam Momtaz        if(hasPatternSelector())
733d50587be8ff021369c90554d814839335b445b0Adam Momtaz            ret.mSelectorAttributes.put(SELECTOR_PATTERN, new UiSelector(getPatternSelector()));
74e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return ret;
75e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
76e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
774ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    static UiSelector patternBuilder(UiSelector selector) {
78e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        if(!selector.hasPatternSelector()) {
794ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            return new UiSelector().patternSelector(selector);
80e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
81e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return selector;
82e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
83e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
844ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    static UiSelector patternBuilder(UiSelector container, UiSelector pattern) {
854ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz        return new UiSelector(
864ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz                new UiSelector().containerSelector(container).patternSelector(pattern));
87e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
88e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
89a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
90a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match the visible text displayed
91a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * for a widget (for example, the text label to launch an app).
92a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
93a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * The text for the widget must match exactly
94a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * with the string in your input argument.
95a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Matching is case-sensitive.
96a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
97a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param text Value to match
98a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
99a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
1004ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector text(String text) {
101e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_TEXT, text);
102e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
103e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
104a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
105a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Text property is usually the widget's visible text on the display.
106a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
107a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Adding this to the search criteria indicates that the search performed
108a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * should match a widget with text value starting with the text parameter.
109a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
110a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * The matching will be case-insensitive.
111a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
112a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param text
113a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with this added search criterion
114a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
1154ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector textStartsWith(String text) {
116e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_START_TEXT, text);
117e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
118e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
119a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
120a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match the visible text displayed
121a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * for a widget (for example, the text label to launch an app).
122a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
123a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * The text for the widget must contain the string in
124a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * your input argument. Matching is case-sensitive.
125a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
126a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param text Value to match
127a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
128a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
1294ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector textContains(String text) {
130e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_CONTAINS_TEXT, text);
131e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
132e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
133a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
134a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match the class property
135a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * for a widget (for example, "android.widget.Button").
136a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
137a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param className Value to match
138a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
139a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
1404ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector className(String className) {
141e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_CLASS, className);
142e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
143e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
144a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
145a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match the content-description
146a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * property for a widget.
147a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
148a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * The content-description is typically used
149a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * by the Android Accessibility framework to
150a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * provide an audio prompt for the widget when
151a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * the widget is selected. The content-description
152a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * for the widget must match exactly
153a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * with the string in your input argument.
154a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
155a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Matching is case-sensitive.
156a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
157a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param desc Value to match
158a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
159a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
1604ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector description(String desc) {
161e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_DESCRIPTION, desc);
162e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
163e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
164a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
165a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match the content-description
166a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * property for a widget.
167a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
168a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * The content-description is typically used
169a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * by the Android Accessibility framework to
170a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * provide an audio prompt for the widget when
171a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * the widget is selected. The content-description
172a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * for the widget must start
173a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * with the string in your input argument.
174a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
175a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Matching is case-insensitive.
176a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
177a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param desc Value to match
178a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
179a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
1804ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector descriptionStartsWith(String desc) {
181e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_START_DESCRIPTION, desc);
182e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
183e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
184a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
185a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match the content-description
186a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * property for a widget.
187a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
188a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * The content-description is typically used
189a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * by the Android Accessibility framework to
190a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * provide an audio prompt for the widget when
191a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * the widget is selected. The content-description
192a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * for the widget must contain
193a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * the string in your input argument.
194a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
195a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Matching is case-insensitive.
196a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
197a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param desc Value to match
198a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
199a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
2004ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector descriptionContains(String desc) {
201e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_CONTAINS_DESCRIPTION, desc);
202e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
203e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
204a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
205a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match the widget by its node
206a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * index in the layout hierarchy.
207a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
208a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * The index value must be 0 or greater.
209a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
210a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Using the index can be unreliable and should only
211a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * be used as a last resort for matching. Instead,
212a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * consider using the {@link #instance(int)} method.
213a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
214a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param index Value to match
215a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
216a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
2174ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector index(final int index) {
218e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_INDEX, index);
219e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
220e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
221a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
222a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match the
223a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * widget by its instance number.
224a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
225a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * The instance value must be 0 or greater, where
226a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * the first instance is 0.
227a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
228a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * For example, to simulate a user click on
229a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * the third image that is enabled in a UI screen, you
230a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * could specify a a search criteria where the instance is
231a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * 2, the {@link #className(String)} matches the image
232a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * widget class, and {@link #enabled(boolean)} is true.
233a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * The code would look like this:
234a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * <code>
235a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * new UiSelector().className("android.widget.ImageView")
236a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *    .enabled(true).instance(2);
237a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * </code>
238a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
239a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param instance Value to match
240a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
241a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
2424ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector instance(final int instance) {
243e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_INSTANCE, instance);
244e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
245e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
246a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
247a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match widgets that are enabled.
248a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
249a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Typically, using this search criteria alone is not useful.
250a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * You should also include additional criteria, such as text,
251a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * content-description, or the class name for a widget.
252a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
253a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * If no other search criteria is specified, and there is more
254a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * than one matching widget, the first widget in the tree
255a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * is selected.
256a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
257a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param val Value to match
258a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
259a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
2604ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector enabled(boolean val) {
261e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_ENABLED, val);
262e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
263e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
264a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
265a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match widgets that have focus.
266a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
267a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Typically, using this search criteria alone is not useful.
268a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * You should also include additional criteria, such as text,
269a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * content-description, or the class name for a widget.
270a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
271a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * If no other search criteria is specified, and there is more
272a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * than one matching widget, the first widget in the tree
273a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * is selected.
274a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
275a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param val Value to match
276a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
277a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
2784ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector focused(boolean val) {
279e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_FOCUSED, val);
280e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
281e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
282a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
283a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match widgets that are focusable.
284a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
285a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Typically, using this search criteria alone is not useful.
286a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * You should also include additional criteria, such as text,
287a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * content-description, or the class name for a widget.
288a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
289a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * If no other search criteria is specified, and there is more
290a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * than one matching widget, the first widget in the tree
291a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * is selected.
292a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
293a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param val Value to match
294a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
295a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
2964ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector focusable(boolean val) {
297e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_FOCUSABLE, val);
298e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
299e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
300a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
301a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match widgets that are scrollable.
302a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
303a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Typically, using this search criteria alone is not useful.
304a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * You should also include additional criteria, such as text,
305a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * content-description, or the class name for a widget.
306a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
307a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * If no other search criteria is specified, and there is more
308a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * than one matching widget, the first widget in the tree
309a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * is selected.
310a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
311a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param val Value to match
312a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
313a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
3144ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector scrollable(boolean val) {
315e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_SCROLLABLE, val);
316e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
317e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
318a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
319a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match widgets that
320a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * are currently selected.
321a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
322a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Typically, using this search criteria alone is not useful.
323a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * You should also include additional criteria, such as text,
324a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * content-description, or the class name for a widget.
325a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
326a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * If no other search criteria is specified, and there is more
327a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * than one matching widget, the first widget in the tree
328a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * is selected.
329a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
330a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param val Value to match
331a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
332a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
3334ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector selected(boolean val) {
334e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_SELECTED, val);
335e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
336e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
337a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
338a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match widgets that
339a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * are currently checked (usually for checkboxes).
340a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
341a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Typically, using this search criteria alone is not useful.
342a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * You should also include additional criteria, such as text,
343a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * content-description, or the class name for a widget.
344a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
345a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * If no other search criteria is specified, and there is more
346a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * than one matching widget, the first widget in the tree
347a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * is selected.
348a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
349a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param val Value to match
350a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
351a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
3524ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector checked(boolean val) {
353e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_CHECKED, val);
354e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
355e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
356a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
357a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match widgets that are clickable.
358a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
359a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Typically, using this search criteria alone is not useful.
360a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * You should also include additional criteria, such as text,
361a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * content-description, or the class name for a widget.
362a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
363a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * If no other search criteria is specified, and there is more
364a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * than one matching widget, the first widget in the tree
365a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * is selected.
366a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
367a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param val Value to match
368a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
369a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
3704ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector clickable(boolean val) {
371e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_CLICKABLE, val);
372e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
373e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
374a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
375a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Adds a child UiSelector criteria to this selector.
376a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
377a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Use this selector to narrow the search scope to
378a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * child widgets under a specific parent widget.
379a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
380a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param selector
381a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with this added search criterion
382a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
3833d50587be8ff021369c90554d814839335b445b0Adam Momtaz    public UiSelector childSelector(UiSelector selector) {
3843d50587be8ff021369c90554d814839335b445b0Adam Momtaz        return buildSelector(SELECTOR_CHILD, selector);
385e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
386e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
3873d50587be8ff021369c90554d814839335b445b0Adam Momtaz    private UiSelector patternSelector(UiSelector selector) {
3883d50587be8ff021369c90554d814839335b445b0Adam Momtaz        return buildSelector(SELECTOR_PATTERN, selector);
389e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
390e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
3913d50587be8ff021369c90554d814839335b445b0Adam Momtaz    private UiSelector containerSelector(UiSelector selector) {
3923d50587be8ff021369c90554d814839335b445b0Adam Momtaz        return buildSelector(SELECTOR_CONTAINER, selector);
393e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
394e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
395a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
396a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Adds a child UiSelector criteria to this selector which is used to
397a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * start search from the parent widget.
398a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
399a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Use this selector to narrow the search scope to
400a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * sibling widgets as well all child widgets under a parent.
401a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
402a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param selector
403a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with this added search criterion
404a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
4053d50587be8ff021369c90554d814839335b445b0Adam Momtaz    public UiSelector fromParent(UiSelector selector) {
4063d50587be8ff021369c90554d814839335b445b0Adam Momtaz        return buildSelector(SELECTOR_PARENT, selector);
407e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
408e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
409a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
410a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match the package name
411a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * of the application that contains the widget.
412a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
413a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param name Value to match
414a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
415a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
4164ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector packageName(String name) {
417e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_PACKAGE_NAME, name);
418e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
419e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
420e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    /**
4213d50587be8ff021369c90554d814839335b445b0Adam Momtaz     * Building a UiSelector always returns a new UiSelector and never modifies the
4223d50587be8ff021369c90554d814839335b445b0Adam Momtaz     * existing UiSelector being used.
423e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     */
4244ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    private UiSelector buildSelector(int selectorId, Object selectorValue) {
4253d50587be8ff021369c90554d814839335b445b0Adam Momtaz        UiSelector selector = new UiSelector(this);
426e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        if(selectorId == SELECTOR_CHILD || selectorId == SELECTOR_PARENT)
4273d50587be8ff021369c90554d814839335b445b0Adam Momtaz            selector.getLastSubSelector().mSelectorAttributes.put(selectorId, selectorValue);
428e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        else
4293d50587be8ff021369c90554d814839335b445b0Adam Momtaz            selector.mSelectorAttributes.put(selectorId, selectorValue);
4303d50587be8ff021369c90554d814839335b445b0Adam Momtaz        return selector;
431e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
432e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
433e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    /**
434e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * Selectors may have a hierarchy defined by specifying child nodes to be matched.
435e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * It is not necessary that every selector have more than one level. A selector
436e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * can also be a single level referencing only one node. In such cases the return
437e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * it null.
438a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
439e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * @return a child selector if one exists. Else null if this selector does not
440e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * reference child node.
441e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     */
4424ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    UiSelector getChildSelector() {
4433d50587be8ff021369c90554d814839335b445b0Adam Momtaz        UiSelector selector = (UiSelector)mSelectorAttributes.get(UiSelector.SELECTOR_CHILD, null);
4443d50587be8ff021369c90554d814839335b445b0Adam Momtaz        if(selector != null)
4453d50587be8ff021369c90554d814839335b445b0Adam Momtaz            return new UiSelector(selector);
446e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return null;
447e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
448e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
4494ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    UiSelector getPatternSelector() {
4503d50587be8ff021369c90554d814839335b445b0Adam Momtaz        UiSelector selector =
4513d50587be8ff021369c90554d814839335b445b0Adam Momtaz                (UiSelector)mSelectorAttributes.get(UiSelector.SELECTOR_PATTERN, null);
4523d50587be8ff021369c90554d814839335b445b0Adam Momtaz        if(selector != null)
4533d50587be8ff021369c90554d814839335b445b0Adam Momtaz            return new UiSelector(selector);
454e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return null;
455e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
456e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
4574ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    UiSelector getContainerSelector() {
4583d50587be8ff021369c90554d814839335b445b0Adam Momtaz        UiSelector selector =
4593d50587be8ff021369c90554d814839335b445b0Adam Momtaz                (UiSelector)mSelectorAttributes.get(UiSelector.SELECTOR_CONTAINER, null);
4603d50587be8ff021369c90554d814839335b445b0Adam Momtaz        if(selector != null)
4613d50587be8ff021369c90554d814839335b445b0Adam Momtaz            return new UiSelector(selector);
462e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return null;
463e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
464e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
4654ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    UiSelector getParentSelector() {
4663d50587be8ff021369c90554d814839335b445b0Adam Momtaz        UiSelector selector =
4673d50587be8ff021369c90554d814839335b445b0Adam Momtaz                (UiSelector) mSelectorAttributes.get(UiSelector.SELECTOR_PARENT, null);
4683d50587be8ff021369c90554d814839335b445b0Adam Momtaz        if(selector != null)
4693d50587be8ff021369c90554d814839335b445b0Adam Momtaz            return new UiSelector(selector);
470e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return null;
471e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
472e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
473e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    int getInstance() {
4744ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz        return getInt(UiSelector.SELECTOR_INSTANCE);
475e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
476e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
477e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    String getString(int criterion) {
478e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return (String) mSelectorAttributes.get(criterion, null);
479e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
480e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
481e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    boolean getBoolean(int criterion) {
482e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return (Boolean) mSelectorAttributes.get(criterion, false);
483e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
484e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
485e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    int getInt(int criterion) {
486e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return (Integer) mSelectorAttributes.get(criterion, 0);
487e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
488e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
489e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    boolean isMatchFor(AccessibilityNodeInfo node, int index) {
490e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        int size = mSelectorAttributes.size();
491e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        for(int x = 0; x < size; x++) {
492e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            CharSequence s = null;
493e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            int criterion = mSelectorAttributes.keyAt(x);
494e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            switch(criterion) {
4954ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_INDEX:
496e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if(index != this.getInt(criterion))
497e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
498e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
4994ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_CHECKED:
500e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if (node.isChecked() != getBoolean(criterion)) {
501e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
502e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
503e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
5044ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_CLASS:
505e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                s = node.getClassName();
506e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if (s == null || !s.toString().contentEquals(getString(criterion))) {
507e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
508e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
509e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
5104ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_CLICKABLE:
511e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if (node.isClickable() != getBoolean(criterion)) {
512e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
513e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
514e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
5154ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_CONTAINS_DESCRIPTION:
516e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                s = node.getContentDescription();
517e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if(s == null || !s.toString().toLowerCase()
518e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                        .contains(getString(criterion).toLowerCase())) {
519e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
520e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
521e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
5224ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_START_DESCRIPTION:
523e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                s = node.getContentDescription();
524e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if(s == null || !s.toString().toLowerCase()
525e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                        .startsWith(getString(criterion).toLowerCase())) {
526e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
527e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
528e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
5294ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_DESCRIPTION:
530e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                s = node.getContentDescription();
531e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if(s == null || !s.toString().contentEquals(getString(criterion))) {
532e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
533e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
534e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
5354ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_CONTAINS_TEXT:
536e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                s = node.getText();
537e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if(s == null || !s.toString().toLowerCase()
538e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                        .contains(getString(criterion).toLowerCase())) {
539e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
540e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
541e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
5424ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_START_TEXT:
543e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                s = node.getText();
544e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if(s == null || !s.toString().toLowerCase()
545e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                        .startsWith(getString(criterion).toLowerCase())) {
546e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
547e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
548e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
5494ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_TEXT:
550e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                s = node.getText();
551e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if(s == null || !s.toString().contentEquals(getString(criterion))) {
552e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
553e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
554e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
5554ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_ENABLED:
556e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if(node.isEnabled() != getBoolean(criterion)) {
557e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
558e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
559e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
5604ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_FOCUSABLE:
561e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if(node.isFocusable() != getBoolean(criterion)) {
562e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
563e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
564e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
5654ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_FOCUSED:
566e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if(node.isFocused() != getBoolean(criterion)) {
567e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
568e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
569e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
5704ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_ID:
571e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break; //TODO: do we need this for AccessibilityNodeInfo.id?
5724ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_PACKAGE_NAME:
573e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                s = node.getPackageName();
574e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if(s == null || !s.toString().contentEquals(getString(criterion))) {
575e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
576e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
577e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
5784ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_SCROLLABLE:
579e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if(node.isScrollable() != getBoolean(criterion)) {
580e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
581e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
582e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
5834ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_SELECTED:
584e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if(node.isSelected() != getBoolean(criterion)) {
585e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
586e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
587e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
588e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            }
589e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
590e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return matchOrUpdateInstance();
591e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
592e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
593e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    private boolean matchOrUpdateInstance() {
594e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        int currentSelectorCounter = 0;
595e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        int currentSelectorInstance = 0;
596e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
597e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        // matched attributes - now check for matching instance number
5984ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz        if(mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_INSTANCE) > 0) {
5994ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            currentSelectorInstance =
6004ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz                    (Integer)mSelectorAttributes.get(UiSelector.SELECTOR_INSTANCE);
601e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
602e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
603e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        // instance is required. Add count if not already counting
6044ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz        if(mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_COUNT) > 0) {
6054ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            currentSelectorCounter = (Integer)mSelectorAttributes.get(UiSelector.SELECTOR_COUNT);
606e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
607e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
608e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        // Verify
609e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        if (currentSelectorInstance == currentSelectorCounter) {
610e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            return true;
611e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
612e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        // Update count
613e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        if (currentSelectorInstance > currentSelectorCounter) {
6144ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            mSelectorAttributes.put(UiSelector.SELECTOR_COUNT, ++currentSelectorCounter);
615e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
616e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return false;
617e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
618e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
619e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    /**
620e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * Leaf selector indicates no more child or parent selectors
621e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * are declared in the this selector.
622e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * @return true if is leaf.
623e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     */
624e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    boolean isLeaf() {
6254ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz        if(mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_CHILD) < 0 &&
6264ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz                mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_PARENT) < 0) {
627e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            return true;
628e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
629e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return false;
630e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
631e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
632e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    boolean hasChildSelector() {
6334ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz        if(mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_CHILD) < 0) {
634e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            return false;
635e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
636e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return true;
637e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
638e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
639e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    boolean hasPatternSelector() {
6404ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz        if(mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_PATTERN) < 0) {
641e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            return false;
642e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
643e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return true;
644e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
645e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
646e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    boolean hasContainerSelector() {
6474ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz        if(mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_CONTAINER) < 0) {
648e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            return false;
649e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
650e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return true;
651e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
652e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
653e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    boolean hasParentSelector() {
6544ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz        if(mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_PARENT) < 0) {
655e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            return false;
656e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
657e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return true;
658e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
659e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
660e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    /**
661e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * Returns the deepest selector in the chain of possible sub selectors.
6624ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz     * A chain of selector is created when either of {@link UiSelector#childSelector(UiSelector)}
6634ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz     * or {@link UiSelector#fromParent(UiSelector)} are used once or more in the construction of
664e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * a selector.
6653d50587be8ff021369c90554d814839335b445b0Adam Momtaz     * @return last UiSelector in chain
666e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     */
6674ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    private UiSelector getLastSubSelector() {
6684ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz        if(mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_CHILD) >= 0) {
6694ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            UiSelector child = (UiSelector)mSelectorAttributes.get(UiSelector.SELECTOR_CHILD);
670e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            if(child.getLastSubSelector() == null) {
671e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                return child;
672e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            }
673e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            return child.getLastSubSelector();
6744ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz        } else if(mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_PARENT) >= 0) {
6754ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            UiSelector parent = (UiSelector)mSelectorAttributes.get(UiSelector.SELECTOR_PARENT);
676e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            if(parent.getLastSubSelector() == null) {
677e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                return parent;
678e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            }
679e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            return parent.getLastSubSelector();
680e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
681e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return this;
682e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
683e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
684e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    @Override
685e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    public String toString() {
686e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return dumpToString(true);
687e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
688e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
689e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    String dumpToString(boolean all) {
690e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        StringBuilder builder = new StringBuilder();
6913d50587be8ff021369c90554d814839335b445b0Adam Momtaz        builder.append(UiSelector.class.getSimpleName() + "[");
692e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        final int criterionCount = mSelectorAttributes.size();
693e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        for (int i = 0; i < criterionCount; i++) {
694e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            if (i > 0) {
695e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append(", ");
696e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            }
697e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            final int criterion = mSelectorAttributes.keyAt(i);
698e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            switch (criterion) {
699e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_TEXT:
700e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("TEXT=").append(mSelectorAttributes.valueAt(i));
701e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
702e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_START_TEXT:
703e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("START_TEXT=").append(mSelectorAttributes.valueAt(i));
704e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
705e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_CONTAINS_TEXT:
706e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("CONTAINS_TEXT=").append(mSelectorAttributes.valueAt(i));
707e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
708e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_CLASS:
709e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("CLASS=").append(mSelectorAttributes.valueAt(i));
710e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
711e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_DESCRIPTION:
712e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("DESCRIPTION=").append(mSelectorAttributes.valueAt(i));
713e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
714e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_START_DESCRIPTION:
715e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("START_DESCRIPTION=").append(mSelectorAttributes.valueAt(i));
716e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
717e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_CONTAINS_DESCRIPTION:
718e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("CONTAINS_DESCRIPTION=").append(mSelectorAttributes.valueAt(i));
719e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
720e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_INDEX:
721e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("INDEX=").append(mSelectorAttributes.valueAt(i));
722e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
723e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_INSTANCE:
724e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("INSTANCE=").append(mSelectorAttributes.valueAt(i));
725e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
726e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_ENABLED:
727e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("ENABLED=").append(mSelectorAttributes.valueAt(i));
728e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
729e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_FOCUSED:
730e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("FOCUSED=").append(mSelectorAttributes.valueAt(i));
731e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
732e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_FOCUSABLE:
733e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("FOCUSABLE=").append(mSelectorAttributes.valueAt(i));
734e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
735e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_SCROLLABLE:
736e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("SCROLLABLE=").append(mSelectorAttributes.valueAt(i));
737e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
738e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_CLICKABLE:
739e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("CLICKABLE=").append(mSelectorAttributes.valueAt(i));
740e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
741e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_CHECKED:
742e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("CHECKED=").append(mSelectorAttributes.valueAt(i));
743e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
744e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_SELECTED:
745e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("SELECTED=").append(mSelectorAttributes.valueAt(i));
746e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
747e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_ID:
748e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("ID=").append(mSelectorAttributes.valueAt(i));
749e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
750e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_CHILD:
751e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if(all)
752e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    builder.append("CHILD=").append(mSelectorAttributes.valueAt(i));
753e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                else
754e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    builder.append("CHILD[..]");
755e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
756e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_PATTERN:
757e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if(all)
758e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    builder.append("PATTERN=").append(mSelectorAttributes.valueAt(i));
759e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                else
760e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    builder.append("PATTERN[..]");
761e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
762e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_CONTAINER:
763e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if(all)
764e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    builder.append("CONTAINER=").append(mSelectorAttributes.valueAt(i));
765e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                else
766e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    builder.append("CONTAINER[..]");
767e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
768e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_PARENT:
769e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if(all)
770e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    builder.append("PARENT=").append(mSelectorAttributes.valueAt(i));
771e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                else
772e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    builder.append("PARENT[..]");
773e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
774e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_COUNT:
775e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("COUNT=").append(mSelectorAttributes.valueAt(i));
776e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
777e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_PACKAGE_NAME:
778e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("PACKAGE NAME=").append(mSelectorAttributes.valueAt(i));
779e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
780e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            default:
781e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("UNDEFINED="+criterion+" ").append(mSelectorAttributes.valueAt(i));
782e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            }
783e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
784e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        builder.append("]");
785e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return builder.toString();
786e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
787e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu}
788