1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
7 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qxsdtypechecker_p.h"
44 #include "qabstractdatetime_p.h"
45 #include "qbase64binary_p.h"
46 #include "qboolean_p.h"
47 #include "qdecimal_p.h"
48 #include "qderivedinteger_p.h"
49 #include "qduration_p.h"
50 #include "qgenericstaticcontext_p.h"
51 #include "qhexbinary_p.h"
52 #include "qnamespaceresolver_p.h"
53 #include "qpatternplatform_p.h"
54 #include "qqnamevalue_p.h"
55 #include "qvaluefactory_p.h"
56 #include "qxmlnamepool.h"
57 #include "qxsdschemahelper_p.h"
58 #include "qxsdschemamerger_p.h"
59 #include "qxsdstatemachine_p.h"
61 #include "qxsdschemadebugger_p.h"
65 using namespace QPatternist;
67 XsdSchemaSourceLocationReflection::XsdSchemaSourceLocationReflection(const QSourceLocation &location)
68 : m_sourceLocation(location)
72 const SourceLocationReflection* XsdSchemaSourceLocationReflection::actualReflection() const
77 QSourceLocation XsdSchemaSourceLocationReflection::sourceLocation() const
79 return m_sourceLocation;
83 static AnySimpleType::Ptr comparableType(const AnySimpleType::Ptr &type)
85 if (!type->isDefinedBySchema()) {
88 const XsdSimpleType::Ptr simpleType(type);
89 if (type->category() == SchemaType::SimpleTypeAtomic) {
90 return simpleType->primitiveType();
91 } else if (type->category() == SchemaType::SimpleTypeList) {
92 return simpleType->itemType();
93 } else if (type->category() == SchemaType::SimpleTypeUnion) {
94 return simpleType->memberTypes().first();
99 return AnySimpleType::Ptr();
102 static int totalDigitsForSignedLongLong(long long value)
104 QString number = QString::number(value);
105 if (number.startsWith(QLatin1Char('-')))
106 number = number.mid(1);
108 return number.length();
111 static int totalDigitsForUnsignedLongLong(unsigned long long value)
113 const QString number = QString::number(value);
114 return number.length();
117 static int totalDigitsForDecimal(const QString &lexicalValue)
119 const QLatin1Char zeroChar('0');
120 const int length = lexicalValue.length() - 1;
122 // strip leading zeros
124 while (lexicalValue.at(pos) == zeroChar && (pos != length))
127 QString value = lexicalValue.mid(pos);
129 // if contains '.' strip trailing zeros
130 if (value.contains(QLatin1Char('.'))) {
131 pos = value.length() - 1;
132 while (value.at(pos) == zeroChar) {
136 value = value.left(pos + 1);
139 // check number of digits of remaining string
141 for (int i = 0; i < value.count(); ++i)
142 if (value.at(i).isDigit())
145 if (totalDigits == 0)
151 static int fractionDigitsForDecimal(const QString &lexicalValue)
153 // we use the lexical value here, as the conversion to double might strip
154 // away decimal positions
156 QString trimmedValue(lexicalValue.trimmed());
157 const int pos = trimmedValue.indexOf(QLatin1Char('.'));
158 if (pos == -1) // no '.' -> 0 fraction digits
161 return (trimmedValue.length() - pos - 1);
164 XsdTypeChecker::XsdTypeChecker(const XsdSchemaContext::Ptr &context, const QVector<QXmlName> &namespaceBindings, const QSourceLocation &location)
166 , m_namePool(m_context->namePool())
167 , m_namespaceBindings(namespaceBindings)
168 , m_reflection(new XsdSchemaSourceLocationReflection(location))
172 XsdTypeChecker::~XsdTypeChecker()
177 QString XsdTypeChecker::normalizedValue(const QString &value, const XsdFacet::Hash &facets)
179 if (!facets.contains(XsdFacet::WhiteSpace))
182 const XsdFacet::Ptr whiteSpaceFacet = facets.value(XsdFacet::WhiteSpace);
184 const DerivedString<TypeString>::Ptr facetValue = whiteSpaceFacet->value();
185 const QString stringValue = facetValue->stringValue();
186 if (stringValue == XsdSchemaToken::toString(XsdSchemaToken::Preserve))
188 else if (stringValue == XsdSchemaToken::toString(XsdSchemaToken::Replace)) {
189 QString newValue(value);
190 newValue.replace(QLatin1Char('\t'), QLatin1Char(' '));
191 newValue.replace(QLatin1Char('\n'), QLatin1Char(' '));
192 newValue.replace(QLatin1Char('\r'), QLatin1Char(' '));
195 } else if (stringValue == XsdSchemaToken::toString(XsdSchemaToken::Collapse)) {
196 return value.simplified();
202 XsdFacet::Hash XsdTypeChecker::mergedFacetsForType(const SchemaType::Ptr &type, const XsdSchemaContext::Ptr &context)
205 return XsdFacet::Hash();
207 const XsdFacet::Hash baseFacets = mergedFacetsForType(type->wxsSuperType(), context);
208 const XsdFacet::Hash facets = context->facetsForType(type);
210 XsdFacet::Hash result = baseFacets;
211 XsdFacet::HashIterator it(facets);
212 while (it.hasNext()) {
215 result.insert(it.key(), it.value());
221 bool XsdTypeChecker::isValidString(const QString &normalizedString, const AnySimpleType::Ptr &type, QString &errorMsg, AnySimpleType::Ptr *boundType) const
223 if (type->name(m_namePool) == BuiltinTypes::xsAnySimpleType->name(m_namePool)) {
230 if (!type->isDefinedBySchema()) {
231 // special QName check
232 if (BuiltinTypes::xsQName->wxsTypeMatches(type)) {
233 if (!XPathHelper::isQName(normalizedString)) {
234 errorMsg = QtXmlPatterns::tr("%1 is not valid according to %2.").arg(formatData(normalizedString)).arg(formatType(m_namePool, type));
239 const AtomicValue::Ptr value = fromLexical(normalizedString, type, m_context, m_reflection);
240 if (value->hasError()) {
241 errorMsg = QtXmlPatterns::tr("%1 is not valid according to %2.").arg(formatData(normalizedString)).arg(formatType(m_namePool, type));
245 if (!checkConstrainingFacets(value, normalizedString, type, errorMsg)) {
253 const XsdSimpleType::Ptr simpleType(type);
255 if (simpleType->category() == XsdSimpleType::SimpleTypeAtomic) {
256 AnySimpleType::Ptr targetType = simpleType->primitiveType();
257 if (!simpleType->wxsSuperType()->isDefinedBySchema())
258 targetType = simpleType->wxsSuperType();
260 const AtomicValue::Ptr value = fromLexical(normalizedString, targetType, m_context, m_reflection);
261 if (value->hasError()) {
262 errorMsg = QtXmlPatterns::tr("%1 is not valid according to %2.").arg(formatData(normalizedString)).arg(formatType(m_namePool, targetType));
266 if (!checkConstrainingFacets(value, normalizedString, type, errorMsg)) {
273 } else if (simpleType->category() == XsdSimpleType::SimpleTypeList) {
274 QStringList entries = normalizedString.split(QLatin1Char(' '), QString::SkipEmptyParts);
275 for (int i = 0; i < entries.count(); ++i) {
276 entries[i] = normalizedValue(entries.at(i), mergedFacetsForType(simpleType->itemType(), m_context));
279 if (!checkConstrainingFacetsList(entries, normalizedString, simpleType->itemType(), mergedFacetsForType(simpleType, m_context), errorMsg)) {
283 for (int i = 0; i < entries.count(); ++i) {
284 if (!isValidString(entries.at(i), simpleType->itemType(), errorMsg)) {
290 *boundType = simpleType->itemType();
292 } else if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) {
293 if (!checkConstrainingFacetsUnion(normalizedString, normalizedString, simpleType, mergedFacetsForType(simpleType, m_context), errorMsg)) {
297 const AnySimpleType::List memberTypes = simpleType->memberTypes();
299 bool foundValidType = false;
300 for (int i = 0; i < memberTypes.count(); ++i) {
301 const XsdFacet::Hash mergedFacets = mergedFacetsForType(memberTypes.at(i), m_context);
302 if (isValidString(normalizedValue(normalizedString, mergedFacets), memberTypes.at(i), errorMsg)) {
303 foundValidType = true;
306 *boundType = memberTypes.at(i);
312 if (!foundValidType) {
321 bool XsdTypeChecker::valuesAreEqual(const QString &value, const QString &otherValue, const AnySimpleType::Ptr &type) const
323 const AnySimpleType::Ptr targetType = comparableType(type);
325 // if the type is xs:anySimpleType we just do string comparison...
326 if (targetType->name(m_namePool) == BuiltinTypes::xsAnySimpleType->name(m_namePool))
327 return (value == otherValue);
329 if (BuiltinTypes::xsQName->wxsTypeMatches(type)) {
330 const QXmlName valueName = convertToQName(value);
331 const QXmlName otherValueName = convertToQName(otherValue);
333 if (valueName == otherValueName)
337 if (type->category() == SchemaType::SimpleTypeAtomic) {
338 // ... otherwise we use the casting platform for value comparison
339 const DerivedString<TypeString>::Ptr valueStr = DerivedString<TypeString>::fromLexical(m_namePool, value);
340 const DerivedString<TypeString>::Ptr otherValueStr = DerivedString<TypeString>::fromLexical(m_namePool, otherValue);
342 return XsdSchemaHelper::constructAndCompare(valueStr, AtomicComparator::OperatorEqual, otherValueStr, targetType, m_context, m_reflection);
343 } else if (type->category() == SchemaType::SimpleTypeList) {
344 const QStringList values = value.split(QLatin1Char(' '), QString::SkipEmptyParts);
345 const QStringList otherValues = otherValue.split(QLatin1Char(' '), QString::SkipEmptyParts);
346 if (values.count() != otherValues.count())
349 for (int i = 0; i < values.count(); ++i) {
350 if (!valuesAreEqual(values.at(i), otherValues.at(i), XsdSimpleType::Ptr(type)->itemType()))
355 } else if (type->category() == SchemaType::SimpleTypeUnion) {
356 const AnySimpleType::List memberTypes = XsdSimpleType::Ptr(type)->memberTypes();
357 for (int i = 0; i < memberTypes.count(); ++i) {
358 if (valuesAreEqual(value, otherValue, memberTypes.at(i))) {
369 bool XsdTypeChecker::checkConstrainingFacets(const AtomicValue::Ptr &value, const QString &lexicalValue, const AnySimpleType::Ptr &type, QString &errorMsg) const
371 const XsdFacet::Hash facets = mergedFacetsForType(type, m_context);
373 if (BuiltinTypes::xsString->wxsTypeMatches(type) ||
374 BuiltinTypes::xsUntypedAtomic->wxsTypeMatches(type)) {
375 return checkConstrainingFacetsString(value->stringValue(), facets, BuiltinTypes::xsString, errorMsg);
376 } else if (BuiltinTypes::xsAnyURI->wxsTypeMatches(type)) {
377 return checkConstrainingFacetsString(value->stringValue(), facets, BuiltinTypes::xsAnyURI, errorMsg);
378 } else if (BuiltinTypes::xsNOTATION->wxsTypeMatches(type)) {
379 return checkConstrainingFacetsNotation(value->as<QNameValue>()->qName(), facets, errorMsg);
380 } else if (BuiltinTypes::xsUnsignedByte->wxsTypeMatches(type) ||
381 BuiltinTypes::xsUnsignedInt->wxsTypeMatches(type) ||
382 BuiltinTypes::xsUnsignedLong->wxsTypeMatches(type) ||
383 BuiltinTypes::xsUnsignedShort->wxsTypeMatches(type)) {
384 return checkConstrainingFacetsUnsignedInteger(value->as<Numeric>()->toUnsignedInteger(), lexicalValue, facets, errorMsg);
385 } else if (BuiltinTypes::xsInteger->wxsTypeMatches(type)) {
386 return checkConstrainingFacetsSignedInteger(value->as<Numeric>()->toInteger(), lexicalValue, facets, errorMsg);
387 } else if (BuiltinTypes::xsFloat->wxsTypeMatches(type) ||
388 BuiltinTypes::xsDouble->wxsTypeMatches(type)) {
389 return checkConstrainingFacetsDouble(value->as<Numeric>()->toDouble(), lexicalValue, facets, errorMsg);
390 } else if (BuiltinTypes::xsDecimal->wxsTypeMatches(type)) {
391 return checkConstrainingFacetsDecimal(value, lexicalValue, facets, errorMsg);
392 } else if (BuiltinTypes::xsDateTime->wxsTypeMatches(type)) {
393 return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsDateTime, errorMsg);
394 } else if (BuiltinTypes::xsDate->wxsTypeMatches(type)) {
395 return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsDate, errorMsg);
396 } else if (BuiltinTypes::xsGYear->wxsTypeMatches(type)) {
397 return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGYear, errorMsg);
398 } else if (BuiltinTypes::xsGYearMonth->wxsTypeMatches(type)) {
399 return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGYearMonth, errorMsg);
400 } else if (BuiltinTypes::xsGMonth->wxsTypeMatches(type)) {
401 return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGMonth, errorMsg);
402 } else if (BuiltinTypes::xsGMonthDay->wxsTypeMatches(type)) {
403 return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGMonthDay, errorMsg);
404 } else if (BuiltinTypes::xsGDay->wxsTypeMatches(type)) {
405 return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGDay, errorMsg);
406 } else if (BuiltinTypes::xsTime->wxsTypeMatches(type)) {
407 return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsTime, errorMsg);
408 } else if (BuiltinTypes::xsDuration->wxsTypeMatches(type)) {
409 return checkConstrainingFacetsDuration(value, lexicalValue, facets, errorMsg);
410 } else if (BuiltinTypes::xsBoolean->wxsTypeMatches(type)) {
411 return checkConstrainingFacetsBoolean(value->as<Boolean>()->value(), lexicalValue, facets, errorMsg);
412 } else if (BuiltinTypes::xsHexBinary->wxsTypeMatches(type)) {
413 return checkConstrainingFacetsBinary(value->as<Base64Binary>()->asByteArray(), facets, BuiltinTypes::xsHexBinary, errorMsg);
414 } else if (BuiltinTypes::xsBase64Binary->wxsTypeMatches(type)) {
415 return checkConstrainingFacetsBinary(value->as<Base64Binary>()->asByteArray(), facets, BuiltinTypes::xsBase64Binary, errorMsg);
416 } else if (BuiltinTypes::xsQName->wxsTypeMatches(type)) {
417 return checkConstrainingFacetsQName(value->as<QNameValue>()->qName(), lexicalValue, facets, errorMsg);
423 bool XsdTypeChecker::checkConstrainingFacetsString(const QString &value, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const
425 if (facets.contains(XsdFacet::Length)) {
426 const XsdFacet::Ptr facet = facets.value(XsdFacet::Length);
427 const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
428 if (length->toInteger() != value.length()) {
429 errorMsg = QtXmlPatterns::tr("String content does not match the length facet.");
433 if (facets.contains(XsdFacet::MinimumLength)) {
434 const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumLength);
435 const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
436 if (length->toInteger() > value.length()) {
437 errorMsg = QtXmlPatterns::tr("String content does not match the minLength facet.");
441 if (facets.contains(XsdFacet::MaximumLength)) {
442 const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumLength);
443 const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
444 if (length->toInteger() < value.length()) {
445 errorMsg = QtXmlPatterns::tr("String content does not match the maxLength facet.");
449 if (facets.contains(XsdFacet::Pattern)) {
450 const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
451 const AtomicValue::List multiValue = facet->multiValue();
453 for (int j = 0; j < multiValue.count(); ++j) {
454 const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
455 const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
456 if (exp.exactMatch(value)) {
463 errorMsg = QtXmlPatterns::tr("String content does not match pattern facet.");
467 if (facets.contains(XsdFacet::Enumeration)) {
468 const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
469 const DerivedString<TypeString>::Ptr valueStr = DerivedString<TypeString>::fromLexical(m_namePool, value);
471 const AtomicValue::List multiValue = facet->multiValue();
473 for (int j = 0; j < multiValue.count(); ++j) {
474 if (XsdSchemaHelper::constructAndCompare(valueStr, AtomicComparator::OperatorEqual, multiValue.at(j), type, m_context, m_reflection)) {
481 errorMsg = QtXmlPatterns::tr("String content is not listed in the enumeration facet.");
485 if (facets.contains(XsdFacet::Assertion)) {
492 bool XsdTypeChecker::checkConstrainingFacetsSignedInteger(long long value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
494 if (facets.contains(XsdFacet::MaximumInclusive)) {
495 const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive);
496 const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsLong, m_context, m_reflection);
497 if (facetValue->toInteger() < value) {
498 errorMsg = QtXmlPatterns::tr("Signed integer content does not match the maxInclusive facet.");
502 if (facets.contains(XsdFacet::MaximumExclusive)) {
503 const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive);
504 const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsLong, m_context, m_reflection);
505 if (facetValue->toInteger() <= value) {
506 errorMsg = QtXmlPatterns::tr("Signed integer content does not match the maxExclusive facet.");
510 if (facets.contains(XsdFacet::MinimumInclusive)) {
511 const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive);
512 const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsLong, m_context, m_reflection);
513 if (facetValue->toInteger() > value) {
514 errorMsg = QtXmlPatterns::tr("Signed integer content does not match the minInclusive facet.");
518 if (facets.contains(XsdFacet::MinimumExclusive)) {
519 const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive);
520 const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsLong, m_context, m_reflection);
521 if (facetValue->toInteger() >= value) {
522 errorMsg = QtXmlPatterns::tr("Signed integer content does not match the minExclusive facet.");
526 if (facets.contains(XsdFacet::Enumeration)) {
527 const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
528 const DerivedString<TypeString>::Ptr valueStr = DerivedString<TypeString>::fromLexical(m_namePool, QString::number(value));
530 const AtomicValue::List multiValue = facet->multiValue();
532 for (int j = 0; j < multiValue.count(); ++j) {
533 if (XsdSchemaHelper::constructAndCompare(valueStr, AtomicComparator::OperatorEqual, multiValue.at(j), BuiltinTypes::xsLong, m_context, m_reflection)) {
540 errorMsg = QtXmlPatterns::tr("Signed integer content is not listed in the enumeration facet.");
544 if (facets.contains(XsdFacet::Pattern)) {
545 const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
546 const AtomicValue::List multiValue = facet->multiValue();
548 for (int j = 0; j < multiValue.count(); ++j) {
549 const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
550 const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
551 if (exp.exactMatch(lexicalValue)) {
558 errorMsg = QtXmlPatterns::tr("Signed integer content does not match pattern facet.");
562 if (facets.contains(XsdFacet::TotalDigits)) {
563 const XsdFacet::Ptr facet = facets.value(XsdFacet::TotalDigits);
564 const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value();
566 if (totalDigitsForSignedLongLong(value) > facetValue->toInteger()) {
567 errorMsg = QtXmlPatterns::tr("Signed integer content does not match in the totalDigits facet.");
571 if (facets.contains(XsdFacet::Assertion)) {
578 bool XsdTypeChecker::checkConstrainingFacetsUnsignedInteger(unsigned long long value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
580 if (facets.contains(XsdFacet::MaximumInclusive)) {
581 const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive);
582 const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsUnsignedLong, m_context, m_reflection);
583 if (facetValue->toUnsignedInteger() < value) {
584 errorMsg = QtXmlPatterns::tr("Unsigned integer content does not match the maxInclusive facet.");
588 if (facets.contains(XsdFacet::MaximumExclusive)) {
589 const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive);
590 const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsUnsignedLong, m_context, m_reflection);
591 if (facetValue->toUnsignedInteger() <= value) {
592 errorMsg = QtXmlPatterns::tr("Unsigned integer content does not match the maxExclusive facet.");
596 if (facets.contains(XsdFacet::MinimumInclusive)) {
597 const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive);
598 const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsUnsignedLong, m_context, m_reflection);
599 if (facetValue->toUnsignedInteger() > value) {
600 errorMsg = QtXmlPatterns::tr("Unsigned integer content does not match the minInclusive facet.");
604 if (facets.contains(XsdFacet::MinimumExclusive)) {
605 const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive);
606 const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsUnsignedLong, m_context, m_reflection);
607 if (facetValue->toUnsignedInteger() >= value) {
608 errorMsg = QtXmlPatterns::tr("Unsigned integer content does not match the minExclusive facet.");
612 if (facets.contains(XsdFacet::Enumeration)) {
613 const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
614 const DerivedString<TypeString>::Ptr valueStr = DerivedString<TypeString>::fromLexical(m_namePool, QString::number(value));
616 const AtomicValue::List multiValue = facet->multiValue();
618 for (int j = 0; j < multiValue.count(); ++j) {
619 if (XsdSchemaHelper::constructAndCompare(valueStr, AtomicComparator::OperatorEqual, multiValue.at(j), BuiltinTypes::xsUnsignedLong, m_context, m_reflection)) {
626 errorMsg = QtXmlPatterns::tr("Unsigned integer content is not listed in the enumeration facet.");
630 if (facets.contains(XsdFacet::Pattern)) {
631 const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
632 const AtomicValue::List multiValue = facet->multiValue();
634 for (int j = 0; j < multiValue.count(); ++j) {
635 const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
636 const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
637 if (exp.exactMatch(lexicalValue)) {
644 errorMsg = QtXmlPatterns::tr("Unsigned integer content does not match pattern facet.");
648 if (facets.contains(XsdFacet::TotalDigits)) {
649 const XsdFacet::Ptr facet = facets.value(XsdFacet::TotalDigits);
650 const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value();
652 if (totalDigitsForUnsignedLongLong(value) > facetValue->toInteger()) {
653 errorMsg = QtXmlPatterns::tr("Unsigned integer content does not match in the totalDigits facet.");
657 if (facets.contains(XsdFacet::Assertion)) {
664 bool XsdTypeChecker::checkConstrainingFacetsDouble(double value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
666 if (facets.contains(XsdFacet::MaximumInclusive)) {
667 const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive);
668 const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsDouble, m_context, m_reflection);
669 if (facetValue->toDouble() < value) {
670 errorMsg = QtXmlPatterns::tr("Double content does not match the maxInclusive facet.");
674 if (facets.contains(XsdFacet::MaximumExclusive)) {
675 const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive);
676 const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsDouble, m_context, m_reflection);
677 if (facetValue->toDouble() <= value) {
678 errorMsg = QtXmlPatterns::tr("Double content does not match the maxExclusive facet.");
682 if (facets.contains(XsdFacet::MinimumInclusive)) {
683 const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive);
684 const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsDouble, m_context, m_reflection);
685 if (facetValue->toDouble() > value) {
686 errorMsg = QtXmlPatterns::tr("Double content does not match the minInclusive facet.");
690 if (facets.contains(XsdFacet::MinimumExclusive)) {
691 const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive);
692 const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsDouble, m_context, m_reflection);
693 if (facetValue->toDouble() >= value) {
694 errorMsg = QtXmlPatterns::tr("Double content does not match the minExclusive facet.");
698 if (facets.contains(XsdFacet::Enumeration)) {
699 const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
700 const DerivedString<TypeString>::Ptr valueStr = DerivedString<TypeString>::fromLexical(m_namePool, QString::number(value));
702 const AtomicValue::List multiValue = facet->multiValue();
704 for (int j = 0; j < multiValue.count(); ++j) {
705 if (XsdSchemaHelper::constructAndCompare(valueStr, AtomicComparator::OperatorEqual, multiValue.at(j), BuiltinTypes::xsDouble, m_context, m_reflection)) {
712 errorMsg = QtXmlPatterns::tr("Double content is not listed in the enumeration facet.");
716 if (facets.contains(XsdFacet::Pattern)) {
717 const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
718 const AtomicValue::List multiValue = facet->multiValue();
720 for (int j = 0; j < multiValue.count(); ++j) {
721 const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
722 const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
723 if (exp.exactMatch(lexicalValue)) {
730 errorMsg = QtXmlPatterns::tr("Double content does not match pattern facet.");
734 if (facets.contains(XsdFacet::Assertion)) {
741 bool XsdTypeChecker::checkConstrainingFacetsDecimal(const AtomicValue::Ptr &value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
743 if (facets.contains(XsdFacet::FractionDigits)) {
744 const XsdFacet::Ptr facet = facets.value(XsdFacet::FractionDigits);
745 const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value();
747 if (fractionDigitsForDecimal(lexicalValue) > facetValue->toInteger()) {
748 errorMsg = QtXmlPatterns::tr("Decimal content does not match in the fractionDigits facet.");
752 if (facets.contains(XsdFacet::TotalDigits)) {
753 const XsdFacet::Ptr facet = facets.value(XsdFacet::TotalDigits);
754 const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value();
756 if (totalDigitsForDecimal(lexicalValue) > facetValue->toInteger()) {
757 errorMsg = QtXmlPatterns::tr("Decimal content does not match in the totalDigits facet.");
762 return checkConstrainingFacetsDouble(value->as<Decimal>()->toDouble(), lexicalValue, facets, errorMsg);
765 bool XsdTypeChecker::checkConstrainingFacetsDateTime(const QDateTime &value, const QString &lexicalValue, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const
767 if (facets.contains(XsdFacet::MaximumInclusive)) {
768 const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive);
769 const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
770 if (facetValue->toDateTime() < value) {
771 errorMsg = QtXmlPatterns::tr("Date time content does not match the maxInclusive facet.");
775 if (facets.contains(XsdFacet::MaximumExclusive)) {
776 const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive);
777 const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
778 if (facetValue->toDateTime() <= value) {
779 errorMsg = QtXmlPatterns::tr("Date time content does not match the maxExclusive facet.");
783 if (facets.contains(XsdFacet::MinimumInclusive)) {
784 const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive);
785 const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
786 if (facetValue->toDateTime() > value) {
787 errorMsg = QtXmlPatterns::tr("Date time content does not match the minInclusive facet.");
791 if (facets.contains(XsdFacet::MinimumExclusive)) {
792 const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive);
793 const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
794 if (facetValue->toDateTime() >= value) {
795 errorMsg = QtXmlPatterns::tr("Date time content does not match the minExclusive facet.");
799 if (facets.contains(XsdFacet::Enumeration)) {
800 const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
802 const AtomicValue::List multiValue = facet->multiValue();
804 for (int j = 0; j < multiValue.count(); ++j) {
805 const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
806 if (facetValue->toDateTime() == value) {
813 errorMsg = QtXmlPatterns::tr("Date time content is not listed in the enumeration facet.");
817 if (facets.contains(XsdFacet::Pattern)) {
818 const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
819 const AtomicValue::List multiValue = facet->multiValue();
821 for (int j = 0; j < multiValue.count(); ++j) {
822 const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
823 const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
824 if (exp.exactMatch(lexicalValue)) {
831 errorMsg = QtXmlPatterns::tr("Date time content does not match pattern facet.");
839 bool XsdTypeChecker::checkConstrainingFacetsDuration(const AtomicValue::Ptr&, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
841 if (facets.contains(XsdFacet::MaximumInclusive)) {
842 const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive);
843 const DerivedString<TypeString>::Ptr value = DerivedString<TypeString>::fromLexical(m_namePool, lexicalValue);
845 if (XsdSchemaHelper::constructAndCompare(facets.value(XsdFacet::MaximumInclusive)->value(), AtomicComparator::OperatorLessThan, value, BuiltinTypes::xsDuration, m_context, m_reflection)) {
846 errorMsg = QtXmlPatterns::tr("Duration content does not match the maxInclusive facet.");
850 if (facets.contains(XsdFacet::MaximumExclusive)) {
851 const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive);
852 const DerivedString<TypeString>::Ptr value = DerivedString<TypeString>::fromLexical(m_namePool, lexicalValue);
854 if (XsdSchemaHelper::constructAndCompare(facets.value(XsdFacet::MaximumExclusive)->value(), AtomicComparator::OperatorLessOrEqual, value, BuiltinTypes::xsDuration, m_context, m_reflection)) {
855 errorMsg = QtXmlPatterns::tr("Duration content does not match the maxExclusive facet.");
859 if (facets.contains(XsdFacet::MinimumInclusive)) {
860 const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive);
861 const DerivedString<TypeString>::Ptr value = DerivedString<TypeString>::fromLexical(m_namePool, lexicalValue);
863 if (XsdSchemaHelper::constructAndCompare(facets.value(XsdFacet::MinimumInclusive)->value(), AtomicComparator::OperatorGreaterThan, value, BuiltinTypes::xsDuration, m_context, m_reflection)) {
864 errorMsg = QtXmlPatterns::tr("Duration content does not match the minInclusive facet.");
868 if (facets.contains(XsdFacet::MinimumExclusive)) {
869 const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive);
870 const DerivedString<TypeString>::Ptr value = DerivedString<TypeString>::fromLexical(m_namePool, lexicalValue);
872 if (XsdSchemaHelper::constructAndCompare(facets.value(XsdFacet::MinimumExclusive)->value(), AtomicComparator::OperatorGreaterOrEqual, value, BuiltinTypes::xsDuration, m_context, m_reflection)) {
873 errorMsg = QtXmlPatterns::tr("Duration content does not match the minExclusive facet.");
877 if (facets.contains(XsdFacet::Enumeration)) {
878 const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
879 const DerivedString<TypeString>::Ptr value = DerivedString<TypeString>::fromLexical(m_namePool, lexicalValue);
881 const AtomicValue::List multiValue = facet->multiValue();
883 for (int j = 0; j < multiValue.count(); ++j) {
884 if (XsdSchemaHelper::constructAndCompare(multiValue.at(j), AtomicComparator::OperatorEqual, value, BuiltinTypes::xsDuration, m_context, m_reflection)) {
891 errorMsg = QtXmlPatterns::tr("Duration content is not listed in the enumeration facet.");
895 if (facets.contains(XsdFacet::Pattern)) {
896 const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
897 const AtomicValue::List multiValue = facet->multiValue();
899 for (int j = 0; j < multiValue.count(); ++j) {
900 const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
901 const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
902 if (exp.exactMatch(lexicalValue)) {
909 errorMsg = QtXmlPatterns::tr("Duration content does not match pattern facet.");
913 if (facets.contains(XsdFacet::Assertion)) {
920 bool XsdTypeChecker::checkConstrainingFacetsBoolean(bool, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
922 if (facets.contains(XsdFacet::Pattern)) {
923 const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
924 const AtomicValue::List multiValue = facet->multiValue();
926 for (int j = 0; j < multiValue.count(); ++j) {
927 const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
928 const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
929 if (exp.exactMatch(lexicalValue)) {
936 errorMsg = QtXmlPatterns::tr("Boolean content does not match pattern facet.");
940 if (facets.contains(XsdFacet::Assertion)) {
947 bool XsdTypeChecker::checkConstrainingFacetsBinary(const QByteArray &value, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const
949 if (facets.contains(XsdFacet::Length)) {
950 const XsdFacet::Ptr facet = facets.value(XsdFacet::Length);
951 const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
952 if (length->toInteger() != value.length()) {
953 errorMsg = QtXmlPatterns::tr("Binary content does not match the length facet.");
957 if (facets.contains(XsdFacet::MinimumLength)) {
958 const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumLength);
959 const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
960 if (length->toInteger() > value.length()) {
961 errorMsg = QtXmlPatterns::tr("Binary content does not match the minLength facet.");
965 if (facets.contains(XsdFacet::MaximumLength)) {
966 const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumLength);
967 const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
968 if (length->toInteger() < value.length()) {
969 errorMsg = QtXmlPatterns::tr("Binary content does not match the maxLength facet.");
973 if (facets.contains(XsdFacet::Enumeration)) {
974 const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
975 const AtomicValue::List multiValue = facet->multiValue();
977 for (int j = 0; j < multiValue.count(); ++j) {
978 const Base64Binary::Ptr binary = ValueFactory::fromLexical(multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
979 const QByteArray facetValue = binary->as<Base64Binary>()->asByteArray();
980 if (value == facetValue) {
987 errorMsg = QtXmlPatterns::tr("Binary content is not listed in the enumeration facet.");
991 if (facets.contains(XsdFacet::Pattern)) {
994 if (facets.contains(XsdFacet::Assertion)) {
1001 bool XsdTypeChecker::checkConstrainingFacetsQName(const QXmlName &value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
1003 if (facets.contains(XsdFacet::Length)) {
1006 if (facets.contains(XsdFacet::MinimumLength)) {
1009 if (facets.contains(XsdFacet::MaximumLength)) {
1012 if (facets.contains(XsdFacet::Enumeration)) {
1013 if (!XPathHelper::isQName(lexicalValue)) {
1014 errorMsg = QtXmlPatterns::tr("Invalid QName content: %1.").arg(formatData(lexicalValue));
1018 const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
1019 const AtomicValue::List multiValue = facet->multiValue();
1021 for (int j = 0; j < multiValue.count(); ++j) {
1022 const QXmlName facetValue = multiValue.at(j)->as<QNameValue>()->qName();
1024 if (value == facetValue) {
1031 errorMsg = QtXmlPatterns::tr("QName content is not listed in the enumeration facet.");
1035 if (facets.contains(XsdFacet::Pattern)) {
1036 const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
1037 const AtomicValue::List multiValue = facet->multiValue();
1039 for (int j = 0; j < multiValue.count(); ++j) {
1040 const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
1041 const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
1042 if (exp.exactMatch(lexicalValue)) {
1049 errorMsg = QtXmlPatterns::tr("QName content does not match pattern facet.");
1053 if (facets.contains(XsdFacet::Assertion)) {
1060 bool XsdTypeChecker::checkConstrainingFacetsNotation(const QXmlName &value, const XsdFacet::Hash &facets, QString &errorMsg) const
1062 if (facets.contains(XsdFacet::Length)) {
1063 // deprecated by spec
1065 if (facets.contains(XsdFacet::MinimumLength)) {
1066 // deprecated by spec
1068 if (facets.contains(XsdFacet::MaximumLength)) {
1069 // deprecated by spec
1071 if (facets.contains(XsdFacet::Enumeration)) {
1072 const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
1073 const AtomicValue::List multiValue = facet->multiValue();
1075 for (int j = 0; j < multiValue.count(); ++j) {
1076 const QXmlName facetValue = multiValue.at(j)->as<QNameValue>()->qName();
1078 if (value == facetValue) {
1085 errorMsg = QtXmlPatterns::tr("Notation content is not listed in the enumeration facet.");
1089 if (facets.contains(XsdFacet::Pattern)) {
1092 if (facets.contains(XsdFacet::Assertion)) {
1099 bool XsdTypeChecker::checkConstrainingFacetsList(const QStringList &values, const QString &lexicalValue, const AnySimpleType::Ptr &itemType, const XsdFacet::Hash &facets, QString &errorMsg) const
1101 if (facets.contains(XsdFacet::Length)) {
1102 const DerivedInteger<TypeNonNegativeInteger>::Ptr value = facets.value(XsdFacet::Length)->value();
1103 if (value->toInteger() != values.count()) {
1104 errorMsg = QtXmlPatterns::tr("List content does not match length facet.");
1108 if (facets.contains(XsdFacet::MinimumLength)) {
1109 const DerivedInteger<TypeNonNegativeInteger>::Ptr value = facets.value(XsdFacet::MinimumLength)->value();
1110 if (value->toInteger() > values.count()) {
1111 errorMsg = QtXmlPatterns::tr("List content does not match minLength facet.");
1115 if (facets.contains(XsdFacet::MaximumLength)) {
1116 const DerivedInteger<TypeNonNegativeInteger>::Ptr value = facets.value(XsdFacet::MaximumLength)->value();
1117 if (value->toInteger() < values.count()) {
1118 errorMsg = QtXmlPatterns::tr("List content does not match maxLength facet.");
1122 if (facets.contains(XsdFacet::Enumeration)) {
1126 // we have to handle lists with QName derived items differently
1127 if (BuiltinTypes::xsQName->wxsTypeMatches(itemType) || BuiltinTypes::xsNOTATION->wxsTypeMatches(itemType)) {
1128 // first convert the string values from the instance document to a list of QXmlName
1129 QList<QXmlName> instanceValues;
1130 for (int i = 0; i < values.count(); ++i) {
1131 instanceValues.append(convertToQName(values.at(i)));
1134 // fetch the values from the facet and create a list of QXmlNames for each of them
1135 const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
1137 const AtomicValue::List multiValue = facet->multiValue();
1138 for (int i = 0; i < multiValue.count(); ++i) {
1139 const QStringList facetValueList = multiValue.at(i)->as<DerivedString<TypeString> >()->stringValue().split(QLatin1Char(' '), QString::SkipEmptyParts);
1141 // create the list of atomic string values
1142 QList<QXmlName> facetValues;
1143 for (int j = 0; j < facetValueList.count(); ++j) {
1144 facetValues.append(convertToQName(facetValueList.at(j)));
1147 // check if both lists have the same length
1148 if (instanceValues.count() != facetValues.count())
1151 // check if both lists are equal, that means the contain equal items in the same order
1152 bool matchesAll = true;
1153 for (int j = 0; j < instanceValues.count(); ++j) {
1154 if (instanceValues.at(j) != facetValues.at(j)) {
1166 // first convert the string values from the instance document to atomic values of type string
1167 AtomicValue::List instanceValues;
1168 for (int i = 0; i < values.count(); ++i) {
1169 instanceValues.append(DerivedString<TypeString>::fromLexical(m_namePool, values.at(i)));
1172 // fetch the values from the facet and create a list of atomic string values for each of them
1173 const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
1175 const AnySimpleType::Ptr targetType = comparableType(itemType);
1177 const AtomicValue::List multiValue = facet->multiValue();
1178 for (int i = 0; i < multiValue.count(); ++i) {
1179 const QStringList facetValueList = multiValue.at(i)->as<DerivedString<TypeString> >()->stringValue().split(QLatin1Char(' '), QString::SkipEmptyParts);
1181 // create the list of atomic string values
1182 AtomicValue::List facetValues;
1183 for (int j = 0; j < facetValueList.count(); ++j) {
1184 facetValues.append(DerivedString<TypeString>::fromLexical(m_namePool, facetValueList.at(j)));
1187 // check if both lists have the same length
1188 if (instanceValues.count() != facetValues.count())
1191 // check if both lists are equal, that means the contain equal items in the same order
1192 bool matchesAll = true;
1193 for (int j = 0; j < instanceValues.count(); ++j) {
1194 if (!XsdSchemaHelper::constructAndCompare(instanceValues.at(j), AtomicComparator::OperatorEqual, facetValues.at(j), targetType, m_context, m_reflection)) {
1208 errorMsg = QtXmlPatterns::tr("List content is not listed in the enumeration facet.");
1212 if (facets.contains(XsdFacet::Pattern)) {
1213 const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
1214 const AtomicValue::List multiValue = facet->multiValue();
1216 for (int j = 0; j < multiValue.count(); ++j) {
1217 const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
1218 const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
1219 if (exp.exactMatch(lexicalValue)) {
1226 errorMsg = QtXmlPatterns::tr("List content does not match pattern facet.");
1230 if (facets.contains(XsdFacet::Assertion)) {
1237 bool XsdTypeChecker::checkConstrainingFacetsUnion(const QString &value, const QString &lexicalValue, const XsdSimpleType::Ptr &simpleType, const XsdFacet::Hash &facets, QString &errorMsg) const
1239 if (facets.contains(XsdFacet::Enumeration)) {
1240 const AnySimpleType::List memberTypes = simpleType->memberTypes();
1242 const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
1244 // convert the instance value into an atomic string value
1245 const DerivedString<TypeString>::Ptr valueString = DerivedString<TypeString>::fromLexical(m_namePool, value);
1247 // collect the facet values into a list of atomic string values
1248 const AtomicValue::List facetValues = facet->multiValue();
1250 // compare the instance value against the facetValues for each member type and
1251 // search for a match
1254 for (int i = 0; i < memberTypes.count(); ++i) {
1255 const AnySimpleType::Ptr targetType = comparableType(memberTypes.at(i));
1256 for (int j = 0; j < facetValues.count(); ++j) {
1257 if (XsdSchemaHelper::constructAndCompare(valueString, AtomicComparator::OperatorEqual, facetValues.at(j), targetType, m_context, m_reflection)) {
1265 errorMsg = QtXmlPatterns::tr("Union content is not listed in the enumeration facet.");
1269 if (facets.contains(XsdFacet::Pattern)) {
1270 const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
1271 const AtomicValue::List multiValue = facet->multiValue();
1273 for (int j = 0; j < multiValue.count(); ++j) {
1274 const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
1275 const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
1276 if (exp.exactMatch(lexicalValue)) {
1283 errorMsg = QtXmlPatterns::tr("Union content does not match pattern facet.");
1287 if (facets.contains(XsdFacet::Assertion)) {
1294 AtomicValue::Ptr XsdTypeChecker::fromLexical(const QString &value, const SchemaType::Ptr &type, const ReportContext::Ptr &context, const SourceLocationReflection *const reflection) const
1296 if (type->name(m_namePool) == BuiltinTypes::xsNOTATION->name(m_namePool) || type->name(m_namePool) == BuiltinTypes::xsQName->name(m_namePool)) {
1297 if (value.simplified().isEmpty())
1298 return ValidationError::createError(QtXmlPatterns::tr("Data of type %1 are not allowed to be empty.").arg(formatType(m_namePool, BuiltinTypes::xsNOTATION)));
1300 const QXmlName valueName = convertToQName(value);
1301 return QNameValue::fromValue(m_namePool, valueName);
1303 return ValueFactory::fromLexical(value, type, context, reflection);
1307 QXmlName XsdTypeChecker::convertToQName(const QString &name) const
1309 const int pos = name.indexOf(QLatin1Char(':'));
1311 QXmlName::PrefixCode prefixCode = 0;
1312 QXmlName::NamespaceCode namespaceCode;
1313 QXmlName::LocalNameCode localNameCode;
1315 prefixCode = m_context->namePool()->allocatePrefix(name.left(pos));
1316 namespaceCode = StandardNamespaces::empty;
1317 for (int i = 0; i < m_namespaceBindings.count(); ++i) {
1318 if (m_namespaceBindings.at(i).prefix() == prefixCode) {
1319 namespaceCode = m_namespaceBindings.at(i).namespaceURI();
1323 localNameCode = m_context->namePool()->allocateLocalName(name.mid(pos + 1));
1325 prefixCode = StandardPrefixes::empty;
1326 namespaceCode = StandardNamespaces::empty;
1327 for (int i = 0; i < m_namespaceBindings.count(); ++i) {
1328 if (m_namespaceBindings.at(i).prefix() == prefixCode) {
1329 namespaceCode = m_namespaceBindings.at(i).namespaceURI();
1333 localNameCode = m_context->namePool()->allocateLocalName(name);
1336 return QXmlName(namespaceCode, localNameCode, prefixCode);