Add support for callbacks

Callbacks are the response in the PDM 'trigger->response' model.
Add general support for implementing callbacks and implement
a log to systemd journal using that framework.

Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
Change-Id: I8bead5368ee5472a02b47e8bba9e9df3a1f346bc
diff --git a/src/journal.hpp b/src/journal.hpp
new file mode 100644
index 0000000..4e47670
--- /dev/null
+++ b/src/journal.hpp
@@ -0,0 +1,90 @@
+#pragma once
+
+#include <phosphor-logging/log.hpp>
+#include "callback.hpp"
+#include "format.hpp"
+
+namespace phosphor
+{
+namespace dbus
+{
+namespace monitoring
+{
+
+/** @class JournalBase
+ *  @brief Journal callback implementation.
+ *
+ *  The journal callback logs the client message and
+ *  journal metadata key value pairs as specified by the
+ *  client supplied property index.
+ */
+class JournalBase : public IndexedCallback
+{
+    public:
+        JournalBase() = delete;
+        JournalBase(const JournalBase&) = delete;
+        JournalBase(JournalBase&&) = default;
+        JournalBase& operator=(const JournalBase&) = delete;
+        JournalBase& operator=(JournalBase&&) = default;
+        virtual ~JournalBase() = default;
+        JournalBase(const char* msg, const PropertyIndex& index) :
+            IndexedCallback(index), message(msg) {}
+
+        /** @brief Callback interface implementation. */
+        void operator()() override;
+
+    private:
+        /** @brief Delegate type specific calls to subclasses. */
+        virtual void log(
+            const char* message,
+            const std::string& pathMeta,
+            const std::string& path,
+            const std::string& propertyMeta,
+            const any_ns::any& value) const = 0;
+
+        /** @brief The client provided message to be traced.  */
+        const char* message;
+};
+
+/** @class Journal
+ *  @brief C++ type specific logic for the journal callback.
+ *
+ *  @tparam T - The C++ type of the property values being traced.
+ *  @tparam Severity - The log severity of the log entry.
+ */
+template <typename T, phosphor::logging::level Severity>
+class Journal : public JournalBase
+{
+    public:
+        Journal() = delete;
+        Journal(const Journal&) = delete;
+        Journal(Journal&&) = default;
+        Journal& operator=(const Journal&) = delete;
+        Journal& operator=(Journal&&) = default;
+        ~Journal() = default;
+        Journal(const char* msg, const PropertyIndex& index) :
+            JournalBase(msg, index) {}
+
+    private:
+        /** @brief log interface implementation. */
+        void log(
+            const char* message,
+            const std::string& pathMeta,
+            const std::string& path,
+            const std::string& propertyMeta,
+            const any_ns::any& value) const override
+        {
+            phosphor::logging::log<Severity>(
+                message,
+                phosphor::logging::entry(
+                    pathMeta + GetFormat<decltype(pathMeta)>::format,
+                    path),
+                phosphor::logging::entry(
+                    propertyMeta + GetFormat<T>::format,
+                    any_ns::any_cast<T>(value)));
+        }
+};
+
+} // namespace monitoring
+} // namespace dbus
+} // namespace phosphor