Add path conditions

Add support to setProperty and destroyObject to conditionally
perform their action based on the result of a condition testing
functor.

Change-Id: I67ded31f4a7ee0f7a29bb6edc06ebf9249cdc070
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
diff --git a/functor.hpp b/functor.hpp
index 265e467..50fdcfa 100644
--- a/functor.hpp
+++ b/functor.hpp
@@ -45,15 +45,51 @@
     return Filter(std::forward<T>(filter));
 }
 
+/** @brief make_path_condition
+ *
+ *  Adapt a path_condition function object.
+ *
+ *  @param[in] filter - The functor being adapted.
+ *  @returns - The adapted functor.
+ *
+ *  @tparam T - The type of the functor being adapted.
+ */
+template <typename T>
+auto make_path_condition(T&& condition)
+{
+    return PathCondition(std::forward<T>(condition));
+}
+
+template <typename T, typename ...Args>
+auto callArrayWithStatus(T&& container, Args&& ...args)
+{
+    for (auto f : container)
+    {
+        if (!f(std::forward<Args>(args)...))
+        {
+            return false;
+        }
+    }
+    return true;
+}
+
 namespace functor
 {
 
 /** @brief Destroy objects action.  */
-inline auto destroyObjects(std::vector<const char*>&& paths)
+inline auto destroyObjects(
+    std::vector<const char*>&& paths,
+    std::vector<PathCondition>&& conditions)
 {
-    return [ = ](auto&, auto & m)
+    return [ = ](auto & b, auto & m)
     {
-        m.destroyObjects(paths);
+        for (const auto& p : paths)
+        {
+            if (callArrayWithStatus(conditions, p, b, m))
+            {
+                m.destroyObjects({p});
+            }
+        }
     };
 }
 
@@ -88,20 +124,27 @@
  */
 template <typename T, typename U, typename V>
 auto setProperty(
-    std::vector<const char*>&& paths, const char* iface,
-    U&& member, V&& value)
+    std::vector<const char*>&& paths,
+    std::vector<PathCondition>&& conditions,
+    const char* iface,
+    U&& member,
+    V&& value)
 {
     // The manager is the only parameter passed to actions.
     // Bind the path, interface, interface member function pointer,
     // and value to a lambda.  When it is called, forward the
     // path, interface and value on to the manager member function.
-    return [paths, iface, member,
-                  value = std::forward<V>(value)](auto&, auto & m)
+    return [paths, conditions = conditions, iface,
+                  member,
+                  value = std::forward<V>(value)](auto & b, auto & m)
     {
         for (auto p : paths)
         {
-            m.template invokeMethod<T>(
-                p, iface, member, value);
+            if (callArrayWithStatus(conditions, p, b, m))
+            {
+                m.template invokeMethod<T>(
+                    p, iface, member, value);
+            }
         }
     };
 }
@@ -199,7 +242,7 @@
             const char* iface,
             const char* property,
             const char* service) :
-            _path(path),
+            _path(path ? path : std::string()),
             _iface(iface),
             _property(property),
             _service(service) {}
@@ -216,6 +259,15 @@
             sdbusplus::message::message&,
             Manager&) const;
 
+        /** @brief Test a property value.
+         *
+         * Make a DBus call and test the value of any property.
+         */
+        bool operator()(
+            const std::string&,
+            sdbusplus::bus::bus&,
+            Manager&) const;
+
     private:
         std::string _path;
         std::string _iface;