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