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 "json.hpp"
17886da342Sopenharmony_ci#include "ui_model.h"
18886da342Sopenharmony_ci
19886da342Sopenharmony_cinamespace OHOS::uitest {
20886da342Sopenharmony_ci    using namespace std;
21886da342Sopenharmony_ci    using namespace nlohmann;
22886da342Sopenharmony_ci
23886da342Sopenharmony_ci    struct DumperCache {
24886da342Sopenharmony_ci        std::map<std::string, int> visitWidgetMap_;
25886da342Sopenharmony_ci        std::map<std::string, int> widgetCountMap_;
26886da342Sopenharmony_ci        std::set<std::string> visibleWidgetHies_;
27886da342Sopenharmony_ci    };
28886da342Sopenharmony_ci
29886da342Sopenharmony_ci    static string_view GetMiddleStr(string_view str, size_t &index, string_view startStr, string_view endStr)
30886da342Sopenharmony_ci    {
31886da342Sopenharmony_ci        size_t ori = index;
32886da342Sopenharmony_ci        auto begin = str.find(startStr, index);
33886da342Sopenharmony_ci        if (begin != string::npos) {
34886da342Sopenharmony_ci            index = begin + startStr.size();
35886da342Sopenharmony_ci            auto end = str.find(endStr, index);
36886da342Sopenharmony_ci            if (end != string::npos) {
37886da342Sopenharmony_ci                string_view result = str.substr(index, end - index);
38886da342Sopenharmony_ci                index = end;
39886da342Sopenharmony_ci                return result;
40886da342Sopenharmony_ci            }
41886da342Sopenharmony_ci        }
42886da342Sopenharmony_ci        index = ori;
43886da342Sopenharmony_ci        return "";
44886da342Sopenharmony_ci    }
45886da342Sopenharmony_ci
46886da342Sopenharmony_ci    static bool HasVisibleChild(const std::set<std::string> &visibleWidgetHies, const string &hie)
47886da342Sopenharmony_ci    {
48886da342Sopenharmony_ci        for (auto visibleHie : visibleWidgetHies) {
49886da342Sopenharmony_ci            if (visibleHie.find(hie) != string::npos) {
50886da342Sopenharmony_ci                return true;
51886da342Sopenharmony_ci            }
52886da342Sopenharmony_ci        }
53886da342Sopenharmony_ci        return false;
54886da342Sopenharmony_ci    }
55886da342Sopenharmony_ci
56886da342Sopenharmony_ci    static void DFSMarshalWidget(std::vector<Widget> &allWidget, int index, nlohmann::json &dom,
57886da342Sopenharmony_ci        const DumperCache &cache)
58886da342Sopenharmony_ci    {
59886da342Sopenharmony_ci        auto attrData = json();
60886da342Sopenharmony_ci        allWidget.at(index).WrapperWidgetToJson(attrData);
61886da342Sopenharmony_ci        auto childrenData = json::array();
62886da342Sopenharmony_ci        int childIndex = 0;
63886da342Sopenharmony_ci        int childCount = 0;
64886da342Sopenharmony_ci        int childVisit = 0;
65886da342Sopenharmony_ci        auto hierarchy = allWidget.at(index).GetHierarchy();
66886da342Sopenharmony_ci        if (cache.widgetCountMap_.find(hierarchy) != cache.widgetCountMap_.cend()) {
67886da342Sopenharmony_ci            childCount = cache.widgetCountMap_.at(hierarchy);
68886da342Sopenharmony_ci        }
69886da342Sopenharmony_ci        while (childVisit < childCount) {
70886da342Sopenharmony_ci            auto tempChildHierarchy = WidgetHierarchyBuilder::GetChildHierarchy(hierarchy, childIndex);
71886da342Sopenharmony_ci            ++childIndex;
72886da342Sopenharmony_ci            if (cache.visitWidgetMap_.find(tempChildHierarchy) == cache.visitWidgetMap_.cend()) {
73886da342Sopenharmony_ci                continue;
74886da342Sopenharmony_ci            }
75886da342Sopenharmony_ci            auto childWidIndex = cache.visitWidgetMap_.at(tempChildHierarchy);
76886da342Sopenharmony_ci            if (!allWidget.at(childWidIndex).IsVisible()) {
77886da342Sopenharmony_ci                if (!HasVisibleChild(cache.visibleWidgetHies_, tempChildHierarchy)) {
78886da342Sopenharmony_ci                    ++childVisit;
79886da342Sopenharmony_ci                    continue;
80886da342Sopenharmony_ci                }
81886da342Sopenharmony_ci            }
82886da342Sopenharmony_ci            auto childData = json();
83886da342Sopenharmony_ci            DFSMarshalWidget(allWidget, childWidIndex, childData, cache);
84886da342Sopenharmony_ci            childrenData.emplace_back(childData);
85886da342Sopenharmony_ci            ++childVisit;
86886da342Sopenharmony_ci        }
87886da342Sopenharmony_ci        dom["attributes"] = attrData;
88886da342Sopenharmony_ci        dom["children"] = childrenData;
89886da342Sopenharmony_ci    }
90886da342Sopenharmony_ci
91886da342Sopenharmony_ci    void DumpHandler::AddExtraAttrs(nlohmann::json &root, const map<int32_t, string_view> &elementTrees, size_t index)
92886da342Sopenharmony_ci    {
93886da342Sopenharmony_ci        auto windowIdValue = root["attributes"]["hostWindowId"].dump();
94886da342Sopenharmony_ci        auto windowId = atoi(windowIdValue.substr(1, windowIdValue.size() - 2).c_str());
95886da342Sopenharmony_ci        auto find = elementTrees.find(windowId);
96886da342Sopenharmony_ci        auto elementTree = (find != elementTrees.end()) ? find->second : "";
97886da342Sopenharmony_ci        string_view nodeEndStr = "|->";
98886da342Sopenharmony_ci        auto accessibilityIdInfo = root["attributes"]["accessibilityId"].dump();
99886da342Sopenharmony_ci        auto accessibilityId = accessibilityIdInfo.substr(1, accessibilityIdInfo.size() - 2);
100886da342Sopenharmony_ci        string_view accessibilityIdStr = "AccessibilityId: " + accessibilityId;
101886da342Sopenharmony_ci        string_view nodeAttrStr = GetMiddleStr(elementTree, index, accessibilityIdStr, nodeEndStr);
102886da342Sopenharmony_ci        auto extraAttrs = json();
103886da342Sopenharmony_ci        size_t nodeAttrTraverlIndex = 0;
104886da342Sopenharmony_ci        auto backgroundColor = GetMiddleStr(nodeAttrStr, nodeAttrTraverlIndex, "BackgroundColor: ", "\n");
105886da342Sopenharmony_ci        auto content = GetMiddleStr(nodeAttrStr, nodeAttrTraverlIndex, "Content: ", "\n");
106886da342Sopenharmony_ci        auto fontColor = GetMiddleStr(nodeAttrStr, nodeAttrTraverlIndex, "FontColor: ", "\n");
107886da342Sopenharmony_ci        auto fontSize = GetMiddleStr(nodeAttrStr, nodeAttrTraverlIndex, "FontSize: ", "\n");
108886da342Sopenharmony_ci        if (!backgroundColor.empty()) {
109886da342Sopenharmony_ci            extraAttrs["BackgroundColor"] = backgroundColor;
110886da342Sopenharmony_ci        }
111886da342Sopenharmony_ci        if (!content.empty()) {
112886da342Sopenharmony_ci            extraAttrs["Content"] = move(content);
113886da342Sopenharmony_ci        }
114886da342Sopenharmony_ci        if (!fontColor.empty()) {
115886da342Sopenharmony_ci            extraAttrs["FontColor"] = move(fontColor);
116886da342Sopenharmony_ci        }
117886da342Sopenharmony_ci        if (!fontSize.empty()) {
118886da342Sopenharmony_ci            extraAttrs["FontSize"] = move(fontSize);
119886da342Sopenharmony_ci        }
120886da342Sopenharmony_ci        if (!extraAttrs.empty()) {
121886da342Sopenharmony_ci            root["extraAttrs"] = extraAttrs;
122886da342Sopenharmony_ci        }
123886da342Sopenharmony_ci        auto &childrenData = root["children"];
124886da342Sopenharmony_ci        auto childCount = childrenData.size();
125886da342Sopenharmony_ci        for (size_t idx = 0; idx < childCount; idx++) {
126886da342Sopenharmony_ci            auto &child = childrenData.at(idx);
127886da342Sopenharmony_ci            AddExtraAttrs(child, elementTrees, index);
128886da342Sopenharmony_ci        }
129886da342Sopenharmony_ci    }
130886da342Sopenharmony_ci
131886da342Sopenharmony_ci    void DumpHandler::DumpWindowInfoToJson(vector<Widget> &allWidget, nlohmann::json &root)
132886da342Sopenharmony_ci    {
133886da342Sopenharmony_ci        DumperCache cache;
134886da342Sopenharmony_ci        for (size_t i = 0; i < allWidget.size(); ++i) {
135886da342Sopenharmony_ci            const Widget &wid = allWidget.at(i);
136886da342Sopenharmony_ci            std::string hie = wid.GetHierarchy();
137886da342Sopenharmony_ci            cache.visitWidgetMap_.emplace(hie, i);
138886da342Sopenharmony_ci            std::string parentHie = WidgetHierarchyBuilder::GetParentWidgetHierarchy(hie);
139886da342Sopenharmony_ci            if (cache.widgetCountMap_.find(parentHie) == cache.widgetCountMap_.cend()) {
140886da342Sopenharmony_ci                cache.widgetCountMap_[parentHie] = 1;
141886da342Sopenharmony_ci            } else {
142886da342Sopenharmony_ci                cache.widgetCountMap_[parentHie] = cache.widgetCountMap_[parentHie] + 1;
143886da342Sopenharmony_ci            }
144886da342Sopenharmony_ci            if (wid.IsVisible()) {
145886da342Sopenharmony_ci                cache.visibleWidgetHies_.insert(hie);
146886da342Sopenharmony_ci            }
147886da342Sopenharmony_ci        }
148886da342Sopenharmony_ci        DFSMarshalWidget(allWidget, 0, root, cache);
149886da342Sopenharmony_ci    }
150886da342Sopenharmony_ci} // namespace OHOS::uitest