Merge actions.hpp and events.hpp

Move all action/filter functors to a common functor.hpp.
The intent of this refactoring is to facilitate reuse
of functors in more than one context.

 - Moved functors from actions.hpp and events.hpp to functor.hpp.
 - Renamed events.cpp to functor.cpp.
 - Moved Action/Filter types to types.hpp.
 - Minor namespace shuffling.
 - Update pimgen to render according to the new namespaces.

Change-Id: I630ec1587b8a48f6dc2eac1111365035873310d9
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
diff --git a/functor.hpp b/functor.hpp
new file mode 100644
index 0000000..265e467
--- /dev/null
+++ b/functor.hpp
@@ -0,0 +1,320 @@
+#pragma once
+
+#include <utility>
+#include <memory>
+#include <sdbusplus/bus.hpp>
+#include "utils.hpp"
+#include "types.hpp"
+
+namespace phosphor
+{
+namespace inventory
+{
+namespace manager
+{
+
+class Manager;
+
+/** @brief make_action
+ *
+ *  Adapt an action function object.
+ *
+ *  @param[in] action - The action being adapted.
+ *  @returns - The adapted action.
+ *
+ *  @tparam T - The type of the action being adapted.
+ */
+template <typename T>
+auto make_action(T&& action)
+{
+    return Action(std::forward<T>(action));
+}
+
+/** @brief make_filter
+ *
+ *  Adapt a filter function object.
+ *
+ *  @param[in] filter - The filter being adapted.
+ *  @returns - The adapted filter.
+ *
+ *  @tparam T - The type of the filter being adapted.
+ */
+template <typename T>
+auto make_filter(T&& filter)
+{
+    return Filter(std::forward<T>(filter));
+}
+
+namespace functor
+{
+
+/** @brief Destroy objects action.  */
+inline auto destroyObjects(std::vector<const char*>&& paths)
+{
+    return [ = ](auto&, auto & m)
+    {
+        m.destroyObjects(paths);
+    };
+}
+
+/** @brief Create objects action.  */
+inline auto createObjects(
+    std::map<sdbusplus::message::object_path, Object>&& objs)
+{
+    return [ = ](auto&, auto & m)
+    {
+        m.createObjects(objs);
+    };
+}
+
+/** @brief Set a property action.
+ *
+ *  Invoke the requested method with a reference to the requested
+ *  sdbusplus server binding interface as a parameter.
+ *
+ *  @tparam T - The sdbusplus server binding interface type.
+ *  @tparam U - The type of the sdbusplus server binding member
+ *      function that sets the property.
+ *  @tparam V - The property value type.
+ *
+ *  @param[in] paths - The DBus paths on which the property should
+ *      be set.
+ *  @param[in] iface - The DBus interface hosting the property.
+ *  @param[in] member - Pointer to sdbusplus server binding member.
+ *  @param[in] value - The value the property should be set to.
+ *
+ *  @returns - A function object that sets the requested property
+ *      to the requested value.
+ */
+template <typename T, typename U, typename V>
+auto setProperty(
+    std::vector<const char*>&& paths, 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)
+    {
+        for (auto p : paths)
+        {
+            m.template invokeMethod<T>(
+                p, iface, member, value);
+        }
+    };
+}
+
+/** @struct PropertyChangedCondition
+ *  @brief Match filter functor that tests a property value.
+ *
+ *  @tparam T - The type of the property being tested.
+ *  @tparam U - The type of the condition checking functor.
+ */
+template <typename T, typename U>
+struct PropertyChangedCondition
+{
+        PropertyChangedCondition() = delete;
+        ~PropertyChangedCondition() = default;
+        PropertyChangedCondition(const PropertyChangedCondition&) = default;
+        PropertyChangedCondition& operator=(const PropertyChangedCondition&) = default;
+        PropertyChangedCondition(PropertyChangedCondition&&) = default;
+        PropertyChangedCondition& operator=(PropertyChangedCondition&&) = default;
+        PropertyChangedCondition(const char* iface, const char* property,
+                                 U&& condition) :
+            _iface(iface),
+            _property(property),
+            _condition(std::forward<U>(condition)) { }
+
+        /** @brief Test a property value.
+         *
+         * Extract the property from the PropertiesChanged
+         * message and run the condition test.
+         */
+        bool operator()(
+            sdbusplus::bus::bus&,
+            sdbusplus::message::message& msg,
+            Manager&) const
+        {
+            std::map <
+            std::string,
+                sdbusplus::message::variant<T >> properties;
+            const char* iface = nullptr;
+
+            msg.read(iface);
+            if (!iface || strcmp(iface, _iface))
+            {
+                return false;
+            }
+
+            msg.read(properties);
+            auto it = properties.find(_property);
+            if (it == properties.cend())
+            {
+                return false;
+            }
+
+            return _condition(
+                       std::forward<T>(it->second.template get<T>()));
+        }
+
+    private:
+        const char* _iface;
+        const char* _property;
+        U _condition;
+};
+
+/** @struct PropertyConditionBase
+ *  @brief Match filter functor that tests a property value.
+ *
+ *  Base class for PropertyCondition - factored out code that
+ *  doesn't need to be templated.
+ */
+struct PropertyConditionBase
+{
+        PropertyConditionBase() = delete;
+        virtual ~PropertyConditionBase() = default;
+        PropertyConditionBase(const PropertyConditionBase&) = default;
+        PropertyConditionBase& operator=(const PropertyConditionBase&) = default;
+        PropertyConditionBase(PropertyConditionBase&&) = default;
+        PropertyConditionBase& operator=(PropertyConditionBase&&) = default;
+
+        /** @brief Constructor
+         *
+         *  The service argument can be nullptr.  If something
+         *  else is provided the function will call the the
+         *  service directly.  If omitted, the function will
+         *  look up the service in the ObjectMapper.
+         *
+         *  @param path - The path of the object containing
+         *     the property to be tested.
+         *  @param iface - The interface hosting the property
+         *     to be tested.
+         *  @param property - The property to be tested.
+         *  @param service - The DBus service hosting the object.
+         */
+        PropertyConditionBase(
+            const char* path,
+            const char* iface,
+            const char* property,
+            const char* service) :
+            _path(path),
+            _iface(iface),
+            _property(property),
+            _service(service) {}
+
+        /** @brief Forward comparison to type specific implementation. */
+        virtual bool eval(sdbusplus::message::message&) const = 0;
+
+        /** @brief Test a property value.
+         *
+         * Make a DBus call and test the value of any property.
+         */
+        bool operator()(
+            sdbusplus::bus::bus&,
+            sdbusplus::message::message&,
+            Manager&) const;
+
+    private:
+        std::string _path;
+        std::string _iface;
+        std::string _property;
+        const char* _service;
+};
+
+/** @struct PropertyCondition
+ *  @brief Match filter functor that tests a property value.
+ *
+ *  @tparam T - The type of the property being tested.
+ *  @tparam U - The type of the condition checking functor.
+ */
+template <typename T, typename U>
+struct PropertyCondition final : public PropertyConditionBase
+{
+        PropertyCondition() = delete;
+        ~PropertyCondition() = default;
+        PropertyCondition(const PropertyCondition&) = default;
+        PropertyCondition& operator=(const PropertyCondition&) = default;
+        PropertyCondition(PropertyCondition&&) = default;
+        PropertyCondition& operator=(PropertyCondition&&) = default;
+
+        /** @brief Constructor
+         *
+         *  The service argument can be nullptr.  If something
+         *  else is provided the function will call the the
+         *  service directly.  If omitted, the function will
+         *  look up the service in the ObjectMapper.
+         *
+         *  @param path - The path of the object containing
+         *     the property to be tested.
+         *  @param iface - The interface hosting the property
+         *     to be tested.
+         *  @param property - The property to be tested.
+         *  @param condition - The test to run on the property.
+         *  @param service - The DBus service hosting the object.
+         */
+        PropertyCondition(
+            const char* path,
+            const char* iface,
+            const char* property,
+            U&& condition,
+            const char* service) :
+            PropertyConditionBase(path, iface, property, service),
+            _condition(std::forward<decltype(condition)>(condition)) {}
+
+        /** @brief Test a property value.
+         *
+         * Make a DBus call and test the value of any property.
+         */
+        bool eval(sdbusplus::message::message& msg) const override
+        {
+            sdbusplus::message::variant<T> value;
+            msg.read(value);
+            return _condition(
+                       std::forward<T>(value.template get<T>()));
+        }
+
+    private:
+        U _condition;
+};
+
+/** @brief Implicit type deduction for constructing PropertyChangedCondition.  */
+template <typename T>
+auto propertyChangedTo(
+    const char* iface,
+    const char* property,
+    T&& val)
+{
+    auto condition = [val = std::forward<T>(val)](T && arg)
+    {
+        return arg == val;
+    };
+    using U = decltype(condition);
+    return PropertyChangedCondition<T, U>(
+               iface, property, std::move(condition));
+}
+
+/** @brief Implicit type deduction for constructing PropertyCondition.  */
+template <typename T>
+auto propertyIs(
+    const char* path,
+    const char* iface,
+    const char* property,
+    T&& val,
+    const char* service = nullptr)
+{
+    auto condition = [val = std::forward<T>(val)](T && arg)
+    {
+        return arg == val;
+    };
+    using U = decltype(condition);
+    return PropertyCondition<T, U>(
+               path, iface, property, std::move(condition), service);
+}
+} // namespace functor
+} // namespace manager
+} // namespace inventory
+} // namespace phosphor
+
+// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4