Comparer: fix depth start at 1
[platform/core/uifw/aurum.git] / libaurum / src / Comparer.cc
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *               http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  *
16  */
17
18 #include "Aurum.h"
19
20 using namespace Aurum;
21
22 Comparer::Comparer(const std::shared_ptr<UiDevice> device, const std::shared_ptr<UiSelector> selector,
23                    const bool &earlyReturn)
24     : mDevice(device), mSelector(selector), mEarlyReturn(earlyReturn)
25 {
26 }
27
28 Comparer::~Comparer() {}
29
30 std::shared_ptr<AccessibleNode> Comparer::findObject(const std::shared_ptr<UiDevice> device,
31                                      const std::shared_ptr<UiSelector> selector,
32                                      const std::shared_ptr<AccessibleNode> root)
33 {
34     std::vector<std::shared_ptr<AccessibleNode>> ret = findObjects(device, selector, root, true);
35     if (ret.size() > 0)
36         return std::move(ret[0]);
37     else
38         return nullptr;
39 }
40
41 std::vector<std::shared_ptr<AccessibleNode>> Comparer::findObjects(const std::shared_ptr<UiDevice> device,
42                                                     const std::shared_ptr<UiSelector> selector,
43                                                     const std::shared_ptr<AccessibleNode> root, bool earlyReturn)
44 {
45     Comparer comparer(device, selector, earlyReturn);
46
47     LOGI("findObjects selector(%s) from (type:%s style:%s, role:%s, text:%s) earlyReturn:%d", selector->description().c_str(), root->getType().c_str(),  root->getStyle().c_str(),  root->getRole().c_str(),  root->getText().c_str(), earlyReturn);
48
49     if (selector->mParent) {
50         auto ret = Comparer::findObjects(device, selector->mParent, root);
51         std::vector<std::shared_ptr<AccessibleNode>> merged{};
52
53         for (const auto &node : ret) {
54             auto tmp = comparer.findObjects(node);
55             std::move(std::begin(tmp), std::end(tmp), std::back_inserter(merged));
56         }
57         return merged;
58     }
59
60     if (selector->mMatchXPath) {
61         std::vector<std::shared_ptr<AccessibleNode>> merged{};
62
63         auto XMLDocMap = AccessibleWatcher::getInstance()->getXMLDocMap();
64         std::string pkg = root->getPkg();
65
66         if (XMLDocMap.count(pkg) == 0) return merged;
67
68         auto XMLDoc = XMLDocMap[pkg];
69
70         auto tmp = XMLDoc->findObjects(selector->mXPath, earlyReturn);
71         std::move(std::begin(tmp), std::end(tmp), std::back_inserter(merged));
72
73         return merged;
74     }
75
76     return comparer.findObjects(root);
77 }
78
79 std::vector<std::shared_ptr<AccessibleNode>> Comparer::findObjects(const std::shared_ptr<AccessibleNode> root)
80 {
81     std::list<std::shared_ptr<PartialMatch>> partialList{};
82     std::vector<std::shared_ptr<AccessibleNode>> ret = findObjects(root, 0, 1, partialList);
83     LOGI("%d object(s) found", (int)ret.size());
84     return ret;
85 }
86
87 std::vector<std::shared_ptr<AccessibleNode>> Comparer::findObjects(
88     const std::shared_ptr<AccessibleNode> root, const int &index, const int &depth,
89     std::list<std::shared_ptr<PartialMatch>> &partialMatches)
90 {
91     std::vector<std::shared_ptr<AccessibleNode>> ret;
92
93     if (mSelector->mMatchShowing && !root->isShowing()) return ret;
94
95     for (auto &match : partialMatches)
96         match->update(root, index, depth, partialMatches);
97
98     std::shared_ptr<PartialMatch> currentMatch =
99         PartialMatch::accept(root, mSelector, index, depth);
100     if (currentMatch) partialMatches.push_front(currentMatch);
101
102     if (!(mSelector->mMaxDepth && (depth+1 > mSelector->mMaxDepth))) {
103         int childCnt = root->getChildCount();
104         for (int i = 0; i < childCnt; i++) {
105             std::shared_ptr<AccessibleNode> childNode = root->getChildAt(i);
106             if (childNode == nullptr) continue;
107
108             std::vector<std::shared_ptr<AccessibleNode>> childret =
109                 findObjects(childNode, i, depth + 1, partialMatches);
110             std::move(std::begin(childret), std::end(childret), std::back_inserter(ret));
111
112             if (!ret.empty() && mEarlyReturn) {
113                 LOGI("Object found and earlyReturn");
114                 return ret;
115             }
116         }
117     } else {
118         LOGI("Abort searching! No need to search children(maxDepth limit overflow, %d < %d < %d)", mSelector->mMinDepth? mSelector->mMinDepth: -1, depth, mSelector->mMaxDepth?(mSelector->mMaxDepth):9999999);
119     }
120
121     if (currentMatch && currentMatch->finalizeMatch()){
122         LOGI("Found matched = %s with criteria %s", root->description().c_str(), currentMatch->debugPrint().c_str());
123         ret.push_back(root);
124     }
125
126     return ret;
127 }