|  | // Copyright 2015 The Weave Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef LIBWEAVE_SRC_COMPONENT_MANAGER_IMPL_H_ | 
|  | #define LIBWEAVE_SRC_COMPONENT_MANAGER_IMPL_H_ | 
|  |  | 
|  | #include <base/time/default_clock.h> | 
|  |  | 
|  | #include "src/commands/command_queue.h" | 
|  | #include "src/component_manager.h" | 
|  | #include "src/states/state_change_queue.h" | 
|  |  | 
|  | namespace weave { | 
|  |  | 
|  | class ComponentManagerImpl final : public ComponentManager { | 
|  | public: | 
|  | explicit ComponentManagerImpl(base::Clock* clock = nullptr); | 
|  | ~ComponentManagerImpl() override; | 
|  |  | 
|  | // Loads trait definition schema. | 
|  | bool LoadTraits(const base::DictionaryValue& dict, ErrorPtr* error) override; | 
|  |  | 
|  | // Same as the overload above, but takes a json string to read the trait | 
|  | // definitions from. | 
|  | bool LoadTraits(const std::string& json, ErrorPtr* error) override; | 
|  |  | 
|  | // Sets callback which is called when new trait definitions are added. | 
|  | void AddTraitDefChangedCallback(const base::Closure& callback) override; | 
|  |  | 
|  | // Adds a new component instance to device. | 
|  | // |path| is a path to the parent component (or empty string if a root-level | 
|  | // component is being added). | 
|  | // |name| is a component name being added. | 
|  | // |traits| is a list of trait names this component supports. | 
|  | bool AddComponent(const std::string& path, | 
|  | const std::string& name, | 
|  | const std::vector<std::string>& traits, | 
|  | ErrorPtr* error) override; | 
|  |  | 
|  | // Adds a new component instance to device, as a part of component array. | 
|  | // |path| is a path to the parent component. | 
|  | // |name| is an array root element inside the child components. | 
|  | // |traits| is a list of trait names this component supports. | 
|  | bool AddComponentArrayItem(const std::string& path, | 
|  | const std::string& name, | 
|  | const std::vector<std::string>& traits, | 
|  | ErrorPtr* error) override; | 
|  |  | 
|  | // Removes an existing component instance from device. | 
|  | // |path| is a path to the parent component (or empty string if a root-level | 
|  | // component is being removed). | 
|  | // |name| is a name of the component to be removed. | 
|  | bool RemoveComponent(const std::string& path, | 
|  | const std::string& name, | 
|  | ErrorPtr* error) override; | 
|  |  | 
|  | // Removes an element from component array. | 
|  | // |path| is a path to the parent component. | 
|  | // |name| is an array root element inside the child components. | 
|  | // |index| is a zero-based element index in the component array. | 
|  | bool RemoveComponentArrayItem(const std::string& path, | 
|  | const std::string& name, | 
|  | size_t index, | 
|  | ErrorPtr* error) override; | 
|  |  | 
|  | // Sets callback which is called when new components are added. | 
|  | void AddComponentTreeChangedCallback(const base::Closure& callback) override; | 
|  |  | 
|  | // Adds a new command instance to the command queue. The command specified in | 
|  | // |command_instance| must be fully initialized and have its name, component, | 
|  | // id populated. | 
|  | void AddCommand(std::unique_ptr<CommandInstance> command_instance) override; | 
|  |  | 
|  | // Parses the command definition from a json dictionary. The resulting command | 
|  | // instance is populated with all the required fields and partially validated | 
|  | // against syntax/schema. | 
|  | // The new command ID is returned through optional |id| param. | 
|  | std::unique_ptr<CommandInstance> ParseCommandInstance( | 
|  | const base::DictionaryValue& command, | 
|  | Command::Origin command_origin, | 
|  | UserRole role, | 
|  | std::string* id, | 
|  | ErrorPtr* error) override; | 
|  |  | 
|  | // Find a command instance with the given ID in the command queue. | 
|  | CommandInstance* FindCommand(const std::string& id) override; | 
|  |  | 
|  | // Command queue monitoring callbacks (called when a new command is added to | 
|  | // or removed from the queue). | 
|  | void AddCommandAddedCallback( | 
|  | const CommandQueue::CommandCallback& callback) override; | 
|  | void AddCommandRemovedCallback( | 
|  | const CommandQueue::CommandCallback& callback) override; | 
|  |  | 
|  | // Adds a command handler for specific component's command. | 
|  | // |component_path| is a path to target component (e.g. "stove.burners[2]"). | 
|  | // |command_name| is a full path of the command, including trait name and | 
|  | // command name (e.g. "burner.setPower"). | 
|  | void AddCommandHandler( | 
|  | const std::string& component_path, | 
|  | const std::string& command_name, | 
|  | const Device::CommandHandlerCallback& callback) override; | 
|  |  | 
|  | // Finds a component instance by its full path. | 
|  | const base::DictionaryValue* FindComponent(const std::string& path, | 
|  | ErrorPtr* error) const override; | 
|  | // Finds a definition of trait with the given |name|. | 
|  | const base::DictionaryValue* FindTraitDefinition( | 
|  | const std::string& name) const override; | 
|  |  | 
|  | // Finds a command definition, where |command_name| is in the form of | 
|  | // "trait.command". | 
|  | const base::DictionaryValue* FindCommandDefinition( | 
|  | const std::string& command_name) const override; | 
|  |  | 
|  | // Checks the minimum required user role for a given command. | 
|  | bool GetMinimalRole(const std::string& command_name, | 
|  | UserRole* minimal_role, | 
|  | ErrorPtr* error) const override; | 
|  |  | 
|  | // Returns the full JSON dictionary containing trait definitions. | 
|  | const base::DictionaryValue& GetTraits() const override { return traits_; } | 
|  |  | 
|  | // Returns the full JSON dictionary containing component instances. | 
|  | const base::DictionaryValue& GetComponents() const override { | 
|  | return components_; | 
|  | } | 
|  |  | 
|  | // Component state manipulation methods. | 
|  | bool SetStateProperties(const std::string& component_path, | 
|  | const base::DictionaryValue& dict, | 
|  | ErrorPtr* error) override; | 
|  | bool SetStatePropertiesFromJson(const std::string& component_path, | 
|  | const std::string& json, | 
|  | ErrorPtr* error) override; | 
|  | const base::Value* GetStateProperty(const std::string& component_path, | 
|  | const std::string& name, | 
|  | ErrorPtr* error) const override; | 
|  | bool SetStateProperty(const std::string& component_path, | 
|  | const std::string& name, | 
|  | const base::Value& value, | 
|  | ErrorPtr* error) override; | 
|  |  | 
|  | void AddStateChangedCallback(const base::Closure& callback) override; | 
|  |  | 
|  | // Returns the recorded state changes since last time this method was called. | 
|  | StateSnapshot GetAndClearRecordedStateChanges() override; | 
|  |  | 
|  | // Called to notify that the state patch with |id| has been successfully sent | 
|  | // to the server and processed. | 
|  | void NotifyStateUpdatedOnServer(UpdateID id) override; | 
|  |  | 
|  | // Returns an ID of last state change update. Each SetStatePropertyNNN() | 
|  | // invocation increments this value by 1. | 
|  | UpdateID GetLastStateChangeId() const override { | 
|  | return last_state_change_id_; | 
|  | } | 
|  |  | 
|  | // Subscribes for device state update notifications from cloud server. | 
|  | // The |callback| will be called every time a state patch with given ID is | 
|  | // successfully received and processed by Weave server. | 
|  | // Returns a subscription token. As soon as this token is destroyed, the | 
|  | // respective callback is removed from the callback list. | 
|  | Token AddServerStateUpdatedCallback( | 
|  | const base::Callback<void(UpdateID)>& callback) override; | 
|  |  | 
|  | // Helper method for legacy API to obtain first component that implements | 
|  | // the given trait. This is useful for routing commands that have no component | 
|  | // path specified. | 
|  | // Returns empty string if no components are found. | 
|  | // This method only searches for component on the top level of components | 
|  | // tree. No sub-components are searched. | 
|  | std::string FindComponentWithTrait(const std::string& trait) const override; | 
|  |  | 
|  | // Support for legacy APIs. Setting command and state definitions. | 
|  | // This translates into modifying a trait definition. | 
|  | bool AddLegacyCommandDefinitions(const base::DictionaryValue& dict, | 
|  | ErrorPtr* error) override; | 
|  | bool AddLegacyStateDefinitions(const base::DictionaryValue& dict, | 
|  | ErrorPtr* error) override; | 
|  | // Returns device state for legacy APIs. | 
|  | const base::DictionaryValue& GetLegacyState() const override; | 
|  | // Returns command definitions for legacy APIs. | 
|  | const base::DictionaryValue& GetLegacyCommandDefinitions() const override; | 
|  |  | 
|  | private: | 
|  | // A helper method to find a JSON element of component at |path| to add new | 
|  | // sub-components to. | 
|  | base::DictionaryValue* FindComponentGraftNode(const std::string& path, | 
|  | ErrorPtr* error); | 
|  | base::DictionaryValue* FindMutableComponent(const std::string& path, | 
|  | ErrorPtr* error); | 
|  |  | 
|  | // Legacy API support: Helper function to support state/command definitions. | 
|  | // Adds the given trait to at least one component. | 
|  | // Searches for available components and if none of them already supports this | 
|  | // trait, it adds it to the first available component. | 
|  | void AddTraitToLegacyComponent(const std::string& trait); | 
|  |  | 
|  | // Helper method to find a sub-component given a root node and a relative path | 
|  | // from the root to the target component. | 
|  | static const base::DictionaryValue* FindComponentAt( | 
|  | const base::DictionaryValue* root, | 
|  | const std::string& path, | 
|  | ErrorPtr* error); | 
|  |  | 
|  | base::DefaultClock default_clock_; | 
|  | base::Clock* clock_{nullptr}; | 
|  |  | 
|  | // An ID of last state change update. Each NotifyPropertiesUpdated() | 
|  | // invocation increments this value by 1. | 
|  | UpdateID last_state_change_id_{0}; | 
|  | // Callback list for state change queue event sinks. | 
|  | // This member must be defined before |command_queue_|. | 
|  | base::CallbackList<void(UpdateID)> on_server_state_updated_; | 
|  |  | 
|  | base::DictionaryValue traits_;      // Trait definitions. | 
|  | base::DictionaryValue components_;  // Component instances. | 
|  | CommandQueue command_queue_;  // Command queue containing command instances. | 
|  | std::vector<base::Closure> on_trait_changed_; | 
|  | std::vector<base::Closure> on_componet_tree_changed_; | 
|  | std::vector<base::Closure> on_state_changed_; | 
|  | uint32_t next_command_id_{0}; | 
|  | std::map<std::string, std::unique_ptr<StateChangeQueue>> state_change_queues_; | 
|  |  | 
|  | // Legacy API support. | 
|  | mutable base::DictionaryValue legacy_state_;         // Device state. | 
|  | mutable base::DictionaryValue legacy_command_defs_;  // Command definitions. | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(ComponentManagerImpl); | 
|  | }; | 
|  |  | 
|  | }  // namespace weave | 
|  |  | 
|  | #endif  // LIBWEAVE_SRC_COMPONENT_MANAGER_IMPL_H_ |