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