Move RAS data support to RasDataParser class

Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
Change-Id: Ib6d604504cce4564c36fb2b461eb330e97811ee6
diff --git a/analyzer/analyzer_main.cpp b/analyzer/analyzer_main.cpp
index 8d69d9b..2485376 100644
--- a/analyzer/analyzer_main.cpp
+++ b/analyzer/analyzer_main.cpp
@@ -2,6 +2,7 @@
 #include <libpdbg.h>
 #include <unistd.h>
 
+#include <analyzer/ras-data/ras-data-parser.hpp>
 #include <analyzer/service_data.hpp>
 #include <hei_main.hpp>
 #include <phosphor-logging/log.hpp>
@@ -28,12 +29,6 @@
 void initializeIsolator(std::vector<libhei::Chip>& o_chips);
 
 /**
- * @brief Apply any RAS actions required by the given data.
- * @param i_servData Data regarding service actions gathered during analysis.
- */
-void applyRasActions(ServiceData& io_servData);
-
-/**
  * @brief Will create and submit a PEL using the given data.
  * @param i_isoData   The data gathered during isolation (for FFDC).
  * @param i_servData  Data regarding service actions gathered during analysis.
@@ -166,8 +161,9 @@
                    rootCause.toUint32(), __attn(rootCause.getAttnType()));
 
         // Perform service actions based on the root cause.
+        RasDataParser rasData{};
         ServiceData servData{rootCause};
-        applyRasActions(servData);
+        rasData.getResolution(rootCause)->resolve(servData);
 
         // Create and commit a PEL.
         createPel(isoData, servData);
diff --git a/analyzer/apply_ras_actions.cpp b/analyzer/apply_ras_actions.cpp
deleted file mode 100644
index 48421e7..0000000
--- a/analyzer/apply_ras_actions.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-#include <analyzer/service_data.hpp>
-#include <hei_main.hpp>
-#include <nlohmann/json.hpp>
-#include <util/data_file.hpp>
-#include <util/trace.hpp>
-
-#include <filesystem>
-#include <fstream>
-#include <string>
-
-namespace fs = std::filesystem;
-
-namespace analyzer
-{
-
-//------------------------------------------------------------------------------
-
-// Returns the RAS data schema file. Will throw exceptions if the file does not
-// exist, is unreadable, or is malformed JSON.
-nlohmann::json __getSchemaFile()
-{
-    // Search all the files in the package `schema` subdirectory and find the
-    // file named `ras-data-schema.json`.
-    fs::path dirPath{PACKAGE_DIR "schema"};
-    std::vector<fs::path> files;
-    util::findFiles(dirPath, R"(ras-data-schema\.json)", files);
-    assert(1 == files.size()); // Should be one, and only one, file.
-
-    // Trace the file for debug.
-    trace::inf("File found: path=%s", files.front().string().c_str());
-
-    // Open the file.
-    std::ifstream file{files.front()};
-    assert(file.good()); // The file must be readable.
-
-    // Parse and return the JSON. Note that this will throw an exception if the
-    // file is not properly formatted.
-    return nlohmann::json::parse(file);
-}
-
-//------------------------------------------------------------------------------
-
-void __getDataFiles(std::map<libhei::ChipType_t, nlohmann::json>& o_files)
-{
-    o_files.clear(); // initially empty
-
-    // Get the schema document for the data files.
-    const auto schema = __getSchemaFile();
-
-    // Get all JSON files in the package `data` subdirectory.
-    fs::path dirPath{PACKAGE_DIR "ras-data"};
-    std::vector<fs::path> files;
-    util::findFiles(dirPath, R"(.*\.json)", files);
-
-    for (const auto& path : files)
-    {
-        // Trace each data file for debug.
-        trace::inf("File found: path=%s", path.string().c_str());
-
-        // Open the file.
-        std::ifstream file{path};
-        assert(file.good()); // The file must be readable.
-
-        // Parse the JSON. Note that this will throw an exception if the
-        // file is not properly formatted.
-        const auto data = nlohmann::json::parse(file);
-
-        // Validate the data against the schema.
-        assert(util::validateJson(schema, data));
-
-        // Get the chip model/EC level from the data. The value is currently
-        // stored as a string representation of the hex value. So it will have
-        // to be converted to an integer.
-        libhei::ChipType_t chipType =
-            std::stoul(data.at("model_ec").get<std::string>(), 0, 16);
-
-        // So far, so good. Add the entry.
-        auto ret = o_files.emplace(chipType, data);
-        assert(ret.second); // Should not have duplicate entries
-    }
-}
-
-//------------------------------------------------------------------------------
-
-void applyRasActions(ServiceData& io_servData)
-{
-    // Find all of the existing chip data files.
-    std::map<libhei::ChipType_t, nlohmann::json> files;
-    __getDataFiles(files);
-
-    // Get the RAS data file for this signature's chip type.
-    auto rootCause   = io_servData.getRootCause();
-    auto rasData_itr = files.find(rootCause.getChip().getType());
-    assert(files.end() != rasData_itr); // the data file must exist
-
-    // TODO: finish implementing
-
-    // The default action is to callout level 2 support.
-    io_servData.addCallout(std::make_shared<ProcedureCallout>(
-        ProcedureCallout::NEXTLVL, Callout::Priority::HIGH));
-}
-
-//------------------------------------------------------------------------------
-
-} // namespace analyzer
diff --git a/analyzer/meson.build b/analyzer/meson.build
index 785a9d3..ebeed4d 100644
--- a/analyzer/meson.build
+++ b/analyzer/meson.build
@@ -1,10 +1,10 @@
 # Source files.
 analyzer_src = files(
     'analyzer_main.cpp',
-    'apply_ras_actions.cpp',
     'create_pel.cpp',
     'hei_user_interface.cpp',
     'initialize_isolator.cpp',
+    'ras-data/ras-data-parser.cpp',
     'resolution.cpp',
 )
 
diff --git a/analyzer/ras-data/ras-data-parser.cpp b/analyzer/ras-data/ras-data-parser.cpp
new file mode 100644
index 0000000..48b0428
--- /dev/null
+++ b/analyzer/ras-data/ras-data-parser.cpp
@@ -0,0 +1,82 @@
+#include <analyzer/ras-data/ras-data-parser.hpp>
+#include <util/data_file.hpp>
+#include <util/trace.hpp>
+
+#include <filesystem>
+#include <fstream>
+#include <string>
+
+namespace fs = std::filesystem;
+
+namespace analyzer
+{
+
+//------------------------------------------------------------------------------
+
+std::shared_ptr<Resolution>
+    RasDataParser::getResolution(const libhei::Signature&)
+{
+    // TODO: Default to level 2 support callout until fully implemented.
+    return std::make_shared<ProcedureCalloutResolution>(
+        ProcedureCallout::NEXTLVL, Callout::HIGH);
+}
+
+//------------------------------------------------------------------------------
+
+void RasDataParser::initDataFiles()
+{
+    iv_dataFiles.clear(); // initially empty
+
+    // Get the RAS data schema files from the package `schema` subdirectory.
+    fs::path schemaDir{PACKAGE_DIR "schema"};
+    auto schemaRegex = R"(ras-data-schema\.json)";
+    std::vector<fs::path> schmemaPaths;
+    util::findFiles(schemaDir, schemaRegex, schmemaPaths);
+    assert(1 == schmemaPaths.size()); // Should be one, and only one, file.
+
+    // Trace the file for debug.
+    trace::inf("File found: path=%s", schmemaPaths.front().string().c_str());
+
+    // Open the file.
+    std::ifstream schemaFile{schmemaPaths.front()};
+    assert(schemaFile.good()); // The file must be readable.
+
+    // Parse the JSON.
+    auto schema = nlohmann::json::parse(schemaFile);
+
+    // Get the RAS data files from the package `ras-data` subdirectory.
+    fs::path dataDir{PACKAGE_DIR "ras-data"};
+    std::vector<fs::path> dataPaths;
+    util::findFiles(dataDir, R"(.*\.json)", dataPaths);
+
+    // Parse each of the data files.
+    for (const auto& path : dataPaths)
+    {
+        // Trace each data file for debug.
+        trace::inf("File found: path=%s", path.string().c_str());
+
+        // Open the file.
+        std::ifstream file{path};
+        assert(file.good()); // The file must be readable.
+
+        // Parse the JSON.
+        const auto data = nlohmann::json::parse(file);
+
+        // Validate the data against the schema.
+        assert(util::validateJson(schema, data));
+
+        // Get the chip model/EC level from the data. The value is currently
+        // stored as a string representation of the hex value. So it will have
+        // to be converted to an integer.
+        libhei::ChipType_t chipType =
+            std::stoul(data.at("model_ec").get<std::string>(), 0, 16);
+
+        // So far, so good. Add the entry.
+        auto ret = iv_dataFiles.emplace(chipType, data);
+        assert(ret.second); // Should not have duplicate entries
+    }
+}
+
+//------------------------------------------------------------------------------
+
+} // namespace analyzer
diff --git a/analyzer/ras-data/ras-data-parser.hpp b/analyzer/ras-data/ras-data-parser.hpp
new file mode 100644
index 0000000..e484167
--- /dev/null
+++ b/analyzer/ras-data/ras-data-parser.hpp
@@ -0,0 +1,46 @@
+#pragma once
+
+#include <analyzer/resolution.hpp>
+#include <hei_main.hpp>
+#include <nlohmann/json.hpp>
+
+#include <map>
+
+namespace analyzer
+{
+
+/**
+ * @brief Manages the RAS data files and resolves service actions required for
+ *        error signatures.
+ */
+class RasDataParser
+{
+  public:
+    /** @brief Default constructor. */
+    RasDataParser()
+    {
+        initDataFiles();
+    }
+
+  private:
+    /** @brief The RAS data files. */
+    std::map<libhei::ChipType_t, nlohmann::json> iv_dataFiles;
+
+  public:
+    /**
+     * @brief Returns a resolution for all the RAS actions needed for the given
+     *        signature.
+     * @param i_signature The target error signature.
+     */
+    std::shared_ptr<Resolution>
+        getResolution(const libhei::Signature& i_signature);
+
+  private:
+    /**
+     * @brief Parses all of the RAS data JSON files and validates them against
+     *        the associated schema.
+     */
+    void initDataFiles();
+};
+
+} // namespace analyzer