| // Copyright 2014 The Chromium OS Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "buffet/states/state_package.h" | 
 |  | 
 | #include <base/logging.h> | 
 | #include <base/values.h> | 
 | #include <chromeos/dbus/data_serialization.h> | 
 |  | 
 | #include "buffet/commands/prop_types.h" | 
 | #include "buffet/commands/prop_values.h" | 
 | #include "buffet/commands/schema_utils.h" | 
 | #include "buffet/states/error_codes.h" | 
 |  | 
 | namespace buffet { | 
 |  | 
 | StatePackage::StatePackage(const std::string& name) : name_(name) { | 
 | } | 
 |  | 
 | bool StatePackage::AddSchemaFromJson(const base::DictionaryValue* json, | 
 |                                      chromeos::ErrorPtr* error) { | 
 |   ObjectSchema schema; | 
 |   if (!schema.FromJson(json, nullptr, error)) | 
 |     return false; | 
 |  | 
 |   // Scan first to make sure we have no property redefinitions. | 
 |   for (const auto& pair : schema.GetProps()) { | 
 |     if (types_.GetProp(pair.first)) { | 
 |       chromeos::Error::AddToPrintf(error, FROM_HERE, errors::state::kDomain, | 
 |                                     errors::state::kPropertyRedefinition, | 
 |                                     "State property '%s.%s' is already defined", | 
 |                                     name_.c_str(), pair.first.c_str()); | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   // Now move all the properties to |types_| object. | 
 |   for (const auto& pair : schema.GetProps()) { | 
 |     types_.AddProp(pair.first, pair.second->Clone()); | 
 |     // Create default value for this state property. | 
 |     values_.emplace(pair.first, pair.second->CreateValue()); | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | bool StatePackage::AddValuesFromJson(const base::DictionaryValue* json, | 
 |                                      chromeos::ErrorPtr* error) { | 
 |   base::DictionaryValue::Iterator iter(*json); | 
 |   while (!iter.IsAtEnd()) { | 
 |     std::string property_name = iter.key(); | 
 |     auto it = values_.find(property_name); | 
 |     if (it == values_.end()) { | 
 |       chromeos::Error::AddToPrintf(error, FROM_HERE, errors::state::kDomain, | 
 |                                     errors::state::kPropertyNotDefined, | 
 |                                     "State property '%s.%s' is not defined", | 
 |                                     name_.c_str(), property_name.c_str()); | 
 |       return false; | 
 |     } | 
 |     auto new_value = it->second->GetPropType()->CreateValue(); | 
 |     if (!new_value->FromJson(&iter.value(), error)) | 
 |       return false; | 
 |     it->second = std::move(new_value); | 
 |     iter.Advance(); | 
 |   } | 
 |   return true; | 
 | } | 
 |  | 
 | std::unique_ptr<base::DictionaryValue> StatePackage::GetValuesAsJson( | 
 |       chromeos::ErrorPtr* error) const { | 
 |   std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue); | 
 |   for (const auto& pair : values_) { | 
 |     auto value = pair.second->ToJson(error); | 
 |     if (!value) { | 
 |       dict.reset(); | 
 |       break; | 
 |     } | 
 |     dict->SetWithoutPathExpansion(pair.first, value.release()); | 
 |   } | 
 |   return dict; | 
 | } | 
 |  | 
 | chromeos::Any StatePackage::GetPropertyValue(const std::string& property_name, | 
 |                                              chromeos::ErrorPtr* error) const { | 
 |   auto it = values_.find(property_name); | 
 |   if (it == values_.end()) { | 
 |     chromeos::Error::AddToPrintf(error, FROM_HERE, errors::state::kDomain, | 
 |                                   errors::state::kPropertyNotDefined, | 
 |                                   "State property '%s.%s' is not defined", | 
 |                                   name_.c_str(), property_name.c_str()); | 
 |     return chromeos::Any(); | 
 |   } | 
 |   return PropValueToDBusVariant(it->second.get()); | 
 | } | 
 |  | 
 | bool StatePackage::SetPropertyValue(const std::string& property_name, | 
 |                                     const chromeos::Any& value, | 
 |                                     chromeos::ErrorPtr* error) { | 
 |   auto it = values_.find(property_name); | 
 |   if (it == values_.end()) { | 
 |     chromeos::Error::AddToPrintf(error, FROM_HERE, errors::state::kDomain, | 
 |                                   errors::state::kPropertyNotDefined, | 
 |                                   "State property '%s.%s' is not defined", | 
 |                                   name_.c_str(), property_name.c_str()); | 
 |     return false; | 
 |   } | 
 |   auto new_value = PropValueFromDBusVariant(it->second->GetPropType(), | 
 |                                             value, error); | 
 |   if (!new_value) | 
 |     return false; | 
 |   it->second = std::move(new_value); | 
 |   return true; | 
 | } | 
 |  | 
 | }  // namespace buffet |