1 #pragma once
2 
3 #include "async_resp.hpp"
4 #include "dbus_utility.hpp"
5 #include "error_messages.hpp"
6 #include "http/utility.hpp"
7 #include "human_sort.hpp"
8 
9 #include <boost/url/url.hpp>
10 #include <nlohmann/json.hpp>
11 
12 #include <span>
13 #include <string>
14 #include <string_view>
15 #include <vector>
16 
17 namespace redfish
18 {
19 namespace collection_util
20 {
21 
22 /**
23  * @brief Populate the collection "Members" from a GetSubTreePaths search of
24  *        inventory
25  *
26  * @param[i,o] asyncResp  Async response object
27  * @param[i]   collectionPath  Redfish collection path which is used for the
28  *             Members Redfish Path
29  * @param[i]   interfaces  List of interfaces to constrain the GetSubTree search
30  * @param[in]  subtree     D-Bus base path to constrain search to.
31  *
32  * @return void
33  */
34 inline void
35     getCollectionMembers(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
36                          const boost::urls::url& collectionPath,
37                          std::span<const std::string_view> interfaces,
38                          const char* subtree = "/xyz/openbmc_project/inventory")
39 {
40     BMCWEB_LOG_DEBUG("Get collection members for: {}", collectionPath.buffer());
41     dbus::utility::getSubTreePaths(
42         subtree, 0, interfaces,
43         [collectionPath, asyncResp{std::move(asyncResp)}](
44             const boost::system::error_code& ec,
45             const dbus::utility::MapperGetSubTreePathsResponse& objects) {
46         if (ec == boost::system::errc::io_error)
47         {
48             asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
49             asyncResp->res.jsonValue["Members@odata.count"] = 0;
50             return;
51         }
52 
53         if (ec)
54         {
55             BMCWEB_LOG_DEBUG("DBUS response error {}", ec.value());
56             messages::internalError(asyncResp->res);
57             return;
58         }
59 
60         std::vector<std::string> pathNames;
61         for (const auto& object : objects)
62         {
63             sdbusplus::message::object_path path(object);
64             std::string leaf = path.filename();
65             if (leaf.empty())
66             {
67                 continue;
68             }
69             pathNames.push_back(leaf);
70         }
71         std::sort(pathNames.begin(), pathNames.end(),
72                   AlphanumLess<std::string>());
73 
74         nlohmann::json& members = asyncResp->res.jsonValue["Members"];
75         members = nlohmann::json::array();
76         for (const std::string& leaf : pathNames)
77         {
78             boost::urls::url url = collectionPath;
79             crow::utility::appendUrlPieces(url, leaf);
80             nlohmann::json::object_t member;
81             member["@odata.id"] = std::move(url);
82             members.emplace_back(std::move(member));
83         }
84         asyncResp->res.jsonValue["Members@odata.count"] = members.size();
85         });
86 }
87 
88 } // namespace collection_util
89 } // namespace redfish
90