Add object/interface update methods

Add methods that handle both adding/updating
objects/interfaces.

Change-Id: I3c682365aad18f439babfb0413f29af05327eead
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
diff --git a/manager.cpp b/manager.cpp
index 0c6831e..820eb62 100644
--- a/manager.cpp
+++ b/manager.cpp
@@ -16,8 +16,10 @@
 #include <iostream>
 #include <exception>
 #include <chrono>
+#include <algorithm>
 #include <log.hpp>
 #include "manager.hpp"
+#include "errors.hpp"
 
 using namespace std::literals::chrono_literals;
 
@@ -140,6 +142,122 @@
     }
 }
 
+void Manager::updateInterfaces(
+    const sdbusplus::message::object_path& path,
+    const Object& interfaces,
+    ObjectReferences::iterator pos,
+    bool newObject)
+{
+    auto& refaces = pos->second;
+    auto ifaceit = interfaces.cbegin();
+    auto opsit = _makers.cbegin();
+    auto refaceit = refaces.begin();
+    std::vector<std::string> signals;
+
+    while (ifaceit != interfaces.cend())
+    {
+        try
+        {
+            // Find the binding ops for this interface.
+            opsit = std::lower_bound(
+                        opsit,
+                        _makers.cend(),
+                        ifaceit->first,
+                        compareFirst(_makers.key_comp()));
+
+            if (opsit == _makers.cend() || opsit->first != ifaceit->first)
+            {
+                // This interface is not supported.
+                throw InterfaceError(
+                    "Encountered unsupported interface.",
+                    ifaceit->first);
+            }
+
+            // Find the binding insertion point or the binding to update.
+            refaceit = std::lower_bound(
+                           refaceit,
+                           refaces.end(),
+                           ifaceit->first,
+                           compareFirst(refaces.key_comp()));
+
+            if (refaceit == refaces.end() || refaceit->first != ifaceit->first)
+            {
+                // Add the new interface.
+                auto& ctor = std::get<MakerType>(opsit->second);
+                refaceit = refaces.insert(
+                               refaceit,
+                               std::make_pair(
+                                   ifaceit->first,
+                                   ctor(
+                                       _bus,
+                                       path.str.c_str(),
+                                       ifaceit->second)));
+                signals.push_back(ifaceit->first);
+            }
+            else
+            {
+                // Set the new property values.
+                auto& assign = std::get<AssignerType>(opsit->second);
+                assign(ifaceit->second, refaceit->second);
+            }
+        }
+        catch (const InterfaceError& e)
+        {
+            // Reset the binding ops iterator since we are
+            // at the end.
+            opsit = _makers.cbegin();
+            e.log();
+        }
+
+        ++ifaceit;
+    }
+
+    if (newObject)
+    {
+        _bus.emit_object_added(path.str.c_str());
+    }
+    else if (!signals.empty())
+    {
+        // TODO: emit an interfaces added signal
+    }
+}
+
+void Manager::updateObjects(
+    const std::map<sdbusplus::message::object_path, Object>& objs)
+{
+    auto objit = objs.cbegin();
+    auto refit = _refs.begin();
+    std::string absPath;
+    bool newObj;
+
+    while (objit != objs.cend())
+    {
+        // Find the insertion point or the object to update.
+        refit = std::lower_bound(
+                    refit,
+                    _refs.end(),
+                    objit->first,
+                    compareFirst(RelPathCompare(_root)));
+
+        absPath.assign(_root);
+        absPath.append(objit->first);
+
+        newObj = false;
+        if (refit == _refs.end() || refit->first != absPath)
+        {
+            refit = _refs.insert(
+                        refit,
+                        std::make_pair(
+                            absPath,
+                            decltype(_refs)::mapped_type()));
+            newObj = true;
+        }
+
+        updateInterfaces(absPath, objit->second, refit, newObj);
+        ++objit;
+    }
+}
+
 void Manager::notify(std::map<sdbusplus::message::object_path, Object> objs)
 {
     updateObjects(objs);