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#include "auto_layout.h" 23 24namespace Updater { 25namespace { 26constexpr auto DEFAULT_MODULE = "default"; 27constexpr auto COMPONENT_MODULE = "coms"; 28constexpr auto COMMON_LABEL = "Common"; 29constexpr auto COMMON_TYPE = "type"; 30} 31 32class LayoutParser::Impl { 33 using cJSONPtr = std::unique_ptr<cJSON, decltype(&cJSON_Delete)>; 34 AutoLayout &layout = AutoLayout::GetInstance(); 35public: 36 bool LoadLayout(const std::vector<std::string> &layoutFiles, std::vector<UxPageInfo> &vec) const 37 { 38 layout.Init(); 39 std::vector<UxPageInfo>().swap(vec); 40 UxPageInfo pageInfo = {}; 41 for (const auto &file : layoutFiles) { 42 if (!LoadLayout(file, pageInfo)) { 43 LOG(ERROR) << file << " load failed"; 44 return false; 45 } 46 vec.push_back(std::move(pageInfo)); 47 pageInfo = {}; 48 } 49 return true; 50 } 51 bool LoadLayout(const std::string &filename, UxPageInfo &pageInfo) const 52 { 53 JsonNode node {std::filesystem::path {filename}}; 54 layout.SetJsonLocation(node); 55 // parse color, id, subpages 56 if (!Visit<SETVAL>(node, pageInfo)) { 57 LOG(ERROR) << "get page info (id, color, subpages) failed"; 58 return false; 59 } 60 61 // parse view info 62 if (!ParseViewInfo(node, pageInfo.viewInfos)) { 63 LOG(ERROR) << "component Node parse failed"; 64 return false; 65 } 66 67 return true; 68 } 69private: 70 bool ParseViewInfo(const JsonNode &root, std::vector<UxViewInfo> &vec) const 71 { 72 UxViewInfo info {}; 73 std::vector<UxViewInfo>().swap(vec); 74 const JsonNode &defaultNode = root[DEFAULT_MODULE]; 75 const JsonNode &componentNodes = root[COMPONENT_MODULE]; 76 if (componentNodes.Type() != NodeType::ARRAY) { 77 LOG(ERROR) << "Please check whether json file has a coms field"; 78 return false; 79 } 80 for (const auto &componentNode : componentNodes) { 81 const JsonNode &comNode = componentNode.get(); 82 auto viewType = comNode[COMMON_TYPE].As<std::string>(); 83 if (viewType == std::nullopt) { 84 LOG(ERROR) << "Component don't have a type field"; 85 return false; 86 } 87 const JsonNode &commonDefault = defaultNode[COMMON_LABEL]; 88 if (!Visit<SETVAL>(componentNode, commonDefault, info.commonInfo)) { 89 LOG(ERROR) << "set common info failed"; 90 return false; 91 } 92 93 auto it = GetSpecificInfoMap<COMPONENT_TYPE_LIST>().find(*viewType); 94 if (it == GetSpecificInfoMap<COMPONENT_TYPE_LIST>().end()) { 95 LOG(ERROR) << "Can't recognize this type " << *viewType; 96 return false; 97 } 98 info.specificInfo = it->second(); 99 auto visitor = [&comNode, &defaultNode] (auto &args) { 100 const JsonNode &defaultComNode = defaultNode[Traits<std::decay_t<decltype(args)>>::STRUCT_KEY]; 101 return Visit<SETVAL>(comNode, defaultComNode, args); 102 }; 103 if (!std::visit(visitor, info.specificInfo)) { 104 return false; 105 } 106 vec.push_back(std::move(info)); 107 info = {}; 108 } 109 return true; 110 } 111}; 112 113LayoutParser::~LayoutParser() = default; 114 115LayoutParser::LayoutParser() : pImpl_(std::make_unique<Impl>()) { } 116 117LayoutParser &LayoutParser::GetInstance() 118{ 119 static LayoutParser layoutParser; 120 return layoutParser; 121} 122 123bool LayoutParser::LoadLayout(const std::string &layoutFile, UxPageInfo &pageInfo) const 124{ 125 return pImpl_->LoadLayout(layoutFile, pageInfo); 126} 127 128bool LayoutParser::LoadLayout(const std::vector<std::string> &layoutFiles, std::vector<UxPageInfo> &vec) const 129{ 130 return pImpl_->LoadLayout(layoutFiles, vec); 131} 132} // namespace Updater 133