Add "component" property to command instance

When sending commands, we'll use "component" to route the command to
the target component it was designated for.

As a temporary stop-gap, use "device" as the component name before
we have full implementation of component/trait schema model.

Also removed CommandDictionary from CommandInstance::FromJson since
the validation will be done outside of JSON parsing code in the future
Component Manager class.

BUG: 25841719
Change-Id: I5c649c257fb48ecaaedc1ced84931009f94c2bb3
Reviewed-on: https://weave-review.googlesource.com/1764
Reviewed-by: Vitaly Buka <vitalybuka@google.com>
diff --git a/src/commands/command_queue.cc b/src/commands/command_queue.cc
index 3d2167f..134dc1c 100644
--- a/src/commands/command_queue.cc
+++ b/src/commands/command_queue.cc
@@ -11,6 +11,11 @@
 
 namespace {
 const int kRemoveCommandDelayMin = 5;
+
+std::string GetCommandHandlerKey(const std::string& component_path,
+                                 const std::string& command_name) {
+  return component_path + ":" + command_name;
+}
 }
 
 void CommandQueue::AddCommandAddedCallback(const CommandCallback& callback) {
@@ -25,6 +30,7 @@
 }
 
 void CommandQueue::AddCommandHandler(
+    const std::string& component_path,
     const std::string& command_name,
     const Device::CommandHandlerCallback& callback) {
   if (!command_name.empty()) {
@@ -33,20 +39,24 @@
 
     for (const auto& command : map_) {
       if (command.second->GetState() == Command::State::kQueued &&
-          command.second->GetName() == command_name) {
+          command.second->GetName() == command_name &&
+          command.second->GetComponent() == component_path) {
         callback.Run(command.second);
       }
     }
 
-    CHECK(command_callbacks_.insert(std::make_pair(command_name, callback))
-              .second)
+    std::string key = GetCommandHandlerKey(component_path, command_name);
+    CHECK(command_callbacks_.insert(std::make_pair(key, callback)).second)
         << command_name << " already has handler";
 
   } else {
+    CHECK(component_path.empty())
+        << "Default handler must not be component-specific";
     for (const auto& command : map_) {
+      std::string key = GetCommandHandlerKey(command.second->GetComponent(),
+                                             command.second->GetName());
       if (command.second->GetState() == Command::State::kQueued &&
-          command_callbacks_.find(command.second->GetName()) ==
-              command_callbacks_.end()) {
+          command_callbacks_.find(key) == command_callbacks_.end()) {
         callback.Run(command.second);
       }
     }
@@ -66,7 +76,9 @@
   for (const auto& cb : on_command_added_)
     cb.Run(pair.first->second.get());
 
-  auto it_handler = command_callbacks_.find(pair.first->second->GetName());
+  std::string key = GetCommandHandlerKey(pair.first->second->GetComponent(),
+                                         pair.first->second->GetName());
+  auto it_handler = command_callbacks_.find(key);
 
   if (it_handler != command_callbacks_.end())
     it_handler->second.Run(pair.first->second);