xref: /openbmc/phosphor-fan-presence/control/json/config_base.hpp (revision b2e9a4fcc2253bcb585e92b4642ed4b0036941df)
1554ba472SMatthew Barth /**
2554ba472SMatthew Barth  * Copyright © 2020 IBM Corporation
3554ba472SMatthew Barth  *
4554ba472SMatthew Barth  * Licensed under the Apache License, Version 2.0 (the "License");
5554ba472SMatthew Barth  * you may not use this file except in compliance with the License.
6554ba472SMatthew Barth  * You may obtain a copy of the License at
7554ba472SMatthew Barth  *
8554ba472SMatthew Barth  *     http://www.apache.org/licenses/LICENSE-2.0
9554ba472SMatthew Barth  *
10554ba472SMatthew Barth  * Unless required by applicable law or agreed to in writing, software
11554ba472SMatthew Barth  * distributed under the License is distributed on an "AS IS" BASIS,
12554ba472SMatthew Barth  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13554ba472SMatthew Barth  * See the License for the specific language governing permissions and
14554ba472SMatthew Barth  * limitations under the License.
15554ba472SMatthew Barth  */
16554ba472SMatthew Barth #pragma once
17554ba472SMatthew Barth 
18554ba472SMatthew Barth #include <nlohmann/json.hpp>
19554ba472SMatthew Barth #include <phosphor-logging/log.hpp>
20554ba472SMatthew Barth 
21a3a8cc57SMatthew Barth #include <vector>
22a3a8cc57SMatthew Barth 
23554ba472SMatthew Barth namespace phosphor::fan::control::json
24554ba472SMatthew Barth {
25554ba472SMatthew Barth 
26554ba472SMatthew Barth using json = nlohmann::json;
27554ba472SMatthew Barth using namespace phosphor::logging;
28554ba472SMatthew Barth 
29b584d818SMatthew Barth using PropertyVariantType =
30b584d818SMatthew Barth     std::variant<bool, int32_t, int64_t, double, std::string>;
31b584d818SMatthew Barth 
32554ba472SMatthew Barth /**
3344ab7693SMatthew Barth  * Configuration object key to uniquely map to the configuration object
3444ab7693SMatthew Barth  * Pair constructed of:
3544ab7693SMatthew Barth  *      std::string = Configuration object's name
3644ab7693SMatthew Barth  *      std::vector<std::string> = List of profiles the configuration object
3744ab7693SMatthew Barth  *                                 is included in
3844ab7693SMatthew Barth  */
3944ab7693SMatthew Barth using configKey = std::pair<std::string, std::vector<std::string>>;
4044ab7693SMatthew Barth 
4144ab7693SMatthew Barth /**
42554ba472SMatthew Barth  * @class ConfigBase - Base configuration object
43554ba472SMatthew Barth  *
44554ba472SMatthew Barth  * Base class for fan control's JSON configuration objects.
45554ba472SMatthew Barth  */
46554ba472SMatthew Barth class ConfigBase
47554ba472SMatthew Barth {
48554ba472SMatthew Barth   public:
49554ba472SMatthew Barth     ConfigBase() = delete;
50554ba472SMatthew Barth     ConfigBase(ConfigBase&&) = delete;
51554ba472SMatthew Barth     ConfigBase& operator=(const ConfigBase&) = delete;
52554ba472SMatthew Barth     ConfigBase& operator=(ConfigBase&&) = delete;
53*b2e9a4fcSMike Capps 
54554ba472SMatthew Barth     virtual ~ConfigBase() = default;
55554ba472SMatthew Barth 
ConfigBase(const json & jsonObj)56554ba472SMatthew Barth     explicit ConfigBase(const json& jsonObj)
57554ba472SMatthew Barth     {
58554ba472SMatthew Barth         // Set the name of this configuration object
59554ba472SMatthew Barth         setName(jsonObj);
60bfd7e1b7SMatthew Barth         if (jsonObj.contains("profiles"))
61bfd7e1b7SMatthew Barth         {
62bfd7e1b7SMatthew Barth             for (const auto& profile : jsonObj["profiles"])
63bfd7e1b7SMatthew Barth             {
64bfd7e1b7SMatthew Barth                 _profiles.emplace_back(profile.get<std::string>());
65bfd7e1b7SMatthew Barth             }
66bfd7e1b7SMatthew Barth         }
67554ba472SMatthew Barth     }
68554ba472SMatthew Barth 
69554ba472SMatthew Barth     /**
70e5578602SMatthew Barth      * Copy Constructor
71e5578602SMatthew Barth      * Creates a config base from another config base's originally parsed JSON
72e5578602SMatthew Barth      * object data
73e5578602SMatthew Barth      *
74e5578602SMatthew Barth      * @param[in] origObj - Original ConfigBase object to be created from
75e5578602SMatthew Barth      */
ConfigBase(const ConfigBase & origObj)76e5578602SMatthew Barth     ConfigBase(const ConfigBase& origObj)
77e5578602SMatthew Barth     {
78e5578602SMatthew Barth         _name = origObj._name;
79e5578602SMatthew Barth         _profiles = origObj._profiles;
80e5578602SMatthew Barth     }
81e5578602SMatthew Barth 
82e5578602SMatthew Barth     /**
83554ba472SMatthew Barth      * @brief Get the configuration object's name
84554ba472SMatthew Barth      *
85554ba472SMatthew Barth      * @return Name of the configuration object
86554ba472SMatthew Barth      */
getName() const87554ba472SMatthew Barth     inline const std::string& getName() const
88554ba472SMatthew Barth     {
89554ba472SMatthew Barth         return _name;
90554ba472SMatthew Barth     }
91554ba472SMatthew Barth 
92ce957268SMatthew Barth     /**
93ce957268SMatthew Barth      * @brief Get the configuration object's list of profiles
94ce957268SMatthew Barth      *
95ce957268SMatthew Barth      * Gets the list of profiles this configuration object belongs to if any
96ce957268SMatthew Barth      * are configured, otherwise an empty list of profiles results in the
97ce957268SMatthew Barth      * object always being included in the configuration.
98ce957268SMatthew Barth      *
99ce957268SMatthew Barth      * @return List of profiles the configuration object belongs to
100ce957268SMatthew Barth      */
getProfiles() const101ce957268SMatthew Barth     inline const auto& getProfiles() const
102ce957268SMatthew Barth     {
103ce957268SMatthew Barth         return _profiles;
104ce957268SMatthew Barth     }
105ce957268SMatthew Barth 
1069167c4d5SMatthew Barth     /**
1079167c4d5SMatthew Barth      * @brief Determines the data type of a JSON configured parameter that is
1089167c4d5SMatthew Barth      * used as a variant within the fan control application and returns the
1099167c4d5SMatthew Barth      * value as that variant.
1109167c4d5SMatthew Barth      * @details Retrieves a JSON object by the first derived data type that
1119167c4d5SMatthew Barth      * is not null. Expected data types should appear in a logical order of
1129167c4d5SMatthew Barth      * conversion. i.e.) uint and int could both be uint
1139167c4d5SMatthew Barth      *
1149167c4d5SMatthew Barth      * @param[in] object - A single JSON object
1159167c4d5SMatthew Barth      *
1169167c4d5SMatthew Barth      * @return A `PropertyVariantType` variant containing the JSON object's
1179167c4d5SMatthew Barth      * value
1189167c4d5SMatthew Barth      */
getJsonValue(const json & object)1199167c4d5SMatthew Barth     static const PropertyVariantType getJsonValue(const json& object)
1209167c4d5SMatthew Barth     {
1219167c4d5SMatthew Barth         if (auto boolPtr = object.get_ptr<const bool*>())
1229167c4d5SMatthew Barth         {
1239167c4d5SMatthew Barth             return *boolPtr;
1249167c4d5SMatthew Barth         }
1259167c4d5SMatthew Barth         if (auto intPtr = object.get_ptr<const int64_t*>())
1269167c4d5SMatthew Barth         {
1279167c4d5SMatthew Barth             return *intPtr;
1289167c4d5SMatthew Barth         }
1299167c4d5SMatthew Barth         if (auto doublePtr = object.get_ptr<const double*>())
1309167c4d5SMatthew Barth         {
1319167c4d5SMatthew Barth             return *doublePtr;
1329167c4d5SMatthew Barth         }
1339167c4d5SMatthew Barth         if (auto stringPtr = object.get_ptr<const std::string*>())
1349167c4d5SMatthew Barth         {
1359167c4d5SMatthew Barth             return *stringPtr;
1369167c4d5SMatthew Barth         }
1379167c4d5SMatthew Barth 
1389167c4d5SMatthew Barth         log<level::ERR>(
1399167c4d5SMatthew Barth             "Unsupported data type for JSON object's value",
1409167c4d5SMatthew Barth             entry("JSON_ENTRY=%s", object.dump().c_str()),
1419167c4d5SMatthew Barth             entry("SUPPORTED_TYPES=%s", "{bool, int, double, string}"));
1429167c4d5SMatthew Barth         throw std::runtime_error(
1439167c4d5SMatthew Barth             "Unsupported data type for JSON object's value");
1449167c4d5SMatthew Barth     }
1459167c4d5SMatthew Barth 
146c272790aSMatt Spinler   protected:
147a3a8cc57SMatthew Barth     /* Name of the configuration object */
148a3a8cc57SMatthew Barth     std::string _name;
149a3a8cc57SMatthew Barth 
150ce957268SMatthew Barth     /**
151ce957268SMatthew Barth      * Profiles this configuration object belongs to (OPTIONAL).
152ce957268SMatthew Barth      * Otherwise always include this object in the configuration
153ce957268SMatthew Barth      * when no profiles are given
154ce957268SMatthew Barth      */
155ce957268SMatthew Barth     std::vector<std::string> _profiles;
156ce957268SMatthew Barth 
157554ba472SMatthew Barth   private:
158554ba472SMatthew Barth     /**
159554ba472SMatthew Barth      * @brief Sets the configuration object's name from the given JSON
160554ba472SMatthew Barth      *
161554ba472SMatthew Barth      * @param[in] jsonObj - JSON to get configuration object's name from
162554ba472SMatthew Barth      */
setName(const json & jsonObj)163554ba472SMatthew Barth     inline void setName(const json& jsonObj)
164554ba472SMatthew Barth     {
165554ba472SMatthew Barth         if (!jsonObj.contains("name"))
166554ba472SMatthew Barth         {
167554ba472SMatthew Barth             // Log error on missing configuration object's name
168554ba472SMatthew Barth             log<level::ERR>("Missing required configuration object's name",
169554ba472SMatthew Barth                             entry("JSON=%s", jsonObj.dump().c_str()));
170554ba472SMatthew Barth             throw std::runtime_error(
171554ba472SMatthew Barth                 "Missing required configuration object's name");
172554ba472SMatthew Barth         }
173554ba472SMatthew Barth         _name = jsonObj["name"].get<std::string>();
174554ba472SMatthew Barth     }
175554ba472SMatthew Barth };
176554ba472SMatthew Barth 
177554ba472SMatthew Barth } // namespace phosphor::fan::control::json
178