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#include "object.h" 16 17#include <algorithm> 18#include <limits> 19 20#include <base/util/uid_util.h> 21#include <core/plugin/intf_class_factory.h> 22 23#include <meta/api/iteration.h> 24#include <meta/interface/builtin_objects.h> 25#include <meta/interface/intf_object_registry.h> 26#include <meta/interface/intf_proxy_object.h> 27#include <meta/interface/intf_required_interfaces.h> 28#include <meta/interface/property/intf_property_internal.h> 29 30#include "ref_uri_util.h" 31 32META_BEGIN_NAMESPACE() 33namespace Internal { 34 35// ILifecycle 36bool Object::Build(const IMetadata::Ptr& data) 37{ 38 return Super::Build(data); 39} 40 41void Object::Destroy() 42{ 43 if (attachments_) { 44 attachments_->RemoveAllAttachments(); 45 attachments_.reset(); 46 } 47 Super::Destroy(); 48} 49 50// IAttach 51bool Object::Attach(const IObject::Ptr& attachment, const IObject::Ptr& dataContext) 52{ 53 ValidateAttachmentContainer(); 54 if (attachments_) { 55 return attachments_->Attach(attachment, dataContext); 56 } 57 return false; 58} 59 60bool Object::Detach(const IObject::Ptr& attachment) 61{ 62 if (attachments_) { 63 return attachments_->Detach(attachment); 64 } 65 return false; 66} 67 68BASE_NS::vector<IObject::Ptr> Object::GetAttachments(const BASE_NS::vector<TypeId>& uids, bool strict) const 69{ 70 if (attachments_) { 71 return attachments_->GetAttachments(uids, strict); 72 } 73 return {}; 74} 75bool Object::HasAttachments() const 76{ 77 if (const auto container = interface_cast<IContainer>(attachments_)) { 78 return container->GetSize() > 0; 79 } 80 return false; 81} 82IContainer::Ptr Object::GetAttachmentContainer(bool initializeAlways) const 83{ 84 if (initializeAlways) { 85 ValidateAttachmentContainer(); 86 } 87 return interface_pointer_cast<IContainer>(attachments_); 88} 89 90void Object::ValidateAttachmentContainer() const 91{ 92 if (!attachments_) { 93 if (attachments_ = 94 META_NS::GetObjectRegistry().Create<META_NS::IAttachmentContainer>(ClassId::AttachmentContainer); 95 attachments_) { 96 attachments_->Initialize(GetSelf<META_NS::IAttach>()); 97 } else { 98 CORE_LOG_E("Failed to create container for attachments"); 99 } 100 } 101} 102 103bool CheckRequiredInterfaces(const IContainer::Ptr& container, const BASE_NS::vector<BASE_NS::Uid>& uids) 104{ 105 if (uids.empty()) { 106 return true; 107 } 108 if (auto req = interface_cast<IRequiredInterfaces>(container)) { 109 const auto reqs = req->GetRequiredInterfaces(); 110 if (reqs.empty()) { 111 return true; // Container has no requirements related to the interfaces it accepts 112 } 113 size_t matches = 0; 114 for (const auto& uid : uids) { 115 if (std::find(reqs.begin(), reqs.end(), uid) != reqs.end()) { 116 matches++; 117 } 118 } 119 return matches == uids.size(); 120 } 121 122 // If container is valid but it does not implement IRequiredInterfaces, anything goes 123 return container.operator bool(); 124} 125 126BASE_NS::vector<IContainer::Ptr> Object::FindAllContainers(const ContainerFindOptions& options) const 127{ 128 BASE_NS::vector<IContainer::Ptr> containers; 129 const auto maxCount = options.maxCount ? options.maxCount : std::numeric_limits<size_t>::max(); 130 const auto& uids = options.uids; 131 const auto addIfMatches = [&containers, &uids](const IContainer::Ptr& container) { 132 if (container) { 133 if (CheckRequiredInterfaces(container, uids)) { 134 containers.push_back(container); 135 } 136 } 137 }; 138 if (const auto me = GetSelf<IContainer>()) { 139 // This object is itself a container 140 addIfMatches(me); 141 } 142 if (containers.size() < maxCount) { 143 if (HasAttachments()) { 144 // Check the attachment container 145 addIfMatches(interface_pointer_cast<IContainer>(attachments_)); 146 // Check the attachments themselves 147 if (containers.size() < maxCount) { 148 IterateShared(attachments_, [&addIfMatches, &containers, &maxCount](const IObject::Ptr& object) { 149 addIfMatches(interface_pointer_cast<IContainer>(object)); 150 return containers.size() < maxCount; 151 }); 152 } 153 } else { 154 // No attachments, but the user has requested IAttachment so we need to create the container 155 if (uids.empty() || std::find(uids.begin(), uids.end(), IAttachment::UID) != uids.end()) { 156 ValidateAttachmentContainer(); 157 addIfMatches(interface_pointer_cast<IContainer>(attachments_)); 158 } 159 } 160 } 161 return containers; 162} 163 164const StaticObjectMetadata& Object::GetStaticMetadata() const 165{ 166 return GetStaticObjectMetadata(); 167} 168 169} // namespace Internal 170 171META_END_NAMESPACE() 172