• 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 #include "attachment_container.h"
16 
17 #include <meta/api/make_callback.h>
18 #include <meta/api/util.h>
19 
META_BEGIN_NAMESPACE()20 META_BEGIN_NAMESPACE()
21 
22 AttachmentContainer::AttachmentContainer()
23 {
24     Super::SetImplementingIContainer(nullptr, this);
25 }
26 
~AttachmentContainer()27 AttachmentContainer::~AttachmentContainer()
28 {
29     RemoveAllAttachments();
30 }
31 
Add(const IObject::Ptr & object)32 bool AttachmentContainer::Add(const IObject::Ptr& object)
33 {
34     return Attach(N_POS, object, {});
35 }
36 
Insert(IContainer::SizeType index,const IObject::Ptr & object)37 bool AttachmentContainer::Insert(IContainer::SizeType index, const IObject::Ptr& object)
38 {
39     return Attach(index, object, {});
40 }
41 
Remove(IContainer::SizeType index)42 bool AttachmentContainer::Remove(IContainer::SizeType index)
43 {
44     return Remove(GetAt(index));
45 }
46 
Remove(const IObject::Ptr & child)47 bool AttachmentContainer::Remove(const IObject::Ptr& child)
48 {
49     return Detach(child);
50 }
51 
Replace(const IObject::Ptr & child,const IObject::Ptr & replaceWith,bool addAlways)52 bool AttachmentContainer::Replace(const IObject::Ptr& child, const IObject::Ptr& replaceWith, bool addAlways)
53 {
54     const auto owner = owner_.lock();
55     if (child && AlreadyAttached(replaceWith)) {
56         return true;
57     }
58 
59     if (auto i = interface_pointer_cast<IAttachable>(replaceWith)) {
60         if (!i->Attaching(owner, nullptr)) {
61             return false;
62         }
63     }
64 
65     bool res = Super::Replace(child, replaceWith, addAlways);
66     if (res) {
67         if (auto i = interface_pointer_cast<IAttachable>(child)) {
68             i->Detaching(owner);
69         }
70     } else {
71         if (auto i = interface_pointer_cast<IAttachable>(replaceWith)) {
72             i->Detaching(owner);
73         }
74     }
75     return res;
76 }
77 
RemoveAll()78 void AttachmentContainer::RemoveAll()
79 {
80     RemoveAllAttachments();
81 }
82 
SetRequiredInterfaces(const BASE_NS::vector<TypeId> & interfaces)83 bool AttachmentContainer::SetRequiredInterfaces(const BASE_NS::vector<TypeId>& interfaces)
84 {
85     CORE_LOG_E("Setting the required interfaces of an attachment container is not allowed.");
86     return false;
87 }
88 
Initialize(const META_NS::IAttach::Ptr & owner)89 bool AttachmentContainer::Initialize(const META_NS::IAttach::Ptr& owner)
90 {
91     if (!owner) {
92         return false;
93     }
94     owner_ = owner;
95     return true;
96 }
97 
Attach(const IObject::Ptr & attachment,const IObject::Ptr & dataContext)98 bool AttachmentContainer::Attach(const IObject::Ptr& attachment, const IObject::Ptr& dataContext)
99 {
100     return Attach(N_POS, attachment, dataContext);
101 }
102 
DetachFromOld(const IAttach::Ptr & me,const IObject::Ptr & attachment,bool & mine)103 bool AttachmentContainer::DetachFromOld(const IAttach::Ptr& me, const IObject::Ptr& attachment, bool& mine)
104 {
105     // If attachment is attached to something, detach it
106     if (const auto att = interface_cast<IAttachment>(attachment)) {
107         if (const auto current = GetValue(att->AttachedTo()).lock()) {
108             mine = current == me;
109             if (!mine) {
110                 return current->Detach(attachment);
111             }
112         }
113     }
114     return true;
115 }
116 
Attach(IContainer::SizeType pos,const IObject::Ptr & attachment,const IObject::Ptr & dataContext)117 bool AttachmentContainer::Attach(
118     IContainer::SizeType pos, const IObject::Ptr& attachment, const IObject::Ptr& dataContext)
119 {
120     if (!attachment) {
121         return false;
122     }
123     bool result = false;
124     if (const auto owner = owner_.lock()) {
125         // If attachment is attached to something, detach it
126         bool mine = false;
127         if (!DetachFromOld(owner, attachment, mine)) {
128             return false;
129         }
130         if (mine) {
131             return true;
132         }
133         if (auto i = interface_pointer_cast<IAttachable>(attachment)) {
134             // If no data context given, use this as the data context
135             const auto context = dataContext ? dataContext : interface_pointer_cast<IObject>(owner);
136             if (i->Attaching(owner, context)) {
137                 result = Super::Insert(pos, attachment);
138                 if (!result) {
139                     i->Detaching(owner);
140                 }
141             }
142         } else {
143             result = Super::Insert(pos, attachment);
144         }
145     }
146     return result;
147 }
148 
Detach(const IObject::Ptr & attachment)149 bool AttachmentContainer::Detach(const IObject::Ptr& attachment)
150 {
151     if (!attachment) {
152         return false;
153     }
154     if (const auto owner = owner_.lock()) {
155         bool res = Super::Remove(attachment);
156         if (res) {
157             if (auto i = interface_pointer_cast<IAttachable>(attachment)) {
158                 i->Detaching(owner);
159             }
160         }
161         return res;
162     }
163     return false;
164 }
165 
GetAttachments(const BASE_NS::vector<TypeId> & uids,bool strict)166 BASE_NS::vector<IObject::Ptr> AttachmentContainer::GetAttachments(const BASE_NS::vector<TypeId>& uids, bool strict)
167 {
168     return Super::FindAll({ "", TraversalType::NO_HIERARCHY, uids, strict });
169 }
170 
RemoveAllAttachments()171 void AttachmentContainer::RemoveAllAttachments()
172 {
173     const auto owner = owner_.lock();
174     const auto all = Super::GetAll();
175     for (const auto& object : all) {
176         if (auto att = interface_cast<IAttachable>(object)) {
177             // Ignore result
178             att->Detaching(owner);
179         }
180     }
181     Super::RemoveAll();
182 }
183 
FindByName(const BASE_NS::string & name) const184 IObject::Ptr AttachmentContainer::FindByName(const BASE_NS::string& name) const
185 {
186     return ContainerBase::FindByName(name);
187 }
188 
AlreadyAttached(const IObject::Ptr & object)189 bool AttachmentContainer::AlreadyAttached(const IObject::Ptr& object)
190 {
191     if (const auto attachment = interface_pointer_cast<IAttachment>(object)) {
192         if (const auto owner = owner_.lock(); attachment && owner) {
193             if (const auto current = GetValue(attachment->AttachedTo()).lock()) {
194                 if (current == owner) {
195                     // Already attached to this
196                     return true;
197                 }
198             }
199         }
200     } else {
201         BASE_NS::shared_ptr<IContainer> self(this, [](auto) {});
202         return META_NS::ContainsObject(self, object);
203     }
204     return false;
205 }
206 
207 META_END_NAMESPACE()
208