1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.uiautomator.core;
17
18/**
19 * Used to enumerate a container's UI elements for the purpose of counting,
20 * or targeting a sub elements by a child's text or description.
21 * @since API Level 16
22 */
23public class UiCollection extends UiObject {
24
25    /**
26     * Constructs an instance as described by the selector
27     *
28     * @param selector
29     * @since API Level 16
30     */
31    public UiCollection(UiSelector selector) {
32        super(selector);
33    }
34
35    /**
36     * Searches for child UI element within the constraints of this UiCollection {@link UiSelector}
37     * selector.
38     *
39     * It looks for any child matching the <code>childPattern</code> argument that has
40     * a child UI element anywhere within its sub hierarchy that has content-description text.
41     * The returned UiObject will point at the <code>childPattern</code> instance that matched the
42     * search and not at the identifying child element that matched the content description.</p>
43     *
44     * @param childPattern {@link UiSelector} selector of the child pattern to match and return
45     * @param text String of the identifying child contents of of the <code>childPattern</code>
46     * @return {@link UiObject} pointing at and instance of <code>childPattern</code>
47     * @throws UiObjectNotFoundException
48     * @since API Level 16
49     */
50    public UiObject getChildByDescription(UiSelector childPattern, String text)
51            throws UiObjectNotFoundException {
52        Tracer.trace(childPattern, text);
53        if (text != null) {
54            int count = getChildCount(childPattern);
55            for (int x = 0; x < count; x++) {
56                UiObject row = getChildByInstance(childPattern, x);
57                String nodeDesc = row.getContentDescription();
58                if(nodeDesc != null && nodeDesc.contains(text)) {
59                    return row;
60                }
61                UiObject item = row.getChild(new UiSelector().descriptionContains(text));
62                if (item.exists()) {
63                    return row;
64                }
65            }
66        }
67        throw new UiObjectNotFoundException("for description= \"" + text + "\"");
68    }
69
70    /**
71     * Searches for child UI element within the constraints of this UiCollection {@link UiSelector}
72     * selector.
73     *
74     * It looks for any child matching the <code>childPattern</code> argument that has
75     * a child UI element anywhere within its sub hierarchy that is at the <code>instance</code>
76     * specified. The operation is performed only on the visible items and no scrolling is performed
77     * in this case.
78     *
79     * @param childPattern {@link UiSelector} selector of the child pattern to match and return
80     * @param instance int the desired matched instance of this <code>childPattern</code>
81     * @return {@link UiObject} pointing at and instance of <code>childPattern</code>
82     * @since API Level 16
83     */
84    public UiObject getChildByInstance(UiSelector childPattern, int instance)
85            throws UiObjectNotFoundException {
86        Tracer.trace(childPattern, instance);
87        UiSelector patternSelector = UiSelector.patternBuilder(getSelector(),
88                UiSelector.patternBuilder(childPattern).instance(instance));
89        return new UiObject(patternSelector);
90    }
91
92    /**
93     * Searches for child UI element within the constraints of this UiCollection {@link UiSelector}
94     * selector.
95     *
96     * It looks for any child matching the <code>childPattern</code> argument that has
97     * a child UI element anywhere within its sub hierarchy that has text attribute =
98     * <code>text</code>. The returned UiObject will point at the <code>childPattern</code>
99     * instance that matched the search and not at the identifying child element that matched the
100     * text attribute.</p>
101     *
102     * @param childPattern {@link UiSelector} selector of the child pattern to match and return
103     * @param text String of the identifying child contents of of the <code>childPattern</code>
104     * @return {@link UiObject} pointing at and instance of <code>childPattern</code>
105     * @throws UiObjectNotFoundException
106     * @since API Level 16
107     */
108    public UiObject getChildByText(UiSelector childPattern, String text)
109            throws UiObjectNotFoundException {
110        Tracer.trace(childPattern, text);
111        if (text != null) {
112            int count = getChildCount(childPattern);
113            for (int x = 0; x < count; x++) {
114                UiObject row = getChildByInstance(childPattern, x);
115                String nodeText = row.getText();
116                if(text.equals(nodeText)) {
117                    return row;
118                }
119                UiObject item = row.getChild(new UiSelector().text(text));
120                if (item.exists()) {
121                    return row;
122                }
123            }
124        }
125        throw new UiObjectNotFoundException("for text= \"" + text + "\"");
126    }
127
128    /**
129     * Counts child UI element instances matching the <code>childPattern</code>
130     * argument. The method returns the number of matching UI elements that are
131     * currently visible.  The count does not include items of a scrollable list
132     * that are off-screen.
133     *
134     * @param childPattern a {@link UiSelector} that represents the matching child UI
135     * elements to count
136     * @return the number of matched childPattern under the current {@link UiCollection}
137     * @since API Level 16
138     */
139    public int getChildCount(UiSelector childPattern) {
140        Tracer.trace(childPattern);
141        UiSelector patternSelector =
142                UiSelector.patternBuilder(getSelector(), UiSelector.patternBuilder(childPattern));
143        return getQueryController().getPatternCount(patternSelector);
144    }
145}
146