aboutsummaryrefslogtreecommitdiff
path: root/src/component_manager_impl.h
blob: f7995ed55d5b889aa0d19afaff17daebe90dfc0f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
// 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(provider::TaskRunner* task_runner,
                                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;

  // Finds a state definition, where |state_property_name| is in the form of
  // "trait.state".
  const base::DictionaryValue* FindStateDefinition(
      const std::string& state_property_name) const;

  // Checks the minimum required user role for a given command.
  bool GetCommandMinimalRole(const std::string& command_name,
                             UserRole* minimal_role,
                             ErrorPtr* error) const override;

  // Checks the minimum required user role for a given state.
  bool GetStateMinimalRole(const std::string& state_property_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_;
  }

  // Returns a JSON dictionary containing component instances with state
  // properties visible to a user of the given |role|.
  std::unique_ptr<base::DictionaryValue> GetComponentsForUserRole(
      UserRole role) const override;

  // 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;

 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);

  // 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_;

  DISALLOW_COPY_AND_ASSIGN(ComponentManagerImpl);
};

}  // namespace weave

#endif  // LIBWEAVE_SRC_COMPONENT_MANAGER_IMPL_H_