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