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 
handleCollectionMembers(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const boost::urls::url & collectionPath,const nlohmann::json::json_pointer & jsonKeyName,const boost::system::error_code & ec,const dbus::utility::MapperGetSubTreePathsResponse & objects)2336b5f1edSLakshmi Yadlapati inline void handleCollectionMembers(
2436b5f1edSLakshmi Yadlapati     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2570c4d545SLakshmi Yadlapati     const boost::urls::url& collectionPath,
2670c4d545SLakshmi Yadlapati     const nlohmann::json::json_pointer& jsonKeyName,
2770c4d545SLakshmi Yadlapati     const boost::system::error_code& ec,
2836b5f1edSLakshmi Yadlapati     const dbus::utility::MapperGetSubTreePathsResponse& objects)
29116bcc5cSGunnar Mills {
30*1aa375b8SEd Tanous     if (jsonKeyName.empty())
31*1aa375b8SEd Tanous     {
32*1aa375b8SEd Tanous         messages::internalError(asyncResp->res);
33*1aa375b8SEd Tanous         BMCWEB_LOG_ERROR("Json Key called empty.  Did you mean /Members?");
34*1aa375b8SEd Tanous         return;
35*1aa375b8SEd Tanous     }
3670c4d545SLakshmi Yadlapati     nlohmann::json::json_pointer jsonCountKeyName = jsonKeyName;
3770c4d545SLakshmi Yadlapati     std::string back = jsonCountKeyName.back();
3870c4d545SLakshmi Yadlapati     jsonCountKeyName.pop_back();
39c48377dbSMyung Bae     jsonCountKeyName /= back + "@odata.count";
4070c4d545SLakshmi Yadlapati 
4127ea7db1SEd Tanous     if (ec == boost::system::errc::io_error)
4227ea7db1SEd Tanous     {
4370c4d545SLakshmi Yadlapati         asyncResp->res.jsonValue[jsonKeyName] = nlohmann::json::array();
4470c4d545SLakshmi Yadlapati         asyncResp->res.jsonValue[jsonCountKeyName] = 0;
4527ea7db1SEd Tanous         return;
4627ea7db1SEd Tanous     }
4727ea7db1SEd Tanous 
48116bcc5cSGunnar Mills     if (ec)
49116bcc5cSGunnar Mills     {
5062598e31SEd Tanous         BMCWEB_LOG_DEBUG("DBUS response error {}", ec.value());
51ac106bf6SEd Tanous         messages::internalError(asyncResp->res);
52116bcc5cSGunnar Mills         return;
53116bcc5cSGunnar Mills     }
54116bcc5cSGunnar Mills 
5592409d0eSEd Tanous     std::vector<std::string> pathNames;
56dea43dd4SJonathan Doman     for (const auto& object : objects)
57116bcc5cSGunnar Mills     {
582dfd18efSEd Tanous         sdbusplus::message::object_path path(object);
592dfd18efSEd Tanous         std::string leaf = path.filename();
602dfd18efSEd Tanous         if (leaf.empty())
61116bcc5cSGunnar Mills         {
622dfd18efSEd Tanous             continue;
63116bcc5cSGunnar Mills         }
6492409d0eSEd Tanous         pathNames.push_back(leaf);
6592409d0eSEd Tanous     }
663544d2a7SEd Tanous     std::ranges::sort(pathNames, AlphanumLess<std::string>());
6792409d0eSEd Tanous 
6870c4d545SLakshmi Yadlapati     nlohmann::json& members = asyncResp->res.jsonValue[jsonKeyName];
6992409d0eSEd Tanous     members = nlohmann::json::array();
7092409d0eSEd Tanous     for (const std::string& leaf : pathNames)
7192409d0eSEd Tanous     {
72ae9031f0SWilly Tu         boost::urls::url url = collectionPath;
73ae9031f0SWilly Tu         crow::utility::appendUrlPieces(url, leaf);
741476687dSEd Tanous         nlohmann::json::object_t member;
75ae9031f0SWilly Tu         member["@odata.id"] = std::move(url);
76b2ba3072SPatrick Williams         members.emplace_back(std::move(member));
77116bcc5cSGunnar Mills     }
7870c4d545SLakshmi Yadlapati     asyncResp->res.jsonValue[jsonCountKeyName] = members.size();
7936b5f1edSLakshmi Yadlapati }
8036b5f1edSLakshmi Yadlapati 
8136b5f1edSLakshmi Yadlapati /**
8270c4d545SLakshmi Yadlapati  * @brief Populate the collection members from a GetSubTreePaths search of
8336b5f1edSLakshmi Yadlapati  *        inventory
8436b5f1edSLakshmi Yadlapati  *
8536b5f1edSLakshmi Yadlapati  * @param[i,o] asyncResp  Async response object
8636b5f1edSLakshmi Yadlapati  * @param[i]   collectionPath  Redfish collection path which is used for the
8736b5f1edSLakshmi Yadlapati  *             Members Redfish Path
8836b5f1edSLakshmi Yadlapati  * @param[i]   interfaces  List of interfaces to constrain the GetSubTree search
8936b5f1edSLakshmi Yadlapati  * @param[in]  subtree     D-Bus base path to constrain search to.
9070c4d545SLakshmi Yadlapati  * @param[in]  jsonKeyName Key name in which the collection members will be
9170c4d545SLakshmi Yadlapati  *             stored.
9236b5f1edSLakshmi Yadlapati  *
9336b5f1edSLakshmi Yadlapati  * @return void
9436b5f1edSLakshmi Yadlapati  */
9536b5f1edSLakshmi Yadlapati inline void
getCollectionToKey(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const boost::urls::url & collectionPath,std::span<const std::string_view> interfaces,const std::string & subtree,const nlohmann::json::json_pointer & jsonKeyName)9670c4d545SLakshmi Yadlapati     getCollectionToKey(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
9770c4d545SLakshmi Yadlapati                        const boost::urls::url& collectionPath,
9870c4d545SLakshmi Yadlapati                        std::span<const std::string_view> interfaces,
9970c4d545SLakshmi Yadlapati                        const std::string& subtree,
10070c4d545SLakshmi Yadlapati                        const nlohmann::json::json_pointer& jsonKeyName)
10170c4d545SLakshmi Yadlapati {
10270c4d545SLakshmi Yadlapati     BMCWEB_LOG_DEBUG("Get collection members for: {}", collectionPath.buffer());
10370c4d545SLakshmi Yadlapati     dbus::utility::getSubTreePaths(subtree, 0, interfaces,
10470c4d545SLakshmi Yadlapati                                    std::bind_front(handleCollectionMembers,
10570c4d545SLakshmi Yadlapati                                                    asyncResp, collectionPath,
10670c4d545SLakshmi Yadlapati                                                    jsonKeyName));
10770c4d545SLakshmi Yadlapati }
10870c4d545SLakshmi Yadlapati inline void
getCollectionMembers(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const boost::urls::url & collectionPath,std::span<const std::string_view> interfaces,const std::string & subtree)10936b5f1edSLakshmi Yadlapati     getCollectionMembers(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
11036b5f1edSLakshmi Yadlapati                          const boost::urls::url& collectionPath,
11136b5f1edSLakshmi Yadlapati                          std::span<const std::string_view> interfaces,
11236b5f1edSLakshmi Yadlapati                          const std::string& subtree)
11336b5f1edSLakshmi Yadlapati {
11470c4d545SLakshmi Yadlapati     getCollectionToKey(asyncResp, collectionPath, interfaces, subtree,
11570c4d545SLakshmi Yadlapati                        nlohmann::json::json_pointer("/Members"));
116116bcc5cSGunnar Mills }
117116bcc5cSGunnar Mills 
118116bcc5cSGunnar Mills } // namespace collection_util
119116bcc5cSGunnar Mills } // namespace redfish
120