xref: /openbmc/bmcweb/features/redfish/include/redfishoemrule.hpp (revision c1a75ebc267a78853fb26a3da8c6b3388e6ee07c)
1*c1a75ebcSrohitpai #pragma once
2*c1a75ebcSrohitpai #include "async_resp.hpp"
3*c1a75ebcSrohitpai #include "http_request.hpp"
4*c1a75ebcSrohitpai 
5*c1a75ebcSrohitpai #include <nlohmann/json.hpp>
6*c1a75ebcSrohitpai 
7*c1a75ebcSrohitpai #include <functional>
8*c1a75ebcSrohitpai #include <memory>
9*c1a75ebcSrohitpai #include <stdexcept>
10*c1a75ebcSrohitpai #include <string>
11*c1a75ebcSrohitpai #include <string_view>
12*c1a75ebcSrohitpai #include <type_traits>
13*c1a75ebcSrohitpai #include <vector>
14*c1a75ebcSrohitpai 
15*c1a75ebcSrohitpai namespace redfish
16*c1a75ebcSrohitpai {
17*c1a75ebcSrohitpai class OemBaseRule
18*c1a75ebcSrohitpai {
19*c1a75ebcSrohitpai   public:
20*c1a75ebcSrohitpai     explicit OemBaseRule(std::string_view thisRule) : rule(thisRule) {}
21*c1a75ebcSrohitpai     virtual ~OemBaseRule() = default;
22*c1a75ebcSrohitpai     OemBaseRule(const OemBaseRule&) = delete;
23*c1a75ebcSrohitpai     OemBaseRule(OemBaseRule&&) = delete;
24*c1a75ebcSrohitpai     OemBaseRule& operator=(const OemBaseRule&) = delete;
25*c1a75ebcSrohitpai     OemBaseRule& operator=(const OemBaseRule&&) = delete;
26*c1a75ebcSrohitpai 
27*c1a75ebcSrohitpai     virtual void handle(const crow::Request& /*req*/,
28*c1a75ebcSrohitpai                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
29*c1a75ebcSrohitpai                         const std::vector<std::string>& /*params*/) = 0;
30*c1a75ebcSrohitpai     std::string rule;
31*c1a75ebcSrohitpai };
32*c1a75ebcSrohitpai 
33*c1a75ebcSrohitpai template <typename... Args>
34*c1a75ebcSrohitpai class OemRule : public OemBaseRule
35*c1a75ebcSrohitpai {
36*c1a75ebcSrohitpai   public:
37*c1a75ebcSrohitpai     using self_t = OemRule<Args...>;
38*c1a75ebcSrohitpai 
39*c1a75ebcSrohitpai     explicit OemRule(std::string_view ruleIn) : OemBaseRule(ruleIn) {}
40*c1a75ebcSrohitpai 
41*c1a75ebcSrohitpai     void validate()
42*c1a75ebcSrohitpai     {
43*c1a75ebcSrohitpai         if (!handler)
44*c1a75ebcSrohitpai         {
45*c1a75ebcSrohitpai             throw std::runtime_error(
46*c1a75ebcSrohitpai                 "no OEM fragment handler for the rule {}" + rule);
47*c1a75ebcSrohitpai         }
48*c1a75ebcSrohitpai     }
49*c1a75ebcSrohitpai 
50*c1a75ebcSrohitpai     template <typename Func>
51*c1a75ebcSrohitpai     void operator()(Func&& f)
52*c1a75ebcSrohitpai     {
53*c1a75ebcSrohitpai         static_assert(
54*c1a75ebcSrohitpai             std::is_invocable_v<Func, crow::Request,
55*c1a75ebcSrohitpai                                 std::shared_ptr<bmcweb::AsyncResp>&, Args...>,
56*c1a75ebcSrohitpai             "Handler type is mismatched with URL parameters");
57*c1a75ebcSrohitpai         static_assert(
58*c1a75ebcSrohitpai             std::is_same_v<
59*c1a75ebcSrohitpai                 void, std::invoke_result_t<Func, crow::Request,
60*c1a75ebcSrohitpai                                            std::shared_ptr<bmcweb::AsyncResp>&,
61*c1a75ebcSrohitpai                                            Args...>>,
62*c1a75ebcSrohitpai             "Handler function with response argument should have void return type");
63*c1a75ebcSrohitpai 
64*c1a75ebcSrohitpai         handler = std::forward<Func>(f);
65*c1a75ebcSrohitpai     }
66*c1a75ebcSrohitpai 
67*c1a75ebcSrohitpai     void handle(const crow::Request& req,
68*c1a75ebcSrohitpai                 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
69*c1a75ebcSrohitpai                 const std::vector<std::string>& params) override
70*c1a75ebcSrohitpai     {
71*c1a75ebcSrohitpai         if constexpr (sizeof...(Args) == 0)
72*c1a75ebcSrohitpai         {
73*c1a75ebcSrohitpai             handler(req, asyncResp);
74*c1a75ebcSrohitpai         }
75*c1a75ebcSrohitpai         else if constexpr (sizeof...(Args) == 1)
76*c1a75ebcSrohitpai         {
77*c1a75ebcSrohitpai             handler(req, asyncResp, params[0]);
78*c1a75ebcSrohitpai         }
79*c1a75ebcSrohitpai         else if constexpr (sizeof...(Args) == 2)
80*c1a75ebcSrohitpai         {
81*c1a75ebcSrohitpai             handler(req, asyncResp, params[0], params[1]);
82*c1a75ebcSrohitpai         }
83*c1a75ebcSrohitpai         else if constexpr (sizeof...(Args) == 3)
84*c1a75ebcSrohitpai         {
85*c1a75ebcSrohitpai             handler(req, asyncResp, params[0], params[1], params[2]);
86*c1a75ebcSrohitpai         }
87*c1a75ebcSrohitpai         else if constexpr (sizeof...(Args) == 4)
88*c1a75ebcSrohitpai         {
89*c1a75ebcSrohitpai             handler(req, asyncResp, params[0], params[1], params[2], params[3]);
90*c1a75ebcSrohitpai         }
91*c1a75ebcSrohitpai         else if constexpr (sizeof...(Args) == 5)
92*c1a75ebcSrohitpai         {
93*c1a75ebcSrohitpai             handler(req, asyncResp, params[0], params[1], params[2], params[3],
94*c1a75ebcSrohitpai                     params[4]);
95*c1a75ebcSrohitpai         }
96*c1a75ebcSrohitpai         static_assert(sizeof...(Args) <= 5, "More args than are supported");
97*c1a75ebcSrohitpai     }
98*c1a75ebcSrohitpai 
99*c1a75ebcSrohitpai   private:
100*c1a75ebcSrohitpai     std::function<void(const crow::Request&,
101*c1a75ebcSrohitpai                        const std::shared_ptr<bmcweb::AsyncResp>&, Args...)>
102*c1a75ebcSrohitpai         handler;
103*c1a75ebcSrohitpai };
104*c1a75ebcSrohitpai } // namespace redfish
105