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