Replace Device::SetProperties with 'nested' version

Previous implementation expected dictionary in form:
{ 'package.name' : 'new_value' }

new version expects:
{ 'package': {'name' : 'new_value'}}

BUG:24267885
Change-Id: I14ae43b7094e12a49433f16a5afa9e20bd5bccb1
Reviewed-on: https://weave-review.googlesource.com/1254
Reviewed-by: Vitaly Buka <vitalybuka@google.com>
diff --git a/libweave/examples/ubuntu/main.cc b/libweave/examples/ubuntu/main.cc
index 12a00d7..a116178 100644
--- a/libweave/examples/ubuntu/main.cc
+++ b/libweave/examples/ubuntu/main.cc
@@ -62,11 +62,11 @@
       "_ledflasher": {"_leds": {"items": "boolean"}}
     })");
 
-    device->SetStateFromJson(R"({
+    device->SetStatePropertiesFromJson(R"({
       "_greeter": {"_greetings_counter": 0},
-    "_ledflasher":{"_leds": [false, false, false]}
+      "_ledflasher":{"_leds": [false, false, false]}
     })",
-                             nullptr);
+                                       nullptr);
 
     device->AddCommandHandler("_greeter._greet",
                               base::Bind(&CommandHandler::OnGreetCommand,
@@ -99,8 +99,7 @@
     LOG(INFO) << cmd->GetName() << " command finished: " << result;
 
     base::DictionaryValue state;
-    state.SetIntegerWithoutPathExpansion("_greeter._greetings_counter",
-                                         ++counter_);
+    state.SetInteger("_greeter._greetings_counter", ++counter_);
     device_->SetStateProperties(state, nullptr);
 
     LOG(INFO) << "New state: " << *device_->GetState();
diff --git a/libweave/include/weave/device.h b/libweave/include/weave/device.h
index eacd959..289cedb 100644
--- a/libweave/include/weave/device.h
+++ b/libweave/include/weave/device.h
@@ -81,11 +81,17 @@
   virtual void AddStateDefinitionsFromJson(const std::string& json) = 0;
   virtual void AddStateDefinitions(const base::DictionaryValue& dict) = 0;
 
-  // Updates multiple properties of the state.
+  // Sets value of multiple properties of the state.
   // It's recommended to call this to initialize state defined by
   // AddStateDefinitions.
-  virtual bool SetStateFromJson(const std::string& json, ErrorPtr* error) = 0;
-  virtual bool SetState(const base::DictionaryValue& dict, ErrorPtr* error) = 0;
+  // Example:
+  //   device->SetStatePropertiesFromJson("{'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& json,
+                                          ErrorPtr* error) = 0;
+  virtual bool SetStateProperties(const base::DictionaryValue& dict,
+                                  ErrorPtr* error) = 0;
 
   // Returns value of the single property.
   // |name| is full property name, including package name. e.g. "base.network".
@@ -98,10 +104,6 @@
                                 const base::Value& value,
                                 ErrorPtr* error) = 0;
 
-  // Updates a multiple property values.
-  virtual bool SetStateProperties(const base::DictionaryValue& property_set,
-                                  ErrorPtr* error) = 0;
-
   // Returns aggregated state properties across all registered packages.
   virtual std::unique_ptr<base::DictionaryValue> GetState() const = 0;
 
diff --git a/libweave/include/weave/test/mock_device.h b/libweave/include/weave/test/mock_device.h
index 98fc6c2..310d5b4 100644
--- a/libweave/include/weave/test/mock_device.h
+++ b/libweave/include/weave/test/mock_device.h
@@ -31,17 +31,15 @@
   MOCK_METHOD1(AddStateChangedCallback, void(const base::Closure& callback));
   MOCK_METHOD1(AddStateDefinitionsFromJson, void(const std::string&));
   MOCK_METHOD1(AddStateDefinitions, void(const base::DictionaryValue&));
-  MOCK_METHOD2(SetStateFromJson, bool(const std::string&, ErrorPtr*));
-  MOCK_METHOD2(SetState, bool(const base::DictionaryValue&, ErrorPtr*));
+  MOCK_METHOD2(SetStatePropertiesFromJson, bool(const std::string&, ErrorPtr*));
+  MOCK_METHOD2(SetStateProperties,
+               bool(const base::DictionaryValue&, ErrorPtr*));
   MOCK_CONST_METHOD1(MockGetStateProperty,
                      base::Value*(const std::string& name));
   MOCK_METHOD3(SetStateProperty,
                bool(const std::string& name,
                     const base::Value& value,
                     ErrorPtr* error));
-  MOCK_METHOD2(SetStateProperties,
-               bool(const base::DictionaryValue& property_set,
-                    ErrorPtr* error));
   MOCK_CONST_METHOD0(MockGetState, base::DictionaryValue*());
   MOCK_CONST_METHOD0(GetGcdState, GcdState());
   MOCK_METHOD1(AddGcdStateChangedCallback,
diff --git a/libweave/src/base_api_handler.cc b/libweave/src/base_api_handler.cc
index 8b6bf05..1a0a58d 100644
--- a/libweave/src/base_api_handler.cc
+++ b/libweave/src/base_api_handler.cc
@@ -26,8 +26,7 @@
 
   const auto& settings = device_info_->GetSettings();
   base::DictionaryValue state;
-  state.SetStringWithoutPathExpansion(kBaseStateFirmwareVersion,
-                                      settings.firmware_version);
+  state.SetString(kBaseStateFirmwareVersion, settings.firmware_version);
   CHECK(device_->SetStateProperties(state, nullptr));
 
   device->AddCommandDefinitionsFromJson(R"({
@@ -76,13 +75,11 @@
 
 void BaseApiHandler::OnConfigChanged(const Settings& settings) {
   base::DictionaryValue state;
-  state.SetStringWithoutPathExpansion(
-      kBaseStateAnonymousAccessRole,
-      EnumToString(settings.local_anonymous_access_role));
-  state.SetBooleanWithoutPathExpansion(kBaseStateDiscoveryEnabled,
-                                       settings.local_discovery_enabled);
-  state.SetBooleanWithoutPathExpansion(kBaseStatePairingEnabled,
-                                       settings.local_pairing_enabled);
+  state.SetString(kBaseStateAnonymousAccessRole,
+                  EnumToString(settings.local_anonymous_access_role));
+  state.SetBoolean(kBaseStateDiscoveryEnabled,
+                   settings.local_discovery_enabled);
+  state.SetBoolean(kBaseStatePairingEnabled, settings.local_pairing_enabled);
   device_->SetStateProperties(state, nullptr);
 }
 
diff --git a/libweave/src/device_manager.cc b/libweave/src/device_manager.cc
index 0f81a2e..25d8d40 100644
--- a/libweave/src/device_manager.cc
+++ b/libweave/src/device_manager.cc
@@ -120,26 +120,21 @@
 }
 
 void DeviceManager::AddStateDefinitionsFromJson(const std::string& json) {
-  CHECK(state_manager_->LoadStateDefinition(json, nullptr));
+  CHECK(state_manager_->LoadStateDefinitionFromJson(json, nullptr));
 }
 
 void DeviceManager::AddStateDefinitions(const base::DictionaryValue& dict) {
   CHECK(state_manager_->LoadStateDefinition(dict, nullptr));
 }
 
-bool DeviceManager::SetStateFromJson(const std::string& json, ErrorPtr* error) {
-  return state_manager_->LoadStateDefaults(json, error);
+bool DeviceManager::SetStatePropertiesFromJson(const std::string& json,
+                                               ErrorPtr* error) {
+  return state_manager_->SetPropertiesFromJson(json, error);
 }
 
-bool DeviceManager::SetState(const base::DictionaryValue& dict,
-                             ErrorPtr* error) {
-  return state_manager_->LoadStateDefaults(dict, error);
-}
-
-bool DeviceManager::SetStateProperties(
-    const base::DictionaryValue& property_set,
-    ErrorPtr* error) {
-  return state_manager_->SetProperties(property_set, error);
+bool DeviceManager::SetStateProperties(const base::DictionaryValue& dict,
+                                       ErrorPtr* error) {
+  return state_manager_->SetProperties(dict, error);
 }
 
 std::unique_ptr<base::Value> DeviceManager::GetStateProperty(
diff --git a/libweave/src/device_manager.h b/libweave/src/device_manager.h
index 7161dc5..8c85a1b 100644
--- a/libweave/src/device_manager.h
+++ b/libweave/src/device_manager.h
@@ -48,9 +48,9 @@
   void AddStateChangedCallback(const base::Closure& callback) override;
   void AddStateDefinitionsFromJson(const std::string& json) override;
   void AddStateDefinitions(const base::DictionaryValue& dict) override;
-  bool SetStateFromJson(const std::string& json, ErrorPtr* error) override;
-  bool SetState(const base::DictionaryValue& dict, ErrorPtr* error) override;
-  bool SetStateProperties(const base::DictionaryValue& property_set,
+  bool SetStatePropertiesFromJson(const std::string& json,
+                                  ErrorPtr* error) override;
+  bool SetStateProperties(const base::DictionaryValue& dict,
                           ErrorPtr* error) override;
   std::unique_ptr<base::Value> GetStateProperty(
       const std::string& name) const override;
diff --git a/libweave/src/privet/privet_handler.cc b/libweave/src/privet/privet_handler.cc
index 47ee8f7..9475cfe 100644
--- a/libweave/src/privet/privet_handler.cc
+++ b/libweave/src/privet/privet_handler.cc
@@ -182,7 +182,7 @@
 }
 
 template <class T>
-void SetState(const T& state, base::DictionaryValue* parent) {
+void SetStateProperties(const T& state, base::DictionaryValue* parent) {
   if (!state.error()) {
     parent->SetString(kStatusKey, EnumToString(state.status()));
     return;
@@ -330,7 +330,7 @@
     DCHECK(!state.IsStatusEqual(ConnectionState::kOnline));
     result->SetString(kInfoWifiHostedSsidKey, hosted_ssid);
   }
-  SetState(state, result.get());
+  SetStateProperties(state, result.get());
   return result;
 }
 
@@ -338,7 +338,7 @@
     const CloudDelegate& cloud) {
   std::unique_ptr<base::DictionaryValue> gcd(new base::DictionaryValue());
   gcd->SetString(kInfoIdKey, cloud.GetCloudId());
-  SetState(cloud.GetConnectionState(), gcd.get());
+  SetStateProperties(cloud.GetConnectionState(), gcd.get());
   return gcd;
 }
 
@@ -718,7 +718,7 @@
   if (!state.IsStatusEqual(SetupState::kNone)) {
     base::DictionaryValue* gcd = new base::DictionaryValue;
     output.Set(kGcdKey, gcd);
-    SetState(state, gcd);
+    SetStateProperties(state, gcd);
     if (state.IsStatusEqual(SetupState::kSuccess))
       gcd->SetString(kInfoIdKey, cloud_->GetCloudId());
   }
@@ -728,7 +728,7 @@
     if (!state.IsStatusEqual(SetupState::kNone)) {
       base::DictionaryValue* wifi = new base::DictionaryValue;
       output.Set(kWifiKey, wifi);
-      SetState(state, wifi);
+      SetStateProperties(state, wifi);
       if (state.IsStatusEqual(SetupState::kSuccess))
         wifi->SetString(kInfoWifiSsidKey, wifi_->GetCurrentlyConnectedSsid());
     }
diff --git a/libweave/src/states/state_manager.cc b/libweave/src/states/state_manager.cc
index b0dd802..c579818 100644
--- a/libweave/src/states/state_manager.cc
+++ b/libweave/src/states/state_manager.cc
@@ -60,7 +60,7 @@
   CHECK(LoadBaseStateDefinition(kBaseStateDefs, nullptr));
 
   // Load standard device state defaults.
-  CHECK(LoadStateDefaults(kBaseStateDefaults, nullptr));
+  CHECK(SetPropertiesFromJson(kBaseStateDefaults, nullptr));
 
   for (const auto& cb : on_changed_)
     cb.Run();
@@ -76,23 +76,6 @@
   return dict;
 }
 
-bool StateManager::SetProperties(const base::DictionaryValue& property_set,
-                                 ErrorPtr* error) {
-  base::Time timestamp = base::Time::Now();
-  bool all_success = true;
-  for (base::DictionaryValue::Iterator it(property_set); !it.IsAtEnd();
-       it.Advance()) {
-    if (!SetPropertyValue(it.key(), it.value(), timestamp, error)) {
-      // Remember that an error occurred but keep going and update the rest of
-      // the properties if possible.
-      all_success = false;
-    }
-  }
-  for (const auto& cb : on_changed_)
-    cb.Run();
-  return all_success;
-}
-
 bool StateManager::SetProperty(const std::string& name,
                                const base::Value& value,
                                ErrorPtr* error) {
@@ -192,8 +175,8 @@
   return true;
 }
 
-bool StateManager::LoadStateDefinition(const std::string& json,
-                                       ErrorPtr* error) {
+bool StateManager::LoadStateDefinitionFromJson(const std::string& json,
+                                               ErrorPtr* error) {
   std::unique_ptr<const base::DictionaryValue> dict = LoadJsonDict(json, error);
   if (!dict)
     return false;
@@ -220,8 +203,8 @@
   return true;
 }
 
-bool StateManager::LoadStateDefaults(const base::DictionaryValue& dict,
-                                     ErrorPtr* error) {
+bool StateManager::SetProperties(const base::DictionaryValue& dict,
+                                 ErrorPtr* error) {
   base::Time timestamp = base::Time::Now();
   bool all_success = true;
   for (base::DictionaryValue::Iterator iter(dict); !iter.IsAtEnd();
@@ -257,11 +240,12 @@
   return all_success;
 }
 
-bool StateManager::LoadStateDefaults(const std::string& json, ErrorPtr* error) {
+bool StateManager::SetPropertiesFromJson(const std::string& json,
+                                         ErrorPtr* error) {
   std::unique_ptr<const base::DictionaryValue> dict = LoadJsonDict(json, error);
   if (!dict)
     return false;
-  if (!LoadStateDefaults(*dict, error)) {
+  if (!SetProperties(*dict, error)) {
     Error::AddToPrintf(error, FROM_HERE, errors::kErrorDomain,
                        errors::kSchemaError, "Failed to load defaults: '%s'",
                        json.c_str());
diff --git a/libweave/src/states/state_manager.h b/libweave/src/states/state_manager.h
index 72f9ddd..ce85e95 100644
--- a/libweave/src/states/state_manager.h
+++ b/libweave/src/states/state_manager.h
@@ -36,11 +36,9 @@
 
   void AddChangedCallback(const base::Closure& callback);
   bool LoadStateDefinition(const base::DictionaryValue& dict, ErrorPtr* error);
-  bool LoadStateDefinition(const std::string& json, ErrorPtr* error);
-  bool LoadStateDefaults(const base::DictionaryValue& dict, ErrorPtr* error);
-  bool LoadStateDefaults(const std::string& json, ErrorPtr* error);
-  bool SetProperties(const base::DictionaryValue& property_set,
-                     ErrorPtr* error);
+  bool LoadStateDefinitionFromJson(const std::string& json, ErrorPtr* error);
+  bool SetProperties(const base::DictionaryValue& dict, ErrorPtr* error);
+  bool SetPropertiesFromJson(const std::string& json, ErrorPtr* error);
   std::unique_ptr<base::Value> GetProperty(const std::string& name) const;
   bool SetProperty(const std::string& name,
                    const base::Value& value,
diff --git a/libweave/src/states/state_manager_unittest.cc b/libweave/src/states/state_manager_unittest.cc
index 3273a16..3496ec6 100644
--- a/libweave/src/states/state_manager_unittest.cc
+++ b/libweave/src/states/state_manager_unittest.cc
@@ -69,7 +69,7 @@
         base::Bind(&StateManagerTest::OnStateChanged, base::Unretained(this)));
 
     LoadStateDefinition(GetTestSchema().get(), nullptr);
-    ASSERT_TRUE(mgr_->LoadStateDefaults(*GetTestValues().get(), nullptr));
+    ASSERT_TRUE(mgr_->SetProperties(*GetTestValues().get(), nullptr));
   }
   void TearDown() override { mgr_.reset(); }
 
@@ -136,10 +136,10 @@
   StateManager manager(&mock_state_change_queue_);
 
   manager.Startup();
-  ASSERT_TRUE(manager.LoadStateDefinition(
+  ASSERT_TRUE(manager.LoadStateDefinitionFromJson(
       R"({"power": {"battery_level":"integer"}})", nullptr));
-  ASSERT_TRUE(
-      manager.LoadStateDefaults(R"({"power": {"battery_level":44}})", nullptr));
+  ASSERT_TRUE(manager.SetPropertiesFromJson(
+      R"({"power": {"battery_level":44}})", nullptr));
 
   auto expected = R"({
     'base': {
@@ -238,7 +238,7 @@
 
   EXPECT_CALL(*this, OnStateChanged()).Times(1);
   ASSERT_TRUE(mgr_->SetProperties(
-      *CreateDictionaryValue("{'base.manufacturer': 'No Name'}"), nullptr));
+      *CreateDictionaryValue("{'base':{'manufacturer':'No Name'}}"), nullptr));
 
   auto expected = R"({
     'base': {
diff --git a/libweave/src/weave_unittest.cc b/libweave/src/weave_unittest.cc
index 1b926f6..458a620 100644
--- a/libweave/src/weave_unittest.cc
+++ b/libweave/src/weave_unittest.cc
@@ -229,7 +229,7 @@
 
     device_->AddCommandDefinitionsFromJson(kCommandDefs);
     device_->AddStateDefinitionsFromJson(kStateDefs);
-    device_->SetStateFromJson(kStateDefaults, nullptr);
+    device_->SetStatePropertiesFromJson(kStateDefaults, nullptr);
 
     for (const auto& cb : http_server_changed_cb_)
       cb.Run(http_server_);