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