control: Add event trigger creation

Event triggers are created by the events JSON configuration given a
trigger class name. That class name is used to lookup the associated
function in order to create the trigger by that class name. Triggers are
not required to be kept around/stored on the event, so that ability was
removed.

Change-Id: I3333b312a063e952d858f78fe80df85820eb5bba
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/json/event.cpp b/control/json/event.cpp
index 31db75f..e50e67e 100644
--- a/control/json/event.cpp
+++ b/control/json/event.cpp
@@ -19,6 +19,7 @@
 #include "config_base.hpp"
 #include "group.hpp"
 #include "manager.hpp"
+#include "triggers/trigger.hpp"
 
 #include <fmt/format.h>
 
@@ -259,6 +260,36 @@
                         entry("JSON=%s", jsonObj.dump().c_str()));
         throw std::runtime_error("Missing required event triggers list");
     }
+    for (const auto& jsonTrig : jsonObj["triggers"])
+    {
+        if (!jsonTrig.contains("class"))
+        {
+            log<level::ERR>("Missing required event trigger class",
+                            entry("JSON=%s", jsonTrig.dump().c_str()));
+            throw std::runtime_error("Missing required event trigger class");
+        }
+        // The class of trigger used to run the event actions
+        auto tClass = jsonTrig["class"].get<std::string>();
+        std::transform(tClass.begin(), tClass.end(), tClass.begin(), tolower);
+        auto trigFunc = trigger::triggers.find(tClass);
+        if (trigFunc != trigger::triggers.end())
+        {
+            trigFunc->second(jsonTrig, getName(), _manager, _actions);
+        }
+        else
+        {
+            // Construct list of available triggers
+            auto availTrigs = std::accumulate(
+                std::next(trigger::triggers.begin()), trigger::triggers.end(),
+                trigger::triggers.begin()->first, [](auto list, auto trig) {
+                    return std::move(list) + ", " + trig.first;
+                });
+            log<level::ERR>(
+                fmt::format("Trigger '{}' is not recognized", tClass).c_str(),
+                entry("AVAILABLE_TRIGGERS=%s", availTrigs.c_str()));
+            throw std::runtime_error("Unsupported trigger class name given");
+        }
+    }
 }
 
 } // namespace phosphor::fan::control::json
diff --git a/control/json/triggers/trigger.hpp b/control/json/triggers/trigger.hpp
new file mode 100644
index 0000000..7051932
--- /dev/null
+++ b/control/json/triggers/trigger.hpp
@@ -0,0 +1,41 @@
+/**
+ * Copyright © 2021 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "action.hpp"
+#include "manager.hpp"
+
+#include <nlohmann/json.hpp>
+
+#include <functional>
+#include <map>
+#include <memory>
+#include <vector>
+
+namespace phosphor::fan::control::json::trigger
+{
+
+using json = nlohmann::json;
+
+// Trigger creation function
+using createTrigger =
+    std::function<void(const json&, const std::string&, Manager*,
+                       std::vector<std::unique_ptr<ActionBase>>&)>;
+
+// Mapping of trigger class name to its creation function
+static const std::map<std::string, createTrigger> triggers = {};
+
+} // namespace phosphor::fan::control::json::trigger