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 "object.h"
16
17 #include <algorithm>
18 #include <limits>
19
20 #include <base/util/uid_util.h>
21 #include <core/plugin/intf_class_factory.h>
22
23 #include <meta/api/iteration.h>
24 #include <meta/interface/builtin_objects.h>
25 #include <meta/interface/intf_object_registry.h>
26 #include <meta/interface/intf_proxy_object.h>
27 #include <meta/interface/intf_required_interfaces.h>
28 #include <meta/interface/property/intf_property_internal.h>
29
30 #include "ref_uri_util.h"
31
32 META_BEGIN_NAMESPACE()
33 namespace Internal {
34
35 // ILifecycle
Build(const IMetadata::Ptr & data)36 bool Object::Build(const IMetadata::Ptr& data)
37 {
38 return Super::Build(data);
39 }
40
Destroy()41 void Object::Destroy()
42 {
43 if (attachments_) {
44 attachments_->RemoveAllAttachments();
45 attachments_.reset();
46 }
47 Super::Destroy();
48 }
49
50 // IAttach
Attach(const IObject::Ptr & attachment,const IObject::Ptr & dataContext)51 bool Object::Attach(const IObject::Ptr& attachment, const IObject::Ptr& dataContext)
52 {
53 ValidateAttachmentContainer();
54 if (attachments_) {
55 return attachments_->Attach(attachment, dataContext);
56 }
57 return false;
58 }
59
Detach(const IObject::Ptr & attachment)60 bool Object::Detach(const IObject::Ptr& attachment)
61 {
62 if (attachments_) {
63 return attachments_->Detach(attachment);
64 }
65 return false;
66 }
67
GetAttachments(const BASE_NS::vector<TypeId> & uids,bool strict) const68 BASE_NS::vector<IObject::Ptr> Object::GetAttachments(const BASE_NS::vector<TypeId>& uids, bool strict) const
69 {
70 if (attachments_) {
71 return attachments_->GetAttachments(uids, strict);
72 }
73 return {};
74 }
HasAttachments() const75 bool Object::HasAttachments() const
76 {
77 if (const auto container = interface_cast<IContainer>(attachments_)) {
78 return container->GetSize() > 0;
79 }
80 return false;
81 }
GetAttachmentContainer(bool initializeAlways) const82 IContainer::Ptr Object::GetAttachmentContainer(bool initializeAlways) const
83 {
84 if (initializeAlways) {
85 ValidateAttachmentContainer();
86 }
87 return interface_pointer_cast<IContainer>(attachments_);
88 }
89
ValidateAttachmentContainer() const90 void Object::ValidateAttachmentContainer() const
91 {
92 if (!attachments_) {
93 if (attachments_ =
94 META_NS::GetObjectRegistry().Create<META_NS::IAttachmentContainer>(ClassId::AttachmentContainer);
95 attachments_) {
96 attachments_->Initialize(GetSelf<META_NS::IAttach>());
97 } else {
98 CORE_LOG_E("Failed to create container for attachments");
99 }
100 }
101 }
102
CheckRequiredInterfaces(const IContainer::Ptr & container,const BASE_NS::vector<BASE_NS::Uid> & uids)103 bool CheckRequiredInterfaces(const IContainer::Ptr& container, const BASE_NS::vector<BASE_NS::Uid>& uids)
104 {
105 if (uids.empty()) {
106 return true;
107 }
108 if (auto req = interface_cast<IRequiredInterfaces>(container)) {
109 const auto reqs = req->GetRequiredInterfaces();
110 if (reqs.empty()) {
111 return true; // Container has no requirements related to the interfaces it accepts
112 }
113 size_t matches = 0;
114 for (const auto& uid : uids) {
115 if (std::find(reqs.begin(), reqs.end(), uid) != reqs.end()) {
116 matches++;
117 }
118 }
119 return matches == uids.size();
120 }
121
122 // If container is valid but it does not implement IRequiredInterfaces, anything goes
123 return container.operator bool();
124 }
125
FindAllContainers(const ContainerFindOptions & options) const126 BASE_NS::vector<IContainer::Ptr> Object::FindAllContainers(const ContainerFindOptions& options) const
127 {
128 BASE_NS::vector<IContainer::Ptr> containers;
129 const auto maxCount = options.maxCount ? options.maxCount : std::numeric_limits<size_t>::max();
130 const auto& uids = options.uids;
131 const auto addIfMatches = [&containers, &uids](const IContainer::Ptr& container) {
132 if (container) {
133 if (CheckRequiredInterfaces(container, uids)) {
134 containers.push_back(container);
135 }
136 }
137 };
138 if (const auto me = GetSelf<IContainer>()) {
139 // This object is itself a container
140 addIfMatches(me);
141 }
142 if (containers.size() < maxCount) {
143 if (HasAttachments()) {
144 // Check the attachment container
145 addIfMatches(interface_pointer_cast<IContainer>(attachments_));
146 // Check the attachments themselves
147 if (containers.size() < maxCount) {
148 IterateShared(attachments_, [&addIfMatches, &containers, &maxCount](const IObject::Ptr& object) {
149 addIfMatches(interface_pointer_cast<IContainer>(object));
150 return containers.size() < maxCount;
151 });
152 }
153 } else {
154 // No attachments, but the user has requested IAttachment so we need to create the container
155 if (uids.empty() || std::find(uids.begin(), uids.end(), IAttachment::UID) != uids.end()) {
156 ValidateAttachmentContainer();
157 addIfMatches(interface_pointer_cast<IContainer>(attachments_));
158 }
159 }
160 }
161 return containers;
162 }
163
GetStaticMetadata() const164 const StaticObjectMetadata& Object::GetStaticMetadata() const
165 {
166 return GetStaticObjectMetadata();
167 }
168
169 } // namespace Internal
170
171 META_END_NAMESPACE()
172