| // 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/commands/prop_constraints.h" |
| |
| #include <base/json/json_writer.h> |
| |
| #include "buffet/commands/prop_values.h" |
| #include "buffet/commands/schema_constants.h" |
| |
| namespace buffet { |
| |
| namespace { |
| |
| // Helper function to convert a property value to string, which is used for |
| // error reporting. |
| std::string PropValueToString(const PropValue& value) { |
| std::string result; |
| auto json = value.ToJson(nullptr); |
| if (json) |
| base::JSONWriter::Write(json.get(), &result); |
| return result; |
| } |
| |
| } // anonymous namespace |
| |
| // Constraint ---------------------------------------------------------------- |
| Constraint::~Constraint() {} |
| |
| bool Constraint::ReportErrorLessThan(chromeos::ErrorPtr* error, |
| const std::string& val, |
| const std::string& limit) { |
| chromeos::Error::AddToPrintf( |
| error, FROM_HERE, errors::commands::kDomain, |
| errors::commands::kOutOfRange, |
| "Value %s is out of range. It must not be less than %s", |
| val.c_str(), limit.c_str()); |
| return false; |
| } |
| |
| bool Constraint::ReportErrorGreaterThan(chromeos::ErrorPtr* error, |
| const std::string& val, |
| const std::string& limit) { |
| chromeos::Error::AddToPrintf( |
| error, FROM_HERE, errors::commands::kDomain, |
| errors::commands::kOutOfRange, |
| "Value %s is out of range. It must not be greater than %s", |
| val.c_str(), limit.c_str()); |
| return false; |
| } |
| |
| bool Constraint::ReportErrorNotOneOf(chromeos::ErrorPtr* error, |
| const std::string& val, |
| const std::vector<std::string>& values) { |
| chromeos::Error::AddToPrintf( |
| error, FROM_HERE, errors::commands::kDomain, |
| errors::commands::kOutOfRange, |
| "Value %s is invalid. Expected one of [%s]", val.c_str(), |
| chromeos::string_utils::Join(",", values).c_str()); |
| return false; |
| } |
| |
| bool Constraint::AddToJsonDict(base::DictionaryValue* dict, |
| bool overridden_only, |
| chromeos::ErrorPtr* error) const { |
| if (!overridden_only || HasOverriddenAttributes()) { |
| auto value = ToJson(error); |
| if (!value) |
| return false; |
| dict->SetWithoutPathExpansion(GetDictKey(), value.release()); |
| } |
| return true; |
| } |
| |
| // ConstraintStringLength ----------------------------------------------------- |
| ConstraintStringLength::ConstraintStringLength( |
| const InheritableAttribute<int>& limit) : limit_(limit) {} |
| ConstraintStringLength::ConstraintStringLength(int limit) : limit_(limit) {} |
| |
| bool ConstraintStringLength::HasOverriddenAttributes() const { |
| return !limit_.is_inherited; |
| } |
| |
| std::unique_ptr<base::Value> ConstraintStringLength::ToJson( |
| chromeos::ErrorPtr* error) const { |
| return TypedValueToJson(limit_.value, error); |
| } |
| |
| // ConstraintStringLengthMin -------------------------------------------------- |
| ConstraintStringLengthMin::ConstraintStringLengthMin( |
| const InheritableAttribute<int>& limit) : ConstraintStringLength(limit) {} |
| ConstraintStringLengthMin::ConstraintStringLengthMin(int limit) |
| : ConstraintStringLength(limit) {} |
| |
| bool ConstraintStringLengthMin::Validate(const PropValue& value, |
| chromeos::ErrorPtr* error) const { |
| CHECK(value.GetString()) << "Expecting a string value for this constraint"; |
| const std::string& str = value.GetString()->GetValue(); |
| int length = static_cast<int>(str.size()); |
| if (length < limit_.value) { |
| if (limit_.value == 1) { |
| chromeos::Error::AddTo(error, FROM_HERE, errors::commands::kDomain, |
| errors::commands::kOutOfRange, |
| "String must not be empty"); |
| } else { |
| chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain, |
| errors::commands::kOutOfRange, |
| "String must be at least %d characters long," |
| " actual length of string '%s' is %d", |
| limit_.value, str.c_str(), length); |
| } |
| return false; |
| } |
| return true; |
| } |
| |
| std::unique_ptr<Constraint> |
| ConstraintStringLengthMin::Clone() const { |
| return std::unique_ptr<Constraint>{new ConstraintStringLengthMin{limit_}}; |
| } |
| |
| std::unique_ptr<Constraint> |
| ConstraintStringLengthMin::CloneAsInherited() const { |
| return std::unique_ptr<Constraint>{ |
| new ConstraintStringLengthMin{limit_.value}}; |
| } |
| |
| // ConstraintStringLengthMax -------------------------------------------------- |
| ConstraintStringLengthMax::ConstraintStringLengthMax( |
| const InheritableAttribute<int>& limit) : ConstraintStringLength(limit) {} |
| ConstraintStringLengthMax::ConstraintStringLengthMax(int limit) |
| : ConstraintStringLength(limit) {} |
| |
| bool ConstraintStringLengthMax::Validate(const PropValue& value, |
| chromeos::ErrorPtr* error) const { |
| CHECK(value.GetString()) << "Expecting a string value for this constraint"; |
| const std::string& str = value.GetString()->GetValue(); |
| int length = static_cast<int>(str.size()); |
| if (length > limit_.value) { |
| chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain, |
| errors::commands::kOutOfRange, |
| "String must be no more than %d character(s) " |
| "long, actual length of string '%s' is %d", |
| limit_.value, str.c_str(), length); |
| return false; |
| } |
| return true; |
| } |
| |
| std::unique_ptr<Constraint> |
| ConstraintStringLengthMax::Clone() const { |
| return std::unique_ptr<Constraint>{new ConstraintStringLengthMax{limit_}}; |
| } |
| |
| std::unique_ptr<Constraint> |
| ConstraintStringLengthMax::CloneAsInherited() const { |
| return std::unique_ptr<Constraint>{ |
| new ConstraintStringLengthMax{limit_.value}}; |
| } |
| |
| // ConstraintOneOf -------------------------------------------------- |
| ConstraintOneOf::ConstraintOneOf(InheritableAttribute<native_types::Array> set) |
| : set_(std::move(set)) {} |
| ConstraintOneOf::ConstraintOneOf(native_types::Array set) |
| : set_(std::move(set)) {} |
| |
| bool ConstraintOneOf::Validate(const PropValue& value, |
| chromeos::ErrorPtr* error) const { |
| for (const auto& item : set_.value) { |
| if (value.IsEqual(item.get())) |
| return true; |
| } |
| std::vector<std::string> choice_list; |
| choice_list.reserve(set_.value.size()); |
| for (const auto& item : set_.value) { |
| choice_list.push_back(PropValueToString(*item)); |
| } |
| return ReportErrorNotOneOf(error, PropValueToString(value), choice_list); |
| } |
| |
| std::unique_ptr<Constraint> ConstraintOneOf::Clone() const { |
| InheritableAttribute<native_types::Array> attr; |
| attr.is_inherited = set_.is_inherited; |
| attr.value.reserve(set_.value.size()); |
| for (const auto& prop_value : set_.value) { |
| attr.value.push_back(prop_value->Clone()); |
| } |
| return std::unique_ptr<Constraint>{new ConstraintOneOf{std::move(attr)}}; |
| } |
| |
| std::unique_ptr<Constraint> ConstraintOneOf::CloneAsInherited() const { |
| native_types::Array cloned; |
| cloned.reserve(set_.value.size()); |
| for (const auto& prop_value : set_.value) { |
| cloned.push_back(prop_value->Clone()); |
| } |
| return std::unique_ptr<Constraint>{new ConstraintOneOf{std::move(cloned)}}; |
| } |
| |
| std::unique_ptr<base::Value> ConstraintOneOf::ToJson( |
| chromeos::ErrorPtr* error) const { |
| return TypedValueToJson(set_.value, error); |
| } |
| |
| const char* ConstraintOneOf::GetDictKey() const { |
| return commands::attributes::kOneOf_Enum; |
| } |
| |
| } // namespace buffet |