* 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.
*/
#include <mutex>
#include <shared_mutex>
#include <meta/api/event_handler.h>
#include <meta/api/property/property_event_handler.h>
#include <meta/api/threading/mutex.h>
#include <meta/base/interface_macros.h>
#include <meta/base/namespace.h>
#include <meta/ext/implementation_macros.h>
#include <meta/interface/intf_content.h>
#include <meta/interface/intf_iterable.h>
#include <meta/interface/intf_required_interfaces.h>
#include "object.h"
META_BEGIN_INTERNAL_NAMESPACE()
class ContentObject : public IntroduceInterfaces<MetaObject, IContent, IRequiredInterfaces, IIterable> {
META_OBJECT(ContentObject, ClassId::ContentObject, IntroduceInterfaces)
public:
META_BEGIN_STATIC_DATA()
META_STATIC_PROPERTY_DATA(IContent, IObject::Ptr, Content)
META_STATIC_PROPERTY_DATA(IContent, bool, ContentSearchable, true)
META_END_STATIC_DATA()
META_IMPLEMENT_READONLY_PROPERTY(IObject::Ptr, Content)
META_IMPLEMENT_PROPERTY(bool, ContentSearchable)
bool SetContent(const IObject::Ptr& content) override
{
bool valid = CheckContentRequirements(content);
SetValue(META_ACCESS_PROPERTY(Content), valid ? content : nullptr);
if (!valid) {
CORE_LOG_W("Content does not fulfil interface requirements");
}
return valid;
}
bool Build(const IMetadata::Ptr& data) override
{
bool ret = Super::Build(data);
if (ret) {
OnSerializeChanged();
}
return ret;
}
void Destroy() override
{
if (auto c = META_ACCESS_PROPERTY(Content)) {
c->OnChanged()->Reset();
c->SetValue(nullptr);
}
Super::Destroy();
}
void OnSerializeChanged()
{
if (auto cont = META_ACCESS_PROPERTY(Content)) {
META_NS::SetObjectFlags(cont.GetProperty(),
ObjectFlagBits::SERIALIZE,
GetObjectFlags().IsSet(ObjectFlagBits::SERIALIZE_HIERARCHY));
}
}
void SetObjectFlags(const ObjectFlagBitsValue& flags) override
{
Super::SetObjectFlags(flags);
OnSerializeChanged();
}
ObjectFlagBitsValue GetObjectDefaultFlags() const override
{
auto flags = Super::GetObjectDefaultFlags();
flags &= ~ObjectFlagBitsValue(ObjectFlagBits::SERIALIZE_HIERARCHY);
return flags;
}
bool SetRequiredInterfaces(const BASE_NS::vector<TypeId>& interfaces) override
{
{
std::unique_lock lock(mutex_);
requiredInterfaces_ = interfaces;
}
if (const auto content = META_ACCESS_PROPERTY_VALUE(Content)) {
if (!CheckContentRequirements(content)) {
SetContent(nullptr);
}
}
return true;
}
BASE_NS::vector<TypeId> GetRequiredInterfaces() const override
{
std::shared_lock lock(mutex_);
return requiredInterfaces_;
}
bool CheckContentRequirements(const IObject::Ptr& object)
{
std::shared_lock lock(mutex_);
return !object || CheckInterfaces(object, requiredInterfaces_, true);
}
template <typename Func>
IterationResult IterateImpl(const Func& f) const
{
if (!f) {
CORE_LOG_W("Incompatible function with Iterate");
return IterationResult::FAILED;
}
if (META_ACCESS_PROPERTY_VALUE(ContentSearchable)) {
if (auto c = META_ACCESS_PROPERTY_VALUE(Content)) {
return f->Invoke(c);
}
}
return IterationResult::CONTINUE;
}
IterationResult Iterate(const IterationParameters& params) override
{
return IterateImpl(params.function.GetInterface<IIterableCallable<IObject::Ptr>>());
}
IterationResult Iterate(const IterationParameters& params) const override
{
return IterateImpl(params.function.GetInterface<IIterableConstCallable<IObject::Ptr>>());
}
private:
mutable std::shared_mutex mutex_;
BASE_NS::vector<TypeId> requiredInterfaces_;
};
IObjectFactory::Ptr GetContentObjectFactory()
{
return ContentObject::GetFactory();
}
META_END_INTERNAL_NAMESPACE()