1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "layout_parser.h"
17 #include "component/component_factory.h"
18 #include "components/ui_view.h"
19 #include "json_visitor.h"
20 #include "log/log.h"
21 #include "view_api.h"
22
23 namespace Updater {
24 namespace {
25 constexpr auto DEFAULT_MODULE = "default";
26 constexpr auto COMPONENT_MODULE = "coms";
27 constexpr auto COMMON_LABEL = "Common";
28 constexpr auto COMMON_TYPE = "type";
29 }
30
31 class LayoutParser::Impl {
32 using cJSONPtr = std::unique_ptr<cJSON, decltype(&cJSON_Delete)>;
33 public:
LoadLayout(const std::vector<std::string> & layoutFiles,std::vector<UxPageInfo> & vec) const34 bool LoadLayout(const std::vector<std::string> &layoutFiles, std::vector<UxPageInfo> &vec) const
35 {
36 std::vector<UxPageInfo>().swap(vec);
37 UxPageInfo pageInfo = {};
38 for (const auto &file : layoutFiles) {
39 if (!LoadLayout(file, pageInfo)) {
40 LOG(ERROR) << file << " load failed";
41 return false;
42 }
43 vec.push_back(std::move(pageInfo));
44 pageInfo = {};
45 }
46 return true;
47 }
LoadLayout(const std::string & filename,UxPageInfo & pageInfo) const48 bool LoadLayout(const std::string &filename, UxPageInfo &pageInfo) const
49 {
50 JsonNode node {std::filesystem::path {filename}};
51
52 // parse color, id, subpages
53 if (!Visit<SETVAL>(node, pageInfo)) {
54 LOG(ERROR) << "get page info (id, color, subpages) failed";
55 return false;
56 }
57
58 // parse view info
59 if (!ParseViewInfo(node, pageInfo.viewInfos)) {
60 LOG(ERROR) << "component Node parse failed";
61 return false;
62 }
63
64 return true;
65 }
66 private:
ParseViewInfo(const JsonNode & root,std::vector<UxViewInfo> & vec) const67 bool ParseViewInfo(const JsonNode &root, std::vector<UxViewInfo> &vec) const
68 {
69 UxViewInfo info {};
70 std::vector<UxViewInfo>().swap(vec);
71 const JsonNode &defaultNode = root[DEFAULT_MODULE];
72 const JsonNode &componentNodes = root[COMPONENT_MODULE];
73 if (componentNodes.Type() != NodeType::ARRAY) {
74 LOG(ERROR) << "Please check whether json file has a coms field";
75 return false;
76 }
77 for (const auto &componentNode : componentNodes) {
78 const JsonNode &comNode = componentNode.get();
79 auto viewType = comNode[COMMON_TYPE].As<std::string>();
80 if (viewType == std::nullopt) {
81 LOG(ERROR) << "Component don't have a type field";
82 return false;
83 }
84 const JsonNode &commonDefault = defaultNode[COMMON_LABEL];
85 if (!Visit<SETVAL>(componentNode, commonDefault, info.commonInfo)) {
86 LOG(ERROR) << "set common info failed";
87 return false;
88 }
89
90 auto it = GetSpecificInfoMap<COMPONENT_TYPE_LIST>().find(*viewType);
91 if (it == GetSpecificInfoMap<COMPONENT_TYPE_LIST>().end()) {
92 LOG(ERROR) << "Can't recognize this type " << *viewType;
93 return false;
94 }
95 info.specificInfo = it->second();
96 auto visitor = [&comNode, &defaultNode] (auto &args) {
97 const JsonNode &defaultComNode = defaultNode[Traits<std::decay_t<decltype(args)>>::STRUCT_KEY];
98 return Visit<SETVAL>(comNode, defaultComNode, args);
99 };
100 if (!std::visit(visitor, info.specificInfo)) {
101 return false;
102 }
103 vec.push_back(std::move(info));
104 info = {};
105 }
106 return true;
107 }
108 };
109
110 LayoutParser::~LayoutParser() = default;
111
LayoutParser()112 LayoutParser::LayoutParser() : pImpl_(std::make_unique<Impl>()) { }
113
GetInstance()114 LayoutParser &LayoutParser::GetInstance()
115 {
116 static LayoutParser layoutParser;
117 return layoutParser;
118 }
119
LoadLayout(const std::string & layoutFile,UxPageInfo & pageInfo) const120 bool LayoutParser::LoadLayout(const std::string &layoutFile, UxPageInfo &pageInfo) const
121 {
122 return pImpl_->LoadLayout(layoutFile, pageInfo);
123 }
124
LoadLayout(const std::vector<std::string> & layoutFiles,std::vector<UxPageInfo> & vec) const125 bool LayoutParser::LoadLayout(const std::vector<std::string> &layoutFiles, std::vector<UxPageInfo> &vec) const
126 {
127 return pImpl_->LoadLayout(layoutFiles, vec);
128 }
129 } // namespace Updater
130