control: Add creating config object without a dbus object

For those configuration objects that do not need a dbus object, create
them using a similar method without requiring a dbus object to be given.
Updated each object to correctly reflect their current need of a dbus
object which was driven by moving the creation of the available group
objects to within the event.

Change-Id: I8ce4ea7baf4cfd1ad86268b760a334fcf0a4f25e
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/json/event.cpp b/control/json/event.cpp
index e7a7bfb..94f860c 100644
--- a/control/json/event.cpp
+++ b/control/json/event.cpp
@@ -15,6 +15,9 @@
  */
 #include "event.hpp"
 
+#include "group.hpp"
+#include "json_parser.hpp"
+
 #include <nlohmann/json.hpp>
 #include <phosphor-logging/log.hpp>
 #include <sdbusplus/bus.hpp>
@@ -25,8 +28,11 @@
 using json = nlohmann::json;
 using namespace phosphor::logging;
 
+const std::map<configKey, std::unique_ptr<Group>> Event::_availGrps =
+    getConfig<Group>(true);
+
 Event::Event(sdbusplus::bus::bus& bus, const json& jsonObj) :
-    ConfigBase(jsonObj)
+    ConfigBase(jsonObj), _bus(bus)
 {
     if (jsonObj.contains("profiles"))
     {
diff --git a/control/json/event.hpp b/control/json/event.hpp
index 5230fbb..3bc41ae 100644
--- a/control/json/event.hpp
+++ b/control/json/event.hpp
@@ -16,6 +16,8 @@
 #pragma once
 
 #include "config_base.hpp"
+#include "group.hpp"
+#include "json_parser.hpp"
 #include "types.hpp"
 
 #include <nlohmann/json.hpp>
@@ -111,6 +113,12 @@
     }
 
   private:
+    /* Mapping of available group names & profiles to their group object */
+    static const std::map<configKey, std::unique_ptr<Group>> _availGrps;
+
+    /* The sdbusplus bus object */
+    sdbusplus::bus::bus& _bus;
+
     /* A precondition the event has in order to be enabled */
     Precondition _precond;
 
diff --git a/control/json/group.cpp b/control/json/group.cpp
index a022338..f193ef7 100644
--- a/control/json/group.cpp
+++ b/control/json/group.cpp
@@ -17,7 +17,6 @@
 
 #include <nlohmann/json.hpp>
 #include <phosphor-logging/log.hpp>
-#include <sdbusplus/bus.hpp>
 
 namespace phosphor::fan::control::json
 {
@@ -25,8 +24,7 @@
 using json = nlohmann::json;
 using namespace phosphor::logging;
 
-Group::Group(sdbusplus::bus::bus& bus, const json& jsonObj) :
-    ConfigBase(jsonObj), _service("")
+Group::Group(const json& jsonObj) : ConfigBase(jsonObj), _service("")
 {
     if (jsonObj.contains("profiles"))
     {
diff --git a/control/json/group.hpp b/control/json/group.hpp
index 7cc84e9..e8d607f 100644
--- a/control/json/group.hpp
+++ b/control/json/group.hpp
@@ -18,7 +18,6 @@
 #include "config_base.hpp"
 
 #include <nlohmann/json.hpp>
-#include <sdbusplus/bus.hpp>
 
 namespace phosphor::fan::control::json
 {
@@ -56,10 +55,9 @@
      * Constructor
      * Parses and populates a configuration group from JSON object data
      *
-     * @param[in] bus - sdbusplus bus object
      * @param[in] jsonObj - JSON object
      */
-    Group(sdbusplus::bus::bus& bus, const json& jsonObj);
+    Group(const json& jsonObj);
 
     /**
      * @brief Get the members
diff --git a/control/json/profile.cpp b/control/json/profile.cpp
index 696716e..0778820 100644
--- a/control/json/profile.cpp
+++ b/control/json/profile.cpp
@@ -19,7 +19,6 @@
 
 #include <nlohmann/json.hpp>
 #include <phosphor-logging/log.hpp>
-#include <sdbusplus/bus.hpp>
 
 #include <algorithm>
 #include <iterator>
@@ -35,8 +34,7 @@
 const std::map<std::string, methodHandler> Profile::_methods = {
     {"all_of", Profile::allOf}};
 
-Profile::Profile(sdbusplus::bus::bus& bus, const json& jsonObj) :
-    ConfigBase(jsonObj), _bus(bus), _active(false)
+Profile::Profile(const json& jsonObj) : ConfigBase(jsonObj), _active(false)
 {
     setActive(jsonObj);
 }
diff --git a/control/json/profile.hpp b/control/json/profile.hpp
index eacb1dc..dd0aed0 100644
--- a/control/json/profile.hpp
+++ b/control/json/profile.hpp
@@ -18,7 +18,6 @@
 #include "config_base.hpp"
 
 #include <nlohmann/json.hpp>
-#include <sdbusplus/bus.hpp>
 
 namespace phosphor::fan::control::json
 {
@@ -57,7 +56,7 @@
      * @param[in] bus - sdbusplus bus object
      * @param[in] jsonObj - JSON object
      */
-    Profile(sdbusplus::bus::bus& bus, const json& jsonObj);
+    Profile(const json& jsonObj);
 
     /**
      * @brief Get the active state
@@ -70,9 +69,6 @@
     }
 
   private:
-    /* The sdbusplus bus object */
-    sdbusplus::bus::bus& _bus;
-
     /* Active state of the profile */
     bool _active;
 
diff --git a/control/json/zone.cpp b/control/json/zone.cpp
index 33ab048..dd0dbfb 100644
--- a/control/json/zone.cpp
+++ b/control/json/zone.cpp
@@ -22,7 +22,6 @@
 
 #include <nlohmann/json.hpp>
 #include <phosphor-logging/log.hpp>
-#include <sdbusplus/bus.hpp>
 
 #include <iterator>
 #include <map>
@@ -41,8 +40,7 @@
                                 {{supportedProp, zone::property::supported},
                                  {currentProp, zone::property::current}}}};
 
-Zone::Zone(sdbusplus::bus::bus& bus, const json& jsonObj) :
-    ConfigBase(jsonObj), _incDelay(0)
+Zone::Zone(const json& jsonObj) : ConfigBase(jsonObj), _incDelay(0)
 {
     if (jsonObj.contains("profiles"))
     {
diff --git a/control/json/zone.hpp b/control/json/zone.hpp
index 4f7742c..09c1dac 100644
--- a/control/json/zone.hpp
+++ b/control/json/zone.hpp
@@ -19,7 +19,6 @@
 #include "types.hpp"
 
 #include <nlohmann/json.hpp>
-#include <sdbusplus/bus.hpp>
 
 #include <any>
 #include <functional>
@@ -68,10 +67,9 @@
      * Constructor
      * Parses and populates a zone from JSON object data
      *
-     * @param[in] bus - sdbusplus bus object
      * @param[in] jsonObj - JSON object
      */
-    Zone(sdbusplus::bus::bus& bus, const json& jsonObj);
+    Zone(const json& jsonObj);
 
     /**
      * @brief Get the full speed
diff --git a/control/json_parser.cpp b/control/json_parser.cpp
index de7bc26..b69bab1 100644
--- a/control/json_parser.cpp
+++ b/control/json_parser.cpp
@@ -64,18 +64,13 @@
     std::vector<ZoneGroup> zoneGrps;
 
     // Profiles are optional
-    auto profiles = getConfig<json::Profile>(bus, true);
+    auto profiles = getConfig<json::Profile>(true);
     // Fans to be controlled
     auto fans = getConfig<json::Fan>(bus);
     // Zones within the system
-    auto zones = getConfig<json::Zone>(bus);
+    auto zones = getConfig<json::Zone>();
     // Fan control events are optional
     auto events = getConfig<json::Event>(bus, true);
-    if (!events.empty())
-    {
-        // Groups to include in events
-        auto groups = getConfig<json::Group>(bus);
-    }
 
     // Ensure all configurations use the same set of active profiles
     // (In case a profile's active state changes during configuration)
diff --git a/control/json_parser.hpp b/control/json_parser.hpp
index 7c08875..adeacbe 100644
--- a/control/json_parser.hpp
+++ b/control/json_parser.hpp
@@ -42,7 +42,8 @@
 using configKey = std::pair<std::string, std::vector<std::string>>;
 
 /**
- * @brief Load the configuration of a given JSON class object type
+ * @brief Load the configuration of a given JSON class object type that requires
+ * a dbus object
  *
  * @param[in] bus - The dbus bus object
  * @param[in] isOptional - JSON configuration file is optional or not
@@ -72,6 +73,37 @@
 }
 
 /**
+ * @brief Load the configuration of a given JSON class object type that does not
+ * require a dbus object
+ *
+ * @param[in] isOptional - JSON configuration file is optional or not
+ *                         Defaults to false
+ *
+ * @return Map of configuration entries
+ *     Map of configuration keys to their corresponding configuration object
+ */
+template <typename T>
+std::map<configKey, std::unique_ptr<T>> getConfig(bool isOptional = false)
+{
+    // Dbus object is needed to retrieve the JSON configuration file
+    auto bus = sdbusplus::bus::new_default();
+    std::map<configKey, std::unique_ptr<T>> config;
+
+    auto confFile = fan::JsonConfig::getConfFile(bus, confAppName,
+                                                 T::confFileName, isOptional);
+    if (!confFile.empty())
+    {
+        for (const auto& entry : fan::JsonConfig::load(confFile))
+        {
+            auto obj = std::make_unique<T>(entry);
+            config.emplace(std::make_pair(obj->getName(), obj->getProfiles()),
+                           std::move(obj));
+        }
+    }
+    return config;
+}
+
+/**
  * @brief Helper function to determine when a configuration entry is included
  * based on the list of active profiles and its list of profiles
  *