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 #ifndef META_EXT_OBJECT_H
17 #define META_EXT_OBJECT_H
18 
19 #include <base/util/uid_util.h>
20 
21 #include <meta/base/interface_macros.h>
22 #include <meta/base/namespace.h>
23 #include <meta/base/types.h>
24 #include <meta/ext/implementation_macros.h>
25 #include <meta/ext/metadata_helpers.h>
26 #include <meta/ext/object_factory.h>
27 #include <meta/interface/interface_helpers.h>
28 #include <meta/interface/intf_attachment.h>
29 #include <meta/interface/intf_container_query.h>
30 #include <meta/interface/intf_derived.h>
31 #include <meta/interface/intf_lifecycle.h>
32 #include <meta/interface/intf_metadata.h>
33 #include <meta/interface/intf_object.h>
34 #include <meta/interface/intf_object_context.h>
35 #include <meta/interface/intf_object_flags.h>
36 #include <meta/interface/intf_object_registry.h>
37 #include <meta/interface/property/intf_property.h>
38 #include <meta/interface/static_object_metadata.h>
39 
40 #include "object_factory.h"
41 
META_BEGIN_NAMESPACE()42 META_BEGIN_NAMESPACE()
43 namespace Internal {
44 // dummy pure virtual to shutup compiler warnings
45 class DummyGetObjectRegistry {
46     virtual META_NS::IObjectRegistry& GetObjectRegistry() = 0;
47 };
48 } // namespace Internal
49 
50 /**
51  * @brief A helper template class for implementing a class which implements a basic set of object interfaces.
52  * @note Usually when inheriting from this template directly SuperClassInfo should be META_NS::ClassId::BaseObject.
53  */
54 template<class FinalClass, const META_NS::ClassInfo& ClassInfo, const META_NS::ClassInfo& SuperClassInfo,
55     class... Interfaces>
56 class BaseObjectFwd : public IntroduceInterfaces<IObjectInstance, IObjectFlags, IDerived, ILifecycle, Interfaces...>,
57                       private Internal::DummyGetObjectRegistry {
58     using Fwd = BaseObjectFwd;
59     using Super = IntroduceInterfaces<IObjectInstance, IObjectFlags, IDerived, ILifecycle, Interfaces...>;
60 
61 public:
62     // using declaration doesn't work with vc, still thinks the function access is protected
GetInterface(const BASE_NS::Uid & uid)63     CORE_NS::IInterface* GetInterface(const BASE_NS::Uid& uid) override
64     {
65         return Super::GetInterface(uid);
66     }
GetInterface(const BASE_NS::Uid & uid)67     const CORE_NS::IInterface* GetInterface(const BASE_NS::Uid& uid) const override
68     {
69         return Super::GetInterface(uid);
70     }
71     template<typename Type>
GetInterface()72     constexpr Type* GetInterface() noexcept
73     {
74         return static_cast<Type*>(Super::StaticGetInterface(Type::UID));
75     }
76     template<typename Type>
GetInterface()77     constexpr const Type* GetInterface() const noexcept
78     {
79         auto* me = const_cast<BaseObjectFwd*>(this);
80         return static_cast<const Type*>(me->StaticGetInterface(Type::UID));
81     }
82 
83 public:
META_DEFINE_OBJECT_TYPE_INFO(FinalClass,ClassInfo)84     META_DEFINE_OBJECT_TYPE_INFO(FinalClass, ClassInfo)
85 
86 public:
87     META_NS::IObjectRegistry& GetObjectRegistry() override
88     {
89         return META_NS::GetObjectRegistry();
90     }
91 
GetStaticObjectMetadata()92     static const StaticObjectMetadata& GetStaticObjectMetadata()
93     {
94         return StaticObjectMeta();
95     }
96 
97 public: // IObject
GetClassName()98     BASE_NS::string_view GetClassName() const override
99     {
100         return ClassInfo.Name();
101     }
GetInstanceId()102     InstanceId GetInstanceId() const override
103     {
104         return object_->GetInstanceId();
105     }
GetClassId()106     ObjectId GetClassId() const override
107     {
108         return ClassInfo.Id();
109     }
GetName()110     BASE_NS::string GetName() const override
111     {
112         return object_->GetName();
113     }
Resolve(const RefUri & uri)114     IObject::Ptr Resolve(const RefUri& uri) const override
115     {
116         return object_->Resolve(uri);
117     }
118     template<typename Interface>
Resolve(const RefUri & uri)119     typename Interface::Ptr Resolve(const RefUri& uri) const
120     {
121         return interface_pointer_cast<Interface>(object_->Resolve(uri));
122     }
GetSelf()123     IObject::Ptr GetSelf() const override
124     {
125         return object_ ? object_->GetSelf() : nullptr;
126     }
127     template<typename Interface>
GetSelf()128     typename Interface::Ptr GetSelf() const
129     {
130         return interface_pointer_cast<Interface>(GetSelf());
131     }
GetInterfaces()132     BASE_NS::vector<BASE_NS::Uid> GetInterfaces() const override
133     {
134         return GetStaticInterfaces();
135     }
136 
GetStaticInterfaces()137     static BASE_NS::vector<BASE_NS::Uid> GetStaticInterfaces()
138     {
139         return Super::GetInterfacesVector();
140     }
141 
142 public: // IObjectFlags
GetObjectFlags()143     ObjectFlagBitsValue GetObjectFlags() const override
144     {
145         if (auto flags = interface_cast<IObjectFlags>(object_)) {
146             return flags->GetObjectFlags();
147         }
148         return {};
149     }
SetObjectFlags(const ObjectFlagBitsValue & value)150     void SetObjectFlags(const ObjectFlagBitsValue& value) override
151     {
152         if (auto flags = interface_cast<IObjectFlags>(object_)) {
153             flags->SetObjectFlags(value);
154         }
155     }
GetObjectDefaultFlags()156     ObjectFlagBitsValue GetObjectDefaultFlags() const override
157     {
158         if (auto flags = interface_cast<IObjectFlags>(object_)) {
159             return flags->GetObjectDefaultFlags();
160         }
161         return {};
162     }
163 
164 protected: // ILifecycle
Build(const IMetadata::Ptr & data)165     bool Build(const IMetadata::Ptr& data) override
166     {
167 #ifdef _DEBUG
168         // Object registry calls this
169         if (buildCalled_) {
170             CORE_LOG_E("Do not call Build explicitly from derived class!");
171         }
172         buildCalled_ = true;
173 #endif
174         return true;
175     }
176 
SetInstanceId(InstanceId uid)177     void SetInstanceId(InstanceId uid) override
178     {
179         // Object registry does this
180     }
Destroy()181     void Destroy() override
182     {
183         if (auto builder = interface_cast<META_NS::ILifecycle>(object_)) {
184             builder->Destroy();
185         }
186     }
187 
188 protected: // IDerived
SetSuperInstance(const META_NS::IObject::Ptr &,const META_NS::IObject::Ptr & super)189     void SetSuperInstance(const META_NS::IObject::Ptr& /*aggr*/, const META_NS::IObject::Ptr& super) override
190     {
191 #ifdef _DEBUG
192         // Object registry calls this
193         if (object_) {
194             CORE_LOG_E("Do not call SetSuperInstance explicitly from derived class!");
195         }
196 #endif
197         if (IsFirstInit()) {
198             if (auto i = interface_cast<IMetadataInternal>(super)) {
199                 StaticObjectMeta().baseclass = &i->GetStaticMetadata();
200             }
201         }
202 
203         object_ = interface_pointer_cast<IObjectInstance>(super); // Save the strong reference to super.
204     }
GetSuperClassUid()205     BASE_NS::Uid GetSuperClassUid() const override
206     {
207         return SuperClassInfo.Id().ToUid();
208     }
209 
210 protected:
IsFirstInit()211     bool IsFirstInit()
212     {
213         static bool init = (isFirstInit_ = true);
214         return isFirstInit_;
215     }
216 
217     template<typename Type>
RegisterStaticPropertyMetadata(const META_NS::InterfaceInfo & intf,BASE_NS::string_view name,ObjectFlagBitsValue flags,Internal::PCtor * ctor,Internal::PMemberInit * init)218     nullptr_t RegisterStaticPropertyMetadata(const META_NS::InterfaceInfo& intf, BASE_NS::string_view name,
219         ObjectFlagBitsValue flags, Internal::PCtor* ctor, Internal::PMemberInit* init)
220     {
221         if (IsFirstInit()) {
222             StaticObjectMeta().properties.push_back(
223                 PropertyMetadata { name, intf, flags, UidFromType<Type>(), ctor, init });
224         }
225         return nullptr;
226     }
227 
228     template<typename Type>
RegisterStaticEventMetadata(const META_NS::InterfaceInfo & intf,BASE_NS::string_view name,Internal::ECtor * ctor,Internal::EMemberInit * init)229     nullptr_t RegisterStaticEventMetadata(const META_NS::InterfaceInfo& intf, BASE_NS::string_view name,
230         Internal::ECtor* ctor, Internal::EMemberInit* init)
231     {
232         if (IsFirstInit()) {
233             StaticObjectMeta().events.push_back(EventMetadata { name, intf, Type::UID, ctor, init });
234         }
235         return nullptr;
236     }
237 
RegisterStaticFunctionMetadata(const META_NS::InterfaceInfo & intf,BASE_NS::string_view name,Internal::FCtor * ctor,Internal::FContext * context)238     nullptr_t RegisterStaticFunctionMetadata(const META_NS::InterfaceInfo& intf, BASE_NS::string_view name,
239         Internal::FCtor* ctor, Internal::FContext* context)
240     {
241         if (IsFirstInit()) {
242             StaticObjectMeta().functions.push_back(FunctionMetadata { name, intf, ctor, context });
243         }
244         return nullptr;
245     }
246 
247 protected:
StaticObjectMeta()248     static StaticObjectMetadata& StaticObjectMeta()
249     {
250         static StaticObjectMetadata meta { ClassInfo, nullptr };
251         return meta;
252     }
253 
GetBase()254     IObject::Ptr GetBase() const noexcept
255     {
256         return object_;
257     }
258 
259     template<typename Type>
GetBaseAs()260     constexpr Type* GetBaseAs()
261     {
262         auto* t = object_->GetInterface<Type>();
263         CORE_ASSERT_MSG(t, "Invalid interface %s for base", BASE_NS::to_string(Type::UID).c_str());
264         return t;
265     }
266     template<typename Type>
GetBaseAs()267     constexpr const Type* GetBaseAs() const
268     {
269         return const_cast<BaseObjectFwd*>(this)->GetBaseAs<Type>();
270     }
271 
272 protected:
273     BaseObjectFwd() = default;
274     ~BaseObjectFwd() override = default;
META_NO_COPY_MOVE(BaseObjectFwd)275     META_NO_COPY_MOVE(BaseObjectFwd)
276 
277 private:
278     bool isFirstInit_ {};
279     IObjectInstance::Ptr object_;
280 #ifdef _DEBUG
281     bool buildCalled_ {};
282 #endif
283 };
284 
285 /**
286  * @brief A helper macro for classes deriving from BaseObjectFwd. Makes a forwarder for an interface
287  *        property implemented by the super class.
288  */
289 #define META_EXT_BASE_READONLY_PROPERTY(Interface, Type, Name) \
290     META_FORWARD_READONLY_PROPERTY(Type, Name, Super::template GetBaseAs<Interface>()->Name())
291 
292 /**
293  * @brief A helper macro for classes deriving from BaseObjectFwd. Makes a forwarder for an interface
294  *        property defined by the super class.
295  */
296 #define META_EXT_BASE_PROPERTY(Interface, Type, Name) \
297     META_FORWARD_PROPERTY(Type, Name, Super::template GetBaseAs<Interface>()->Name())
298 
299 /**
300  * @brief A helper macro for classes deriving from BaseObjectFwd. Calls a method through an interface defined
301  *        by the super class.
302  */
303 #define META_EXT_CALL_BASE(Interface, Function) Super::template GetBaseAs<Interface>()->Function
304 
305 /**
306  * @brief A helper template class for implementing a class which implements a basic set of object interfaces with
307  *        the addition of Metadata related interfaces.
308  * @note Usually when inheriting from this template directly SuperClassInfo should be META_NS::ClassId::MetaObject.
309  */
310 template<class FinalClass, const META_NS::ClassInfo& ClassInfo, const META_NS::ClassInfo& SuperClassInfo,
311     class... Interfaces>
312 class MetaObjectFwd : public BaseObjectFwd<FinalClass, ClassInfo, SuperClassInfo, IMetadata, IMetadataInternal,
313                           IObjectContextProvider, Interfaces...> {
314     using Super = BaseObjectFwd<FinalClass, ClassInfo, SuperClassInfo, IMetadata, IMetadataInternal,
315         IObjectContextProvider, Interfaces...>;
316 
317 protected: // IMetadata
GetPropertyContainer()318     IContainer::Ptr GetPropertyContainer() override
319     {
320         return meta_->GetPropertyContainer();
321     }
322 
GetPropertyContainer()323     IContainer::ConstPtr GetPropertyContainer() const override
324     {
325         return meta_->GetPropertyContainer();
326     }
327 
328 protected:
CloneMetadata()329     IMetadata::Ptr CloneMetadata() const override
330     {
331         return meta_->CloneMetadata();
332     }
AddProperty(const IProperty::Ptr & p)333     void AddProperty(const IProperty::Ptr& p) override
334     {
335         auto self = Super::GetSelf();
336         if (self) {
337             if (auto pp = interface_pointer_cast<IPropertyInternal>(p)) {
338                 pp->SetOwner(self);
339             }
340         }
341         meta_->AddProperty(p);
342     }
RemoveProperty(const IProperty::Ptr & p)343     void RemoveProperty(const IProperty::Ptr& p) override
344     {
345         meta_->RemoveProperty(p);
346     }
AddFunction(const IFunction::Ptr & p)347     void AddFunction(const IFunction::Ptr& p) override
348     {
349         meta_->AddFunction(p);
350     }
RemoveFunction(const IFunction::Ptr & p)351     void RemoveFunction(const IFunction::Ptr& p) override
352     {
353         meta_->RemoveFunction(p);
354     }
AddEvent(const IEvent::Ptr & p)355     void AddEvent(const IEvent::Ptr& p) override
356     {
357         meta_->AddEvent(p);
358     }
RemoveEvent(const IEvent::Ptr & p)359     void RemoveEvent(const IEvent::Ptr& p) override
360     {
361         meta_->RemoveEvent(p);
362     }
SetProperties(const BASE_NS::vector<IProperty::Ptr> & vec)363     void SetProperties(const BASE_NS::vector<IProperty::Ptr>& vec) override
364     {
365         meta_->SetProperties(vec);
366     }
Merge(const IMetadata::Ptr & data)367     void Merge(const IMetadata::Ptr& data) override
368     {
369         meta_->Merge(data);
370     }
GetAllProperties()371     BASE_NS::vector<META_NS::IProperty::Ptr> GetAllProperties() override
372     {
373         return meta_->GetAllProperties();
374     }
GetAllProperties()375     BASE_NS::vector<META_NS::IProperty::ConstPtr> GetAllProperties() const override
376     {
377         return static_cast<const IMetadata*>(meta_.get())->GetAllProperties();
378     }
GetAllFunctions()379     BASE_NS::vector<IFunction::Ptr> GetAllFunctions() override
380     {
381         return meta_->GetAllFunctions();
382     }
GetAllFunctions()383     BASE_NS::vector<IFunction::ConstPtr> GetAllFunctions() const override
384     {
385         return static_cast<const IMetadata*>(meta_.get())->GetAllFunctions();
386     }
GetAllEvents()387     BASE_NS::vector<IEvent::Ptr> GetAllEvents() override
388     {
389         return meta_->GetAllEvents();
390     }
GetAllEvents()391     BASE_NS::vector<IEvent::ConstPtr> GetAllEvents() const override
392     {
393         return static_cast<const IMetadata*>(meta_.get())->GetAllEvents();
394     }
395 
GetPropertyByName(BASE_NS::string_view name)396     IProperty::Ptr GetPropertyByName(BASE_NS::string_view name) override
397     {
398         return meta_->GetPropertyByName(name);
399     }
GetPropertyByName(BASE_NS::string_view name)400     IProperty::ConstPtr GetPropertyByName(BASE_NS::string_view name) const override
401     {
402         return meta_->GetPropertyByName(name);
403     }
404 
GetFunctionByName(BASE_NS::string_view name)405     IFunction::ConstPtr GetFunctionByName(BASE_NS::string_view name) const override
406     {
407         return meta_->GetFunctionByName(name);
408     }
GetFunctionByName(BASE_NS::string_view name)409     IFunction::Ptr GetFunctionByName(BASE_NS::string_view name) override
410     {
411         return meta_->GetFunctionByName(name);
412     }
GetEventByName(BASE_NS::string_view name)413     IEvent::ConstPtr GetEventByName(BASE_NS::string_view name) const override
414     {
415         return meta_->GetEventByName(name);
416     }
GetEventByName(BASE_NS::string_view name)417     IEvent::Ptr GetEventByName(BASE_NS::string_view name) override
418     {
419         return meta_->GetEventByName(name);
420     }
421 
422 protected: // IMetadataInternal
SetMetadata(const IMetadata::Ptr & meta)423     void SetMetadata(const IMetadata::Ptr& meta) override
424     {
425         meta_ = meta;
426         ConstructPropertiesFromMetadata(this, FinalClass::StaticObjectMeta(), meta);
427         ConstructEventsFromMetadata(this, FinalClass::StaticObjectMeta(), meta);
428         ConstructFunctionsFromMetadata(this, FinalClass::StaticObjectMeta(), meta);
429     }
430 
GetMetadata()431     IMetadata::Ptr GetMetadata() const override
432     {
433         return meta_;
434     }
435 
GetStaticMetadata()436     const StaticObjectMetadata& GetStaticMetadata() const override
437     {
438         return FinalClass::GetStaticObjectMetadata();
439     }
440 
441 protected: // IObjectContextProvider
META_EXT_BASE_PROPERTY(IObjectContextProvider,IObjectContext::Ptr,ObjectContext)442     META_EXT_BASE_PROPERTY(IObjectContextProvider, IObjectContext::Ptr, ObjectContext)
443     void ResetObjectContext() override
444     {
445         META_EXT_CALL_BASE(IObjectContextProvider, ResetObjectContext());
446     }
447 
448 protected:
449     MetaObjectFwd() = default;
450     ~MetaObjectFwd() override = default;
451     META_NO_COPY_MOVE(MetaObjectFwd)
452 
453 private:
454     IMetadata::Ptr meta_;
455 };
456 
457 /**
458  * @brief A helper template class for implementing a class which implements the full set of object interfaces.
459  * @note Usually this template should be used as the base class, unless SuperClassInfo is
460  *       META_NS::ClassId::BaseObject or META_NS::ClassId::MetaObject.
461  */
462 template<class FinalClass, const META_NS::ClassInfo& ClassInfo, const META_NS::ClassInfo& SuperClassInfo,
463     class... Interfaces>
464 class ObjectFwd : public MetaObjectFwd<FinalClass, ClassInfo, SuperClassInfo, IAttach, IContainerQuery, Interfaces...> {
465     using Super = MetaObjectFwd<FinalClass, ClassInfo, SuperClassInfo, IAttach, IContainerQuery, Interfaces...>;
466 
467 public:
GetObjectRegistry()468     META_NS::IObjectRegistry& GetObjectRegistry() override
469     {
470         if (auto context = Super::ObjectContext()->GetValue()) {
471             return context->GetObjectRegistry();
472         }
473         return Super::GetObjectRegistry();
474     }
475 
476 protected: // IAttach
Attach(const IObject::Ptr & attachment,const IObject::Ptr & dataContext)477     bool Attach(const IObject::Ptr& attachment, const IObject::Ptr& dataContext) override
478     {
479         return META_EXT_CALL_BASE(IAttach, Attach(attachment, dataContext));
480     }
481 
Detach(const IObject::Ptr & attachment)482     bool Detach(const IObject::Ptr& attachment) override
483     {
484         return META_EXT_CALL_BASE(IAttach, Detach(attachment));
485     }
GetAttachments(const BASE_NS::vector<TypeId> & uids,bool strict)486     BASE_NS::vector<IObject::Ptr> GetAttachments(const BASE_NS::vector<TypeId>& uids, bool strict) const override
487     {
488         return META_EXT_CALL_BASE(IAttach, GetAttachments(uids, strict));
489     }
HasAttachments()490     bool HasAttachments() const override
491     {
492         return META_EXT_CALL_BASE(IAttach, HasAttachments());
493     }
GetAttachmentContainer(bool initializeAlways)494     IContainer::Ptr GetAttachmentContainer(bool initializeAlways) const override
495     {
496         return META_EXT_CALL_BASE(IAttach, GetAttachmentContainer(initializeAlways));
497     }
498 
499 protected: // IContainerQuery
FindAllContainers(const IContainerQuery::ContainerFindOptions & options)500     BASE_NS::vector<IContainer::Ptr> FindAllContainers(
501         const IContainerQuery::ContainerFindOptions& options) const override
502     {
503         return META_EXT_CALL_BASE(IContainerQuery, FindAllContainers(options));
504     }
505 
506 protected:
507     ObjectFwd() = default;
508     ~ObjectFwd() override = default;
509     META_NO_COPY_MOVE(ObjectFwd)
510 };
511 
512 META_END_NAMESPACE()
513 
514 #endif
515