Add policy::Table class

This class holds the error log policy data defined by
IBM's service people.  The raw data is stored in a JSON
file on the BMC, and loaded into the class on construction.

The policy data is a map of error messages (i.e.  the
xyz.openbmc_project.Foo.Error.Bar strings) to a list of
policy details structures.

Each details structure has:
* a search modifier - used to find the specific details
  entry for a specific error log message.
* a message - a customer facing description of the error
* an event ID - an ID defined by IBM that can be used to
                locate information about the error online.

An example of an entry of the JSON data it consumes is:
  {
    "dtls":[
      {
        "CEID":"ID 1",
        "mod":"mod 1",
        "msg":"Error 1"
      },
      {
        "CEID":"ID 2",
        "mod":"mod 2",
        "msg":"Error 2 "
      }
    ],
    "err":"xyz.openbmc_project.Error.Test1"
  }

A future commit will add the ability to find an entry.

Change-Id: I9869c15799914acf9cbc9d91ff714edb6e2512ef
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
diff --git a/Makefile.am b/Makefile.am
index 0997d31..67d142c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5,7 +5,8 @@
 ibm_log_manager_SOURCES = \
 	dbus.cpp \
 	main.cpp \
-	manager.cpp
+	manager.cpp \
+	policy_table.cpp
 
 ibm_log_manager_CXX_FLAGS =  \
 	$(PHOSPHOR_DBUS_INTERFACES_CFLAGS) \
diff --git a/configure.ac b/configure.ac
index 6b38795..9bbe9fb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,6 +17,9 @@
 PKG_CHECK_MODULES([PHOSPHOR_LOGGING], [phosphor-logging],,\
     AC_MSG_ERROR(["Requires openbmc/phosphor-logging package."]))
 
+AC_CHECK_HEADER(nlohmann/json.hpp, ,
+                [AC_MSG_ERROR([Could not find nlohmann/json.hpp... nlohmann/json package required])])
+
 # Checks for typedefs, structures, and compiler characteristics.
 AX_CXX_COMPILE_STDCXX_14([noext])
 AX_APPEND_COMPILE_FLAGS([-Wall -Werror], [CXXFLAGS])
diff --git a/policy_table.cpp b/policy_table.cpp
new file mode 100644
index 0000000..247ff4f
--- /dev/null
+++ b/policy_table.cpp
@@ -0,0 +1,81 @@
+/**
+ * Copyright © 2018 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.
+ */
+#include <experimental/filesystem>
+#include <fstream>
+#include <nlohmann/json.hpp>
+#include <phosphor-logging/log.hpp>
+#include "policy_table.hpp"
+
+namespace ibm
+{
+namespace logging
+{
+namespace policy
+{
+
+namespace fs = std::experimental::filesystem;
+using namespace phosphor::logging;
+
+Table::Table(const std::string& jsonFile)
+{
+    if (fs::exists(jsonFile))
+    {
+        load(jsonFile);
+    }
+    else
+    {
+        log<level::INFO>("Policy table JSON file does not exist",
+                entry("FILE=%s", jsonFile.c_str()));
+    }
+}
+
+void Table::load(const std::string& jsonFile)
+{
+    try
+    {
+        std::ifstream file{jsonFile};
+
+        auto json = nlohmann::json::parse(file, nullptr, true);
+
+        for (const auto& policy : json)
+        {
+            DetailsList detailsList;
+
+            for (const auto& details : policy["dtls"])
+            {
+                Details d;
+                d.modifier = details["mod"];
+                d.msg = details["msg"];
+                d.ceid = details["CEID"];
+                detailsList.emplace_back(std::move(d));
+            }
+            policies.emplace(policy["err"], std::move(detailsList));
+        }
+
+        loaded = true;
+    }
+    catch (std::exception& e)
+    {
+        log<level::ERR>("Failed loading policy table json file",
+                entry("FILE=%s", jsonFile.c_str()),
+                entry("ERROR=%s", e.what()));
+        loaded = false;
+    }
+}
+
+}
+}
+}
diff --git a/policy_table.hpp b/policy_table.hpp
new file mode 100644
index 0000000..b6fade3
--- /dev/null
+++ b/policy_table.hpp
@@ -0,0 +1,90 @@
+#pragma once
+
+#include <map>
+#include <vector>
+#include "config.h"
+
+namespace ibm
+{
+namespace logging
+{
+namespace policy
+{
+
+
+/**
+ *  The details of a policy table entry:
+ *  - search modifier
+ *  - error message
+ *  - common error event ID
+ */
+struct Details
+{
+    std::string modifier;
+    std::string msg;
+    std::string ceid;
+};
+
+using DetailsList = std::vector<Details>;
+using PolicyMap = std::map<std::string, DetailsList>;
+
+/**
+ * @class Table
+ *
+ * This class wraps the error policy table data, and provides the
+ * ability to find a policy table entry based on the error and a
+ * search modifier.  This data contains additional information
+ * about error logs and may be system specific.
+ */
+class Table
+{
+    public:
+
+        Table() = delete;
+        ~Table() = default;
+        Table(const Table&) = default;
+        Table& operator=(const Table&) = default;
+        Table(Table&&) = default;
+        Table& operator=(Table&&) = default;
+
+        /**
+         * Constructor
+         *
+         * @param[in] jsonFile - the path to the policy JSON.
+         */
+        explicit Table(const std::string& jsonFile);
+
+        /**
+         * Says if the JSON has been loaded successfully.
+         *
+         * @return bool
+         */
+        inline bool isLoaded() const
+        {
+            return loaded;
+        }
+
+    private:
+
+        /**
+         * Loads the JSON data into the PolicyMap map
+         *
+         * @param[in] jsonFile - the path to the .json file
+         */
+        void load(const std::string& jsonFile);
+
+        /**
+         * Reflects if the JSON was successfully loaded or not.
+         */
+        bool loaded = false;
+
+        /**
+         * The policy table
+         */
+        PolicyMap policies;
+};
+
+
+}
+}
+}