fb47448691bffaeca3f2b3ff3de89110a9daee0e
[profile/ivi/qtxmlpatterns.git] / src / xmlpatterns / schema / qxsdtypechecker.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
8 **
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.
17 **
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.
21 **
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.
29 **
30 ** Other Usage
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.
33 **
34 **
35 **
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"
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"
60
61 #include "qxsdschemadebugger_p.h"
62
63 QT_BEGIN_NAMESPACE
64
65 using namespace QPatternist;
66
67 XsdSchemaSourceLocationReflection::XsdSchemaSourceLocationReflection(const QSourceLocation &location)
68     : m_sourceLocation(location)
69 {
70 }
71
72 const SourceLocationReflection* XsdSchemaSourceLocationReflection::actualReflection() const
73 {
74     return this;
75 }
76
77 QSourceLocation XsdSchemaSourceLocationReflection::sourceLocation() const
78 {
79     return m_sourceLocation;
80 }
81
82
83 static AnySimpleType::Ptr comparableType(const AnySimpleType::Ptr &type)
84 {
85     if (!type->isDefinedBySchema()) {
86         return type;
87     } else {
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();
95         }
96     }
97
98     Q_ASSERT(false);
99     return AnySimpleType::Ptr();
100 }
101
102 static int totalDigitsForSignedLongLong(long long value)
103 {
104     QString number = QString::number(value);
105     if (number.startsWith(QLatin1Char('-')))
106         number = number.mid(1);
107
108     return number.length();
109 }
110
111 static int totalDigitsForUnsignedLongLong(unsigned long long value)
112 {
113     const QString number = QString::number(value);
114     return number.length();
115 }
116
117 static int totalDigitsForDecimal(const QString &lexicalValue)
118 {
119     const QLatin1Char zeroChar('0');
120     const int length = lexicalValue.length() - 1;
121
122     // strip leading zeros
123     int pos = 0;
124     while (lexicalValue.at(pos) == zeroChar && (pos != length))
125         pos++;
126
127     QString value = lexicalValue.mid(pos);
128
129     // if contains '.' strip trailing zeros
130     if (value.contains(QLatin1Char('.'))) {
131         pos = value.length() - 1;
132         while (value.at(pos) == zeroChar) {
133             pos--;
134         }
135
136         value = value.left(pos + 1);
137     }
138
139     // check number of digits of remaining string
140     int totalDigits = 0;
141     for (int i = 0; i < value.count(); ++i)
142         if (value.at(i).isDigit())
143             ++totalDigits;
144
145     if (totalDigits == 0)
146         totalDigits = 1;
147
148     return totalDigits;
149 }
150
151 static int fractionDigitsForDecimal(const QString &lexicalValue)
152 {
153     // we use the lexical value here, as the conversion to double might strip
154     // away decimal positions
155
156     QString trimmedValue(lexicalValue.trimmed());
157     const int pos = trimmedValue.indexOf(QLatin1Char('.'));
158     if (pos == -1) // no '.' -> 0 fraction digits
159         return 0;
160     else
161         return (trimmedValue.length() - pos - 1);
162 }
163
164 XsdTypeChecker::XsdTypeChecker(const XsdSchemaContext::Ptr &context, const QVector<QXmlName> &namespaceBindings, const QSourceLocation &location)
165     : m_context(context)
166     , m_namePool(m_context->namePool())
167     , m_namespaceBindings(namespaceBindings)
168     , m_reflection(new XsdSchemaSourceLocationReflection(location))
169 {
170 }
171
172 XsdTypeChecker::~XsdTypeChecker()
173 {
174     delete m_reflection;
175 }
176
177 QString XsdTypeChecker::normalizedValue(const QString &value, const XsdFacet::Hash &facets)
178 {
179     if (!facets.contains(XsdFacet::WhiteSpace))
180         return value;
181
182     const XsdFacet::Ptr whiteSpaceFacet = facets.value(XsdFacet::WhiteSpace);
183
184     const DerivedString<TypeString>::Ptr facetValue = whiteSpaceFacet->value();
185     const QString stringValue = facetValue->stringValue();
186     if (stringValue == XsdSchemaToken::toString(XsdSchemaToken::Preserve))
187         return value;
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(' '));
193
194         return newValue;
195     } else if (stringValue == XsdSchemaToken::toString(XsdSchemaToken::Collapse)) {
196         return value.simplified();
197     }
198
199     return value;
200 }
201
202 XsdFacet::Hash XsdTypeChecker::mergedFacetsForType(const SchemaType::Ptr &type, const XsdSchemaContext::Ptr &context)
203 {
204     if (!type)
205         return XsdFacet::Hash();
206
207     const XsdFacet::Hash baseFacets = mergedFacetsForType(type->wxsSuperType(), context);
208     const XsdFacet::Hash facets = context->facetsForType(type);
209
210     XsdFacet::Hash result = baseFacets;
211     XsdFacet::HashIterator it(facets);
212     while (it.hasNext()) {
213         it.next();
214
215         result.insert(it.key(), it.value());
216     }
217
218     return result;
219 }
220
221 bool XsdTypeChecker::isValidString(const QString &normalizedString, const AnySimpleType::Ptr &type, QString &errorMsg, AnySimpleType::Ptr *boundType) const
222 {
223     if (type->name(m_namePool) == BuiltinTypes::xsAnySimpleType->name(m_namePool)) {
224         if (boundType)
225             *boundType = type;
226
227         return true;
228     }
229
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));
235                 return false;
236             }
237         }
238
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));
242             return false;
243         }
244
245         if (!checkConstrainingFacets(value, normalizedString, type, errorMsg)) {
246             return false;
247         }
248
249         if (boundType)
250             *boundType = type;
251
252     } else {
253         const XsdSimpleType::Ptr simpleType(type);
254
255         if (simpleType->category() == XsdSimpleType::SimpleTypeAtomic) {
256             AnySimpleType::Ptr targetType = simpleType->primitiveType();
257             if (!simpleType->wxsSuperType()->isDefinedBySchema())
258                 targetType = simpleType->wxsSuperType();
259
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));
263                 return false;
264             }
265
266             if (!checkConstrainingFacets(value, normalizedString, type, errorMsg)) {
267                 return false;
268             }
269
270             if (boundType)
271                 *boundType = type;
272
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));
277             }
278
279             if (!checkConstrainingFacetsList(entries, normalizedString, simpleType->itemType(), mergedFacetsForType(simpleType, m_context), errorMsg)) {
280                 return false;
281             }
282
283             for (int i = 0; i < entries.count(); ++i) {
284                 if (!isValidString(entries.at(i), simpleType->itemType(), errorMsg)) {
285                     return false;
286                 }
287             }
288
289             if (boundType)
290                 *boundType = simpleType->itemType();
291
292         } else if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) {
293             if (!checkConstrainingFacetsUnion(normalizedString, normalizedString, simpleType, mergedFacetsForType(simpleType, m_context), errorMsg)) {
294                 return false;
295             }
296
297             const AnySimpleType::List memberTypes = simpleType->memberTypes();
298
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;
304
305                     if (boundType)
306                         *boundType = memberTypes.at(i);
307
308                     break;
309                 }
310             }
311
312             if (!foundValidType) {
313                 return false;
314             }
315         }
316     }
317
318     return true;
319 }
320
321 bool XsdTypeChecker::valuesAreEqual(const QString &value, const QString &otherValue, const AnySimpleType::Ptr &type) const
322 {
323     const AnySimpleType::Ptr targetType = comparableType(type);
324
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);
328
329     if (BuiltinTypes::xsQName->wxsTypeMatches(type)) {
330         const QXmlName valueName = convertToQName(value);
331         const QXmlName otherValueName = convertToQName(otherValue);
332
333         if (valueName == otherValueName)
334             return true;
335     }
336
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);
341
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())
347             return false;
348
349         for (int i = 0; i < values.count(); ++i) {
350             if (!valuesAreEqual(values.at(i), otherValues.at(i), XsdSimpleType::Ptr(type)->itemType()))
351                 return false;
352         }
353
354         return true;
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))) {
359                 return true;
360             }
361         }
362
363         return false;
364     }
365
366     return false;
367 }
368
369 bool XsdTypeChecker::checkConstrainingFacets(const AtomicValue::Ptr &value, const QString &lexicalValue, const AnySimpleType::Ptr &type, QString &errorMsg) const
370 {
371     const XsdFacet::Hash facets = mergedFacetsForType(type, m_context);
372
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);
418     }
419
420     return true;
421 }
422
423 bool XsdTypeChecker::checkConstrainingFacetsString(const QString &value, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const
424 {
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.");
430             return false;
431         }
432     }
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.");
438             return false;
439         }
440     }
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.");
446             return false;
447         }
448     }
449     if (facets.contains(XsdFacet::Pattern)) {
450         const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
451         const AtomicValue::List multiValue = facet->multiValue();
452         bool found = false;
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)) {
457                 found = true;
458                 break;
459             }
460         }
461
462         if (!found) {
463             errorMsg = QtXmlPatterns::tr("String content does not match pattern facet.");
464             return false;
465         }
466     }
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);
470
471         const AtomicValue::List multiValue = facet->multiValue();
472         bool found = false;
473         for (int j = 0; j < multiValue.count(); ++j) {
474             if (XsdSchemaHelper::constructAndCompare(valueStr, AtomicComparator::OperatorEqual, multiValue.at(j), type, m_context, m_reflection)) {
475                 found = true;
476                 break;
477             }
478         }
479
480         if (!found) {
481             errorMsg = QtXmlPatterns::tr("String content is not listed in the enumeration facet.");
482             return false;
483         }
484     }
485     if (facets.contains(XsdFacet::Assertion)) {
486         //TODO: implement
487     }
488
489     return true;
490 }
491
492 bool XsdTypeChecker::checkConstrainingFacetsSignedInteger(long long value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
493 {
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.");
499             return false;
500         }
501     }
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.");
507             return false;
508         }
509     }
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.");
515             return false;
516         }
517     }
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.");
523             return false;
524         }
525     }
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));
529
530         const AtomicValue::List multiValue = facet->multiValue();
531         bool found = false;
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)) {
534                 found = true;
535                 break;
536             }
537         }
538
539         if (!found) {
540             errorMsg = QtXmlPatterns::tr("Signed integer content is not listed in the enumeration facet.");
541             return false;
542         }
543     }
544     if (facets.contains(XsdFacet::Pattern)) {
545         const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
546         const AtomicValue::List multiValue = facet->multiValue();
547         bool found = false;
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)) {
552                 found = true;
553                 break;
554             }
555         }
556
557         if (!found) {
558             errorMsg = QtXmlPatterns::tr("Signed integer content does not match pattern facet.");
559             return false;
560         }
561     }
562     if (facets.contains(XsdFacet::TotalDigits)) {
563         const XsdFacet::Ptr facet = facets.value(XsdFacet::TotalDigits);
564         const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value();
565
566         if (totalDigitsForSignedLongLong(value) > facetValue->toInteger()) {
567             errorMsg = QtXmlPatterns::tr("Signed integer content does not match in the totalDigits facet.");
568             return false;
569         }
570     }
571     if (facets.contains(XsdFacet::Assertion)) {
572         //TODO: implement
573     }
574
575     return true;
576 }
577
578 bool XsdTypeChecker::checkConstrainingFacetsUnsignedInteger(unsigned long long value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
579 {
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.");
585             return false;
586         }
587     }
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.");
593             return false;
594         }
595     }
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.");
601             return false;
602         }
603     }
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.");
609             return false;
610         }
611     }
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));
615
616         const AtomicValue::List multiValue = facet->multiValue();
617         bool found = false;
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)) {
620                 found = true;
621                 break;
622             }
623         }
624
625         if (!found) {
626             errorMsg = QtXmlPatterns::tr("Unsigned integer content is not listed in the enumeration facet.");
627             return false;
628         }
629     }
630     if (facets.contains(XsdFacet::Pattern)) {
631         const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
632         const AtomicValue::List multiValue = facet->multiValue();
633         bool found = false;
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)) {
638                 found = true;
639                 break;
640             }
641         }
642
643         if (!found) {
644             errorMsg = QtXmlPatterns::tr("Unsigned integer content does not match pattern facet.");
645             return false;
646         }
647     }
648     if (facets.contains(XsdFacet::TotalDigits)) {
649         const XsdFacet::Ptr facet = facets.value(XsdFacet::TotalDigits);
650         const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value();
651
652         if (totalDigitsForUnsignedLongLong(value) > facetValue->toInteger()) {
653             errorMsg = QtXmlPatterns::tr("Unsigned integer content does not match in the totalDigits facet.");
654             return false;
655         }
656     }
657     if (facets.contains(XsdFacet::Assertion)) {
658         //TODO: implement
659     }
660
661     return true;
662 }
663
664 bool XsdTypeChecker::checkConstrainingFacetsDouble(double value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
665 {
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.");
671             return false;
672         }
673     }
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.");
679             return false;
680         }
681     }
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.");
687             return false;
688         }
689     }
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.");
695             return false;
696         }
697     }
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));
701
702         const AtomicValue::List multiValue = facet->multiValue();
703         bool found = false;
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)) {
706                 found = true;
707                 break;
708             }
709         }
710
711         if (!found) {
712             errorMsg = QtXmlPatterns::tr("Double content is not listed in the enumeration facet.");
713             return false;
714         }
715     }
716     if (facets.contains(XsdFacet::Pattern)) {
717         const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
718         const AtomicValue::List multiValue = facet->multiValue();
719         bool found = false;
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)) {
724                 found = true;
725                 break;
726             }
727         }
728
729         if (!found) {
730             errorMsg = QtXmlPatterns::tr("Double content does not match pattern facet.");
731             return false;
732         }
733     }
734     if (facets.contains(XsdFacet::Assertion)) {
735         //TODO: implement
736     }
737
738     return true;
739 }
740
741 bool XsdTypeChecker::checkConstrainingFacetsDecimal(const AtomicValue::Ptr &value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
742 {
743     if (facets.contains(XsdFacet::FractionDigits)) {
744         const XsdFacet::Ptr facet = facets.value(XsdFacet::FractionDigits);
745         const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value();
746
747         if (fractionDigitsForDecimal(lexicalValue) > facetValue->toInteger()) {
748             errorMsg = QtXmlPatterns::tr("Decimal content does not match in the fractionDigits facet.");
749             return false;
750         }
751     }
752     if (facets.contains(XsdFacet::TotalDigits)) {
753         const XsdFacet::Ptr facet = facets.value(XsdFacet::TotalDigits);
754         const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value();
755
756         if (totalDigitsForDecimal(lexicalValue) > facetValue->toInteger()) {
757             errorMsg = QtXmlPatterns::tr("Decimal content does not match in the totalDigits facet.");
758             return false;
759         }
760     }
761
762     return checkConstrainingFacetsDouble(value->as<Decimal>()->toDouble(), lexicalValue, facets, errorMsg);
763 }
764
765 bool XsdTypeChecker::checkConstrainingFacetsDateTime(const QDateTime &value, const QString &lexicalValue, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const
766 {
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.");
772             return false;
773         }
774     }
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.");
780             return false;
781         }
782     }
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.");
788             return false;
789         }
790     }
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.");
796             return false;
797         }
798     }
799     if (facets.contains(XsdFacet::Enumeration)) {
800         const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
801
802         const AtomicValue::List multiValue = facet->multiValue();
803         bool found = false;
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) {
807                 found = true;
808                 break;
809             }
810         }
811
812         if (!found) {
813             errorMsg = QtXmlPatterns::tr("Date time content is not listed in the enumeration facet.");
814             return false;
815         }
816     }
817     if (facets.contains(XsdFacet::Pattern)) {
818         const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
819         const AtomicValue::List multiValue = facet->multiValue();
820         bool found = false;
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)) {
825                 found = true;
826                 break;
827             }
828         }
829
830         if (!found) {
831             errorMsg = QtXmlPatterns::tr("Date time content does not match pattern facet.");
832             return false;
833         }
834     }
835
836     return true;
837 }
838
839 bool XsdTypeChecker::checkConstrainingFacetsDuration(const AtomicValue::Ptr&, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
840 {
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);
844
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.");
847             return false;
848         }
849     }
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);
853
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.");
856             return false;
857         }
858     }
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);
862
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.");
865             return false;
866         }
867     }
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);
871
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.");
874             return false;
875         }
876     }
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);
880
881         const AtomicValue::List multiValue = facet->multiValue();
882         bool found = false;
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)) {
885                 found = true;
886                 break;
887             }
888         }
889
890         if (!found) {
891             errorMsg = QtXmlPatterns::tr("Duration content is not listed in the enumeration facet.");
892             return false;
893         }
894     }
895     if (facets.contains(XsdFacet::Pattern)) {
896         const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
897         const AtomicValue::List multiValue = facet->multiValue();
898         bool found = false;
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)) {
903                 found = true;
904                 break;
905             }
906         }
907
908         if (!found) {
909             errorMsg = QtXmlPatterns::tr("Duration content does not match pattern facet.");
910             return false;
911         }
912     }
913     if (facets.contains(XsdFacet::Assertion)) {
914         //TODO: implement
915     }
916
917     return true;
918 }
919
920 bool XsdTypeChecker::checkConstrainingFacetsBoolean(bool, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
921 {
922     if (facets.contains(XsdFacet::Pattern)) {
923         const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
924         const AtomicValue::List multiValue = facet->multiValue();
925         bool found = false;
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)) {
930                 found = true;
931                 break;
932             }
933         }
934
935         if (!found) {
936             errorMsg = QtXmlPatterns::tr("Boolean content does not match pattern facet.");
937             return false;
938         }
939     }
940     if (facets.contains(XsdFacet::Assertion)) {
941         //TODO: implement
942     }
943
944     return true;
945 }
946
947 bool XsdTypeChecker::checkConstrainingFacetsBinary(const QByteArray &value, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const
948 {
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.");
954             return false;
955         }
956     }
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.");
962             return false;
963         }
964     }
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.");
970             return false;
971         }
972     }
973     if (facets.contains(XsdFacet::Enumeration)) {
974         const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
975         const AtomicValue::List multiValue = facet->multiValue();
976         bool found = false;
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) {
981                 found = true;
982                 break;
983             }
984         }
985
986         if (!found) {
987             errorMsg = QtXmlPatterns::tr("Binary content is not listed in the enumeration facet.");
988             return false;
989         }
990     }
991     if (facets.contains(XsdFacet::Pattern)) {
992         //TODO: implement
993     }
994     if (facets.contains(XsdFacet::Assertion)) {
995         //TODO: implement
996     }
997
998     return true;
999 }
1000
1001 bool XsdTypeChecker::checkConstrainingFacetsQName(const QXmlName &value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
1002 {
1003     if (facets.contains(XsdFacet::Length)) {
1004         // always true
1005     }
1006     if (facets.contains(XsdFacet::MinimumLength)) {
1007         // always true
1008     }
1009     if (facets.contains(XsdFacet::MaximumLength)) {
1010         // always true
1011     }
1012     if (facets.contains(XsdFacet::Enumeration)) {
1013         if (!XPathHelper::isQName(lexicalValue)) {
1014             errorMsg = QtXmlPatterns::tr("Invalid QName content: %1.").arg(formatData(lexicalValue));
1015             return false;
1016         }
1017
1018         const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
1019         const AtomicValue::List multiValue = facet->multiValue();
1020         bool found = false;
1021         for (int j = 0; j < multiValue.count(); ++j) {
1022             const QXmlName facetValue = multiValue.at(j)->as<QNameValue>()->qName();
1023
1024             if (value == facetValue) {
1025                 found = true;
1026                 break;
1027             }
1028         }
1029
1030         if (!found) {
1031             errorMsg = QtXmlPatterns::tr("QName content is not listed in the enumeration facet.");
1032             return false;
1033         }
1034     }
1035     if (facets.contains(XsdFacet::Pattern)) {
1036         const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
1037         const AtomicValue::List multiValue = facet->multiValue();
1038         bool found = false;
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)) {
1043                 found = true;
1044                 break;
1045             }
1046         }
1047
1048         if (!found) {
1049             errorMsg = QtXmlPatterns::tr("QName content does not match pattern facet.");
1050             return false;
1051         }
1052     }
1053     if (facets.contains(XsdFacet::Assertion)) {
1054         //TODO: implement
1055     }
1056
1057     return true;
1058 }
1059
1060 bool XsdTypeChecker::checkConstrainingFacetsNotation(const QXmlName &value, const XsdFacet::Hash &facets, QString &errorMsg) const
1061 {
1062     if (facets.contains(XsdFacet::Length)) {
1063         // deprecated by spec
1064     }
1065     if (facets.contains(XsdFacet::MinimumLength)) {
1066         // deprecated by spec
1067     }
1068     if (facets.contains(XsdFacet::MaximumLength)) {
1069         // deprecated by spec
1070     }
1071     if (facets.contains(XsdFacet::Enumeration)) {
1072         const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
1073         const AtomicValue::List multiValue = facet->multiValue();
1074         bool found = false;
1075         for (int j = 0; j < multiValue.count(); ++j) {
1076             const QXmlName facetValue = multiValue.at(j)->as<QNameValue>()->qName();
1077
1078             if (value == facetValue) {
1079                 found = true;
1080                 break;
1081             }
1082         }
1083
1084         if (!found) {
1085             errorMsg = QtXmlPatterns::tr("Notation content is not listed in the enumeration facet.");
1086             return false;
1087         }
1088     }
1089     if (facets.contains(XsdFacet::Pattern)) {
1090         //TODO: implement
1091     }
1092     if (facets.contains(XsdFacet::Assertion)) {
1093         //TODO: implement
1094     }
1095
1096     return true;
1097 }
1098
1099 bool XsdTypeChecker::checkConstrainingFacetsList(const QStringList &values, const QString &lexicalValue, const AnySimpleType::Ptr &itemType, const XsdFacet::Hash &facets, QString &errorMsg) const
1100 {
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.");
1105             return false;
1106         }
1107     }
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.");
1112             return false;
1113         }
1114     }
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.");
1119             return false;
1120         }
1121     }
1122     if (facets.contains(XsdFacet::Enumeration)) {
1123
1124         bool found = false;
1125
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)));
1132             }
1133
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);
1136
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);
1140
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)));
1145                 }
1146
1147                 // check if both lists have the same length
1148                 if (instanceValues.count() != facetValues.count())
1149                     continue;
1150
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)) {
1155                         matchesAll = false;
1156                         break;
1157                     }
1158                 }
1159
1160                 if (matchesAll) {
1161                     found = true;
1162                     break;
1163                 }
1164             }
1165         } else {
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)));
1170             }
1171
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);
1174
1175             const AnySimpleType::Ptr targetType = comparableType(itemType);
1176
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);
1180
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)));
1185                 }
1186
1187                 // check if both lists have the same length
1188                 if (instanceValues.count() != facetValues.count())
1189                     continue;
1190
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)) {
1195                         matchesAll = false;
1196                         break;
1197                     }
1198                 }
1199
1200                 if (matchesAll) {
1201                     found = true;
1202                     break;
1203                 }
1204             }
1205         }
1206
1207         if (!found) {
1208             errorMsg = QtXmlPatterns::tr("List content is not listed in the enumeration facet.");
1209             return false;
1210         }
1211     }
1212     if (facets.contains(XsdFacet::Pattern)) {
1213         const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
1214         const AtomicValue::List multiValue = facet->multiValue();
1215         bool found = false;
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)) {
1220                 found = true;
1221                 break;
1222             }
1223         }
1224
1225         if (!found) {
1226             errorMsg = QtXmlPatterns::tr("List content does not match pattern facet.");
1227             return false;
1228         }
1229     }
1230     if (facets.contains(XsdFacet::Assertion)) {
1231         //TODO: implement
1232     }
1233
1234     return true;
1235 }
1236
1237 bool XsdTypeChecker::checkConstrainingFacetsUnion(const QString &value, const QString &lexicalValue, const XsdSimpleType::Ptr &simpleType, const XsdFacet::Hash &facets, QString &errorMsg) const
1238 {
1239     if (facets.contains(XsdFacet::Enumeration)) {
1240         const AnySimpleType::List memberTypes = simpleType->memberTypes();
1241
1242         const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
1243
1244         // convert the instance value into an atomic string value
1245         const DerivedString<TypeString>::Ptr valueString = DerivedString<TypeString>::fromLexical(m_namePool, value);
1246
1247         // collect the facet values into a list of atomic string values
1248         const AtomicValue::List facetValues = facet->multiValue();
1249
1250         // compare the instance value against the facetValues for each member type and
1251         // search for a match
1252
1253         bool found = false;
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)) {
1258                     found = true;
1259                     break;
1260                 }
1261             }
1262         }
1263
1264         if (!found) {
1265             errorMsg = QtXmlPatterns::tr("Union content is not listed in the enumeration facet.");
1266             return false;
1267         }
1268     }
1269     if (facets.contains(XsdFacet::Pattern)) {
1270         const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
1271         const AtomicValue::List multiValue = facet->multiValue();
1272         bool found = false;
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)) {
1277                 found = true;
1278                 break;
1279             }
1280         }
1281
1282         if (!found) {
1283             errorMsg = QtXmlPatterns::tr("Union content does not match pattern facet.");
1284             return false;
1285         }
1286     }
1287     if (facets.contains(XsdFacet::Assertion)) {
1288         //TODO: implement
1289     }
1290
1291     return true;
1292 }
1293
1294 AtomicValue::Ptr XsdTypeChecker::fromLexical(const QString &value, const SchemaType::Ptr &type, const ReportContext::Ptr &context, const SourceLocationReflection *const reflection) const
1295 {
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)));
1299
1300         const QXmlName valueName = convertToQName(value);
1301         return QNameValue::fromValue(m_namePool, valueName);
1302     } else {
1303         return ValueFactory::fromLexical(value, type, context, reflection);
1304     }
1305 }
1306
1307 QXmlName XsdTypeChecker::convertToQName(const QString &name) const
1308 {
1309     const int pos = name.indexOf(QLatin1Char(':'));
1310
1311     QXmlName::PrefixCode prefixCode = 0;
1312     QXmlName::NamespaceCode namespaceCode;
1313     QXmlName::LocalNameCode localNameCode;
1314     if (pos != -1) {
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();
1320                 break;
1321             }
1322         }
1323         localNameCode = m_context->namePool()->allocateLocalName(name.mid(pos + 1));
1324     } else {
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();
1330                 break;
1331             }
1332         }
1333         localNameCode = m_context->namePool()->allocateLocalName(name);
1334     }
1335
1336     return QXmlName(namespaceCode, localNameCode, prefixCode);
1337 }
1338
1339 QT_END_NAMESPACE