Qt 4.8
qxsdtypechecker.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qxsdtypechecker_p.h"
43 
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"
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"
60 #include "qabstractfloat_p.h"
61 
62 #include "qxsdschemadebugger_p.h"
63 
65 
66 using namespace QPatternist;
67 
69  : m_sourceLocation(location)
70 {
71 }
72 
74 {
75  return this;
76 }
77 
79 {
80  return m_sourceLocation;
81 }
82 
83 
85 {
86  if (!type->isDefinedBySchema()) {
87  return type;
88  } else {
89  const XsdSimpleType::Ptr simpleType(type);
90  if (type->category() == SchemaType::SimpleTypeAtomic) {
91  return simpleType->primitiveType();
92  } else if (type->category() == SchemaType::SimpleTypeList) {
93  return simpleType->itemType();
94  } else if (type->category() == SchemaType::SimpleTypeUnion) {
95  return simpleType->memberTypes().first();
96  }
97  }
98 
99  Q_ASSERT(false);
100  return AnySimpleType::Ptr();
101 }
102 
103 static int totalDigitsForSignedLongLong(long long value)
104 {
105  QString number = QString::number(value);
106  if (number.startsWith(QLatin1Char('-')))
107  number = number.mid(1);
108 
109  return number.length();
110 }
111 
112 static int totalDigitsForUnsignedLongLong(unsigned long long value)
113 {
114  const QString number = QString::number(value);
115  return number.length();
116 }
117 
118 static int totalDigitsForDecimal(const QString &lexicalValue)
119 {
120  const QLatin1Char zeroChar('0');
121  const int length = lexicalValue.length() - 1;
122 
123  // strip leading zeros
124  int pos = 0;
125  while (lexicalValue.at(pos) == zeroChar && (pos != length))
126  pos++;
127 
128  QString value = lexicalValue.mid(pos);
129 
130  // if contains '.' strip trailing zeros
131  if (value.contains(QLatin1Char('.'))) {
132  pos = value.length() - 1;
133  while (value.at(pos) == zeroChar) {
134  pos--;
135  }
136 
137  value = value.left(pos + 1);
138  }
139 
140  // check number of digits of remaining string
141  int totalDigits = 0;
142  for (int i = 0; i < value.count(); ++i)
143  if (value.at(i).isDigit())
144  ++totalDigits;
145 
146  if (totalDigits == 0)
147  totalDigits = 1;
148 
149  return totalDigits;
150 }
151 
152 static int fractionDigitsForDecimal(const QString &lexicalValue)
153 {
154  // we use the lexical value here, as the conversion to double might strip
155  // away decimal positions
156 
157  QString trimmedValue(lexicalValue.trimmed());
158  const int pos = trimmedValue.indexOf(QLatin1Char('.'));
159  if (pos == -1) // no '.' -> 0 fraction digits
160  return 0;
161  else
162  return (trimmedValue.length() - pos - 1);
163 }
164 
166  : m_context(context)
167  , m_namePool(m_context->namePool())
168  , m_namespaceBindings(namespaceBindings)
169  , m_reflection(new XsdSchemaSourceLocationReflection(location))
170 {
171 }
172 
174 {
175  delete m_reflection;
176 }
177 
179 {
180  if (!facets.contains(XsdFacet::WhiteSpace))
181  return value;
182 
183  const XsdFacet::Ptr whiteSpaceFacet = facets.value(XsdFacet::WhiteSpace);
184 
185  const DerivedString<TypeString>::Ptr facetValue = whiteSpaceFacet->value();
186  const QString stringValue = facetValue->stringValue();
188  return value;
189  else if (stringValue == XsdSchemaToken::toString(XsdSchemaToken::Replace)) {
190  QString newValue(value);
191  newValue.replace(QLatin1Char('\t'), QLatin1Char(' '));
192  newValue.replace(QLatin1Char('\n'), QLatin1Char(' '));
193  newValue.replace(QLatin1Char('\r'), QLatin1Char(' '));
194 
195  return newValue;
196  } else if (stringValue == XsdSchemaToken::toString(XsdSchemaToken::Collapse)) {
197  return value.simplified();
198  }
199 
200  return value;
201 }
202 
204 {
205  if (!type)
206  return XsdFacet::Hash();
207 
208  const XsdFacet::Hash baseFacets = mergedFacetsForType(type->wxsSuperType(), context);
209  const XsdFacet::Hash facets = context->facetsForType(type);
210 
211  XsdFacet::Hash result = baseFacets;
212  XsdFacet::HashIterator it(facets);
213  while (it.hasNext()) {
214  it.next();
215 
216  result.insert(it.key(), it.value());
217  }
218 
219  return result;
220 }
221 
222 bool XsdTypeChecker::isValidString(const QString &normalizedString, const AnySimpleType::Ptr &type, QString &errorMsg, AnySimpleType::Ptr *boundType) const
223 {
225  if (boundType)
226  *boundType = type;
227 
228  return true;
229  }
230 
231  if (!type->isDefinedBySchema()) {
232  // special QName check
234  if (!XPathHelper::isQName(normalizedString)) {
235  errorMsg = QtXmlPatterns::tr("%1 is not valid according to %2.").arg(formatData(normalizedString)).arg(formatType(m_namePool, type));
236  return false;
237  }
238  }
239 
240  const AtomicValue::Ptr value = fromLexical(normalizedString, type, m_context, m_reflection);
241  if (value->hasError()) {
242  errorMsg = QtXmlPatterns::tr("%1 is not valid according to %2.").arg(formatData(normalizedString)).arg(formatType(m_namePool, type));
243  return false;
244  }
245 
246  if (!checkConstrainingFacets(value, normalizedString, type, errorMsg)) {
247  return false;
248  }
249 
250  if (boundType)
251  *boundType = type;
252 
253  } else {
254  const XsdSimpleType::Ptr simpleType(type);
255 
256  if (simpleType->category() == XsdSimpleType::SimpleTypeAtomic) {
257  AnySimpleType::Ptr targetType = simpleType->primitiveType();
258  if (!simpleType->wxsSuperType()->isDefinedBySchema())
259  targetType = simpleType->wxsSuperType();
260 
261  const AtomicValue::Ptr value = fromLexical(normalizedString, targetType, m_context, m_reflection);
262  if (value->hasError()) {
263  errorMsg = QtXmlPatterns::tr("%1 is not valid according to %2.").arg(formatData(normalizedString)).arg(formatType(m_namePool, targetType));
264  return false;
265  }
266 
267  if (!checkConstrainingFacets(value, normalizedString, type, errorMsg)) {
268  return false;
269  }
270 
271  if (boundType)
272  *boundType = type;
273 
274  } else if (simpleType->category() == XsdSimpleType::SimpleTypeList) {
275  QStringList entries = normalizedString.split(QLatin1Char(' '), QString::SkipEmptyParts);
276  for (int i = 0; i < entries.count(); ++i) {
277  entries[i] = normalizedValue(entries.at(i), mergedFacetsForType(simpleType->itemType(), m_context));
278  }
279 
280  if (!checkConstrainingFacetsList(entries, normalizedString, simpleType->itemType(), mergedFacetsForType(simpleType, m_context), errorMsg)) {
281  return false;
282  }
283 
284  for (int i = 0; i < entries.count(); ++i) {
285  if (!isValidString(entries.at(i), simpleType->itemType(), errorMsg)) {
286  return false;
287  }
288  }
289 
290  if (boundType)
291  *boundType = simpleType->itemType();
292 
293  } else if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) {
294  if (!checkConstrainingFacetsUnion(normalizedString, normalizedString, simpleType, mergedFacetsForType(simpleType, m_context), errorMsg)) {
295  return false;
296  }
297 
298  const AnySimpleType::List memberTypes = simpleType->memberTypes();
299 
300  bool foundValidType = false;
301  for (int i = 0; i < memberTypes.count(); ++i) {
302  const XsdFacet::Hash mergedFacets = mergedFacetsForType(memberTypes.at(i), m_context);
303  if (isValidString(normalizedValue(normalizedString, mergedFacets), memberTypes.at(i), errorMsg)) {
304  foundValidType = true;
305 
306  if (boundType)
307  *boundType = memberTypes.at(i);
308 
309  break;
310  }
311  }
312 
313  if (!foundValidType) {
314  return false;
315  }
316  }
317  }
318 
319  return true;
320 }
321 
322 bool XsdTypeChecker::valuesAreEqual(const QString &value, const QString &otherValue, const AnySimpleType::Ptr &type) const
323 {
324  const AnySimpleType::Ptr targetType = comparableType(type);
325 
326  // if the type is xs:anySimpleType we just do string comparison...
328  return (value == otherValue);
329 
331  const QXmlName valueName = convertToQName(value);
332  const QXmlName otherValueName = convertToQName(otherValue);
333 
334  if (valueName == otherValueName)
335  return true;
336  }
337 
338  if (type->category() == SchemaType::SimpleTypeAtomic) {
339  // ... otherwise we use the casting platform for value comparison
342 
344  } else if (type->category() == SchemaType::SimpleTypeList) {
346  const QStringList otherValues = otherValue.split(QLatin1Char(' '), QString::SkipEmptyParts);
347  if (values.count() != otherValues.count())
348  return false;
349 
350  for (int i = 0; i < values.count(); ++i) {
351  if (!valuesAreEqual(values.at(i), otherValues.at(i), XsdSimpleType::Ptr(type)->itemType()))
352  return false;
353  }
354 
355  return true;
356  } else if (type->category() == SchemaType::SimpleTypeUnion) {
357  const AnySimpleType::List memberTypes = XsdSimpleType::Ptr(type)->memberTypes();
358  for (int i = 0; i < memberTypes.count(); ++i) {
359  if (valuesAreEqual(value, otherValue, memberTypes.at(i))) {
360  return true;
361  }
362  }
363 
364  return false;
365  }
366 
367  return false;
368 }
369 
370 bool XsdTypeChecker::checkConstrainingFacets(const AtomicValue::Ptr &value, const QString &lexicalValue, const AnySimpleType::Ptr &type, QString &errorMsg) const
371 {
372  const XsdFacet::Hash facets = mergedFacetsForType(type, m_context);
373 
376  return checkConstrainingFacetsString(value->stringValue(), facets, BuiltinTypes::xsString, errorMsg);
377  } else if (BuiltinTypes::xsAnyURI->wxsTypeMatches(type)) {
378  return checkConstrainingFacetsString(value->stringValue(), facets, BuiltinTypes::xsAnyURI, errorMsg);
379  } else if (BuiltinTypes::xsNOTATION->wxsTypeMatches(type)) {
380  return checkConstrainingFacetsNotation(value->as<QNameValue>()->qName(), facets, errorMsg);
381  } else if (BuiltinTypes::xsUnsignedByte->wxsTypeMatches(type) ||
382  BuiltinTypes::xsUnsignedInt->wxsTypeMatches(type) ||
383  BuiltinTypes::xsUnsignedLong->wxsTypeMatches(type) ||
384  BuiltinTypes::xsUnsignedShort->wxsTypeMatches(type)) {
385  return checkConstrainingFacetsUnsignedInteger(value->as<Numeric>()->toUnsignedInteger(), lexicalValue, facets, errorMsg);
386  } else if (BuiltinTypes::xsInteger->wxsTypeMatches(type)) {
387  return checkConstrainingFacetsSignedInteger(value->as<Numeric>()->toInteger(), lexicalValue, facets, errorMsg);
388  } else if (BuiltinTypes::xsFloat->wxsTypeMatches(type) ||
389  BuiltinTypes::xsDouble->wxsTypeMatches(type)) {
390  return checkConstrainingFacetsDouble(value->as<Numeric>()->toDouble(), lexicalValue, facets, errorMsg);
391  } else if (BuiltinTypes::xsDecimal->wxsTypeMatches(type)) {
392  return checkConstrainingFacetsDecimal(value, lexicalValue, facets, errorMsg);
393  } else if (BuiltinTypes::xsDateTime->wxsTypeMatches(type)) {
394  return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsDateTime, errorMsg);
395  } else if (BuiltinTypes::xsDate->wxsTypeMatches(type)) {
396  return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsDate, errorMsg);
397  } else if (BuiltinTypes::xsGYear->wxsTypeMatches(type)) {
398  return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGYear, errorMsg);
399  } else if (BuiltinTypes::xsGYearMonth->wxsTypeMatches(type)) {
400  return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGYearMonth, errorMsg);
401  } else if (BuiltinTypes::xsGMonth->wxsTypeMatches(type)) {
402  return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGMonth, errorMsg);
403  } else if (BuiltinTypes::xsGMonthDay->wxsTypeMatches(type)) {
404  return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGMonthDay, errorMsg);
405  } else if (BuiltinTypes::xsGDay->wxsTypeMatches(type)) {
406  return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGDay, errorMsg);
407  } else if (BuiltinTypes::xsTime->wxsTypeMatches(type)) {
408  return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsTime, errorMsg);
409  } else if (BuiltinTypes::xsDuration->wxsTypeMatches(type)) {
410  return checkConstrainingFacetsDuration(value, lexicalValue, facets, errorMsg);
411  } else if (BuiltinTypes::xsBoolean->wxsTypeMatches(type)) {
412  return checkConstrainingFacetsBoolean(value->as<Boolean>()->value(), lexicalValue, facets, errorMsg);
413  } else if (BuiltinTypes::xsHexBinary->wxsTypeMatches(type)) {
415  } else if (BuiltinTypes::xsBase64Binary->wxsTypeMatches(type)) {
417  } else if (BuiltinTypes::xsQName->wxsTypeMatches(type)) {
418  return checkConstrainingFacetsQName(value->as<QNameValue>()->qName(), lexicalValue, facets, errorMsg);
419  }
420 
421  return true;
422 }
423 
424 bool XsdTypeChecker::checkConstrainingFacetsString(const QString &value, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const
425 {
426  if (facets.contains(XsdFacet::Length)) {
427  const XsdFacet::Ptr facet = facets.value(XsdFacet::Length);
428  const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
429  if (length->toInteger() != value.length()) {
430  errorMsg = QtXmlPatterns::tr("String content does not match the length facet.");
431  return false;
432  }
433  }
434  if (facets.contains(XsdFacet::MinimumLength)) {
435  const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumLength);
436  const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
437  if (length->toInteger() > value.length()) {
438  errorMsg = QtXmlPatterns::tr("String content does not match the minLength facet.");
439  return false;
440  }
441  }
442  if (facets.contains(XsdFacet::MaximumLength)) {
443  const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumLength);
444  const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
445  if (length->toInteger() < value.length()) {
446  errorMsg = QtXmlPatterns::tr("String content does not match the maxLength facet.");
447  return false;
448  }
449  }
450  if (facets.contains(XsdFacet::Pattern)) {
451  const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
452  const AtomicValue::List multiValue = facet->multiValue();
453  bool found = false;
454  for (int j = 0; j < multiValue.count(); ++j) {
455  const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
457  if (exp.exactMatch(value)) {
458  found = true;
459  break;
460  }
461  }
462 
463  if (!found) {
464  errorMsg = QtXmlPatterns::tr("String content does not match pattern facet.");
465  return false;
466  }
467  }
468  if (facets.contains(XsdFacet::Enumeration)) {
469  const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
471 
472  const AtomicValue::List multiValue = facet->multiValue();
473  bool found = false;
474  for (int j = 0; j < multiValue.count(); ++j) {
476  found = true;
477  break;
478  }
479  }
480 
481  if (!found) {
482  errorMsg = QtXmlPatterns::tr("String content is not listed in the enumeration facet.");
483  return false;
484  }
485  }
486  if (facets.contains(XsdFacet::Assertion)) {
487  //TODO: implement
488  }
489 
490  return true;
491 }
492 
493 bool XsdTypeChecker::checkConstrainingFacetsSignedInteger(long long value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
494 {
495  if (facets.contains(XsdFacet::MaximumInclusive)) {
496  const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive);
497  const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsLong, m_context, m_reflection);
498  if (facetValue->toInteger() < value) {
499  errorMsg = QtXmlPatterns::tr("Signed integer content does not match the maxInclusive facet.");
500  return false;
501  }
502  }
503  if (facets.contains(XsdFacet::MaximumExclusive)) {
504  const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive);
505  const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsLong, m_context, m_reflection);
506  if (facetValue->toInteger() <= value) {
507  errorMsg = QtXmlPatterns::tr("Signed integer content does not match the maxExclusive facet.");
508  return false;
509  }
510  }
511  if (facets.contains(XsdFacet::MinimumInclusive)) {
512  const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive);
513  const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsLong, m_context, m_reflection);
514  if (facetValue->toInteger() > value) {
515  errorMsg = QtXmlPatterns::tr("Signed integer content does not match the minInclusive facet.");
516  return false;
517  }
518  }
519  if (facets.contains(XsdFacet::MinimumExclusive)) {
520  const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive);
521  const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsLong, m_context, m_reflection);
522  if (facetValue->toInteger() >= value) {
523  errorMsg = QtXmlPatterns::tr("Signed integer content does not match the minExclusive facet.");
524  return false;
525  }
526  }
527  if (facets.contains(XsdFacet::Enumeration)) {
528  const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
530 
531  const AtomicValue::List multiValue = facet->multiValue();
532  bool found = false;
533  for (int j = 0; j < multiValue.count(); ++j) {
535  found = true;
536  break;
537  }
538  }
539 
540  if (!found) {
541  errorMsg = QtXmlPatterns::tr("Signed integer content is not listed in the enumeration facet.");
542  return false;
543  }
544  }
545  if (facets.contains(XsdFacet::Pattern)) {
546  const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
547  const AtomicValue::List multiValue = facet->multiValue();
548  bool found = false;
549  for (int j = 0; j < multiValue.count(); ++j) {
550  const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
552  if (exp.exactMatch(lexicalValue)) {
553  found = true;
554  break;
555  }
556  }
557 
558  if (!found) {
559  errorMsg = QtXmlPatterns::tr("Signed integer content does not match pattern facet.");
560  return false;
561  }
562  }
563  if (facets.contains(XsdFacet::TotalDigits)) {
564  const XsdFacet::Ptr facet = facets.value(XsdFacet::TotalDigits);
565  const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value();
566 
567  if (totalDigitsForSignedLongLong(value) > facetValue->toInteger()) {
568  errorMsg = QtXmlPatterns::tr("Signed integer content does not match in the totalDigits facet.");
569  return false;
570  }
571  }
572  if (facets.contains(XsdFacet::Assertion)) {
573  //TODO: implement
574  }
575 
576  return true;
577 }
578 
579 bool XsdTypeChecker::checkConstrainingFacetsUnsignedInteger(unsigned long long value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
580 {
581  if (facets.contains(XsdFacet::MaximumInclusive)) {
582  const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive);
583  const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsUnsignedLong, m_context, m_reflection);
584  if (facetValue->toUnsignedInteger() < value) {
585  errorMsg = QtXmlPatterns::tr("Unsigned integer content does not match the maxInclusive facet.");
586  return false;
587  }
588  }
589  if (facets.contains(XsdFacet::MaximumExclusive)) {
590  const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive);
591  const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsUnsignedLong, m_context, m_reflection);
592  if (facetValue->toUnsignedInteger() <= value) {
593  errorMsg = QtXmlPatterns::tr("Unsigned integer content does not match the maxExclusive facet.");
594  return false;
595  }
596  }
597  if (facets.contains(XsdFacet::MinimumInclusive)) {
598  const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive);
599  const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsUnsignedLong, m_context, m_reflection);
600  if (facetValue->toUnsignedInteger() > value) {
601  errorMsg = QtXmlPatterns::tr("Unsigned integer content does not match the minInclusive facet.");
602  return false;
603  }
604  }
605  if (facets.contains(XsdFacet::MinimumExclusive)) {
606  const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive);
607  const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsUnsignedLong, m_context, m_reflection);
608  if (facetValue->toUnsignedInteger() >= value) {
609  errorMsg = QtXmlPatterns::tr("Unsigned integer content does not match the minExclusive facet.");
610  return false;
611  }
612  }
613  if (facets.contains(XsdFacet::Enumeration)) {
614  const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
616 
617  const AtomicValue::List multiValue = facet->multiValue();
618  bool found = false;
619  for (int j = 0; j < multiValue.count(); ++j) {
621  found = true;
622  break;
623  }
624  }
625 
626  if (!found) {
627  errorMsg = QtXmlPatterns::tr("Unsigned integer content is not listed in the enumeration facet.");
628  return false;
629  }
630  }
631  if (facets.contains(XsdFacet::Pattern)) {
632  const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
633  const AtomicValue::List multiValue = facet->multiValue();
634  bool found = false;
635  for (int j = 0; j < multiValue.count(); ++j) {
636  const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
638  if (exp.exactMatch(lexicalValue)) {
639  found = true;
640  break;
641  }
642  }
643 
644  if (!found) {
645  errorMsg = QtXmlPatterns::tr("Unsigned integer content does not match pattern facet.");
646  return false;
647  }
648  }
649  if (facets.contains(XsdFacet::TotalDigits)) {
650  const XsdFacet::Ptr facet = facets.value(XsdFacet::TotalDigits);
651  const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value();
652 
653  if (totalDigitsForUnsignedLongLong(value) > facetValue->toInteger()) {
654  errorMsg = QtXmlPatterns::tr("Unsigned integer content does not match in the totalDigits facet.");
655  return false;
656  }
657  }
658  if (facets.contains(XsdFacet::Assertion)) {
659  //TODO: implement
660  }
661 
662  return true;
663 }
664 
665 bool XsdTypeChecker::checkConstrainingFacetsDouble(double value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
666 {
667  if (facets.contains(XsdFacet::MaximumInclusive)) {
668  const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive);
669  const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsDouble, m_context, m_reflection);
670  if (facetValue->toDouble() < value) {
671  errorMsg = QtXmlPatterns::tr("Double content does not match the maxInclusive facet.");
672  return false;
673  }
674  }
675  if (facets.contains(XsdFacet::MaximumExclusive)) {
676  const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive);
677  const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsDouble, m_context, m_reflection);
678  if (facetValue->toDouble() <= value) {
679  errorMsg = QtXmlPatterns::tr("Double content does not match the maxExclusive facet.");
680  return false;
681  }
682  }
683  if (facets.contains(XsdFacet::MinimumInclusive)) {
684  const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive);
685  const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsDouble, m_context, m_reflection);
686  if (facetValue->toDouble() > value) {
687  errorMsg = QtXmlPatterns::tr("Double content does not match the minInclusive facet.");
688  return false;
689  }
690  }
691  if (facets.contains(XsdFacet::MinimumExclusive)) {
692  const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive);
693  const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsDouble, m_context, m_reflection);
694  if (facetValue->toDouble() >= value) {
695  errorMsg = QtXmlPatterns::tr("Double content does not match the minExclusive facet.");
696  return false;
697  }
698  }
699  if (facets.contains(XsdFacet::Enumeration)) {
700  const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
701  const Numeric::Ptr valuePtr = Double::fromValue(value);
702  const DerivedString<TypeString>::Ptr valueStr = DerivedString<TypeString>::fromLexical(m_namePool, valuePtr->stringValue());
703 
704  const AtomicValue::List multiValue = facet->multiValue();
705  bool found = false;
706  for (int j = 0; j < multiValue.count(); ++j) {
708  found = true;
709  break;
710  }
711 
712  // Handle case when both facet and value are NaN separately as equals for NaN returns always false.
713  const Numeric::Ptr facetValue = ValueFactory::fromLexical(multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsDouble, m_context, m_reflection);
714  if (facetValue->isNaN() && valuePtr->isNaN()) {
715  found = true;
716  break;
717  }
718  }
719 
720  if (!found) {
721  errorMsg = QtXmlPatterns::tr("Double content is not listed in the enumeration facet.");
722  return false;
723  }
724  }
725  if (facets.contains(XsdFacet::Pattern)) {
726  const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
727  const AtomicValue::List multiValue = facet->multiValue();
728  bool found = false;
729  for (int j = 0; j < multiValue.count(); ++j) {
730  const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
732  if (exp.exactMatch(lexicalValue)) {
733  found = true;
734  break;
735  }
736  }
737 
738  if (!found) {
739  errorMsg = QtXmlPatterns::tr("Double content does not match pattern facet.");
740  return false;
741  }
742  }
743  if (facets.contains(XsdFacet::Assertion)) {
744  //TODO: implement
745  }
746 
747  return true;
748 }
749 
750 bool XsdTypeChecker::checkConstrainingFacetsDecimal(const AtomicValue::Ptr &value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
751 {
752  if (facets.contains(XsdFacet::FractionDigits)) {
753  const XsdFacet::Ptr facet = facets.value(XsdFacet::FractionDigits);
754  const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value();
755 
756  if (fractionDigitsForDecimal(lexicalValue) > facetValue->toInteger()) {
757  errorMsg = QtXmlPatterns::tr("Decimal content does not match in the fractionDigits facet.");
758  return false;
759  }
760  }
761  if (facets.contains(XsdFacet::TotalDigits)) {
762  const XsdFacet::Ptr facet = facets.value(XsdFacet::TotalDigits);
763  const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value();
764 
765  if (totalDigitsForDecimal(lexicalValue) > facetValue->toInteger()) {
766  errorMsg = QtXmlPatterns::tr("Decimal content does not match in the totalDigits facet.");
767  return false;
768  }
769  }
770 
771  return checkConstrainingFacetsDouble(value->as<Decimal>()->toDouble(), lexicalValue, facets, errorMsg);
772 }
773 
774 bool XsdTypeChecker::checkConstrainingFacetsDateTime(const QDateTime &value, const QString &lexicalValue, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const
775 {
776  if (facets.contains(XsdFacet::MaximumInclusive)) {
777  const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive);
778  const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
779  if (facetValue->toDateTime() < value) {
780  errorMsg = QtXmlPatterns::tr("Date time content does not match the maxInclusive facet.");
781  return false;
782  }
783  }
784  if (facets.contains(XsdFacet::MaximumExclusive)) {
785  const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive);
786  const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
787  if (facetValue->toDateTime() <= value) {
788  errorMsg = QtXmlPatterns::tr("Date time content does not match the maxExclusive facet.");
789  return false;
790  }
791  }
792  if (facets.contains(XsdFacet::MinimumInclusive)) {
793  const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive);
794  const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
795  if (facetValue->toDateTime() > value) {
796  errorMsg = QtXmlPatterns::tr("Date time content does not match the minInclusive facet.");
797  return false;
798  }
799  }
800  if (facets.contains(XsdFacet::MinimumExclusive)) {
801  const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive);
802  const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
803  if (facetValue->toDateTime() >= value) {
804  errorMsg = QtXmlPatterns::tr("Date time content does not match the minExclusive facet.");
805  return false;
806  }
807  }
808  if (facets.contains(XsdFacet::Enumeration)) {
809  const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
810 
811  const AtomicValue::List multiValue = facet->multiValue();
812  bool found = false;
813  for (int j = 0; j < multiValue.count(); ++j) {
814  const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
815  if (facetValue->toDateTime() == value) {
816  found = true;
817  break;
818  }
819  }
820 
821  if (!found) {
822  errorMsg = QtXmlPatterns::tr("Date time content is not listed in the enumeration facet.");
823  return false;
824  }
825  }
826  if (facets.contains(XsdFacet::Pattern)) {
827  const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
828  const AtomicValue::List multiValue = facet->multiValue();
829  bool found = false;
830  for (int j = 0; j < multiValue.count(); ++j) {
831  const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
833  if (exp.exactMatch(lexicalValue)) {
834  found = true;
835  break;
836  }
837  }
838 
839  if (!found) {
840  errorMsg = QtXmlPatterns::tr("Date time content does not match pattern facet.");
841  return false;
842  }
843  }
844 
845  return true;
846 }
847 
848 bool XsdTypeChecker::checkConstrainingFacetsDuration(const AtomicValue::Ptr&, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
849 {
850  if (facets.contains(XsdFacet::MaximumInclusive)) {
851  const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive);
853 
855  errorMsg = QtXmlPatterns::tr("Duration content does not match the maxInclusive facet.");
856  return false;
857  }
858  }
859  if (facets.contains(XsdFacet::MaximumExclusive)) {
860  const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive);
862 
864  errorMsg = QtXmlPatterns::tr("Duration content does not match the maxExclusive facet.");
865  return false;
866  }
867  }
868  if (facets.contains(XsdFacet::MinimumInclusive)) {
869  const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive);
871 
873  errorMsg = QtXmlPatterns::tr("Duration content does not match the minInclusive facet.");
874  return false;
875  }
876  }
877  if (facets.contains(XsdFacet::MinimumExclusive)) {
878  const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive);
880 
882  errorMsg = QtXmlPatterns::tr("Duration content does not match the minExclusive facet.");
883  return false;
884  }
885  }
886  if (facets.contains(XsdFacet::Enumeration)) {
887  const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
889 
890  const AtomicValue::List multiValue = facet->multiValue();
891  bool found = false;
892  for (int j = 0; j < multiValue.count(); ++j) {
894  found = true;
895  break;
896  }
897  }
898 
899  if (!found) {
900  errorMsg = QtXmlPatterns::tr("Duration content is not listed in the enumeration facet.");
901  return false;
902  }
903  }
904  if (facets.contains(XsdFacet::Pattern)) {
905  const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
906  const AtomicValue::List multiValue = facet->multiValue();
907  bool found = false;
908  for (int j = 0; j < multiValue.count(); ++j) {
909  const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
911  if (exp.exactMatch(lexicalValue)) {
912  found = true;
913  break;
914  }
915  }
916 
917  if (!found) {
918  errorMsg = QtXmlPatterns::tr("Duration content does not match pattern facet.");
919  return false;
920  }
921  }
922  if (facets.contains(XsdFacet::Assertion)) {
923  //TODO: implement
924  }
925 
926  return true;
927 }
928 
929 bool XsdTypeChecker::checkConstrainingFacetsBoolean(bool, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
930 {
931  if (facets.contains(XsdFacet::Pattern)) {
932  const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
933  const AtomicValue::List multiValue = facet->multiValue();
934  bool found = false;
935  for (int j = 0; j < multiValue.count(); ++j) {
936  const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
938  if (exp.exactMatch(lexicalValue)) {
939  found = true;
940  break;
941  }
942  }
943 
944  if (!found) {
945  errorMsg = QtXmlPatterns::tr("Boolean content does not match pattern facet.");
946  return false;
947  }
948  }
949  if (facets.contains(XsdFacet::Assertion)) {
950  //TODO: implement
951  }
952 
953  return true;
954 }
955 
957 {
958  if (facets.contains(XsdFacet::Length)) {
959  const XsdFacet::Ptr facet = facets.value(XsdFacet::Length);
960  const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
961  if (length->toInteger() != value.length()) {
962  errorMsg = QtXmlPatterns::tr("Binary content does not match the length facet.");
963  return false;
964  }
965  }
966  if (facets.contains(XsdFacet::MinimumLength)) {
967  const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumLength);
968  const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
969  if (length->toInteger() > value.length()) {
970  errorMsg = QtXmlPatterns::tr("Binary content does not match the minLength facet.");
971  return false;
972  }
973  }
974  if (facets.contains(XsdFacet::MaximumLength)) {
975  const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumLength);
976  const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
977  if (length->toInteger() < value.length()) {
978  errorMsg = QtXmlPatterns::tr("Binary content does not match the maxLength facet.");
979  return false;
980  }
981  }
982  if (facets.contains(XsdFacet::Enumeration)) {
983  const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
984  const AtomicValue::List multiValue = facet->multiValue();
985  bool found = false;
986  for (int j = 0; j < multiValue.count(); ++j) {
987  const Base64Binary::Ptr binary = ValueFactory::fromLexical(multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
988  const QByteArray facetValue = binary->as<Base64Binary>()->asByteArray();
989  if (value == facetValue) {
990  found = true;
991  break;
992  }
993  }
994 
995  if (!found) {
996  errorMsg = QtXmlPatterns::tr("Binary content is not listed in the enumeration facet.");
997  return false;
998  }
999  }
1000  if (facets.contains(XsdFacet::Pattern)) {
1001  //TODO: implement
1002  }
1003  if (facets.contains(XsdFacet::Assertion)) {
1004  //TODO: implement
1005  }
1006 
1007  return true;
1008 }
1009 
1010 bool XsdTypeChecker::checkConstrainingFacetsQName(const QXmlName &value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
1011 {
1012  if (facets.contains(XsdFacet::Length)) {
1013  // always true
1014  }
1015  if (facets.contains(XsdFacet::MinimumLength)) {
1016  // always true
1017  }
1018  if (facets.contains(XsdFacet::MaximumLength)) {
1019  // always true
1020  }
1021  if (facets.contains(XsdFacet::Enumeration)) {
1022  if (!XPathHelper::isQName(lexicalValue)) {
1023  errorMsg = QtXmlPatterns::tr("Invalid QName content: %1.").arg(formatData(lexicalValue));
1024  return false;
1025  }
1026 
1027  const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
1028  const AtomicValue::List multiValue = facet->multiValue();
1029  bool found = false;
1030  for (int j = 0; j < multiValue.count(); ++j) {
1031  const QXmlName facetValue = multiValue.at(j)->as<QNameValue>()->qName();
1032 
1033  if (value == facetValue) {
1034  found = true;
1035  break;
1036  }
1037  }
1038 
1039  if (!found) {
1040  errorMsg = QtXmlPatterns::tr("QName content is not listed in the enumeration facet.");
1041  return false;
1042  }
1043  }
1044  if (facets.contains(XsdFacet::Pattern)) {
1045  const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
1046  const AtomicValue::List multiValue = facet->multiValue();
1047  bool found = false;
1048  for (int j = 0; j < multiValue.count(); ++j) {
1049  const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
1051  if (exp.exactMatch(lexicalValue)) {
1052  found = true;
1053  break;
1054  }
1055  }
1056 
1057  if (!found) {
1058  errorMsg = QtXmlPatterns::tr("QName content does not match pattern facet.");
1059  return false;
1060  }
1061  }
1062  if (facets.contains(XsdFacet::Assertion)) {
1063  //TODO: implement
1064  }
1065 
1066  return true;
1067 }
1068 
1069 bool XsdTypeChecker::checkConstrainingFacetsNotation(const QXmlName &value, const XsdFacet::Hash &facets, QString &errorMsg) const
1070 {
1071  if (facets.contains(XsdFacet::Length)) {
1072  // deprecated by spec
1073  }
1074  if (facets.contains(XsdFacet::MinimumLength)) {
1075  // deprecated by spec
1076  }
1077  if (facets.contains(XsdFacet::MaximumLength)) {
1078  // deprecated by spec
1079  }
1080  if (facets.contains(XsdFacet::Enumeration)) {
1081  const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
1082  const AtomicValue::List multiValue = facet->multiValue();
1083  bool found = false;
1084  for (int j = 0; j < multiValue.count(); ++j) {
1085  const QXmlName facetValue = multiValue.at(j)->as<QNameValue>()->qName();
1086 
1087  if (value == facetValue) {
1088  found = true;
1089  break;
1090  }
1091  }
1092 
1093  if (!found) {
1094  errorMsg = QtXmlPatterns::tr("Notation content is not listed in the enumeration facet.");
1095  return false;
1096  }
1097  }
1098  if (facets.contains(XsdFacet::Pattern)) {
1099  //TODO: implement
1100  }
1101  if (facets.contains(XsdFacet::Assertion)) {
1102  //TODO: implement
1103  }
1104 
1105  return true;
1106 }
1107 
1108 bool XsdTypeChecker::checkConstrainingFacetsList(const QStringList &values, const QString &lexicalValue, const AnySimpleType::Ptr &itemType, const XsdFacet::Hash &facets, QString &errorMsg) const
1109 {
1110  if (facets.contains(XsdFacet::Length)) {
1112  if (value->toInteger() != values.count()) {
1113  errorMsg = QtXmlPatterns::tr("List content does not match length facet.");
1114  return false;
1115  }
1116  }
1117  if (facets.contains(XsdFacet::MinimumLength)) {
1119  if (value->toInteger() > values.count()) {
1120  errorMsg = QtXmlPatterns::tr("List content does not match minLength facet.");
1121  return false;
1122  }
1123  }
1124  if (facets.contains(XsdFacet::MaximumLength)) {
1126  if (value->toInteger() < values.count()) {
1127  errorMsg = QtXmlPatterns::tr("List content does not match maxLength facet.");
1128  return false;
1129  }
1130  }
1131  if (facets.contains(XsdFacet::Enumeration)) {
1132 
1133  bool found = false;
1134 
1135  // we have to handle lists with QName derived items differently
1136  if (BuiltinTypes::xsQName->wxsTypeMatches(itemType) || BuiltinTypes::xsNOTATION->wxsTypeMatches(itemType)) {
1137  // first convert the string values from the instance document to a list of QXmlName
1138  QList<QXmlName> instanceValues;
1139  for (int i = 0; i < values.count(); ++i) {
1140  instanceValues.append(convertToQName(values.at(i)));
1141  }
1142 
1143  // fetch the values from the facet and create a list of QXmlNames for each of them
1144  const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
1145 
1146  const AtomicValue::List multiValue = facet->multiValue();
1147  for (int i = 0; i < multiValue.count(); ++i) {
1148  const QStringList facetValueList = multiValue.at(i)->as<DerivedString<TypeString> >()->stringValue().split(QLatin1Char(' '), QString::SkipEmptyParts);
1149 
1150  // create the list of atomic string values
1151  QList<QXmlName> facetValues;
1152  for (int j = 0; j < facetValueList.count(); ++j) {
1153  facetValues.append(convertToQName(facetValueList.at(j)));
1154  }
1155 
1156  // check if both lists have the same length
1157  if (instanceValues.count() != facetValues.count())
1158  continue;
1159 
1160  // check if both lists are equal, that means the contain equal items in the same order
1161  bool matchesAll = true;
1162  for (int j = 0; j < instanceValues.count(); ++j) {
1163  if (instanceValues.at(j) != facetValues.at(j)) {
1164  matchesAll = false;
1165  break;
1166  }
1167  }
1168 
1169  if (matchesAll) {
1170  found = true;
1171  break;
1172  }
1173  }
1174  } else {
1175  // first convert the string values from the instance document to atomic values of type string
1176  AtomicValue::List instanceValues;
1177  for (int i = 0; i < values.count(); ++i) {
1178  instanceValues.append(DerivedString<TypeString>::fromLexical(m_namePool, values.at(i)));
1179  }
1180 
1181  // fetch the values from the facet and create a list of atomic string values for each of them
1182  const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
1183 
1184  const AnySimpleType::Ptr targetType = comparableType(itemType);
1185 
1186  const AtomicValue::List multiValue = facet->multiValue();
1187  for (int i = 0; i < multiValue.count(); ++i) {
1188  const QStringList facetValueList = multiValue.at(i)->as<DerivedString<TypeString> >()->stringValue().split(QLatin1Char(' '), QString::SkipEmptyParts);
1189 
1190  // create the list of atomic string values
1191  AtomicValue::List facetValues;
1192  for (int j = 0; j < facetValueList.count(); ++j) {
1193  facetValues.append(DerivedString<TypeString>::fromLexical(m_namePool, facetValueList.at(j)));
1194  }
1195 
1196  // check if both lists have the same length
1197  if (instanceValues.count() != facetValues.count())
1198  continue;
1199 
1200  // check if both lists are equal, that means the contain equal items in the same order
1201  bool matchesAll = true;
1202  for (int j = 0; j < instanceValues.count(); ++j) {
1203  if (!XsdSchemaHelper::constructAndCompare(instanceValues.at(j), AtomicComparator::OperatorEqual, facetValues.at(j), targetType, m_context, m_reflection)) {
1204  matchesAll = false;
1205  break;
1206  }
1207  }
1208 
1209  if (matchesAll) {
1210  found = true;
1211  break;
1212  }
1213  }
1214  }
1215 
1216  if (!found) {
1217  errorMsg = QtXmlPatterns::tr("List content is not listed in the enumeration facet.");
1218  return false;
1219  }
1220  }
1221  if (facets.contains(XsdFacet::Pattern)) {
1222  const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
1223  const AtomicValue::List multiValue = facet->multiValue();
1224  bool found = false;
1225  for (int j = 0; j < multiValue.count(); ++j) {
1226  const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
1228  if (exp.exactMatch(lexicalValue)) {
1229  found = true;
1230  break;
1231  }
1232  }
1233 
1234  if (!found) {
1235  errorMsg = QtXmlPatterns::tr("List content does not match pattern facet.");
1236  return false;
1237  }
1238  }
1239  if (facets.contains(XsdFacet::Assertion)) {
1240  //TODO: implement
1241  }
1242 
1243  return true;
1244 }
1245 
1246 bool XsdTypeChecker::checkConstrainingFacetsUnion(const QString &value, const QString &lexicalValue, const XsdSimpleType::Ptr &simpleType, const XsdFacet::Hash &facets, QString &errorMsg) const
1247 {
1248  if (facets.contains(XsdFacet::Enumeration)) {
1249  const AnySimpleType::List memberTypes = simpleType->memberTypes();
1250 
1251  const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
1252 
1253  // convert the instance value into an atomic string value
1255 
1256  // collect the facet values into a list of atomic string values
1257  const AtomicValue::List facetValues = facet->multiValue();
1258 
1259  // compare the instance value against the facetValues for each member type and
1260  // search for a match
1261 
1262  bool found = false;
1263  for (int i = 0; i < memberTypes.count(); ++i) {
1264  const AnySimpleType::Ptr targetType = comparableType(memberTypes.at(i));
1265  for (int j = 0; j < facetValues.count(); ++j) {
1266  if (XsdSchemaHelper::constructAndCompare(valueString, AtomicComparator::OperatorEqual, facetValues.at(j), targetType, m_context, m_reflection)) {
1267  found = true;
1268  break;
1269  }
1270  }
1271  }
1272 
1273  if (!found) {
1274  errorMsg = QtXmlPatterns::tr("Union content is not listed in the enumeration facet.");
1275  return false;
1276  }
1277  }
1278  if (facets.contains(XsdFacet::Pattern)) {
1279  const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
1280  const AtomicValue::List multiValue = facet->multiValue();
1281  bool found = false;
1282  for (int j = 0; j < multiValue.count(); ++j) {
1283  const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
1285  if (exp.exactMatch(lexicalValue)) {
1286  found = true;
1287  break;
1288  }
1289  }
1290 
1291  if (!found) {
1292  errorMsg = QtXmlPatterns::tr("Union content does not match pattern facet.");
1293  return false;
1294  }
1295  }
1296  if (facets.contains(XsdFacet::Assertion)) {
1297  //TODO: implement
1298  }
1299 
1300  return true;
1301 }
1302 
1304 {
1306  if (value.simplified().isEmpty())
1307  return ValidationError::createError(QtXmlPatterns::tr("Data of type %1 are not allowed to be empty.").arg(formatType(m_namePool, BuiltinTypes::xsNOTATION)));
1308 
1309  const QXmlName valueName = convertToQName(value);
1310  return QNameValue::fromValue(m_namePool, valueName);
1311  } else {
1312  return ValueFactory::fromLexical(value, type, context, reflection);
1313  }
1314 }
1315 
1317 {
1318  const int pos = name.indexOf(QLatin1Char(':'));
1319 
1320  QXmlName::PrefixCode prefixCode = 0;
1321  QXmlName::NamespaceCode namespaceCode;
1322  QXmlName::LocalNameCode localNameCode;
1323  if (pos != -1) {
1324  prefixCode = m_context->namePool()->allocatePrefix(name.left(pos));
1325  namespaceCode = StandardNamespaces::empty;
1326  for (int i = 0; i < m_namespaceBindings.count(); ++i) {
1327  if (m_namespaceBindings.at(i).prefix() == prefixCode) {
1328  namespaceCode = m_namespaceBindings.at(i).namespaceURI();
1329  break;
1330  }
1331  }
1332  localNameCode = m_context->namePool()->allocateLocalName(name.mid(pos + 1));
1333  } else {
1334  prefixCode = StandardPrefixes::empty;
1335  namespaceCode = StandardNamespaces::empty;
1336  for (int i = 0; i < m_namespaceBindings.count(); ++i) {
1337  if (m_namespaceBindings.at(i).prefix() == prefixCode) {
1338  namespaceCode = m_namespaceBindings.at(i).namespaceURI();
1339  break;
1340  }
1341  }
1342  localNameCode = m_context->namePool()->allocateLocalName(name);
1343  }
1344 
1345  return QXmlName(namespaceCode, localNameCode, prefixCode);
1346 }
1347 
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qstring.cpp:6448
Match an assertion (Assertion Definition)
Definition: qxsdfacet_p.h:116
QBool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.h:904
static AtomicValue::Ptr fromLexical(const QString &lexicalValue, const SchemaType::Ptr &type, const ReportContext::Ptr &context, const SourceLocationReflection *const sourceLocationReflection)
Returns an AtomicValue of type type from the lexical space lexicalValue, and raise an error through c...
static const AtomicType::Ptr xsBase64Binary
static AnySimpleType::Ptr comparableType(const AnySimpleType::Ptr &type)
int type
Definition: qmetatype.cpp:239
virtual TypeCategory category() const
virtual qulonglong toUnsignedInteger() const =0
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
NamespaceCode LocalNameCode
Definition: qxmlname.h:84
Base class for classes implementing values related to time, date or both.
Match a minimum inclusive (Minimum Inclusive Definition)
Definition: qxsdfacet_p.h:111
const QChar at(int i) const
Returns the character at the given index position in the string.
Definition: qstring.h:698
The QRegExp class provides pattern matching using regular expressions.
Definition: qregexp.h:61
bool checkConstrainingFacetsString(const QString &value, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const
virtual bool hasError() const
#define it(className, varName)
int count(const T &t) const
Returns the number of occurrences of value in the vector.
Definition: qvector.h:742
static QRegExp parsePattern(const QString &pattern, const ReportContext::Ptr &context, const SourceLocationReflection *const location)
Parses pattern.
static const AtomicType::Ptr xsDuration
XsdSchemaSourceLocationReflection(const QSourceLocation &location)
qint16 NamespaceCode
Definition: qxmlname.h:82
QString & replace(int i, int len, QChar after)
Definition: qstring.cpp:2005
QString formatType(const NamePool::Ptr &np, const T &type)
Formats ItemType and SequenceType.
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
QXmlName convertToQName(const QString &name) const
virtual TypeCategory category() const
static const AtomicType::Ptr xsGYearMonth
static AtomicValue::Ptr createError(const QString &description=QString(), const ReportContext::ErrorCode=ReportContext::FORG0001)
static int totalDigitsForSignedLongLong(long long value)
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition: qstring.cpp:3734
static const AtomicType::Ptr xsGMonthDay
bool checkConstrainingFacetsUnion(const QString &value, const QString &lexicalValue, const XsdSimpleType::Ptr &simpleType, const XsdFacet::Hash &facets, QString &errorMsg) const
bool checkConstrainingFacetsDuration(const AtomicValue::Ptr &value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
bool checkConstrainingFacetsDateTime(const QDateTime &value, const QString &lexicalValue, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
virtual NamePool::Ptr namePool() const
XsdSchemaContext::Ptr m_context
The QString class provides a Unicode character string.
Definition: qstring.h:83
static QString toString(NodeName token)
static bool constructAndCompare(const DerivedString< TypeString >::Ptr &operand1, const AtomicComparator::Operator op, const DerivedString< TypeString >::Ptr &operand2, const SchemaType::Ptr &type, const ReportContext::Ptr &context, const SourceLocationReflection *const sourceLocationReflection)
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
static int totalDigitsForUnsignedLongLong(unsigned long long value)
bool contains(const Key &key) const
Returns true if the hash contains an item with the key; otherwise returns false.
Definition: qhash.h:872
QString prefix(const QXmlNamePool &query) const
Returns the prefix.
Definition: qxmlname.cpp:370
const T value(const Key &key) const
Returns the value associated with the key.
Definition: qhash.h:606
static const AtomicType::Ptr xsUnsignedByte
QHash< XsdFacet::Type, XsdFacet::Ptr > Hash
Definition: qxsdfacet_p.h:118
virtual QXmlName name(const NamePool::Ptr &np) const
Returns the name of the type.
Match a maximum exclusive (Maximum Exclusive Definition)
Definition: qxsdfacet_p.h:110
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition: qhash.h:753
static const AtomicType::Ptr xsString
QXmlName::PrefixCode allocatePrefix(const QString &prefix)
Definition: qnamepool_p.h:214
static int fractionDigitsForDecimal(const QString &lexicalValue)
Match an enumeration (Enumeration Definition)
Definition: qxsdfacet_p.h:115
QXmlName::LocalNameCode allocateLocalName(const QString &ln)
Definition: qnamepool_p.h:208
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
static const AtomicType::Ptr xsGDay
QXmlName qName() const
Definition: qqnamevalue_p.h:96
virtual SchemaType::Ptr wxsSuperType() const
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
virtual const SourceLocationReflection * actualReflection() const
const TCastTarget * as() const
Match the minimum length (Minimum Length Definition)
Definition: qxsdfacet_p.h:105
static XsdFacet::Hash mergedFacetsForType(const SchemaType::Ptr &type, const XsdSchemaContext::Ptr &context)
static QNameValue::Ptr fromValue(const NamePool::Ptr &np, const QXmlName name)
Definition: qqnamevalue.cpp:59
bool checkConstrainingFacetsSignedInteger(long long value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
Definition: qstring.cpp:3664
static const AtomicType::Ptr xsDateTime
QString trimmed() const Q_REQUIRED_RESULT
Returns a string that has whitespace removed from the start and the end.
Definition: qstring.cpp:4506
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
virtual xsDouble toDouble() const
Definition: qdecimal.cpp:157
const char * name
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
AtomicValue::Ptr fromLexical(const QString &value, const SchemaType::Ptr &type, const ReportContext::Ptr &context, const SourceLocationReflection *const reflection) const
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
static int totalDigitsForDecimal(const QString &lexicalValue)
static const AtomicType::Ptr xsUnsignedInt
The namespace for the internal API of QtXmlPatterns.
static const AtomicType::Ptr xsDouble
The QSourceLocation class identifies a location in a resource by URI, line, and column.
int indexOf(QChar c, int from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:2838
virtual QString stringValue() const =0
bool checkConstrainingFacetsBoolean(bool value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
static QString normalizedValue(const QString &value, const XsdFacet::Hash &facets)
bool checkConstrainingFacetsQName(const QXmlName &, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
const QDateTime & toDateTime() const
bool isValidString(const QString &normalizedString, const AnySimpleType::Ptr &type, QString &errorMsg, AnySimpleType::Ptr *boundType=0) const
const NamePool::Ptr m_namePool
static const AtomicType::Ptr xsGYear
bool value() const
Definition: qboolean_p.h:109
quint16 values[128]
static QString formatData(const QString &data)
int count() const
Definition: qstring.h:103
Match a whitespace rule (White Space Definition)
Definition: qxsdfacet_p.h:108
Match a maximum inclusive (Maximum Inclusive Definition)
Definition: qxsdfacet_p.h:109
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
static const AtomicType::Ptr xsUntypedAtomic
bool checkConstrainingFacetsUnsignedInteger(unsigned long long value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
virtual QSourceLocation sourceLocation() const
int length() const
Same as size().
Definition: qbytearray.h:356
Implements the value instance of the xs:boolean type.
Definition: qboolean_p.h:69
Match some double digits (Fraction Digits Definition)
Definition: qxsdfacet_p.h:114
T & first()
Returns a reference to the first item in the list.
Definition: qlist.h:282
Represents instances of derived xs:string types, such as xs:normalizedString.
Match a minimum exclusive (Minimum Exclusive Definition)
Definition: qxsdfacet_p.h:112
static const MacSpecialKey entries[NumEntries]
QString mid(int position, int n=-1) const Q_REQUIRED_RESULT
Returns a string that contains n characters of this string, starting at the specified position index...
Definition: qstring.cpp:3706
NamespaceCode namespaceURI() const
Definition: qnamepool_p.h:503
Match some integer digits (Total Digits Definition)
Definition: qxsdfacet_p.h:113
bool valuesAreEqual(const QString &value, const QString &otherValue, const AnySimpleType::Ptr &type) const
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
The QXmlName class represents the name of an XML node, in an efficient, namespace-aware way...
Definition: qxmlname.h:58
The QDateTime class provides date and time functions.
Definition: qdatetime.h:216
static const AtomicType::Ptr xsQName
Base class for all numeric values.
static bool wxsTypeMatches(const SchemaType::Ptr &type, const SchemaType::Ptr &otherType, QSet< SchemaType::Ptr > &visitedTypes, SchemaType::Ptr &conflictingType)
QExplicitlySharedDataPointer< XsdSimpleType > Ptr
QString simplified() const Q_REQUIRED_RESULT
Returns a string that has whitespace removed from the start and the end, and that has each sequence o...
Definition: qstring.cpp:4415
Match the exact length (Length Definition)
Definition: qxsdfacet_p.h:104
virtual xsInteger toInteger() const =0
An implementation of SourceLocationReflection that takes a QSourceLocation.
static const SchemaType::Ptr xsAnySimpleType
Match a regular expression (Pattern Definition)
Definition: qxsdfacet_p.h:107
static const AtomicType::Ptr xsFloat
static QTestResult::TestLocation location
Definition: qtestresult.cpp:63
Implements the value instance of the xs:QName type.
Definition: qqnamevalue_p.h:73
XsdFacet::Hash facetsForType(const AnySimpleType::Ptr &type) const
virtual xsDouble toDouble() const =0
static Numeric::Ptr fromValue(const xsDouble num)
QExplicitlySharedDataPointer< AnySimpleType > Ptr
AnySimpleType::Ptr primitiveType() const
static const AtomicType::Ptr xsInteger
QHashIterator< XsdFacet::Type, XsdFacet::Ptr > HashIterator
Definition: qxsdfacet_p.h:119
Implements the value instance of the xs:decimal type.
Definition: qdecimal_p.h:76
static const AtomicType::Ptr xsTime
const QByteArray & asByteArray() const
AnySimpleType::List memberTypes() const
bool exactMatch(const QString &str) const
Returns true if str is matched exactly by this regular expression; otherwise returns false...
Definition: qregexp.cpp:4094
static const AtomicType::Ptr xsUnsignedShort
static const AtomicType::Ptr xsDecimal
static const AtomicType::Ptr xsBoolean
bool checkConstrainingFacetsDecimal(const AtomicValue::Ptr &value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
QStringList split(const QString &sep, SplitBehavior behavior=KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const Q_REQUIRED_RESULT
Splits the string into substrings wherever sep occurs, and returns the list of those strings...
Definition: qstring.cpp:6526
SourceLocationReflection * m_reflection
static const AtomicType::Ptr xsDate
QVector< QXmlName > m_namespaceBindings
static const AtomicType::Ptr xsLong
static bool isQName(const QString &qName)
bool checkConstrainingFacetsNotation(const QXmlName &value, const XsdFacet::Hash &facets, QString &errorMsg) const
Implements the value instance of the xs:base64Binary type.
virtual bool isDefinedBySchema() const
Definition: qschematype.cpp:75
bool checkConstrainingFacetsDouble(double value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
static const AtomicType::Ptr xsNOTATION
static const AtomicType::Ptr xsGMonth
virtual SchemaType::Ptr wxsSuperType() const =0
bool checkConstrainingFacets(const AtomicValue::Ptr &value, const QString &lexicalValue, const AnySimpleType::Ptr &type, QString &errorMsg) const
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
static const AtomicType::Ptr xsHexBinary
static const AtomicType::Ptr xsUnsignedLong
bool isDigit() const
Returns true if the character is a decimal digit (Number_DecimalDigit); otherwise returns false...
Definition: qchar.cpp:699
static const AtomicType::Ptr xsAnyURI
virtual QXmlName name(const NamePool::Ptr &np) const =0
Returns the name of the type.
Match the maximum length (Maximum Length Definition)
Definition: qxsdfacet_p.h:106
XsdTypeChecker(const XsdSchemaContext::Ptr &context, const QVector< QXmlName > &namespaceBindings, const QSourceLocation &location)
static AtomicValue::Ptr fromLexical(const NamePool::Ptr &np, const QString &lexical)
Base class for all instances that represents something at a certain location.
bool checkConstrainingFacetsList(const QStringList &values, const QString &lexicalValue, const AnySimpleType::Ptr &itemType, const XsdFacet::Hash &facets, QString &errorMsg) const
bool checkConstrainingFacetsBinary(const QByteArray &value, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const
AnySimpleType::Ptr itemType() const
NamespaceCode PrefixCode
Definition: qxmlname.h:83