xref: /openbmc/phosphor-buttons/inc/button_factory.hpp (revision ea47dd49799e74f082a0a1386efac9bdfd6aaba4)
1 #pragma once
2 
3 #include "button_config.hpp"
4 #include "button_interface.hpp"
5 #include "config.hpp"
6 
7 #include <phosphor-logging/elog-errors.hpp>
8 
9 #include <unordered_map>
10 
11 using buttonIfCreatorMethod = std::function<std::unique_ptr<ButtonIface>(
12     sdbusplus::bus_t& bus, EventPtr& event, ButtonConfig& buttonCfg)>;
13 
14 /**
15  * @brief This is abstract factory for the creating phosphor buttons objects
16  * based on the button  / formfactor type given.
17  */
18 
19 class ButtonFactory
20 {
21   public:
instance()22     static ButtonFactory& instance()
23     {
24         static ButtonFactory buttonFactoryObj;
25         return buttonFactoryObj;
26     }
27 
28     /**
29      * @brief this method creates a key and value pair element
30      * for the given button interface where key is the form factor
31      * name and the value is lambda method to return
32      * the instance of the button interface.
33      * This key value pair is stored in the Map buttonIfaceRegistry.
34      */
35 
36     template <typename T>
addToRegistry()37     void addToRegistry()
38     {
39         buttonIfaceRegistry[T::getFormFactorName()] =
40             [](sdbusplus::bus_t& bus, EventPtr& event,
41                ButtonConfig& buttonCfg) {
42                 return std::make_unique<T>(bus, T::getDbusObjectPath().c_str(),
43                                            event, buttonCfg);
44             };
45     }
46 
47     template <typename T>
addToRegistry(size_t index)48     void addToRegistry(size_t index)
49     {
50         auto indexStr = std::to_string(index);
51         buttonIfaceRegistry[T::getFormFactorName() + indexStr] =
52             [=](sdbusplus::bus_t& bus, EventPtr& event,
53                 ButtonConfig& buttonCfg) {
54                 return std::make_unique<T>(
55                     bus, (T::getDbusObjectPath() + indexStr).c_str(), event,
56                     buttonCfg);
57             };
58     }
59 
60     /**
61      * @brief this method returns the button interface object
62      *    corresponding to the button formfactor name provided
63      */
createInstance(const std::string & name,sdbusplus::bus_t & bus,EventPtr & event,ButtonConfig & buttonCfg)64     std::unique_ptr<ButtonIface> createInstance(
65         const std::string& name, sdbusplus::bus_t& bus, EventPtr& event,
66         ButtonConfig& buttonCfg)
67     {
68         // find matching name in the registry and call factory method.
69         auto objectIter = buttonIfaceRegistry.find(name);
70         if (objectIter != buttonIfaceRegistry.end())
71         {
72             return objectIter->second(bus, event, buttonCfg);
73         }
74         else
75         {
76             return nullptr;
77         }
78     }
79 
80   private:
81     // This map is the registry for keeping supported button interface types.
82     std::unordered_map<std::string, buttonIfCreatorMethod> buttonIfaceRegistry;
83 };
84 
85 template <class T>
86 class ButtonIFRegister
87 {
88   public:
ButtonIFRegister()89     ButtonIFRegister()
90     {
91         // register the class factory function
92         ButtonFactory::instance().addToRegistry<T>();
93     }
94 
ButtonIFRegister(size_t count)95     explicit ButtonIFRegister(size_t count)
96     {
97         // The JSON power button definitions only have an instance in
98         // their name if there is more than 1 chassis.
99         if (instances.size() > 1)
100         {
101             // register the class factory function
102             // The index, 'countIter', starts at 1 and increments,
103             // representing slot_1 through slot_N.
104             for (size_t countIter = 1; countIter <= count; countIter++)
105             {
106                 ButtonFactory::instance().addToRegistry<T>(countIter);
107             }
108         }
109         else
110         {
111             ButtonFactory::instance().addToRegistry<T>();
112         }
113     }
114 };
115