Add conditional callbacks

Enable conditional application of callbacks.

Change-Id: I9d765e5f585aac40994b65da3b51ea891beae9bf
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
diff --git a/src/callback.hpp b/src/callback.hpp
index 7c6f69b..f7886cb 100644
--- a/src/callback.hpp
+++ b/src/callback.hpp
@@ -28,6 +28,50 @@
         virtual void operator()() = 0;
 };
 
+/** @class Conditional
+ *  @brief Condition interface.
+ *
+ *  Conditions of any type can be tested for true or false.
+ */
+class Conditional
+{
+    public:
+        Conditional() = default;
+        Conditional(const Conditional&) = delete;
+        Conditional(Conditional&&) = default;
+        Conditional& operator=(const Conditional&) = delete;
+        Conditional& operator=(Conditional&&) = default;
+        virtual ~Conditional() = default;
+
+        /** @brief Test the condition. */
+        virtual bool operator()() = 0;
+};
+
+/** @class IndexedConditional
+ *  @brief Condition with an index.
+ */
+class IndexedConditional : public Conditional
+{
+    public:
+        IndexedConditional() = delete;
+        IndexedConditional(const IndexedConditional&) = delete;
+        IndexedConditional(IndexedConditional&&) = default;
+        IndexedConditional& operator=(const IndexedConditional&) = delete;
+        IndexedConditional& operator=(IndexedConditional&&) = default;
+        virtual ~IndexedConditional() = default;
+
+        explicit IndexedConditional(const PropertyIndex& conditionIndex)
+            : Conditional(), index(conditionIndex) {}
+
+        /** @brief Test the condition. */
+        virtual bool operator()() override = 0;
+
+    protected:
+
+        /** @brief Property names and their associated storage. */
+        const PropertyIndex& index;
+};
+
 /** @class IndexedCallback
  *  @brief Callback with an index.
  */
@@ -90,6 +134,41 @@
         const std::vector<size_t>& graph;
 };
 
+/** @class ConditionalCallback
+ *  @brief Callback adaptor that asssociates a condition with a callback.
+ */
+template <typename CallbackAccess>
+class ConditionalCallback: public Callback
+{
+    public:
+        ConditionalCallback() = delete;
+        ConditionalCallback(const ConditionalCallback&) = delete;
+        ConditionalCallback(ConditionalCallback&&) = default;
+        ConditionalCallback& operator=(const ConditionalCallback&) = delete;
+        ConditionalCallback& operator=(ConditionalCallback&&) = default;
+        ~ConditionalCallback() = default;
+        ConditionalCallback(
+            const std::vector<size_t>& graphEntry,
+            Conditional& cond)
+            : graph(graphEntry), condition(cond) {}
+
+        /** @brief Run the callback if the condition is satisfied. */
+        void operator()() override
+        {
+            if (condition())
+            {
+                (*CallbackAccess::get()[graph[0]])();
+            }
+        }
+
+    private:
+        /** @brief The index of the callback to conditionally invoke. */
+        const std::vector<size_t>& graph;
+
+        /** @brief The condition to test. */
+        Conditional& condition;
+};
+
 } // namespace monitoring
 } // namespace dbus
 } // namespace phosphor