1 /*
2 * Copyright (c) 2024 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 <mutex>
17 #include <shared_mutex>
18
19 #include <meta/api/event_handler.h>
20 #include <meta/api/property/property_event_handler.h>
21 #include <meta/api/threading/mutex.h>
22 #include <meta/base/interface_macros.h>
23 #include <meta/base/namespace.h>
24 #include <meta/ext/implementation_macros.h>
25 #include <meta/interface/intf_content.h>
26 #include <meta/interface/intf_iterable.h>
27 #include <meta/interface/intf_required_interfaces.h>
28 #include <meta/interface/loaders/intf_dynamic_content_loader.h>
29
30 #include "object.h"
31
32 META_BEGIN_INTERNAL_NAMESPACE()
33
34 class ContentObject : public IntroduceInterfaces<MetaObject, IContent, IRequiredInterfaces, IIterable> {
35 META_OBJECT(ContentObject, ClassId::ContentObject, IntroduceInterfaces)
36 public:
37 META_BEGIN_STATIC_DATA()
META_STATIC_PROPERTY_DATA(IContent,IObject::Ptr,Content)38 META_STATIC_PROPERTY_DATA(IContent, IObject::Ptr, Content)
39 META_STATIC_PROPERTY_DATA(IContent, bool, ContentSearchable, true)
40 META_END_STATIC_DATA()
41 META_IMPLEMENT_READONLY_PROPERTY(IObject::Ptr, Content)
42 META_IMPLEMENT_PROPERTY(bool, ContentSearchable)
43
44 bool SetContent(const IObject::Ptr& content) override
45 {
46 bool valid = CheckContentRequirements(content);
47 SetValue(META_ACCESS_PROPERTY(Content), valid ? content : nullptr);
48 if (!valid) {
49 CORE_LOG_W("Content does not fulfil interface requirements");
50 }
51 return valid;
52 }
53
Build(const IMetadata::Ptr & data)54 bool Build(const IMetadata::Ptr& data) override
55 {
56 bool ret = Super::Build(data);
57 if (ret) {
58 OnSerializeChanged();
59 }
60 return ret;
61 }
62
Destroy()63 void Destroy() override
64 {
65 if (auto c = META_ACCESS_PROPERTY(Content)) {
66 c->OnChanged()->Reset();
67 c->SetValue(nullptr);
68 }
69 Super::Destroy();
70 }
71
OnSerializeChanged()72 void OnSerializeChanged()
73 {
74 if (auto cont = META_ACCESS_PROPERTY(Content)) {
75 META_NS::SetObjectFlags(cont.GetProperty(), ObjectFlagBits::SERIALIZE,
76 GetObjectFlags().IsSet(ObjectFlagBits::SERIALIZE_HIERARCHY));
77 }
78 }
79
SetObjectFlags(const ObjectFlagBitsValue & flags)80 void SetObjectFlags(const ObjectFlagBitsValue& flags) override
81 {
82 Super::SetObjectFlags(flags);
83 OnSerializeChanged();
84 }
85
GetObjectDefaultFlags() const86 ObjectFlagBitsValue GetObjectDefaultFlags() const override
87 {
88 auto flags = Super::GetObjectDefaultFlags();
89 flags &= ~ObjectFlagBitsValue(ObjectFlagBits::SERIALIZE_HIERARCHY);
90 return flags;
91 }
92
SetRequiredInterfaces(const BASE_NS::vector<TypeId> & interfaces)93 bool SetRequiredInterfaces(const BASE_NS::vector<TypeId>& interfaces) override
94 {
95 {
96 std::unique_lock lock(mutex_);
97 requiredInterfaces_ = interfaces;
98 }
99 if (const auto content = META_ACCESS_PROPERTY_VALUE(Content)) {
100 if (!CheckContentRequirements(content)) {
101 SetContent(nullptr);
102 }
103 }
104 return true;
105 }
GetRequiredInterfaces() const106 BASE_NS::vector<TypeId> GetRequiredInterfaces() const override
107 {
108 std::shared_lock lock(mutex_);
109 return requiredInterfaces_;
110 }
111
CheckContentRequirements(const IObject::Ptr & object)112 bool CheckContentRequirements(const IObject::Ptr& object)
113 {
114 std::shared_lock lock(mutex_);
115 // Null object always passes content requirements
116 return !object || CheckInterfaces(object, requiredInterfaces_, true);
117 }
118
119 template<typename Func>
IterateImpl(const Func & f) const120 IterationResult IterateImpl(const Func& f) const
121 {
122 if (!f) {
123 CORE_LOG_W("Incompatible function with Iterate");
124 return IterationResult::FAILED;
125 }
126 if (META_ACCESS_PROPERTY_VALUE(ContentSearchable)) {
127 if (auto c = META_ACCESS_PROPERTY_VALUE(Content)) {
128 return f->Invoke(c);
129 }
130 }
131 return IterationResult::CONTINUE;
132 }
133
Iterate(const IterationParameters & params)134 IterationResult Iterate(const IterationParameters& params) override
135 {
136 return IterateImpl(params.function.GetInterface<IIterableCallable<IObject::Ptr>>());
137 }
138
Iterate(const IterationParameters & params) const139 IterationResult Iterate(const IterationParameters& params) const override
140 {
141 return IterateImpl(params.function.GetInterface<IIterableConstCallable<IObject::Ptr>>());
142 }
143
144 private:
145 mutable std::shared_mutex mutex_;
146 BASE_NS::vector<TypeId> requiredInterfaces_;
147 };
148
GetContentObjectFactory()149 IObjectFactory::Ptr GetContentObjectFactory()
150 {
151 return ContentObject::GetFactory();
152 }
153
154 META_END_INTERNAL_NAMESPACE()
155