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 "attachment_container.h" 168bf80f4bSopenharmony_ci 178bf80f4bSopenharmony_ci#include <meta/api/make_callback.h> 188bf80f4bSopenharmony_ci#include <meta/api/util.h> 198bf80f4bSopenharmony_ci 208bf80f4bSopenharmony_ciMETA_BEGIN_NAMESPACE() 218bf80f4bSopenharmony_ci 228bf80f4bSopenharmony_ciAttachmentContainer::AttachmentContainer() = default; 238bf80f4bSopenharmony_ci 248bf80f4bSopenharmony_ciAttachmentContainer::~AttachmentContainer() 258bf80f4bSopenharmony_ci{ 268bf80f4bSopenharmony_ci RemoveAllAttachments(); 278bf80f4bSopenharmony_ci} 288bf80f4bSopenharmony_ci 298bf80f4bSopenharmony_civoid AttachmentContainer::SetSuperInstance(const IObject::Ptr& aggr, const IObject::Ptr& super) 308bf80f4bSopenharmony_ci{ 318bf80f4bSopenharmony_ci Super::SetSuperInstance(aggr, super); 328bf80f4bSopenharmony_ci transaction_ = interface_cast<IContainerPreTransaction>(super); 338bf80f4bSopenharmony_ci CORE_ASSERT(transaction_); 348bf80f4bSopenharmony_ci} 358bf80f4bSopenharmony_ci 368bf80f4bSopenharmony_cibool AttachmentContainer::Build(const IMetadata::Ptr& data) 378bf80f4bSopenharmony_ci{ 388bf80f4bSopenharmony_ci // Always set null as the parent of all our attachments 398bf80f4bSopenharmony_ci ObjectContainerFwd::SetProxyParent({}); 408bf80f4bSopenharmony_ci 418bf80f4bSopenharmony_ci OnRemoved()->AddHandler(MakeCallback<IOnChildChanged>(this, &AttachmentContainer::RemovedFromContainer)); 428bf80f4bSopenharmony_ci OnAdding()->AddHandler(MakeCallback<IOnChildChanging>(this, &AttachmentContainer::AddingToContainer)); 438bf80f4bSopenharmony_ci return true; 448bf80f4bSopenharmony_ci} 458bf80f4bSopenharmony_ci 468bf80f4bSopenharmony_cibool AttachmentContainer::Add(const IObject::Ptr& object) 478bf80f4bSopenharmony_ci{ 488bf80f4bSopenharmony_ci return Attach(N_POS, object, {}); 498bf80f4bSopenharmony_ci} 508bf80f4bSopenharmony_ci 518bf80f4bSopenharmony_cibool AttachmentContainer::Insert(IContainer::SizeType index, const IObject::Ptr& object) 528bf80f4bSopenharmony_ci{ 538bf80f4bSopenharmony_ci return Attach(index, object, {}); 548bf80f4bSopenharmony_ci} 558bf80f4bSopenharmony_ci 568bf80f4bSopenharmony_cibool AttachmentContainer::Remove(IContainer::SizeType index) 578bf80f4bSopenharmony_ci{ 588bf80f4bSopenharmony_ci return Remove(GetAt(index)); 598bf80f4bSopenharmony_ci} 608bf80f4bSopenharmony_ci 618bf80f4bSopenharmony_cibool AttachmentContainer::Remove(const IObject::Ptr& child) 628bf80f4bSopenharmony_ci{ 638bf80f4bSopenharmony_ci return Detach(child); 648bf80f4bSopenharmony_ci} 658bf80f4bSopenharmony_ci 668bf80f4bSopenharmony_cibool AttachmentContainer::Replace(const IObject::Ptr& child, const IObject::Ptr& replaceWith, bool addAlways) 678bf80f4bSopenharmony_ci{ 688bf80f4bSopenharmony_ci const auto owner = owner_.lock(); 698bf80f4bSopenharmony_ci if (child && AlreadyAttached(replaceWith)) { 708bf80f4bSopenharmony_ci return true; 718bf80f4bSopenharmony_ci } 728bf80f4bSopenharmony_ci return ObjectContainerFwd::Replace(child, replaceWith, addAlways); 738bf80f4bSopenharmony_ci} 748bf80f4bSopenharmony_ci 758bf80f4bSopenharmony_civoid AttachmentContainer::RemoveAll() 768bf80f4bSopenharmony_ci{ 778bf80f4bSopenharmony_ci RemoveAllAttachments(); 788bf80f4bSopenharmony_ci} 798bf80f4bSopenharmony_ci 808bf80f4bSopenharmony_cibool AttachmentContainer::SetRequiredInterfaces(const BASE_NS::vector<TypeId>& interfaces) 818bf80f4bSopenharmony_ci{ 828bf80f4bSopenharmony_ci CORE_LOG_E("Setting the required interfaces of an attachment container is not allowed."); 838bf80f4bSopenharmony_ci return false; 848bf80f4bSopenharmony_ci} 858bf80f4bSopenharmony_ci 868bf80f4bSopenharmony_cibool AttachmentContainer::Initialize(const META_NS::IAttach::Ptr& owner) 878bf80f4bSopenharmony_ci{ 888bf80f4bSopenharmony_ci if (!owner) { 898bf80f4bSopenharmony_ci return false; 908bf80f4bSopenharmony_ci } 918bf80f4bSopenharmony_ci owner_ = owner; 928bf80f4bSopenharmony_ci return true; 938bf80f4bSopenharmony_ci} 948bf80f4bSopenharmony_ci 958bf80f4bSopenharmony_cibool AttachmentContainer::Attach(const IObject::Ptr& attachment, const IObject::Ptr& dataContext) 968bf80f4bSopenharmony_ci{ 978bf80f4bSopenharmony_ci return Attach(N_POS, attachment, dataContext); 988bf80f4bSopenharmony_ci} 998bf80f4bSopenharmony_ci 1008bf80f4bSopenharmony_cibool AttachmentContainer::Attach( 1018bf80f4bSopenharmony_ci IContainer::SizeType pos, const IObject::Ptr& attachment, const IObject::Ptr& dataContext) 1028bf80f4bSopenharmony_ci{ 1038bf80f4bSopenharmony_ci const auto object = interface_pointer_cast<IObject>(attachment); 1048bf80f4bSopenharmony_ci if (!object) { 1058bf80f4bSopenharmony_ci return false; 1068bf80f4bSopenharmony_ci } 1078bf80f4bSopenharmony_ci bool result = false; 1088bf80f4bSopenharmony_ci if (const auto owner = owner_.lock()) { 1098bf80f4bSopenharmony_ci // If attachment is attached to something, detach it 1108bf80f4bSopenharmony_ci if (const auto att = interface_cast<IAttachment>(attachment)) { 1118bf80f4bSopenharmony_ci if (const auto current = GetValue(att->AttachedTo()).lock()) { 1128bf80f4bSopenharmony_ci if (current == owner) { 1138bf80f4bSopenharmony_ci // Already attached to this 1148bf80f4bSopenharmony_ci return true; 1158bf80f4bSopenharmony_ci } 1168bf80f4bSopenharmony_ci if (!current->Detach(attachment)) { 1178bf80f4bSopenharmony_ci return false; 1188bf80f4bSopenharmony_ci } 1198bf80f4bSopenharmony_ci } 1208bf80f4bSopenharmony_ci } 1218bf80f4bSopenharmony_ci // If no data context given, use this as the data context 1228bf80f4bSopenharmony_ci const auto context = dataContext ? dataContext : interface_pointer_cast<IObject>(owner); 1238bf80f4bSopenharmony_ci addingContexts_.emplace_back(BASE_NS::pair<IObject*, IObject::WeakPtr> { attachment.get(), context }); 1248bf80f4bSopenharmony_ci result = ObjectContainerFwd::Insert(pos, object); 1258bf80f4bSopenharmony_ci if (!result) { 1268bf80f4bSopenharmony_ci addingContexts_.pop_back(); 1278bf80f4bSopenharmony_ci } 1288bf80f4bSopenharmony_ci } 1298bf80f4bSopenharmony_ci return result; 1308bf80f4bSopenharmony_ci} 1318bf80f4bSopenharmony_ci 1328bf80f4bSopenharmony_cibool AttachmentContainer::Detach(const IObject::Ptr& attachment) 1338bf80f4bSopenharmony_ci{ 1348bf80f4bSopenharmony_ci if (!attachment) { 1358bf80f4bSopenharmony_ci return false; 1368bf80f4bSopenharmony_ci } 1378bf80f4bSopenharmony_ci if (const auto owner = owner_.lock()) { 1388bf80f4bSopenharmony_ci if (const auto att = interface_cast<IAttachment>(attachment)) { 1398bf80f4bSopenharmony_ci const auto current = GetValue(att->AttachedTo()).lock(); 1408bf80f4bSopenharmony_ci if (current != owner) { 1418bf80f4bSopenharmony_ci return false; 1428bf80f4bSopenharmony_ci } 1438bf80f4bSopenharmony_ci } 1448bf80f4bSopenharmony_ci return ObjectContainerFwd::Remove(attachment); 1458bf80f4bSopenharmony_ci } 1468bf80f4bSopenharmony_ci return false; 1478bf80f4bSopenharmony_ci} 1488bf80f4bSopenharmony_ci 1498bf80f4bSopenharmony_civoid AttachmentContainer::AddingToContainer(const ChildChangedInfo& info, bool& success) 1508bf80f4bSopenharmony_ci{ 1518bf80f4bSopenharmony_ci if (const auto owner = owner_.lock()) { 1528bf80f4bSopenharmony_ci if (auto object = info.object) { 1538bf80f4bSopenharmony_ci IObject::Ptr context; 1548bf80f4bSopenharmony_ci for (auto it = addingContexts_.begin(); it != addingContexts_.end(); it++) { 1558bf80f4bSopenharmony_ci if (it->first == object.get()) { 1568bf80f4bSopenharmony_ci context = it->second.lock(); 1578bf80f4bSopenharmony_ci addingContexts_.erase(it); 1588bf80f4bSopenharmony_ci break; 1598bf80f4bSopenharmony_ci } 1608bf80f4bSopenharmony_ci } 1618bf80f4bSopenharmony_ci if (auto attachment = interface_pointer_cast<IAttachment>(info.object)) { 1628bf80f4bSopenharmony_ci if (GetValue(attachment->AttachedTo()).lock() == owner) { 1638bf80f4bSopenharmony_ci // Already attached to this 1648bf80f4bSopenharmony_ci return; 1658bf80f4bSopenharmony_ci } 1668bf80f4bSopenharmony_ci if (!attachment->Attaching(owner, context)) { 1678bf80f4bSopenharmony_ci success = false; 1688bf80f4bSopenharmony_ci } 1698bf80f4bSopenharmony_ci } else { 1708bf80f4bSopenharmony_ci success = true; 1718bf80f4bSopenharmony_ci } 1728bf80f4bSopenharmony_ci } 1738bf80f4bSopenharmony_ci } 1748bf80f4bSopenharmony_ci} 1758bf80f4bSopenharmony_civoid AttachmentContainer::RemovedFromContainer(const ChildChangedInfo& info) 1768bf80f4bSopenharmony_ci{ 1778bf80f4bSopenharmony_ci if (const auto owner = owner_.lock()) { 1788bf80f4bSopenharmony_ci if (auto attachment = interface_pointer_cast<IAttachment>(info.object)) { 1798bf80f4bSopenharmony_ci attachment->Detaching(owner); 1808bf80f4bSopenharmony_ci } 1818bf80f4bSopenharmony_ci } 1828bf80f4bSopenharmony_ci} 1838bf80f4bSopenharmony_ci 1848bf80f4bSopenharmony_ciBASE_NS::vector<IObject::Ptr> AttachmentContainer::GetAttachments(const BASE_NS::vector<TypeId>& uids, bool strict) 1858bf80f4bSopenharmony_ci{ 1868bf80f4bSopenharmony_ci return ObjectContainerFwd::FindAll({ "", TraversalType::NO_HIERARCHY, uids, strict }); 1878bf80f4bSopenharmony_ci} 1888bf80f4bSopenharmony_ci 1898bf80f4bSopenharmony_civoid AttachmentContainer::RemoveAllAttachments() 1908bf80f4bSopenharmony_ci{ 1918bf80f4bSopenharmony_ci const auto owner = owner_.lock(); 1928bf80f4bSopenharmony_ci const auto all = ObjectContainerFwd::GetAll(); 1938bf80f4bSopenharmony_ci for (const auto& object : all) { 1948bf80f4bSopenharmony_ci if (auto att = interface_cast<IAttachment>(object)) { 1958bf80f4bSopenharmony_ci // Ignore result 1968bf80f4bSopenharmony_ci att->Detaching(owner); 1978bf80f4bSopenharmony_ci } 1988bf80f4bSopenharmony_ci } 1998bf80f4bSopenharmony_ci ObjectContainerFwd::RemoveAll(); 2008bf80f4bSopenharmony_ci} 2018bf80f4bSopenharmony_ci 2028bf80f4bSopenharmony_ciIObject::Ptr AttachmentContainer::FindByName(const BASE_NS::string& name) const 2038bf80f4bSopenharmony_ci{ 2048bf80f4bSopenharmony_ci return ObjectContainerFwd::FindByName(name); 2058bf80f4bSopenharmony_ci} 2068bf80f4bSopenharmony_ci 2078bf80f4bSopenharmony_cibool AttachmentContainer::AlreadyAttached(const IObject::Ptr& object) 2088bf80f4bSopenharmony_ci{ 2098bf80f4bSopenharmony_ci if (const auto attachment = interface_pointer_cast<IAttachment>(object)) { 2108bf80f4bSopenharmony_ci if (const auto owner = owner_.lock(); attachment && owner) { 2118bf80f4bSopenharmony_ci if (const auto current = GetValue(attachment->AttachedTo()).lock()) { 2128bf80f4bSopenharmony_ci if (current == owner) { 2138bf80f4bSopenharmony_ci // Already attached to this 2148bf80f4bSopenharmony_ci return true; 2158bf80f4bSopenharmony_ci } 2168bf80f4bSopenharmony_ci } 2178bf80f4bSopenharmony_ci } 2188bf80f4bSopenharmony_ci } else { 2198bf80f4bSopenharmony_ci return META_NS::ContainsObject(GetSelf<IContainer>(), object); 2208bf80f4bSopenharmony_ci } 2218bf80f4bSopenharmony_ci return false; 2228bf80f4bSopenharmony_ci} 2238bf80f4bSopenharmony_ci 2248bf80f4bSopenharmony_ciMETA_END_NAMESPACE() 225