/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef META_EXT_OBJECT_H
#define META_EXT_OBJECT_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "object_factory.h"
META_BEGIN_NAMESPACE()
namespace Internal {
// dummy pure virtual to shutup compiler warnings
class DummyGetObjectRegistry {
virtual META_NS::IObjectRegistry& GetObjectRegistry() = 0;
};
} // namespace Internal
/**
* @brief A helper template class for implementing a class which implements a basic set of object interfaces.
* @note Usually when inheriting from this template directly SuperClassInfo should be META_NS::ClassId::BaseObject.
*/
template
class BaseObjectFwd : public IntroduceInterfaces,
private Internal::DummyGetObjectRegistry {
using Fwd = BaseObjectFwd;
using Super = IntroduceInterfaces;
public:
// using declaration doesn't work with vc, still thinks the function access is protected
CORE_NS::IInterface* GetInterface(const BASE_NS::Uid& uid) override
{
return Super::GetInterface(uid);
}
const CORE_NS::IInterface* GetInterface(const BASE_NS::Uid& uid) const override
{
return Super::GetInterface(uid);
}
template
constexpr Type* GetInterface() noexcept
{
return static_cast(Super::StaticGetInterface(Type::UID));
}
template
constexpr const Type* GetInterface() const noexcept
{
auto* me = const_cast(this);
return static_cast(me->StaticGetInterface(Type::UID));
}
public:
META_DEFINE_OBJECT_TYPE_INFO(FinalClass, ClassInfo)
public:
META_NS::IObjectRegistry& GetObjectRegistry() override
{
return META_NS::GetObjectRegistry();
}
static const StaticObjectMetadata& GetStaticObjectMetadata()
{
return StaticObjectMeta();
}
public: // IObject
BASE_NS::string_view GetClassName() const override
{
return ClassInfo.Name();
}
InstanceId GetInstanceId() const override
{
return object_->GetInstanceId();
}
ObjectId GetClassId() const override
{
return ClassInfo.Id();
}
BASE_NS::string GetName() const override
{
return object_->GetName();
}
IObject::Ptr Resolve(const RefUri& uri) const override
{
return object_->Resolve(uri);
}
template
typename Interface::Ptr Resolve(const RefUri& uri) const
{
return interface_pointer_cast(object_->Resolve(uri));
}
IObject::Ptr GetSelf() const override
{
return object_ ? object_->GetSelf() : nullptr;
}
template
typename Interface::Ptr GetSelf() const
{
return interface_pointer_cast(GetSelf());
}
BASE_NS::vector GetInterfaces() const override
{
return GetStaticInterfaces();
}
static BASE_NS::vector GetStaticInterfaces()
{
return Super::GetInterfacesVector();
}
public: // IObjectFlags
ObjectFlagBitsValue GetObjectFlags() const override
{
if (auto flags = interface_cast(object_)) {
return flags->GetObjectFlags();
}
return {};
}
void SetObjectFlags(const ObjectFlagBitsValue& value) override
{
if (auto flags = interface_cast(object_)) {
flags->SetObjectFlags(value);
}
}
ObjectFlagBitsValue GetObjectDefaultFlags() const override
{
if (auto flags = interface_cast(object_)) {
return flags->GetObjectDefaultFlags();
}
return {};
}
protected: // ILifecycle
bool Build(const IMetadata::Ptr& data) override
{
#ifdef _DEBUG
// Object registry calls this
if (buildCalled_) {
CORE_LOG_E("Do not call Build explicitly from derived class!");
}
buildCalled_ = true;
#endif
return true;
}
void SetInstanceId(InstanceId uid) override
{
// Object registry does this
}
void Destroy() override
{
if (auto builder = interface_cast(object_)) {
builder->Destroy();
}
}
protected: // IDerived
void SetSuperInstance(const META_NS::IObject::Ptr& /*aggr*/, const META_NS::IObject::Ptr& super) override
{
#ifdef _DEBUG
// Object registry calls this
if (object_) {
CORE_LOG_E("Do not call SetSuperInstance explicitly from derived class!");
}
#endif
if (IsFirstInit()) {
if (auto i = interface_cast(super)) {
StaticObjectMeta().baseclass = &i->GetStaticMetadata();
}
}
object_ = interface_pointer_cast(super); // Save the strong reference to super.
}
BASE_NS::Uid GetSuperClassUid() const override
{
return SuperClassInfo.Id().ToUid();
}
protected:
bool IsFirstInit()
{
static bool init = (isFirstInit_ = true);
return isFirstInit_;
}
template
nullptr_t RegisterStaticPropertyMetadata(const META_NS::InterfaceInfo& intf, BASE_NS::string_view name,
ObjectFlagBitsValue flags, Internal::PCtor* ctor, Internal::PMemberInit* init)
{
if (IsFirstInit()) {
StaticObjectMeta().properties.push_back(
PropertyMetadata { name, intf, flags, UidFromType(), ctor, init });
}
return nullptr;
}
template
nullptr_t RegisterStaticEventMetadata(const META_NS::InterfaceInfo& intf, BASE_NS::string_view name,
Internal::ECtor* ctor, Internal::EMemberInit* init)
{
if (IsFirstInit()) {
StaticObjectMeta().events.push_back(EventMetadata { name, intf, Type::UID, ctor, init });
}
return nullptr;
}
nullptr_t RegisterStaticFunctionMetadata(const META_NS::InterfaceInfo& intf, BASE_NS::string_view name,
Internal::FCtor* ctor, Internal::FContext* context)
{
if (IsFirstInit()) {
StaticObjectMeta().functions.push_back(FunctionMetadata { name, intf, ctor, context });
}
return nullptr;
}
protected:
static StaticObjectMetadata& StaticObjectMeta()
{
static StaticObjectMetadata meta { ClassInfo, nullptr };
return meta;
}
IObject::Ptr GetBase() const noexcept
{
return object_;
}
template
constexpr Type* GetBaseAs()
{
auto* t = object_->GetInterface();
CORE_ASSERT_MSG(t, "Invalid interface %s for base", BASE_NS::to_string(Type::UID).c_str());
return t;
}
template
constexpr const Type* GetBaseAs() const
{
return const_cast(this)->GetBaseAs();
}
protected:
BaseObjectFwd() = default;
~BaseObjectFwd() override = default;
META_NO_COPY_MOVE(BaseObjectFwd)
private:
bool isFirstInit_ {};
IObjectInstance::Ptr object_;
#ifdef _DEBUG
bool buildCalled_ {};
#endif
};
/**
* @brief A helper macro for classes deriving from BaseObjectFwd. Makes a forwarder for an interface
* property implemented by the super class.
*/
#define META_EXT_BASE_READONLY_PROPERTY(Interface, Type, Name) \
META_FORWARD_READONLY_PROPERTY(Type, Name, Super::template GetBaseAs()->Name())
/**
* @brief A helper macro for classes deriving from BaseObjectFwd. Makes a forwarder for an interface
* property defined by the super class.
*/
#define META_EXT_BASE_PROPERTY(Interface, Type, Name) \
META_FORWARD_PROPERTY(Type, Name, Super::template GetBaseAs()->Name())
/**
* @brief A helper macro for classes deriving from BaseObjectFwd. Calls a method through an interface defined
* by the super class.
*/
#define META_EXT_CALL_BASE(Interface, Function) Super::template GetBaseAs()->Function
/**
* @brief A helper template class for implementing a class which implements a basic set of object interfaces with
* the addition of Metadata related interfaces.
* @note Usually when inheriting from this template directly SuperClassInfo should be META_NS::ClassId::MetaObject.
*/
template
class MetaObjectFwd : public BaseObjectFwd {
using Super = BaseObjectFwd;
protected: // IMetadata
IContainer::Ptr GetPropertyContainer() override
{
return meta_->GetPropertyContainer();
}
IContainer::ConstPtr GetPropertyContainer() const override
{
return meta_->GetPropertyContainer();
}
protected:
IMetadata::Ptr CloneMetadata() const override
{
return meta_->CloneMetadata();
}
void AddProperty(const IProperty::Ptr& p) override
{
auto self = Super::GetSelf();
if (self) {
if (auto pp = interface_pointer_cast(p)) {
pp->SetOwner(self);
}
}
meta_->AddProperty(p);
}
void RemoveProperty(const IProperty::Ptr& p) override
{
meta_->RemoveProperty(p);
}
void AddFunction(const IFunction::Ptr& p) override
{
meta_->AddFunction(p);
}
void RemoveFunction(const IFunction::Ptr& p) override
{
meta_->RemoveFunction(p);
}
void AddEvent(const IEvent::Ptr& p) override
{
meta_->AddEvent(p);
}
void RemoveEvent(const IEvent::Ptr& p) override
{
meta_->RemoveEvent(p);
}
void SetProperties(const BASE_NS::vector& vec) override
{
meta_->SetProperties(vec);
}
void Merge(const IMetadata::Ptr& data) override
{
meta_->Merge(data);
}
BASE_NS::vector GetAllProperties() override
{
return meta_->GetAllProperties();
}
BASE_NS::vector GetAllProperties() const override
{
return static_cast(meta_.get())->GetAllProperties();
}
BASE_NS::vector GetAllFunctions() override
{
return meta_->GetAllFunctions();
}
BASE_NS::vector GetAllFunctions() const override
{
return static_cast(meta_.get())->GetAllFunctions();
}
BASE_NS::vector GetAllEvents() override
{
return meta_->GetAllEvents();
}
BASE_NS::vector GetAllEvents() const override
{
return static_cast(meta_.get())->GetAllEvents();
}
IProperty::Ptr GetPropertyByName(BASE_NS::string_view name) override
{
return meta_->GetPropertyByName(name);
}
IProperty::ConstPtr GetPropertyByName(BASE_NS::string_view name) const override
{
return meta_->GetPropertyByName(name);
}
IFunction::ConstPtr GetFunctionByName(BASE_NS::string_view name) const override
{
return meta_->GetFunctionByName(name);
}
IFunction::Ptr GetFunctionByName(BASE_NS::string_view name) override
{
return meta_->GetFunctionByName(name);
}
IEvent::ConstPtr GetEventByName(BASE_NS::string_view name) const override
{
return meta_->GetEventByName(name);
}
IEvent::Ptr GetEventByName(BASE_NS::string_view name) override
{
return meta_->GetEventByName(name);
}
protected: // IMetadataInternal
void SetMetadata(const IMetadata::Ptr& meta) override
{
meta_ = meta;
ConstructPropertiesFromMetadata(this, FinalClass::StaticObjectMeta(), meta);
ConstructEventsFromMetadata(this, FinalClass::StaticObjectMeta(), meta);
ConstructFunctionsFromMetadata(this, FinalClass::StaticObjectMeta(), meta);
}
IMetadata::Ptr GetMetadata() const override
{
return meta_;
}
const StaticObjectMetadata& GetStaticMetadata() const override
{
return FinalClass::GetStaticObjectMetadata();
}
protected: // IObjectContextProvider
META_EXT_BASE_PROPERTY(IObjectContextProvider, IObjectContext::Ptr, ObjectContext)
void ResetObjectContext() override
{
META_EXT_CALL_BASE(IObjectContextProvider, ResetObjectContext());
}
protected:
MetaObjectFwd() = default;
~MetaObjectFwd() override = default;
META_NO_COPY_MOVE(MetaObjectFwd)
private:
IMetadata::Ptr meta_;
};
/**
* @brief A helper template class for implementing a class which implements the full set of object interfaces.
* @note Usually this template should be used as the base class, unless SuperClassInfo is
* META_NS::ClassId::BaseObject or META_NS::ClassId::MetaObject.
*/
template
class ObjectFwd : public MetaObjectFwd {
using Super = MetaObjectFwd;
public:
META_NS::IObjectRegistry& GetObjectRegistry() override
{
if (auto context = Super::ObjectContext()->GetValue()) {
return context->GetObjectRegistry();
}
return Super::GetObjectRegistry();
}
protected: // IAttach
bool Attach(const IObject::Ptr& attachment, const IObject::Ptr& dataContext) override
{
return META_EXT_CALL_BASE(IAttach, Attach(attachment, dataContext));
}
bool Detach(const IObject::Ptr& attachment) override
{
return META_EXT_CALL_BASE(IAttach, Detach(attachment));
}
BASE_NS::vector GetAttachments(const BASE_NS::vector& uids, bool strict) const override
{
return META_EXT_CALL_BASE(IAttach, GetAttachments(uids, strict));
}
bool HasAttachments() const override
{
return META_EXT_CALL_BASE(IAttach, HasAttachments());
}
IContainer::Ptr GetAttachmentContainer(bool initializeAlways) const override
{
return META_EXT_CALL_BASE(IAttach, GetAttachmentContainer(initializeAlways));
}
protected: // IContainerQuery
BASE_NS::vector FindAllContainers(
const IContainerQuery::ContainerFindOptions& options) const override
{
return META_EXT_CALL_BASE(IContainerQuery, FindAllContainers(options));
}
protected:
ObjectFwd() = default;
~ObjectFwd() override = default;
META_NO_COPY_MOVE(ObjectFwd)
};
META_END_NAMESPACE()
#endif