Add support for legacy state/commandDefs to ComponentManager
Added methods to convert legacy state/stateDefs/commandDefs to
the new trait definitions and components and functions to convert
the trait definitions/component tree back to old commandDefs and
state.
Change-Id: Ia03142c53d00bbc4f880389166982167e3c8b1e9
Reviewed-on: https://weave-review.googlesource.com/1787
Reviewed-by: Vitaly Buka <vitalybuka@google.com>
diff --git a/src/component_manager_impl.cc b/src/component_manager_impl.cc
index 8cfa95e..1883739 100644
--- a/src/component_manager_impl.cc
+++ b/src/component_manager_impl.cc
@@ -448,6 +448,142 @@
return std::string{};
}
+bool ComponentManagerImpl::AddLegacyCommandDefinitions(
+ const base::DictionaryValue& dict,
+ ErrorPtr* error) {
+ bool result = true;
+ bool modified = false;
+ for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
+ const base::DictionaryValue* command_dict = nullptr;
+ if (!it.value().GetAsDictionary(&command_dict)) {
+ Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
+ errors::commands::kTypeMismatch,
+ "Package '%s' must be an object", it.key().c_str());
+ result = false;
+ continue;
+ }
+ AddTraitToLegacyComponent(it.key());
+ for (base::DictionaryValue::Iterator it_def(*command_dict);
+ !it_def.IsAtEnd(); it_def.Advance()) {
+ std::string key = base::StringPrintf("%s.commands.%s", it.key().c_str(),
+ it_def.key().c_str());
+ if (traits_.GetDictionary(key, nullptr)) {
+ Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
+ errors::commands::kInvalidPropValue,
+ "Redefining command '%s.%s'",
+ it.key().c_str(), it_def.key().c_str());
+ result = false;
+ continue;
+ }
+ traits_.Set(key, it_def.value().DeepCopy());
+ modified = true;
+ }
+ }
+
+ if (modified) {
+ for (const auto& cb : on_trait_changed_)
+ cb.Run();
+ }
+ return result;
+}
+
+bool ComponentManagerImpl::AddLegacyStateDefinitions(
+ const base::DictionaryValue& dict,
+ ErrorPtr* error) {
+ bool result = true;
+ bool modified = false;
+ for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
+ const base::DictionaryValue* state_dict = nullptr;
+ if (!it.value().GetAsDictionary(&state_dict)) {
+ Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
+ errors::commands::kTypeMismatch,
+ "Package '%s' must be an object", it.key().c_str());
+ result = false;
+ continue;
+ }
+ AddTraitToLegacyComponent(it.key());
+ for (base::DictionaryValue::Iterator it_def(*state_dict); !it_def.IsAtEnd();
+ it_def.Advance()) {
+ std::string key = base::StringPrintf("%s.state.%s", it.key().c_str(),
+ it_def.key().c_str());
+ if (traits_.GetDictionary(key, nullptr)) {
+ Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
+ errors::commands::kInvalidPropValue,
+ "Redefining state property '%s.%s'",
+ it.key().c_str(), it_def.key().c_str());
+ result = false;
+ continue;
+ }
+ traits_.Set(key, it_def.value().DeepCopy());
+ modified = true;
+ }
+ }
+
+ if (modified) {
+ for (const auto& cb : on_trait_changed_)
+ cb.Run();
+ }
+ return result;
+}
+
+const base::DictionaryValue& ComponentManagerImpl::GetLegacyState() const {
+ legacy_state_.Clear();
+ // Build state from components.
+ for (base::DictionaryValue::Iterator it(components_); !it.IsAtEnd();
+ it.Advance()) {
+ const base::DictionaryValue* component_dict = nullptr;
+ const base::DictionaryValue* component_state = nullptr;
+ if (it.value().GetAsDictionary(&component_dict) &&
+ component_dict->GetDictionary("state", &component_state)) {
+ legacy_state_.MergeDictionary(component_state);
+ }
+ }
+ return legacy_state_;
+}
+
+const base::DictionaryValue&
+ComponentManagerImpl::GetLegacyCommandDefinitions() const {
+ legacy_command_defs_.Clear();
+ // Build commandDefs from traits.
+ for (base::DictionaryValue::Iterator it(traits_); !it.IsAtEnd();
+ it.Advance()) {
+ const base::DictionaryValue* trait_dict = nullptr;
+ const base::DictionaryValue* trait_commands = nullptr;
+ if (it.value().GetAsDictionary(&trait_dict) &&
+ trait_dict->GetDictionary("commands", &trait_commands)) {
+ base::DictionaryValue dict;
+ dict.Set(it.key(), trait_commands->DeepCopy());
+ legacy_command_defs_.MergeDictionary(&dict);
+ }
+ }
+ return legacy_command_defs_;
+}
+
+void ComponentManagerImpl::AddTraitToLegacyComponent(const std::string& trait) {
+ // First check if we already have a component supporting this trait.
+ if (!FindComponentWithTrait(trait).empty())
+ return;
+
+ // If not, add this trait to the first component available.
+ base::DictionaryValue* component = nullptr;
+ base::DictionaryValue::Iterator it(components_);
+ if (it.IsAtEnd()) {
+ // No components at all. Create a new one with dummy name.
+ // This normally wouldn't happen since libweave creates its own component
+ // at startup.
+ component = new base::DictionaryValue;
+ components_.Set("__weave__", component);
+ } else {
+ CHECK(components_.GetDictionary(it.key(), &component));
+ }
+ base::ListValue* traits = nullptr;
+ if (!component->GetList("traits", &traits)) {
+ traits = new base::ListValue;
+ component->Set("traits", traits);
+ }
+ traits->AppendString(trait);
+}
+
base::DictionaryValue* ComponentManagerImpl::FindComponentGraftNode(
const std::string& path, ErrorPtr* error) {
base::DictionaryValue* root = nullptr;