Add associations::Manager class

This class will handle creating the org.openbmc.Associations
D-Bus interfaces on inventory paths if it has been told to
by a JSON configuration file.

Every time PIM creates a new inventory path, this class will
check to see if any associations need to be created.

This functionality is optional, and is off by default.  To
enable it, the --enable-associations configure option needs to
be used.

This commit just introduces the class.

Change-Id: I70045b768f3db683bcfac0c7d4bc9798eb10a5c5
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
diff --git a/Makefile.am b/Makefile.am
index d045e64..7d0e1d4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -17,6 +17,11 @@
 	errors.cpp \
 	functor.cpp \
 	manager.cpp
+
+if CREATE_INV_ASSOCIATIONS
+libmanagercommon_la_SOURCES += association_manager.cpp
+endif
+
 libmanagercommon_la_LIBADD = \
 	$(SDBUSPLUS_LIBS) \
 	$(PHOSPHOR_DBUS_INTERFACES_LIBS) \
diff --git a/association_manager.cpp b/association_manager.cpp
new file mode 100644
index 0000000..41f135d
--- /dev/null
+++ b/association_manager.cpp
@@ -0,0 +1,24 @@
+#include "association_manager.hpp"
+
+namespace phosphor
+{
+namespace inventory
+{
+namespace manager
+{
+namespace associations
+{
+
+Manager::Manager(sdbusplus::bus::bus& bus, const std::string& jsonPath) :
+    _bus(bus), _jsonFile(jsonPath)
+{
+}
+
+void Manager::createAssociations(const std::string& objectPath)
+{
+    // TODO
+}
+} // namespace associations
+} // namespace manager
+} // namespace inventory
+} // namespace phosphor
diff --git a/association_manager.hpp b/association_manager.hpp
new file mode 100644
index 0000000..1aff7e0
--- /dev/null
+++ b/association_manager.hpp
@@ -0,0 +1,84 @@
+#pragma once
+
+#include "config.h"
+
+#include <sdbusplus/bus.hpp>
+
+namespace phosphor
+{
+namespace inventory
+{
+namespace manager
+{
+namespace associations
+{
+
+/**
+ * @class Manager
+ *
+ * @brief This class provides the ability to add org.openbmc.Associations
+ *        interfaces on inventory D-Bus objects, based on a definition in a
+ *        JSON file.
+ *
+ *        The purpose for this is to be able to associate other D-Bus paths
+ *        with the inventory items they relate to.
+ *
+ *        For example, a card temperature sensor D-Bus object can be associated
+ *        with the D-Bus object for that card's inventory entry so that some
+ *        code can tie them together.
+ */
+class Manager
+{
+  public:
+    Manager() = delete;
+    ~Manager() = default;
+    Manager(const Manager&) = delete;
+    Manager& operator=(const Manager&) = delete;
+    Manager(Manager&&) = delete;
+    Manager& operator=(Manager&&) = delete;
+
+    /**
+     * @brief Constructor
+     *
+     * @param[in] bus - sdbusplus object
+     * @param[in] jsonPath - path to the JSON File that contains associations
+     */
+    Manager(sdbusplus::bus::bus& bus, const std::string& jsonPath);
+
+    /**
+     * @brief Constructor
+     *
+     * @param[in] bus - sdbusplus object
+     */
+    explicit Manager(sdbusplus::bus::bus& bus) :
+        Manager(bus, ASSOCIATIONS_FILE_PATH)
+    {
+    }
+
+    /**
+     * @brief Creates any association D-Bus interfaces required based on
+     *        the JSON associations definition for the object path passed
+     *        in.
+     *
+     * Called after PIM creates a new inventory D-Bus interface on objectPath.
+     *
+     * @param[in] objectPath - the D-Bus object path to check for associations
+     */
+    void createAssociations(const std::string& objectPath);
+
+  private:
+    /**
+     * @brief The sdbusplus bus object.
+     */
+    sdbusplus::bus::bus& _bus;
+
+    /**
+     * @brief The path to the associations JSON File.
+     */
+    const std::string _jsonFile;
+};
+
+} // namespace associations
+} // namespace manager
+} // namespace inventory
+} // namespace phosphor
diff --git a/configure.ac b/configure.ac
index 482fa5b..e159549 100644
--- a/configure.ac
+++ b/configure.ac
@@ -90,6 +90,28 @@
 AC_DEFINE_UNQUOTED([PIM_PERSIST_PATH], ["$PIM_PERSIST_PATH"], \
     [Path of directory housing persisted inventory])
 
+AC_ARG_ENABLE([associations],
+    AS_HELP_STRING([--enable-associations], [Enable creating D-Bus associations from a JSON definition.])
+)
+
+AC_ARG_VAR(CREATE_ASSOCIATIONS, [If associations should be created from a JSON definition.])
+
+AS_IF([test "x$enable_associations" == "xyes"],
+    [CREATE_ASSOCIATIONS="yes"]
+    AC_DEFINE_UNQUOTED([CREATE_ASSOCIATIONS], ["$CREATE_ASSOCIATIONS"],
+                         [If associations should be created from a JSON definition.])
+    AC_CHECK_HEADER(nlohmann/json.hpp, ,
+                    [AC_MSG_ERROR([Could not find nlohmann/json.hpp... nlohmann/json package required])])
+)
+
+AM_CONDITIONAL([CREATE_INV_ASSOCIATIONS], [test "x$enable_associations" == "xyes"])
+
+AC_ARG_VAR(ASSOCIATIONS_FILE_PATH, [Path of associations JSON file.])
+AS_IF([test "x$ASSOCIATIONS_FILE_PATH" == "x"], \
+    [ASSOCIATIONS_FILE_PATH="/usr/share/phosphor-inventory-manager/associations.json"])
+AC_DEFINE_UNQUOTED([ASSOCIATIONS_FILE_PATH], ["$ASSOCIATIONS_FILE_PATH"], \
+    [Path of associations JSON file])
+
 AC_ARG_VAR(CLASS_VERSION, [Class version to register with Cereal])
 AS_IF([test "x$CLASS_VERSION" == "x"], [CLASS_VERSION=1])
 AC_DEFINE_UNQUOTED([CLASS_VERSION], [$CLASS_VERSION], [Class version to register with Cereal])
diff --git a/manager.cpp b/manager.cpp
index a665ea8..c9d84c6 100644
--- a/manager.cpp
+++ b/manager.cpp
@@ -60,6 +60,10 @@
                  const char* root, const char* iface) :
     ServerObject<ManagerIface>(bus, root),
     _shutdown(false), _root(root), _bus(std::move(bus)), _manager(_bus, root)
+#ifdef CREATE_ASSOCIATIONS
+    ,
+    _associations(_bus)
+#endif
 {
     for (auto& group : _events)
     {
@@ -237,6 +241,12 @@
 
         updateInterfaces(absPath, objit->second, refit, newObj,
                          restoreFromCache);
+#ifdef CREATE_ASSOCIATIONS
+        if (newObj)
+        {
+            _associations.createAssociations(absPath);
+        }
+#endif
         ++objit;
     }
 }
diff --git a/manager.hpp b/manager.hpp
index cabbac9..5ad4f44 100644
--- a/manager.hpp
+++ b/manager.hpp
@@ -5,6 +5,9 @@
 #include "interface_ops.hpp"
 #include "serialize.hpp"
 #include "types.hpp"
+#ifdef CREATE_ASSOCIATIONS
+#include "association_manager.hpp"
+#endif
 
 #include <any>
 #include <map>
@@ -205,6 +208,11 @@
 
     /** @brief A container of pimgen generated factory methods.  */
     static const Makers _makers;
+
+    /** @brief Handles creating mapper associations for inventory objects */
+#ifdef CREATE_ASSOCIATIONS
+    associations::Manager _associations;
+#endif
 };
 
 } // namespace manager