• 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 
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