• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include "flat_container.h"
17 
18 #include <algorithm>
19 #include <mutex>
20 
21 #include <base/math/mathf.h>
22 
23 #include <meta/api/internal/iteration.h>
24 #include <meta/base/interface_utils.h>
25 #include <meta/interface/intf_containable.h>
26 
META_BEGIN_NAMESPACE()27 META_BEGIN_NAMESPACE()
28 
29 IObject::Ptr FlatContainer::FindAny(const IContainer::FindOptions& options) const
30 {
31     return ContainerBase::FindAnyImpl(options, true);
32 }
33 
FindAll(const IContainer::FindOptions & options) const34 BASE_NS::vector<IObject::Ptr> FlatContainer::FindAll(const IContainer::FindOptions& options) const
35 {
36     return ContainerBase::FindAllImpl(options, true);
37 }
38 
Add(const META_NS::IObject::Ptr & object)39 bool FlatContainer::Add(const META_NS::IObject::Ptr& object)
40 {
41     return Insert(-1, object);
42 }
43 
Insert(SizeType index,const IObject::Ptr & object)44 bool FlatContainer::Insert(SizeType index, const IObject::Ptr& object)
45 {
46     if (!object) {
47         return false;
48     }
49     {
50         std::unique_lock lock(mutex_);
51         if (!IsCompatible(object)) {
52             return false;
53         }
54         index = BASE_NS::Math::min(index, children_.size());
55         children_.insert(children_.begin() + index, object);
56     }
57     ChildChangedInfo info { ContainerChangeType::ADDED, object, parent_, size_t(-1), index };
58     SetObjectParent(object, interface_pointer_cast<IObject>(parent_));
59     Invoke<IOnChildChanged>(EventOnContainerChanged(MetadataQuery::EXISTING), info);
60     return true;
61 }
62 
Replace(const IObject::Ptr & child,const IObject::Ptr & replaceWith,bool addAlways)63 bool FlatContainer::Replace(const IObject::Ptr& child, const IObject::Ptr& replaceWith, bool addAlways)
64 {
65     SizeType index = 0;
66     IObject::Ptr added;
67     IObject::Ptr removed;
68     {
69         std::unique_lock lock(mutex_);
70         if (replaceWith && !IsCompatible(replaceWith)) {
71             return false;
72         }
73         auto it = children_.begin();
74         for (; it != children_.end() && *it != child; ++it, ++index) {
75         }
76         if (it != children_.end()) {
77             removed = *it;
78             if (removed == replaceWith) {
79                 return removed != nullptr;
80             }
81             if (replaceWith) {
82                 *it = replaceWith;
83                 added = replaceWith;
84             } else {
85                 children_.erase(it);
86             }
87         } else if (addAlways && replaceWith) {
88             children_.push_back(replaceWith);
89             added = replaceWith;
90         }
91     }
92     ChildChangedInfo addedInfo { ContainerChangeType::ADDED, added, parent_, size_t(-1), index };
93     ChildChangedInfo removedInfo { ContainerChangeType::REMOVED, removed, parent_, index };
94     if (removed) {
95         SetObjectParent(removed, nullptr);
96         Invoke<IOnChildChanged>(EventOnContainerChanged(MetadataQuery::EXISTING), removedInfo);
97     }
98     if (added) {
99         SetObjectParent(added, interface_pointer_cast<IObject>(parent_));
100         Invoke<IOnChildChanged>(EventOnContainerChanged(MetadataQuery::EXISTING), addedInfo);
101     }
102     return added || removed;
103 }
104 
SetObjectParent(const IObject::Ptr & object,const IObject::Ptr & parent) const105 void FlatContainer::SetObjectParent(const IObject::Ptr& object, const IObject::Ptr& parent) const
106 {
107     const auto set = interface_cast<IMutableContainable>(object);
108     if (!set) {
109         // Object does not support setting a parent
110         return;
111     }
112     if (const auto cont = interface_cast<IContainable>(object)) {
113         // Remove from old parent (if any)
114         if (const auto old = interface_pointer_cast<IContainer>(cont->GetParent())) {
115             if (old == interface_pointer_cast<IContainer>(parent)) {
116                 // The object is already a child of the new parent container
117                 return;
118             }
119             old->Remove(object);
120         }
121     }
122     if (!parent) {
123         for (auto&& c : children_) {
124             // we have another, don't remove the parent
125             if (c == object) {
126                 return;
127             }
128         }
129     }
130     set->SetParent(parent);
131 }
132 
EventOnContainerChanged(MetadataQuery q) const133 BASE_NS::shared_ptr<IEvent> FlatContainer::EventOnContainerChanged(MetadataQuery q) const
134 {
135     std::unique_lock lock(this->mutex_);
136     if (!onChanged_ && q == MetadataQuery::CONSTRUCT_ON_REQUEST) {
137         onChanged_ = { CreateShared<EventImpl<IOnChildChanged>>("OnContainerChanged") };
138     }
139     return onChanged_;
140 }
141 
142 META_END_NAMESPACE()
143