created Callout classes for various PEL callouts

Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
Change-Id: Ia36c52281ebd425ab1c38be57ff35ea19ee01740
diff --git a/analyzer/service_data.hpp b/analyzer/service_data.hpp
new file mode 100644
index 0000000..9c5e6fd
--- /dev/null
+++ b/analyzer/service_data.hpp
@@ -0,0 +1,151 @@
+#pragma once
+
+#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 Procedure
+    {
+        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(Procedure i_procedure, Priority i_priority) :
+        Callout(i_priority), iv_procedure(i_procedure)
+    {}
+
+  private:
+    /** The callout priority. */
+    const Procedure iv_procedure;
+
+  public:
+    void getJson(nlohmann::json& j) const override
+    {
+        // clang-format off
+        static const std::map<Procedure, std::string> m =
+        {
+            {NEXTLVL, "NEXTLVL"},
+        };
+        // clang-format on
+
+        nlohmann::json c = {{"Procedure", m.at(iv_procedure)}};
+        addPriority(c);
+        j.emplace_back(c);
+    }
+};
+
+} // namespace analyzer
diff --git a/test/meson.build b/test/meson.build
index 764ab9a..676c518 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -8,6 +8,7 @@
 tests = [
   'hello-world',
   'bin_stream_test',
+  'service_data_test',
 ]
 
 gtest = dependency('gtest', main : true, required : false, method : 'system')
diff --git a/test/service_data_test.cpp b/test/service_data_test.cpp
new file mode 100644
index 0000000..4f8505e
--- /dev/null
+++ b/test/service_data_test.cpp
@@ -0,0 +1,38 @@
+#include <stdio.h>
+
+#include <analyzer/service_data.hpp>
+
+#include "gtest/gtest.h"
+
+using namespace analyzer;
+
+TEST(SericeData, TestSet1)
+{
+    HardwareCallout c1{"Test location 1", Callout::Priority::HIGH};
+    HardwareCallout c2{"Test location 2", Callout::Priority::MED_A};
+    ProcedureCallout c3{ProcedureCallout::NEXTLVL, Callout::Priority::LOW};
+
+    nlohmann::json j{};
+
+    c1.getJson(j);
+    c2.getJson(j);
+    c3.getJson(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));
+}