Add new component-based APIs to Device interface

This change just adds ComponentManager to DeviceManager and adds
new APIs that forward the calls to the component manager. The old
APIs are still intact and work with the old StateManager and Command
Manager.

BUG: 25916427, 25917240, 25917419, 25917523, 25917601
BUG: 25917650, 25917243, 25917525, 25917247
Change-Id: I88ce4bc6c447335e8b48ad5b1555eaa6331e447f
Reviewed-on: https://weave-review.googlesource.com/1782
Reviewed-by: Vitaly Buka <vitalybuka@google.com>
diff --git a/include/weave/device.h b/include/weave/device.h
index ca04bdf..2d7aaff 100644
--- a/include/weave/device.h
+++ b/include/weave/device.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <set>
 #include <string>
+#include <vector>
 
 #include <weave/command.h>
 #include <weave/export.h>
@@ -45,10 +46,74 @@
   virtual void AddSettingsChangedCallback(
       const SettingsChangedCallback& callback) = 0;
 
+  // Adds new trait definitions to device.
+  virtual void AddTraitDefinitionsFromJson(const std::string& json) = 0;
+  virtual void AddTraitDefinitions(const base::DictionaryValue& dict) = 0;
+
+  // Returns the full JSON dictionary containing trait definitions.
+  virtual const base::DictionaryValue& GetTraits() const = 0;
+
+  // Adds a new component instance to device. Traits used by this component
+  // must be already defined.
+  virtual bool AddComponent(const std::string& name,
+                            const std::vector<std::string>& traits,
+                            ErrorPtr* error) = 0;
+
+  // Sets callback which is called when new components are added.
+  virtual void AddComponentTreeChangedCallback(
+      const base::Closure& callback) = 0;
+
+  // Returns the full JSON dictionary containing component instances.
+  virtual const base::DictionaryValue& GetComponents() const = 0;
+
+  // Sets value of multiple properties of the state.
+  // It's recommended to call this to initialize component state defined.
+  // Example:
+  //   device->SetStatePropertiesFromJson("myComponent",
+  //                                      "{'base':{'firmwareVersion':'123'}}")
+  // Method completely replaces properties included |json| or |dict|.
+  // Properties of the state not included |json| or |dict| will stay unchanged.
+  virtual bool SetStatePropertiesFromJson(
+      const std::string& component,
+      const std::string& json,
+      ErrorPtr* error) = 0;
+  virtual bool SetStateProperties(
+      const std::string& component,
+      const base::DictionaryValue& dict,
+      ErrorPtr* error) = 0;
+
+  // Returns value of the single property.
+  // |name| is full property name, including trait name. e.g. "base.network".
+  virtual const base::Value* GetStateProperty(
+      const std::string& component,
+      const std::string& name,
+      ErrorPtr* error) const = 0;
+
+  // Sets value of the single property.
+  // |name| is full property name, including trait name. e.g. "base.network".
+  virtual bool SetStateProperty(
+      const std::string& component,
+      const std::string& name,
+      const base::Value& value,
+      ErrorPtr* error) = 0;
+
   // Callback type for AddCommandHandler.
   using CommandHandlerCallback =
       base::Callback<void(const std::weak_ptr<Command>& command)>;
 
+  // Sets handler for new commands added to the queue.
+  // |component| is the name of the component for which commands should be
+  // handled.
+  // |command_name| is the full command name of the command to handle. e.g.
+  // "base.reboot". Each command can have no more than one handler.
+  // Empty |component| and |command_name| sets default handler for all unhanded
+  // commands.
+  // No new command handlers can be set after default handler was set.
+  virtual void AddCommandHandler(
+      const std::string& component,
+      const std::string& command_name,
+      const CommandHandlerCallback& callback) = 0;
+
   // Adds a new command to the command queue.
   virtual bool AddCommand(const base::DictionaryValue& command,
                           std::string* id,
diff --git a/include/weave/test/mock_device.h b/include/weave/test/mock_device.h
index e5063e7..88cc5e0 100644
--- a/include/weave/test/mock_device.h
+++ b/include/weave/test/mock_device.h
@@ -21,14 +21,51 @@
   MOCK_CONST_METHOD0(GetSettings, const Settings&());
   MOCK_METHOD1(AddSettingsChangedCallback,
                void(const SettingsChangedCallback& callback));
-  MOCK_METHOD1(AddCommandDefinitionsFromJson, void(const std::string&));
-  MOCK_METHOD1(AddCommandDefinitions, void(const base::DictionaryValue&));
-  MOCK_METHOD2(AddCommandHandler,
-               void(const std::string&, const CommandHandlerCallback&));
+  MOCK_METHOD1(AddTraitDefinitionsFromJson, void(const std::string& json));
+  MOCK_METHOD1(AddTraitDefinitions, void(const base::DictionaryValue& dict));
+  MOCK_CONST_METHOD0(GetTraits, const base::DictionaryValue&());
+  MOCK_METHOD3(AddComponent, bool(const std::string& name,
+                                  const std::vector<std::string>& traits,
+                                  ErrorPtr* error));
+  MOCK_METHOD1(AddComponentTreeChangedCallback,
+               void(const base::Closure& callback));
+  MOCK_CONST_METHOD0(GetComponents, const base::DictionaryValue&());
+  MOCK_METHOD3(SetStatePropertiesFromJson, bool(const std::string& component,
+                                                const std::string& json,
+                                                ErrorPtr* error));
+  MOCK_METHOD3(SetStateProperties, bool(const std::string& component,
+                                        const base::DictionaryValue& dict,
+                                        ErrorPtr* error));
+  MOCK_CONST_METHOD3(GetStateProperty,
+                     const base::Value*(const std::string& component,
+                                        const std::string& name,
+                                        ErrorPtr* error));
+  MOCK_METHOD4(SetStateProperty, bool(const std::string& component,
+                                      const std::string& name,
+                                      const base::Value& value,
+                                      ErrorPtr* error));
+  MOCK_METHOD3(AddCommandHandler, void(const std::string& component,
+                                       const std::string& command_name,
+                                       const CommandHandlerCallback& callback));
   MOCK_METHOD3(AddCommand,
                bool(const base::DictionaryValue&, std::string*, ErrorPtr*));
   MOCK_METHOD1(FindCommand, Command*(const std::string&));
   MOCK_METHOD1(AddStateChangedCallback, void(const base::Closure& callback));
+  MOCK_CONST_METHOD0(GetGcdState, GcdState());
+  MOCK_METHOD1(AddGcdStateChangedCallback,
+               void(const GcdStateChangedCallback& callback));
+  MOCK_METHOD2(Register,
+               void(const std::string& ticket_id,
+                    const DoneCallback& callback));
+  MOCK_METHOD2(AddPairingChangedCallbacks,
+               void(const PairingBeginCallback& begin_callback,
+                    const PairingEndCallback& end_callback));
+
+  // Deprecated methods.
+  MOCK_METHOD1(AddCommandDefinitionsFromJson, void(const std::string&));
+  MOCK_METHOD1(AddCommandDefinitions, void(const base::DictionaryValue&));
+  MOCK_METHOD2(AddCommandHandler,
+               void(const std::string&, const CommandHandlerCallback&));
   MOCK_METHOD1(AddStateDefinitionsFromJson, void(const std::string&));
   MOCK_METHOD1(AddStateDefinitions, void(const base::DictionaryValue&));
   MOCK_METHOD2(SetStatePropertiesFromJson, bool(const std::string&, ErrorPtr*));
@@ -41,15 +78,6 @@
                     const base::Value& value,
                     ErrorPtr* error));
   MOCK_CONST_METHOD0(GetState, const base::DictionaryValue&());
-  MOCK_CONST_METHOD0(GetGcdState, GcdState());
-  MOCK_METHOD1(AddGcdStateChangedCallback,
-               void(const GcdStateChangedCallback& callback));
-  MOCK_METHOD2(Register,
-               void(const std::string& ticket_id,
-                    const DoneCallback& callback));
-  MOCK_METHOD2(AddPairingChangedCallbacks,
-               void(const PairingBeginCallback& begin_callback,
-                    const PairingEndCallback& end_callback));
 };
 
 }  // namespace test
diff --git a/src/device_manager.cc b/src/device_manager.cc
index 52b2882..64a8093 100644
--- a/src/device_manager.cc
+++ b/src/device_manager.cc
@@ -10,6 +10,7 @@
 
 #include "src/base_api_handler.h"
 #include "src/commands/command_manager.h"
+#include "src/component_manager.h"
 #include "src/config.h"
 #include "src/device_registration_info.h"
 #include "src/privet/privet_manager.h"
@@ -33,6 +34,7 @@
                              provider::HttpServer* http_server,
                              provider::Wifi* wifi,
                              provider::Bluetooth* bluetooth) {
+  component_manager_.reset(new ComponentManager);
   command_manager_ = std::make_shared<CommandManager>();
   state_change_queue_.reset(new StateChangeQueue(kMaxStateChangeQueueSize));
   state_manager_ = std::make_shared<StateManager>(state_change_queue_.get());
@@ -89,6 +91,65 @@
   device_info_->AddGcdStateChangedCallback(callback);
 }
 
+void DeviceManager::AddTraitDefinitionsFromJson(const std::string& json) {
+  CHECK(component_manager_->LoadTraits(json, nullptr));
+}
+
+void DeviceManager::AddTraitDefinitions(const base::DictionaryValue& dict) {
+  CHECK(component_manager_->LoadTraits(dict, nullptr));
+}
+
+const base::DictionaryValue& DeviceManager::GetTraits() const {
+  return component_manager_->GetTraits();
+}
+
+bool DeviceManager::AddComponent(const std::string& name,
+                                 const std::vector<std::string>& traits,
+                                 ErrorPtr* error) {
+  return component_manager_->AddComponent("", name, traits, error);
+}
+
+void DeviceManager::AddComponentTreeChangedCallback(
+    const base::Closure& callback) {
+  component_manager_->AddComponentTreeChangedCallback(callback);
+}
+
+const base::DictionaryValue& DeviceManager::GetComponents() const {
+  return component_manager_->GetComponents();
+}
+
+bool DeviceManager::SetStatePropertiesFromJson(const std::string& component,
+                                               const std::string& json,
+                                               ErrorPtr* error) {
+  return component_manager_->SetStatePropertiesFromJson(component, json, error);
+}
+
+bool DeviceManager::SetStateProperties(const std::string& component,
+                                       const base::DictionaryValue& dict,
+                                       ErrorPtr* error) {
+  return component_manager_->SetStateProperties(component, dict, error);
+}
+
+const base::Value* DeviceManager::GetStateProperty(
+    const std::string& component,
+    const std::string& name,
+    ErrorPtr* error) const {
+  return component_manager_->GetStateProperty(component, name, error);
+}
+
+bool DeviceManager::SetStateProperty(const std::string& component,
+                                     const std::string& name,
+                                     const base::Value& value,
+                                     ErrorPtr* error) {
+  return component_manager_->SetStateProperty(component, name, value, error);
+}
+
+void DeviceManager::AddCommandHandler(const std::string& component,
+                                      const std::string& command_name,
+                                      const CommandHandlerCallback& callback) {
+  component_manager_->AddCommandHandler(component, command_name, callback);
+}
+
 void DeviceManager::AddCommandDefinitionsFromJson(const std::string& json) {
   CHECK(command_manager_->LoadCommands(json, nullptr));
 }
diff --git a/src/device_manager.h b/src/device_manager.h
index 6c3df05..2a23755 100644
--- a/src/device_manager.h
+++ b/src/device_manager.h
@@ -13,6 +13,7 @@
 class BaseApiHandler;
 class Config;
 class CommandManager;
+class ComponentManager;
 class DeviceRegistrationInfo;
 class StateChangeQueue;
 class StateManager;
@@ -37,15 +38,48 @@
   const Settings& GetSettings() const override;
   void AddSettingsChangedCallback(
       const SettingsChangedCallback& callback) override;
-  void AddCommandDefinitionsFromJson(const std::string& json) override;
-  void AddCommandDefinitions(const base::DictionaryValue& dict) override;
+  void AddTraitDefinitionsFromJson(const std::string& json) override;
+  void AddTraitDefinitions(const base::DictionaryValue& dict) override;
+  const base::DictionaryValue& GetTraits() const override;
+  bool AddComponent(const std::string& name,
+                    const std::vector<std::string>& traits,
+                    ErrorPtr* error) override;
+  void AddComponentTreeChangedCallback(const base::Closure& callback) override;
+  const base::DictionaryValue& GetComponents() const override;
+  bool SetStatePropertiesFromJson(const std::string& component,
+                                  const std::string& json,
+                                  ErrorPtr* error) override;
+  bool SetStateProperties(const std::string& component,
+                          const base::DictionaryValue& dict,
+                          ErrorPtr* error) override;
+  const base::Value* GetStateProperty(const std::string& component,
+                                      const std::string& name,
+                                      ErrorPtr* error) const override;
+  bool SetStateProperty(const std::string& component,
+                        const std::string& name,
+                        const base::Value& value,
+                        ErrorPtr* error) override;
+  void AddCommandHandler(const std::string& component,
+                         const std::string& command_name,
+                         const CommandHandlerCallback& callback) override;
   bool AddCommand(const base::DictionaryValue& command,
                   std::string* id,
                   ErrorPtr* error) override;
   Command* FindCommand(const std::string& id) override;
+  void AddStateChangedCallback(const base::Closure& callback) override;
+  void Register(const std::string& ticket_id,
+                const DoneCallback& callback) override;
+  GcdState GetGcdState() const override;
+  void AddGcdStateChangedCallback(
+      const GcdStateChangedCallback& callback) override;
+  void AddPairingChangedCallbacks(
+      const PairingBeginCallback& begin_callback,
+      const PairingEndCallback& end_callback) override;
+
+  void AddCommandDefinitionsFromJson(const std::string& json) override;
+  void AddCommandDefinitions(const base::DictionaryValue& dict) override;
   void AddCommandHandler(const std::string& command_name,
                          const CommandHandlerCallback& callback) override;
-  void AddStateChangedCallback(const base::Closure& callback) override;
   void AddStateDefinitionsFromJson(const std::string& json) override;
   void AddStateDefinitions(const base::DictionaryValue& dict) override;
   bool SetStatePropertiesFromJson(const std::string& json,
@@ -57,14 +91,6 @@
                         const base::Value& value,
                         ErrorPtr* error) override;
   const base::DictionaryValue& GetState() const override;
-  void Register(const std::string& ticket_id,
-                const DoneCallback& callback) override;
-  GcdState GetGcdState() const override;
-  void AddGcdStateChangedCallback(
-      const GcdStateChangedCallback& callback) override;
-  void AddPairingChangedCallbacks(
-      const PairingBeginCallback& begin_callback,
-      const PairingEndCallback& end_callback) override;
 
   Config* GetConfig();
 
@@ -76,6 +102,7 @@
                    provider::Wifi* wifi,
                    provider::Bluetooth* bluetooth);
 
+  std::unique_ptr<ComponentManager> component_manager_;
   std::shared_ptr<CommandManager> command_manager_;
   std::unique_ptr<StateChangeQueue> state_change_queue_;
   std::shared_ptr<StateManager> state_manager_;