1886da342Sopenharmony_ci/*
2886da342Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3886da342Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4886da342Sopenharmony_ci * you may not use this file except in compliance with the License.
5886da342Sopenharmony_ci * You may obtain a copy of the License at
6886da342Sopenharmony_ci *
7886da342Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8886da342Sopenharmony_ci *
9886da342Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10886da342Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11886da342Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12886da342Sopenharmony_ci * See the License for the specific language governing permissions and
13886da342Sopenharmony_ci * limitations under the License.
14886da342Sopenharmony_ci */
15886da342Sopenharmony_ci
16886da342Sopenharmony_ci#include "select_strategy.h"
17886da342Sopenharmony_cinamespace OHOS::uitest {
18886da342Sopenharmony_ci    constexpr int32_t MAX_TRAVEL_TIMES = 20000;
19886da342Sopenharmony_ci    void SelectStrategy::RegisterAnchorMatch(const WidgetMatchModel &matchModel)
20886da342Sopenharmony_ci    {
21886da342Sopenharmony_ci        anchorMatch_.emplace_back(matchModel);
22886da342Sopenharmony_ci    }
23886da342Sopenharmony_ci
24886da342Sopenharmony_ci    void SelectStrategy::RegisterMyselfMatch(const WidgetMatchModel &matchModel)
25886da342Sopenharmony_ci    {
26886da342Sopenharmony_ci        myselfMatch_.emplace_back(matchModel);
27886da342Sopenharmony_ci    }
28886da342Sopenharmony_ci
29886da342Sopenharmony_ci    void SelectStrategy::SetWantMulti(bool isWantMulti)
30886da342Sopenharmony_ci    {
31886da342Sopenharmony_ci        wantMulti_ = isWantMulti;
32886da342Sopenharmony_ci    }
33886da342Sopenharmony_ci
34886da342Sopenharmony_ci    void SelectStrategy::SetAndCalcSelectWindowRect(const Rect &windowBounds, const std::vector<Rect> &windowBoundsVec)
35886da342Sopenharmony_ci    {
36886da342Sopenharmony_ci        windowBounds_ = windowBounds;
37886da342Sopenharmony_ci        overplayWindowBoundsVec_ = windowBoundsVec;
38886da342Sopenharmony_ci    }
39886da342Sopenharmony_ci
40886da342Sopenharmony_ci    SelectStrategy::~SelectStrategy()
41886da342Sopenharmony_ci    {
42886da342Sopenharmony_ci        anchorMatch_.clear();
43886da342Sopenharmony_ci        myselfMatch_.clear();
44886da342Sopenharmony_ci    }
45886da342Sopenharmony_ci
46886da342Sopenharmony_ci    void SelectStrategy::CalcWidgetVisibleBounds(Widget &widget)
47886da342Sopenharmony_ci    {
48886da342Sopenharmony_ci        const auto noneZone = Rect{0, 0, 0, 0};
49886da342Sopenharmony_ci        // calc bounds with its window
50886da342Sopenharmony_ci        Rect visibleRect{0, 0, 0, 0};
51886da342Sopenharmony_ci        if (!RectAlgorithm::ComputeIntersection(widget.GetBounds(), windowBounds_, visibleRect)) {
52886da342Sopenharmony_ci            LOG_D("Widget %{public}s bounds is %{public}s, without window bounds %{public}s, widget info is %{public}s",
53886da342Sopenharmony_ci                  widget.GetAttr(UiAttr::ACCESSIBILITY_ID).data(), widget.GetBounds().Describe().data(),
54886da342Sopenharmony_ci                  windowBounds_.Describe().data(), widget.ToStr().data());
55886da342Sopenharmony_ci            widget.SetBounds(noneZone);
56886da342Sopenharmony_ci            return;
57886da342Sopenharmony_ci        }
58886da342Sopenharmony_ci        widget.SetBounds(visibleRect);
59886da342Sopenharmony_ci
60886da342Sopenharmony_ci        // calc bounds with its cliper
61886da342Sopenharmony_ci        auto hier = widget.GetAttr(UiAttr::HIERARCHY);
62886da342Sopenharmony_ci        while (WidgetHierarchyBuilder::GetParentWidgetHierarchy(hier) != "") {
63886da342Sopenharmony_ci            std::string parentHie = WidgetHierarchyBuilder::GetParentWidgetHierarchy(hier);
64886da342Sopenharmony_ci            auto find = clipers_.find(parentHie);
65886da342Sopenharmony_ci            if (find != clipers_.end()) {
66886da342Sopenharmony_ci                if (!RectAlgorithm::ComputeIntersection(widget.GetBounds(), find->second, visibleRect)) {
67886da342Sopenharmony_ci                    widget.SetBounds(noneZone);
68886da342Sopenharmony_ci                    return;
69886da342Sopenharmony_ci                }
70886da342Sopenharmony_ci                widget.SetBounds(visibleRect);
71886da342Sopenharmony_ci                break;
72886da342Sopenharmony_ci            }
73886da342Sopenharmony_ci            hier = parentHie;
74886da342Sopenharmony_ci        }
75886da342Sopenharmony_ci
76886da342Sopenharmony_ci        // calc bounds with overplay windows
77886da342Sopenharmony_ci        if (overplayWindowBoundsVec_.size() == 0) {
78886da342Sopenharmony_ci            return;
79886da342Sopenharmony_ci        }
80886da342Sopenharmony_ci        if (!RectAlgorithm::ComputeMaxVisibleRegion(widget.GetBounds(), overplayWindowBoundsVec_, visibleRect)) {
81886da342Sopenharmony_ci            LOG_D("widget %{public}s is hide by overplays, widget info is %{public}s",
82886da342Sopenharmony_ci                  widget.GetAttr(UiAttr::ACCESSIBILITY_ID).data(), widget.ToStr().data());
83886da342Sopenharmony_ci            widget.SetBounds(noneZone);
84886da342Sopenharmony_ci        }
85886da342Sopenharmony_ci        widget.SetBounds(visibleRect);
86886da342Sopenharmony_ci    }
87886da342Sopenharmony_ci
88886da342Sopenharmony_ci    std::string SelectStrategy::Describe() const
89886da342Sopenharmony_ci    {
90886da342Sopenharmony_ci        std::string strategy = "PLAIN";
91886da342Sopenharmony_ci        switch (GetStrategyType()) {
92886da342Sopenharmony_ci            case StrategyEnum::PLAIN:
93886da342Sopenharmony_ci                strategy = "PLAIN";
94886da342Sopenharmony_ci                break;
95886da342Sopenharmony_ci            case StrategyEnum::WITH_IN:
96886da342Sopenharmony_ci                strategy = "WITH_IN";
97886da342Sopenharmony_ci                break;
98886da342Sopenharmony_ci            case StrategyEnum::IS_AFTER:
99886da342Sopenharmony_ci                strategy = "IS_AFTER";
100886da342Sopenharmony_ci                break;
101886da342Sopenharmony_ci            case StrategyEnum::IS_BEFORE:
102886da342Sopenharmony_ci                strategy = "IS_BEFORE";
103886da342Sopenharmony_ci                break;
104886da342Sopenharmony_ci            case StrategyEnum::COMPLEX:
105886da342Sopenharmony_ci                strategy = "COMPLEX";
106886da342Sopenharmony_ci                break;
107886da342Sopenharmony_ci            default:
108886da342Sopenharmony_ci                LOG_I("Error StrategyType, use plain");
109886da342Sopenharmony_ci                strategy = "PLAIN";
110886da342Sopenharmony_ci                break;
111886da342Sopenharmony_ci        }
112886da342Sopenharmony_ci        stringstream ss;
113886da342Sopenharmony_ci        ss << "{";
114886da342Sopenharmony_ci        ss << strategy;
115886da342Sopenharmony_ci        if (!anchorMatch_.empty()) {
116886da342Sopenharmony_ci            ss << "; anchorMatcher=";
117886da342Sopenharmony_ci            for (auto &locator : anchorMatch_) {
118886da342Sopenharmony_ci                ss << "[" << locator.Describe() << "]";
119886da342Sopenharmony_ci            }
120886da342Sopenharmony_ci        }
121886da342Sopenharmony_ci        if (!myselfMatch_.empty()) {
122886da342Sopenharmony_ci            ss << "; myselfMatcher=";
123886da342Sopenharmony_ci            for (auto &locator : myselfMatch_) {
124886da342Sopenharmony_ci                ss << "[" << locator.Describe() << "]";
125886da342Sopenharmony_ci            }
126886da342Sopenharmony_ci        }
127886da342Sopenharmony_ci        ss << "}";
128886da342Sopenharmony_ci        return ss.str();
129886da342Sopenharmony_ci    }
130886da342Sopenharmony_ci
131886da342Sopenharmony_ci    void SelectStrategy::RefreshWidgetBounds(Widget &widget)
132886da342Sopenharmony_ci    {
133886da342Sopenharmony_ci        CalcWidgetVisibleBounds(widget);
134886da342Sopenharmony_ci        auto widgetVisibleBounds = widget.GetBounds();
135886da342Sopenharmony_ci        if (widgetVisibleBounds.GetHeight() <= 0 || widgetVisibleBounds.GetWidth() <= 0) {
136886da342Sopenharmony_ci            widget.SetAttr(UiAttr::VISIBLE, "false");
137886da342Sopenharmony_ci        } else {
138886da342Sopenharmony_ci            widget.SetAttr(UiAttr::VISIBLE, "true");
139886da342Sopenharmony_ci        }
140886da342Sopenharmony_ci        if (widget.GetAttr(UiAttr::CLIP) == "true") {
141886da342Sopenharmony_ci            clipers_.insert(make_pair(widget.GetAttr(UiAttr::HIERARCHY), widget.GetBounds()));
142886da342Sopenharmony_ci        }
143886da342Sopenharmony_ci    }
144886da342Sopenharmony_ci
145886da342Sopenharmony_ci    class AfterSelectorStrategy : public SelectStrategy {
146886da342Sopenharmony_ci    public:
147886da342Sopenharmony_ci        AfterSelectorStrategy() = default;
148886da342Sopenharmony_ci        void LocateNode(const Window &window,
149886da342Sopenharmony_ci                        ElementNodeIterator &elementNodeRef,
150886da342Sopenharmony_ci                        std::vector<Widget> &visitWidgets,
151886da342Sopenharmony_ci                        std::vector<int> &targetWidgets,
152886da342Sopenharmony_ci                        bool isRemoveInvisible = true) override
153886da342Sopenharmony_ci        {
154886da342Sopenharmony_ci            elementNodeRef.ClearDFSNext();
155886da342Sopenharmony_ci            SetAndCalcSelectWindowRect(window.bounds_, window.invisibleBoundsVec_);
156886da342Sopenharmony_ci            while (true) {
157886da342Sopenharmony_ci                Widget anchorWidget{"test"};
158886da342Sopenharmony_ci                if (!elementNodeRef.DFSNext(anchorWidget, window.id_)) {
159886da342Sopenharmony_ci                    return;
160886da342Sopenharmony_ci                }
161886da342Sopenharmony_ci                anchorWidget.SetAttr(UiAttr::HOST_WINDOW_ID, std::to_string(window.id_));
162886da342Sopenharmony_ci                if (anchorWidget.GetAttr(UiAttr::VISIBLE) == "false") {
163886da342Sopenharmony_ci                    LOG_D("Widget %{public}s is invisible", anchorWidget.GetAttr(UiAttr::ACCESSIBILITY_ID).data());
164886da342Sopenharmony_ci                    elementNodeRef.RemoveInvisibleWidget();
165886da342Sopenharmony_ci                    continue;
166886da342Sopenharmony_ci                }
167886da342Sopenharmony_ci                RefreshWidgetBounds(anchorWidget);
168886da342Sopenharmony_ci                if (anchorWidget.GetAttr(UiAttr::VISIBLE) == "false") {
169886da342Sopenharmony_ci                    LOG_D("Widget %{public}s is invisible", anchorWidget.GetAttr(UiAttr::ACCESSIBILITY_ID).data());
170886da342Sopenharmony_ci                    continue;
171886da342Sopenharmony_ci                }
172886da342Sopenharmony_ci                visitWidgets.emplace_back(move(anchorWidget));
173886da342Sopenharmony_ci                if (visitWidgets.size() > MAX_TRAVEL_TIMES) {
174886da342Sopenharmony_ci                    LOG_E("ElementInfos obtained from AAMS is abnormal, traversal node failed");
175886da342Sopenharmony_ci                    visitWidgets.clear();
176886da342Sopenharmony_ci                    return;
177886da342Sopenharmony_ci                }
178886da342Sopenharmony_ci                std::reference_wrapper<Widget const> tempAnchorWidget = visitWidgets.back();
179886da342Sopenharmony_ci                bool isAnchorMatch = true;
180886da342Sopenharmony_ci                for (const auto &anchorIt : anchorMatch_) {
181886da342Sopenharmony_ci                    isAnchorMatch = tempAnchorWidget.get().MatchAttr(anchorIt) && isAnchorMatch;
182886da342Sopenharmony_ci                    if (!isAnchorMatch) {
183886da342Sopenharmony_ci                        break;
184886da342Sopenharmony_ci                    }
185886da342Sopenharmony_ci                }
186886da342Sopenharmony_ci                if (!isAnchorMatch) {
187886da342Sopenharmony_ci                    continue;
188886da342Sopenharmony_ci                }
189886da342Sopenharmony_ci                LocateNodeAfterAnchor(window, elementNodeRef, visitWidgets, targetWidgets);
190886da342Sopenharmony_ci            }
191886da342Sopenharmony_ci        }
192886da342Sopenharmony_ci
193886da342Sopenharmony_ci        void LocateNodeAfterAnchor(const Window &window,
194886da342Sopenharmony_ci                                   ElementNodeIterator &elementNodeRef,
195886da342Sopenharmony_ci                                   std::vector<Widget> &visitWidgets,
196886da342Sopenharmony_ci                                   std::vector<int> &targetWidgets)
197886da342Sopenharmony_ci        {
198886da342Sopenharmony_ci            while (true) {
199886da342Sopenharmony_ci                Widget myselfWidget{"myselfWidget"};
200886da342Sopenharmony_ci                if (!elementNodeRef.DFSNext(myselfWidget, window.id_)) {
201886da342Sopenharmony_ci                    return;
202886da342Sopenharmony_ci                }
203886da342Sopenharmony_ci                myselfWidget.SetAttr(UiAttr::HOST_WINDOW_ID, std::to_string(window.id_));
204886da342Sopenharmony_ci                RefreshWidgetBounds(myselfWidget);
205886da342Sopenharmony_ci                if (myselfWidget.GetAttr(UiAttr::VISIBLE) == "false") {
206886da342Sopenharmony_ci                    LOG_D("Widget %{public}s is invisible", myselfWidget.GetAttr(UiAttr::ACCESSIBILITY_ID).data());
207886da342Sopenharmony_ci                    continue;
208886da342Sopenharmony_ci                }
209886da342Sopenharmony_ci                visitWidgets.emplace_back(move(myselfWidget));
210886da342Sopenharmony_ci                if (visitWidgets.size() > MAX_TRAVEL_TIMES) {
211886da342Sopenharmony_ci                    LOG_E("ElementInfos obtained from AAMS is abnormal, traversal node failed");
212886da342Sopenharmony_ci                    visitWidgets.clear();
213886da342Sopenharmony_ci                    return;
214886da342Sopenharmony_ci                }
215886da342Sopenharmony_ci                std::reference_wrapper<Widget const> tempWidget = visitWidgets.back();
216886da342Sopenharmony_ci                bool isMyselfMatch = true;
217886da342Sopenharmony_ci                for (const auto &myselfIt : myselfMatch_) {
218886da342Sopenharmony_ci                    isMyselfMatch = tempWidget.get().MatchAttr(myselfIt) && isMyselfMatch;
219886da342Sopenharmony_ci                    if (!isMyselfMatch) {
220886da342Sopenharmony_ci                        break;
221886da342Sopenharmony_ci                    }
222886da342Sopenharmony_ci                }
223886da342Sopenharmony_ci                if (!isMyselfMatch) {
224886da342Sopenharmony_ci                    continue;
225886da342Sopenharmony_ci                }
226886da342Sopenharmony_ci                targetWidgets.emplace_back(visitWidgets.size() - 1);
227886da342Sopenharmony_ci                if (!wantMulti_) {
228886da342Sopenharmony_ci                    return;
229886da342Sopenharmony_ci                }
230886da342Sopenharmony_ci            }
231886da342Sopenharmony_ci        }
232886da342Sopenharmony_ci
233886da342Sopenharmony_ci        StrategyEnum GetStrategyType() const override
234886da342Sopenharmony_ci        {
235886da342Sopenharmony_ci            return StrategyEnum::IS_AFTER;
236886da342Sopenharmony_ci        }
237886da342Sopenharmony_ci        ~AfterSelectorStrategy() override = default;
238886da342Sopenharmony_ci    };
239886da342Sopenharmony_ci
240886da342Sopenharmony_ci    class BeforeSelectorStrategy : public SelectStrategy {
241886da342Sopenharmony_ci    public:
242886da342Sopenharmony_ci        BeforeSelectorStrategy() = default;
243886da342Sopenharmony_ci        void LocateNode(const Window &window,
244886da342Sopenharmony_ci                        ElementNodeIterator &elementNodeRef,
245886da342Sopenharmony_ci                        std::vector<Widget> &visitWidgets,
246886da342Sopenharmony_ci                        std::vector<int> &targetWidgets,
247886da342Sopenharmony_ci                        bool isRemoveInvisible = true) override
248886da342Sopenharmony_ci        {
249886da342Sopenharmony_ci            elementNodeRef.ClearDFSNext();
250886da342Sopenharmony_ci            SetAndCalcSelectWindowRect(window.bounds_, window.invisibleBoundsVec_);
251886da342Sopenharmony_ci            while (true) {
252886da342Sopenharmony_ci                Widget anchorWidget{"anchorWidget"};
253886da342Sopenharmony_ci                if (!elementNodeRef.DFSNext(anchorWidget, window.id_)) {
254886da342Sopenharmony_ci                    return;
255886da342Sopenharmony_ci                }
256886da342Sopenharmony_ci                anchorWidget.SetAttr(UiAttr::HOST_WINDOW_ID, std::to_string(window.id_));
257886da342Sopenharmony_ci                if (anchorWidget.GetAttr(UiAttr::VISIBLE) == "false") {
258886da342Sopenharmony_ci                    LOG_D("Widget %{public}s is invisible", anchorWidget.GetAttr(UiAttr::ACCESSIBILITY_ID).data());
259886da342Sopenharmony_ci                    elementNodeRef.RemoveInvisibleWidget();
260886da342Sopenharmony_ci                    continue;
261886da342Sopenharmony_ci                }
262886da342Sopenharmony_ci                RefreshWidgetBounds(anchorWidget);
263886da342Sopenharmony_ci                if (anchorWidget.GetAttr(UiAttr::VISIBLE) == "false") {
264886da342Sopenharmony_ci                    LOG_D("Widget %{public}s is invisible", anchorWidget.GetAttr(UiAttr::ACCESSIBILITY_ID).data());
265886da342Sopenharmony_ci                    continue;
266886da342Sopenharmony_ci                }
267886da342Sopenharmony_ci                visitWidgets.emplace_back(move(anchorWidget));
268886da342Sopenharmony_ci                if (visitWidgets.size() > MAX_TRAVEL_TIMES) {
269886da342Sopenharmony_ci                    LOG_E("ElementInfos obtained from AAMS is abnormal, traversal node failed");
270886da342Sopenharmony_ci                    visitWidgets.clear();
271886da342Sopenharmony_ci                    return;
272886da342Sopenharmony_ci                }
273886da342Sopenharmony_ci                std::reference_wrapper<Widget const> tempAnchorWidget = visitWidgets.back();
274886da342Sopenharmony_ci                bool isAnchorMatch = true;
275886da342Sopenharmony_ci                for (const auto &anchorIt : anchorMatch_) {
276886da342Sopenharmony_ci                    isAnchorMatch = tempAnchorWidget.get().MatchAttr(anchorIt) && isAnchorMatch;
277886da342Sopenharmony_ci                    if (!isAnchorMatch) {
278886da342Sopenharmony_ci                        break;
279886da342Sopenharmony_ci                    }
280886da342Sopenharmony_ci                }
281886da342Sopenharmony_ci                if (!isAnchorMatch) {
282886da342Sopenharmony_ci                    continue;
283886da342Sopenharmony_ci                }
284886da342Sopenharmony_ci                LocateNodeAfterBeforeAnchor(visitWidgets, targetWidgets);
285886da342Sopenharmony_ci                if (!targetWidgets.empty() && !wantMulti_) {
286886da342Sopenharmony_ci                    return;
287886da342Sopenharmony_ci                }
288886da342Sopenharmony_ci            }
289886da342Sopenharmony_ci        }
290886da342Sopenharmony_ci
291886da342Sopenharmony_ci        void LocateNodeAfterBeforeAnchor(std::vector<Widget> &visitWidgets,
292886da342Sopenharmony_ci                                         std::vector<int> &targetWidgets)
293886da342Sopenharmony_ci        {
294886da342Sopenharmony_ci            size_t index = 0;
295886da342Sopenharmony_ci            if (targetWidgets.size() > 0) {
296886da342Sopenharmony_ci                index = targetWidgets[targetWidgets.size() - 1] + 1;
297886da342Sopenharmony_ci            }
298886da342Sopenharmony_ci            for (; index < visitWidgets.size() - 1; ++index) {
299886da342Sopenharmony_ci                bool isMyselfMatch = true;
300886da342Sopenharmony_ci                for (const auto &myselfIt : myselfMatch_) {
301886da342Sopenharmony_ci                    isMyselfMatch = visitWidgets[index].MatchAttr(myselfIt) && isMyselfMatch;
302886da342Sopenharmony_ci                }
303886da342Sopenharmony_ci                if (!isMyselfMatch) {
304886da342Sopenharmony_ci                    continue;
305886da342Sopenharmony_ci                }
306886da342Sopenharmony_ci                targetWidgets.emplace_back(index);
307886da342Sopenharmony_ci                if (!wantMulti_) {
308886da342Sopenharmony_ci                    return;
309886da342Sopenharmony_ci                }
310886da342Sopenharmony_ci            }
311886da342Sopenharmony_ci        }
312886da342Sopenharmony_ci
313886da342Sopenharmony_ci        StrategyEnum GetStrategyType() const override
314886da342Sopenharmony_ci        {
315886da342Sopenharmony_ci            return StrategyEnum::IS_BEFORE;
316886da342Sopenharmony_ci        }
317886da342Sopenharmony_ci        ~BeforeSelectorStrategy() override = default;
318886da342Sopenharmony_ci    };
319886da342Sopenharmony_ci
320886da342Sopenharmony_ci    class WithInSelectorStrategy : public SelectStrategy {
321886da342Sopenharmony_ci    public:
322886da342Sopenharmony_ci        WithInSelectorStrategy() = default;
323886da342Sopenharmony_ci        void LocateNode(const Window &window,
324886da342Sopenharmony_ci                        ElementNodeIterator &elementNodeRef,
325886da342Sopenharmony_ci                        std::vector<Widget> &visitWidgets,
326886da342Sopenharmony_ci                        std::vector<int> &targetWidgets,
327886da342Sopenharmony_ci                        bool isRemoveInvisible = true) override
328886da342Sopenharmony_ci        {
329886da342Sopenharmony_ci            elementNodeRef.ClearDFSNext();
330886da342Sopenharmony_ci            SetAndCalcSelectWindowRect(window.bounds_, window.invisibleBoundsVec_);
331886da342Sopenharmony_ci            while (true) {
332886da342Sopenharmony_ci                Widget anchorWidget{"withInWidget"};
333886da342Sopenharmony_ci                if (!elementNodeRef.DFSNext(anchorWidget, window.id_)) {
334886da342Sopenharmony_ci                    return;
335886da342Sopenharmony_ci                }
336886da342Sopenharmony_ci                anchorWidget.SetAttr(UiAttr::HOST_WINDOW_ID, std::to_string(window.id_));
337886da342Sopenharmony_ci                if (anchorWidget.GetAttr(UiAttr::VISIBLE) == "false") {
338886da342Sopenharmony_ci                    LOG_D("Widget %{public}s is invisible", anchorWidget.GetAttr(UiAttr::ACCESSIBILITY_ID).data());
339886da342Sopenharmony_ci                    elementNodeRef.RemoveInvisibleWidget();
340886da342Sopenharmony_ci                    continue;
341886da342Sopenharmony_ci                }
342886da342Sopenharmony_ci                RefreshWidgetBounds(anchorWidget);
343886da342Sopenharmony_ci                if (anchorWidget.GetAttr(UiAttr::VISIBLE) == "false") {
344886da342Sopenharmony_ci                    LOG_D("Widget %{public}s is invisible", anchorWidget.GetAttr(UiAttr::ACCESSIBILITY_ID).data());
345886da342Sopenharmony_ci                    continue;
346886da342Sopenharmony_ci                }
347886da342Sopenharmony_ci                visitWidgets.emplace_back(move(anchorWidget));
348886da342Sopenharmony_ci                if (visitWidgets.size() > MAX_TRAVEL_TIMES) {
349886da342Sopenharmony_ci                    LOG_E("ElementInfos obtained from AAMS is abnormal, traversal node failed");
350886da342Sopenharmony_ci                    visitWidgets.clear();
351886da342Sopenharmony_ci                    return;
352886da342Sopenharmony_ci                }
353886da342Sopenharmony_ci                std::reference_wrapper<Widget const> tempAnchorWidget = visitWidgets.back();
354886da342Sopenharmony_ci                bool isAnchorMatch = true;
355886da342Sopenharmony_ci                for (const auto &anchorIt : anchorMatch_) {
356886da342Sopenharmony_ci                    isAnchorMatch = tempAnchorWidget.get().MatchAttr(anchorIt) && isAnchorMatch;
357886da342Sopenharmony_ci                    if (!isAnchorMatch) {
358886da342Sopenharmony_ci                        break;
359886da342Sopenharmony_ci                    }
360886da342Sopenharmony_ci                }
361886da342Sopenharmony_ci                if (!isAnchorMatch) {
362886da342Sopenharmony_ci                    continue;
363886da342Sopenharmony_ci                }
364886da342Sopenharmony_ci                LocateNodeWithInAnchor(window, elementNodeRef, visitWidgets, targetWidgets);
365886da342Sopenharmony_ci                if (!targetWidgets.empty() && !wantMulti_) {
366886da342Sopenharmony_ci                    return;
367886da342Sopenharmony_ci                }
368886da342Sopenharmony_ci            }
369886da342Sopenharmony_ci        }
370886da342Sopenharmony_ci
371886da342Sopenharmony_ci        void LocateNodeWithInAnchor(const Window &window,
372886da342Sopenharmony_ci                                    ElementNodeIterator &elementNodeRef,
373886da342Sopenharmony_ci                                    std::vector<Widget> &visitWidgets,
374886da342Sopenharmony_ci                                    std::vector<int> &targetWidgets)
375886da342Sopenharmony_ci        {
376886da342Sopenharmony_ci            // restore current index and set top to anchor index
377886da342Sopenharmony_ci            elementNodeRef.RestoreNodeIndexByAnchor();
378886da342Sopenharmony_ci            while (true) {
379886da342Sopenharmony_ci                Widget myselfWidget{"myselfWidget"};
380886da342Sopenharmony_ci                if (!elementNodeRef.DFSNextWithInTarget(myselfWidget)) {
381886da342Sopenharmony_ci                    break;
382886da342Sopenharmony_ci                }
383886da342Sopenharmony_ci                myselfWidget.SetAttr(UiAttr::HOST_WINDOW_ID, std::to_string(window.id_));
384886da342Sopenharmony_ci                RefreshWidgetBounds(myselfWidget);
385886da342Sopenharmony_ci
386886da342Sopenharmony_ci                if (myselfWidget.GetAttr(UiAttr::VISIBLE) == "false") {
387886da342Sopenharmony_ci                    LOG_D("Widget %{public}s is invisible", myselfWidget.GetAttr(UiAttr::ACCESSIBILITY_ID).data());
388886da342Sopenharmony_ci                    continue;
389886da342Sopenharmony_ci                }
390886da342Sopenharmony_ci                visitWidgets.emplace_back(move(myselfWidget));
391886da342Sopenharmony_ci                if (visitWidgets.size() > MAX_TRAVEL_TIMES) {
392886da342Sopenharmony_ci                    LOG_E("ElementInfos obtained from AAMS is abnormal, traversal node failed");
393886da342Sopenharmony_ci                    visitWidgets.clear();
394886da342Sopenharmony_ci                    return;
395886da342Sopenharmony_ci                }
396886da342Sopenharmony_ci                std::reference_wrapper<Widget const> tempWidget = visitWidgets.back();
397886da342Sopenharmony_ci                bool isMyselfMatch = true;
398886da342Sopenharmony_ci                for (const auto &myselfIt : myselfMatch_) {
399886da342Sopenharmony_ci                    isMyselfMatch = tempWidget.get().MatchAttr(myselfIt) && isMyselfMatch;
400886da342Sopenharmony_ci                    if (!isMyselfMatch) {
401886da342Sopenharmony_ci                        break;
402886da342Sopenharmony_ci                    }
403886da342Sopenharmony_ci                }
404886da342Sopenharmony_ci                if (!isMyselfMatch) {
405886da342Sopenharmony_ci                    continue;
406886da342Sopenharmony_ci                }
407886da342Sopenharmony_ci                targetWidgets.emplace_back(visitWidgets.size() - 1);
408886da342Sopenharmony_ci                if (!wantMulti_) {
409886da342Sopenharmony_ci                    return;
410886da342Sopenharmony_ci                }
411886da342Sopenharmony_ci            }
412886da342Sopenharmony_ci            elementNodeRef.ResetNodeIndexToAnchor();
413886da342Sopenharmony_ci        }
414886da342Sopenharmony_ci
415886da342Sopenharmony_ci        StrategyEnum GetStrategyType() const override
416886da342Sopenharmony_ci        {
417886da342Sopenharmony_ci            return StrategyEnum::WITH_IN;
418886da342Sopenharmony_ci        }
419886da342Sopenharmony_ci        ~WithInSelectorStrategy() override = default;
420886da342Sopenharmony_ci    };
421886da342Sopenharmony_ci
422886da342Sopenharmony_ci    class PlainSelectorStrategy : public SelectStrategy {
423886da342Sopenharmony_ci    public:
424886da342Sopenharmony_ci        PlainSelectorStrategy() = default;
425886da342Sopenharmony_ci        void LocateNode(const Window &window,
426886da342Sopenharmony_ci                        ElementNodeIterator &elementNodeRef,
427886da342Sopenharmony_ci                        std::vector<Widget> &visitWidgets,
428886da342Sopenharmony_ci                        std::vector<int> &targetWidgets,
429886da342Sopenharmony_ci                        bool isRemoveInvisible = true) override
430886da342Sopenharmony_ci        {
431886da342Sopenharmony_ci            elementNodeRef.ClearDFSNext();
432886da342Sopenharmony_ci            SetAndCalcSelectWindowRect(window.bounds_, window.invisibleBoundsVec_);
433886da342Sopenharmony_ci            while (true) {
434886da342Sopenharmony_ci                Widget myselfWidget{"myselfWidget"};
435886da342Sopenharmony_ci                if (!elementNodeRef.DFSNext(myselfWidget, window.id_)) {
436886da342Sopenharmony_ci                    return;
437886da342Sopenharmony_ci                }
438886da342Sopenharmony_ci                myselfWidget.SetAttr(UiAttr::HOST_WINDOW_ID, std::to_string(window.id_));
439886da342Sopenharmony_ci                if (isRemoveInvisible) {
440886da342Sopenharmony_ci                    if (myselfWidget.GetAttr(UiAttr::VISIBLE) == "false") {
441886da342Sopenharmony_ci                        LOG_D("Widget %{public}s is invisible", myselfWidget.GetAttr(UiAttr::ACCESSIBILITY_ID).data());
442886da342Sopenharmony_ci                        elementNodeRef.RemoveInvisibleWidget();
443886da342Sopenharmony_ci                        continue;
444886da342Sopenharmony_ci                    }
445886da342Sopenharmony_ci                    RefreshWidgetBounds(myselfWidget);
446886da342Sopenharmony_ci                }
447886da342Sopenharmony_ci                visitWidgets.emplace_back(move(myselfWidget));
448886da342Sopenharmony_ci                if (visitWidgets.size() > MAX_TRAVEL_TIMES) {
449886da342Sopenharmony_ci                    LOG_E("ElementInfos obtained from AAMS is abnormal, traversal node failed");
450886da342Sopenharmony_ci                    visitWidgets.clear();
451886da342Sopenharmony_ci                    return;
452886da342Sopenharmony_ci                }
453886da342Sopenharmony_ci                if (myselfWidget.GetAttr(UiAttr::VISIBLE) == "false") {
454886da342Sopenharmony_ci                    continue;
455886da342Sopenharmony_ci                }
456886da342Sopenharmony_ci                std::reference_wrapper<Widget const> tempWidget = visitWidgets.back();
457886da342Sopenharmony_ci                bool isMyselfMatch = true;
458886da342Sopenharmony_ci                for (const auto &myselfIt : myselfMatch_) {
459886da342Sopenharmony_ci                    isMyselfMatch = tempWidget.get().MatchAttr(myselfIt) && isMyselfMatch;
460886da342Sopenharmony_ci                    if (!isMyselfMatch) {
461886da342Sopenharmony_ci                        break;
462886da342Sopenharmony_ci                    }
463886da342Sopenharmony_ci                }
464886da342Sopenharmony_ci                if (!isMyselfMatch) {
465886da342Sopenharmony_ci                    continue;
466886da342Sopenharmony_ci                }
467886da342Sopenharmony_ci                targetWidgets.emplace_back(visitWidgets.size() - 1);
468886da342Sopenharmony_ci                if (!wantMulti_) {
469886da342Sopenharmony_ci                    return;
470886da342Sopenharmony_ci                }
471886da342Sopenharmony_ci            }
472886da342Sopenharmony_ci        }
473886da342Sopenharmony_ci
474886da342Sopenharmony_ci        StrategyEnum GetStrategyType() const override
475886da342Sopenharmony_ci        {
476886da342Sopenharmony_ci            return StrategyEnum::PLAIN;
477886da342Sopenharmony_ci        }
478886da342Sopenharmony_ci        ~PlainSelectorStrategy() override = default;
479886da342Sopenharmony_ci    };
480886da342Sopenharmony_ci
481886da342Sopenharmony_ci    class ComplexSelectorStrategy : public SelectStrategy {
482886da342Sopenharmony_ci    public:
483886da342Sopenharmony_ci        ComplexSelectorStrategy() = default;
484886da342Sopenharmony_ci        void LocateNode(const Window &window,
485886da342Sopenharmony_ci                        ElementNodeIterator &elementNodeRef,
486886da342Sopenharmony_ci                        std::vector<Widget> &visitWidgets,
487886da342Sopenharmony_ci                        std::vector<int> &targetWidgets,
488886da342Sopenharmony_ci                        bool isRemoveInvisible = true) override
489886da342Sopenharmony_ci        {
490886da342Sopenharmony_ci            elementNodeRef.ClearDFSNext();
491886da342Sopenharmony_ci            SetAndCalcSelectWindowRect(window.bounds_, window.invisibleBoundsVec_);
492886da342Sopenharmony_ci            std::vector<int> fakeTargetWidgets;
493886da342Sopenharmony_ci            while (true) {
494886da342Sopenharmony_ci                Widget myselfWidget{"myselfWidget"};
495886da342Sopenharmony_ci                if (!elementNodeRef.DFSNext(myselfWidget, window.id_)) {
496886da342Sopenharmony_ci                    break;
497886da342Sopenharmony_ci                }
498886da342Sopenharmony_ci                myselfWidget.SetAttr(UiAttr::HOST_WINDOW_ID, std::to_string(window.id_));
499886da342Sopenharmony_ci                if (myselfWidget.GetAttr(UiAttr::VISIBLE) == "false") {
500886da342Sopenharmony_ci                    LOG_D("Widget %{public}s is invisible", myselfWidget.GetAttr(UiAttr::ACCESSIBILITY_ID).data());
501886da342Sopenharmony_ci                    elementNodeRef.RemoveInvisibleWidget();
502886da342Sopenharmony_ci                    continue;
503886da342Sopenharmony_ci                }
504886da342Sopenharmony_ci                RefreshWidgetBounds(myselfWidget);
505886da342Sopenharmony_ci                if (myselfWidget.GetAttr(UiAttr::VISIBLE) == "false") {
506886da342Sopenharmony_ci                    continue;
507886da342Sopenharmony_ci                }
508886da342Sopenharmony_ci                visitWidgets.emplace_back(move(myselfWidget));
509886da342Sopenharmony_ci                if (visitWidgets.size() > MAX_TRAVEL_TIMES) {
510886da342Sopenharmony_ci                    LOG_E("ElementInfos obtained from AAMS is abnormal, traversal node failed");
511886da342Sopenharmony_ci                    visitWidgets.clear();
512886da342Sopenharmony_ci                    return;
513886da342Sopenharmony_ci                }
514886da342Sopenharmony_ci                std::reference_wrapper<Widget const> tempWidget = visitWidgets.back();
515886da342Sopenharmony_ci                bool isMyselfMatch = true;
516886da342Sopenharmony_ci                for (const auto &myselfIt : myselfMatch_) {
517886da342Sopenharmony_ci                    isMyselfMatch = tempWidget.get().MatchAttr(myselfIt) && isMyselfMatch;
518886da342Sopenharmony_ci                    if (!isMyselfMatch) {
519886da342Sopenharmony_ci                        break;
520886da342Sopenharmony_ci                    }
521886da342Sopenharmony_ci                }
522886da342Sopenharmony_ci                if (!isMyselfMatch) {
523886da342Sopenharmony_ci                    continue;
524886da342Sopenharmony_ci                }
525886da342Sopenharmony_ci                fakeTargetWidgets.emplace_back(visitWidgets.size() - 1);
526886da342Sopenharmony_ci            }
527886da342Sopenharmony_ci            DoComplexSelect(visitWidgets, fakeTargetWidgets, targetWidgets);
528886da342Sopenharmony_ci        }
529886da342Sopenharmony_ci
530886da342Sopenharmony_ci        void RegisterMultiAfterAnchor(const std::vector<WidgetMatchModel> &afterAnchor)
531886da342Sopenharmony_ci        {
532886da342Sopenharmony_ci            multiAfterAnchorMatcher.emplace_back(afterAnchor);
533886da342Sopenharmony_ci        }
534886da342Sopenharmony_ci
535886da342Sopenharmony_ci        void RegisterMultiBeforeAnchor(const std::vector<WidgetMatchModel> &beforeAnchor)
536886da342Sopenharmony_ci        {
537886da342Sopenharmony_ci            multiBeforeAnchorMatcher.emplace_back(beforeAnchor);
538886da342Sopenharmony_ci        }
539886da342Sopenharmony_ci
540886da342Sopenharmony_ci        void RegisterMultiWithInAnchor(const std::vector<WidgetMatchModel> &withInAnchor)
541886da342Sopenharmony_ci        {
542886da342Sopenharmony_ci            multiWithInAnchorMatcher.emplace_back(withInAnchor);
543886da342Sopenharmony_ci        }
544886da342Sopenharmony_ci
545886da342Sopenharmony_ci        int CalcMaxAfterAnchorIndex(const std::vector<Widget> &visitWidgets)
546886da342Sopenharmony_ci        {
547886da342Sopenharmony_ci            int32_t startAfterIndex = -1;
548886da342Sopenharmony_ci            for (auto &afterLocator : multiAfterAnchorMatcher) {
549886da342Sopenharmony_ci                int32_t startIndex = 0;
550886da342Sopenharmony_ci                for (; static_cast<size_t>(startIndex) < visitWidgets.size(); ++startIndex) {
551886da342Sopenharmony_ci                    bool isFrontMatch = true;
552886da342Sopenharmony_ci                    for (auto &attrModel : afterLocator) {
553886da342Sopenharmony_ci                        isFrontMatch = isFrontMatch && visitWidgets[startIndex].MatchAttr(attrModel);
554886da342Sopenharmony_ci                    }
555886da342Sopenharmony_ci                    if (isFrontMatch) {
556886da342Sopenharmony_ci                        startAfterIndex = startAfterIndex > startIndex ? startAfterIndex : startIndex;
557886da342Sopenharmony_ci                        break;
558886da342Sopenharmony_ci                    }
559886da342Sopenharmony_ci                }
560886da342Sopenharmony_ci                if (static_cast<size_t>(startIndex) == visitWidgets.size()) {
561886da342Sopenharmony_ci                    startAfterIndex = visitWidgets.size();
562886da342Sopenharmony_ci                }
563886da342Sopenharmony_ci            }
564886da342Sopenharmony_ci            return startAfterIndex;
565886da342Sopenharmony_ci        }
566886da342Sopenharmony_ci
567886da342Sopenharmony_ci        int CalcMinBeforeAnchorIndex(const std::vector<Widget> &visitWidgets)
568886da342Sopenharmony_ci        {
569886da342Sopenharmony_ci            int startBeforeIndex = visitWidgets.size();
570886da342Sopenharmony_ci            for (auto &beforeLocator : multiBeforeAnchorMatcher) {
571886da342Sopenharmony_ci                int beforeIndex = visitWidgets.size() - 1;
572886da342Sopenharmony_ci                for (; beforeIndex > 0; --beforeIndex) {
573886da342Sopenharmony_ci                    bool isRearMatch = true;
574886da342Sopenharmony_ci                    for (auto &attrModel : beforeLocator) {
575886da342Sopenharmony_ci                        isRearMatch = isRearMatch && visitWidgets[beforeIndex].MatchAttr(attrModel);
576886da342Sopenharmony_ci                    }
577886da342Sopenharmony_ci                    if (isRearMatch) {
578886da342Sopenharmony_ci                        startBeforeIndex = startBeforeIndex > beforeIndex ? beforeIndex : startBeforeIndex;
579886da342Sopenharmony_ci                        break;
580886da342Sopenharmony_ci                    }
581886da342Sopenharmony_ci                }
582886da342Sopenharmony_ci                if (beforeIndex == 0) {
583886da342Sopenharmony_ci                    startBeforeIndex = 0;
584886da342Sopenharmony_ci                }
585886da342Sopenharmony_ci            }
586886da342Sopenharmony_ci            return startBeforeIndex;
587886da342Sopenharmony_ci        }
588886da342Sopenharmony_ci
589886da342Sopenharmony_ci        bool CheckTargetIdByParentSelect(const std::vector<int> &parentIndexVec,
590886da342Sopenharmony_ci                                         const std::vector<Widget> &visitWidgets)
591886da342Sopenharmony_ci        {
592886da342Sopenharmony_ci            bool isAllLocatorMatch = true;
593886da342Sopenharmony_ci            for (auto &parentLocator : multiWithInAnchorMatcher) {
594886da342Sopenharmony_ci                bool hasValidParent = false;
595886da342Sopenharmony_ci                for (auto &parentIndex : parentIndexVec) {
596886da342Sopenharmony_ci                    bool isMatch = true;
597886da342Sopenharmony_ci                    for (auto &selfMatch : parentLocator) {
598886da342Sopenharmony_ci                        isMatch = isMatch && visitWidgets[parentIndex].MatchAttr(selfMatch);
599886da342Sopenharmony_ci                    }
600886da342Sopenharmony_ci                    hasValidParent = hasValidParent || isMatch;
601886da342Sopenharmony_ci                    if (hasValidParent) {
602886da342Sopenharmony_ci                        break;
603886da342Sopenharmony_ci                    }
604886da342Sopenharmony_ci                }
605886da342Sopenharmony_ci                isAllLocatorMatch = isAllLocatorMatch && hasValidParent;
606886da342Sopenharmony_ci                if (!isAllLocatorMatch) {
607886da342Sopenharmony_ci                    break;
608886da342Sopenharmony_ci                }
609886da342Sopenharmony_ci            }
610886da342Sopenharmony_ci            return isAllLocatorMatch;
611886da342Sopenharmony_ci        }
612886da342Sopenharmony_ci
613886da342Sopenharmony_ci        void LocateNodeWithInComplexSelect(std::vector<int> &filterParentValidId,
614886da342Sopenharmony_ci                                           const std::vector<Widget> &visitWidgets,
615886da342Sopenharmony_ci                                           const std::vector<int> &myselfTargets)
616886da342Sopenharmony_ci        {
617886da342Sopenharmony_ci            for (int targetId : myselfTargets) {
618886da342Sopenharmony_ci                const std::string &targetHie = visitWidgets[targetId].GetHierarchy();
619886da342Sopenharmony_ci                std::vector<int> parentIndexVec;
620886da342Sopenharmony_ci                for (size_t index = 0; index < visitWidgets.size(); ++index) {
621886da342Sopenharmony_ci                    const std::string &visitHie = visitWidgets[index].GetHierarchy();
622886da342Sopenharmony_ci                    if (targetHie.length() <= visitHie.length() || targetHie.find(visitHie) != 0) {
623886da342Sopenharmony_ci                        continue;
624886da342Sopenharmony_ci                    }
625886da342Sopenharmony_ci                    parentIndexVec.emplace_back(index);
626886da342Sopenharmony_ci                }
627886da342Sopenharmony_ci                bool isAllLocatorMatch = CheckTargetIdByParentSelect(parentIndexVec, visitWidgets);
628886da342Sopenharmony_ci                if (isAllLocatorMatch) {
629886da342Sopenharmony_ci                    filterParentValidId.emplace_back(targetId);
630886da342Sopenharmony_ci                }
631886da342Sopenharmony_ci            }
632886da342Sopenharmony_ci        }
633886da342Sopenharmony_ci
634886da342Sopenharmony_ci        void DoComplexSelect(const std::vector<Widget> &visitWidgets,
635886da342Sopenharmony_ci                             std::vector<int> &fakeTargets,
636886da342Sopenharmony_ci                             std::vector<int> &myselfTargets)
637886da342Sopenharmony_ci        {
638886da342Sopenharmony_ci            int startAfterIndex = CalcMaxAfterAnchorIndex(visitWidgets);
639886da342Sopenharmony_ci            int startBeforeIndex = CalcMinBeforeAnchorIndex(visitWidgets);
640886da342Sopenharmony_ci            if (startBeforeIndex <= startAfterIndex) {
641886da342Sopenharmony_ci                return;
642886da342Sopenharmony_ci            }
643886da342Sopenharmony_ci            for (auto index : fakeTargets) {
644886da342Sopenharmony_ci                if (index > startAfterIndex && index < startBeforeIndex) {
645886da342Sopenharmony_ci                    myselfTargets.emplace_back(index);
646886da342Sopenharmony_ci                }
647886da342Sopenharmony_ci            }
648886da342Sopenharmony_ci
649886da342Sopenharmony_ci            if (myselfTargets.empty()) {
650886da342Sopenharmony_ci                return;
651886da342Sopenharmony_ci            }
652886da342Sopenharmony_ci            if (multiWithInAnchorMatcher.empty()) {
653886da342Sopenharmony_ci                if (!wantMulti_) {
654886da342Sopenharmony_ci                    myselfTargets.erase(myselfTargets.begin() + 1, myselfTargets.end());
655886da342Sopenharmony_ci                }
656886da342Sopenharmony_ci                return;
657886da342Sopenharmony_ci            }
658886da342Sopenharmony_ci            std::vector<int> filterParentValidId;
659886da342Sopenharmony_ci            LocateNodeWithInComplexSelect(filterParentValidId, visitWidgets, myselfTargets);
660886da342Sopenharmony_ci            if (filterParentValidId.empty()) {
661886da342Sopenharmony_ci                myselfTargets.clear();
662886da342Sopenharmony_ci                return;
663886da342Sopenharmony_ci            }
664886da342Sopenharmony_ci            if (wantMulti_) {
665886da342Sopenharmony_ci                myselfTargets = filterParentValidId;
666886da342Sopenharmony_ci            } else {
667886da342Sopenharmony_ci                myselfTargets.clear();
668886da342Sopenharmony_ci                myselfTargets.emplace_back(filterParentValidId.at(0));
669886da342Sopenharmony_ci            }
670886da342Sopenharmony_ci        }
671886da342Sopenharmony_ci
672886da342Sopenharmony_ci        StrategyEnum GetStrategyType() const override
673886da342Sopenharmony_ci        {
674886da342Sopenharmony_ci            return StrategyEnum::COMPLEX;
675886da342Sopenharmony_ci        }
676886da342Sopenharmony_ci        ~ComplexSelectorStrategy() override = default;
677886da342Sopenharmony_ci
678886da342Sopenharmony_ci    private:
679886da342Sopenharmony_ci        std::vector<std::vector<WidgetMatchModel>> multiAfterAnchorMatcher;
680886da342Sopenharmony_ci        std::vector<std::vector<WidgetMatchModel>> multiBeforeAnchorMatcher;
681886da342Sopenharmony_ci        std::vector<std::vector<WidgetMatchModel>> multiWithInAnchorMatcher;
682886da342Sopenharmony_ci    };
683886da342Sopenharmony_ci
684886da342Sopenharmony_ci    static std::unique_ptr<SelectStrategy> BuildComplexStrategy(const StrategyBuildParam &buildParam, bool isWantMulti)
685886da342Sopenharmony_ci    {
686886da342Sopenharmony_ci        std::unique_ptr<ComplexSelectorStrategy> selectStrategy = std::make_unique<ComplexSelectorStrategy>();
687886da342Sopenharmony_ci        for (const auto &matchModel : buildParam.myselfMatcher) {
688886da342Sopenharmony_ci            selectStrategy->RegisterMyselfMatch(matchModel);
689886da342Sopenharmony_ci        }
690886da342Sopenharmony_ci        for (const auto &afterWidgetAnchor : buildParam.afterAnchorMatcherVec) {
691886da342Sopenharmony_ci            selectStrategy->RegisterMultiAfterAnchor(afterWidgetAnchor);
692886da342Sopenharmony_ci        }
693886da342Sopenharmony_ci        for (const auto &beforeWidgetAnchor : buildParam.beforeAnchorMatcherVec) {
694886da342Sopenharmony_ci            selectStrategy->RegisterMultiBeforeAnchor(beforeWidgetAnchor);
695886da342Sopenharmony_ci        }
696886da342Sopenharmony_ci        for (const auto &withInWidgetAnchor : buildParam.withInAnchorMatcherVec) {
697886da342Sopenharmony_ci            selectStrategy->RegisterMultiWithInAnchor(withInWidgetAnchor);
698886da342Sopenharmony_ci        }
699886da342Sopenharmony_ci        selectStrategy->SetWantMulti(isWantMulti);
700886da342Sopenharmony_ci        return selectStrategy;
701886da342Sopenharmony_ci    }
702886da342Sopenharmony_ci
703886da342Sopenharmony_ci    static std::unique_ptr<SelectStrategy> BuildWithInStrategy(const StrategyBuildParam &buildParam, bool isWantMulti)
704886da342Sopenharmony_ci    {
705886da342Sopenharmony_ci        std::unique_ptr<SelectStrategy> selectStrategy = std::make_unique<WithInSelectorStrategy>();
706886da342Sopenharmony_ci        for (const auto &matchModel : buildParam.myselfMatcher) {
707886da342Sopenharmony_ci            selectStrategy->RegisterMyselfMatch(matchModel);
708886da342Sopenharmony_ci        }
709886da342Sopenharmony_ci        for (const auto &anchorModel : buildParam.withInAnchorMatcherVec.at(0)) {
710886da342Sopenharmony_ci            selectStrategy->RegisterAnchorMatch(anchorModel);
711886da342Sopenharmony_ci        }
712886da342Sopenharmony_ci        selectStrategy->SetWantMulti(isWantMulti);
713886da342Sopenharmony_ci        return selectStrategy;
714886da342Sopenharmony_ci    }
715886da342Sopenharmony_ci
716886da342Sopenharmony_ci    static std::unique_ptr<SelectStrategy> BuildBeforeStrategy(const StrategyBuildParam &buildParam, bool isWantMulti)
717886da342Sopenharmony_ci    {
718886da342Sopenharmony_ci        std::unique_ptr<SelectStrategy> selectStrategy = std::make_unique<BeforeSelectorStrategy>();
719886da342Sopenharmony_ci        for (const auto &matchModel : buildParam.myselfMatcher) {
720886da342Sopenharmony_ci            selectStrategy->RegisterMyselfMatch(matchModel);
721886da342Sopenharmony_ci        }
722886da342Sopenharmony_ci        for (const auto &anchorModel : buildParam.beforeAnchorMatcherVec.at(0)) {
723886da342Sopenharmony_ci            selectStrategy->RegisterAnchorMatch(anchorModel);
724886da342Sopenharmony_ci        }
725886da342Sopenharmony_ci        selectStrategy->SetWantMulti(isWantMulti);
726886da342Sopenharmony_ci        return selectStrategy;
727886da342Sopenharmony_ci    }
728886da342Sopenharmony_ci
729886da342Sopenharmony_ci    static std::unique_ptr<SelectStrategy> BuildAfterStrategy(const StrategyBuildParam &buildParam, bool isWantMulti)
730886da342Sopenharmony_ci    {
731886da342Sopenharmony_ci        std::unique_ptr<SelectStrategy> selectStrategy = std::make_unique<AfterSelectorStrategy>();
732886da342Sopenharmony_ci        for (const auto &matchModel : buildParam.myselfMatcher) {
733886da342Sopenharmony_ci            selectStrategy->RegisterMyselfMatch(matchModel);
734886da342Sopenharmony_ci        }
735886da342Sopenharmony_ci        for (const auto &anchorModel : buildParam.afterAnchorMatcherVec.at(0)) {
736886da342Sopenharmony_ci            selectStrategy->RegisterAnchorMatch(anchorModel);
737886da342Sopenharmony_ci        }
738886da342Sopenharmony_ci        selectStrategy->SetWantMulti(isWantMulti);
739886da342Sopenharmony_ci        return selectStrategy;
740886da342Sopenharmony_ci    }
741886da342Sopenharmony_ci
742886da342Sopenharmony_ci    std::unique_ptr<SelectStrategy> SelectStrategy::BuildSelectStrategy(const StrategyBuildParam &buildParam,
743886da342Sopenharmony_ci                                                                        bool isWantMulti)
744886da342Sopenharmony_ci    {
745886da342Sopenharmony_ci        if (buildParam.afterAnchorMatcherVec.empty() && buildParam.beforeAnchorMatcherVec.empty() &&
746886da342Sopenharmony_ci            buildParam.withInAnchorMatcherVec.empty()) {
747886da342Sopenharmony_ci            std::unique_ptr<SelectStrategy> selectStrategy = std::make_unique<PlainSelectorStrategy>();
748886da342Sopenharmony_ci            for (const auto &matchModel : buildParam.myselfMatcher) {
749886da342Sopenharmony_ci                selectStrategy->RegisterMyselfMatch(matchModel);
750886da342Sopenharmony_ci            }
751886da342Sopenharmony_ci            selectStrategy->SetWantMulti(isWantMulti);
752886da342Sopenharmony_ci            return selectStrategy;
753886da342Sopenharmony_ci        } else if (!buildParam.afterAnchorMatcherVec.empty() && (buildParam.afterAnchorMatcherVec.size() == 1) &&
754886da342Sopenharmony_ci                   buildParam.beforeAnchorMatcherVec.empty() && buildParam.withInAnchorMatcherVec.empty()) {
755886da342Sopenharmony_ci            return BuildAfterStrategy(buildParam, isWantMulti);
756886da342Sopenharmony_ci        } else if (buildParam.afterAnchorMatcherVec.empty() && !buildParam.beforeAnchorMatcherVec.empty() &&
757886da342Sopenharmony_ci                   (buildParam.beforeAnchorMatcherVec.size() == 1) && buildParam.withInAnchorMatcherVec.empty()) {
758886da342Sopenharmony_ci            return BuildBeforeStrategy(buildParam, isWantMulti);
759886da342Sopenharmony_ci        } else if (buildParam.afterAnchorMatcherVec.empty() && buildParam.beforeAnchorMatcherVec.empty() &&
760886da342Sopenharmony_ci                   !buildParam.withInAnchorMatcherVec.empty() && (buildParam.withInAnchorMatcherVec.size() == 1)) {
761886da342Sopenharmony_ci            return BuildWithInStrategy(buildParam, isWantMulti);
762886da342Sopenharmony_ci        } else {
763886da342Sopenharmony_ci            return BuildComplexStrategy(buildParam, isWantMulti);
764886da342Sopenharmony_ci        }
765886da342Sopenharmony_ci    }
766886da342Sopenharmony_ci} // namespace OHOS::uitest