Moved Callout class logic to Resolution classes

This simplified the confusion between the Callout and Resolution classes
because there was a lot of overlap.

Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
Change-Id: Iea0fb30a1577869ebfe5b2b195fee832a694adb5
diff --git a/analyzer/callout.hpp b/analyzer/callout.hpp
new file mode 100644
index 0000000..cee3dd1
--- /dev/null
+++ b/analyzer/callout.hpp
@@ -0,0 +1,115 @@
+#pragma once
+
+#include <string>
+
+namespace analyzer
+{
+
+namespace callout
+{
+
+/** @brief All callouts will have a priority indicating when to issue the
+ *         required service action. */
+class Priority
+{
+  public:
+    /** Serivce is mandatory. */
+    static const Priority HIGH;
+
+    /** Serivce medium priority callouts one at a time, in order, until the
+     *  issue is resolved. */
+    static const Priority MED;
+
+    /** Same as MED, except replace all A's as a group. */
+    static const Priority MED_A;
+
+    /** Same as MED, except replace all A's as a group. */
+    static const Priority MED_B;
+
+    /** Same as MED, except replace all A's as a group. */
+    static const Priority MED_C;
+
+    /** If servicing all high and medium priority callouts did not resolve
+     *  the issue, service low priority callouts one at a time, in order,
+     *  until the issue is resolved. */
+    static const Priority LOW;
+
+  private:
+    /**
+     * @brief Constructor from components.
+     *
+     * At the moment, the priority values for the callout list user data
+     * section are different from the priority values hard-coded in the
+     * registry. Therefore, two different values must be stored.
+     *
+     * @param i_registry The string representation of a priority used in
+     *                   registry callouts.
+     * @param i_userData The string representation of a priority used in user
+     *                   data callouts.
+     */
+    Priority(const std::string& i_registry, const std::string& i_userData) :
+        iv_registry(i_registry), iv_userData(i_userData)
+    {}
+
+  private:
+    /** The string representation of a priority used in registry callouts. */
+    const std::string iv_registry;
+
+    /** The string representation of a priority used in user data callouts. */
+    const std::string iv_userData;
+
+  public:
+    /** iv_registry accessor */
+    const std::string& getRegistryString() const
+    {
+        return iv_registry;
+    }
+
+    /** iv_userData accessor */
+    const std::string& getUserDataString() const
+    {
+        return iv_userData;
+    }
+};
+
+// clang-format off
+inline const Priority Priority::HIGH {"high",          "H"};
+inline const Priority Priority::MED  {"medium",        "M"};
+inline const Priority Priority::MED_A{"medium_group_A","A"};
+inline const Priority Priority::MED_B{"medium_group_B","B"};
+inline const Priority Priority::MED_C{"medium_group_C","C"};
+inline const Priority Priority::LOW  {"low",           "L"};
+// clang-format on
+
+/** @brief Container class for procedure callout service actions. */
+class Procedure
+{
+  public:
+    /** Contact next level support. */
+    static const Procedure NEXTLVL;
+
+  private:
+    /**
+     * @brief Constructor from components.
+     * @param i_string The string representation of the procedure used for
+     *                 callouts.
+     */
+    explicit Procedure(const std::string& i_string) : iv_string(i_string) {}
+
+  private:
+    /** The string representation of the procedure used for callouts. */
+    const std::string iv_string;
+
+  public:
+    /** iv_string accessor */
+    std::string getString() const
+    {
+        return iv_string;
+    }
+};
+
+inline const Procedure Procedure::NEXTLVL{"NEXTLVL"};
+
+} // namespace callout
+
+} // namespace analyzer
diff --git a/analyzer/create_pel.cpp b/analyzer/create_pel.cpp
index 38a7d5f..2106b36 100644
--- a/analyzer/create_pel.cpp
+++ b/analyzer/create_pel.cpp
@@ -84,17 +84,13 @@
 void __addCalloutList(const ServiceData& i_servData,
                       std::vector<util::FFDCFile>& io_userDataFiles)
 {
-    // Get the JSON output for the callout list.
-    nlohmann::json json;
-    i_servData.getCalloutList(json);
-
     // Create a new entry for the user data section containing the callout list.
     io_userDataFiles.emplace_back(util::FFDCFormat::JSON, FFDC_CALLOUTS,
                                   FFDC_VERSION1);
 
     // Use a file stream to write the JSON to file.
     std::ofstream o{io_userDataFiles.back().getPath()};
-    o << json;
+    o << i_servData.getCalloutList();
 }
 
 //------------------------------------------------------------------------------
diff --git a/analyzer/ras-data/ras-data-parser.cpp b/analyzer/ras-data/ras-data-parser.cpp
index 78ec9d2..559a947 100644
--- a/analyzer/ras-data/ras-data-parser.cpp
+++ b/analyzer/ras-data/ras-data-parser.cpp
@@ -199,9 +199,9 @@
             auto priority = a.at("priority").get<std::string>();
 
             // clang-format off
-            static const std::map<std::string, ProcedureCallout::Type> m =
+            static const std::map<std::string, callout::Procedure> m =
             {
-                {"LEVEL2", ProcedureCallout::NEXTLVL},
+                {"LEVEL2", callout::Procedure::NEXTLVL},
             };
             // clang-format on
 
@@ -238,17 +238,17 @@
 
 //------------------------------------------------------------------------------
 
-Callout::Priority RasDataParser::getPriority(const std::string& i_priority)
+callout::Priority RasDataParser::getPriority(const std::string& i_priority)
 {
     // clang-format off
-    static const std::map<std::string, Callout::Priority> m =
+    static const std::map<std::string, callout::Priority> m =
     {
-        {"HIGH",  Callout::HIGH},
-        {"MED",   Callout::MED},
-        {"MED_A", Callout::MED_A},
-        {"MED_B", Callout::MED_B},
-        {"MED_C", Callout::MED_C},
-        {"LOW",   Callout::LOW},
+        {"HIGH",  callout::Priority::HIGH},
+        {"MED",   callout::Priority::MED},
+        {"MED_A", callout::Priority::MED_A},
+        {"MED_B", callout::Priority::MED_B},
+        {"MED_C", callout::Priority::MED_C},
+        {"LOW",   callout::Priority::LOW},
     };
     // clang-format on
 
diff --git a/analyzer/ras-data/ras-data-parser.hpp b/analyzer/ras-data/ras-data-parser.hpp
index 6d45ad2..fe5e4a1 100644
--- a/analyzer/ras-data/ras-data-parser.hpp
+++ b/analyzer/ras-data/ras-data-parser.hpp
@@ -74,7 +74,7 @@
      * @param  i_priority The priority string.
      * @return A callout priority enum value.
      */
-    Callout::Priority getPriority(const std::string& i_priority);
+    callout::Priority getPriority(const std::string& i_priority);
 };
 
 } // namespace analyzer
diff --git a/analyzer/resolution.cpp b/analyzer/resolution.cpp
index 9ad7502..cce581f 100644
--- a/analyzer/resolution.cpp
+++ b/analyzer/resolution.cpp
@@ -23,17 +23,14 @@
         }
     }
 
-    // Add location code to callout list.
+    // Get the location code for this target.
     auto locCode = util::pdbg::getLocationCode(trgt);
-    if (locCode.empty())
-    {
-        trace::err("Unable to find location code for %s", path.c_str());
-    }
-    else
-    {
-        io_sd.addCallout(
-            std::make_shared<HardwareCallout>(locCode, iv_priority));
-    }
+
+    // Add the actual callout to the service data.
+    nlohmann::json callout;
+    callout["LocationCode"] = locCode;
+    callout["Priority"]     = iv_priority.getUserDataString();
+    io_sd.addCallout(callout);
 
     // Add entity path to gard list.
     auto entityPath = util::pdbg::getPhysDevPath(trgt);
@@ -53,4 +50,17 @@
     }
 }
 
+//------------------------------------------------------------------------------
+
+void ProcedureCalloutResolution::resolve(ServiceData& io_sd) const
+{
+    // Add the actual callout to the service data.
+    nlohmann::json callout;
+    callout["Procedure"] = iv_procedure.getString();
+    callout["Priority"]  = iv_priority.getUserDataString();
+    io_sd.addCallout(callout);
+}
+
+//------------------------------------------------------------------------------
+
 } // namespace analyzer
diff --git a/analyzer/resolution.hpp b/analyzer/resolution.hpp
index 62afd76..44638be 100644
--- a/analyzer/resolution.hpp
+++ b/analyzer/resolution.hpp
@@ -36,7 +36,7 @@
      * @param i_guard    True, if guard is required. False, otherwise.
      */
     HardwareCalloutResolution(const std::string& i_path,
-                              Callout::Priority i_priority, bool i_guard) :
+                              callout::Priority i_priority, bool i_guard) :
         iv_path(i_path),
         iv_priority(i_priority), iv_guard(i_guard)
     {}
@@ -47,7 +47,7 @@
     const std::string iv_path;
 
     /** The callout priority. */
-    const Callout::Priority iv_priority;
+    const callout::Priority iv_priority;
 
     /** True, if guard is required. False, otherwise. */
     const bool iv_guard;
@@ -65,26 +65,21 @@
      * @param i_procedure The procedure callout type.
      * @param i_priority  The callout priority.
      */
-    ProcedureCalloutResolution(ProcedureCallout::Type i_procedure,
-                               Callout::Priority i_priority) :
+    ProcedureCalloutResolution(const callout::Procedure& i_procedure,
+                               const callout::Priority& i_priority) :
         iv_procedure(i_procedure),
         iv_priority(i_priority)
     {}
 
   private:
     /** The procedure callout type. */
-    const ProcedureCallout::Type iv_procedure;
+    const callout::Procedure iv_procedure;
 
     /** The callout priority. */
-    const Callout::Priority iv_priority;
+    const callout::Priority iv_priority;
 
   public:
-    void resolve(ServiceData& io_sd) const override
-    {
-        // Simply add the procedure to the callout list.
-        io_sd.addCallout(
-            std::make_shared<ProcedureCallout>(iv_procedure, iv_priority));
-    }
+    void resolve(ServiceData& io_sd) const override;
 };
 
 /**
diff --git a/analyzer/service_data.hpp b/analyzer/service_data.hpp
index 66e0200..c9f9c41 100644
--- a/analyzer/service_data.hpp
+++ b/analyzer/service_data.hpp
@@ -1,154 +1,12 @@
 #pragma once
 
+#include <analyzer/callout.hpp>
 #include <hei_main.hpp>
 #include <nlohmann/json.hpp>
 
 namespace analyzer
 {
 
-/** @brief An abstract class for service event, also known as a callout. */
-class Callout
-{
-  public:
-    /** Each callout will have a priority indicating when to issue the required
-     *  service action. Details below. */
-    enum Priority
-    {
-        /** Serivce is mandatory. */
-        HIGH,
-
-        /** Serivce medium priority callouts one at a time, in order, until the
-         *  issue is resolved. */
-        MED,
-
-        MED_A, ///< Same as PRI_MED, except replace all A's as a group.
-        MED_B, ///< Same as PRI_MED, except replace all B's as a group.
-        MED_C, ///< Same as PRI_MED, except replace all C's as a group.
-
-        /** If servicing all high and medium priority callouts did not resolve
-         *  the issue, service low priority callouts one at a time, in order,
-         *  until the issue is resolved. */
-        LOW,
-    };
-
-  public:
-    /** @brief Pure virtual destructor. */
-    virtual ~Callout() = 0;
-
-  protected:
-    /**
-     * @brief Constructor from components.
-     * @param p The callout priority.
-     */
-    explicit Callout(Priority p) : iv_priority(p) {}
-
-  private:
-    /** The callout priority. */
-    const Priority iv_priority;
-
-  protected:
-    /**
-     * @brief Appends the callout priority to the end of the given json object.
-     * @param j The json object for a single callout.
-     */
-    void addPriority(nlohmann::json& j) const
-    {
-        // clang-format off
-        static const std::map<Priority, std::string> m =
-        {
-            {HIGH,  "H"},
-            {MED,   "M"},
-            {MED_A, "A"},
-            {MED_B, "B"},
-            {MED_C, "C"},
-            {LOW,   "L"},
-        };
-        // clang-format on
-
-        j.emplace("Priority", m.at(iv_priority));
-    }
-
-  public:
-    /**
-     * @brief Appends a json object representing this callout to the end of the
-     *        given json object.
-     * @param j The json object containing all current callouts for a PEL.
-     */
-    virtual void getJson(nlohmann::json&) const = 0;
-};
-
-// Pure virtual destructor must be defined.
-inline Callout::~Callout() {}
-
-/** @brief A service event requiring hardware replacement. */
-class HardwareCallout : public Callout
-{
-  public:
-    /**
-     * @brief Constructor from components.
-     * @param i_locationCode The location code of the hardware callout.
-     * @param i_priority     The callout priority.
-     */
-    HardwareCallout(const std::string& i_locationCode, Priority i_priority) :
-        Callout(i_priority), iv_locationCode(i_locationCode)
-    {}
-
-  private:
-    /** The hardware location code. */
-    const std::string iv_locationCode;
-
-  public:
-    void getJson(nlohmann::json& j) const override
-    {
-        nlohmann::json c = {{"LocationCode", iv_locationCode}};
-        addPriority(c);
-        j.emplace_back(c);
-    }
-};
-
-/**
- * @brief A service event requiring a special procedure to be handled by a
- *        service engineer.
- */
-class ProcedureCallout : public Callout
-{
-  public:
-    /** Supported service procedures. */
-    enum Type
-    {
-        NEXTLVL, ///< Contact next level support.
-    };
-
-  public:
-    /**
-     * @brief Constructor from components.
-     * @param i_procedure The location code of the hardware callout.
-     * @param i_priority     The callout priority.
-     */
-    ProcedureCallout(Type i_procedure, Priority i_priority) :
-        Callout(i_priority), iv_procedure(i_procedure)
-    {}
-
-  private:
-    /** The callout priority. */
-    const Type iv_procedure;
-
-  public:
-    void getJson(nlohmann::json& j) const override
-    {
-        // clang-format off
-        static const std::map<Type, std::string> m =
-        {
-            {NEXTLVL, "NEXTLVL"},
-        };
-        // clang-format on
-
-        nlohmann::json c = {{"Procedure", m.at(iv_procedure)}};
-        addPriority(c);
-        j.emplace_back(c);
-    }
-};
-
 /**
  * @brief A service event requiring hardware to be guarded.
  */
@@ -232,7 +90,7 @@
     const bool iv_isCheckstop;
 
     /** The list of callouts that will be added to a PEL. */
-    std::vector<std::shared_ptr<Callout>> iv_calloutList;
+    nlohmann::json iv_calloutList = nlohmann::json::array();
 
     /** The list of hardware guard requests. Some information will be added to
      * the PEL, but the actual guard record will be created after submitting the
@@ -253,8 +111,11 @@
         return iv_isCheckstop;
     }
 
-    /** Add a callout to the list. */
-    void addCallout(const std::shared_ptr<Callout>& i_callout)
+    /**
+     * @brief Add callout information to the callout list.
+     * @param The JSON object for this callout.
+     */
+    void addCallout(const nlohmann::json& i_callout)
     {
         iv_calloutList.push_back(i_callout);
     }
@@ -265,19 +126,10 @@
         iv_guardList.push_back(i_guard);
     }
 
-    /**
-     * @brief Iterates the callout list and returns the json attached to each
-     *        callout in the list.
-     * @param o_json The returned json data.
-     */
-    void getCalloutList(nlohmann::json& o_json) const
+    /** @brief Accessor to iv_calloutList. */
+    const nlohmann::json& getCalloutList() const
     {
-        o_json.clear(); // Ensure we are starting with a clean list.
-
-        for (const auto& c : iv_calloutList)
-        {
-            c->getJson(o_json);
-        }
+        return iv_calloutList;
     }
 
     /**
diff --git a/test/meson.build b/test/meson.build
index 4e61fe2..ea40e4c 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -9,7 +9,6 @@
   'bin_stream_test',
   'ffdc_file_test',
   'resolution_test',
-  'service_data_test',
 ]
 
 gtest = dependency('gtest', main : true, required : false, method : 'system')
diff --git a/test/resolution_test.cpp b/test/resolution_test.cpp
index e8b3f71..13c296a 100644
--- a/test/resolution_test.cpp
+++ b/test/resolution_test.cpp
@@ -27,7 +27,11 @@
         path += "/" + iv_path;
     }
 
-    io_sd.addCallout(std::make_shared<HardwareCallout>(fru, iv_priority));
+    // Add the actual callout to the service data.
+    nlohmann::json callout;
+    callout["LocationCode"] = fru;
+    callout["Priority"]     = iv_priority.getUserDataString();
+    io_sd.addCallout(callout);
 
     Guard::Type guard = Guard::NONE;
     if (iv_guard)
@@ -38,6 +42,17 @@
     io_sd.addGuard(std::make_shared<Guard>(path, guard));
 }
 
+//------------------------------------------------------------------------------
+
+void ProcedureCalloutResolution::resolve(ServiceData& io_sd) const
+{
+    // Add the actual callout to the service data.
+    nlohmann::json callout;
+    callout["Procedure"] = iv_procedure.getString();
+    callout["Priority"]  = iv_priority.getUserDataString();
+    io_sd.addCallout(callout);
+}
+
 } // namespace analyzer
 
 using namespace analyzer;
@@ -46,16 +61,16 @@
 {
     // Create a few resolutions
     auto c1 = std::make_shared<HardwareCalloutResolution>(
-        proc_str, Callout::Priority::HIGH, false);
+        proc_str, callout::Priority::HIGH, false);
 
     auto c2 = std::make_shared<HardwareCalloutResolution>(
-        omi_str, Callout::Priority::MED_A, true);
+        omi_str, callout::Priority::MED_A, true);
 
     auto c3 = std::make_shared<HardwareCalloutResolution>(
-        core_str, Callout::Priority::MED, true);
+        core_str, callout::Priority::MED, true);
 
     auto c4 = std::make_shared<ProcedureCalloutResolution>(
-        ProcedureCallout::NEXTLVL, Callout::Priority::LOW);
+        callout::Procedure::NEXTLVL, callout::Priority::LOW);
 
     // l1 = (c1, c2)
     auto l1 = std::make_shared<ResolutionList>();
@@ -82,7 +97,7 @@
     nlohmann::json j{};
     std::string s{};
 
-    sd1.getCalloutList(j);
+    j = sd1.getCalloutList();
     s = R"([
     {
         "LocationCode": "/proc0",
@@ -108,7 +123,7 @@
 ])";
     ASSERT_EQ(s, j.dump(4));
 
-    sd2.getCalloutList(j);
+    j = sd2.getCalloutList();
     s = R"([
     {
         "Priority": "L",
diff --git a/test/service_data_test.cpp b/test/service_data_test.cpp
deleted file mode 100644
index 01f4556..0000000
--- a/test/service_data_test.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-#include <stdio.h>
-
-#include <analyzer/service_data.hpp>
-
-#include "gtest/gtest.h"
-
-using namespace analyzer;
-
-TEST(ServiceData, TestSet1)
-{
-    libhei::Chip chip{"/proc0", 0xdeadbeef};
-    libhei::Signature rootCause{chip, 0xabcd, 0, 0,
-                                libhei::ATTN_TYPE_CHECKSTOP};
-
-    ServiceData sd{rootCause, true};
-
-    sd.addCallout(std::make_shared<HardwareCallout>("Test location 1",
-                                                    Callout::Priority::HIGH));
-    sd.addCallout(std::make_shared<HardwareCallout>("Test location 2",
-                                                    Callout::Priority::MED_A));
-    sd.addCallout(std::make_shared<ProcedureCallout>(ProcedureCallout::NEXTLVL,
-                                                     Callout::Priority::LOW));
-
-    nlohmann::json j{};
-    sd.getCalloutList(j);
-
-    // Create a RAW string containing what we should expect in the JSON output.
-    std::string s = R"([
-    {
-        "LocationCode": "Test location 1",
-        "Priority": "H"
-    },
-    {
-        "LocationCode": "Test location 2",
-        "Priority": "A"
-    },
-    {
-        "Priority": "L",
-        "Procedure": "NEXTLVL"
-    }
-])";
-
-    ASSERT_EQ(s, j.dump(4));
-}