Add DisableNode keyword

This new special keyword allows one configuration
to disable another entity. This is useful for cases
where a system without a chassis desires one configuration,
but when it is in a chassis, it requres a different
configuration.

Tested: Verified DisableNode disabled configurations, and
that Bind still worked

Change-Id: I3ff1f8bca7c7dffd5210ddea238877c65c859068
Signed-off-by: James Feist <james.feist@linux.intel.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c6f7d8a..960f76d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -58,7 +58,7 @@
 
     externalproject_add (
         nlohmann-json GIT_REPOSITORY "https://github.com/nlohmann/json.git"
-        GIT_TAG d2dd27dc3b8472dbaa7d66f83619b3ebcd9185fe SOURCE_DIR
+        GIT_TAG 456478b3c50d60100dbb1fb9bc931f370a2c1c28 SOURCE_DIR
         "${CMAKE_BINARY_DIR}/nlohmann-json-src" BINARY_DIR
         "${CMAKE_BINARY_DIR}/nlohmann-json-build" CONFIGURE_COMMAND ""
         BUILD_COMMAND "" INSTALL_COMMAND mkdir -p
diff --git a/src/EntityManager.cpp b/src/EntityManager.cpp
index 53a34bc..4f3709a 100644
--- a/src/EntityManager.cpp
+++ b/src/EntityManager.cpp
@@ -1296,64 +1296,105 @@
                             templateCharReplace(keyPair, foundDevice,
                                                 foundDeviceIdx);
 
-                            // special case bind
-                            if (boost::starts_with(keyPair.key(), "Bind"))
+                            bool isBind =
+                                boost::starts_with(keyPair.key(), "Bind");
+                            bool isDisable = keyPair.key() == "DisableNode";
+
+                            // special cases
+                            if (!(isBind || isDisable))
                             {
-                                if (keyPair.value().type() !=
-                                    nlohmann::json::value_t::string)
+                                continue;
+                            }
+
+                            if (keyPair.value().type() !=
+                                    nlohmann::json::value_t::string &&
+                                keyPair.value().type() !=
+                                    nlohmann::json::value_t::array)
+                            {
+                                std::cerr << "Value is invalid type "
+                                          << keyPair.key() << "\n";
+                                continue;
+                            }
+
+                            std::vector<std::string> matches;
+                            if (keyPair.value().type() ==
+                                nlohmann::json::value_t::string)
+                            {
+                                matches.emplace_back(keyPair.value());
+                            }
+                            else
+                            {
+                                for (const auto& value : keyPair.value())
                                 {
-                                    std::cerr << "bind_ value must be of "
-                                                 "type string "
-                                              << keyPair.key() << "\n";
-                                    continue;
+                                    if (value.type() !=
+                                        nlohmann::json::value_t::string)
+                                    {
+                                        std::cerr << "Value is invalid type "
+                                                  << value << "\n";
+                                        break;
+                                    }
+                                    matches.emplace_back(value);
                                 }
-                                bool foundBind = false;
-                                std::string bind =
-                                    keyPair.key().substr(sizeof("Bind") - 1);
+                            }
 
-                                for (auto& configurationPair :
-                                     _systemConfiguration.items())
+                            std::set<std::string> foundMatches;
+                            for (auto& configurationPair :
+                                 _systemConfiguration.items())
+                            {
+                                if (isDisable)
                                 {
-
-                                    auto configListFind =
-                                        configurationPair.value().find(
-                                            "Exposes");
-
-                                    if (configListFind ==
-                                            configurationPair.value().end() ||
-                                        configListFind->type() !=
-                                            nlohmann::json::value_t::array)
+                                    // don't disable ourselves
+                                    if (configurationPair.key() == recordName)
                                     {
                                         continue;
                                     }
-                                    for (auto& exposedObject : *configListFind)
-                                    {
-                                        std::string foundObjectName =
-                                            (exposedObject)["Name"];
-                                        if (boost::iequals(
-                                                foundObjectName,
-                                                keyPair.value()
-                                                    .get<std::string>()))
-                                        {
-                                            exposedObject["Status"] = "okay";
-                                            expose[bind] = exposedObject;
+                                }
+                                auto configListFind =
+                                    configurationPair.value().find("Exposes");
 
-                                            foundBind = true;
-                                            break;
-                                        }
-                                    }
-                                    if (foundBind)
-                                    {
-                                        break;
-                                    }
-                                }
-                                if (!foundBind)
+                                if (configListFind ==
+                                        configurationPair.value().end() ||
+                                    configListFind->type() !=
+                                        nlohmann::json::value_t::array)
                                 {
-                                    std::cerr << "configuration file "
-                                                 "dependency error, "
-                                                 "could not find bind "
-                                              << keyPair.value() << "\n";
+                                    continue;
                                 }
+                                for (auto& exposedObject : *configListFind)
+                                {
+                                    auto matchIt = std::find_if(
+                                        matches.begin(), matches.end(),
+                                        [name = (exposedObject)["Name"]
+                                                    .get<std::string>()](
+                                            const std::string& s) {
+                                            return s == name;
+                                        });
+                                    if (matchIt == matches.end())
+                                    {
+                                        continue;
+                                    }
+                                    foundMatches.insert(*matchIt);
+
+                                    if (isBind)
+                                    {
+                                        std::string bind = keyPair.key().substr(
+                                            sizeof("Bind") - 1);
+
+                                        exposedObject["Status"] = "okay";
+                                        expose[bind] = exposedObject;
+                                    }
+                                    else if (isDisable)
+                                    {
+                                        exposedObject["Status"] = "disabled";
+                                    }
+                                }
+                            }
+                            if (foundMatches.size() != matches.size())
+                            {
+                                std::cerr << "configuration file "
+                                             "dependency error, "
+                                             "could not find "
+                                          << keyPair.key() << " "
+                                          << keyPair.value() << "\n";
                             }
                         }
                     }