140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3116bcc5cSGunnar Mills #pragma once 4116bcc5cSGunnar Mills 53ccb3adbSEd Tanous #include "async_resp.hpp" 67a1dbc48SGeorge Liu #include "dbus_utility.hpp" 73ccb3adbSEd Tanous #include "error_messages.hpp" 83ccb3adbSEd Tanous #include "http/utility.hpp" 93ccb3adbSEd Tanous #include "human_sort.hpp" 10*d7857201SEd Tanous #include "logging.hpp" 117a1dbc48SGeorge Liu 123ccb3adbSEd Tanous #include <boost/url/url.hpp> 133ccb3adbSEd Tanous #include <nlohmann/json.hpp> 14*d7857201SEd Tanous #include <sdbusplus/message/native_types.hpp> 15116bcc5cSGunnar Mills 16*d7857201SEd Tanous #include <algorithm> 17*d7857201SEd Tanous #include <functional> 18*d7857201SEd Tanous #include <memory> 193544d2a7SEd Tanous #include <ranges> 207a1dbc48SGeorge Liu #include <span> 21116bcc5cSGunnar Mills #include <string> 227a1dbc48SGeorge Liu #include <string_view> 23*d7857201SEd Tanous #include <utility> 24116bcc5cSGunnar Mills #include <vector> 25116bcc5cSGunnar Mills 26116bcc5cSGunnar Mills namespace redfish 27116bcc5cSGunnar Mills { 28116bcc5cSGunnar Mills namespace collection_util 29116bcc5cSGunnar Mills { 30116bcc5cSGunnar Mills 3136b5f1edSLakshmi Yadlapati inline void handleCollectionMembers( 3236b5f1edSLakshmi Yadlapati const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 3370c4d545SLakshmi Yadlapati const boost::urls::url& collectionPath, 3470c4d545SLakshmi Yadlapati const nlohmann::json::json_pointer& jsonKeyName, 3570c4d545SLakshmi Yadlapati const boost::system::error_code& ec, 3636b5f1edSLakshmi Yadlapati const dbus::utility::MapperGetSubTreePathsResponse& objects) 37116bcc5cSGunnar Mills { 381aa375b8SEd Tanous if (jsonKeyName.empty()) 391aa375b8SEd Tanous { 401aa375b8SEd Tanous messages::internalError(asyncResp->res); 411aa375b8SEd Tanous BMCWEB_LOG_ERROR("Json Key called empty. Did you mean /Members?"); 421aa375b8SEd Tanous return; 431aa375b8SEd Tanous } 4470c4d545SLakshmi Yadlapati nlohmann::json::json_pointer jsonCountKeyName = jsonKeyName; 4570c4d545SLakshmi Yadlapati std::string back = jsonCountKeyName.back(); 4670c4d545SLakshmi Yadlapati jsonCountKeyName.pop_back(); 47c48377dbSMyung Bae jsonCountKeyName /= back + "@odata.count"; 4870c4d545SLakshmi Yadlapati 4927ea7db1SEd Tanous if (ec == boost::system::errc::io_error) 5027ea7db1SEd Tanous { 5170c4d545SLakshmi Yadlapati asyncResp->res.jsonValue[jsonKeyName] = nlohmann::json::array(); 5270c4d545SLakshmi Yadlapati asyncResp->res.jsonValue[jsonCountKeyName] = 0; 5327ea7db1SEd Tanous return; 5427ea7db1SEd Tanous } 5527ea7db1SEd Tanous 56116bcc5cSGunnar Mills if (ec) 57116bcc5cSGunnar Mills { 5862598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error {}", ec.value()); 59ac106bf6SEd Tanous messages::internalError(asyncResp->res); 60116bcc5cSGunnar Mills return; 61116bcc5cSGunnar Mills } 62116bcc5cSGunnar Mills 6392409d0eSEd Tanous std::vector<std::string> pathNames; 64dea43dd4SJonathan Doman for (const auto& object : objects) 65116bcc5cSGunnar Mills { 662dfd18efSEd Tanous sdbusplus::message::object_path path(object); 672dfd18efSEd Tanous std::string leaf = path.filename(); 682dfd18efSEd Tanous if (leaf.empty()) 69116bcc5cSGunnar Mills { 702dfd18efSEd Tanous continue; 71116bcc5cSGunnar Mills } 7292409d0eSEd Tanous pathNames.push_back(leaf); 7392409d0eSEd Tanous } 743544d2a7SEd Tanous std::ranges::sort(pathNames, AlphanumLess<std::string>()); 7592409d0eSEd Tanous 7670c4d545SLakshmi Yadlapati nlohmann::json& members = asyncResp->res.jsonValue[jsonKeyName]; 7792409d0eSEd Tanous members = nlohmann::json::array(); 7892409d0eSEd Tanous for (const std::string& leaf : pathNames) 7992409d0eSEd Tanous { 80ae9031f0SWilly Tu boost::urls::url url = collectionPath; 81ae9031f0SWilly Tu crow::utility::appendUrlPieces(url, leaf); 821476687dSEd Tanous nlohmann::json::object_t member; 83ae9031f0SWilly Tu member["@odata.id"] = std::move(url); 84b2ba3072SPatrick Williams members.emplace_back(std::move(member)); 85116bcc5cSGunnar Mills } 8670c4d545SLakshmi Yadlapati asyncResp->res.jsonValue[jsonCountKeyName] = members.size(); 8736b5f1edSLakshmi Yadlapati } 8836b5f1edSLakshmi Yadlapati 8936b5f1edSLakshmi Yadlapati /** 9070c4d545SLakshmi Yadlapati * @brief Populate the collection members from a GetSubTreePaths search of 9136b5f1edSLakshmi Yadlapati * inventory 9236b5f1edSLakshmi Yadlapati * 9336b5f1edSLakshmi Yadlapati * @param[i,o] asyncResp Async response object 9436b5f1edSLakshmi Yadlapati * @param[i] collectionPath Redfish collection path which is used for the 9536b5f1edSLakshmi Yadlapati * Members Redfish Path 9636b5f1edSLakshmi Yadlapati * @param[i] interfaces List of interfaces to constrain the GetSubTree search 9736b5f1edSLakshmi Yadlapati * @param[in] subtree D-Bus base path to constrain search to. 9870c4d545SLakshmi Yadlapati * @param[in] jsonKeyName Key name in which the collection members will be 9970c4d545SLakshmi Yadlapati * stored. 10036b5f1edSLakshmi Yadlapati * 10136b5f1edSLakshmi Yadlapati * @return void 10236b5f1edSLakshmi Yadlapati */ 103bd79bce8SPatrick Williams inline void getCollectionToKey( 104bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 10570c4d545SLakshmi Yadlapati const boost::urls::url& collectionPath, 106bd79bce8SPatrick Williams std::span<const std::string_view> interfaces, const std::string& subtree, 10770c4d545SLakshmi Yadlapati const nlohmann::json::json_pointer& jsonKeyName) 10870c4d545SLakshmi Yadlapati { 10970c4d545SLakshmi Yadlapati BMCWEB_LOG_DEBUG("Get collection members for: {}", collectionPath.buffer()); 110bd79bce8SPatrick Williams dbus::utility::getSubTreePaths( 111bd79bce8SPatrick Williams subtree, 0, interfaces, 112bd79bce8SPatrick Williams std::bind_front(handleCollectionMembers, asyncResp, collectionPath, 11370c4d545SLakshmi Yadlapati jsonKeyName)); 11470c4d545SLakshmi Yadlapati } 115bd79bce8SPatrick Williams inline void getCollectionMembers( 116bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 11736b5f1edSLakshmi Yadlapati const boost::urls::url& collectionPath, 118bd79bce8SPatrick Williams std::span<const std::string_view> interfaces, const std::string& subtree) 11936b5f1edSLakshmi Yadlapati { 12070c4d545SLakshmi Yadlapati getCollectionToKey(asyncResp, collectionPath, interfaces, subtree, 12170c4d545SLakshmi Yadlapati nlohmann::json::json_pointer("/Members")); 122116bcc5cSGunnar Mills } 123116bcc5cSGunnar Mills 124116bcc5cSGunnar Mills } // namespace collection_util 125116bcc5cSGunnar Mills } // namespace redfish 126