xref: /openbmc/bmcweb/features/redfish/include/utils/collection.hpp (revision 36b5f1ed97fe5806c53e0eb5b2f9a07e9a8acd5f)
1116bcc5cSGunnar Mills #pragma once
2116bcc5cSGunnar Mills 
33ccb3adbSEd Tanous #include "async_resp.hpp"
47a1dbc48SGeorge Liu #include "dbus_utility.hpp"
53ccb3adbSEd Tanous #include "error_messages.hpp"
63ccb3adbSEd Tanous #include "http/utility.hpp"
73ccb3adbSEd Tanous #include "human_sort.hpp"
87a1dbc48SGeorge Liu 
93ccb3adbSEd Tanous #include <boost/url/url.hpp>
103ccb3adbSEd Tanous #include <nlohmann/json.hpp>
11116bcc5cSGunnar Mills 
123544d2a7SEd Tanous #include <ranges>
137a1dbc48SGeorge Liu #include <span>
14116bcc5cSGunnar Mills #include <string>
157a1dbc48SGeorge Liu #include <string_view>
16116bcc5cSGunnar Mills #include <vector>
17116bcc5cSGunnar Mills 
18116bcc5cSGunnar Mills namespace redfish
19116bcc5cSGunnar Mills {
20116bcc5cSGunnar Mills namespace collection_util
21116bcc5cSGunnar Mills {
22116bcc5cSGunnar Mills 
23*36b5f1edSLakshmi Yadlapati inline void handleCollectionMembers(
24*36b5f1edSLakshmi Yadlapati     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
25*36b5f1edSLakshmi Yadlapati     const boost::urls::url& collectionPath, const boost::system::error_code& ec,
26*36b5f1edSLakshmi Yadlapati     const dbus::utility::MapperGetSubTreePathsResponse& objects)
27116bcc5cSGunnar Mills {
2827ea7db1SEd Tanous     if (ec == boost::system::errc::io_error)
2927ea7db1SEd Tanous     {
30ac106bf6SEd Tanous         asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
31ac106bf6SEd Tanous         asyncResp->res.jsonValue["Members@odata.count"] = 0;
3227ea7db1SEd Tanous         return;
3327ea7db1SEd Tanous     }
3427ea7db1SEd Tanous 
35116bcc5cSGunnar Mills     if (ec)
36116bcc5cSGunnar Mills     {
3762598e31SEd Tanous         BMCWEB_LOG_DEBUG("DBUS response error {}", ec.value());
38ac106bf6SEd Tanous         messages::internalError(asyncResp->res);
39116bcc5cSGunnar Mills         return;
40116bcc5cSGunnar Mills     }
41116bcc5cSGunnar Mills 
4292409d0eSEd Tanous     std::vector<std::string> pathNames;
43dea43dd4SJonathan Doman     for (const auto& object : objects)
44116bcc5cSGunnar Mills     {
452dfd18efSEd Tanous         sdbusplus::message::object_path path(object);
462dfd18efSEd Tanous         std::string leaf = path.filename();
472dfd18efSEd Tanous         if (leaf.empty())
48116bcc5cSGunnar Mills         {
492dfd18efSEd Tanous             continue;
50116bcc5cSGunnar Mills         }
5192409d0eSEd Tanous         pathNames.push_back(leaf);
5292409d0eSEd Tanous     }
533544d2a7SEd Tanous     std::ranges::sort(pathNames, AlphanumLess<std::string>());
5492409d0eSEd Tanous 
55ac106bf6SEd Tanous     nlohmann::json& members = asyncResp->res.jsonValue["Members"];
5692409d0eSEd Tanous     members = nlohmann::json::array();
5792409d0eSEd Tanous     for (const std::string& leaf : pathNames)
5892409d0eSEd Tanous     {
59ae9031f0SWilly Tu         boost::urls::url url = collectionPath;
60ae9031f0SWilly Tu         crow::utility::appendUrlPieces(url, leaf);
611476687dSEd Tanous         nlohmann::json::object_t member;
62ae9031f0SWilly Tu         member["@odata.id"] = std::move(url);
63b2ba3072SPatrick Williams         members.emplace_back(std::move(member));
64116bcc5cSGunnar Mills     }
65ac106bf6SEd Tanous     asyncResp->res.jsonValue["Members@odata.count"] = members.size();
66*36b5f1edSLakshmi Yadlapati }
67*36b5f1edSLakshmi Yadlapati 
68*36b5f1edSLakshmi Yadlapati /**
69*36b5f1edSLakshmi Yadlapati  * @brief Populate the collection "Members" from a GetSubTreePaths search of
70*36b5f1edSLakshmi Yadlapati  *        inventory
71*36b5f1edSLakshmi Yadlapati  *
72*36b5f1edSLakshmi Yadlapati  * @param[i,o] asyncResp  Async response object
73*36b5f1edSLakshmi Yadlapati  * @param[i]   collectionPath  Redfish collection path which is used for the
74*36b5f1edSLakshmi Yadlapati  *             Members Redfish Path
75*36b5f1edSLakshmi Yadlapati  * @param[i]   interfaces  List of interfaces to constrain the GetSubTree search
76*36b5f1edSLakshmi Yadlapati  * @param[in]  subtree     D-Bus base path to constrain search to.
77*36b5f1edSLakshmi Yadlapati  *
78*36b5f1edSLakshmi Yadlapati  * @return void
79*36b5f1edSLakshmi Yadlapati  */
80*36b5f1edSLakshmi Yadlapati inline void
81*36b5f1edSLakshmi Yadlapati     getCollectionMembers(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
82*36b5f1edSLakshmi Yadlapati                          const boost::urls::url& collectionPath,
83*36b5f1edSLakshmi Yadlapati                          std::span<const std::string_view> interfaces,
84*36b5f1edSLakshmi Yadlapati                          const std::string& subtree)
85*36b5f1edSLakshmi Yadlapati {
86*36b5f1edSLakshmi Yadlapati     BMCWEB_LOG_DEBUG("Get collection members for: {}", collectionPath.buffer());
87*36b5f1edSLakshmi Yadlapati     dbus::utility::getSubTreePaths(
88*36b5f1edSLakshmi Yadlapati         subtree, 0, interfaces,
89*36b5f1edSLakshmi Yadlapati         std::bind_front(handleCollectionMembers, asyncResp, collectionPath));
90116bcc5cSGunnar Mills }
91116bcc5cSGunnar Mills 
92116bcc5cSGunnar Mills } // namespace collection_util
93116bcc5cSGunnar Mills } // namespace redfish
94