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 "flat_container.h" 168bf80f4bSopenharmony_ci 178bf80f4bSopenharmony_ci#include <algorithm> 188bf80f4bSopenharmony_ci 198bf80f4bSopenharmony_ci#include <base/math/mathf.h> 208bf80f4bSopenharmony_ci 218bf80f4bSopenharmony_ci#include <meta/api/internal/iteration.h> 228bf80f4bSopenharmony_ci#include <meta/base/interface_utils.h> 238bf80f4bSopenharmony_ci#include <meta/interface/intf_containable.h> 248bf80f4bSopenharmony_ci 258bf80f4bSopenharmony_ciMETA_BEGIN_NAMESPACE() 268bf80f4bSopenharmony_ci 278bf80f4bSopenharmony_ciIObject::Ptr FlatContainer::FindAny(const IContainer::FindOptions& options) const 288bf80f4bSopenharmony_ci{ 298bf80f4bSopenharmony_ci return ContainerBase::FindAnyImpl(options, true); 308bf80f4bSopenharmony_ci} 318bf80f4bSopenharmony_ci 328bf80f4bSopenharmony_ciBASE_NS::vector<IObject::Ptr> FlatContainer::FindAll(const IContainer::FindOptions& options) const 338bf80f4bSopenharmony_ci{ 348bf80f4bSopenharmony_ci return ContainerBase::FindAllImpl(options, true); 358bf80f4bSopenharmony_ci} 368bf80f4bSopenharmony_ci 378bf80f4bSopenharmony_cibool FlatContainer::Add(const IObject::Ptr& object) 388bf80f4bSopenharmony_ci{ 398bf80f4bSopenharmony_ci if (!object) { 408bf80f4bSopenharmony_ci return false; 418bf80f4bSopenharmony_ci } 428bf80f4bSopenharmony_ci const auto direct = !OnAdding()->HasHandlers(); 438bf80f4bSopenharmony_ci SizeType index = 0; 448bf80f4bSopenharmony_ci { 458bf80f4bSopenharmony_ci std::unique_lock lock(mutex_); 468bf80f4bSopenharmony_ci if (!IsCompatible(object)) { 478bf80f4bSopenharmony_ci return false; 488bf80f4bSopenharmony_ci } 498bf80f4bSopenharmony_ci index = children_.size(); 508bf80f4bSopenharmony_ci if (direct) { 518bf80f4bSopenharmony_ci children_.push_back(object); 528bf80f4bSopenharmony_ci } 538bf80f4bSopenharmony_ci } 548bf80f4bSopenharmony_ci bool success = true; 558bf80f4bSopenharmony_ci ChildChangedInfo info { object, index, parent_ }; 568bf80f4bSopenharmony_ci if (!direct) { 578bf80f4bSopenharmony_ci Invoke<IOnChildChanging>(OnAdding(), info, success); 588bf80f4bSopenharmony_ci if (success) { 598bf80f4bSopenharmony_ci std::unique_lock lock(mutex_); 608bf80f4bSopenharmony_ci children_.push_back(object); 618bf80f4bSopenharmony_ci } 628bf80f4bSopenharmony_ci } 638bf80f4bSopenharmony_ci // Calling external interface methods outside of our internal lock 648bf80f4bSopenharmony_ci if (success) { 658bf80f4bSopenharmony_ci SetObjectParent(object, interface_pointer_cast<IObject>(parent_)); 668bf80f4bSopenharmony_ci Invoke<IOnChildChanged>(OnAdded(), info); 678bf80f4bSopenharmony_ci } 688bf80f4bSopenharmony_ci return success; 698bf80f4bSopenharmony_ci} 708bf80f4bSopenharmony_ci 718bf80f4bSopenharmony_cibool FlatContainer::Insert(SizeType index, const IObject::Ptr& object) 728bf80f4bSopenharmony_ci{ 738bf80f4bSopenharmony_ci if (!object) { 748bf80f4bSopenharmony_ci return false; 758bf80f4bSopenharmony_ci } 768bf80f4bSopenharmony_ci const auto direct = !OnAdding()->HasHandlers(); 778bf80f4bSopenharmony_ci { 788bf80f4bSopenharmony_ci std::unique_lock lock(mutex_); 798bf80f4bSopenharmony_ci if (!IsCompatible(object)) { 808bf80f4bSopenharmony_ci return false; 818bf80f4bSopenharmony_ci } 828bf80f4bSopenharmony_ci index = BASE_NS::Math::min(index, children_.size()); 838bf80f4bSopenharmony_ci if (direct) { 848bf80f4bSopenharmony_ci children_.insert(children_.begin() + index, object); 858bf80f4bSopenharmony_ci } 868bf80f4bSopenharmony_ci } 878bf80f4bSopenharmony_ci bool success = true; 888bf80f4bSopenharmony_ci ChildChangedInfo info { object, index, parent_ }; 898bf80f4bSopenharmony_ci if (!direct) { 908bf80f4bSopenharmony_ci Invoke<IOnChildChanging>(OnAdding(), info, success); 918bf80f4bSopenharmony_ci if (success) { 928bf80f4bSopenharmony_ci std::unique_lock lock(mutex_); 938bf80f4bSopenharmony_ci children_.insert(children_.begin() + index, object); 948bf80f4bSopenharmony_ci } 958bf80f4bSopenharmony_ci } 968bf80f4bSopenharmony_ci // Calling external interface methods outside of our internal lock 978bf80f4bSopenharmony_ci if (success) { 988bf80f4bSopenharmony_ci SetObjectParent(object, interface_pointer_cast<IObject>(parent_)); 998bf80f4bSopenharmony_ci Invoke<IOnChildChanged>(OnAdded(), ChildChangedInfo { object, index, parent_ }); 1008bf80f4bSopenharmony_ci } 1018bf80f4bSopenharmony_ci return success; 1028bf80f4bSopenharmony_ci} 1038bf80f4bSopenharmony_ci 1048bf80f4bSopenharmony_cibool FlatContainer::Replace(const IObject::Ptr& child, const IObject::Ptr& replaceWith, bool addAlways) 1058bf80f4bSopenharmony_ci{ 1068bf80f4bSopenharmony_ci SizeType index = 0; 1078bf80f4bSopenharmony_ci IObject::Ptr added; 1088bf80f4bSopenharmony_ci IObject::Ptr removed; 1098bf80f4bSopenharmony_ci { 1108bf80f4bSopenharmony_ci std::unique_lock lock(mutex_); 1118bf80f4bSopenharmony_ci if (replaceWith && !IsCompatible(replaceWith)) { 1128bf80f4bSopenharmony_ci return false; 1138bf80f4bSopenharmony_ci } 1148bf80f4bSopenharmony_ci for (auto&& v : children_) { 1158bf80f4bSopenharmony_ci if (child == v) { 1168bf80f4bSopenharmony_ci break; 1178bf80f4bSopenharmony_ci } 1188bf80f4bSopenharmony_ci ++index; 1198bf80f4bSopenharmony_ci } 1208bf80f4bSopenharmony_ci if (index < children_.size()) { 1218bf80f4bSopenharmony_ci removed = children_[index]; 1228bf80f4bSopenharmony_ci if (removed == replaceWith) { 1238bf80f4bSopenharmony_ci return removed != nullptr; 1248bf80f4bSopenharmony_ci } 1258bf80f4bSopenharmony_ci if (replaceWith) { 1268bf80f4bSopenharmony_ci children_[index] = replaceWith; 1278bf80f4bSopenharmony_ci added = replaceWith; 1288bf80f4bSopenharmony_ci } else { 1298bf80f4bSopenharmony_ci children_.erase(children_.begin() + index); 1308bf80f4bSopenharmony_ci } 1318bf80f4bSopenharmony_ci } else if (addAlways && replaceWith) { 1328bf80f4bSopenharmony_ci children_.push_back(replaceWith); 1338bf80f4bSopenharmony_ci added = replaceWith; 1348bf80f4bSopenharmony_ci } 1358bf80f4bSopenharmony_ci } 1368bf80f4bSopenharmony_ci ChildChangedInfo addedInfo { added, index, parent_ }; 1378bf80f4bSopenharmony_ci ChildChangedInfo removedInfo { removed, index, parent_ }; 1388bf80f4bSopenharmony_ci bool success = true; 1398bf80f4bSopenharmony_ci if (removed) { 1408bf80f4bSopenharmony_ci Invoke<IOnChildChanging>(OnRemoving(), removedInfo, success); 1418bf80f4bSopenharmony_ci if (!success) { 1428bf80f4bSopenharmony_ci CORE_LOG_E("Failing a remove transaction during replace operation is not supported"); 1438bf80f4bSopenharmony_ci success = true; 1448bf80f4bSopenharmony_ci } 1458bf80f4bSopenharmony_ci } 1468bf80f4bSopenharmony_ci if (added) { 1478bf80f4bSopenharmony_ci Invoke<IOnChildChanging>(OnAdding(), addedInfo, success); 1488bf80f4bSopenharmony_ci if (!success) { 1498bf80f4bSopenharmony_ci CORE_LOG_E("Failing an add transaction during replace operation is not supported"); 1508bf80f4bSopenharmony_ci } 1518bf80f4bSopenharmony_ci } 1528bf80f4bSopenharmony_ci if (removed) { 1538bf80f4bSopenharmony_ci SetObjectParent(removed, nullptr); 1548bf80f4bSopenharmony_ci Invoke<IOnChildChanged>(OnRemoved(), removedInfo); 1558bf80f4bSopenharmony_ci } 1568bf80f4bSopenharmony_ci if (added) { 1578bf80f4bSopenharmony_ci SetObjectParent(added, interface_pointer_cast<IObject>(parent_)); 1588bf80f4bSopenharmony_ci Invoke<IOnChildChanged>(OnAdded(), addedInfo); 1598bf80f4bSopenharmony_ci } 1608bf80f4bSopenharmony_ci return added || removed; 1618bf80f4bSopenharmony_ci} 1628bf80f4bSopenharmony_ci 1638bf80f4bSopenharmony_civoid FlatContainer::SetObjectParent(const IObject::Ptr& object, const IObject::Ptr& parent) const 1648bf80f4bSopenharmony_ci{ 1658bf80f4bSopenharmony_ci const auto set = interface_cast<IMutableContainable>(object); 1668bf80f4bSopenharmony_ci if (!set) { 1678bf80f4bSopenharmony_ci // Object does not support setting a parent 1688bf80f4bSopenharmony_ci return; 1698bf80f4bSopenharmony_ci } 1708bf80f4bSopenharmony_ci if (const auto cont = interface_cast<IContainable>(object)) { 1718bf80f4bSopenharmony_ci // Remove from old parent (if any) 1728bf80f4bSopenharmony_ci if (const auto old = interface_pointer_cast<IContainer>(cont->GetParent())) { 1738bf80f4bSopenharmony_ci if (old == interface_pointer_cast<IContainer>(parent)) { 1748bf80f4bSopenharmony_ci // The object is already a child of the new parent container 1758bf80f4bSopenharmony_ci return; 1768bf80f4bSopenharmony_ci } 1778bf80f4bSopenharmony_ci old->Remove(object); 1788bf80f4bSopenharmony_ci } 1798bf80f4bSopenharmony_ci } 1808bf80f4bSopenharmony_ci if (!parent) { 1818bf80f4bSopenharmony_ci for (auto&& c : children_) { 1828bf80f4bSopenharmony_ci // we have another, don't remove the parent 1838bf80f4bSopenharmony_ci if (c == object) { 1848bf80f4bSopenharmony_ci return; 1858bf80f4bSopenharmony_ci } 1868bf80f4bSopenharmony_ci } 1878bf80f4bSopenharmony_ci } 1888bf80f4bSopenharmony_ci set->SetParent(parent); 1898bf80f4bSopenharmony_ci} 1908bf80f4bSopenharmony_ci 1918bf80f4bSopenharmony_ciMETA_END_NAMESPACE() 192