b88e32dbbbb36c0c2d2410b5b42e1f9814fee9ab
[profile/ivi/qtxmlpatterns.git] / src / xmlpatterns / schema / qxsdschemachecker.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 "qxsdschemachecker_p.h"
43
44 #include "qderivedinteger_p.h"
45 #include "qderivedstring_p.h"
46 #include "qpatternplatform_p.h"
47 #include "qqnamevalue_p.h"
48 #include "qsourcelocationreflection_p.h"
49 #include "qvaluefactory_p.h"
50 #include "qxsdattributereference_p.h"
51 #include "qxsdparticlechecker_p.h"
52 #include "qxsdreference_p.h"
53 #include "qxsdschemacontext_p.h"
54 #include "qxsdschemahelper_p.h"
55 #include "qxsdschemaparsercontext_p.h"
56 #include "qxsdschematypesfactory_p.h"
57 #include "qxsdtypechecker_p.h"
58
59 #include "qxsdschemachecker_helper.cpp"
60
61 QT_BEGIN_NAMESPACE
62
63 using namespace QPatternist;
64
65 XsdSchemaChecker::XsdSchemaChecker(const QExplicitlySharedDataPointer<XsdSchemaContext> &context, const XsdSchemaParserContext *parserContext)
66     : m_context(context)
67     , m_namePool(parserContext->namePool())
68     , m_schema(parserContext->schema())
69 {
70     setupAllowedAtomicFacets();
71 }
72
73 XsdSchemaChecker::~XsdSchemaChecker()
74 {
75 }
76
77 /*
78  * This method is called after the resolver has set the base type for every
79  * type and information about deriavtion and 'is simple type vs. is complex type'
80  * are available.
81  */
82 void XsdSchemaChecker::basicCheck()
83 {
84     // first check that there is no circular inheritance, only the
85     // wxsSuperType is used here
86     checkBasicCircularInheritances();
87
88     // check the basic constraints like simple type can not inherit from complex type etc.
89     checkBasicSimpleTypeConstraints();
90     checkBasicComplexTypeConstraints();
91 }
92
93 void XsdSchemaChecker::check()
94 {
95     checkCircularInheritances();
96     checkInheritanceRestrictions();
97     checkSimpleDerivationRestrictions();
98     checkSimpleTypeConstraints();
99     checkComplexTypeConstraints();
100     checkDuplicatedAttributeUses();
101
102     checkElementConstraints();
103     checkAttributeConstraints();
104     checkAttributeUseConstraints();
105 //    checkElementDuplicates();
106 }
107
108 void XsdSchemaChecker::addComponentLocationHash(const ComponentLocationHash &hash)
109 {
110     m_componentLocationHash.unite(hash);
111 }
112
113 /**
114  * Checks whether the @p otherType is the same as @p myType or if one of its
115  * ancestors is the same as @p myType.
116  */
117 static bool matchesType(const SchemaType::Ptr &myType, const SchemaType::Ptr &otherType, QSet<SchemaType::Ptr> visitedTypes)
118 {
119     bool retval = false;
120
121     if (otherType) {
122         if (visitedTypes.contains(otherType)) {
123             return true;
124         } else {
125             visitedTypes.insert(otherType);
126         }
127         // simple types can have different varieties, so we have to check each of them
128         if (otherType->isSimpleType()) {
129             const XsdSimpleType::Ptr simpleType = otherType;
130             if (simpleType->category() == XsdSimpleType::SimpleTypeAtomic) {
131                 // for atomic type we use the same test as in SchemaType::wxsTypeMatches
132                 retval = (myType == simpleType ? true : matchesType(myType, simpleType->wxsSuperType(), visitedTypes));
133             } else if (simpleType->category() == XsdSimpleType::SimpleTypeList) {
134                 // for list type we test against the itemType property
135                 retval = (myType == simpleType->itemType() ? true : matchesType(myType, simpleType->itemType()->wxsSuperType(), visitedTypes));
136             } else if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) {
137                 // for union type we test against each member type
138                 const XsdSimpleType::List members = simpleType->memberTypes();
139                 for (int i = 0; i < members.count(); ++i) {
140                     if (myType == members.at(i) ? true : matchesType(myType, members.at(i)->wxsSuperType(), visitedTypes)) {
141                         retval = true;
142                         break;
143                     }
144                 }
145             } else {
146                 // reached xsAnySimple type whichs category is None
147                 retval = false;
148             }
149         } else {
150             // if no simple type we handle it like in SchemaType::wxsTypeMatches
151             retval = (myType == otherType ? true : matchesType(myType, otherType->wxsSuperType(), visitedTypes));
152         }
153     } else // if otherType is null it doesn't match
154         retval = false;
155
156     return retval;
157 }
158
159 /**
160  * Checks whether there is a circular inheritance for the union inheritance.
161  */
162 static bool hasCircularUnionInheritance(const XsdSimpleType::Ptr &type, const SchemaType::Ptr &otherType, NamePool::Ptr &namePool)
163 {
164     if (type == otherType) {
165         return true;
166     }
167
168     if (!otherType->isSimpleType() || !otherType->isDefinedBySchema()) {
169         return false;
170     }
171
172     const XsdSimpleType::Ptr simpleOtherType = otherType;
173
174     if (simpleOtherType->category() == XsdSimpleType::SimpleTypeUnion) {
175         const XsdSimpleType::List memberTypes = simpleOtherType->memberTypes();
176         for (int i = 0; i < memberTypes.count(); ++i) {
177             if (otherType->wxsSuperType() == type) {
178                 return true;
179             }
180             if (hasCircularUnionInheritance(type, memberTypes.at(i), namePool)) {
181                 return true;
182             }
183         }
184     }
185
186     return false;
187 }
188
189 static inline bool wxsTypeMatches(const SchemaType::Ptr &type, const SchemaType::Ptr &otherType, QSet<SchemaType::Ptr> &visitedTypes, SchemaType::Ptr &conflictingType)
190 {
191     if (!otherType)
192         return false;
193
194     if (visitedTypes.contains(otherType)) { // inheritance loop detected
195         conflictingType = otherType;
196         return true;
197     } else {
198         visitedTypes.insert(otherType);
199     }
200
201     if (type == otherType)
202         return true;
203
204     return wxsTypeMatches(type, otherType->wxsSuperType(), visitedTypes, conflictingType);
205 }
206
207 void XsdSchemaChecker::checkBasicCircularInheritances()
208 {
209     // check all global types...
210     SchemaType::List types = m_schema->types();
211
212     // .. and anonymous types
213     types << m_schema->anonymousTypes();
214
215     for (int i = 0; i < types.count(); ++i) {
216         const SchemaType::Ptr type = types.at(i);
217         const QSourceLocation location = sourceLocationForType(type);
218
219         // @see http://www.w3.org/TR/xmlschema11-1/#ct-props-correct 3)
220
221         // check normal base type inheritance
222         QSet<SchemaType::Ptr> visitedTypes;
223         SchemaType::Ptr conflictingType;
224
225         if (wxsTypeMatches(type, type->wxsSuperType(), visitedTypes, conflictingType)) {
226             if (conflictingType)
227                 m_context->error(QtXmlPatterns::tr("%1 has inheritance loop in its base type %2.")
228                                                   .arg(formatType(m_namePool, type))
229                                                   .arg(formatType(m_namePool, conflictingType)),
230                                  XsdSchemaContext::XSDError, location);
231             else
232                 m_context->error(QtXmlPatterns::tr("Circular inheritance of base type %1.").arg(formatType(m_namePool, type)), XsdSchemaContext::XSDError, location);
233
234             return;
235         }
236     }
237 }
238
239 void XsdSchemaChecker::checkCircularInheritances()
240 {
241     // check all global types...
242     SchemaType::List types = m_schema->types();
243
244     // .. and anonymous types
245     types << m_schema->anonymousTypes();
246
247     for (int i = 0; i < types.count(); ++i) {
248         const SchemaType::Ptr type = types.at(i);
249         const QSourceLocation location = sourceLocationForType(type);
250
251         // @see http://www.w3.org/TR/xmlschema11-1/#ct-props-correct 3)
252
253         // check normal base type inheritance
254         QSet<SchemaType::Ptr> visitedTypes;
255         if (matchesType(type, type->wxsSuperType(), visitedTypes)) {
256             m_context->error(QtXmlPatterns::tr("Circular inheritance of base type %1.").arg(formatType(m_namePool, type)), XsdSchemaContext::XSDError, location);
257             return;
258         }
259
260         // check union member inheritance
261         if (type->isSimpleType() && type->isDefinedBySchema()) {
262             const XsdSimpleType::Ptr simpleType = type;
263             if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) {
264                 const XsdSimpleType::List memberTypes = simpleType->memberTypes();
265                 for (int j = 0; j < memberTypes.count(); ++j) {
266                     if (hasCircularUnionInheritance(simpleType, memberTypes.at(j), m_namePool)) {
267                         m_context->error(QtXmlPatterns::tr("Circular inheritance of union %1.").arg(formatType(m_namePool, type)), XsdSchemaContext::XSDError, location);
268                         return;
269                     }
270                 }
271             }
272         }
273     }
274 }
275
276 void XsdSchemaChecker::checkInheritanceRestrictions()
277 {
278     // check all global types...
279     SchemaType::List types = m_schema->types();
280
281     // .. and anonymous types
282     types << m_schema->anonymousTypes();
283
284     for (int i = 0; i < types.count(); ++i) {
285         const SchemaType::Ptr type = types.at(i);
286         const QSourceLocation location = sourceLocationForType(type);
287
288         // check inheritance restrictions given by final property of base class
289         const SchemaType::Ptr baseType = type->wxsSuperType();
290         if (baseType->isDefinedBySchema()) {
291             if ((type->derivationMethod() == SchemaType::DerivationRestriction) && (baseType->derivationConstraints() & SchemaType::RestrictionConstraint)) {
292                 m_context->error(QtXmlPatterns::tr("%1 is not allowed to derive from %2 by restriction as the latter defines it as final.")
293                                                   .arg(formatType(m_namePool, type))
294                                                   .arg(formatType(m_namePool, baseType)), XsdSchemaContext::XSDError, location);
295                 return;
296             } else if ((type->derivationMethod() == SchemaType::DerivationExtension) && (baseType->derivationConstraints() & SchemaType::ExtensionConstraint)) {
297                 m_context->error(QtXmlPatterns::tr("%1 is not allowed to derive from %2 by extension as the latter defines it as final.")
298                                                   .arg(formatType(m_namePool, type))
299                                                   .arg(formatType(m_namePool, baseType)), XsdSchemaContext::XSDError, location);
300                 return;
301             }
302         }
303     }
304 }
305
306 void XsdSchemaChecker::checkBasicSimpleTypeConstraints()
307 {
308     // check all global types...
309     SchemaType::List types = m_schema->types();
310
311     // .. and anonymous types
312     types << m_schema->anonymousTypes();
313
314     for (int i = 0; i < types.count(); ++i) {
315         const SchemaType::Ptr type = types.at(i);
316
317         if (!type->isSimpleType())
318             continue;
319
320         const XsdSimpleType::Ptr simpleType = type;
321
322         const QSourceLocation location = sourceLocation(simpleType);
323
324         // check inheritance restrictions of simple type defined by schema constraints
325         const SchemaType::Ptr baseType = simpleType->wxsSuperType();
326
327         if (baseType->isComplexType() && (simpleType->name(m_namePool) != BuiltinTypes::xsAnySimpleType->name(m_namePool))) {
328             m_context->error(QtXmlPatterns::tr("Base type of simple type %1 cannot be complex type %2.")
329                                               .arg(formatType(m_namePool, simpleType))
330                                               .arg(formatType(m_namePool, baseType)),
331                              XsdSchemaContext::XSDError, location);
332             return;
333         }
334
335         if (baseType == BuiltinTypes::xsAnyType) {
336             if (type->name(m_namePool) != BuiltinTypes::xsAnySimpleType->name(m_namePool)) {
337                 m_context->error(QtXmlPatterns::tr("Simple type %1 cannot have direct base type %2.")
338                                                   .arg(formatType(m_namePool, simpleType))
339                                                   .arg(formatType(m_namePool, BuiltinTypes::xsAnyType)),
340                                  XsdSchemaContext::XSDError, location);
341                 return;
342             }
343         }
344     }
345 }
346
347 void XsdSchemaChecker::checkSimpleTypeConstraints()
348 {
349     // check all global types...
350     SchemaType::List types = m_schema->types();
351
352     // .. and anonymous types
353     types << m_schema->anonymousTypes();
354
355     for (int i = 0; i < types.count(); ++i) {
356         const SchemaType::Ptr type = types.at(i);
357
358         if (!type->isSimpleType())
359             continue;
360
361         const XsdSimpleType::Ptr simpleType = type;
362
363         const QSourceLocation location = sourceLocation(simpleType);
364
365         if (simpleType->category() == XsdSimpleType::None) {
366             // additional checks
367             // check that no user defined type has xs:AnySimpleType as base type (except xs:AnyAtomicType)
368             if (simpleType->wxsSuperType()->name(m_namePool) == BuiltinTypes::xsAnySimpleType->name(m_namePool)) {
369                 if (simpleType->name(m_namePool) != BuiltinTypes::xsAnyAtomicType->name(m_namePool)) {
370                     m_context->error(QtXmlPatterns::tr("Simple type %1 is not allowed to have base type %2.")
371                                                       .arg(formatType(m_namePool, simpleType))
372                                                       .arg(formatType(m_namePool, simpleType->wxsSuperType())),
373                                      XsdSchemaContext::XSDError, location);
374                     return;
375                 }
376             }
377             // check that no user defined type has xs:AnyAtomicType as base type
378             if (simpleType->wxsSuperType()->name(m_namePool) == BuiltinTypes::xsAnyAtomicType->name(m_namePool)) {
379                 m_context->error(QtXmlPatterns::tr("Simple type %1 is not allowed to have base type %2.")
380                                                   .arg(formatType(m_namePool, simpleType))
381                                                   .arg(formatType(m_namePool, simpleType->wxsSuperType())),
382                                  XsdSchemaContext::XSDError, location);
383                 return;
384             }
385         }
386
387         // @see http://www.w3.org/TR/xmlschema11-1/#d0e37310
388         if (simpleType->category() == XsdSimpleType::SimpleTypeAtomic) {
389             // 1.1
390             if ((simpleType->wxsSuperType()->category() != XsdSimpleType::SimpleTypeAtomic) && (simpleType->name(m_namePool) != BuiltinTypes::xsAnyAtomicType->name(m_namePool))) {
391                 m_context->error(QtXmlPatterns::tr("Simple type %1 can only have simple atomic type as base type.")
392                                                   .arg(formatType(m_namePool, simpleType)),
393                                  XsdSchemaContext::XSDError, location);
394             }
395             // 1.2
396             if (simpleType->wxsSuperType()->derivationConstraints() & SchemaType::RestrictionConstraint) {
397                 m_context->error(QtXmlPatterns::tr("Simple type %1 cannot derive from %2 as the latter defines restriction as final.")
398                                                   .arg(formatType(m_namePool, simpleType->wxsSuperType()))
399                                                   .arg(formatType(m_namePool, simpleType)),
400                                  XsdSchemaContext::XSDError, location);
401             }
402
403             // 1.3
404             // checked by checkConstrainingFacets  already
405         } else if (simpleType->category() == XsdSimpleType::SimpleTypeList) {
406             const AnySimpleType::Ptr itemType = simpleType->itemType();
407
408             // 2.1 or @see http://www.w3.org/TR/xmlschema-2/#cos-list-of-atomic
409             if (itemType->category() != SchemaType::SimpleTypeAtomic && itemType->category() != SchemaType::SimpleTypeUnion) {
410                 m_context->error(QtXmlPatterns::tr("Variety of item type of %1 must be either atomic or union.").arg(formatType(m_namePool, simpleType)), XsdSchemaContext::XSDError, location);
411                 return;
412             }
413
414             // 2.1 second part
415             if (itemType->category() == SchemaType::SimpleTypeUnion && itemType->isDefinedBySchema()) {
416                 const XsdSimpleType::Ptr simpleItemType = itemType;
417                 const AnySimpleType::List memberTypes = simpleItemType->memberTypes();
418                 for (int j = 0; j < memberTypes.count(); ++j) {
419                     if (memberTypes.at(j)->category() != SchemaType::SimpleTypeAtomic) {
420                         m_context->error(QtXmlPatterns::tr("Variety of member types of %1 must be atomic.").arg(formatType(m_namePool, simpleItemType)), XsdSchemaContext::XSDError, location);
421                         return;
422                     }
423                 }
424             }
425
426             // 2.2.1
427             if (simpleType->wxsSuperType()->name(m_namePool) == BuiltinTypes::xsAnySimpleType->name(m_namePool)) {
428                 if (itemType->isSimpleType() && itemType->isDefinedBySchema()) {
429                     const XsdSimpleType::Ptr simpleItemType = itemType;
430
431                     // 2.2.1.1
432                     if (simpleItemType->derivationConstraints() & XsdSimpleType::ListConstraint) {
433                         m_context->error(QtXmlPatterns::tr("%1 is not allowed to derive from %2 by list as the latter defines it as final.")
434                                                           .arg(formatType(m_namePool, simpleType))
435                                                           .arg(formatType(m_namePool, simpleItemType)), XsdSchemaContext::XSDError, location);
436                         return;
437                     }
438
439                     // 2.2.1.2
440                     const XsdFacet::Hash facets = simpleType->facets();
441                     XsdFacet::HashIterator it(facets);
442
443                     bool invalidFacetFound = false;
444                     while (it.hasNext()) {
445                         it.next();
446                         if (it.key() != XsdFacet::WhiteSpace) {
447                             invalidFacetFound = true;
448                             break;
449                         }
450                     }
451
452                     if (invalidFacetFound) {
453                         m_context->error(QtXmlPatterns::tr("Simple type %1 is only allowed to have %2 facet.")
454                                                           .arg(formatType(m_namePool, simpleType))
455                                                           .arg(formatKeyword("whiteSpace")),
456                                          XsdSchemaContext::XSDError, location);
457                         return;
458                     }
459                 }
460             } else { // 2.2.2
461                 // 2.2.2.1
462                 if (simpleType->wxsSuperType()->category() != XsdSimpleType::SimpleTypeList) {
463                     m_context->error(QtXmlPatterns::tr("Base type of simple type %1 must have variety of type list.").arg(formatType(m_namePool, simpleType)), XsdSchemaContext::XSDError, location);
464                     return;
465                 }
466
467                 // 2.2.2.2
468                 if (simpleType->wxsSuperType()->derivationConstraints() & SchemaType::RestrictionConstraint) {
469                     m_context->error(QtXmlPatterns::tr("Base type of simple type %1 has defined derivation by restriction as final.").arg(formatType(m_namePool, simpleType)), XsdSchemaContext::XSDError, location);
470                     return;
471                 }
472
473                 // 2.2.2.3
474                 if (!XsdSchemaHelper::isSimpleDerivationOk(itemType, XsdSimpleType::Ptr(simpleType->wxsSuperType())->itemType(), SchemaType::DerivationConstraints())) {
475                     m_context->error(QtXmlPatterns::tr("Item type of base type does not match item type of %1.").arg(formatType(m_namePool, simpleType)), XsdSchemaContext::XSDError, location);
476                     return;
477                 }
478
479                 // 2.2.2.4
480                 const XsdFacet::Hash facets = simpleType->facets();
481                 XsdFacet::HashIterator it(facets);
482
483                 bool invalidFacetFound = false;
484                 XsdFacet::Type invalidFacetType = XsdFacet::None;
485                 while (it.hasNext()) {
486                     it.next();
487                     const XsdFacet::Type facetType = it.key();
488                     if (facetType != XsdFacet::Length &&
489                         facetType != XsdFacet::MinimumLength &&
490                         facetType != XsdFacet::MaximumLength &&
491                         facetType != XsdFacet::WhiteSpace &&
492                         facetType != XsdFacet::Pattern &&
493                         facetType != XsdFacet::Enumeration) {
494                         invalidFacetType = facetType;
495                         invalidFacetFound = true;
496                         break;
497                     }
498                 }
499
500                 if (invalidFacetFound) {
501                     m_context->error(QtXmlPatterns::tr("Simple type %1 contains not allowed facet type %2.")
502                                                       .arg(formatType(m_namePool, simpleType))
503                                                       .arg(formatKeyword(XsdFacet::typeName(invalidFacetType))),
504                                      XsdSchemaContext::XSDError, location);
505                     return;
506                 }
507
508                 // 2.2.2.5
509                 // TODO: check value constraints
510             }
511
512
513         } else if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) {
514             const AnySimpleType::List memberTypes = simpleType->memberTypes();
515
516             if (simpleType->wxsSuperType()->name(m_namePool) == BuiltinTypes::xsAnySimpleType->name(m_namePool)) { // 3.1.1
517                 // 3.3.1.1
518                 for (int i = 0; i < memberTypes.count(); ++i) {
519                     const AnySimpleType::Ptr memberType = memberTypes.at(i);
520
521                     if (memberType->derivationConstraints() & XsdSimpleType::UnionConstraint) {
522                         m_context->error(QtXmlPatterns::tr("%1 is not allowed to derive from %2 by union as the latter defines it as final.")
523                                                           .arg(formatType(m_namePool, simpleType))
524                                                           .arg(formatType(m_namePool, memberType)), XsdSchemaContext::XSDError, location);
525                         return;
526                     }
527                 }
528
529                 // 3.3.1.2
530                 if (!simpleType->facets().isEmpty()) {
531                     m_context->error(QtXmlPatterns::tr("%1 is not allowed to have any facets.")
532                                                       .arg(formatType(m_namePool, simpleType)),
533                                      XsdSchemaContext::XSDError, location);
534                     return;
535                 }
536             } else {
537                 // 3.1.2.1
538                 if (simpleType->wxsSuperType()->category() != SchemaType::SimpleTypeUnion) {
539                     m_context->error(QtXmlPatterns::tr("Base type %1 of simple type %2 must have variety of union.")
540                                                       .arg(formatType(m_namePool, simpleType->wxsSuperType()))
541                                                       .arg(formatType(m_namePool, simpleType)),
542                                      XsdSchemaContext::XSDError, location);
543                     return;
544                 }
545
546                 // 3.1.2.2
547                 if (simpleType->wxsSuperType()->derivationConstraints() & SchemaType::DerivationRestriction) {
548                     m_context->error(QtXmlPatterns::tr("Base type %1 of simple type %2 is not allowed to have restriction in %3 attribute.")
549                                                       .arg(formatType(m_namePool, simpleType->wxsSuperType()))
550                                                       .arg(formatType(m_namePool, simpleType))
551                                                       .arg(formatAttribute("final")),
552                                      XsdSchemaContext::XSDError, location);
553                     return;
554                 }
555
556                 //3.1.2.3
557                 if (simpleType->wxsSuperType()->isDefinedBySchema()) {
558                     const XsdSimpleType::Ptr simpleBaseType(simpleType->wxsSuperType());
559
560                     AnySimpleType::List baseMemberTypes = simpleBaseType->memberTypes();
561                     for (int i = 0; i < memberTypes.count(); ++i) {
562                         const AnySimpleType::Ptr memberType = memberTypes.at(i);
563                         const AnySimpleType::Ptr baseMemberType = baseMemberTypes.at(i);
564
565                         if (!XsdSchemaHelper::isSimpleDerivationOk(memberType, baseMemberType, SchemaType::DerivationConstraints())) {
566                             m_context->error(QtXmlPatterns::tr("Member type %1 cannot be derived from member type %2 of %3's base type %4.")
567                                                               .arg(formatType(m_namePool, memberType))
568                                                               .arg(formatType(m_namePool, baseMemberType))
569                                                               .arg(formatType(m_namePool, simpleType))
570                                                               .arg(formatType(m_namePool, simpleBaseType)),
571                                              XsdSchemaContext::XSDError, location);
572                         }
573                     }
574                 }
575
576                 // 3.1.2.4
577                 const XsdFacet::Hash facets = simpleType->facets();
578                 XsdFacet::HashIterator it(facets);
579
580                 bool invalidFacetFound = false;
581                 XsdFacet::Type invalidFacetType = XsdFacet::None;
582                 while (it.hasNext()) {
583                     it.next();
584                     const XsdFacet::Type facetType = it.key();
585                     if (facetType != XsdFacet::Pattern &&
586                         facetType != XsdFacet::Enumeration) {
587                         invalidFacetType = facetType;
588                         invalidFacetFound = true;
589                         break;
590                     }
591                 }
592
593                 if (invalidFacetFound) {
594                     m_context->error(QtXmlPatterns::tr("Simple type %1 contains not allowed facet type %2.")
595                                                       .arg(formatType(m_namePool, simpleType))
596                                                       .arg(formatKeyword(XsdFacet::typeName(invalidFacetType))),
597                                      XsdSchemaContext::XSDError, location);
598                     return;
599                 }
600
601                 // 3.1.2.5
602                 // TODO: check value constraints
603             }
604         }
605     }
606 }
607
608 void XsdSchemaChecker::checkBasicComplexTypeConstraints()
609 {
610     // check all global types...
611     SchemaType::List types = m_schema->types();
612
613     // .. and anonymous types
614     types << m_schema->anonymousTypes();
615
616     for (int i = 0; i < types.count(); ++i) {
617         const SchemaType::Ptr type = types.at(i);
618
619         if (!type->isComplexType() || !type->isDefinedBySchema())
620             continue;
621
622         const XsdComplexType::Ptr complexType = type;
623
624         const QSourceLocation location = sourceLocation(complexType);
625
626         // check inheritance restrictions of complex type defined by schema constraints
627         const SchemaType::Ptr baseType = complexType->wxsSuperType();
628
629         // @see http://www.w3.org/TR/xmlschema11-1/#ct-props-correct 2)
630         if (baseType->isSimpleType() && (complexType->derivationMethod() != XsdComplexType::DerivationExtension)) {
631             m_context->error(QtXmlPatterns::tr("Derivation method of %1 must be extension because the base type %2 is a simple type.")
632                                               .arg(formatType(m_namePool, complexType))
633                                               .arg(formatType(m_namePool, baseType)),
634                              XsdSchemaContext::XSDError, location);
635             return;
636         }
637     }
638 }
639
640 void XsdSchemaChecker::checkComplexTypeConstraints()
641 {
642     // check all global types...
643     SchemaType::List types = m_schema->types();
644
645     // .. and anonymous types
646     types << m_schema->anonymousTypes();
647
648     for (int i = 0; i < types.count(); ++i) {
649         const SchemaType::Ptr type = types.at(i);
650
651         if (!type->isComplexType() || !type->isDefinedBySchema())
652             continue;
653
654         const XsdComplexType::Ptr complexType = type;
655
656         const QSourceLocation location = sourceLocation(complexType);
657
658         if (complexType->contentType()->particle()) {
659             XsdElement::Ptr duplicatedElement;
660             if (XsdParticleChecker::hasDuplicatedElements(complexType->contentType()->particle(), m_namePool, duplicatedElement)) {
661                 m_context->error(QtXmlPatterns::tr("Complex type %1 has duplicated element %2 in its content model.")
662                                                   .arg(formatType(m_namePool, complexType))
663                                                   .arg(formatKeyword(duplicatedElement->displayName(m_namePool))),
664                                  XsdSchemaContext::XSDError, location);
665                 return;
666             }
667
668             if (!XsdParticleChecker::isUPAConform(complexType->contentType()->particle(), m_namePool)) {
669                 m_context->error(QtXmlPatterns::tr("Complex type %1 has non-deterministic content.")
670                                                   .arg(formatType(m_namePool, complexType)),
671                                  XsdSchemaContext::XSDError, location);
672                 return;
673             }
674         }
675
676         // check inheritance restrictions of complex type defined by schema constraints
677         const SchemaType::Ptr baseType = complexType->wxsSuperType();
678
679         // @see http://www.w3.org/TR/xmlschema11-1/#cos-ct-extends
680         if (complexType->derivationMethod() == XsdComplexType::DerivationExtension) {
681             if (baseType->isComplexType() && baseType->isDefinedBySchema()) {
682                 const XsdComplexType::Ptr complexBaseType = baseType;
683
684                 // we can skip 1.1 here, as it is tested in checkInheritanceRestrictions() already
685
686                 // 1.2 and 1.3
687                 QString errorMsg;
688                 if (!XsdSchemaHelper::isValidAttributeUsesExtension(complexType->attributeUses(), complexBaseType->attributeUses(),
689                                                                     complexType->attributeWildcard(), complexBaseType->attributeWildcard(), m_context, errorMsg)) {
690                     m_context->error(QtXmlPatterns::tr("Attributes of complex type %1 are not a valid extension of the attributes of base type %2: %3.")
691                                                       .arg(formatType(m_namePool, complexType))
692                                                       .arg(formatType(m_namePool, baseType))
693                                                       .arg(errorMsg),
694                                      XsdSchemaContext::XSDError, location);
695                     return;
696                 }
697
698                 // 1.4
699                 bool validContentType = false;
700                 if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple && complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Simple) {
701                     if (complexType->contentType()->simpleType() == complexBaseType->contentType()->simpleType()) {
702                         validContentType = true; // 1.4.1
703                     }
704                 } else if (complexType->contentType()->variety() == XsdComplexType::ContentType::Empty && complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Empty) {
705                     validContentType = true; // 1.4.2
706                 } else { // 1.4.3
707                     if (complexType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly || complexType->contentType()->variety() == XsdComplexType::ContentType::Mixed) { // 1.4.3.1
708                         if (complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Empty) {
709                             validContentType = true; // 1.4.3.2.1
710                         } else { // 1.4.3.2.2
711                             if (complexType->contentType()->particle()) {  // our own check
712                                 if ((complexType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly && complexBaseType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly) ||
713                                            (complexType->contentType()->variety() == XsdComplexType::ContentType::Mixed && complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Mixed)) {  // 1.4.3.2.2.1
714                                     if (isValidParticleExtension(complexType->contentType()->particle(), complexBaseType->contentType()->particle())) {
715                                         validContentType = true; // 1.4.3.2.2.2
716                                     }
717                                 }
718                             }
719                             // 1.4.3.2.2.3  and 1.4.3.2.2.4 handle 'open content' that we do not support yet
720                         }
721                     }
722                 }
723
724                 // 1.5 WTF?!?
725
726                 if (!validContentType) {
727                     m_context->error(QtXmlPatterns::tr("Content model of complex type %1 is not a valid extension of content model of %2.")
728                                                       .arg(formatType(m_namePool, complexType))
729                                                       .arg(formatType(m_namePool, complexBaseType)),
730                                      XsdSchemaContext::XSDError, location);
731                     return;
732                 }
733
734             } else if (baseType->isSimpleType()) {
735                 // 2.1
736                 if (complexType->contentType()->variety() != XsdComplexType::ContentType::Simple) {
737                     m_context->error(QtXmlPatterns::tr("Complex type %1 must have simple content.")
738                                                       .arg(formatType(m_namePool, complexType)),
739                                      XsdSchemaContext::XSDError, location);
740                     return;
741                 }
742
743                 if (complexType->contentType()->simpleType() != baseType) {
744                     m_context->error(QtXmlPatterns::tr("Complex type %1 must have the same simple type as its base class %2.")
745                                                       .arg(formatType(m_namePool, complexType))
746                                                       .arg(formatType(m_namePool, baseType)),
747                                      XsdSchemaContext::XSDError, location);
748                     return;
749                 }
750
751                 // 2.2 tested in checkInheritanceRestrictions() already
752             }
753         } else if (complexType->derivationMethod() == XsdComplexType::DerivationRestriction) {
754             // @see http://www.w3.org/TR/xmlschema11-1/#d0e21402
755             const SchemaType::Ptr baseType(complexType->wxsSuperType());
756
757             bool derivationOk = false;
758             QString errorMsg;
759
760             // we can partly skip 1 here, as it is tested in checkInheritanceRestrictions() already
761             if (baseType->isComplexType()) {
762
763                 // 2.1
764                 if (baseType->name(m_namePool) == BuiltinTypes::xsAnyType->name(m_namePool)) {
765                     derivationOk = true;
766                 }
767
768                 if (baseType->isDefinedBySchema()) {
769                     const XsdComplexType::Ptr complexBaseType(baseType);
770
771                     // 2.2.1
772                     if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple) {
773                         // 2.2.2.1
774                         if (XsdSchemaHelper::isSimpleDerivationOk(complexType->contentType()->simpleType(), complexBaseType->contentType()->simpleType(), SchemaType::DerivationConstraints()))
775                             derivationOk = true;
776
777                         // 2.2.2.2
778                         if (complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Mixed) {
779                             if (XsdSchemaHelper::isParticleEmptiable(complexBaseType->contentType()->particle()))
780                                 derivationOk = true;
781                         }
782                     }
783
784                     // 2.3.1
785                     if (complexType->contentType()->variety() == XsdComplexType::ContentType::Empty) {
786                         // 2.3.2.1
787                         if (complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Empty)
788                             derivationOk = true;
789
790                         // 2.3.2.2
791                         if (complexBaseType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly || complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Mixed) {
792                             if (XsdSchemaHelper::isParticleEmptiable(complexBaseType->contentType()->particle()))
793                                 derivationOk = true;
794                         }
795                     }
796
797                     // 2.4.1.1
798                     if (((complexType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly) &&
799                          (complexBaseType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly || complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Mixed)) ||
800                         // 2.4.1.2
801                         (complexType->contentType()->variety() == XsdComplexType::ContentType::Mixed && complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Mixed)) {
802
803                         // 2.4.2
804                         if (XsdParticleChecker::subsumes(complexBaseType->contentType()->particle(), complexType->contentType()->particle(), m_context, errorMsg))
805                             derivationOk = true;
806                     }
807                 }
808             }
809
810             if (!derivationOk) {
811                 m_context->error(QtXmlPatterns::tr("Complex type %1 cannot be derived from base type %2%3.")
812                                                   .arg(formatType(m_namePool, complexType))
813                                                   .arg(formatType(m_namePool, baseType))
814                                                   .arg(errorMsg.isEmpty() ? QString() : QLatin1String(": ") + errorMsg),
815                                  XsdSchemaContext::XSDError, location);
816                 return;
817             }
818
819             if (baseType->isDefinedBySchema()) {
820                 const XsdComplexType::Ptr complexBaseType(baseType);
821
822                 QString errorMsg;
823                 if (!XsdSchemaHelper::isValidAttributeUsesRestriction(complexType->attributeUses(), complexBaseType->attributeUses(),
824                                                                       complexType->attributeWildcard(), complexBaseType->attributeWildcard(), m_context, errorMsg)) {
825                     m_context->error(QtXmlPatterns::tr("Attributes of complex type %1 are not a valid restriction from the attributes of base type %2: %3.")
826                                                       .arg(formatType(m_namePool, complexType))
827                                                       .arg(formatType(m_namePool, baseType))
828                                                       .arg(errorMsg),
829                                      XsdSchemaContext::XSDError, location);
830                     return;
831                 }
832             }
833         }
834
835         // check that complex type with simple content is not allowed to inherit from
836         // built in complex type xs:AnyType
837         if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple) {
838             if (baseType->name(m_namePool) == BuiltinTypes::xsAnyType->name(m_namePool)) {
839                 m_context->error(QtXmlPatterns::tr("Complex type %1 with simple content cannot be derived from complex base type %2.")
840                                                   .arg(formatType(m_namePool, complexType))
841                                                   .arg(formatType(m_namePool, baseType)),
842                                  XsdSchemaContext::XSDError, location);
843                 return;
844             }
845         }
846     }
847 }
848
849 void XsdSchemaChecker::checkSimpleDerivationRestrictions()
850 {
851     // check all global types...
852     SchemaType::List types = m_schema->types();
853
854     // .. and anonymous types
855     types << m_schema->anonymousTypes();
856
857     for (int i = 0; i < types.count(); ++i) {
858         const SchemaType::Ptr type = types.at(i);
859
860         if (type->isComplexType())
861             continue;
862
863         if (type->category() != SchemaType::SimpleTypeList && type->category() != SchemaType::SimpleTypeUnion)
864             continue;
865
866         const XsdSimpleType::Ptr simpleType = type;
867         const QSourceLocation location = sourceLocation(simpleType);
868
869         // check all simple types derived by list
870         if (simpleType->category() == XsdSimpleType::SimpleTypeList) {
871             const AnySimpleType::Ptr itemType = simpleType->itemType();
872
873             if (itemType->isComplexType()) {
874                 m_context->error(QtXmlPatterns::tr("Item type of simple type %1 cannot be a complex type.")
875                                                   .arg(formatType(m_namePool, simpleType)),
876                                  XsdSchemaContext::XSDError, location);
877                 return;
878             }
879
880
881             if (itemType->isSimpleType() && itemType->isDefinedBySchema()) {
882                 const XsdSimpleType::Ptr simpleItemType = itemType;
883                 if (simpleItemType->derivationConstraints() & XsdSimpleType::ListConstraint) {
884                     m_context->error(QtXmlPatterns::tr("%1 is not allowed to derive from %2 by list as the latter defines it as final.")
885                                                       .arg(formatType(m_namePool, simpleType))
886                                                       .arg(formatType(m_namePool, simpleItemType)),
887                                      XsdSchemaContext::XSDError, location);
888                     return;
889                 }
890             }
891
892             // @see http://www.w3.org/TR/xmlschema-2/#cos-list-of-atomic
893             if (itemType->category() != SchemaType::SimpleTypeAtomic && itemType->category() != SchemaType::SimpleTypeUnion) {
894                 m_context->error(QtXmlPatterns::tr("Variety of item type of %1 must be either atomic or union.").arg(formatType(m_namePool, simpleType)), XsdSchemaContext::XSDError, location);
895                 return;
896             }
897
898             if (itemType->category() == SchemaType::SimpleTypeUnion && itemType->isDefinedBySchema()) {
899                 const XsdSimpleType::Ptr simpleItemType = itemType;
900                 const AnySimpleType::List memberTypes = simpleItemType->memberTypes();
901                 for (int j = 0; j < memberTypes.count(); ++j) {
902                     if (memberTypes.at(j)->category() != SchemaType::SimpleTypeAtomic) {
903                         m_context->error(QtXmlPatterns::tr("Variety of member types of %1 must be atomic.").arg(formatType(m_namePool, simpleItemType)), XsdSchemaContext::XSDError, location);
904                         return;
905                     }
906                 }
907             }
908         }
909
910         // check all simple types derived by union
911         if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) {
912             const AnySimpleType::List memberTypes = simpleType->memberTypes();
913
914             for (int i = 0; i < memberTypes.count(); ++i) {
915                 const AnySimpleType::Ptr memberType = memberTypes.at(i);
916
917                 if (memberType->isComplexType()) {
918                     m_context->error(QtXmlPatterns::tr("Member type of simple type %1 cannot be a complex type.")
919                                                       .arg(formatType(m_namePool, simpleType)),
920                                      XsdSchemaContext::XSDError, location);
921                     return;
922                 }
923
924                 // @see http://www.w3.org/TR/xmlschema-2/#cos-no-circular-unions
925                 if (simpleType->name(m_namePool) == memberType->name(m_namePool)) {
926                     m_context->error(QtXmlPatterns::tr("%1 is not allowed to have a member type with the same name as itself.")
927                                                       .arg(formatType(m_namePool, simpleType)),
928                                      XsdSchemaContext::XSDError, location);
929                     return;
930                 }
931
932                 if (memberType->isSimpleType() && memberType->isDefinedBySchema()) {
933                     const XsdSimpleType::Ptr simpleMemberType = memberType;
934                     if (simpleMemberType->derivationConstraints() & XsdSimpleType::UnionConstraint) {
935                         m_context->error(QtXmlPatterns::tr("%1 is not allowed to derive from %2 by union as the latter defines it as final.")
936                                                           .arg(formatType(m_namePool, simpleType))
937                                                           .arg(formatType(m_namePool, simpleMemberType)),
938                                          XsdSchemaContext::XSDError, location);
939                         return;
940                     }
941                 }
942             }
943         }
944     }
945 }
946
947 void XsdSchemaChecker::checkConstrainingFacets()
948 {
949     // first the global simple types
950     const SchemaType::List types = m_schema->types();
951     for (int i = 0; i < types.count(); ++i) {
952         if (!(types.at(i)->isSimpleType()) || !(types.at(i)->isDefinedBySchema()))
953             continue;
954
955         const XsdSimpleType::Ptr simpleType = types.at(i);
956         checkConstrainingFacets(simpleType->facets(), simpleType);
957     }
958
959     // and afterwards all anonymous simple types
960     const SchemaType::List anonymousTypes = m_schema->anonymousTypes();
961     for (int i = 0; i < anonymousTypes.count(); ++i) {
962         if (!(anonymousTypes.at(i)->isSimpleType()) || !(anonymousTypes.at(i)->isDefinedBySchema()))
963             continue;
964
965         const XsdSimpleType::Ptr simpleType = anonymousTypes.at(i);
966         checkConstrainingFacets(simpleType->facets(), simpleType);
967     }
968 }
969
970 void XsdSchemaChecker::checkConstrainingFacets(const XsdFacet::Hash &facets, const XsdSimpleType::Ptr &simpleType)
971 {
972     if (facets.isEmpty())
973         return;
974
975     SchemaType::Ptr comparableBaseType;
976     if (!simpleType->wxsSuperType()->isDefinedBySchema())
977         comparableBaseType = simpleType->wxsSuperType();
978     else
979         comparableBaseType = simpleType->primitiveType();
980
981     const XsdSchemaSourceLocationReflection reflection(sourceLocation(simpleType));
982
983     // start checks
984     if (facets.contains(XsdFacet::Length)) {
985         const XsdFacet::Ptr lengthFacet = facets.value(XsdFacet::Length);
986         const DerivedInteger<TypeNonNegativeInteger>::Ptr lengthValue = lengthFacet->value();
987
988         // @see http://www.w3.org/TR/xmlschema-2/#length-minLength-maxLength
989         if (facets.contains(XsdFacet::MinimumLength)) {
990             const XsdFacet::Ptr minLengthFacet = facets.value(XsdFacet::MinimumLength);
991             const DerivedInteger<TypeNonNegativeInteger>::Ptr minLengthValue = minLengthFacet->value();
992
993             bool foundSuperMinimumLength = false;
994             SchemaType::Ptr baseType = simpleType->wxsSuperType();
995             while (baseType) {
996                 const XsdFacet::Hash baseFacets = m_context->facetsForType(baseType);
997                 if (baseFacets.contains(XsdFacet::MinimumLength) && !baseFacets.contains(XsdFacet::Length)) {
998                     const DerivedInteger<TypeNonNegativeInteger>::Ptr superValue(baseFacets.value(XsdFacet::MinimumLength)->value());
999                     if (minLengthValue->toInteger() == superValue->toInteger()) {
1000                         foundSuperMinimumLength = true;
1001                         break;
1002                     }
1003                 }
1004
1005                 baseType = baseType->wxsSuperType();
1006             }
1007
1008             if ((minLengthValue->toInteger() > lengthValue->toInteger()) || !foundSuperMinimumLength) {
1009                 m_context->error(QtXmlPatterns::tr("%1 facet collides with %2 facet.")
1010                                                   .arg(formatKeyword("length"))
1011                                                   .arg(formatKeyword("minLength")),
1012                                  XsdSchemaContext::XSDError, sourceLocation(simpleType));
1013                 return;
1014             }
1015         }
1016
1017         // @see http://www.w3.org/TR/xmlschema-2/#length-minLength-maxLength
1018         if (facets.contains(XsdFacet::MaximumLength)) {
1019             const XsdFacet::Ptr maxLengthFacet = facets.value(XsdFacet::MaximumLength);
1020             const DerivedInteger<TypeNonNegativeInteger>::Ptr maxLengthValue = maxLengthFacet->value();
1021
1022             bool foundSuperMaximumLength = false;
1023             SchemaType::Ptr baseType = simpleType->wxsSuperType();
1024             while (baseType) {
1025                 const XsdFacet::Hash baseFacets = m_context->facetsForType(baseType);
1026                 if (baseFacets.contains(XsdFacet::MaximumLength) && !baseFacets.contains(XsdFacet::Length)) {
1027                     const DerivedInteger<TypeNonNegativeInteger>::Ptr superValue(baseFacets.value(XsdFacet::MaximumLength)->value());
1028                     if (maxLengthValue->toInteger() == superValue->toInteger()) {
1029                         foundSuperMaximumLength = true;
1030                         break;
1031                     }
1032                 }
1033
1034                 baseType = baseType->wxsSuperType();
1035             }
1036
1037             if ((maxLengthValue->toInteger() < lengthValue->toInteger()) || !foundSuperMaximumLength) {
1038                 m_context->error(QtXmlPatterns::tr("%1 facet collides with %2 facet.")
1039                                                   .arg(formatKeyword("length"))
1040                                                   .arg(formatKeyword("maxLength")),
1041                                  XsdSchemaContext::XSDError, sourceLocation(simpleType));
1042                 return;
1043             }
1044         }
1045
1046         // @see http://www.w3.org/TR/xmlschema-2/#length-valid-restriction
1047         if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) {
1048             const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType());
1049             if (baseFacets.contains(XsdFacet::Length)) {
1050                 const DerivedInteger<TypeNonNegativeInteger>::Ptr baseValue = baseFacets.value(XsdFacet::Length)->value();
1051                 if (lengthValue->toInteger() != baseValue->toInteger()) {
1052                     m_context->error(QtXmlPatterns::tr("%1 facet must have the same value as %2 facet of base type.")
1053                                                       .arg(formatKeyword("length"))
1054                                                       .arg(formatKeyword("length")),
1055                                      XsdSchemaContext::XSDError, sourceLocation(simpleType));
1056                     return;
1057                 }
1058             }
1059         }
1060     }
1061
1062     if (facets.contains(XsdFacet::MinimumLength)) {
1063         const XsdFacet::Ptr minLengthFacet = facets.value(XsdFacet::MinimumLength);
1064         const DerivedInteger<TypeNonNegativeInteger>::Ptr minLengthValue = minLengthFacet->value();
1065
1066         if (facets.contains(XsdFacet::MaximumLength)) {
1067             const XsdFacet::Ptr maxLengthFacet = facets.value(XsdFacet::MaximumLength);
1068             const DerivedInteger<TypeNonNegativeInteger>::Ptr maxLengthValue = maxLengthFacet->value();
1069
1070             // @see http://www.w3.org/TR/xmlschema-2/#minLength-less-than-equal-to-maxLength
1071             if (maxLengthValue->toInteger() < minLengthValue->toInteger()) {
1072                 m_context->error(QtXmlPatterns::tr("%1 facet collides with %2 facet.")
1073                                                   .arg(formatKeyword("minLength"))
1074                                                   .arg(formatKeyword("maxLength")),
1075                                  XsdSchemaContext::XSDError, sourceLocation(simpleType));
1076                 return;
1077             }
1078
1079             // @see http://www.w3.org/TR/xmlschema-2/#minLength-valid-restriction
1080             //TODO: check parent facets
1081         }
1082
1083         // @see http://www.w3.org/TR/xmlschema-2/#minLength-valid-restriction
1084         if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) {
1085             const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType());
1086             if (baseFacets.contains(XsdFacet::MinimumLength)) {
1087                 const DerivedInteger<TypeNonNegativeInteger>::Ptr baseValue = baseFacets.value(XsdFacet::MinimumLength)->value();
1088                 if (minLengthValue->toInteger() < baseValue->toInteger()) {
1089                     m_context->error(QtXmlPatterns::tr("%1 facet must be equal or greater than %2 facet of base type.")
1090                                                       .arg(formatKeyword("minLength"))
1091                                                       .arg(formatKeyword("minLength")),
1092                                      XsdSchemaContext::XSDError, sourceLocation(simpleType));
1093                     return;
1094                 }
1095             }
1096         }
1097     }
1098     if (facets.contains(XsdFacet::MaximumLength)) {
1099         const XsdFacet::Ptr maxLengthFacet = facets.value(XsdFacet::MaximumLength);
1100         const DerivedInteger<TypeNonNegativeInteger>::Ptr maxLengthValue = maxLengthFacet->value();
1101
1102         // @see http://www.w3.org/TR/xmlschema-2/#maxLength-valid-restriction
1103         if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) {
1104             const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType());
1105             if (baseFacets.contains(XsdFacet::MaximumLength)) {
1106                 const DerivedInteger<TypeNonNegativeInteger>::Ptr baseValue(baseFacets.value(XsdFacet::MaximumLength)->value());
1107                 if (maxLengthValue->toInteger() > baseValue->toInteger()) {
1108                     m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type.")
1109                                                       .arg(formatKeyword("maxLength"))
1110                                                       .arg(formatKeyword("maxLength")),
1111                                      XsdSchemaContext::XSDError, sourceLocation(simpleType));
1112                     return;
1113                 }
1114             }
1115         }
1116     }
1117     if (facets.contains(XsdFacet::Pattern)) {
1118         //  we keep the patterns in separated facets
1119         // @see http://www.w3.org/TR/xmlschema-2/#src-multiple-patterns
1120
1121         // @see http://www.w3.org/TR/xmlschema-2/#cvc-pattern-valid
1122         const XsdFacet::Ptr patternFacet = facets.value(XsdFacet::Pattern);
1123         const AtomicValue::List multiValue = patternFacet->multiValue();
1124
1125         for (int i = 0; i < multiValue.count(); ++i) {
1126             const DerivedString<TypeString>::Ptr value = multiValue.at(i);
1127             const QRegExp exp = PatternPlatform::parsePattern(value->stringValue(), m_context, &reflection);
1128             if (!exp.isValid()) {
1129                 m_context->error(QtXmlPatterns::tr("%1 facet contains invalid regular expression").arg(formatKeyword("pattern.")), XsdSchemaContext::XSDError, sourceLocation(simpleType));
1130                 return;
1131             }
1132         }
1133     }
1134     if (facets.contains(XsdFacet::Enumeration)) {
1135         // @see http://www.w3.org/TR/xmlschema-2/#src-multiple-enumerations
1136
1137         const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
1138
1139         if (BuiltinTypes::xsNOTATION->wxsTypeMatches(simpleType)) {
1140             const AtomicValue::List notationNames = facet->multiValue();
1141             for (int k = 0; k < notationNames.count(); ++k) {
1142                 const QNameValue::Ptr notationName = notationNames.at(k);
1143                 if (!m_schema->notation(notationName->qName())) {
1144                     m_context->error(QtXmlPatterns::tr("Unknown notation %1 used in %2 facet.")
1145                                                       .arg(formatKeyword(m_namePool, notationName->qName()))
1146                                                       .arg(formatKeyword("enumeration")),
1147                                      XsdSchemaContext::XSDError, sourceLocation(simpleType));
1148                 }
1149             }
1150         } else if (BuiltinTypes::xsQName->wxsTypeMatches(simpleType)) {
1151         } else {
1152             const XsdTypeChecker checker(m_context, QVector<QXmlName>(), sourceLocation(simpleType));
1153
1154             const AnySimpleType::Ptr baseType = simpleType->wxsSuperType();
1155             const XsdFacet::Hash baseFacets = XsdTypeChecker::mergedFacetsForType(baseType, m_context);
1156
1157             const AtomicValue::List multiValue = facet->multiValue();
1158             for (int k = 0; k < multiValue.count(); ++k) {
1159                 const QString stringValue = multiValue.at(k)->as<DerivedString<TypeString> >()->stringValue();
1160                 const QString actualValue = XsdTypeChecker::normalizedValue(stringValue, baseFacets);
1161
1162                 QString errorMsg;
1163                 if (!checker.isValidString(actualValue, baseType, errorMsg)) {
1164                     m_context->error(QtXmlPatterns::tr("%1 facet contains invalid value %2: %3.")
1165                                                       .arg(formatKeyword("enumeration"))
1166                                                       .arg(formatData(stringValue))
1167                                                       .arg(errorMsg),
1168                                      XsdSchemaContext::XSDError, sourceLocation(simpleType));
1169                     return;
1170                 }
1171             }
1172         }
1173     }
1174     if (facets.contains(XsdFacet::WhiteSpace)) {
1175         const XsdFacet::Ptr whiteSpaceFacet = facets.value(XsdFacet::WhiteSpace);
1176         const DerivedString<TypeString>::Ptr whiteSpaceValue = whiteSpaceFacet->value();
1177
1178         // @see http://www.w3.org/TR/xmlschema-2/#whiteSpace-valid-restriction
1179         if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) {
1180             const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType());
1181             if (baseFacets.contains(XsdFacet::WhiteSpace)) {
1182                 const QString value = whiteSpaceValue->stringValue();
1183                 const QString baseValue = DerivedString<TypeString>::Ptr(baseFacets.value(XsdFacet::WhiteSpace)->value())->stringValue();
1184                 if (value == XsdSchemaToken::toString(XsdSchemaToken::Replace) || value == XsdSchemaToken::toString(XsdSchemaToken::Preserve)) {
1185                     if (baseValue == XsdSchemaToken::toString(XsdSchemaToken::Collapse)) {
1186                         m_context->error(QtXmlPatterns::tr("%1 facet cannot be %2 or %3 if %4 facet of base type is %5.")
1187                                                           .arg(formatKeyword("whiteSpace"))
1188                                                           .arg(formatData("replace"))
1189                                                           .arg(formatData("preserve"))
1190                                                           .arg(formatKeyword("whiteSpace"))
1191                                                           .arg(formatData("collapse")),
1192                                          XsdSchemaContext::XSDError, sourceLocation(simpleType));
1193                         return;
1194                     }
1195                 }
1196                 if (value == XsdSchemaToken::toString(XsdSchemaToken::Preserve) && baseValue == XsdSchemaToken::toString(XsdSchemaToken::Replace)) {
1197                     m_context->error(QtXmlPatterns::tr("%1 facet cannot be %2 if %3 facet of base type is %4.")
1198                                                       .arg(formatKeyword("whiteSpace"))
1199                                                       .arg(formatData("preserve"))
1200                                                       .arg(formatKeyword("whiteSpace"))
1201                                                       .arg(formatData("replace")),
1202                                      XsdSchemaContext::XSDError, sourceLocation(simpleType));
1203                     return;
1204                 }
1205             }
1206         }
1207     }
1208     if (facets.contains(XsdFacet::MaximumInclusive)) {
1209         const XsdFacet::Ptr maxFacet = facets.value(XsdFacet::MaximumInclusive);
1210
1211         // @see http://www.w3.org/TR/xmlschema-2/#minInclusive-less-than-equal-to-maxInclusive
1212         if (facets.contains(XsdFacet::MinimumInclusive)) {
1213             const XsdFacet::Ptr minFacet = facets.value(XsdFacet::MinimumInclusive);
1214
1215             if (comparableBaseType) {
1216                 if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterThan, maxFacet->value(), comparableBaseType, m_context, &reflection)) {
1217                     m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet.")
1218                                                       .arg(formatKeyword("minInclusive"))
1219                                                       .arg(formatKeyword("maxInclusive")),
1220                                      XsdSchemaContext::XSDError, sourceLocation(simpleType));
1221                     return;
1222                 }
1223             }
1224         }
1225
1226         // @see http://www.w3.org/TR/xmlschema-2/#maxInclusive-valid-restriction
1227         if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) {
1228             const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType());
1229             if (baseFacets.contains(XsdFacet::MaximumInclusive)) {
1230                 const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumInclusive);
1231                 if (comparableBaseType) {
1232                     if (XsdSchemaHelper::constructAndCompare(maxFacet->value(), AtomicComparator::OperatorGreaterThan, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
1233                         m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type.")
1234                                                           .arg(formatKeyword("maxInclusive"))
1235                                                           .arg(formatKeyword("maxInclusive")),
1236                                          XsdSchemaContext::XSDError, sourceLocation(simpleType));
1237                         return;
1238                     }
1239                 }
1240             }
1241             if (baseFacets.contains(XsdFacet::MaximumExclusive)) {
1242                 const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumExclusive);
1243                 if (comparableBaseType) {
1244                     if (XsdSchemaHelper::constructAndCompare(maxFacet->value(), AtomicComparator::OperatorGreaterOrEqual, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
1245                         m_context->error(QtXmlPatterns::tr("%1 facet must be less than %2 facet of base type.")
1246                                                           .arg(formatKeyword("maxInclusive"))
1247                                                           .arg(formatKeyword("maxExclusive")),
1248                                          XsdSchemaContext::XSDError, sourceLocation(simpleType));
1249                         return;
1250                     }
1251                 }
1252             }
1253         }
1254     }
1255     if (facets.contains(XsdFacet::MaximumExclusive)) {
1256         const XsdFacet::Ptr maxFacet = facets.value(XsdFacet::MaximumExclusive);
1257
1258         // @see http://www.w3.org/TR/xmlschema-2/#maxInclusive-maxExclusive
1259         if (facets.contains(XsdFacet::MaximumInclusive)) {
1260             m_context->error(QtXmlPatterns::tr("%1 facet and %2 facet cannot appear together.")
1261                                               .arg(formatKeyword("maxExclusive"))
1262                                               .arg(formatKeyword("maxInclusive")),
1263                              XsdSchemaContext::XSDError, sourceLocation(simpleType));
1264             return;
1265         }
1266
1267         // @see http://www.w3.org/TR/xmlschema-2/#minExclusive-less-than-equal-to-maxExclusive
1268         if (facets.contains(XsdFacet::MinimumExclusive)) {
1269             const XsdFacet::Ptr minFacet = facets.value(XsdFacet::MinimumExclusive);
1270             if (comparableBaseType) {
1271                 if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterThan, maxFacet->value(), comparableBaseType, m_context, &reflection)) {
1272                     m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet.")
1273                                                       .arg(formatKeyword("minExclusive"))
1274                                                       .arg(formatKeyword("maxExclusive")),
1275                                      XsdSchemaContext::XSDError, sourceLocation(simpleType));
1276                     return;
1277                 }
1278             }
1279         }
1280
1281         // @see http://www.w3.org/TR/xmlschema-2/#maxExclusive-valid-restriction
1282         if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) {
1283             const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType());
1284             if (baseFacets.contains(XsdFacet::MaximumExclusive)) {
1285                 const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumExclusive);
1286                 if (comparableBaseType) {
1287                     if (XsdSchemaHelper::constructAndCompare(maxFacet->value(), AtomicComparator::OperatorGreaterThan, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
1288                         m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type.")
1289                                                           .arg(formatKeyword("maxExclusive"))
1290                                                           .arg(formatKeyword("maxExclusive")),
1291                                          XsdSchemaContext::XSDError, sourceLocation(simpleType));
1292                         return;
1293                     }
1294                 }
1295             }
1296             if (baseFacets.contains(XsdFacet::MaximumInclusive)) {
1297                 const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumInclusive);
1298                 if (comparableBaseType) {
1299                     if (XsdSchemaHelper::constructAndCompare(maxFacet->value(), AtomicComparator::OperatorGreaterThan, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
1300                         m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type.")
1301                                                           .arg(formatKeyword("maxExclusive"))
1302                                                           .arg(formatKeyword("maxInclusive")),
1303                                          XsdSchemaContext::XSDError, sourceLocation(simpleType));
1304                         return;
1305                     }
1306                 }
1307             }
1308             if (baseFacets.contains(XsdFacet::MinimumInclusive)) {
1309                 const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MinimumInclusive);
1310                 if (comparableBaseType) {
1311                     if (XsdSchemaHelper::constructAndCompare(maxFacet->value(), AtomicComparator::OperatorLessOrEqual, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
1312                         m_context->error(QtXmlPatterns::tr("%1 facet must be greater than %2 facet of base type.")
1313                                                           .arg(formatKeyword("maxExclusive"))
1314                                                           .arg(formatKeyword("minInclusive")),
1315                                          XsdSchemaContext::XSDError, sourceLocation(simpleType));
1316                         return;
1317                     }
1318                 }
1319             }
1320             if (baseFacets.contains(XsdFacet::MinimumExclusive)) {
1321                 const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MinimumExclusive);
1322                 if (comparableBaseType) {
1323                     if (XsdSchemaHelper::constructAndCompare(maxFacet->value(), AtomicComparator::OperatorLessOrEqual, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
1324                         m_context->error(QtXmlPatterns::tr("%1 facet must be greater than %2 facet of base type.")
1325                                                           .arg(formatKeyword("maxExclusive"))
1326                                                           .arg(formatKeyword("minExclusive")),
1327                                          XsdSchemaContext::XSDError, sourceLocation(simpleType));
1328                         return;
1329                     }
1330                 }
1331             }
1332         }
1333     }
1334     if (facets.contains(XsdFacet::MinimumExclusive)) {
1335         const XsdFacet::Ptr minFacet = facets.value(XsdFacet::MinimumExclusive);
1336
1337         // @see http://www.w3.org/TR/xmlschema-2/#minInclusive-minExclusive
1338         if (facets.contains(XsdFacet::MinimumInclusive)) {
1339             m_context->error(QtXmlPatterns::tr("%1 facet and %2 facet cannot appear together.")
1340                                               .arg(formatKeyword("minExclusive"))
1341                                               .arg(formatKeyword("minInclusive")),
1342                              XsdSchemaContext::XSDError, sourceLocation(simpleType));
1343             return;
1344         }
1345
1346         // @see http://www.w3.org/TR/xmlschema-2/#minExclusive-less-than-maxInclusive
1347         if (facets.contains(XsdFacet::MaximumInclusive)) {
1348             const XsdFacet::Ptr maxFacet = facets.value(XsdFacet::MaximumInclusive);
1349             if (comparableBaseType) {
1350                 if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterOrEqual, maxFacet->value(), comparableBaseType, m_context, &reflection)) {
1351                     m_context->error(QtXmlPatterns::tr("%1 facet must be less than %2 facet.")
1352                                                       .arg(formatKeyword("minExclusive"))
1353                                                       .arg(formatKeyword("maxInclusive")),
1354                                      XsdSchemaContext::XSDError, sourceLocation(simpleType));
1355                     return;
1356                 }
1357             }
1358         }
1359
1360         // @see http://www.w3.org/TR/xmlschema-2/#minExclusive-valid-restriction
1361         if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) {
1362             const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType());
1363             if (baseFacets.contains(XsdFacet::MinimumExclusive)) {
1364                 const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MinimumExclusive);
1365                 if (comparableBaseType) {
1366                     if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorLessThan, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
1367                         m_context->error(QtXmlPatterns::tr("%1 facet must be greater than or equal to %2 facet of base type.")
1368                                                           .arg(formatKeyword("minExclusive"))
1369                                                           .arg(formatKeyword("minExclusive")),
1370                                          XsdSchemaContext::XSDError, sourceLocation(simpleType));
1371                         return;
1372                     }
1373                 }
1374             }
1375             if (baseFacets.contains(XsdFacet::MaximumExclusive)) {
1376                 const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumExclusive);
1377                 if (comparableBaseType) {
1378                     if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterOrEqual, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
1379                         m_context->error(QtXmlPatterns::tr("%1 facet must be less than %2 facet of base type.")
1380                                                           .arg(formatKeyword("minExclusive"))
1381                                                           .arg(formatKeyword("maxExclusive")),
1382                                          XsdSchemaContext::XSDError, sourceLocation(simpleType));
1383                         return;
1384                     }
1385                 }
1386             }
1387             if (baseFacets.contains(XsdFacet::MaximumInclusive)) {
1388                 const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumInclusive);
1389                 if (comparableBaseType) {
1390                     if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterThan, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
1391                         m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type.")
1392                                                           .arg(formatKeyword("minExclusive"))
1393                                                           .arg(formatKeyword("maxInclusive")),
1394                                          XsdSchemaContext::XSDError, sourceLocation(simpleType));
1395                         return;
1396                     }
1397                 }
1398             }
1399         }
1400     }
1401     if (facets.contains(XsdFacet::MinimumInclusive)) {
1402         const XsdFacet::Ptr minFacet = facets.value(XsdFacet::MinimumInclusive);
1403
1404         // @see http://www.w3.org/TR/xmlschema-2/#minInclusive-less-than-maxExclusive
1405         if (facets.contains(XsdFacet::MaximumExclusive)) {
1406             const XsdFacet::Ptr maxFacet = facets.value(XsdFacet::MaximumExclusive);
1407             if (comparableBaseType) {
1408                 if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterOrEqual, maxFacet->value(), comparableBaseType, m_context, &reflection)) {
1409                     m_context->error(QtXmlPatterns::tr("%1 facet must be less than %2 facet.")
1410                                                       .arg(formatKeyword("minInclusive"))
1411                                                       .arg(formatKeyword("maxExclusive")),
1412                                      XsdSchemaContext::XSDError, sourceLocation(simpleType));
1413                     return;
1414                 }
1415             }
1416         }
1417
1418         // @see http://www.w3.org/TR/xmlschema-2/#minInclusive-valid-restriction
1419         if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) {
1420             const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType());
1421             if (baseFacets.contains(XsdFacet::MinimumInclusive)) {
1422                 const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MinimumInclusive);
1423                 if (comparableBaseType) {
1424                     if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorLessThan, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
1425                         m_context->error(QtXmlPatterns::tr("%1 facet must be greater than or equal to %2 facet of base type.")
1426                                                           .arg(formatKeyword("minInclusive"))
1427                                                           .arg(formatKeyword("minInclusive")),
1428                                          XsdSchemaContext::XSDError, sourceLocation(simpleType));
1429                         return;
1430                     }
1431                 }
1432             }
1433             if (baseFacets.contains(XsdFacet::MinimumExclusive)) {
1434                 const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MinimumExclusive);
1435                 if (comparableBaseType) {
1436                     if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorLessOrEqual, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
1437                         m_context->error(QtXmlPatterns::tr("%1 facet must be greater than %2 facet of base type.")
1438                                                           .arg(formatKeyword("minInclusive"))
1439                                                           .arg(formatKeyword("minExclusive")),
1440                                          XsdSchemaContext::XSDError, sourceLocation(simpleType));
1441                         return;
1442                     }
1443                 }
1444             }
1445             if (baseFacets.contains(XsdFacet::MaximumInclusive)) {
1446                 const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumInclusive);
1447                 if (comparableBaseType) {
1448                     if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterThan, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
1449                         m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type.")
1450                                                           .arg(formatKeyword("minInclusive"))
1451                                                           .arg(formatKeyword("maxInclusive")),
1452                                          XsdSchemaContext::XSDError, sourceLocation(simpleType));
1453                         return;
1454                     }
1455                 }
1456             }
1457             if (baseFacets.contains(XsdFacet::MaximumExclusive)) {
1458                 const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumExclusive);
1459                 if (comparableBaseType) {
1460                     if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterOrEqual, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
1461                         m_context->error(QtXmlPatterns::tr("%1 facet must be less than %2 facet of base type.")
1462                                                           .arg(formatKeyword("minInclusive"))
1463                                                           .arg(formatKeyword("maxExclusive")),
1464                                          XsdSchemaContext::XSDError, sourceLocation(simpleType));
1465                         return;
1466                     }
1467                 }
1468             }
1469         }
1470     }
1471     if (facets.contains(XsdFacet::TotalDigits)) {
1472         const XsdFacet::Ptr totalDigitsFacet = facets.value(XsdFacet::TotalDigits);
1473         const DerivedInteger<TypeNonNegativeInteger>::Ptr totalDigitsValue = totalDigitsFacet->value();
1474
1475         // @see http://www.w3.org/TR/xmlschema-2/#totalDigits-valid-restriction
1476         if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) {
1477             const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType());
1478             if (baseFacets.contains(XsdFacet::TotalDigits)) {
1479                 const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::TotalDigits);
1480                 const DerivedInteger<TypeNonNegativeInteger>::Ptr baseValue = baseFacet->value();
1481
1482                 if (totalDigitsValue->toInteger() > baseValue->toInteger()) {
1483                     m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type.")
1484                                                       .arg(formatKeyword("totalDigits"))
1485                                                       .arg(formatKeyword("totalDigits")),
1486                                      XsdSchemaContext::XSDError, sourceLocation(simpleType));
1487                     return;
1488                 }
1489             }
1490         }
1491     }
1492     if (facets.contains(XsdFacet::FractionDigits)) {
1493         const XsdFacet::Ptr fractionDigitsFacet = facets.value(XsdFacet::FractionDigits);
1494         const DerivedInteger<TypeNonNegativeInteger>::Ptr fractionDigitsValue = fractionDigitsFacet->value();
1495
1496         // http://www.w3.org/TR/xmlschema-2/#fractionDigits-totalDigits
1497         if (facets.contains(XsdFacet::TotalDigits)) {
1498             const XsdFacet::Ptr totalDigitsFacet = facets.value(XsdFacet::TotalDigits);
1499             const DerivedInteger<TypeNonNegativeInteger>::Ptr totalDigitsValue = totalDigitsFacet->value();
1500
1501             if (fractionDigitsValue->toInteger() > totalDigitsValue->toInteger()) {
1502                 m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet.")
1503                                                   .arg(formatKeyword("fractionDigits"))
1504                                                   .arg(formatKeyword("totalDigits")),
1505                                  XsdSchemaContext::XSDError, sourceLocation(simpleType));
1506                 return;
1507             }
1508         }
1509
1510         // @see http://www.w3.org/TR/xmlschema-2/#fractionDigits-valid-restriction
1511         if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) {
1512             const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType());
1513             if (baseFacets.contains(XsdFacet::FractionDigits)) {
1514                 const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::FractionDigits);
1515                 const DerivedInteger<TypeNonNegativeInteger>::Ptr baseValue = baseFacet->value();
1516
1517                 if (fractionDigitsValue->toInteger() > baseValue->toInteger()) {
1518                     m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type.")
1519                                                       .arg(formatKeyword("fractionDigits"))
1520                                                       .arg(formatKeyword("fractionDigits")),
1521                                      XsdSchemaContext::XSDError, sourceLocation(simpleType));
1522                     return;
1523                 }
1524             }
1525         }
1526     }
1527
1528
1529     // check whether facets are allowed for simple types variety
1530     if (simpleType->wxsSuperType()->category() == SchemaType::SimpleTypeAtomic) {
1531         if (simpleType->primitiveType()) {
1532             const QXmlName primitiveTypeName = simpleType->primitiveType()->name(m_namePool);
1533             if (m_allowedAtomicFacets.contains(primitiveTypeName)) {
1534                 const QSet<XsdFacet::Type> allowedFacets = m_allowedAtomicFacets.value(primitiveTypeName);
1535                 QSet<XsdFacet::Type> availableFacets = facets.keys().toSet();
1536
1537                 if (!availableFacets.subtract(allowedFacets).isEmpty()) {
1538                     m_context->error(QtXmlPatterns::tr("Simple type contains not allowed facet %1.")
1539                                                       .arg(formatKeyword(XsdFacet::typeName(availableFacets.toList().first()))),
1540                                      XsdSchemaContext::XSDError, sourceLocation(simpleType));
1541                     return;
1542                 }
1543             }
1544         }
1545     } else if (simpleType->wxsSuperType()->category() == SchemaType::SimpleTypeList) {
1546         if (facets.contains(XsdFacet::MaximumInclusive) || facets.contains(XsdFacet::MinimumInclusive) ||
1547             facets.contains(XsdFacet::MaximumExclusive) || facets.contains(XsdFacet::MinimumExclusive) ||
1548             facets.contains(XsdFacet::TotalDigits) || facets.contains(XsdFacet::FractionDigits))
1549         {
1550             m_context->error(QtXmlPatterns::tr("%1, %2, %3, %4, %5 and %6 facets are not allowed when derived by list.")
1551                                               .arg(formatKeyword("maxInclusive"))
1552                                               .arg(formatKeyword("maxExclusive"))
1553                                               .arg(formatKeyword("minInclusive"))
1554                                               .arg(formatKeyword("minExclusive"))
1555                                               .arg(formatKeyword("totalDigits"))
1556                                               .arg(formatKeyword("fractionDigits")),
1557                              XsdSchemaContext::XSDError, sourceLocation(simpleType));
1558         }
1559     } else if (simpleType->wxsSuperType()->category() == SchemaType::SimpleTypeUnion) {
1560         if (facets.contains(XsdFacet::MaximumInclusive) || facets.contains(XsdFacet::MinimumInclusive) ||
1561             facets.contains(XsdFacet::MaximumExclusive) || facets.contains(XsdFacet::MinimumExclusive) ||
1562             facets.contains(XsdFacet::TotalDigits) || facets.contains(XsdFacet::FractionDigits) ||
1563             facets.contains(XsdFacet::MinimumLength) || facets.contains(XsdFacet::MaximumLength) ||
1564             facets.contains(XsdFacet::Length) || facets.contains(XsdFacet::WhiteSpace))
1565         {
1566             m_context->error(QtXmlPatterns::tr("Only %1 and %2 facets are allowed when derived by union.")
1567                                               .arg(formatKeyword("pattern"))
1568                                               .arg(formatKeyword("enumeration")),
1569                              XsdSchemaContext::XSDError, sourceLocation(simpleType));
1570         }
1571     }
1572
1573     // check whether value of facet matches the value space of the simple types base type
1574     const SchemaType::Ptr baseType = simpleType->wxsSuperType();
1575     if (!baseType->isDefinedBySchema()) {
1576         const XsdSchemaSourceLocationReflection reflection(sourceLocation(simpleType));
1577
1578         XsdFacet::HashIterator it(facets);
1579         while (it.hasNext()) {
1580             it.next();
1581             const XsdFacet::Ptr facet = it.value();
1582             if (facet->type() == XsdFacet::MaximumInclusive ||
1583                 facet->type() == XsdFacet::MaximumExclusive ||
1584                 facet->type() == XsdFacet::MinimumInclusive ||
1585                 facet->type() == XsdFacet::MinimumExclusive) {
1586                 const DerivedString<TypeString>::Ptr stringValue = facet->value();
1587                 const AtomicValue::Ptr value = ValueFactory::fromLexical(stringValue->stringValue(), baseType, m_context, &reflection);
1588                 if (value->hasError()) {
1589                     m_context->error(QtXmlPatterns::tr("%1 contains %2 facet with invalid data: %3.")
1590                                                       .arg(formatType(m_namePool, simpleType))
1591                                                       .arg(formatKeyword(XsdFacet::typeName(facet->type())))
1592                                                       .arg(formatData(stringValue->stringValue())),
1593                                      XsdSchemaContext::XSDError, sourceLocation(simpleType));
1594                     return;
1595                 }
1596             }
1597
1598             // @see http://www.w3.org/TR/xmlschema-2/#enumeration-valid-restriction
1599             if (facet->type() == XsdFacet::Enumeration && baseType != BuiltinTypes::xsNOTATION) {
1600                 const AtomicValue::List multiValue = facet->multiValue();
1601                 for (int j = 0; j < multiValue.count(); ++j) {
1602                     const QString stringValue = DerivedString<TypeString>::Ptr(multiValue.at(j))->stringValue();
1603                     const AtomicValue::Ptr value = ValueFactory::fromLexical(stringValue, baseType, m_context, &reflection);
1604                     if (value->hasError()) {
1605                         m_context->error(QtXmlPatterns::tr("%1 contains %2 facet with invalid data: %3.")
1606                                                           .arg(formatType(m_namePool, simpleType))
1607                                                           .arg(formatKeyword(XsdFacet::typeName(XsdFacet::Enumeration)))
1608                                                           .arg(formatData(stringValue)),
1609                                          XsdSchemaContext::XSDError, sourceLocation(simpleType));
1610                         return;
1611                     }
1612                 }
1613             }
1614         }
1615     }
1616 }
1617
1618 void XsdSchemaChecker::checkDuplicatedAttributeUses()
1619 {
1620     // first all global attribute groups
1621     const XsdAttributeGroup::List attributeGroups = m_schema->attributeGroups();
1622     for (int i = 0; i < attributeGroups.count(); ++i) {
1623         const XsdAttributeGroup::Ptr attributeGroup = attributeGroups.at(i);
1624         const XsdAttributeUse::List uses = attributeGroup->attributeUses();
1625
1626         // @see http://www.w3.org/TR/xmlschema11-1/#ct-props-correct 4)
1627         XsdAttribute::Ptr conflictingAttribute;
1628         if (hasDuplicatedAttributeUses(uses, conflictingAttribute)) {
1629             m_context->error(QtXmlPatterns::tr("Attribute group %1 contains attribute %2 twice.")
1630                                               .arg(formatKeyword(attributeGroup->displayName(m_namePool)))
1631                                               .arg(formatKeyword(conflictingAttribute->displayName(m_namePool))),
1632                              XsdSchemaContext::XSDError, sourceLocation(attributeGroup));
1633             return;
1634         }
1635
1636         // @see http://www.w3.org/TR/xmlschema11-1/#ct-props-correct 5)
1637         if (hasMultipleIDAttributeUses(uses)) {
1638             m_context->error(QtXmlPatterns::tr("Attribute group %1 contains two different attributes that both have types derived from %2.")
1639                                               .arg(formatKeyword(attributeGroup->displayName(m_namePool)))
1640                                               .arg(formatType(m_namePool, BuiltinTypes::xsID)),
1641                              XsdSchemaContext::XSDError, sourceLocation(attributeGroup));
1642             return;
1643         }
1644
1645         if (hasConstraintIDAttributeUse(uses, conflictingAttribute)) {
1646             m_context->error(QtXmlPatterns::tr("Attribute group %1 contains attribute %2 that has value constraint but type that inherits from %3.")
1647                                               .arg(formatKeyword(attributeGroup->displayName(m_namePool)))
1648                                               .arg(formatKeyword(conflictingAttribute->displayName(m_namePool)))
1649                                               .arg(formatType(m_namePool, BuiltinTypes::xsID)),
1650                              XsdSchemaContext::XSDError, sourceLocation(attributeGroup));
1651             return;
1652         }
1653     }
1654
1655     // then the global and anonymous complex types
1656     SchemaType::List types = m_schema->types();
1657     types << m_schema->anonymousTypes();
1658
1659     for (int i = 0; i < types.count(); ++i) {
1660         if (!(types.at(i)->isComplexType()) || !types.at(i)->isDefinedBySchema())
1661             continue;
1662
1663         const XsdComplexType::Ptr complexType = types.at(i);
1664         const XsdAttributeUse::List attributeUses = complexType->attributeUses();
1665
1666         // @see http://www.w3.org/TR/xmlschema11-1/#ct-props-correct 4)
1667         XsdAttribute::Ptr conflictingAttribute;
1668         if (hasDuplicatedAttributeUses(attributeUses, conflictingAttribute)) {
1669             m_context->error(QtXmlPatterns::tr("Complex type %1 contains attribute %2 twice.")
1670                                               .arg(formatType(m_namePool, complexType))
1671                                               .arg(formatKeyword(conflictingAttribute->displayName(m_namePool))),
1672                              XsdSchemaContext::XSDError, sourceLocation(complexType));
1673             return;
1674         }
1675
1676         // @see http://www.w3.org/TR/xmlschema11-1/#ct-props-correct 5)
1677         if (hasMultipleIDAttributeUses(attributeUses)) {
1678             m_context->error(QtXmlPatterns::tr("Complex type %1 contains two different attributes that both have types derived from %2.")
1679                                               .arg(formatType(m_namePool, complexType))
1680                                               .arg(formatType(m_namePool, BuiltinTypes::xsID)),
1681                              XsdSchemaContext::XSDError, sourceLocation(complexType));
1682             return;
1683         }
1684
1685         if (hasConstraintIDAttributeUse(attributeUses, conflictingAttribute)) {
1686             m_context->error(QtXmlPatterns::tr("Complex type %1 contains attribute %2 that has value constraint but type that inherits from %3.")
1687                                               .arg(formatType(m_namePool, complexType))
1688                                               .arg(formatKeyword(conflictingAttribute->displayName(m_namePool)))
1689                                               .arg(formatType(m_namePool, BuiltinTypes::xsID)),
1690                              XsdSchemaContext::XSDError, sourceLocation(complexType));
1691             return;
1692         }
1693     }
1694 }
1695
1696 void XsdSchemaChecker::checkElementConstraints()
1697 {
1698     const QSet<XsdElement::Ptr> elements = collectAllElements(m_schema);
1699     QSetIterator<XsdElement::Ptr> it(elements);
1700     while (it.hasNext()) {
1701         const XsdElement::Ptr element = it.next();
1702
1703         // @see http://www.w3.org/TR/xmlschema11-1/#e-props-correct
1704
1705         // 2 and xs:ID check
1706         if (element->valueConstraint()) {
1707             const SchemaType::Ptr type = element->type();
1708
1709             AnySimpleType::Ptr targetType;
1710             if (type->isSimpleType() && type->category() == SchemaType::SimpleTypeAtomic) {
1711                 targetType = type;
1712
1713                 // if it is a XsdSimpleType, use its primitive type as target type
1714                 if (type->isDefinedBySchema())
1715                     targetType = XsdSimpleType::Ptr(type)->primitiveType();
1716
1717             } else if (type->isComplexType() && type->isDefinedBySchema()) {
1718                 const XsdComplexType::Ptr complexType(type);
1719
1720                 if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple) {
1721                     const AnySimpleType::Ptr simpleType = complexType->contentType()->simpleType();
1722                     if (simpleType->category() == AnySimpleType::SimpleTypeAtomic) {
1723                         targetType = simpleType;
1724
1725                         if (simpleType->isDefinedBySchema())
1726                             targetType = XsdSimpleType::Ptr(simpleType)->primitiveType();
1727                     }
1728                 } else if (complexType->contentType()->variety() != XsdComplexType::ContentType::Mixed) {
1729                     m_context->error(QtXmlPatterns::tr("Element %1 is not allowed to have a value constraint if its base type is complex.")
1730                                                       .arg(formatKeyword(element->displayName(m_namePool))),
1731                                      XsdSchemaContext::XSDError, sourceLocation(element));
1732                     return;
1733                 }
1734             }
1735             if ((targetType == BuiltinTypes::xsID) || BuiltinTypes::xsID->wxsTypeMatches(type)) {
1736                 m_context->error(QtXmlPatterns::tr("Element %1 is not allowed to have a value constraint if its type is derived from %2.")
1737                                                   .arg(formatKeyword(element->displayName(m_namePool)))
1738                                                   .arg(formatType(m_namePool, BuiltinTypes::xsID)),
1739                                  XsdSchemaContext::XSDError, sourceLocation(element));
1740                 return;
1741             }
1742
1743             if (type->isSimpleType()) {
1744                 QString errorMsg;
1745                 if (!isValidValue(element->valueConstraint()->value(), type, errorMsg)) {
1746                     m_context->error(QtXmlPatterns::tr("Value constraint of element %1 is not of elements type: %2.")
1747                                                       .arg(formatKeyword(element->displayName(m_namePool)))
1748                                                       .arg(errorMsg),
1749                                      XsdSchemaContext::XSDError, sourceLocation(element));
1750                     return;
1751                 }
1752             } else if (type->isComplexType() && type->isDefinedBySchema()) {
1753                 const XsdComplexType::Ptr complexType(type);
1754                 if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple) {
1755                     QString errorMsg;
1756                     if (!isValidValue(element->valueConstraint()->value(), complexType->contentType()->simpleType(), errorMsg)) {
1757                         m_context->error(QtXmlPatterns::tr("Value constraint of element %1 is not of elements type: %2.")
1758                                                           .arg(formatKeyword(element->displayName(m_namePool)))
1759                                                           .arg(errorMsg),
1760                                          XsdSchemaContext::XSDError, sourceLocation(element));
1761                         return;
1762                     }
1763                 }
1764             }
1765         }
1766
1767         if (!element->substitutionGroupAffiliations().isEmpty()) {
1768             // 3
1769             if (!element->scope() || element->scope()->variety() != XsdElement::Scope::Global) {
1770                 m_context->error(QtXmlPatterns::tr("Element %1 is not allowed to have substitution group affiliation as it is no global element.").arg(formatKeyword(element->displayName(m_namePool))),
1771                                  XsdSchemaContext::XSDError, sourceLocation(element));
1772                 return;
1773             }
1774
1775             // 4
1776             const XsdElement::List affiliations = element->substitutionGroupAffiliations();
1777             for (int i = 0; i < affiliations.count(); ++i) {
1778                 const XsdElement::Ptr affiliation = affiliations.at(i);
1779
1780                 bool derivationOk = false;
1781                 if (element->type()->isComplexType() && affiliation->type()->isComplexType()) {
1782                     if (XsdSchemaHelper::isComplexDerivationOk(element->type(), affiliation->type(), affiliation->substitutionGroupExclusions())) {
1783                         derivationOk = true;
1784                     }
1785                 }
1786                 if (element->type()->isComplexType() && affiliation->type()->isSimpleType()) {
1787                     if (XsdSchemaHelper::isComplexDerivationOk(element->type(), affiliation->type(), affiliation->substitutionGroupExclusions())) {
1788                         derivationOk = true;
1789                     }
1790                 }
1791                 if (element->type()->isSimpleType()) {
1792                     if (XsdSchemaHelper::isSimpleDerivationOk(element->type(), affiliation->type(), affiliation->substitutionGroupExclusions())) {
1793                         derivationOk = true;
1794                     }
1795                 }
1796
1797                 if (!derivationOk) {
1798                     m_context->error(QtXmlPatterns::tr("Type of element %1 cannot be derived from type of substitution group affiliation.").arg(formatKeyword(element->displayName(m_namePool))),
1799                                      XsdSchemaContext::XSDError, sourceLocation(element));
1800                     return;
1801                 }
1802             }
1803
1804             // 5 was checked in XsdSchemaResolver::resolveSubstitutionGroupAffiliations() already
1805         }
1806     }
1807 }
1808
1809 void XsdSchemaChecker::checkAttributeConstraints()
1810 {
1811     // all global attributes
1812     XsdAttribute::List attributes = m_schema->attributes();
1813
1814     // and all local attributes
1815     SchemaType::List types = m_schema->types();
1816     types << m_schema->anonymousTypes();
1817
1818     for (int i = 0; i < types.count(); ++i) {
1819         if (!types.at(i)->isComplexType() || !types.at(i)->isDefinedBySchema())
1820             continue;
1821
1822         const XsdComplexType::Ptr complexType(types.at(i));
1823         const XsdAttributeUse::List uses = complexType->attributeUses();
1824         for (int j = 0; j < uses.count(); ++j)
1825             attributes.append(uses.at(j)->attribute());
1826     }
1827
1828     for (int i = 0; i < attributes.count(); ++i) {
1829         const XsdAttribute::Ptr attribute = attributes.at(i);
1830
1831         if (!attribute->valueConstraint())
1832             continue;
1833
1834         if (attribute->valueConstraint()->variety() == XsdAttribute::ValueConstraint::Default || attribute->valueConstraint()->variety() == XsdAttribute::ValueConstraint::Fixed) {
1835             const SchemaType::Ptr type = attribute->type();
1836
1837             QString errorMsg;
1838             if (!isValidValue(attribute->valueConstraint()->value(), attribute->type(), errorMsg)) {
1839                 m_context->error(QtXmlPatterns::tr("Value constraint of attribute %1 is not of attributes type: %2.")
1840                                                   .arg(formatKeyword(attribute->displayName(m_namePool)))
1841                                                   .arg(errorMsg),
1842                                  XsdSchemaContext::XSDError, sourceLocation(attribute));
1843                 return;
1844             }
1845         }
1846
1847         if (BuiltinTypes::xsID->wxsTypeMatches(attribute->type())) {
1848             m_context->error(QtXmlPatterns::tr("Attribute %1 has value constraint but has type derived from %2.")
1849                                               .arg(formatKeyword(attribute->displayName(m_namePool)))
1850                                               .arg(formatType(m_namePool, BuiltinTypes::xsID)),
1851                              XsdSchemaContext::XSDError, sourceLocation(attribute));
1852             return;
1853         }
1854     }
1855 }
1856
1857 bool XsdSchemaChecker::isValidValue(const QString &stringValue, const AnySimpleType::Ptr &type, QString &errorMsg) const
1858 {
1859     if (BuiltinTypes::xsAnySimpleType->name(m_namePool) == type->name(m_namePool))
1860         return true; // no need to check xs:anyType content
1861
1862     const XsdFacet::Hash facets = XsdTypeChecker::mergedFacetsForType(type, m_context);
1863     const QString actualValue = XsdTypeChecker::normalizedValue(stringValue, facets);
1864
1865     const XsdTypeChecker checker(m_context, QVector<QXmlName>(), QSourceLocation(QUrl(QLatin1String("http://dummy.org")), 1, 1));
1866     return checker.isValidString(actualValue, type, errorMsg);
1867 }
1868
1869 void XsdSchemaChecker::checkAttributeUseConstraints()
1870 {
1871     XsdComplexType::List complexTypes;
1872
1873     SchemaType::List types = m_schema->types();
1874     types << m_schema->anonymousTypes();
1875
1876     for (int i = 0; i < types.count(); ++i) {
1877         const SchemaType::Ptr type = types.at(i);
1878         if (type->isComplexType() && type->isDefinedBySchema())
1879             complexTypes.append(XsdComplexType::Ptr(type));
1880     }
1881
1882     for (int i = 0; i < complexTypes.count(); ++i) {
1883         const XsdComplexType::Ptr complexType(complexTypes.at(i));
1884         const SchemaType::Ptr baseType = complexType->wxsSuperType();
1885         if (!baseType || !baseType->isComplexType() || !baseType->isDefinedBySchema())
1886             continue;
1887
1888         const XsdComplexType::Ptr complexBaseType(baseType);
1889
1890         const XsdAttributeUse::List attributeUses = complexType->attributeUses();
1891         QHash<QXmlName, XsdAttributeUse::Ptr> lookupHash;
1892         for (int j = 0; j < attributeUses.count(); ++j)
1893             lookupHash.insert(attributeUses.at(j)->attribute()->name(m_namePool), attributeUses.at(j));
1894
1895         const XsdAttributeUse::List baseAttributeUses = complexBaseType->attributeUses();
1896         for (int j = 0; j < baseAttributeUses.count(); ++j) {
1897             const XsdAttributeUse::Ptr baseAttributeUse = baseAttributeUses.at(j);
1898
1899             if (lookupHash.contains(baseAttributeUse->attribute()->name(m_namePool))) {
1900                 const XsdAttributeUse::Ptr attributeUse = lookupHash.value(baseAttributeUse->attribute()->name(m_namePool));
1901
1902                 if (baseAttributeUse->useType() == XsdAttributeUse::RequiredUse) {
1903                     if (attributeUse->useType() == XsdAttributeUse::OptionalUse || attributeUse->useType() == XsdAttributeUse::ProhibitedUse) {
1904                         m_context->error(QtXmlPatterns::tr("%1 attribute in derived complex type must be %2 like in base type.")
1905                                                           .arg(formatAttribute("use"))
1906                                                           .arg(formatData("required")),
1907                                          XsdSchemaContext::XSDError, sourceLocation(complexType));
1908                         return;
1909                     }
1910                 }
1911
1912                 if (baseAttributeUse->valueConstraint()) {
1913                     if (baseAttributeUse->valueConstraint()->variety() == XsdAttributeUse::ValueConstraint::Fixed) {
1914                         if (!attributeUse->valueConstraint()) {
1915                             m_context->error(QtXmlPatterns::tr("Attribute %1 in derived complex type must have %2 value constraint like in base type.")
1916                                                               .arg(formatKeyword(attributeUse->attribute()->displayName(m_namePool)))
1917                                                               .arg(formatData("fixed")),
1918                                              XsdSchemaContext::XSDError, sourceLocation(complexType));
1919                             return;
1920                         } else {
1921                             if (attributeUse->valueConstraint()->variety() == XsdAttributeUse::ValueConstraint::Fixed) {
1922                                 const XsdTypeChecker checker(m_context, QVector<QXmlName>(), sourceLocation(complexType));
1923                                 if (!checker.valuesAreEqual(attributeUse->valueConstraint()->value(), baseAttributeUse->valueConstraint()->value(), attributeUse->attribute()->type())) {
1924                                     m_context->error(QtXmlPatterns::tr("Attribute %1 in derived complex type must have the same %2 value constraint like in base type.")
1925                                                                       .arg(formatKeyword(attributeUse->attribute()->displayName(m_namePool)))
1926                                                                       .arg(formatData("fixed")),
1927                                                      XsdSchemaContext::XSDError, sourceLocation(complexType));
1928                                     return;
1929                                 }
1930                             } else {
1931                                 m_context->error(QtXmlPatterns::tr("Attribute %1 in derived complex type must have %2 value constraint.")
1932                                                                   .arg(formatKeyword(attributeUse->attribute()->displayName(m_namePool)))
1933                                                                   .arg(formatData("fixed")),
1934                                                  XsdSchemaContext::XSDError, sourceLocation(complexType));
1935                                 return;
1936                             }
1937                         }
1938                     }
1939                 }
1940             }
1941         }
1942
1943         // additional check that process content property of attribute wildcard in derived type is
1944         // not weaker than the wildcard in base type
1945         const XsdWildcard::Ptr baseWildcard(complexBaseType->attributeWildcard());
1946         const XsdWildcard::Ptr derivedWildcard(complexType->attributeWildcard());
1947         if (baseWildcard && derivedWildcard) {
1948             if (!XsdSchemaHelper::checkWildcardProcessContents(baseWildcard, derivedWildcard)) {
1949                 m_context->error(QtXmlPatterns::tr("processContent of base wildcard must be weaker than derived wildcard."), XsdSchemaContext::XSDError, sourceLocation(complexType));
1950                 return;
1951             }
1952         }
1953     }
1954 }
1955
1956 void XsdSchemaChecker::checkElementDuplicates()
1957 {
1958     // check all global types...
1959     SchemaType::List types = m_schema->types();
1960
1961     // .. and anonymous types
1962     types << m_schema->anonymousTypes();
1963
1964     for (int i = 0; i < types.count(); ++i) {
1965         const SchemaType::Ptr type = types.at(i);
1966
1967         if (!type->isComplexType() || !type->isDefinedBySchema())
1968             continue;
1969
1970         const XsdComplexType::Ptr complexType(type);
1971
1972         if ((complexType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly) || (complexType->contentType()->variety() == XsdComplexType::ContentType::Mixed)) {
1973             DuplicatedElementMap elementMap;
1974             DuplicatedWildcardMap wildcardMap;
1975
1976             checkElementDuplicates(complexType->contentType()->particle(), elementMap, wildcardMap);
1977         }
1978     }
1979 }
1980
1981 void XsdSchemaChecker::checkElementDuplicates(const XsdParticle::Ptr &particle, DuplicatedElementMap &elementMap, DuplicatedWildcardMap &wildcardMap)
1982 {
1983     if (particle->term()->isElement()) {
1984         const XsdElement::Ptr element(particle->term());
1985
1986         if (elementMap.contains(element->name(m_namePool))) {
1987             if (element->type() != elementMap.value(element->name(m_namePool))) {
1988                 m_context->error(QtXmlPatterns::tr("Element %1 exists twice with different types.")
1989                                                   .arg(formatKeyword(element->displayName(m_namePool))),
1990                                  XsdSchemaContext::XSDError, sourceLocation(element));
1991                 return;
1992             }
1993         } else {
1994             elementMap.insert(element->name(m_namePool), element->type());
1995         }
1996
1997         // check substitution group affiliation
1998         const XsdElement::List substElements = element->substitutionGroupAffiliations();
1999         for (int i = 0; i < substElements.count(); ++i) {
2000             const XsdElement::Ptr substElement = substElements.at(i);
2001             if (elementMap.contains(substElement->name(m_namePool))) {
2002                 if (substElement->type() != elementMap.value(substElement->name(m_namePool))) {
2003                     m_context->error(QtXmlPatterns::tr("Element %1 exists twice with different types.")
2004                                                       .arg(formatKeyword(substElement->displayName(m_namePool))),
2005                                      XsdSchemaContext::XSDError, sourceLocation(element));
2006                     return;
2007                 }
2008             } else {
2009                 elementMap.insert(substElement->name(m_namePool), substElement->type());
2010             }
2011         }
2012     } else if (particle->term()->isModelGroup()) {
2013         const XsdModelGroup::Ptr group(particle->term());
2014         const XsdParticle::List particles = group->particles();
2015         for (int i = 0; i < particles.count(); ++i)
2016             checkElementDuplicates(particles.at(i), elementMap, wildcardMap);
2017     } else if (particle->term()->isWildcard()) {
2018         const XsdWildcard::Ptr wildcard(particle->term());
2019
2020         bool error = false;
2021         if (!wildcardMap.contains(wildcard->namespaceConstraint()->variety())) {
2022             if (!wildcardMap.isEmpty())
2023                 error = true;
2024         } else {
2025             const XsdWildcard::Ptr otherWildcard = wildcardMap.value(wildcard->namespaceConstraint()->variety());
2026             if ((wildcard->processContents() != otherWildcard->processContents()) || (wildcard->namespaceConstraint()->namespaces() != otherWildcard->namespaceConstraint()->namespaces()))
2027                 error = true;
2028         }
2029
2030         if (error) {
2031             m_context->error(QtXmlPatterns::tr("Particle contains non-deterministic wildcards."), XsdSchemaContext::XSDError, sourceLocation(wildcard));
2032             return;
2033         } else {
2034             wildcardMap.insert(wildcard->namespaceConstraint()->variety(), wildcard);
2035         }
2036     }
2037 }
2038
2039 QSourceLocation XsdSchemaChecker::sourceLocation(const NamedSchemaComponent::Ptr &component) const
2040 {
2041     if (m_componentLocationHash.contains(component)) {
2042         return m_componentLocationHash.value(component);
2043     } else {
2044         QSourceLocation location;
2045         location.setLine(1);
2046         location.setColumn(1);
2047         location.setUri(QString::fromLatin1("dummyUri"));
2048
2049         return location;
2050     }
2051 }
2052
2053 QSourceLocation XsdSchemaChecker::sourceLocationForType(const SchemaType::Ptr &type) const
2054 {
2055     if (type->isSimpleType())
2056         return sourceLocation(XsdSimpleType::Ptr(type));
2057     else
2058         return sourceLocation(XsdComplexType::Ptr(type));
2059 }
2060
2061 QT_END_NAMESPACE