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] aResp  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> aResp,
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: "
41                      << collectionPath.buffer();
42     dbus::utility::getSubTreePaths(
43         subtree, 0, interfaces,
44         [collectionPath, aResp{std::move(aResp)}](
45             const boost::system::error_code& ec,
46             const dbus::utility::MapperGetSubTreePathsResponse& objects) {
47         if (ec == boost::system::errc::io_error)
48         {
49             aResp->res.jsonValue["Members"] = nlohmann::json::array();
50             aResp->res.jsonValue["Members@odata.count"] = 0;
51             return;
52         }
53 
54         if (ec)
55         {
56             BMCWEB_LOG_DEBUG << "DBUS response error " << ec.value();
57             messages::internalError(aResp->res);
58             return;
59         }
60 
61         std::vector<std::string> pathNames;
62         for (const auto& object : objects)
63         {
64             sdbusplus::message::object_path path(object);
65             std::string leaf = path.filename();
66             if (leaf.empty())
67             {
68                 continue;
69             }
70             pathNames.push_back(leaf);
71         }
72         std::sort(pathNames.begin(), pathNames.end(),
73                   AlphanumLess<std::string>());
74 
75         nlohmann::json& members = aResp->res.jsonValue["Members"];
76         members = nlohmann::json::array();
77         for (const std::string& leaf : pathNames)
78         {
79             boost::urls::url url = collectionPath;
80             crow::utility::appendUrlPieces(url, leaf);
81             nlohmann::json::object_t member;
82             member["@odata.id"] = std::move(url);
83             members.emplace_back(std::move(member));
84         }
85         aResp->res.jsonValue["Members@odata.count"] = members.size();
86         });
87 }
88 
89 } // namespace collection_util
90 } // namespace redfish
91