buffet: Adding GCD command definition schema - phase 1.
Initial implementation of GCD command definition schema
and parsing command definition provided as JSON.
This change introduces the class hierarchy to describe
parameter type description (ParamType-derived classes),
parameter values (ParamValue-derived classes), constraints,
and general object schema which is a collection of
parameter definition for an object which corresponds
almost directly into a GCD command definition.
Object definition parsing from JSON is implemented
as well as validation of parameter values with rich
error reporting.
This is a basis for future command definition implementation
and device draft definition for GCD devices.
BUG=chromium:374860
TEST=Unit tests pass
Change-Id: I82d185b155956ff31a2d2e33f75bec9605ef32ee
Reviewed-on: https://chromium-review.googlesource.com/201159
Reviewed-by: Christopher Wiley <wiley@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/commands/prop_constraints.cc b/buffet/commands/prop_constraints.cc
new file mode 100644
index 0000000..2376588
--- /dev/null
+++ b/buffet/commands/prop_constraints.cc
@@ -0,0 +1,139 @@
+// 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 "buffet/commands/schema_constants.h"
+#include "buffet/string_utils.h"
+
+namespace buffet {
+
+// Specializations of TypedValueToJson<T>() for supported C++ types.
+std::unique_ptr<base::Value> TypedValueToJson(bool value) {
+ return std::unique_ptr<base::Value>(base::Value::CreateBooleanValue(value));
+}
+std::unique_ptr<base::Value> TypedValueToJson(int value) {
+ return std::unique_ptr<base::Value>(base::Value::CreateIntegerValue(value));
+}
+std::unique_ptr<base::Value> TypedValueToJson(double value) {
+ return std::unique_ptr<base::Value>(base::Value::CreateDoubleValue(value));
+}
+std::unique_ptr<base::Value> TypedValueToJson(const std::string& value) {
+ return std::unique_ptr<base::Value>(base::Value::CreateStringValue(value));
+}
+
+// Constraint ----------------------------------------------------------------
+Constraint::~Constraint() {}
+
+bool Constraint::ReportErrorLessThan(
+ ErrorPtr* error, const std::string& val, const std::string& limit) {
+ Error::AddToPrintf(error, commands::errors::kDomain,
+ commands::errors::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(
+ ErrorPtr* error, const std::string& val, const std::string& limit) {
+ Error::AddToPrintf(error, commands::errors::kDomain,
+ commands::errors::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(
+ ErrorPtr* error, const std::string& val,
+ const std::vector<std::string>& values) {
+ Error::AddToPrintf(error, commands::errors::kDomain,
+ commands::errors::kOutOfRange,
+ "Value %s is invalid. Expected one of [%s]",
+ val.c_str(), string_utils::Join(',', values).c_str());
+ return false;
+}
+
+bool Constraint::AddToJsonDict(base::DictionaryValue* dict,
+ bool overridden_only,
+ 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(
+ ErrorPtr* error) const {
+ return TypedValueToJson(limit_.value);
+}
+
+// ConstraintStringLengthMin --------------------------------------------------
+ConstraintStringLengthMin::ConstraintStringLengthMin(
+ const InheritableAttribute<int>& limit) : ConstraintStringLength(limit) {}
+ConstraintStringLengthMin::ConstraintStringLengthMin(int limit)
+ : ConstraintStringLength(limit) {}
+
+bool ConstraintStringLengthMin::Validate(const Any& value,
+ ErrorPtr* error) const {
+ std::string str = value.Get<std::string>();
+ int length = static_cast<int>(str.size());
+ if (length < limit_.value) {
+ if (limit_.value == 1) {
+ Error::AddTo(error, commands::errors::kDomain,
+ commands::errors::kOutOfRange, "String must not be empty");
+ } else {
+ Error::AddToPrintf(error, commands::errors::kDomain,
+ commands::errors::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::shared_ptr<Constraint>
+ ConstraintStringLengthMin::CloneAsInherited() const {
+ return std::make_shared<ConstraintStringLengthMin>(limit_.value);
+}
+
+// ConstraintStringLengthMax --------------------------------------------------
+ConstraintStringLengthMax::ConstraintStringLengthMax(
+ const InheritableAttribute<int>& limit) : ConstraintStringLength(limit) {}
+ConstraintStringLengthMax::ConstraintStringLengthMax(int limit)
+ : ConstraintStringLength(limit) {}
+
+bool ConstraintStringLengthMax::Validate(const Any& value,
+ ErrorPtr* error) const {
+ std::string str = value.Get<std::string>();
+ int length = static_cast<int>(str.size());
+ if (length > limit_.value) {
+ Error::AddToPrintf(error, commands::errors::kDomain,
+ commands::errors::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::shared_ptr<Constraint>
+ ConstraintStringLengthMax::CloneAsInherited() const {
+ return std::make_shared<ConstraintStringLengthMax>(limit_.value);
+}
+
+} // namespace buffet