buffet: GCD command defintion. Compound object type support.
Added support for "object" type. Refactored parameter validation
to make sure we have object schema context when we validate
a value of parameter.
Parameter |schema| was used in two different contexts, as both
a base parameter definition and as a custom object definition.
Renamed the former to be 'base_schema' and latter as
'object_schema' to remove the confusion.
Extracted common data type manipulation functions into
schema_utils.cc/.h files.
BUG=chromium:374860
TEST=All unit tests pass.
Change-Id: I6c3549849a258bcc94b3d754acd14e072438d140
Reviewed-on: https://chromium-review.googlesource.com/204793
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
Reviewed-by: Christopher Wiley <wiley@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/commands/object_schema.cc b/buffet/commands/object_schema.cc
index 19610be..0312735 100644
--- a/buffet/commands/object_schema.cc
+++ b/buffet/commands/object_schema.cc
@@ -41,14 +41,15 @@
}
bool ObjectSchema::FromJson(const base::DictionaryValue* value,
- const ObjectSchema* schema, ErrorPtr* error) {
+ const ObjectSchema* object_schema,
+ ErrorPtr* error) {
Properties properties;
base::DictionaryValue::Iterator iter(*value);
while (!iter.IsAtEnd()) {
std::string name = iter.key();
- const PropType* schemaProp = schema ? schema->GetProp(iter.key()) :
- nullptr;
- if (!PropFromJson(iter.key(), iter.value(), schemaProp, &properties,
+ const PropType* base_schema =
+ object_schema ? object_schema->GetProp(iter.key()) : nullptr;
+ if (!PropFromJson(iter.key(), iter.value(), base_schema, &properties,
error))
return false;
iter.Advance();
@@ -84,21 +85,21 @@
bool ObjectSchema::PropFromJson(const std::string& prop_name,
const base::Value& value,
- const PropType* schemaProp,
+ const PropType* base_schema,
Properties* properties,
ErrorPtr* error) const {
if (value.IsType(base::Value::TYPE_STRING)) {
// A string value is a short-hand object specification and provides
// the parameter type.
- return PropFromJsonString(prop_name, value, schemaProp, properties,
+ return PropFromJsonString(prop_name, value, base_schema, properties,
error);
} else if (value.IsType(base::Value::TYPE_LIST)) {
// One of the enumerated types.
- return PropFromJsonArray(prop_name, value, schemaProp, properties,
+ return PropFromJsonArray(prop_name, value, base_schema, properties,
error);
} else if (value.IsType(base::Value::TYPE_DICTIONARY)) {
// Full parameter definition.
- return PropFromJsonObject(prop_name, value, schemaProp, properties,
+ return PropFromJsonObject(prop_name, value, base_schema, properties,
error);
}
Error::AddToPrintf(error, commands::errors::kDomain,
@@ -109,7 +110,7 @@
bool ObjectSchema::PropFromJsonString(const std::string& prop_name,
const base::Value& value,
- const PropType* schemaProp,
+ const PropType* base_schema,
Properties* properties,
ErrorPtr* error) const {
std::string type_name;
@@ -118,17 +119,17 @@
if (!prop)
return false;
base::DictionaryValue empty;
- if (!prop->FromJson(&empty, schemaProp, error))
+ if (!prop->FromJson(&empty, base_schema, error))
return false;
properties->insert(std::make_pair(prop_name, std::move(prop)));
return true;
}
static std::string DetectArrayType(const base::ListValue* list,
- const PropType* schemaProp) {
+ const PropType* base_schema) {
std::string type_name;
- if (schemaProp) {
- type_name = schemaProp->GetTypeAsString();
+ if (base_schema) {
+ type_name = base_schema->GetTypeAsString();
} else if (list->GetSize() > 0) {
const base::Value* first_element = nullptr;
if (list->Get(0, &first_element)) {
@@ -145,6 +146,9 @@
case base::Value::TYPE_STRING:
type_name = PropType::GetTypeStringFromType(ValueType::String);
break;
+ case base::Value::TYPE_DICTIONARY:
+ type_name = PropType::GetTypeStringFromType(ValueType::Object);
+ break;
default:
// The rest are unsupported.
break;
@@ -156,12 +160,12 @@
bool ObjectSchema::PropFromJsonArray(const std::string& prop_name,
const base::Value& value,
- const PropType* schemaProp,
+ const PropType* base_schema,
Properties* properties,
ErrorPtr* error) const {
const base::ListValue* list = nullptr;
CHECK(value.GetAsList(&list)) << "Unable to get array value";
- std::string type_name = DetectArrayType(list, schemaProp);
+ std::string type_name = DetectArrayType(list, base_schema);
if (type_name.empty())
return ErrorInvalidTypeInfo(prop_name, error);
std::unique_ptr<PropType> prop = CreatePropType(type_name, prop_name, error);
@@ -170,14 +174,14 @@
base::DictionaryValue array_object;
array_object.SetWithoutPathExpansion(commands::attributes::kOneOf_Enum,
list->DeepCopy());
- if (!prop->FromJson(&array_object, schemaProp, error))
+ if (!prop->FromJson(&array_object, base_schema, error))
return false;
properties->insert(std::make_pair(prop_name, std::move(prop)));
return true;
}
static std::string DetectObjectType(const base::DictionaryValue* dict,
- const PropType* schemaProp) {
+ const PropType* base_schema) {
bool has_min_max = dict->HasKey(commands::attributes::kNumeric_Min) ||
dict->HasKey(commands::attributes::kNumeric_Max);
@@ -191,7 +195,7 @@
// "min:0, max:0" instead of just forcing it to be only "min:0.0, max:0.0".
// If we have "minimum" or "maximum", and we have a Double schema object,
// treat this object as a Double (even if both min and max are integers).
- if (has_min_max && schemaProp && schemaProp->GetType() == ValueType::Double)
+ if (has_min_max && base_schema && base_schema->GetType() == ValueType::Double)
return PropType::GetTypeStringFromType(ValueType::Double);
// If we have at least one "minimum" or "maximum" that is Double,
@@ -213,18 +217,22 @@
dict->HasKey(commands::attributes::kString_MaxLength))
return PropType::GetTypeStringFromType(ValueType::String);
- // If we have "values", it's an array.
+ // If we have "properties", it's an object.
+ if (dict->HasKey(commands::attributes::kObject_Properties))
+ return PropType::GetTypeStringFromType(ValueType::Object);
+
+ // If we have "enum", it's an array. Detect type from array elements.
const base::ListValue* list = nullptr;
if (dict->GetListWithoutPathExpansion(
commands::attributes::kOneOf_Enum, &list))
- return DetectArrayType(list, schemaProp);
+ return DetectArrayType(list, base_schema);
return std::string();
}
bool ObjectSchema::PropFromJsonObject(const std::string& prop_name,
const base::Value& value,
- const PropType* schemaProp,
+ const PropType* base_schema,
Properties* properties,
ErrorPtr* error) const {
const base::DictionaryValue* dict = nullptr;
@@ -234,15 +242,15 @@
if (!dict->GetString(commands::attributes::kType, &type_name))
return ErrorInvalidTypeInfo(prop_name, error);
} else {
- type_name = DetectObjectType(dict, schemaProp);
+ type_name = DetectObjectType(dict, base_schema);
}
if (type_name.empty()) {
- if (!schemaProp)
+ if (!base_schema)
return ErrorInvalidTypeInfo(prop_name, error);
- type_name = schemaProp->GetTypeAsString();
+ type_name = base_schema->GetTypeAsString();
}
std::unique_ptr<PropType> prop = CreatePropType(type_name, prop_name, error);
- if (!prop || !prop->FromJson(dict, schemaProp, error))
+ if (!prop || !prop->FromJson(dict, base_schema, error))
return false;
properties->insert(std::make_pair(prop_name, std::move(prop)));
return true;