Implemented property dependencies of schema
This commit is contained in:
parent
c629d37a00
commit
a5d700e9e8
@ -44,15 +44,18 @@ class BaseSchema;
|
|||||||
|
|
||||||
template <typename Encoding>
|
template <typename Encoding>
|
||||||
struct SchemaValidationContext {
|
struct SchemaValidationContext {
|
||||||
SchemaValidationContext(const BaseSchema<Encoding>* s) : schema(s), valueSchema(), multiTypeSchema() {}
|
SchemaValidationContext(const BaseSchema<Encoding>* s) : schema(s), valueSchema(), multiTypeSchema(), objectDependencies() {}
|
||||||
|
|
||||||
~SchemaValidationContext() {}
|
~SchemaValidationContext() {
|
||||||
|
delete[] objectDependencies;
|
||||||
|
}
|
||||||
|
|
||||||
const BaseSchema<Encoding>* schema;
|
const BaseSchema<Encoding>* schema;
|
||||||
const BaseSchema<Encoding>* valueSchema;
|
const BaseSchema<Encoding>* valueSchema;
|
||||||
const BaseSchema<Encoding>* multiTypeSchema;
|
const BaseSchema<Encoding>* multiTypeSchema;
|
||||||
SizeType objectRequiredCount;
|
SizeType objectRequiredCount;
|
||||||
SizeType arrayElementIndex;
|
SizeType arrayElementIndex;
|
||||||
|
bool* objectDependencies;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Encoding>
|
template <typename Encoding>
|
||||||
@ -246,7 +249,8 @@ public:
|
|||||||
requiredCount_(),
|
requiredCount_(),
|
||||||
minProperties_(),
|
minProperties_(),
|
||||||
maxProperties_(SizeType(~0)),
|
maxProperties_(SizeType(~0)),
|
||||||
additionalProperty_(true)
|
additionalProperty_(true),
|
||||||
|
hasDependencies_()
|
||||||
{
|
{
|
||||||
typename ValueType::ConstMemberIterator propretiesItr = value.FindMember("properties");
|
typename ValueType::ConstMemberIterator propretiesItr = value.FindMember("properties");
|
||||||
if (propretiesItr != value.MemberEnd()) {
|
if (propretiesItr != value.MemberEnd()) {
|
||||||
@ -272,13 +276,53 @@ public:
|
|||||||
properties_[index].required = true;
|
properties_[index].required = true;
|
||||||
requiredCount_++;
|
requiredCount_++;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (requiredCount_ != requiredItr->value.Size()) {
|
// Establish dependencies after properties
|
||||||
// Error
|
typename ValueType::ConstMemberIterator dependenciesItr = value.FindMember("dependencies");
|
||||||
|
if (dependenciesItr != value.MemberEnd()) {
|
||||||
|
if (dependenciesItr->value.IsObject()) {
|
||||||
|
hasDependencies_ = true;
|
||||||
|
for (typename ValueType::ConstMemberIterator itr = dependenciesItr->value.MemberBegin(); itr != dependenciesItr->value.MemberEnd(); ++itr) {
|
||||||
|
SizeType sourceIndex;
|
||||||
|
if (FindPropertyIndex(itr->name, &sourceIndex)) {
|
||||||
|
properties_[sourceIndex].dependencies = new bool[propertyCount_];
|
||||||
|
std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool) * propertyCount_);
|
||||||
|
if (itr->value.IsArray()) {
|
||||||
|
for (typename ValueType::ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) {
|
||||||
|
SizeType targetIndex;
|
||||||
|
if (FindPropertyIndex(*targetItr, &targetIndex)) {
|
||||||
|
properties_[sourceIndex].dependencies[targetIndex] = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// Error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typename ValueType::ConstMemberIterator additionalPropretiesItr = value.FindMember("additionalProperties");
|
typename ValueType::ConstMemberIterator additionalPropretiesItr = value.FindMember("additionalProperties");
|
||||||
@ -329,6 +373,10 @@ public:
|
|||||||
|
|
||||||
virtual bool StartObject(Context& context) const {
|
virtual bool StartObject(Context& context) const {
|
||||||
context.objectRequiredCount = 0;
|
context.objectRequiredCount = 0;
|
||||||
|
if (hasDependencies_) {
|
||||||
|
context.objectDependencies = new bool[propertyCount_];
|
||||||
|
std::memset(context.objectDependencies, 0, sizeof(bool) * propertyCount_);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,6 +388,9 @@ public:
|
|||||||
if (properties_[index].required)
|
if (properties_[index].required)
|
||||||
context.objectRequiredCount++;
|
context.objectRequiredCount++;
|
||||||
|
|
||||||
|
if (hasDependencies_)
|
||||||
|
context.objectDependencies[index] = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,9 +407,18 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual bool EndObject(Context& context, SizeType memberCount) const {
|
virtual bool EndObject(Context& context, SizeType memberCount) const {
|
||||||
return context.objectRequiredCount == requiredCount_ &&
|
if (context.objectRequiredCount != requiredCount_ || memberCount < minProperties_ || memberCount > maxProperties_)
|
||||||
memberCount >= minProperties_ &&
|
return false;
|
||||||
memberCount <= maxProperties_;
|
|
||||||
|
if (hasDependencies_) {
|
||||||
|
for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++)
|
||||||
|
if (context.objectDependencies[sourceIndex] && properties_[sourceIndex].dependencies)
|
||||||
|
for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++)
|
||||||
|
if (properties_[sourceIndex].dependencies[targetIndex] && !context.objectDependencies[targetIndex])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool StartArray(Context&) const { return false; }
|
virtual bool StartArray(Context&) const { return false; }
|
||||||
@ -391,13 +451,15 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct Property {
|
struct Property {
|
||||||
Property() : schema(), required(false) {}
|
Property() : schema(), dependencies(), required(false) {}
|
||||||
~Property() {
|
~Property() {
|
||||||
delete schema;
|
delete schema;
|
||||||
|
delete[] dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericValue<Encoding> name;
|
GenericValue<Encoding> name;
|
||||||
BaseSchema<Encoding>* schema;
|
BaseSchema<Encoding>* schema;
|
||||||
|
bool* dependencies;
|
||||||
bool required;
|
bool required;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -409,6 +471,7 @@ private:
|
|||||||
SizeType minProperties_;
|
SizeType minProperties_;
|
||||||
SizeType maxProperties_;
|
SizeType maxProperties_;
|
||||||
bool additionalProperty_;
|
bool additionalProperty_;
|
||||||
|
bool hasDependencies_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Encoding>
|
template <typename Encoding>
|
||||||
@ -894,7 +957,6 @@ public:
|
|||||||
schemaStack_(allocator, schemaStackCapacity),
|
schemaStack_(allocator, schemaStackCapacity),
|
||||||
documentStack_(allocator, documentStackCapacity)
|
documentStack_(allocator, documentStackCapacity)
|
||||||
{
|
{
|
||||||
Reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericSchemaValidator(
|
GenericSchemaValidator(
|
||||||
@ -909,11 +971,15 @@ public:
|
|||||||
schemaStack_(allocator, schemaStackCapacity),
|
schemaStack_(allocator, schemaStackCapacity),
|
||||||
documentStack_(allocator, documentStackCapacity)
|
documentStack_(allocator, documentStackCapacity)
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~GenericSchemaValidator() {
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset() {
|
void Reset() {
|
||||||
schemaStack_.Clear();
|
while (!schemaStack_.Empty())
|
||||||
|
PopSchema();
|
||||||
documentStack_.Clear();
|
documentStack_.Clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -965,7 +1031,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PushSchema(const BaseSchemaType& schema) { *schemaStack_.template Push<Context>() = Context(&schema); }
|
void PushSchema(const BaseSchemaType& schema) { *schemaStack_.template Push<Context>() = Context(&schema); }
|
||||||
const BaseSchemaType& PopSchema() { return *schemaStack_.template Pop<Context>(1)->schema; }
|
void PopSchema() { schemaStack_.template Pop<Context>(1)->~Context(); }
|
||||||
const BaseSchemaType& CurrentSchema() { return *schemaStack_.template Top<Context>()->schema; }
|
const BaseSchemaType& CurrentSchema() { return *schemaStack_.template Top<Context>()->schema; }
|
||||||
Context& CurrentContext() { return *schemaStack_.template Top<Context>(); }
|
Context& CurrentContext() { return *schemaStack_.template Top<Context>(); }
|
||||||
|
|
||||||
|
@ -278,8 +278,6 @@ TEST(SchemaValidator, Object_PropertiesRange) {
|
|||||||
VALIDATE(s, "{\"a\":0,\"b\":1,\"c\":2,\"d\":3}", false);
|
VALIDATE(s, "{\"a\":0,\"b\":1,\"c\":2,\"d\":3}", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
// TODO
|
|
||||||
TEST(SchemaValidator, Object_PropertyDependencies) {
|
TEST(SchemaValidator, Object_PropertyDependencies) {
|
||||||
Document sd;
|
Document sd;
|
||||||
sd.Parse(
|
sd.Parse(
|
||||||
@ -302,7 +300,6 @@ TEST(SchemaValidator, Object_PropertyDependencies) {
|
|||||||
VALIDATE(s, "{ \"name\": \"John Doe\"}", true);
|
VALIDATE(s, "{ \"name\": \"John Doe\"}", true);
|
||||||
VALIDATE(s, "{ \"name\": \"John Doe\", \"billing_address\": \"555 Debtor's Lane\" }", true);
|
VALIDATE(s, "{ \"name\": \"John Doe\", \"billing_address\": \"555 Debtor's Lane\" }", true);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
TEST(SchemaValidator, Array) {
|
TEST(SchemaValidator, Array) {
|
||||||
Document sd;
|
Document sd;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user