src/xmlpatterns/schema/qxsdschemachecker.cpp
changeset 0 1918ee327afb
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     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 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    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