Allow arrays of dbus events

The current event <-> action relationship is one to many.
Allow a many to many relationship to be expressed.

Change-Id: Ibfb995cbf677b21757864dc62d9a3818af6c2aa3
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
diff --git a/generated.mako.cpp b/generated.mako.cpp
index 2dccf82..8534674 100644
--- a/generated.mako.cpp
+++ b/generated.mako.cpp
@@ -38,7 +38,8 @@
         // ${e['description']}
     % endif
         std::make_tuple(
-            std::make_shared<details::DbusSignal>(
+            std::vector<details::EventBasePtr>({
+                std::make_shared<details::DbusSignal>(
         % for i, s in enumerate(e['signature'].items()):
             % if i + 1 == len(e['signature']):
             ${'"{0}=\'{1}\'"'.format(*s)},
@@ -50,13 +51,13 @@
                 details::make_filter(filters::${e['filter']['type']}(
                 % for i, a in enumerate(e['filter']['args']):
                     % if i + 1 == len(e['filter']['args']):
-                "${a['value']}"))),
+                "${a['value']}")))}),
                     % else:
                 "${a['value']}",
                     % endif
                 % endfor
             % else:
-                details::make_filter(filters::${e['filter']['type']})),
+                details::make_filter(filters::${e['filter']['type']}))}),
             % endif
             % if e['action'].get('args'):
             std::vector<details::ActionBasePtr>({details::make_action(actions::${e['action']['type']}(
diff --git a/manager.cpp b/manager.cpp
index 07d3d31..b9e8ace 100644
--- a/manager.cpp
+++ b/manager.cpp
@@ -38,7 +38,11 @@
         auto &args = *static_cast<Manager::SigArg*>(data);
         sd_bus_message_ref(m);
         auto &mgr = *std::get<0>(args);
-        mgr.signal(msg, *std::get<1>(args));
+        mgr.signal(
+                msg,
+                static_cast<const details::DbusSignal &>(
+                    *std::get<1>(args)),
+                *std::get<2>(args));
     }
     catch (const std::exception &e) {
         std::cerr << e.what() << std::endl;
@@ -60,28 +64,38 @@
     _bus(std::move(bus)),
     _manager(sdbusplus::server::manager::manager(_bus, root))
 {
-    for (auto &x: _events) {
-        auto pEvent = std::get<0>(x);
-        if (pEvent->type !=
-                details::Event::Type::DBUS_SIGNAL)
-            continue;
+    for (auto &group: _events)
+    {
+        for (auto pEvent: std::get<0>(group))
+        {
+            if (pEvent->type !=
+                    details::Event::Type::DBUS_SIGNAL)
+                continue;
 
-        // Create a callback context for each event.
-        _sigargs.emplace_back(
-                std::make_unique<SigArg>(
-                    std::make_tuple(
-                        this,
-                        &x)));
-        // Register our callback and the context for
-        // each event.
-        auto &dbusEvent = static_cast<details::DbusSignal &>(
-                *pEvent);
-        _matches.emplace_back(
-                sdbusplus::server::match::match(
-                    _bus,
-                    std::get<0>(dbusEvent),
-                    details::_signal,
-                    _sigargs.back().get()));
+            // Create a callback context for this event group.
+            auto dbusEvent = static_cast<details::DbusSignal *>(
+                    pEvent.get());
+
+            // Go ahead and store an iterator pointing at
+            // the event data to avoid lookups later since
+            // additional signal callbacks aren't added
+            // after the manager is constructed.
+            _sigargs.emplace_back(
+                    std::make_unique<SigArg>(
+                        std::make_tuple(
+                            this,
+                            dbusEvent,
+                            &group)));
+
+            // Register our callback and the context for
+            // each signal event.
+            _matches.emplace_back(
+                    sdbusplus::server::match::match(
+                        _bus,
+                        std::get<0>(*dbusEvent),
+                        details::_signal,
+                        _sigargs.back().get()));
+        }
     }
 
     _bus.request_name(busname);
@@ -149,11 +163,13 @@
     }
 }
 
-void Manager::signal(sdbusplus::message::message &msg, auto &args)
+void Manager::signal(
+        sdbusplus::message::message &msg,
+        const details::DbusSignal &event,
+        const EventInfo &info)
 {
-    auto &event = std::get<0>(args);
-    auto &actions = std::get<1>(args);
-    auto &filter = *std::get<1>(static_cast<details::DbusSignal &>(*event));
+    auto &filter = *std::get<1>(event);
+    auto &actions = std::get<1>(info);
 
     if(filter(msg, *this)) {
         for (auto &action: actions)
diff --git a/manager.hpp b/manager.hpp
index c905b8b..92afd9f 100644
--- a/manager.hpp
+++ b/manager.hpp
@@ -78,6 +78,9 @@
     using Object = std::map<
         std::string, std::map<
             std::string, sdbusplus::message::variant<std::string>>>;
+    using EventInfo = std::tuple<
+        std::vector<details::EventBasePtr>,
+        std::vector<details::ActionBasePtr>>;
 
     /** @brief Start processing DBus messages. */
     void run() noexcept;
@@ -89,18 +92,18 @@
     void notify(std::string path, Object) override;
 
     /** @brief sd_bus signal callback. */
-    void signal(sdbusplus::message::message &, auto &);
+    void signal(sdbusplus::message::message&,
+            const details::DbusSignal &event,
+            const EventInfo &info);
 
     /** @brief Drop an object from DBus. */
     void destroyObject(const char *);
 
-    using EventInfo = std::tuple<
-        details::EventBasePtr,
-        std::vector<details::ActionBasePtr>>;
     using SigArgs = std::vector<
         std::unique_ptr<
             std::tuple<
                 Manager *,
+                const details::DbusSignal *,
                 const EventInfo *>>>;
     using SigArg = SigArgs::value_type::element_type;