From 581e5c36f6b93e0fdfb57cf7c67f11f8eea28267 Mon Sep 17 00:00:00 2001 From: Alexei Rousskikh Date: Wed, 22 Feb 2012 19:26:55 -0500 Subject: implemented schema syntax error handling; removed obsolete files Change-Id: I1389abae9da4438071d8e7271d7212b91ddc75c3 Reviewed-by: Andrew Christian --- src/qtjsonschema/checkpoints_p.h | 64 +++++++++-- src/qtjsonschema/jsonobjecttypes_impl_p.h | 16 ++- src/qtjsonschema/jsonobjecttypes_p.h | 4 +- src/qtjsonschema/schemaerror.h | 6 +- src/qtjsonschema/schemamanager_impl_p.h | 17 ++- src/qtjsonschema/schemaobject_p.h | 23 +++- src/qtjsonschema/varobjecttypes_impl_p.h | 176 ------------------------------ src/qtjsonschema/varobjecttypes_p.h | 115 ------------------- src/src.pro | 4 +- tests/auto/jsonschema/tst_jsonschema.cpp | 4 +- 10 files changed, 110 insertions(+), 319 deletions(-) delete mode 100644 src/qtjsonschema/varobjecttypes_impl_p.h delete mode 100644 src/qtjsonschema/varobjecttypes_p.h diff --git a/src/qtjsonschema/checkpoints_p.h b/src/qtjsonschema/checkpoints_p.h index 4d0e7ed..493a74f 100644 --- a/src/qtjsonschema/checkpoints_p.h +++ b/src/qtjsonschema/checkpoints_p.h @@ -54,6 +54,9 @@ QT_BEGIN_HEADER +#include "schemaerror.h" +QT_USE_NAMESPACE_JSONSTREAM + namespace SchemaValidation { /** @@ -525,7 +528,10 @@ public: { bool ok; m_min = minimum.toDouble(&ok); - Q_ASSERT(ok); + + if (!ok) { + Check::m_schema->setLoadError("wrong 'minimum' value", minimum, SchemaError::SchemaWrongParamType); + } } virtual bool doCheck(const Value &value) @@ -548,7 +554,10 @@ public: // qDebug() << Q_FUNC_INFO << this; bool ok; m_max = maximum.toDouble(&ok); - Q_ASSERT(ok); + + if (!ok) { + Check::m_schema->setLoadError("wrong 'maximum' value", maximum, SchemaError::SchemaWrongParamType); + } } virtual bool doCheck(const Value &value) @@ -580,12 +589,15 @@ public: else if (value == QString::fromLatin1("true")) bExclusive = true; else - Q_ASSERT(false); + ok = false; if (!value.isEmpty()) qWarning() << QString::fromLatin1("Wrong 'exclusiveMinimum' syntax found, instead of boolean type a string was used"); } - Q_ASSERT(ok); + + if (!ok) { + Check::m_schema->setLoadError("wrong 'exclusiveMinimum' value", _value, SchemaError::SchemaWrongParamType); + } if (bExclusive) { Check::m_data->m_flags |= CheckSharedData::ExclusiveMinimum; @@ -617,12 +629,15 @@ public: else if (value == QString::fromLatin1("true")) bExclusive = true; else - Q_ASSERT(false); + ok = false; if (!value.isEmpty()) qWarning() << QString::fromLatin1("Wrong 'exclusiveMaximum' syntax found, instead of boolean type a string was used"); } - Q_ASSERT(ok); + + if (!ok) { + Check::m_schema->setLoadError("wrong 'exclusiveMaximum' value", _value, SchemaError::SchemaWrongParamType); + } if (bExclusive) { Check::m_data->m_flags |= CheckSharedData::ExclusiveMaximum; @@ -646,7 +661,9 @@ public: { bool ok; m_min = minimum.toInt(&ok); - Q_ASSERT(ok); + if (!ok) { + Check::m_schema->setLoadError("wrong 'minItems' value", minimum, SchemaError::SchemaWrongParamType); + } } virtual bool doCheck(const Value &value) @@ -668,7 +685,9 @@ public: { bool ok; m_max = maximum.toInt(&ok); - Q_ASSERT(ok); + if (!ok) { + Check::m_schema->setLoadError("wrong 'maxItems' value", maximum, SchemaError::SchemaWrongParamType); + } } virtual bool doCheck(const Value &value) @@ -692,7 +711,10 @@ public: bool ok; QString patternString = patternValue.toString(&ok); m_regexp.setPattern(patternString); - Q_ASSERT(ok && m_regexp.isValid()); + if (!ok || !m_regexp.isValid()) { + Check::m_schema->setLoadError("wrong 'pattern' value", patternValue, + !ok ? SchemaError::SchemaWrongParamType : SchemaError::SchemaWrongParamValue); + } } virtual bool doCheck(const Value &value) @@ -928,7 +950,10 @@ public: // qDebug() << Q_FUNC_INFO << this; bool ok; m_div = value.toDouble(&ok); - Q_ASSERT(ok && m_div != 0); + + if (!ok || m_div == 0) + Check::m_schema->setLoadError("wrong 'divisibleBy' value", value, + !ok ? SchemaError::SchemaWrongParamType : SchemaError::SchemaWrongParamValue); } virtual bool doCheck(const Value &value) @@ -1017,7 +1042,7 @@ public: const QString msg = QString::fromLatin1("Schema extends %1 but it is unknown.") .arg(schemaName); qWarning() << msg; - schema->m_callbacks->setError(msg); + schema->m_callbacks->setValidationError(msg); } } virtual bool doCheck(const Value &value) @@ -1194,7 +1219,7 @@ bool SchemaPrivate::check(const Value &value) const } } if (m_requiredCount != m_maxRequired) { - m_callbacks->setError(QString::fromLatin1("Schema validation error: Required field is missing")); + m_callbacks->setValidationError(QString::fromLatin1("Schema validation error: Required field is missing")); return false; } return true; @@ -1208,6 +1233,21 @@ void SchemaPrivate::checkDefault(Value &value, Object &object) const } } +template +void SchemaPrivate::setLoadError(const char *message, const Value & value, int code) +{ + if (!m_bLoadError) { + m_callbacks->setLoadError(QString::fromLatin1("Schema errors found. Schema can not be loaded properly.")); + m_bLoadError = true; + } + + QString str; + QDebug(&str) << value.value(); // put parameter value into the message + str = QString("Schema Error: %1 ( %2 )").arg(message).arg(str); + m_callbacks->setSubError(str, code); +} + + } // namespace SchemaValidation QT_END_HEADER diff --git a/src/qtjsonschema/jsonobjecttypes_impl_p.h b/src/qtjsonschema/jsonobjecttypes_impl_p.h index 2b2d386..7c743dd 100644 --- a/src/qtjsonschema/jsonobjecttypes_impl_p.h +++ b/src/qtjsonschema/jsonobjecttypes_impl_p.h @@ -362,12 +362,26 @@ inline QJsonObject JsonObjectTypes::Service::error() const return m_errorMap; } -inline void JsonObjectTypes::Service::setError(const QString &message) +inline void JsonObjectTypes::Service::setValidationError(const QString &message) { m_errorMap.insert(SchemaError::kCodeStr, SchemaError::FailedSchemaValidation); m_errorMap.insert(SchemaError::kMessageStr, message); } +inline void JsonObjectTypes::Service::setLoadError(const QString &message) +{ + m_errorMap.insert(SchemaError::kCodeStr, SchemaError::InvalidSchemaLoading); + m_errorMap.insert(SchemaError::kMessageStr, message); +} + +inline void JsonObjectTypes::Service::setSubError(const QString &message, int errorCode) +{ + QJsonObject error; + error.insert(SchemaError::kCodeStr, errorCode); + error.insert(SchemaError::kMessageStr, message); + m_errorMap.insert(QString("%1").arg(m_errorMap.count()), error); +} + inline SchemaValidation::Schema JsonObjectTypes::Service::loadSchema(const QString &schemaName) { return reinterpret_cast< SchemaManager *>(m_schemas)->schema(schemaName, this); diff --git a/src/qtjsonschema/jsonobjecttypes_p.h b/src/qtjsonschema/jsonobjecttypes_p.h index 0fb665f..2bef1a5 100644 --- a/src/qtjsonschema/jsonobjecttypes_p.h +++ b/src/qtjsonschema/jsonobjecttypes_p.h @@ -164,7 +164,9 @@ public: inline QJsonObject error() const; // interface - inline void setError(const QString &message); + inline void setValidationError(const QString &message); + inline void setLoadError(const QString &message); + inline void setSubError(const QString &message, int errorCode); inline SchemaValidation::Schema loadSchema(const QString &schemaName); private: diff --git a/src/qtjsonschema/schemaerror.h b/src/qtjsonschema/schemaerror.h index 71f1304..ada86e1 100644 --- a/src/qtjsonschema/schemaerror.h +++ b/src/qtjsonschema/schemaerror.h @@ -59,7 +59,11 @@ public: InvalidObject, // Unable to parse an incoming object FailedSchemaFileOpenRead, // Schema file could not be opened or read from InvalidSchemaFolder, // Schema folder does not exist - InvalidSchemaLoading // Schema loading errors + InvalidSchemaLoading, // Schema loading errors + + // Schema Errors + SchemaWrongParamType = 100, + SchemaWrongParamValue }; SchemaError() {} diff --git a/src/qtjsonschema/schemamanager_impl_p.h b/src/qtjsonschema/schemamanager_impl_p.h index dc7b43e..1b448f3 100644 --- a/src/qtjsonschema/schemamanager_impl_p.h +++ b/src/qtjsonschema/schemamanager_impl_p.h @@ -84,7 +84,12 @@ template inline T SchemaManager::ensureCompiled(const QString &schemaName, MapSchemaPair *pair, TypesService *callbacks) { SchemaValidation::Schema schema(pair->second); - if (!schema.isValid()) { + if (schema.hasErrors()) + { + callbacks->setLoadError("Schema errors found. Schema can not be loaded properly."); + return callbacks->error(); + } + else if (!schema.isValid()) { // Try to compile schema typename TT::Object schemaObject(pair->first); SchemaValidation::Schema compiledSchema(schemaObject, callbacks); @@ -103,10 +108,12 @@ inline T SchemaManager::validate(const QString &schemaName, T object) TypesService callbacks(this); MapSchemaPair schemaPair = m_schemas.value(schemaName); - ensureCompiled(schemaName, &schemaPair, &callbacks); - SchemaValidation::Schema schema(schemaPair.second); - typename TT::Value rootObject(QString(), object); - /*bool result = */ schema.check(rootObject, &callbacks); + if (ensureCompiled(schemaName, &schemaPair, &callbacks).isEmpty()) { + // schema compiled successfully can validate an object + SchemaValidation::Schema schema(schemaPair.second); + typename TT::Value rootObject(QString(), object); + schema.check(rootObject, &callbacks); + } return callbacks.error(); } diff --git a/src/qtjsonschema/schemaobject_p.h b/src/qtjsonschema/schemaobject_p.h index c34c6b9..55a5638 100644 --- a/src/qtjsonschema/schemaobject_p.h +++ b/src/qtjsonschema/schemaobject_p.h @@ -93,7 +93,9 @@ namespace SchemaValidation { // ValueList::constEnd() // ValueList::const_iterator() // -// void Service::setError(const QString &message) +// void Service::setValidationError(const SchemaError &error) +// void Service::setLoadError(const QString &message) +// void Service::setSubError(const QString &message, int errorCode) // Schema Service::loadSchema(const QString &name) template @@ -128,6 +130,12 @@ public: { return d_ptr->isValid(); } + + bool hasErrors() const + { + return d_ptr->hasErrors(); + } + private: friend class SchemaPrivate; @@ -178,7 +186,7 @@ class SchemaPrivate : public QSharedData bool ok; // TODO it is tricky, as we do not have access to source code of this schema. // maybe we can set "additional, hidden " source property in each schema property, or some nice hash? - m_schema->m_callbacks->setError(QLatin1String("Schema validation error: ") + + m_schema->m_callbacks->setValidationError(QLatin1String("Schema validation error: ") + QString::fromLatin1(m_errorMessage).arg(value.toString(&ok))); } return result; @@ -252,6 +260,7 @@ public: : m_maxRequired(0) , m_requiredCount(0) , m_callbacks(0) + , m_bLoadError(false) {} ~SchemaPrivate() { @@ -279,16 +288,24 @@ public: bool isValid() const { // we have some checks so it means that something got compiled. - return m_checks.size(); + return m_checks.size() && !m_bLoadError; + } + + bool hasErrors() const + { + return m_bLoadError; } void checkDefault(Value &value, Object &object) const; + void setLoadError(const char *, const Value &, int); + private: QVarLengthArray m_checks; qint32 m_maxRequired; mutable qint32 m_requiredCount; mutable Service *m_callbacks; + bool m_bLoadError; }; } diff --git a/src/qtjsonschema/varobjecttypes_impl_p.h b/src/qtjsonschema/varobjecttypes_impl_p.h deleted file mode 100644 index 28e440f..0000000 --- a/src/qtjsonschema/varobjecttypes_impl_p.h +++ /dev/null @@ -1,176 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef VAROBJECTTYPES_IMPL_P_H -#define VAROBJECTTYPES_IMPL_P_H - -#include "varobjecttypes_p.h" -#include "schemamanager_p.h" - -#include "jsonschema-global.h" - -QT_BEGIN_NAMESPACE_JSONSTREAM - -inline VarObjectTypes::Value::Value(const QVariant &var) - : QVariant(var) -{} - -inline VarObjectTypes::Value::Value(Key, const QVariantMap &map) - : QVariant(map) -{} - -inline VarObjectTypes::Value::Value(const int, const QVariantList &list) - : QVariant(list) -{} - -inline int VarObjectTypes::Value::toInt(bool *ok) const -{ - if (type() == QVariant::Int || type() == QVariant::UInt) - { - *ok = true; - return value(); - } - - *ok = false; - return -1; -} - -inline double VarObjectTypes::Value::toDouble(bool *ok) const -{ - if (type() == QVariant::Double) - { - *ok = true; - return value(); - } - - *ok = false; - return -1; -} - -inline VarObjectTypes::ValueList VarObjectTypes::Value::toList(bool *ok) const -{ - if (type() == QVariant::List) - { - *ok = true; - return value(); - } - - *ok = false; - return ValueList(); -} - -inline QString VarObjectTypes::Value::toString(bool *ok) const -{ - if (type() == QVariant::String) - { - *ok = true; - return value(); - } - - *ok = false; - return QString(); -} - -inline bool VarObjectTypes::Value::toBoolean(bool *ok) const -{ - if (type() == QVariant::Bool) - { - *ok = true; - return value(); - } - - *ok = false; - return false; -} - -inline void VarObjectTypes::Value::toNull(bool *ok) const -{ - *ok = (type() == QVariant::Invalid); -} - -inline VarObjectTypes::Object VarObjectTypes::Value::toObject(bool *ok) const -{ - if (type() == QVariant::Map) - { - *ok = true; - return value(); - } - - *ok = false; - return QVariantMap(); -} - -inline VarObjectTypes::Object::Object() -{} - -inline VarObjectTypes::Object::Object(const QVariantMap &map) - : QVariantMap(map) -{} - -inline VarObjectTypes::Value VarObjectTypes::Object::property(const VarObjectTypes::Key& name) const -{ - qDebug() << "Object::property " << name << "[" << value(name) << "]"; - return value(name); -} - -inline QList VarObjectTypes::Object::propertyNames() const { return keys(); } - -inline VarObjectTypes::Service::Service(SchemaManagerBase *schemas) - : m_schemas(schemas) -{} - -inline QVariantMap VarObjectTypes::Service::error() const -{ - return m_errorMap; -} - -inline void VarObjectTypes::Service::setError(const QString &message) -{ - m_errorMap.insert("code", FailedSchemaValidation); - m_errorMap.insert("message", message); -} - -inline SchemaValidation::Schema VarObjectTypes::Service::loadSchema(const QString &schemaName) -{ - return reinterpret_cast< SchemaManager *>(m_schemas)->schema(schemaName, this); -} - -QT_END_NAMESPACE_JSONSTREAM - -#endif // VAROBJECTTYPES_IMPL_P_H diff --git a/src/qtjsonschema/varobjecttypes_p.h b/src/qtjsonschema/varobjecttypes_p.h deleted file mode 100644 index b774697..0000000 --- a/src/qtjsonschema/varobjecttypes_p.h +++ /dev/null @@ -1,115 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef VAROBJECTTYPES_P_H -#define VAROBJECTTYPES_P_H - -#include "schemaobject_p.h" - -#include - -#include "jsonschema-global.h" - -QT_BEGIN_NAMESPACE_JSONSTREAM - -class SchemaManagerBase; - -/** - \internal - This is type definition for schema validation framework. It was created because of planed change - of data representation in jsondb (Bson -> Qson). Essentially schema validation is independent from - data representation. The performance cost of this indirection is about 0. We can consider removing - it in future or leave it and check different data representation (think about QJSValue). - - These types define the simplest types in JSON. - */ -class VarObjectTypes { -public: - typedef QString Key; - typedef QVariantList ValueList; - - class Object; - class Value : QVariant - { - public: - inline Value(const QVariant &var); - inline Value(Key propertyName, const QVariantMap &map); - inline Value(const int index, const QVariantList &list); - - // interface - inline int toInt(bool *ok) const; - inline double toDouble(bool *ok) const; - inline ValueList toList(bool *ok) const; - inline QString toString(bool *ok) const; - inline bool toBoolean(bool *ok) const; - inline void toNull(bool *ok) const; - inline Object toObject(bool *ok) const; - - private: - }; - - class Object : public QVariantMap - { - public: - inline Object(const QVariantMap &map); - - // interface - inline Object(); - inline Value property(const Key& name) const; - inline QList propertyNames() const; - }; - - class Service { - public: - inline Service(SchemaManagerBase *schemas); - inline QVariantMap error() const; - - // interface - inline void setError(const QString &message); - inline SchemaValidation::Schema loadSchema(const QString &schemaName); - - private: - SchemaManagerBase *m_schemas; - QVariantMap m_errorMap; - }; -}; - -QT_END_NAMESPACE_JSONSTREAM - -#endif // VAROBJECTTYPES_P_H diff --git a/src/src.pro b/src/src.pro index 82e285d..84b1af2 100644 --- a/src/src.pro +++ b/src/src.pro @@ -37,9 +37,7 @@ SCHEMA_HEADERS = \ $$PWD/qtjsonschema/schemamanager_impl_p.h \ $$PWD/qtjsonschema/schemamanager_p.h \ $$PWD/qtjsonschema/jsonobjecttypes_p.h \ - $$PWD/qtjsonschema/jsonobjecttypes_impl_p.h \ - $$PWD/qtjsonschema/varobjecttypes_p.h \ - $$PWD/qtjsonschema/varobjecttypes_impl_p.h + $$PWD/qtjsonschema/jsonobjecttypes_impl_p.h SCHEMA_SOURCES = \ $$PWD/qtjsonschema/schemaerror.cpp \ diff --git a/tests/auto/jsonschema/tst_jsonschema.cpp b/tests/auto/jsonschema/tst_jsonschema.cpp index e9f2f1e..c11e001 100644 --- a/tests/auto/jsonschema/tst_jsonschema.cpp +++ b/tests/auto/jsonschema/tst_jsonschema.cpp @@ -355,7 +355,7 @@ void tst_JsonSchema::testPatternValidation() QVERIFY(!validate(QJsonValue(QString("")), "{ \"pattern\" : \"^ $\" }")); QVERIFY(!validate(QJsonValue(QString("today")), "{ \"pattern\" : \"dam\" }")); -//fix QVERIFY(!validate(QJsonValue(QString("aaaaa")), "{ \"pattern\" : \"aa(a\" }")); + QVERIFY(!validate(QJsonValue(QString("aaaaa")), "{ \"pattern\" : \"aa(a\" }")); } // 5.17, 5.18 @@ -441,7 +441,7 @@ void tst_JsonSchema::testDivisibleByValidation() QVERIFY(validate(QJsonValue(5), "{ \"divisibleBy\" : 2.5 }")); QVERIFY(validate(QJsonValue(7.5), "{ \"divisibleBy\" : 2.5 }")); -//fix QVERIFY(!validate(QJsonValue(0), "{ \"divisibleBy\" : 0 }")); + QVERIFY(!validate(QJsonValue(0), "{ \"divisibleBy\" : 0 }")); QVERIFY(!validate(QJsonValue(7), "{ \"divisibleBy\" : 5 }")); QVERIFY(!validate(QJsonValue(4.5), "{ \"divisibleBy\" : 2 }")); QVERIFY(!validate(QJsonValue(7.5), "{ \"divisibleBy\" : 1.8 }")); -- cgit v1.2.3