/* * Copyright (c) 2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "layout_parser.h" #include "component/component_factory.h" #include "components/ui_view.h" #include "json_visitor.h" #include "log/log.h" #include "view_api.h" #include "auto_layout.h" namespace Updater { namespace { constexpr auto DEFAULT_MODULE = "default"; constexpr auto COMPONENT_MODULE = "coms"; constexpr auto COMMON_LABEL = "Common"; constexpr auto COMMON_TYPE = "type"; } class LayoutParser::Impl { using cJSONPtr = std::unique_ptr; AutoLayout &layout = AutoLayout::GetInstance(); public: bool LoadLayout(const std::vector &layoutFiles, std::vector &vec) const { layout.Init(); std::vector().swap(vec); UxPageInfo pageInfo = {}; for (const auto &file : layoutFiles) { if (!LoadLayout(file, pageInfo)) { LOG(ERROR) << file << " load failed"; return false; } vec.push_back(std::move(pageInfo)); pageInfo = {}; } return true; } bool LoadLayout(const std::string &filename, UxPageInfo &pageInfo) const { JsonNode node {std::filesystem::path {filename}}; layout.SetJsonLocation(node); // parse color, id, subpages if (!Visit(node, pageInfo)) { LOG(ERROR) << "get page info (id, color, subpages) failed"; return false; } // parse view info if (!ParseViewInfo(node, pageInfo.viewInfos)) { LOG(ERROR) << "component Node parse failed"; return false; } return true; } private: bool ParseViewInfo(const JsonNode &root, std::vector &vec) const { UxViewInfo info {}; std::vector().swap(vec); const JsonNode &defaultNode = root[DEFAULT_MODULE]; const JsonNode &componentNodes = root[COMPONENT_MODULE]; if (componentNodes.Type() != NodeType::ARRAY) { LOG(ERROR) << "Please check whether json file has a coms field"; return false; } for (const auto &componentNode : componentNodes) { const JsonNode &comNode = componentNode.get(); auto viewType = comNode[COMMON_TYPE].As(); if (viewType == std::nullopt) { LOG(ERROR) << "Component don't have a type field"; return false; } const JsonNode &commonDefault = defaultNode[COMMON_LABEL]; if (!Visit(componentNode, commonDefault, info.commonInfo)) { LOG(ERROR) << "set common info failed"; return false; } auto it = GetSpecificInfoMap().find(*viewType); if (it == GetSpecificInfoMap().end()) { LOG(ERROR) << "Can't recognize this type " << *viewType; return false; } info.specificInfo = it->second(); auto visitor = [&comNode, &defaultNode] (auto &args) { const JsonNode &defaultComNode = defaultNode[Traits>::STRUCT_KEY]; return Visit(comNode, defaultComNode, args); }; if (!std::visit(visitor, info.specificInfo)) { return false; } vec.push_back(std::move(info)); info = {}; } return true; } }; LayoutParser::~LayoutParser() = default; LayoutParser::LayoutParser() : pImpl_(std::make_unique()) { } LayoutParser &LayoutParser::GetInstance() { static LayoutParser layoutParser; return layoutParser; } bool LayoutParser::LoadLayout(const std::string &layoutFile, UxPageInfo &pageInfo) const { return pImpl_->LoadLayout(layoutFile, pageInfo); } bool LayoutParser::LoadLayout(const std::vector &layoutFiles, std::vector &vec) const { return pImpl_->LoadLayout(layoutFiles, vec); } } // namespace Updater