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