control: Pair profiles with name as key

Include the profiles of a configuration object in combination with its
name to construct a unique key for building the complete fan control
configuration. This is necessary for supporting the zones, groups, and
events configurations.

Tested:
    Object name and list of profiles construct key
    Profile objects always contain an empty list of profiles
    Fan objects may or may not contain a list of profiles

Change-Id: I4be7229e3fb695d845d60159d0f08f601512c812
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/json/config_base.hpp b/control/json/config_base.hpp
index 3184cb5..6b060c1 100644
--- a/control/json/config_base.hpp
+++ b/control/json/config_base.hpp
@@ -57,6 +57,20 @@
         return _name;
     }
 
+    /**
+     * @brief Get the configuration object's list of profiles
+     *
+     * Gets the list of profiles this configuration object belongs to if any
+     * are configured, otherwise an empty list of profiles results in the
+     * object always being included in the configuration.
+     *
+     * @return List of profiles the configuration object belongs to
+     */
+    inline const auto& getProfiles() const
+    {
+        return _profiles;
+    }
+
   protected:
     /**
      * @brief Determines the data type of a JSON configured parameter that is
@@ -98,6 +112,13 @@
             "Unsupported data type for JSON object's value");
     }
 
+    /**
+     * Profiles this configuration object belongs to (OPTIONAL).
+     * Otherwise always include this object in the configuration
+     * when no profiles are given
+     */
+    std::vector<std::string> _profiles;
+
   private:
     /* Name of the configuration object */
     std::string _name;
diff --git a/control/json/fan.cpp b/control/json/fan.cpp
index 4512f49..3fe4aec 100644
--- a/control/json/fan.cpp
+++ b/control/json/fan.cpp
@@ -28,15 +28,6 @@
 Fan::Fan(sdbusplus::bus::bus& bus, const json& jsonObj) :
     ConfigBase(jsonObj), _bus(bus)
 {
-    setProfiles(jsonObj);
-    setZone(jsonObj);
-    setSensors(jsonObj);
-    setInterface(jsonObj);
-}
-
-void Fan::setProfiles(const json& jsonObj)
-{
-    _profiles = {};
     if (jsonObj.contains("profiles"))
     {
         for (const auto& profile : jsonObj["profiles"])
@@ -44,6 +35,9 @@
             _profiles.emplace_back(profile.get<std::string>());
         }
     }
+    setZone(jsonObj);
+    setSensors(jsonObj);
+    setInterface(jsonObj);
 }
 
 void Fan::setZone(const json& jsonObj)
diff --git a/control/json/fan.hpp b/control/json/fan.hpp
index 63d975c..45bb035 100644
--- a/control/json/fan.hpp
+++ b/control/json/fan.hpp
@@ -61,16 +61,6 @@
     Fan(sdbusplus::bus::bus& bus, const json& jsonObj);
 
     /**
-     * @brief Get the list of profiles
-     *
-     * @return List of profiles this fan belongs to
-     */
-    inline const auto& getProfiles() const
-    {
-        return _profiles;
-    }
-
-    /**
      * @brief Get the zone
      *
      * @return Zone this fan belongs in
@@ -104,13 +94,6 @@
     /* The sdbusplus bus object */
     sdbusplus::bus::bus& _bus;
 
-    /**
-     * Profiles this fan belongs to (OPTIONAL).
-     * Otherwise always include this fan in the zone
-     * it belongs to when no profiles given
-     */
-    std::vector<std::string> _profiles;
-
     /* The zone this fan belongs to */
     std::string _zone;
 
@@ -127,17 +110,6 @@
     std::string _interface;
 
     /**
-     * @brief Parse and set the fan's profiles
-     *
-     * @param[in] jsonObj - JSON object for the fan
-     *
-     * Sets the list of profiles this fan belongs to if any are configured,
-     * otherwise an empty list of profiles results in the fan always being
-     * included in the zone.
-     */
-    void setProfiles(const json& jsonObj);
-
-    /**
      * @brief Parse and set the fan's zone
      *
      * @param[in] jsonObj - JSON object for the fan
diff --git a/control/json_parser.hpp b/control/json_parser.hpp
index 29d1697..df9c680 100644
--- a/control/json_parser.hpp
+++ b/control/json_parser.hpp
@@ -15,7 +15,6 @@
  */
 #pragma once
 
-#include "json/profile.hpp"
 #include "json_config.hpp"
 #include "types.hpp"
 
@@ -24,6 +23,8 @@
 
 #include <map>
 #include <memory>
+#include <utility>
+#include <vector>
 
 namespace phosphor::fan::control
 {
@@ -32,6 +33,15 @@
 constexpr auto confAppName = "control";
 
 /**
+ * Configuration object key to uniquely map to the configuration object
+ * Pair constructed of:
+ *      std::string = Configuration object's name
+ *      std::vector<std::string> = List of profiles the configuration object
+ *                                 is included in
+ */
+using configKey = std::pair<std::string, std::vector<std::string>>;
+
+/**
  * @brief Load the configuration of a given JSON class object type
  *
  * @param[in] bus - The dbus bus object
@@ -39,13 +49,13 @@
  *                         Defaults to false
  *
  * @return Map of configuration entries
- *     Map of configuration names to their corresponding configuration object
+ *     Map of configuration keys to their corresponding configuration object
  */
 template <typename T>
-std::map<std::string, std::unique_ptr<T>> getConfig(sdbusplus::bus::bus& bus,
-                                                    bool isOptional = false)
+std::map<configKey, std::unique_ptr<T>> getConfig(sdbusplus::bus::bus& bus,
+                                                  bool isOptional = false)
 {
-    std::map<std::string, std::unique_ptr<T>> config;
+    std::map<configKey, std::unique_ptr<T>> config;
 
     auto confFile = fan::JsonConfig::getConfFile(bus, confAppName,
                                                  T::confFileName, isOptional);
@@ -54,10 +64,10 @@
         for (const auto& entry : fan::JsonConfig::load(confFile))
         {
             auto obj = std::make_unique<T>(bus, entry);
-            config.emplace(obj->getName(), std::move(obj));
+            config.emplace(std::make_pair(obj->getName(), obj->getProfiles()),
+                           std::move(obj));
         }
     }
-
     return config;
 }