• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 #ifndef UPDATER_UI_COMPONENT_FACTORY_H
17 #define UPDATER_UI_COMPONENT_FACTORY_H
18 
19 #include <functional>
20 #include <memory>
21 #include <mutex>
22 #include <string>
23 #include <tuple>
24 #include <unordered_map>
25 #include <variant>
26 
27 #include "component_common.h"
28 #include "log/log.h"
29 
30 namespace Updater {
31 
32 // Generic factory for create UxView and UxInfo
33 class ComponentFactory final {
34     using TViewPtr = std::unique_ptr<ComponentInterface>;
35     using TViewCreator = std::function<TViewPtr(const UxViewInfo &)>;
36     using TSpecificInfoCreator = std::function<std::unique_ptr<UxViewSpecificInfo>()>;
37 
38     ComponentFactory() = default;
39     DISALLOW_COPY_MOVE(ComponentFactory);
40 
41     struct RegistryInfo {
42         std::string componentType;
43         TViewCreator createView;
44         TSpecificInfoCreator createInfo;
45 
RegistryInfoRegistryInfo46         RegistryInfo(
47             const std::string &componentTypeName, TViewCreator &&createViewFunc, TSpecificInfoCreator &&createInfoFunc)
48             : componentType(componentTypeName), createView(createViewFunc), createInfo(createInfoFunc)
49         {}
50     };
51 
52 public:
53     template <typename TComponent>
Register(const std::string & componentType)54     static bool Register(const std::string &componentType)
55     {
56         auto &factory = Instance();
57         factory.RegisterImpl<TComponent>(componentType);
58         return true;
59     }
60 
CreateView(const std::string & componentType,const UxViewInfo & info)61     static std::unique_ptr<ComponentInterface> CreateView(const std::string &componentType, const UxViewInfo &info)
62     {
63         auto &factory = Instance();
64         std::lock_guard<std::mutex> lock(factory.mutex_);
65 
66         auto itr = factory.registry_.find(componentType);
67         if (itr == factory.registry_.end()) {
68             LOG(ERROR) << "CreateView failed, componentType: " << componentType;
69             return nullptr;
70         }
71         if (itr->second == nullptr) {
72             LOG(ERROR) << "CreateView failed, no factory, componentType:" << componentType;
73             return nullptr;
74         }
75 
76         return itr->second->createView(info);
77     }
78 
CreateSpecificInfo(const std::string & componentType)79     static std::unique_ptr<UxViewSpecificInfo> CreateSpecificInfo(const std::string &componentType)
80     {
81         auto &factory = Instance();
82         std::lock_guard<std::mutex> lock(factory.mutex_);
83 
84         auto itr = factory.registry_.find(componentType);
85         if (itr == factory.registry_.end()) {
86             LOG(ERROR) << "CreateSpecificInfo failed, componentType: " << componentType;
87             return nullptr;
88         }
89         if (itr->second == nullptr) {
90             LOG(ERROR) << "CreateSpecificInfo failed, no factory, componentType: " << componentType;
91             return nullptr;
92         }
93 
94         return itr->second->createInfo();
95     }
96 
97 private:
Instance()98     static ComponentFactory &Instance()
99     {
100         static ComponentFactory factory;
101         return factory;
102     }
103 
104     template <typename TComponent>
RegisterImpl(const std::string & componentType)105     void RegisterImpl(const std::string &componentType)
106     {
107         std::lock_guard<std::mutex> lock(mutex_);
108         if (registry_.count(componentType) > 0) {
109             LOG(WARNING) << "component register again: " << componentType;
110             return;
111         }
112 
113         auto item = std::make_unique<RegistryInfo>(
114             componentType,
115             // Create concrete UxView component
116             [](const UxViewInfo &info) { return std::make_unique<TComponent>(info); },
117             // Create concrete UxView's info
118             []() { return std::make_unique<SpecificInfoWrapper<TComponent>>(); });
119 
120         registry_.emplace(componentType, std::move(item));
121         LOG(INFO) << "component register: " << componentType;
122     }
123 
124 private:
125     std::mutex mutex_;
126     std::unordered_map<std::string, std::unique_ptr<RegistryInfo>> registry_;
127 };
128 
129 // crtp util to ensure type conversion safety and make component code less repetitive
130 template <typename TComponent, typename TSpecificInfo>
131 class ComponentCommon : public ComponentInterface {
132 public:
133     using SpecificInfoType = TSpecificInfo;
134 
RegisterHook()135     static bool RegisterHook()
136     {
137         return ComponentFactory::Register<TComponent>(TComponent::COMPONENT_TYPE);
138     }
139 
140     ~ComponentCommon() override = default;
GetComponentType()141     const char *GetComponentType() override
142     {
143         static_assert(TComponent::COMPONENT_TYPE != nullptr, "you must not assign a nullptr to COMPONNET_TYPE");
144         return TComponent::COMPONENT_TYPE;
145     }
GetOhosView()146     OHOS::UIView *GetOhosView() override
147     {
148         return static_cast<TComponent *>(this);
149     }
SetViewCommonInfo(const UxViewCommonInfo & common)150     void SetViewCommonInfo(const UxViewCommonInfo &common) override
151     {
152         viewId_ = common.id;
153         auto child = static_cast<TComponent *>(this);
154         child->SetPosition(common.x, common.y, common.w, common.h);
155         child->SetVisible(common.visible);
156         child->SetViewId(viewId_.c_str());
157     }
158 
159 protected:
AsSpecific(const std::unique_ptr<UxViewSpecificInfo> & specificPtr)160     const TSpecificInfo &AsSpecific(const std::unique_ptr<UxViewSpecificInfo> &specificPtr)
161     {
162         const static SpecificInfoWrapper<TComponent> empty {};
163 
164         if (specificPtr == nullptr) {
165             LOG(ERROR) << TComponent::COMPONENT_TYPE << " specific convert failed, src is nullptr";
166             return empty.data;
167         }
168         if (empty.GetType() != specificPtr->GetType()) {
169             LOG(ERROR) << TComponent::COMPONENT_TYPE << " specific convert failed, src COMPONENT_TYPE is "
170                        << specificPtr->GetType();
171             return empty.data;
172         }
173         if (empty.GetStructKey() != specificPtr->GetStructKey()) {
174             LOG(ERROR) << TComponent::COMPONENT_TYPE << " specific convert failed, src STRUCT_KEY is "
175                        << specificPtr->GetStructKey();
176             return empty.data;
177         }
178 
179         return static_cast<SpecificInfoWrapper<TComponent> *>(specificPtr.get())->data;
180     }
181 
182 protected:
183     std::string viewId_{};
184 
185 private:
186     friend TComponent;
187     ComponentCommon() = default;
188 };
189 
190 }  // namespace Updater
191 #endif
192