• 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_INTERNAL_NAMESPACE()20 META_BEGIN_INTERNAL_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 (i->Attaching(owner, dataContext)) {
135                 result = Super::Insert(pos, attachment);
136                 if (!result) {
137                     i->Detaching(owner);
138                 }
139             }
140         } else {
141             result = Super::Insert(pos, attachment);
142         }
143     }
144     return result;
145 }
146 
Detach(const IObject::Ptr & attachment)147 bool AttachmentContainer::Detach(const IObject::Ptr& attachment)
148 {
149     if (!attachment) {
150         return false;
151     }
152     if (const auto owner = owner_.lock()) {
153         bool res = Super::Remove(attachment);
154         if (res) {
155             if (auto i = interface_pointer_cast<IAttachable>(attachment)) {
156                 i->Detaching(owner);
157             }
158         }
159         return res;
160     }
161     return false;
162 }
163 
GetAttachments(const BASE_NS::vector<TypeId> & uids,bool strict)164 BASE_NS::vector<IObject::Ptr> AttachmentContainer::GetAttachments(const BASE_NS::vector<TypeId>& uids, bool strict)
165 {
166     return Super::FindAll({ "", TraversalType::NO_HIERARCHY, uids, strict });
167 }
168 
RemoveAllAttachments()169 void AttachmentContainer::RemoveAllAttachments()
170 {
171     const auto owner = owner_.lock();
172     const auto all = Super::GetAll();
173     for (const auto& object : all) {
174         if (auto att = interface_cast<IAttachable>(object)) {
175             // Ignore result
176             att->Detaching(owner);
177         }
178     }
179     Super::RemoveAll();
180 }
181 
FindByName(const BASE_NS::string & name) const182 IObject::Ptr AttachmentContainer::FindByName(const BASE_NS::string& name) const
183 {
184     return ContainerBase::FindByName(name);
185 }
186 
AlreadyAttached(const IObject::Ptr & object)187 bool AttachmentContainer::AlreadyAttached(const IObject::Ptr& object)
188 {
189     if (const auto attachment = interface_pointer_cast<IAttachment>(object)) {
190         if (const auto owner = owner_.lock(); attachment && owner) {
191             if (const auto current = GetValue(attachment->AttachedTo()).lock()) {
192                 if (current == owner) {
193                     // Already attached to this
194                     return true;
195                 }
196             }
197         }
198     } else {
199         BASE_NS::shared_ptr<IContainer> self(this, [](auto) {});
200         return META_NS::ContainsObject(self, object);
201     }
202     return false;
203 }
204 
205 META_END_INTERNAL_NAMESPACE()
206