summaryrefslogtreecommitdiff
path: root/src/xmlpatterns/schema/qxsdtypechecker.cpp
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commite1b2c9deb5943faae2b29be6a5c006f75bb73f06 (patch)
treefc79e45367c0a8fc71185e9afc33f7503a58653c /src/xmlpatterns/schema/qxsdtypechecker.cpp
downloadqtxmlpatterns-e1b2c9deb5943faae2b29be6a5c006f75bb73f06.tar.gz
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'src/xmlpatterns/schema/qxsdtypechecker.cpp')
-rw-r--r--src/xmlpatterns/schema/qxsdtypechecker.cpp1339
1 files changed, 1339 insertions, 0 deletions
diff --git a/src/xmlpatterns/schema/qxsdtypechecker.cpp b/src/xmlpatterns/schema/qxsdtypechecker.cpp
new file mode 100644
index 0000000..217932e
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdtypechecker.cpp
@@ -0,0 +1,1339 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdtypechecker_p.h"
+
+#include "qabstractdatetime_p.h"
+#include "qbase64binary_p.h"
+#include "qboolean_p.h"
+#include "qdecimal_p.h"
+#include "qderivedinteger_p.h"
+#include "qduration_p.h"
+#include "qgenericstaticcontext_p.h"
+#include "qhexbinary_p.h"
+#include "qnamespaceresolver_p.h"
+#include "qpatternplatform_p.h"
+#include "qqnamevalue_p.h"
+#include "qvaluefactory_p.h"
+#include "qxmlnamepool.h"
+#include "qxsdschemahelper_p.h"
+#include "qxsdschemamerger_p.h"
+#include "qxsdstatemachine_p.h"
+
+#include "qxsdschemadebugger_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+XsdSchemaSourceLocationReflection::XsdSchemaSourceLocationReflection(const QSourceLocation &location)
+ : m_sourceLocation(location)
+{
+}
+
+const SourceLocationReflection* XsdSchemaSourceLocationReflection::actualReflection() const
+{
+ return this;
+}
+
+QSourceLocation XsdSchemaSourceLocationReflection::sourceLocation() const
+{
+ return m_sourceLocation;
+}
+
+
+static AnySimpleType::Ptr comparableType(const AnySimpleType::Ptr &type)
+{
+ if (!type->isDefinedBySchema()) {
+ return type;
+ } else {
+ const XsdSimpleType::Ptr simpleType(type);
+ if (type->category() == SchemaType::SimpleTypeAtomic) {
+ return simpleType->primitiveType();
+ } else if (type->category() == SchemaType::SimpleTypeList) {
+ return simpleType->itemType();
+ } else if (type->category() == SchemaType::SimpleTypeUnion) {
+ return simpleType->memberTypes().first();
+ }
+ }
+
+ Q_ASSERT(false);
+ return AnySimpleType::Ptr();
+}
+
+static int totalDigitsForSignedLongLong(long long value)
+{
+ QString number = QString::number(value);
+ if (number.startsWith(QLatin1Char('-')))
+ number = number.mid(1);
+
+ return number.length();
+}
+
+static int totalDigitsForUnsignedLongLong(unsigned long long value)
+{
+ const QString number = QString::number(value);
+ return number.length();
+}
+
+static int totalDigitsForDecimal(const QString &lexicalValue)
+{
+ const QLatin1Char zeroChar('0');
+ const int length = lexicalValue.length() - 1;
+
+ // strip leading zeros
+ int pos = 0;
+ while (lexicalValue.at(pos) == zeroChar && (pos != length))
+ pos++;
+
+ QString value = lexicalValue.mid(pos);
+
+ // if contains '.' strip trailing zeros
+ if (value.contains(QLatin1Char('.'))) {
+ pos = value.length() - 1;
+ while (value.at(pos) == zeroChar) {
+ pos--;
+ }
+
+ value = value.left(pos + 1);
+ }
+
+ // check number of digits of remaining string
+ int totalDigits = 0;
+ for (int i = 0; i < value.count(); ++i)
+ if (value.at(i).isDigit())
+ ++totalDigits;
+
+ if (totalDigits == 0)
+ totalDigits = 1;
+
+ return totalDigits;
+}
+
+static int fractionDigitsForDecimal(const QString &lexicalValue)
+{
+ // we use the lexical value here, as the conversion to double might strip
+ // away decimal positions
+
+ QString trimmedValue(lexicalValue.trimmed());
+ const int pos = trimmedValue.indexOf(QLatin1Char('.'));
+ if (pos == -1) // no '.' -> 0 fraction digits
+ return 0;
+ else
+ return (trimmedValue.length() - pos - 1);
+}
+
+XsdTypeChecker::XsdTypeChecker(const XsdSchemaContext::Ptr &context, const QVector<QXmlName> &namespaceBindings, const QSourceLocation &location)
+ : m_context(context)
+ , m_namePool(m_context->namePool())
+ , m_namespaceBindings(namespaceBindings)
+ , m_reflection(new XsdSchemaSourceLocationReflection(location))
+{
+}
+
+XsdTypeChecker::~XsdTypeChecker()
+{
+ delete m_reflection;
+}
+
+QString XsdTypeChecker::normalizedValue(const QString &value, const XsdFacet::Hash &facets)
+{
+ if (!facets.contains(XsdFacet::WhiteSpace))
+ return value;
+
+ const XsdFacet::Ptr whiteSpaceFacet = facets.value(XsdFacet::WhiteSpace);
+
+ const DerivedString<TypeString>::Ptr facetValue = whiteSpaceFacet->value();
+ const QString stringValue = facetValue->stringValue();
+ if (stringValue == XsdSchemaToken::toString(XsdSchemaToken::Preserve))
+ return value;
+ else if (stringValue == XsdSchemaToken::toString(XsdSchemaToken::Replace)) {
+ QString newValue(value);
+ newValue.replace(QLatin1Char('\t'), QLatin1Char(' '));
+ newValue.replace(QLatin1Char('\n'), QLatin1Char(' '));
+ newValue.replace(QLatin1Char('\r'), QLatin1Char(' '));
+
+ return newValue;
+ } else if (stringValue == XsdSchemaToken::toString(XsdSchemaToken::Collapse)) {
+ return value.simplified();
+ }
+
+ return value;
+}
+
+XsdFacet::Hash XsdTypeChecker::mergedFacetsForType(const SchemaType::Ptr &type, const XsdSchemaContext::Ptr &context)
+{
+ if (!type)
+ return XsdFacet::Hash();
+
+ const XsdFacet::Hash baseFacets = mergedFacetsForType(type->wxsSuperType(), context);
+ const XsdFacet::Hash facets = context->facetsForType(type);
+
+ XsdFacet::Hash result = baseFacets;
+ XsdFacet::HashIterator it(facets);
+ while (it.hasNext()) {
+ it.next();
+
+ result.insert(it.key(), it.value());
+ }
+
+ return result;
+}
+
+bool XsdTypeChecker::isValidString(const QString &normalizedString, const AnySimpleType::Ptr &type, QString &errorMsg, AnySimpleType::Ptr *boundType) const
+{
+ if (type->name(m_namePool) == BuiltinTypes::xsAnySimpleType->name(m_namePool)) {
+ if (boundType)
+ *boundType = type;
+
+ return true;
+ }
+
+ if (!type->isDefinedBySchema()) {
+ // special QName check
+ if (BuiltinTypes::xsQName->wxsTypeMatches(type)) {
+ if (!XPathHelper::isQName(normalizedString)) {
+ errorMsg = QtXmlPatterns::tr("%1 is not valid according to %2.").arg(formatData(normalizedString)).arg(formatType(m_namePool, type));
+ return false;
+ }
+ }
+
+ const AtomicValue::Ptr value = fromLexical(normalizedString, type, m_context, m_reflection);
+ if (value->hasError()) {
+ errorMsg = QtXmlPatterns::tr("%1 is not valid according to %2.").arg(formatData(normalizedString)).arg(formatType(m_namePool, type));
+ return false;
+ }
+
+ if (!checkConstrainingFacets(value, normalizedString, type, errorMsg)) {
+ return false;
+ }
+
+ if (boundType)
+ *boundType = type;
+
+ } else {
+ const XsdSimpleType::Ptr simpleType(type);
+
+ if (simpleType->category() == XsdSimpleType::SimpleTypeAtomic) {
+ AnySimpleType::Ptr targetType = simpleType->primitiveType();
+ if (!simpleType->wxsSuperType()->isDefinedBySchema())
+ targetType = simpleType->wxsSuperType();
+
+ const AtomicValue::Ptr value = fromLexical(normalizedString, targetType, m_context, m_reflection);
+ if (value->hasError()) {
+ errorMsg = QtXmlPatterns::tr("%1 is not valid according to %2.").arg(formatData(normalizedString)).arg(formatType(m_namePool, targetType));
+ return false;
+ }
+
+ if (!checkConstrainingFacets(value, normalizedString, type, errorMsg)) {
+ return false;
+ }
+
+ if (boundType)
+ *boundType = type;
+
+ } else if (simpleType->category() == XsdSimpleType::SimpleTypeList) {
+ QStringList entries = normalizedString.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ for (int i = 0; i < entries.count(); ++i) {
+ entries[i] = normalizedValue(entries.at(i), mergedFacetsForType(simpleType->itemType(), m_context));
+ }
+
+ if (!checkConstrainingFacetsList(entries, normalizedString, simpleType->itemType(), mergedFacetsForType(simpleType, m_context), errorMsg)) {
+ return false;
+ }
+
+ for (int i = 0; i < entries.count(); ++i) {
+ if (!isValidString(entries.at(i), simpleType->itemType(), errorMsg)) {
+ return false;
+ }
+ }
+
+ if (boundType)
+ *boundType = simpleType->itemType();
+
+ } else if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) {
+ if (!checkConstrainingFacetsUnion(normalizedString, normalizedString, simpleType, mergedFacetsForType(simpleType, m_context), errorMsg)) {
+ return false;
+ }
+
+ const AnySimpleType::List memberTypes = simpleType->memberTypes();
+
+ bool foundValidType = false;
+ for (int i = 0; i < memberTypes.count(); ++i) {
+ const XsdFacet::Hash mergedFacets = mergedFacetsForType(memberTypes.at(i), m_context);
+ if (isValidString(normalizedValue(normalizedString, mergedFacets), memberTypes.at(i), errorMsg)) {
+ foundValidType = true;
+
+ if (boundType)
+ *boundType = memberTypes.at(i);
+
+ break;
+ }
+ }
+
+ if (!foundValidType) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::valuesAreEqual(const QString &value, const QString &otherValue, const AnySimpleType::Ptr &type) const
+{
+ const AnySimpleType::Ptr targetType = comparableType(type);
+
+ // if the type is xs:anySimpleType we just do string comparison...
+ if (targetType->name(m_namePool) == BuiltinTypes::xsAnySimpleType->name(m_namePool))
+ return (value == otherValue);
+
+ if (BuiltinTypes::xsQName->wxsTypeMatches(type)) {
+ const QXmlName valueName = convertToQName(value);
+ const QXmlName otherValueName = convertToQName(otherValue);
+
+ if (valueName == otherValueName)
+ return true;
+ }
+
+ if (type->category() == SchemaType::SimpleTypeAtomic) {
+ // ... otherwise we use the casting platform for value comparison
+ const DerivedString<TypeString>::Ptr valueStr = DerivedString<TypeString>::fromLexical(m_namePool, value);
+ const DerivedString<TypeString>::Ptr otherValueStr = DerivedString<TypeString>::fromLexical(m_namePool, otherValue);
+
+ return XsdSchemaHelper::constructAndCompare(valueStr, AtomicComparator::OperatorEqual, otherValueStr, targetType, m_context, m_reflection);
+ } else if (type->category() == SchemaType::SimpleTypeList) {
+ const QStringList values = value.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ const QStringList otherValues = otherValue.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ if (values.count() != otherValues.count())
+ return false;
+
+ for (int i = 0; i < values.count(); ++i) {
+ if (!valuesAreEqual(values.at(i), otherValues.at(i), XsdSimpleType::Ptr(type)->itemType()))
+ return false;
+ }
+
+ return true;
+ } else if (type->category() == SchemaType::SimpleTypeUnion) {
+ const AnySimpleType::List memberTypes = XsdSimpleType::Ptr(type)->memberTypes();
+ for (int i = 0; i < memberTypes.count(); ++i) {
+ if (valuesAreEqual(value, otherValue, memberTypes.at(i))) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ return false;
+}
+
+bool XsdTypeChecker::checkConstrainingFacets(const AtomicValue::Ptr &value, const QString &lexicalValue, const AnySimpleType::Ptr &type, QString &errorMsg) const
+{
+ const XsdFacet::Hash facets = mergedFacetsForType(type, m_context);
+
+ if (BuiltinTypes::xsString->wxsTypeMatches(type) ||
+ BuiltinTypes::xsUntypedAtomic->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsString(value->stringValue(), facets, BuiltinTypes::xsString, errorMsg);
+ } else if (BuiltinTypes::xsAnyURI->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsString(value->stringValue(), facets, BuiltinTypes::xsAnyURI, errorMsg);
+ } else if (BuiltinTypes::xsNOTATION->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsNotation(value->as<QNameValue>()->qName(), facets, errorMsg);
+ } else if (BuiltinTypes::xsUnsignedByte->wxsTypeMatches(type) ||
+ BuiltinTypes::xsUnsignedInt->wxsTypeMatches(type) ||
+ BuiltinTypes::xsUnsignedLong->wxsTypeMatches(type) ||
+ BuiltinTypes::xsUnsignedShort->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsUnsignedInteger(value->as<Numeric>()->toUnsignedInteger(), lexicalValue, facets, errorMsg);
+ } else if (BuiltinTypes::xsInteger->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsSignedInteger(value->as<Numeric>()->toInteger(), lexicalValue, facets, errorMsg);
+ } else if (BuiltinTypes::xsFloat->wxsTypeMatches(type) ||
+ BuiltinTypes::xsDouble->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDouble(value->as<Numeric>()->toDouble(), lexicalValue, facets, errorMsg);
+ } else if (BuiltinTypes::xsDecimal->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDecimal(value, lexicalValue, facets, errorMsg);
+ } else if (BuiltinTypes::xsDateTime->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsDateTime, errorMsg);
+ } else if (BuiltinTypes::xsDate->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsDate, errorMsg);
+ } else if (BuiltinTypes::xsGYear->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGYear, errorMsg);
+ } else if (BuiltinTypes::xsGYearMonth->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGYearMonth, errorMsg);
+ } else if (BuiltinTypes::xsGMonth->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGMonth, errorMsg);
+ } else if (BuiltinTypes::xsGMonthDay->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGMonthDay, errorMsg);
+ } else if (BuiltinTypes::xsGDay->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGDay, errorMsg);
+ } else if (BuiltinTypes::xsTime->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsTime, errorMsg);
+ } else if (BuiltinTypes::xsDuration->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDuration(value, lexicalValue, facets, errorMsg);
+ } else if (BuiltinTypes::xsBoolean->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsBoolean(value->as<Boolean>()->value(), lexicalValue, facets, errorMsg);
+ } else if (BuiltinTypes::xsHexBinary->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsBinary(value->as<Base64Binary>()->asByteArray(), facets, BuiltinTypes::xsHexBinary, errorMsg);
+ } else if (BuiltinTypes::xsBase64Binary->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsBinary(value->as<Base64Binary>()->asByteArray(), facets, BuiltinTypes::xsBase64Binary, errorMsg);
+ } else if (BuiltinTypes::xsQName->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsQName(value->as<QNameValue>()->qName(), lexicalValue, facets, errorMsg);
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsString(const QString &value, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::Length)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Length);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
+ if (length->toInteger() != value.length()) {
+ errorMsg = QtXmlPatterns::tr("String content does not match the length facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumLength)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumLength);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
+ if (length->toInteger() > value.length()) {
+ errorMsg = QtXmlPatterns::tr("String content does not match the minLength facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MaximumLength)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumLength);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
+ if (length->toInteger() < value.length()) {
+ errorMsg = QtXmlPatterns::tr("String content does not match the maxLength facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
+ const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
+ if (exp.exactMatch(value)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("String content does not match pattern facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Enumeration)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+ const DerivedString<TypeString>::Ptr valueStr = DerivedString<TypeString>::fromLexical(m_namePool, value);
+
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ if (XsdSchemaHelper::constructAndCompare(valueStr, AtomicComparator::OperatorEqual, multiValue.at(j), type, m_context, m_reflection)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("String content is not listed in the enumeration facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsSignedInteger(long long value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::MaximumInclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsLong, m_context, m_reflection);
+ if (facetValue->toInteger() < value) {
+ errorMsg = QtXmlPatterns::tr("Signed integer content does not match the maxInclusive facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MaximumExclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsLong, m_context, m_reflection);
+ if (facetValue->toInteger() <= value) {
+ errorMsg = QtXmlPatterns::tr("Signed integer content does not match the maxExclusive facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumInclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsLong, m_context, m_reflection);
+ if (facetValue->toInteger() > value) {
+ errorMsg = QtXmlPatterns::tr("Signed integer content does not match the minInclusive facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumExclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsLong, m_context, m_reflection);
+ if (facetValue->toInteger() >= value) {
+ errorMsg = QtXmlPatterns::tr("Signed integer content does not match the minExclusive facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Enumeration)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+ const DerivedString<TypeString>::Ptr valueStr = DerivedString<TypeString>::fromLexical(m_namePool, QString::number(value));
+
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ if (XsdSchemaHelper::constructAndCompare(valueStr, AtomicComparator::OperatorEqual, multiValue.at(j), BuiltinTypes::xsLong, m_context, m_reflection)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("Signed integer content is not listed in the enumeration facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
+ const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
+ if (exp.exactMatch(lexicalValue)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("Signed integer content does not match pattern facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::TotalDigits)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::TotalDigits);
+ const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value();
+
+ if (totalDigitsForSignedLongLong(value) > facetValue->toInteger()) {
+ errorMsg = QtXmlPatterns::tr("Signed integer content does not match in the totalDigits facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsUnsignedInteger(unsigned long long value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::MaximumInclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsUnsignedLong, m_context, m_reflection);
+ if (facetValue->toUnsignedInteger() < value) {
+ errorMsg = QtXmlPatterns::tr("Unsigned integer content does not match the maxInclusive facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MaximumExclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsUnsignedLong, m_context, m_reflection);
+ if (facetValue->toUnsignedInteger() <= value) {
+ errorMsg = QtXmlPatterns::tr("Unsigned integer content does not match the maxExclusive facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumInclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsUnsignedLong, m_context, m_reflection);
+ if (facetValue->toUnsignedInteger() > value) {
+ errorMsg = QtXmlPatterns::tr("Unsigned integer content does not match the minInclusive facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumExclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsUnsignedLong, m_context, m_reflection);
+ if (facetValue->toUnsignedInteger() >= value) {
+ errorMsg = QtXmlPatterns::tr("Unsigned integer content does not match the minExclusive facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Enumeration)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+ const DerivedString<TypeString>::Ptr valueStr = DerivedString<TypeString>::fromLexical(m_namePool, QString::number(value));
+
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ if (XsdSchemaHelper::constructAndCompare(valueStr, AtomicComparator::OperatorEqual, multiValue.at(j), BuiltinTypes::xsUnsignedLong, m_context, m_reflection)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("Unsigned integer content is not listed in the enumeration facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
+ const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
+ if (exp.exactMatch(lexicalValue)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("Unsigned integer content does not match pattern facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::TotalDigits)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::TotalDigits);
+ const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value();
+
+ if (totalDigitsForUnsignedLongLong(value) > facetValue->toInteger()) {
+ errorMsg = QtXmlPatterns::tr("Unsigned integer content does not match in the totalDigits facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsDouble(double value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::MaximumInclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsDouble, m_context, m_reflection);
+ if (facetValue->toDouble() < value) {
+ errorMsg = QtXmlPatterns::tr("Double content does not match the maxInclusive facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MaximumExclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsDouble, m_context, m_reflection);
+ if (facetValue->toDouble() <= value) {
+ errorMsg = QtXmlPatterns::tr("Double content does not match the maxExclusive facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumInclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsDouble, m_context, m_reflection);
+ if (facetValue->toDouble() > value) {
+ errorMsg = QtXmlPatterns::tr("Double content does not match the minInclusive facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumExclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsDouble, m_context, m_reflection);
+ if (facetValue->toDouble() >= value) {
+ errorMsg = QtXmlPatterns::tr("Double content does not match the minExclusive facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Enumeration)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+ const DerivedString<TypeString>::Ptr valueStr = DerivedString<TypeString>::fromLexical(m_namePool, QString::number(value));
+
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ if (XsdSchemaHelper::constructAndCompare(valueStr, AtomicComparator::OperatorEqual, multiValue.at(j), BuiltinTypes::xsDouble, m_context, m_reflection)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("Double content is not listed in the enumeration facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
+ const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
+ if (exp.exactMatch(lexicalValue)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("Double content does not match pattern facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsDecimal(const AtomicValue::Ptr &value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::FractionDigits)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::FractionDigits);
+ const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value();
+
+ if (fractionDigitsForDecimal(lexicalValue) > facetValue->toInteger()) {
+ errorMsg = QtXmlPatterns::tr("Decimal content does not match in the fractionDigits facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::TotalDigits)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::TotalDigits);
+ const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value();
+
+ if (totalDigitsForDecimal(lexicalValue) > facetValue->toInteger()) {
+ errorMsg = QtXmlPatterns::tr("Decimal content does not match in the totalDigits facet.");
+ return false;
+ }
+ }
+
+ return checkConstrainingFacetsDouble(value->as<Decimal>()->toDouble(), lexicalValue, facets, errorMsg);
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsDateTime(const QDateTime &value, const QString &lexicalValue, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::MaximumInclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive);
+ const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
+ if (facetValue->toDateTime() < value) {
+ errorMsg = QtXmlPatterns::tr("Date time content does not match the maxInclusive facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MaximumExclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive);
+ const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
+ if (facetValue->toDateTime() <= value) {
+ errorMsg = QtXmlPatterns::tr("Date time content does not match the maxExclusive facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumInclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive);
+ const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
+ if (facetValue->toDateTime() > value) {
+ errorMsg = QtXmlPatterns::tr("Date time content does not match the minInclusive facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumExclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive);
+ const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
+ if (facetValue->toDateTime() >= value) {
+ errorMsg = QtXmlPatterns::tr("Date time content does not match the minExclusive facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Enumeration)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
+ if (facetValue->toDateTime() == value) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("Date time content is not listed in the enumeration facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
+ const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
+ if (exp.exactMatch(lexicalValue)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("Date time content does not match pattern facet.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsDuration(const AtomicValue::Ptr&, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::MaximumInclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive);
+ const DerivedString<TypeString>::Ptr value = DerivedString<TypeString>::fromLexical(m_namePool, lexicalValue);
+
+ if (XsdSchemaHelper::constructAndCompare(facets.value(XsdFacet::MaximumInclusive)->value(), AtomicComparator::OperatorLessThan, value, BuiltinTypes::xsDuration, m_context, m_reflection)) {
+ errorMsg = QtXmlPatterns::tr("Duration content does not match the maxInclusive facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MaximumExclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive);
+ const DerivedString<TypeString>::Ptr value = DerivedString<TypeString>::fromLexical(m_namePool, lexicalValue);
+
+ if (XsdSchemaHelper::constructAndCompare(facets.value(XsdFacet::MaximumExclusive)->value(), AtomicComparator::OperatorLessOrEqual, value, BuiltinTypes::xsDuration, m_context, m_reflection)) {
+ errorMsg = QtXmlPatterns::tr("Duration content does not match the maxExclusive facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumInclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive);
+ const DerivedString<TypeString>::Ptr value = DerivedString<TypeString>::fromLexical(m_namePool, lexicalValue);
+
+ if (XsdSchemaHelper::constructAndCompare(facets.value(XsdFacet::MinimumInclusive)->value(), AtomicComparator::OperatorGreaterThan, value, BuiltinTypes::xsDuration, m_context, m_reflection)) {
+ errorMsg = QtXmlPatterns::tr("Duration content does not match the minInclusive facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumExclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive);
+ const DerivedString<TypeString>::Ptr value = DerivedString<TypeString>::fromLexical(m_namePool, lexicalValue);
+
+ if (XsdSchemaHelper::constructAndCompare(facets.value(XsdFacet::MinimumExclusive)->value(), AtomicComparator::OperatorGreaterOrEqual, value, BuiltinTypes::xsDuration, m_context, m_reflection)) {
+ errorMsg = QtXmlPatterns::tr("Duration content does not match the minExclusive facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Enumeration)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+ const DerivedString<TypeString>::Ptr value = DerivedString<TypeString>::fromLexical(m_namePool, lexicalValue);
+
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ if (XsdSchemaHelper::constructAndCompare(multiValue.at(j), AtomicComparator::OperatorEqual, value, BuiltinTypes::xsDuration, m_context, m_reflection)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("Duration content is not listed in the enumeration facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
+ const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
+ if (exp.exactMatch(lexicalValue)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("Duration content does not match pattern facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsBoolean(bool, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::Pattern)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
+ const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
+ if (exp.exactMatch(lexicalValue)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("Boolean content does not match pattern facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsBinary(const QByteArray &value, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::Length)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Length);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
+ if (length->toInteger() != value.length()) {
+ errorMsg = QtXmlPatterns::tr("Binary content does not match the length facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumLength)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumLength);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
+ if (length->toInteger() > value.length()) {
+ errorMsg = QtXmlPatterns::tr("Binary content does not match the minLength facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MaximumLength)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumLength);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
+ if (length->toInteger() < value.length()) {
+ errorMsg = QtXmlPatterns::tr("Binary content does not match the maxLength facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Enumeration)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const Base64Binary::Ptr binary = ValueFactory::fromLexical(multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
+ const QByteArray facetValue = binary->as<Base64Binary>()->asByteArray();
+ if (value == facetValue) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("Binary content is not listed in the enumeration facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ //TODO: implement
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsQName(const QXmlName &value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::Length)) {
+ // always true
+ }
+ if (facets.contains(XsdFacet::MinimumLength)) {
+ // always true
+ }
+ if (facets.contains(XsdFacet::MaximumLength)) {
+ // always true
+ }
+ if (facets.contains(XsdFacet::Enumeration)) {
+ if (!XPathHelper::isQName(lexicalValue)) {
+ errorMsg = QtXmlPatterns::tr("Invalid QName content: %1.").arg(formatData(lexicalValue));
+ return false;
+ }
+
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QXmlName facetValue = multiValue.at(j)->as<QNameValue>()->qName();
+
+ if (value == facetValue) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("QName content is not listed in the enumeration facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
+ const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
+ if (exp.exactMatch(lexicalValue)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("QName content does not match pattern facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsNotation(const QXmlName &value, const XsdFacet::Hash &facets, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::Length)) {
+ // deprecated by spec
+ }
+ if (facets.contains(XsdFacet::MinimumLength)) {
+ // deprecated by spec
+ }
+ if (facets.contains(XsdFacet::MaximumLength)) {
+ // deprecated by spec
+ }
+ if (facets.contains(XsdFacet::Enumeration)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QXmlName facetValue = multiValue.at(j)->as<QNameValue>()->qName();
+
+ if (value == facetValue) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("Notation content is not listed in the enumeration facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ //TODO: implement
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsList(const QStringList &values, const QString &lexicalValue, const AnySimpleType::Ptr &itemType, const XsdFacet::Hash &facets, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::Length)) {
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr value = facets.value(XsdFacet::Length)->value();
+ if (value->toInteger() != values.count()) {
+ errorMsg = QtXmlPatterns::tr("List content does not match length facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumLength)) {
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr value = facets.value(XsdFacet::MinimumLength)->value();
+ if (value->toInteger() > values.count()) {
+ errorMsg = QtXmlPatterns::tr("List content does not match minLength facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MaximumLength)) {
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr value = facets.value(XsdFacet::MaximumLength)->value();
+ if (value->toInteger() < values.count()) {
+ errorMsg = QtXmlPatterns::tr("List content does not match maxLength facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Enumeration)) {
+
+ bool found = false;
+
+ // we have to handle lists with QName derived items differently
+ if (BuiltinTypes::xsQName->wxsTypeMatches(itemType) || BuiltinTypes::xsNOTATION->wxsTypeMatches(itemType)) {
+ // first convert the string values from the instance document to a list of QXmlName
+ QList<QXmlName> instanceValues;
+ for (int i = 0; i < values.count(); ++i) {
+ instanceValues.append(convertToQName(values.at(i)));
+ }
+
+ // fetch the values from the facet and create a list of QXmlNames for each of them
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+
+ const AtomicValue::List multiValue = facet->multiValue();
+ for (int i = 0; i < multiValue.count(); ++i) {
+ const QStringList facetValueList = multiValue.at(i)->as<DerivedString<TypeString> >()->stringValue().split(QLatin1Char(' '), QString::SkipEmptyParts);
+
+ // create the list of atomic string values
+ QList<QXmlName> facetValues;
+ for (int j = 0; j < facetValueList.count(); ++j) {
+ facetValues.append(convertToQName(facetValueList.at(j)));
+ }
+
+ // check if both lists have the same length
+ if (instanceValues.count() != facetValues.count())
+ continue;
+
+ // check if both lists are equal, that means the contain equal items in the same order
+ bool matchesAll = true;
+ for (int j = 0; j < instanceValues.count(); ++j) {
+ if (instanceValues.at(j) != facetValues.at(j)) {
+ matchesAll = false;
+ break;
+ }
+ }
+
+ if (matchesAll) {
+ found = true;
+ break;
+ }
+ }
+ } else {
+ // first convert the string values from the instance document to atomic values of type string
+ AtomicValue::List instanceValues;
+ for (int i = 0; i < values.count(); ++i) {
+ instanceValues.append(DerivedString<TypeString>::fromLexical(m_namePool, values.at(i)));
+ }
+
+ // fetch the values from the facet and create a list of atomic string values for each of them
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+
+ const AnySimpleType::Ptr targetType = comparableType(itemType);
+
+ const AtomicValue::List multiValue = facet->multiValue();
+ for (int i = 0; i < multiValue.count(); ++i) {
+ const QStringList facetValueList = multiValue.at(i)->as<DerivedString<TypeString> >()->stringValue().split(QLatin1Char(' '), QString::SkipEmptyParts);
+
+ // create the list of atomic string values
+ AtomicValue::List facetValues;
+ for (int j = 0; j < facetValueList.count(); ++j) {
+ facetValues.append(DerivedString<TypeString>::fromLexical(m_namePool, facetValueList.at(j)));
+ }
+
+ // check if both lists have the same length
+ if (instanceValues.count() != facetValues.count())
+ continue;
+
+ // check if both lists are equal, that means the contain equal items in the same order
+ bool matchesAll = true;
+ for (int j = 0; j < instanceValues.count(); ++j) {
+ if (!XsdSchemaHelper::constructAndCompare(instanceValues.at(j), AtomicComparator::OperatorEqual, facetValues.at(j), targetType, m_context, m_reflection)) {
+ matchesAll = false;
+ break;
+ }
+ }
+
+ if (matchesAll) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("List content is not listed in the enumeration facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
+ const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
+ if (exp.exactMatch(lexicalValue)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("List content does not match pattern facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsUnion(const QString &value, const QString &lexicalValue, const XsdSimpleType::Ptr &simpleType, const XsdFacet::Hash &facets, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::Enumeration)) {
+ const AnySimpleType::List memberTypes = simpleType->memberTypes();
+
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+
+ // convert the instance value into an atomic string value
+ const DerivedString<TypeString>::Ptr valueString = DerivedString<TypeString>::fromLexical(m_namePool, value);
+
+ // collect the facet values into a list of atomic string values
+ const AtomicValue::List facetValues = facet->multiValue();
+
+ // compare the instance value against the facetValues for each member type and
+ // search for a match
+
+ bool found = false;
+ for (int i = 0; i < memberTypes.count(); ++i) {
+ const AnySimpleType::Ptr targetType = comparableType(memberTypes.at(i));
+ for (int j = 0; j < facetValues.count(); ++j) {
+ if (XsdSchemaHelper::constructAndCompare(valueString, AtomicComparator::OperatorEqual, facetValues.at(j), targetType, m_context, m_reflection)) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("Union content is not listed in the enumeration facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
+ const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
+ if (exp.exactMatch(lexicalValue)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("Union content does not match pattern facet.");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+AtomicValue::Ptr XsdTypeChecker::fromLexical(const QString &value, const SchemaType::Ptr &type, const ReportContext::Ptr &context, const SourceLocationReflection *const reflection) const
+{
+ if (type->name(m_namePool) == BuiltinTypes::xsNOTATION->name(m_namePool) || type->name(m_namePool) == BuiltinTypes::xsQName->name(m_namePool)) {
+ if (value.simplified().isEmpty())
+ return ValidationError::createError(QtXmlPatterns::tr("Data of type %1 are not allowed to be empty.").arg(formatType(m_namePool, BuiltinTypes::xsNOTATION)));
+
+ const QXmlName valueName = convertToQName(value);
+ return QNameValue::fromValue(m_namePool, valueName);
+ } else {
+ return ValueFactory::fromLexical(value, type, context, reflection);
+ }
+}
+
+QXmlName XsdTypeChecker::convertToQName(const QString &name) const
+{
+ const int pos = name.indexOf(QLatin1Char(':'));
+
+ QXmlName::PrefixCode prefixCode = 0;
+ QXmlName::NamespaceCode namespaceCode;
+ QXmlName::LocalNameCode localNameCode;
+ if (pos != -1) {
+ prefixCode = m_context->namePool()->allocatePrefix(name.left(pos));
+ namespaceCode = StandardNamespaces::empty;
+ for (int i = 0; i < m_namespaceBindings.count(); ++i) {
+ if (m_namespaceBindings.at(i).prefix() == prefixCode) {
+ namespaceCode = m_namespaceBindings.at(i).namespaceURI();
+ break;
+ }
+ }
+ localNameCode = m_context->namePool()->allocateLocalName(name.mid(pos + 1));
+ } else {
+ prefixCode = StandardPrefixes::empty;
+ namespaceCode = StandardNamespaces::empty;
+ for (int i = 0; i < m_namespaceBindings.count(); ++i) {
+ if (m_namespaceBindings.at(i).prefix() == prefixCode) {
+ namespaceCode = m_namespaceBindings.at(i).namespaceURI();
+ break;
+ }
+ }
+ localNameCode = m_context->namePool()->allocateLocalName(name);
+ }
+
+ return QXmlName(namespaceCode, localNameCode, prefixCode);
+}
+
+QT_END_NAMESPACE