18bf80f4bSopenharmony_ci/* 28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License. 58bf80f4bSopenharmony_ci * You may obtain a copy of the License at 68bf80f4bSopenharmony_ci * 78bf80f4bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 88bf80f4bSopenharmony_ci * 98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and 138bf80f4bSopenharmony_ci * limitations under the License. 148bf80f4bSopenharmony_ci */ 158bf80f4bSopenharmony_ci 168bf80f4bSopenharmony_ci#include <shared_mutex> 178bf80f4bSopenharmony_ci 188bf80f4bSopenharmony_ci#include <meta/api/event_handler.h> 198bf80f4bSopenharmony_ci#include <meta/api/property/property_event_handler.h> 208bf80f4bSopenharmony_ci#include <meta/api/threading/mutex.h> 218bf80f4bSopenharmony_ci#include <meta/ext/implementation_macros.h> 228bf80f4bSopenharmony_ci#include <meta/interface/intf_content.h> 238bf80f4bSopenharmony_ci#include <meta/interface/intf_iterable.h> 248bf80f4bSopenharmony_ci#include <meta/interface/intf_required_interfaces.h> 258bf80f4bSopenharmony_ci#include <meta/interface/loaders/intf_dynamic_content_loader.h> 268bf80f4bSopenharmony_ci 278bf80f4bSopenharmony_ci#include "object.h" 288bf80f4bSopenharmony_ci 298bf80f4bSopenharmony_ciMETA_BEGIN_NAMESPACE() 308bf80f4bSopenharmony_ci 318bf80f4bSopenharmony_ciclass ContentObject 328bf80f4bSopenharmony_ci : public Internal::ObjectFwd<ContentObject, ClassId::ContentObject, IContent, IRequiredInterfaces, IIterable> { 338bf80f4bSopenharmony_ci using Super = Internal::ObjectFwd<ContentObject, ClassId::ContentObject, IContent, IRequiredInterfaces, IIterable>; 348bf80f4bSopenharmony_ci 358bf80f4bSopenharmony_cipublic: 368bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_READONLY_PROPERTY(IContent, IObject::Ptr, Content) 378bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_PROPERTY(IContent, bool, ContentSearchable, true) 388bf80f4bSopenharmony_ci META_IMPLEMENT_INTERFACE_PROPERTY(IContent, IContentLoader::Ptr, ContentLoader) 398bf80f4bSopenharmony_ci 408bf80f4bSopenharmony_ci bool SetContent(const IObject::Ptr& content) override 418bf80f4bSopenharmony_ci { 428bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(ContentLoader)->SetValue(nullptr); 438bf80f4bSopenharmony_ci return SetContentInternal(content); 448bf80f4bSopenharmony_ci } 458bf80f4bSopenharmony_ci 468bf80f4bSopenharmony_ci bool Build(const IMetadata::Ptr& data) override 478bf80f4bSopenharmony_ci { 488bf80f4bSopenharmony_ci bool ret = Super::Build(data); 498bf80f4bSopenharmony_ci if (ret) { 508bf80f4bSopenharmony_ci loaderChanged_.Subscribe(META_ACCESS_PROPERTY(ContentLoader), [this] { OnLoaderChanged(); }); 518bf80f4bSopenharmony_ci OnSerializeChanged(); 528bf80f4bSopenharmony_ci } 538bf80f4bSopenharmony_ci return ret; 548bf80f4bSopenharmony_ci } 558bf80f4bSopenharmony_ci 568bf80f4bSopenharmony_ci void Destroy() override 578bf80f4bSopenharmony_ci { 588bf80f4bSopenharmony_ci if (auto c = META_ACCESS_PROPERTY(Content)) { 598bf80f4bSopenharmony_ci c->OnChanged()->Reset(); 608bf80f4bSopenharmony_ci c->SetValue(nullptr); 618bf80f4bSopenharmony_ci } 628bf80f4bSopenharmony_ci Super::Destroy(); 638bf80f4bSopenharmony_ci } 648bf80f4bSopenharmony_ci 658bf80f4bSopenharmony_ci void OnSerializeChanged() 668bf80f4bSopenharmony_ci { 678bf80f4bSopenharmony_ci if (auto cont = META_ACCESS_PROPERTY(Content)) { 688bf80f4bSopenharmony_ci META_NS::SetObjectFlags(cont.GetProperty(), ObjectFlagBits::SERIALIZE, 698bf80f4bSopenharmony_ci GetObjectFlags().IsSet(ObjectFlagBits::SERIALIZE_HIERARCHY)); 708bf80f4bSopenharmony_ci } 718bf80f4bSopenharmony_ci } 728bf80f4bSopenharmony_ci 738bf80f4bSopenharmony_ci void OnLoaderChanged() 748bf80f4bSopenharmony_ci { 758bf80f4bSopenharmony_ci contentChanged_.Unsubscribe(); 768bf80f4bSopenharmony_ci if (auto dynamic = interface_pointer_cast<IDynamicContentLoader>(META_ACCESS_PROPERTY_VALUE(ContentLoader))) { 778bf80f4bSopenharmony_ci // If our loader is dynamic (i.e. the content can change), subscribe to change events 788bf80f4bSopenharmony_ci contentChanged_.Subscribe<IOnChanged>(dynamic->ContentChanged(), [&] { OnContentChanged(); }); 798bf80f4bSopenharmony_ci } 808bf80f4bSopenharmony_ci OnContentChanged(); 818bf80f4bSopenharmony_ci } 828bf80f4bSopenharmony_ci 838bf80f4bSopenharmony_ci void OnContentChanged() 848bf80f4bSopenharmony_ci { 858bf80f4bSopenharmony_ci const auto loader = META_ACCESS_PROPERTY_VALUE(ContentLoader); 868bf80f4bSopenharmony_ci SetContentInternal(loader ? loader->Create({}) : nullptr); 878bf80f4bSopenharmony_ci } 888bf80f4bSopenharmony_ci 898bf80f4bSopenharmony_ci void SetObjectFlags(const ObjectFlagBitsValue& flags) override 908bf80f4bSopenharmony_ci { 918bf80f4bSopenharmony_ci Super::SetObjectFlags(flags); 928bf80f4bSopenharmony_ci OnSerializeChanged(); 938bf80f4bSopenharmony_ci } 948bf80f4bSopenharmony_ci 958bf80f4bSopenharmony_ci ObjectFlagBitsValue GetObjectDefaultFlags() const override 968bf80f4bSopenharmony_ci { 978bf80f4bSopenharmony_ci auto flags = Super::GetObjectDefaultFlags(); 988bf80f4bSopenharmony_ci flags &= ~ObjectFlagBitsValue(ObjectFlagBits::SERIALIZE_HIERARCHY); 998bf80f4bSopenharmony_ci return flags; 1008bf80f4bSopenharmony_ci } 1018bf80f4bSopenharmony_ci 1028bf80f4bSopenharmony_ci bool SetRequiredInterfaces(const BASE_NS::vector<TypeId>& interfaces) override 1038bf80f4bSopenharmony_ci { 1048bf80f4bSopenharmony_ci { 1058bf80f4bSopenharmony_ci std::unique_lock lock(mutex_); 1068bf80f4bSopenharmony_ci requiredInterfaces_ = interfaces; 1078bf80f4bSopenharmony_ci } 1088bf80f4bSopenharmony_ci bool valid = false; 1098bf80f4bSopenharmony_ci if (const auto content = META_ACCESS_PROPERTY_VALUE(Content)) { 1108bf80f4bSopenharmony_ci valid = CheckContentRequirements(content); 1118bf80f4bSopenharmony_ci } 1128bf80f4bSopenharmony_ci if (!valid) { 1138bf80f4bSopenharmony_ci // We don't have valid content, check if we could create one with our loader 1148bf80f4bSopenharmony_ci OnContentChanged(); 1158bf80f4bSopenharmony_ci } 1168bf80f4bSopenharmony_ci return true; 1178bf80f4bSopenharmony_ci } 1188bf80f4bSopenharmony_ci BASE_NS::vector<TypeId> GetRequiredInterfaces() const override 1198bf80f4bSopenharmony_ci { 1208bf80f4bSopenharmony_ci std::shared_lock lock(mutex_); 1218bf80f4bSopenharmony_ci return requiredInterfaces_; 1228bf80f4bSopenharmony_ci } 1238bf80f4bSopenharmony_ci 1248bf80f4bSopenharmony_ci bool SetContentInternal(const IObject::Ptr& content) 1258bf80f4bSopenharmony_ci { 1268bf80f4bSopenharmony_ci bool valid = CheckContentRequirements(content); 1278bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(Content)->SetValue(valid ? content : nullptr); 1288bf80f4bSopenharmony_ci if (!valid) { 1298bf80f4bSopenharmony_ci CORE_LOG_W("Content does not fulfil interface requirements"); 1308bf80f4bSopenharmony_ci } 1318bf80f4bSopenharmony_ci return valid; 1328bf80f4bSopenharmony_ci } 1338bf80f4bSopenharmony_ci 1348bf80f4bSopenharmony_ci bool CheckContentRequirements(const IObject::Ptr& object) 1358bf80f4bSopenharmony_ci { 1368bf80f4bSopenharmony_ci std::shared_lock lock(mutex_); 1378bf80f4bSopenharmony_ci // Null object always passes content requirements 1388bf80f4bSopenharmony_ci return !object || CheckInterfaces(object, requiredInterfaces_, true); 1398bf80f4bSopenharmony_ci } 1408bf80f4bSopenharmony_ci 1418bf80f4bSopenharmony_ci template<typename Func> 1428bf80f4bSopenharmony_ci IterationResult IterateImpl(const Func& f) const 1438bf80f4bSopenharmony_ci { 1448bf80f4bSopenharmony_ci if (!f) { 1458bf80f4bSopenharmony_ci CORE_LOG_W("Incompatible function with Iterate"); 1468bf80f4bSopenharmony_ci return IterationResult::FAILED; 1478bf80f4bSopenharmony_ci } 1488bf80f4bSopenharmony_ci if (META_ACCESS_PROPERTY_VALUE(ContentSearchable)) { 1498bf80f4bSopenharmony_ci if (auto c = META_ACCESS_PROPERTY_VALUE(Content)) { 1508bf80f4bSopenharmony_ci return f->Invoke(c); 1518bf80f4bSopenharmony_ci } 1528bf80f4bSopenharmony_ci } 1538bf80f4bSopenharmony_ci return IterationResult::CONTINUE; 1548bf80f4bSopenharmony_ci } 1558bf80f4bSopenharmony_ci 1568bf80f4bSopenharmony_ci IterationResult Iterate(const IterationParameters& params) override 1578bf80f4bSopenharmony_ci { 1588bf80f4bSopenharmony_ci return IterateImpl(params.function.GetInterface<IIterableCallable<IObject::Ptr>>()); 1598bf80f4bSopenharmony_ci } 1608bf80f4bSopenharmony_ci 1618bf80f4bSopenharmony_ci IterationResult Iterate(const IterationParameters& params) const override 1628bf80f4bSopenharmony_ci { 1638bf80f4bSopenharmony_ci return IterateImpl(params.function.GetInterface<IIterableConstCallable<IObject::Ptr>>()); 1648bf80f4bSopenharmony_ci } 1658bf80f4bSopenharmony_ci 1668bf80f4bSopenharmony_ciprivate: 1678bf80f4bSopenharmony_ci PropertyChangedEventHandler loaderChanged_; 1688bf80f4bSopenharmony_ci EventHandler contentChanged_; 1698bf80f4bSopenharmony_ci BASE_NS::vector<TypeId> requiredInterfaces_; 1708bf80f4bSopenharmony_ci mutable std::shared_mutex mutex_; 1718bf80f4bSopenharmony_ci}; 1728bf80f4bSopenharmony_ci 1738bf80f4bSopenharmony_cinamespace Internal { 1748bf80f4bSopenharmony_ci 1758bf80f4bSopenharmony_ciIObjectFactory::Ptr GetContentObjectFactory() 1768bf80f4bSopenharmony_ci{ 1778bf80f4bSopenharmony_ci return ContentObject::GetFactory(); 1788bf80f4bSopenharmony_ci} 1798bf80f4bSopenharmony_ci 1808bf80f4bSopenharmony_ci} // namespace Internal 1818bf80f4bSopenharmony_ci 1828bf80f4bSopenharmony_ciMETA_END_NAMESPACE() 183