blob: 8c4ad16ee0d2985e0e98e921886675557a525c52 [file] [log] [blame]
Alex Vakulenkoba981152015-12-05 13:58:22 -08001// Copyright 2015 The Weave Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef LIBWEAVE_SRC_COMPONENT_MANAGER_IMPL_H_
6#define LIBWEAVE_SRC_COMPONENT_MANAGER_IMPL_H_
7
Vitaly Bukaece713e2015-12-09 10:59:33 -08008#include <base/time/default_clock.h>
9
Alex Vakulenkoba981152015-12-05 13:58:22 -080010#include "src/commands/command_queue.h"
11#include "src/component_manager.h"
12#include "src/states/state_change_queue.h"
13
14namespace weave {
15
16class ComponentManagerImpl final : public ComponentManager {
17 public:
Vitaly Bukaece713e2015-12-09 10:59:33 -080018 explicit ComponentManagerImpl(base::Clock* clock = nullptr);
Alex Vakulenkoba981152015-12-05 13:58:22 -080019 ~ComponentManagerImpl() override;
20
21 // Loads trait definition schema.
22 bool LoadTraits(const base::DictionaryValue& dict, ErrorPtr* error) override;
23
24 // Same as the overload above, but takes a json string to read the trait
25 // definitions from.
26 bool LoadTraits(const std::string& json, ErrorPtr* error) override;
27
28 // Sets callback which is called when new trait definitions are added.
29 void AddTraitDefChangedCallback(const base::Closure& callback) override;
30
31 // Adds a new component instance to device.
32 // |path| is a path to the parent component (or empty string if a root-level
33 // component is being added).
34 // |name| is a component name being added.
35 // |traits| is a list of trait names this component supports.
36 bool AddComponent(const std::string& path,
37 const std::string& name,
38 const std::vector<std::string>& traits,
39 ErrorPtr* error) override;
40
41 // Adds a new component instance to device, as a part of component array.
42 // |path| is a path to the parent component.
43 // |name| is an array root element inside the child components.
44 // |traits| is a list of trait names this component supports.
45 bool AddComponentArrayItem(const std::string& path,
46 const std::string& name,
47 const std::vector<std::string>& traits,
48 ErrorPtr* error) override;
49
Alex Vakulenkoce850b52016-01-04 09:27:50 -080050 // Removes an existing component instance from device.
51 // |path| is a path to the parent component (or empty string if a root-level
52 // component is being removed).
53 // |name| is a name of the component to be removed.
54 bool RemoveComponent(const std::string& path,
55 const std::string& name,
56 ErrorPtr* error) override;
57
58 // Removes an element from component array.
59 // |path| is a path to the parent component.
60 // |name| is an array root element inside the child components.
61 // |index| is a zero-based element index in the component array.
62 bool RemoveComponentArrayItem(const std::string& path,
63 const std::string& name,
64 size_t index,
65 ErrorPtr* error) override;
66
Alex Vakulenkoba981152015-12-05 13:58:22 -080067 // Sets callback which is called when new components are added.
68 void AddComponentTreeChangedCallback(const base::Closure& callback) override;
69
Alex Vakulenkod91d6252015-12-05 17:14:39 -080070 // Adds a new command instance to the command queue. The command specified in
71 // |command_instance| must be fully initialized and have its name, component,
72 // id populated.
Vitaly Buka34668e72015-12-15 14:46:47 -080073 void AddCommand(std::unique_ptr<CommandInstance> command_instance) override;
Alex Vakulenkod91d6252015-12-05 17:14:39 -080074
75 // Parses the command definition from a json dictionary. The resulting command
76 // instance is populated with all the required fields and partially validated
77 // against syntax/schema.
78 // The new command ID is returned through optional |id| param.
79 std::unique_ptr<CommandInstance> ParseCommandInstance(
80 const base::DictionaryValue& command,
81 Command::Origin command_origin,
82 UserRole role,
83 std::string* id,
84 ErrorPtr* error) override;
Alex Vakulenkoba981152015-12-05 13:58:22 -080085
86 // Find a command instance with the given ID in the command queue.
87 CommandInstance* FindCommand(const std::string& id) override;
88
89 // Command queue monitoring callbacks (called when a new command is added to
90 // or removed from the queue).
91 void AddCommandAddedCallback(
92 const CommandQueue::CommandCallback& callback) override;
93 void AddCommandRemovedCallback(
94 const CommandQueue::CommandCallback& callback) override;
95
96 // Adds a command handler for specific component's command.
97 // |component_path| is a path to target component (e.g. "stove.burners[2]").
98 // |command_name| is a full path of the command, including trait name and
99 // command name (e.g. "burner.setPower").
100 void AddCommandHandler(
101 const std::string& component_path,
102 const std::string& command_name,
103 const Device::CommandHandlerCallback& callback) override;
104
105 // Finds a component instance by its full path.
106 const base::DictionaryValue* FindComponent(const std::string& path,
107 ErrorPtr* error) const override;
108 // Finds a definition of trait with the given |name|.
109 const base::DictionaryValue* FindTraitDefinition(
110 const std::string& name) const override;
111
112 // Finds a command definition, where |command_name| is in the form of
113 // "trait.command".
114 const base::DictionaryValue* FindCommandDefinition(
115 const std::string& command_name) const override;
116
117 // Checks the minimum required user role for a given command.
118 bool GetMinimalRole(const std::string& command_name,
119 UserRole* minimal_role,
120 ErrorPtr* error) const override;
121
122 // Returns the full JSON dictionary containing trait definitions.
123 const base::DictionaryValue& GetTraits() const override { return traits_; }
124
125 // Returns the full JSON dictionary containing component instances.
126 const base::DictionaryValue& GetComponents() const override {
127 return components_;
128 }
129
130 // Component state manipulation methods.
131 bool SetStateProperties(const std::string& component_path,
132 const base::DictionaryValue& dict,
133 ErrorPtr* error) override;
134 bool SetStatePropertiesFromJson(const std::string& component_path,
135 const std::string& json,
136 ErrorPtr* error) override;
137 const base::Value* GetStateProperty(const std::string& component_path,
138 const std::string& name,
139 ErrorPtr* error) const override;
140 bool SetStateProperty(const std::string& component_path,
141 const std::string& name,
142 const base::Value& value,
143 ErrorPtr* error) override;
144
145 void AddStateChangedCallback(const base::Closure& callback) override;
146
147 // Returns the recorded state changes since last time this method was called.
148 StateSnapshot GetAndClearRecordedStateChanges() override;
149
150 // Called to notify that the state patch with |id| has been successfully sent
151 // to the server and processed.
152 void NotifyStateUpdatedOnServer(UpdateID id) override;
153
154 // Returns an ID of last state change update. Each SetStatePropertyNNN()
155 // invocation increments this value by 1.
156 UpdateID GetLastStateChangeId() const override {
157 return last_state_change_id_;
158 }
159
160 // Subscribes for device state update notifications from cloud server.
161 // The |callback| will be called every time a state patch with given ID is
162 // successfully received and processed by Weave server.
163 // Returns a subscription token. As soon as this token is destroyed, the
164 // respective callback is removed from the callback list.
165 Token AddServerStateUpdatedCallback(
166 const base::Callback<void(UpdateID)>& callback) override;
167
168 // Helper method for legacy API to obtain first component that implements
169 // the given trait. This is useful for routing commands that have no component
170 // path specified.
171 // Returns empty string if no components are found.
172 // This method only searches for component on the top level of components
173 // tree. No sub-components are searched.
174 std::string FindComponentWithTrait(const std::string& trait) const override;
175
Alex Vakulenko6b394d12015-12-05 15:52:54 -0800176 // Support for legacy APIs. Setting command and state definitions.
177 // This translates into modifying a trait definition.
178 bool AddLegacyCommandDefinitions(const base::DictionaryValue& dict,
179 ErrorPtr* error) override;
180 bool AddLegacyStateDefinitions(const base::DictionaryValue& dict,
181 ErrorPtr* error) override;
182 // Returns device state for legacy APIs.
183 const base::DictionaryValue& GetLegacyState() const override;
184 // Returns command definitions for legacy APIs.
185 const base::DictionaryValue& GetLegacyCommandDefinitions() const override;
186
Alex Vakulenkoba981152015-12-05 13:58:22 -0800187 private:
188 // A helper method to find a JSON element of component at |path| to add new
189 // sub-components to.
190 base::DictionaryValue* FindComponentGraftNode(const std::string& path,
191 ErrorPtr* error);
192 base::DictionaryValue* FindMutableComponent(const std::string& path,
193 ErrorPtr* error);
194
Alex Vakulenko6b394d12015-12-05 15:52:54 -0800195 // Legacy API support: Helper function to support state/command definitions.
196 // Adds the given trait to at least one component.
197 // Searches for available components and if none of them already supports this
198 // trait, it adds it to the first available component.
199 void AddTraitToLegacyComponent(const std::string& trait);
200
Alex Vakulenkoba981152015-12-05 13:58:22 -0800201 // Helper method to find a sub-component given a root node and a relative path
202 // from the root to the target component.
203 static const base::DictionaryValue* FindComponentAt(
204 const base::DictionaryValue* root,
205 const std::string& path,
206 ErrorPtr* error);
207
Vitaly Bukaece713e2015-12-09 10:59:33 -0800208 base::DefaultClock default_clock_;
Alex Vakulenkoba981152015-12-05 13:58:22 -0800209 base::Clock* clock_{nullptr};
Vitaly Buka41aa8092015-12-09 20:04:34 -0800210
Alex Vakulenkod91d6252015-12-05 17:14:39 -0800211 // An ID of last state change update. Each NotifyPropertiesUpdated()
212 // invocation increments this value by 1.
213 UpdateID last_state_change_id_{0};
214 // Callback list for state change queue event sinks.
215 // This member must be defined before |command_queue_|.
216 base::CallbackList<void(UpdateID)> on_server_state_updated_;
217
Vitaly Buka34668e72015-12-15 14:46:47 -0800218 base::DictionaryValue traits_; // Trait definitions.
Alex Vakulenkoba981152015-12-05 13:58:22 -0800219 base::DictionaryValue components_; // Component instances.
220 CommandQueue command_queue_; // Command queue containing command instances.
221 std::vector<base::Closure> on_trait_changed_;
222 std::vector<base::Closure> on_componet_tree_changed_;
223 std::vector<base::Closure> on_state_changed_;
224 uint32_t next_command_id_{0};
Alex Vakulenkoba981152015-12-05 13:58:22 -0800225 std::map<std::string, std::unique_ptr<StateChangeQueue>> state_change_queues_;
Alex Vakulenkoba981152015-12-05 13:58:22 -0800226
Alex Vakulenko6b394d12015-12-05 15:52:54 -0800227 // Legacy API support.
Vitaly Buka34668e72015-12-15 14:46:47 -0800228 mutable base::DictionaryValue legacy_state_; // Device state.
Alex Vakulenko6b394d12015-12-05 15:52:54 -0800229 mutable base::DictionaryValue legacy_command_defs_; // Command definitions.
230
Alex Vakulenkoba981152015-12-05 13:58:22 -0800231 DISALLOW_COPY_AND_ASSIGN(ComponentManagerImpl);
232};
233
234} // namespace weave
235
236#endif // LIBWEAVE_SRC_COMPONENT_MANAGER_IMPL_H_