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 #ifndef META_API_CONTAINER_FIND_CONTAINERS_H
17 #define META_API_CONTAINER_FIND_CONTAINERS_H
18
19 #include <meta/api/iteration.h>
20 #include <meta/interface/intf_attach.h>
21 #include <meta/interface/intf_container_query.h>
22 #include <meta/interface/intf_required_interfaces.h>
23
META_BEGIN_NAMESPACE()24 META_BEGIN_NAMESPACE()
25
26 inline bool CheckRequiredContainerInterfaces(const IContainer::Ptr& container, const BASE_NS::vector<BASE_NS::Uid>& ids)
27 {
28 if (ids.empty()) {
29 return true;
30 }
31 if (auto req = interface_cast<IRequiredInterfaces>(container)) {
32 const auto reqs = req->GetRequiredInterfaces();
33 if (reqs.empty()) {
34 return true; // Container has no requirements related to the interfaces it accepts
35 }
36 size_t matches = 0;
37 for (const auto& req : reqs) {
38 for (const auto& uid : ids) {
39 if (req == uid) {
40 ++matches;
41 break;
42 }
43 }
44 }
45 return matches == ids.size();
46 }
47
48 // If container is valid but it does not implement IRequiredInterfaces, anything goes
49 return container.operator bool();
50 }
51
52 inline BASE_NS::vector<IContainer::Ptr> FindAllContainers(
53 const IObject::Ptr& obj, const IContainerQuery::ContainerFindOptions& options = {})
54 {
55 BASE_NS::vector<IContainer::Ptr> containers;
56 const auto maxCount = options.maxCount ? options.maxCount : size_t(-1);
57 const auto& uids = options.uids;
58 const auto addIfMatches = [&containers, &uids](const IContainer::Ptr& container) {
59 if (container) {
60 if (CheckRequiredContainerInterfaces(container, uids)) {
61 containers.push_back(container);
62 }
63 }
64 };
65 if (const auto me = interface_pointer_cast<IContainer>(obj)) {
66 // This object is itself a container
67 addIfMatches(me);
68 }
69 if (containers.size() < maxCount) {
70 if (auto att = interface_pointer_cast<IAttach>(obj)) {
71 // Check the attachment container
72 auto attCont = att->GetAttachmentContainer();
73 addIfMatches(attCont);
74 // Check the attachments themselves
75 if (containers.size() < maxCount) {
76 IterateShared(attCont, [&addIfMatches, &containers, &maxCount](const IObject::Ptr& object) {
77 addIfMatches(interface_pointer_cast<IContainer>(object));
78 return containers.size() < maxCount;
79 });
80 }
81 }
82 }
83 return containers;
84 }
85
86 META_END_NAMESPACE()
87
88 #endif
89