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#include "object.h"
168bf80f4bSopenharmony_ci
178bf80f4bSopenharmony_ci#include <algorithm>
188bf80f4bSopenharmony_ci#include <limits>
198bf80f4bSopenharmony_ci
208bf80f4bSopenharmony_ci#include <base/util/uid_util.h>
218bf80f4bSopenharmony_ci#include <core/plugin/intf_class_factory.h>
228bf80f4bSopenharmony_ci
238bf80f4bSopenharmony_ci#include <meta/api/iteration.h>
248bf80f4bSopenharmony_ci#include <meta/interface/builtin_objects.h>
258bf80f4bSopenharmony_ci#include <meta/interface/intf_object_registry.h>
268bf80f4bSopenharmony_ci#include <meta/interface/intf_proxy_object.h>
278bf80f4bSopenharmony_ci#include <meta/interface/intf_required_interfaces.h>
288bf80f4bSopenharmony_ci#include <meta/interface/property/intf_property_internal.h>
298bf80f4bSopenharmony_ci
308bf80f4bSopenharmony_ci#include "ref_uri_util.h"
318bf80f4bSopenharmony_ci
328bf80f4bSopenharmony_ciMETA_BEGIN_NAMESPACE()
338bf80f4bSopenharmony_cinamespace Internal {
348bf80f4bSopenharmony_ci
358bf80f4bSopenharmony_ci// ILifecycle
368bf80f4bSopenharmony_cibool Object::Build(const IMetadata::Ptr& data)
378bf80f4bSopenharmony_ci{
388bf80f4bSopenharmony_ci    return Super::Build(data);
398bf80f4bSopenharmony_ci}
408bf80f4bSopenharmony_ci
418bf80f4bSopenharmony_civoid Object::Destroy()
428bf80f4bSopenharmony_ci{
438bf80f4bSopenharmony_ci    if (attachments_) {
448bf80f4bSopenharmony_ci        attachments_->RemoveAllAttachments();
458bf80f4bSopenharmony_ci        attachments_.reset();
468bf80f4bSopenharmony_ci    }
478bf80f4bSopenharmony_ci    Super::Destroy();
488bf80f4bSopenharmony_ci}
498bf80f4bSopenharmony_ci
508bf80f4bSopenharmony_ci// IAttach
518bf80f4bSopenharmony_cibool Object::Attach(const IObject::Ptr& attachment, const IObject::Ptr& dataContext)
528bf80f4bSopenharmony_ci{
538bf80f4bSopenharmony_ci    ValidateAttachmentContainer();
548bf80f4bSopenharmony_ci    if (attachments_) {
558bf80f4bSopenharmony_ci        return attachments_->Attach(attachment, dataContext);
568bf80f4bSopenharmony_ci    }
578bf80f4bSopenharmony_ci    return false;
588bf80f4bSopenharmony_ci}
598bf80f4bSopenharmony_ci
608bf80f4bSopenharmony_cibool Object::Detach(const IObject::Ptr& attachment)
618bf80f4bSopenharmony_ci{
628bf80f4bSopenharmony_ci    if (attachments_) {
638bf80f4bSopenharmony_ci        return attachments_->Detach(attachment);
648bf80f4bSopenharmony_ci    }
658bf80f4bSopenharmony_ci    return false;
668bf80f4bSopenharmony_ci}
678bf80f4bSopenharmony_ci
688bf80f4bSopenharmony_ciBASE_NS::vector<IObject::Ptr> Object::GetAttachments(const BASE_NS::vector<TypeId>& uids, bool strict) const
698bf80f4bSopenharmony_ci{
708bf80f4bSopenharmony_ci    if (attachments_) {
718bf80f4bSopenharmony_ci        return attachments_->GetAttachments(uids, strict);
728bf80f4bSopenharmony_ci    }
738bf80f4bSopenharmony_ci    return {};
748bf80f4bSopenharmony_ci}
758bf80f4bSopenharmony_cibool Object::HasAttachments() const
768bf80f4bSopenharmony_ci{
778bf80f4bSopenharmony_ci    if (const auto container = interface_cast<IContainer>(attachments_)) {
788bf80f4bSopenharmony_ci        return container->GetSize() > 0;
798bf80f4bSopenharmony_ci    }
808bf80f4bSopenharmony_ci    return false;
818bf80f4bSopenharmony_ci}
828bf80f4bSopenharmony_ciIContainer::Ptr Object::GetAttachmentContainer(bool initializeAlways) const
838bf80f4bSopenharmony_ci{
848bf80f4bSopenharmony_ci    if (initializeAlways) {
858bf80f4bSopenharmony_ci        ValidateAttachmentContainer();
868bf80f4bSopenharmony_ci    }
878bf80f4bSopenharmony_ci    return interface_pointer_cast<IContainer>(attachments_);
888bf80f4bSopenharmony_ci}
898bf80f4bSopenharmony_ci
908bf80f4bSopenharmony_civoid Object::ValidateAttachmentContainer() const
918bf80f4bSopenharmony_ci{
928bf80f4bSopenharmony_ci    if (!attachments_) {
938bf80f4bSopenharmony_ci        if (attachments_ =
948bf80f4bSopenharmony_ci                META_NS::GetObjectRegistry().Create<META_NS::IAttachmentContainer>(ClassId::AttachmentContainer);
958bf80f4bSopenharmony_ci            attachments_) {
968bf80f4bSopenharmony_ci            attachments_->Initialize(GetSelf<META_NS::IAttach>());
978bf80f4bSopenharmony_ci        } else {
988bf80f4bSopenharmony_ci            CORE_LOG_E("Failed to create container for attachments");
998bf80f4bSopenharmony_ci        }
1008bf80f4bSopenharmony_ci    }
1018bf80f4bSopenharmony_ci}
1028bf80f4bSopenharmony_ci
1038bf80f4bSopenharmony_cibool CheckRequiredInterfaces(const IContainer::Ptr& container, const BASE_NS::vector<BASE_NS::Uid>& uids)
1048bf80f4bSopenharmony_ci{
1058bf80f4bSopenharmony_ci    if (uids.empty()) {
1068bf80f4bSopenharmony_ci        return true;
1078bf80f4bSopenharmony_ci    }
1088bf80f4bSopenharmony_ci    if (auto req = interface_cast<IRequiredInterfaces>(container)) {
1098bf80f4bSopenharmony_ci        const auto reqs = req->GetRequiredInterfaces();
1108bf80f4bSopenharmony_ci        if (reqs.empty()) {
1118bf80f4bSopenharmony_ci            return true; // Container has no requirements related to the interfaces it accepts
1128bf80f4bSopenharmony_ci        }
1138bf80f4bSopenharmony_ci        size_t matches = 0;
1148bf80f4bSopenharmony_ci        for (const auto& uid : uids) {
1158bf80f4bSopenharmony_ci            if (std::find(reqs.begin(), reqs.end(), uid) != reqs.end()) {
1168bf80f4bSopenharmony_ci                matches++;
1178bf80f4bSopenharmony_ci            }
1188bf80f4bSopenharmony_ci        }
1198bf80f4bSopenharmony_ci        return matches == uids.size();
1208bf80f4bSopenharmony_ci    }
1218bf80f4bSopenharmony_ci
1228bf80f4bSopenharmony_ci    // If container is valid but it does not implement IRequiredInterfaces, anything goes
1238bf80f4bSopenharmony_ci    return container.operator bool();
1248bf80f4bSopenharmony_ci}
1258bf80f4bSopenharmony_ci
1268bf80f4bSopenharmony_ciBASE_NS::vector<IContainer::Ptr> Object::FindAllContainers(const ContainerFindOptions& options) const
1278bf80f4bSopenharmony_ci{
1288bf80f4bSopenharmony_ci    BASE_NS::vector<IContainer::Ptr> containers;
1298bf80f4bSopenharmony_ci    const auto maxCount = options.maxCount ? options.maxCount : std::numeric_limits<size_t>::max();
1308bf80f4bSopenharmony_ci    const auto& uids = options.uids;
1318bf80f4bSopenharmony_ci    const auto addIfMatches = [&containers, &uids](const IContainer::Ptr& container) {
1328bf80f4bSopenharmony_ci        if (container) {
1338bf80f4bSopenharmony_ci            if (CheckRequiredInterfaces(container, uids)) {
1348bf80f4bSopenharmony_ci                containers.push_back(container);
1358bf80f4bSopenharmony_ci            }
1368bf80f4bSopenharmony_ci        }
1378bf80f4bSopenharmony_ci    };
1388bf80f4bSopenharmony_ci    if (const auto me = GetSelf<IContainer>()) {
1398bf80f4bSopenharmony_ci        // This object is itself a container
1408bf80f4bSopenharmony_ci        addIfMatches(me);
1418bf80f4bSopenharmony_ci    }
1428bf80f4bSopenharmony_ci    if (containers.size() < maxCount) {
1438bf80f4bSopenharmony_ci        if (HasAttachments()) {
1448bf80f4bSopenharmony_ci            // Check the attachment container
1458bf80f4bSopenharmony_ci            addIfMatches(interface_pointer_cast<IContainer>(attachments_));
1468bf80f4bSopenharmony_ci            // Check the attachments themselves
1478bf80f4bSopenharmony_ci            if (containers.size() < maxCount) {
1488bf80f4bSopenharmony_ci                IterateShared(attachments_, [&addIfMatches, &containers, &maxCount](const IObject::Ptr& object) {
1498bf80f4bSopenharmony_ci                    addIfMatches(interface_pointer_cast<IContainer>(object));
1508bf80f4bSopenharmony_ci                    return containers.size() < maxCount;
1518bf80f4bSopenharmony_ci                });
1528bf80f4bSopenharmony_ci            }
1538bf80f4bSopenharmony_ci        } else {
1548bf80f4bSopenharmony_ci            // No attachments, but the user has requested IAttachment so we need to create the container
1558bf80f4bSopenharmony_ci            if (uids.empty() || std::find(uids.begin(), uids.end(), IAttachment::UID) != uids.end()) {
1568bf80f4bSopenharmony_ci                ValidateAttachmentContainer();
1578bf80f4bSopenharmony_ci                addIfMatches(interface_pointer_cast<IContainer>(attachments_));
1588bf80f4bSopenharmony_ci            }
1598bf80f4bSopenharmony_ci        }
1608bf80f4bSopenharmony_ci    }
1618bf80f4bSopenharmony_ci    return containers;
1628bf80f4bSopenharmony_ci}
1638bf80f4bSopenharmony_ci
1648bf80f4bSopenharmony_ciconst StaticObjectMetadata& Object::GetStaticMetadata() const
1658bf80f4bSopenharmony_ci{
1668bf80f4bSopenharmony_ci    return GetStaticObjectMetadata();
1678bf80f4bSopenharmony_ci}
1688bf80f4bSopenharmony_ci
1698bf80f4bSopenharmony_ci} // namespace Internal
1708bf80f4bSopenharmony_ci
1718bf80f4bSopenharmony_ciMETA_END_NAMESPACE()
172