summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexei Rousskikh <ext-alexei.rousskikh@nokia.com>2012-02-16 13:39:08 -0500
committerAndrew Christian <andrew.christian@nokia.com>2012-02-16 21:16:40 +0100
commit7073c61891b6b0bb92aea512692a7686568656f4 (patch)
tree50c3cf13ff95b56da62911a6188536594a8504e8
parenta870d6db7ecd32516ec5029cbde06e4f89805e97 (diff)
initial default schema property implementation
Change-Id: I7a876291cbea19a00bb692cdf9000bcb7a586904 Reviewed-by: Andrew Christian <andrew.christian@nokia.com>
-rw-r--r--src/qtjsonschema/checkpoints_p.h104
-rw-r--r--src/qtjsonschema/jsonobjecttypes_impl_p.h15
-rw-r--r--src/qtjsonschema/jsonobjecttypes_p.h1
-rw-r--r--src/qtjsonschema/schemaobject_p.h13
-rw-r--r--src/qtjsonschema/schemavalidator.h2
-rw-r--r--tests/auto/jsonschema/tst_jsonschema.cpp10
-rw-r--r--tests/auto/jsonstream/schemas/PaintEvent.json3
-rw-r--r--tests/auto/jsonstream/schemas/PaintTextEvent.json13
8 files changed, 157 insertions, 4 deletions
diff --git a/src/qtjsonschema/checkpoints_p.h b/src/qtjsonschema/checkpoints_p.h
index 480f7c1..9ca8a1d 100644
--- a/src/qtjsonschema/checkpoints_p.h
+++ b/src/qtjsonschema/checkpoints_p.h
@@ -324,6 +324,65 @@ public:
}
return true;
}
+
+
+ void checkDefault(Value& value, Object &_object) const
+ {
+ bool ok;
+ Object object = value.toObject(&ok);
+ if (!ok)
+ return;
+
+ //qDebug() << Q_FUNC_INFO;
+
+ // create missing properties list
+ QList<Key> strs;
+ QHashIterator<const Key, QVarLengthArray<Check *, 4> > it(m_checks);
+ while (it.hasNext()) {
+ it.next();
+ strs << it.key();
+ }
+
+ foreach (const Key &key, object.propertyNames()) {
+ QVarLengthArray<Check *, 4> empty;
+ QVarLengthArray<Check *, 4> checks = m_checks.value(key, empty);
+ Value property = object.property(key);
+
+ // remove from missing properties list
+ strs.removeOne(key);
+
+ if (_object[key].isObject()) {
+ foreach (Check *check, checks) {
+ Object oo(_object[key].toObject());
+ check->checkDefault(property, oo);
+ _object[key] = oo;
+ }
+ }
+ }
+
+ // add defaults for missing properties
+ foreach (const Key &key, strs) {
+ QVarLengthArray<Check *, 4> empty;
+ QVarLengthArray<Check *, 4> checks = m_checks.value(key, empty);
+ Value property = object.property(key);
+
+ if (checks.first()->getDefault()) { // basic type
+ _object.insert(key, checks.first()->getDefault()->value());
+ }
+ else { // looks like object or array
+ Object object;
+ foreach (Check *check, checks) {
+ Value value("", Object());
+ check->checkDefault(value, object);
+ }
+
+ if (!object.isEmpty()) {
+ _object.insert(key, object);
+ }
+ }
+ }
+ }
+
private:
QHash<const Key, QVarLengthArray<Check *, 4> > m_checks;
};
@@ -676,6 +735,24 @@ private:
ValueList m_enum;
};
+// 5.20
+template<class T>
+class SchemaPrivate<T>::CheckDefault : public Check {
+public:
+ CheckDefault(SchemaPrivate *schema, QSharedPointer<CheckSharedData> &data, const Value& value)
+ : Check(schema, data, "Default check failed for %1")
+ {
+ // used shared data to store
+ Check::m_data->m_default = QSharedPointer<Value>(new Value(value));
+ }
+
+ virtual bool doCheck(const Value &value)
+ {
+ return true;
+ }
+private:
+};
+
// 5.23
template<class T>
class SchemaPrivate<T>::CheckFormat : public Check {
@@ -849,6 +926,14 @@ public:
}
return true;
}
+
+ void checkDefault(Value& value, Object &_object) const
+ {
+ for (int i = 0; i < m_extendedSchema.count(); ++i) {
+ m_extendedSchema[i].checkDefault(value, _object);
+ }
+ }
+
private:
QVarLengthArray<Schema<T>, 4> m_extendedSchema;
};
@@ -883,6 +968,13 @@ public:
// qDebug() << Q_FUNC_INFO << result;
return result;
}
+
+ void checkDefault(Value& value, Object &_object) const
+ {
+ m_newSchema.checkDefault(value, _object);
+
+ }
+
private:
Schema<T> m_newSchema;
};
@@ -982,6 +1074,10 @@ typename SchemaPrivate<T>::Check *SchemaPrivate<T>::createCheckPoint(const Key &
if (QString::fromLatin1("format") == keyName)
return new CheckFormat(this, data, value);
break;
+ case QStaticStringHash<'d','e','f','a','u','l','t'>::Hash:
+ if (QString::fromLatin1("default") == keyName)
+ return new CheckDefault(this, data, value);
+ break;
case QStaticStringHash<'d','i','v','i','s','i','b','l','e','b','y'>::Hash:
if (QString::fromLatin1("divisibleby") == keyName)
return new CheckDivisibleBy(this, data, value);
@@ -1042,6 +1138,14 @@ bool SchemaPrivate<T>::check(const Value &value) const
return true;
}
+template<class T>
+void SchemaPrivate<T>::checkDefault(Value &value, Object &object) const
+{
+ foreach (Check *check, m_checks) {
+ check->checkDefault(value, object);
+ }
+}
+
} // namespace SchemaValidation
QT_END_HEADER
diff --git a/src/qtjsonschema/jsonobjecttypes_impl_p.h b/src/qtjsonschema/jsonobjecttypes_impl_p.h
index 23e4398..dfa8918 100644
--- a/src/qtjsonschema/jsonobjecttypes_impl_p.h
+++ b/src/qtjsonschema/jsonobjecttypes_impl_p.h
@@ -290,6 +290,21 @@ inline bool JsonObjectTypes::Value::compare(const Value & val) const
return v0 == v1;
}
+inline QJsonValue JsonObjectTypes::Value::value() const
+{
+ switch (m_type) {
+ case Map:
+ return map().value(m_property);
+ case List:
+ return list().at(m_index);
+ case RootMap:
+ return m_value;
+ default:
+ Q_ASSERT(false);
+ }
+ return QJsonValue();
+}
+
inline const QJsonObject JsonObjectTypes::Value::map() const
{
Q_ASSERT(m_type == Map);
diff --git a/src/qtjsonschema/jsonobjecttypes_p.h b/src/qtjsonschema/jsonobjecttypes_p.h
index ab5faa0..0fb665f 100644
--- a/src/qtjsonschema/jsonobjecttypes_p.h
+++ b/src/qtjsonschema/jsonobjecttypes_p.h
@@ -128,6 +128,7 @@ public:
inline Object toObject(bool *ok) const;
inline bool compare(const Value &) const;
+ inline QJsonValue value() const;
private:
inline const QJsonObject map() const;
diff --git a/src/qtjsonschema/schemaobject_p.h b/src/qtjsonschema/schemaobject_p.h
index bedc638..68c5d94 100644
--- a/src/qtjsonschema/schemaobject_p.h
+++ b/src/qtjsonschema/schemaobject_p.h
@@ -109,6 +109,10 @@ class Schema {
public:
inline bool check(const Value &value, Service *callbackToUseForCheck) const;
+ void checkDefault(Value &value, Object &object) const
+ {
+ d_ptr->checkDefault(value, object);
+ }
Schema()
: d_ptr(new SchemaPrivate<T>())
@@ -151,6 +155,7 @@ class SchemaPrivate : public QSharedData
};
Q_DECLARE_FLAGS(Flags, Flag)
Flags m_flags;
+ QSharedPointer<Value> m_default; // keeps a default value
};
class Check {
@@ -177,6 +182,10 @@ class SchemaPrivate : public QSharedData
return result;
}
+ Value* getDefault() const { return m_data && m_data->m_default ? m_data->m_default.data() : 0; }
+
+ virtual void checkDefault(Value& value, Object &object) const {} // do nothing in generic case
+
protected:
SchemaPrivate *m_schema;
QSharedPointer<CheckSharedData> m_data; // is used to exchange information between attributes
@@ -217,6 +226,8 @@ class SchemaPrivate : public QSharedData
class CheckMaxLength;
// 5.19
class CheckEnum;
+ // 5.20
+ class CheckDefault;
// 5.21
class CheckTitle;
// 5.23
@@ -267,6 +278,8 @@ public:
return m_checks.size();
}
+ void checkDefault(Value &value, Object &object) const;
+
private:
QVarLengthArray<Check *, 4> m_checks;
qint32 m_maxRequired;
diff --git a/src/qtjsonschema/schemavalidator.h b/src/qtjsonschema/schemavalidator.h
index 0941d60..71b66c8 100644
--- a/src/qtjsonschema/schemavalidator.h
+++ b/src/qtjsonschema/schemavalidator.h
@@ -109,7 +109,7 @@ public:
public:
virtual ~SchemaNameMatcher() {}
- // knowing exact schema name aloows skip schema iteration and validate with a single schema only
+ // knowing exact schema name allows to skip schema iteration and validate with a single schema only
virtual QString getSchemaName(const QJsonObject &) { return QString::null; }
// limit schemas iteration by matching json object with some schemas
diff --git a/tests/auto/jsonschema/tst_jsonschema.cpp b/tests/auto/jsonschema/tst_jsonschema.cpp
index 487d2e8..fc493f8 100644
--- a/tests/auto/jsonschema/tst_jsonschema.cpp
+++ b/tests/auto/jsonschema/tst_jsonschema.cpp
@@ -77,6 +77,7 @@ private slots:
// 5.19
void testEnumValidation();
// TODO: 5.20 default
+ void testDefaultValidation();
// 5.21
void testTitleValidation();
// 5.22
@@ -334,6 +335,15 @@ void tst_JsonSchema::testEnumValidation()
//FIX QVERIFY(!validate({}, "{ \"properties\" : { \"a\" : { \"enum\" : [\"a\"], \"optional\" : false, \"required\" : true } } }"));
}
+
+// 5.20
+void tst_JsonSchema::testDefaultValidation()
+{
+// QVERIFY(validate("{ \"b\" : true }", "{ \"type\":\"object\", \"properties\" : { \"a\" : { \"type\":\"string\", \"default\": \"hoi\"} } }"));
+ QVERIFY(validate("{ \"b\" : true }", "{ \"type\":\"object\", \"properties\" : { \"a\" : { \"type\":\"string\", \"default\": \"hoi\"}, \"c\" : { \"type\":\"array\", \"default\":[\"a\",\"b\",\"c\"]} } }"));
+}
+
+
// 5.21
void tst_JsonSchema::testTitleValidation()
{
diff --git a/tests/auto/jsonstream/schemas/PaintEvent.json b/tests/auto/jsonstream/schemas/PaintEvent.json
index 60e263a..8b65415 100644
--- a/tests/auto/jsonstream/schemas/PaintEvent.json
+++ b/tests/auto/jsonstream/schemas/PaintEvent.json
@@ -5,6 +5,7 @@
"properties": {
"event": {"type":"string", "pattern":"Paint\\w*Event", "required":true },
"x": {"type":"number", "minimum": 0, "maximum": 1024, "required":true },
- "y": {"type":"number", "minimum": 0, "maximum": 768, "required":true }
+ "y": {"type":"number", "minimum": 0, "maximum": 768, "required":true },
+ "owner" : {"type":"string", "default": "painter" }
}
}
diff --git a/tests/auto/jsonstream/schemas/PaintTextEvent.json b/tests/auto/jsonstream/schemas/PaintTextEvent.json
index 6c90882..b8da0c7 100644
--- a/tests/auto/jsonstream/schemas/PaintTextEvent.json
+++ b/tests/auto/jsonstream/schemas/PaintTextEvent.json
@@ -1,5 +1,5 @@
{
- "title": "PaintLineEvent schema",
+ "title": "PaintTextEvent schema",
"extends": { "$ref": "PaintEvent" },
"description": "Inform the application to paint a text",
"type": "object",
@@ -7,6 +7,15 @@
"event": {"type":"string", "pattern":"PaintTextEvent", "required":true },
"text": {"type":"string", "required":true },
"font-size": {"type":"number", "minimum": 0 },
- "bold": {"type":"boolean"}
+ "bold": {"type":"boolean"},
+ "font-name": {"type":"string", "default": "times"},
+ "settings": {
+ "type": "object",
+ "properties": {
+ "border-color": { "type": "string", "default": "red" },
+ "border-width": { "type": "number", "default": 5 },
+ "border": {"type":"boolean", "default": true}
+ }
+ }
}
}