src/xmlpatterns/schema/qxsdschemaresolver.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 "qxsdschemaresolver_p.h"
       
    43 
       
    44 #include "qderivedinteger_p.h"
       
    45 #include "qderivedstring_p.h"
       
    46 #include "qqnamevalue_p.h"
       
    47 #include "qxsdattributereference_p.h"
       
    48 #include "qxsdparticlechecker_p.h"
       
    49 #include "qxsdreference_p.h"
       
    50 #include "qxsdschemacontext_p.h"
       
    51 #include "qxsdschemahelper_p.h"
       
    52 #include "qxsdschemaparsercontext_p.h"
       
    53 #include "qxsdschematypesfactory_p.h"
       
    54 
       
    55 QT_BEGIN_NAMESPACE
       
    56 
       
    57 using namespace QPatternist;
       
    58 
       
    59 XsdSchemaResolver::XsdSchemaResolver(const QExplicitlySharedDataPointer<XsdSchemaContext> &context, const XsdSchemaParserContext *parserContext)
       
    60     : m_context(context)
       
    61     , m_checker(parserContext->checker())
       
    62     , m_namePool(parserContext->namePool())
       
    63     , m_schema(parserContext->schema())
       
    64 {
       
    65     m_keyReferences.reserve(20);
       
    66     m_simpleRestrictionBases.reserve(20);
       
    67     m_simpleListTypes.reserve(20);
       
    68     m_simpleUnionTypes.reserve(20);
       
    69     m_elementTypes.reserve(20);
       
    70     m_complexBaseTypes.reserve(20);
       
    71     m_attributeTypes.reserve(20);
       
    72     m_alternativeTypes.reserve(20);
       
    73     m_alternativeTypeElements.reserve(20);
       
    74     m_substitutionGroupAffiliations.reserve(20);
       
    75 
       
    76     m_predefinedSchemaTypes = m_context->schemaTypeFactory()->types().values();
       
    77 }
       
    78 
       
    79 XsdSchemaResolver::~XsdSchemaResolver()
       
    80 {
       
    81 }
       
    82 
       
    83 void XsdSchemaResolver::resolve()
       
    84 {
       
    85     m_checker->addComponentLocationHash(m_componentLocationHash);
       
    86 
       
    87     // resolve the base types for all types
       
    88     resolveSimpleRestrictionBaseTypes();
       
    89     resolveComplexBaseTypes();
       
    90 
       
    91     // do the basic checks which depend on having a base type available
       
    92     m_checker->basicCheck();
       
    93 
       
    94     // resolve further types that only map a type name to a type object
       
    95     resolveSimpleListType();
       
    96     resolveSimpleUnionTypes();
       
    97     resolveElementTypes();
       
    98     resolveAttributeTypes();
       
    99     resolveAlternativeTypes();
       
   100 
       
   101     // resolve objects that do not need information about inheritance
       
   102     resolveKeyReferences();
       
   103     resolveSubstitutionGroupAffiliations();
       
   104 
       
   105     // resolve objects that do need information about inheritance
       
   106     resolveSimpleRestrictions();
       
   107     resolveSimpleContentComplexTypes();
       
   108 
       
   109     // resolve objects which replace place holders
       
   110     resolveTermReferences();
       
   111     resolveAttributeTermReferences();
       
   112 
       
   113     // resolve additional objects that do need information about inheritance
       
   114     resolveAttributeInheritance();
       
   115     resolveComplexContentComplexTypes();
       
   116     resolveSubstitutionGroups();
       
   117 
       
   118     resolveEnumerationFacetValues();
       
   119 
       
   120     checkRedefinedGroups();
       
   121     checkRedefinedAttributeGroups();
       
   122 
       
   123     // check the constraining facets before we resolve them
       
   124     m_checker->checkConstrainingFacets();
       
   125 
       
   126     // add it again, as we may have added new components in the meantime
       
   127     m_checker->addComponentLocationHash(m_componentLocationHash);
       
   128 
       
   129     m_checker->check();
       
   130 }
       
   131 
       
   132 void XsdSchemaResolver::addKeyReference(const XsdElement::Ptr &element, const XsdIdentityConstraint::Ptr &keyRef, const QXmlName &reference, const QSourceLocation &location)
       
   133 {
       
   134     KeyReference item;
       
   135     item.element = element;
       
   136     item.keyRef = keyRef;
       
   137     item.reference = reference;
       
   138     item.location = location;
       
   139 
       
   140     m_keyReferences.append(item);
       
   141 }
       
   142 
       
   143 void XsdSchemaResolver::addSimpleRestrictionBase(const XsdSimpleType::Ptr &simpleType, const QXmlName &baseName, const QSourceLocation &location)
       
   144 {
       
   145     SimpleRestrictionBase item;
       
   146     item.simpleType = simpleType;
       
   147     item.baseName = baseName;
       
   148     item.location = location;
       
   149 
       
   150     m_simpleRestrictionBases.append(item);
       
   151 }
       
   152 
       
   153 void XsdSchemaResolver::removeSimpleRestrictionBase(const XsdSimpleType::Ptr &type)
       
   154 {
       
   155     for (int i = 0; i < m_simpleRestrictionBases.count(); ++i) {
       
   156         if (m_simpleRestrictionBases.at(i).simpleType == type) {
       
   157             m_simpleRestrictionBases.remove(i);
       
   158             break;
       
   159         }
       
   160     }
       
   161 }
       
   162 
       
   163 void XsdSchemaResolver::addSimpleListType(const XsdSimpleType::Ptr &simpleType, const QXmlName &typeName, const QSourceLocation &location)
       
   164 {
       
   165     SimpleListType item;
       
   166     item.simpleType = simpleType;
       
   167     item.typeName = typeName;
       
   168     item.location = location;
       
   169 
       
   170     m_simpleListTypes.append(item);
       
   171 }
       
   172 
       
   173 void XsdSchemaResolver::addSimpleUnionTypes(const XsdSimpleType::Ptr &simpleType, const QList<QXmlName> &typeNames, const QSourceLocation &location)
       
   174 {
       
   175     SimpleUnionType item;
       
   176     item.simpleType = simpleType;
       
   177     item.typeNames = typeNames;
       
   178     item.location = location;
       
   179 
       
   180     m_simpleUnionTypes.append(item);
       
   181 }
       
   182 
       
   183 void XsdSchemaResolver::addElementType(const XsdElement::Ptr &element, const QXmlName &typeName, const QSourceLocation &location)
       
   184 {
       
   185     ElementType item;
       
   186     item.element = element;
       
   187     item.typeName = typeName;
       
   188     item.location = location;
       
   189 
       
   190     m_elementTypes.append(item);
       
   191 }
       
   192 
       
   193 void XsdSchemaResolver::addComplexBaseType(const XsdComplexType::Ptr &complexType, const QXmlName &baseName, const QSourceLocation &location, const XsdFacet::Hash &facets)
       
   194 {
       
   195     ComplexBaseType item;
       
   196     item.complexType = complexType;
       
   197     item.baseName = baseName;
       
   198     item.location = location;
       
   199     item.facets = facets;
       
   200 
       
   201     m_complexBaseTypes.append(item);
       
   202 }
       
   203 
       
   204 void XsdSchemaResolver::removeComplexBaseType(const XsdComplexType::Ptr &type)
       
   205 {
       
   206     for (int i = 0; i < m_complexBaseTypes.count(); ++i) {
       
   207         if (m_complexBaseTypes.at(i).complexType == type) {
       
   208             m_complexBaseTypes.remove(i);
       
   209             break;
       
   210         }
       
   211     }
       
   212 }
       
   213 
       
   214 void XsdSchemaResolver::addComplexContentType(const XsdComplexType::Ptr &complexType, const XsdParticle::Ptr &content, bool mixed)
       
   215 {
       
   216     ComplexContentType item;
       
   217     item.complexType = complexType;
       
   218     item.explicitContent = content;
       
   219     item.effectiveMixed = mixed;
       
   220     m_complexContentTypes.append(item);
       
   221 }
       
   222 
       
   223 void XsdSchemaResolver::addAttributeType(const XsdAttribute::Ptr &attribute, const QXmlName &typeName, const QSourceLocation &location)
       
   224 {
       
   225     AttributeType item;
       
   226     item.attribute = attribute;
       
   227     item.typeName = typeName;
       
   228     item.location = location;
       
   229 
       
   230     m_attributeTypes.append(item);
       
   231 }
       
   232 
       
   233 void XsdSchemaResolver::addAlternativeType(const XsdAlternative::Ptr &alternative, const QXmlName &typeName, const QSourceLocation &location)
       
   234 {
       
   235     AlternativeType item;
       
   236     item.alternative = alternative;
       
   237     item.typeName = typeName;
       
   238     item.location = location;
       
   239 
       
   240     m_alternativeTypes.append(item);
       
   241 }
       
   242 
       
   243 void XsdSchemaResolver::addAlternativeType(const XsdAlternative::Ptr &alternative, const XsdElement::Ptr &element)
       
   244 {
       
   245     AlternativeTypeElement item;
       
   246     item.alternative = alternative;
       
   247     item.element = element;
       
   248 
       
   249     m_alternativeTypeElements.append(item);
       
   250 }
       
   251 
       
   252 void XsdSchemaResolver::addSubstitutionGroupAffiliation(const XsdElement::Ptr &element, const QList<QXmlName> &elementNames, const QSourceLocation &location)
       
   253 {
       
   254     SubstitutionGroupAffiliation item;
       
   255     item.element = element;
       
   256     item.elementNames = elementNames;
       
   257     item.location = location;
       
   258 
       
   259     m_substitutionGroupAffiliations.append(item);
       
   260 }
       
   261 
       
   262 void XsdSchemaResolver::addSubstitutionGroupType(const XsdElement::Ptr &element)
       
   263 {
       
   264     m_substitutionGroupTypes.append(element);
       
   265 }
       
   266 
       
   267 void XsdSchemaResolver::addComponentLocationHash(const ComponentLocationHash &hash)
       
   268 {
       
   269     m_componentLocationHash.unite(hash);
       
   270 }
       
   271 
       
   272 void XsdSchemaResolver::addEnumerationFacetValue(const AtomicValue::Ptr &facetValue, const NamespaceSupport &namespaceSupport)
       
   273 {
       
   274     m_enumerationFacetValues.insert(facetValue, namespaceSupport);
       
   275 }
       
   276 
       
   277 void XsdSchemaResolver::addRedefinedGroups(const XsdModelGroup::Ptr &redefinedGroup, const XsdModelGroup::Ptr &group)
       
   278 {
       
   279     RedefinedGroups item;
       
   280     item.redefinedGroup = redefinedGroup;
       
   281     item.group = group;
       
   282 
       
   283     m_redefinedGroups.append(item);
       
   284 }
       
   285 
       
   286 void XsdSchemaResolver::addRedefinedAttributeGroups(const XsdAttributeGroup::Ptr &redefinedGroup, const XsdAttributeGroup::Ptr &group)
       
   287 {
       
   288     RedefinedAttributeGroups item;
       
   289     item.redefinedGroup = redefinedGroup;
       
   290     item.group = group;
       
   291 
       
   292     m_redefinedAttributeGroups.append(item);
       
   293 }
       
   294 
       
   295 void XsdSchemaResolver::addAllGroupCheck(const XsdReference::Ptr &reference)
       
   296 {
       
   297     m_allGroups.insert(reference);
       
   298 }
       
   299 
       
   300 void XsdSchemaResolver::copyDataTo(const XsdSchemaResolver::Ptr &other) const
       
   301 {
       
   302     other->m_keyReferences << m_keyReferences;
       
   303     other->m_simpleRestrictionBases << m_simpleRestrictionBases;
       
   304     other->m_simpleListTypes << m_simpleListTypes;
       
   305     other->m_simpleUnionTypes << m_simpleUnionTypes;
       
   306     other->m_elementTypes << m_elementTypes;
       
   307     other->m_complexBaseTypes << m_complexBaseTypes;
       
   308     other->m_complexContentTypes << m_complexContentTypes;
       
   309     other->m_attributeTypes << m_attributeTypes;
       
   310     other->m_alternativeTypes << m_alternativeTypes;
       
   311     other->m_alternativeTypeElements << m_alternativeTypeElements;
       
   312     other->m_substitutionGroupAffiliations << m_substitutionGroupAffiliations;
       
   313     other->m_substitutionGroupTypes << m_substitutionGroupTypes;
       
   314 }
       
   315 
       
   316 QXmlName XsdSchemaResolver::baseTypeNameOfType(const SchemaType::Ptr &type) const
       
   317 {
       
   318     for (int i = 0; i < m_simpleRestrictionBases.count(); ++i) {
       
   319         if (m_simpleRestrictionBases.at(i).simpleType == type)
       
   320             return m_simpleRestrictionBases.at(i).baseName;
       
   321     }
       
   322 
       
   323     for (int i = 0; i < m_complexBaseTypes.count(); ++i) {
       
   324         if (m_complexBaseTypes.at(i).complexType == type)
       
   325             return m_complexBaseTypes.at(i).baseName;
       
   326     }
       
   327 
       
   328     return QXmlName();
       
   329 }
       
   330 
       
   331 QXmlName XsdSchemaResolver::typeNameOfAttribute(const XsdAttribute::Ptr &attribute) const
       
   332 {
       
   333     for (int i = 0; i < m_attributeTypes.count(); ++i) {
       
   334         if (m_attributeTypes.at(i).attribute == attribute)
       
   335             return m_attributeTypes.at(i).typeName;
       
   336     }
       
   337 
       
   338     return QXmlName();
       
   339 }
       
   340 
       
   341 void XsdSchemaResolver::setDefaultOpenContent(const XsdComplexType::OpenContent::Ptr &openContent, bool appliesToEmpty)
       
   342 {
       
   343     m_defaultOpenContent = openContent;
       
   344     m_defaultOpenContentAppliesToEmpty = appliesToEmpty;
       
   345 }
       
   346 
       
   347 void XsdSchemaResolver::resolveKeyReferences()
       
   348 {
       
   349     for (int i = 0; i < m_keyReferences.count(); ++i) {
       
   350         const KeyReference ref = m_keyReferences.at(i);
       
   351 
       
   352         const XsdIdentityConstraint::Ptr constraint = m_schema->identityConstraint(ref.reference);
       
   353         if (!constraint) {
       
   354             m_context->error(QtXmlPatterns::tr("%1 references unknown %2 or %3 element %4.")
       
   355                                               .arg(formatKeyword(ref.keyRef->displayName(m_namePool)))
       
   356                                               .arg(formatElement("key"))
       
   357                                               .arg(formatElement("unique"))
       
   358                                               .arg(formatKeyword(m_namePool, ref.reference)),
       
   359                              XsdSchemaContext::XSDError, ref.location);
       
   360             return;
       
   361         }
       
   362 
       
   363         if (constraint->category() != XsdIdentityConstraint::Key && constraint->category() != XsdIdentityConstraint::Unique) { // only key and unique can be referenced
       
   364             m_context->error(QtXmlPatterns::tr("%1 references identity constraint %2 that is no %3 or %4 element.")
       
   365                                               .arg(formatKeyword(ref.keyRef->displayName(m_namePool)))
       
   366                                               .arg(formatKeyword(m_namePool, ref.reference))
       
   367                                               .arg(formatElement("key"))
       
   368                                               .arg(formatElement("unique")),
       
   369                              XsdSchemaContext::XSDError, ref.location);
       
   370             return;
       
   371         }
       
   372 
       
   373         if (constraint->fields().count() != ref.keyRef->fields().count()) {
       
   374             m_context->error(QtXmlPatterns::tr("%1 has a different number of fields from the identity constraint %2 that it references.")
       
   375                                               .arg(formatKeyword(ref.keyRef->displayName(m_namePool)))
       
   376                                               .arg(formatKeyword(m_namePool, ref.reference)),
       
   377                              XsdSchemaContext::XSDError, ref.location);
       
   378             return;
       
   379         }
       
   380 
       
   381         ref.keyRef->setReferencedKey(constraint);
       
   382     }
       
   383 }
       
   384 
       
   385 void XsdSchemaResolver::resolveSimpleRestrictionBaseTypes()
       
   386 {
       
   387     // iterate over all simple types that are derived by restriction
       
   388     for (int i = 0; i < m_simpleRestrictionBases.count(); ++i) {
       
   389         const SimpleRestrictionBase item = m_simpleRestrictionBases.at(i);
       
   390 
       
   391         // find the base type
       
   392         SchemaType::Ptr type = m_schema->type(item.baseName);
       
   393         if (!type) {
       
   394             // maybe it's a basic type...
       
   395             type = m_context->schemaTypeFactory()->createSchemaType(item.baseName);
       
   396             if (!type) {
       
   397                 m_context->error(QtXmlPatterns::tr("Base type %1 of %2 element cannot be resolved.")
       
   398                                                   .arg(formatType(m_namePool, item.baseName))
       
   399                                                   .arg(formatElement("restriction")),
       
   400                                  XsdSchemaContext::XSDError, item.location);
       
   401                 return;
       
   402             }
       
   403         }
       
   404 
       
   405         item.simpleType->setWxsSuperType(type);
       
   406     }
       
   407 }
       
   408 
       
   409 void XsdSchemaResolver::resolveSimpleRestrictions()
       
   410 {
       
   411     XsdSimpleType::List simpleTypes;
       
   412 
       
   413     // first collect the global simple types
       
   414     const SchemaType::List types = m_schema->types();
       
   415     for (int i = 0; i < types.count(); ++i) {
       
   416         if (types.at(i)->isSimpleType() && (types.at(i)->derivationMethod() == SchemaType::DerivationRestriction))
       
   417             simpleTypes.append(types.at(i));
       
   418     }
       
   419 
       
   420     // then collect all anonymous simple types
       
   421     const SchemaType::List anonymousTypes = m_schema->anonymousTypes();
       
   422     for (int i = 0; i < anonymousTypes.count(); ++i) {
       
   423         if (anonymousTypes.at(i)->isSimpleType() && (anonymousTypes.at(i)->derivationMethod() == SchemaType::DerivationRestriction))
       
   424             simpleTypes.append(anonymousTypes.at(i));
       
   425     }
       
   426 
       
   427     QSet<XsdSimpleType::Ptr> visitedTypes;
       
   428     for (int i = 0; i < simpleTypes.count(); ++i) {
       
   429         resolveSimpleRestrictions(simpleTypes.at(i), visitedTypes);
       
   430     }
       
   431 }
       
   432 
       
   433 void XsdSchemaResolver::resolveSimpleRestrictions(const XsdSimpleType::Ptr &simpleType, QSet<XsdSimpleType::Ptr> &visitedTypes)
       
   434 {
       
   435     if (visitedTypes.contains(simpleType))
       
   436         return;
       
   437     else
       
   438         visitedTypes.insert(simpleType);
       
   439 
       
   440     if (simpleType->derivationMethod() != XsdSimpleType::DerivationRestriction)
       
   441         return;
       
   442 
       
   443     // as xs:NMTOKENS, xs:ENTITIES and xs:IDREFS are provided by our XsdSchemaTypesFactory, they are
       
   444     // setup correctly already and shouldn't be handled here
       
   445     if (m_predefinedSchemaTypes.contains(simpleType))
       
   446         return;
       
   447 
       
   448     const SchemaType::Ptr baseType = simpleType->wxsSuperType();
       
   449     Q_ASSERT(baseType);
       
   450 
       
   451     if (baseType->isDefinedBySchema())
       
   452         resolveSimpleRestrictions(XsdSimpleType::Ptr(baseType), visitedTypes);
       
   453 
       
   454     simpleType->setCategory(baseType->category());
       
   455 
       
   456     if (simpleType->category() == XsdSimpleType::SimpleTypeAtomic) {
       
   457         QSet<AnySimpleType::Ptr> visitedPrimitiveTypes;
       
   458         const AnySimpleType::Ptr primitiveType = findPrimitiveType(baseType, visitedPrimitiveTypes);
       
   459         simpleType->setPrimitiveType(primitiveType);
       
   460     } else if (simpleType->category() == XsdSimpleType::SimpleTypeList) {
       
   461         const XsdSimpleType::Ptr simpleBaseType = baseType;
       
   462         simpleType->setItemType(simpleBaseType->itemType());
       
   463     } else if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) {
       
   464         const XsdSimpleType::Ptr simpleBaseType = baseType;
       
   465         simpleType->setMemberTypes(simpleBaseType->memberTypes());
       
   466     }
       
   467 }
       
   468 
       
   469 void XsdSchemaResolver::resolveSimpleListType()
       
   470 {
       
   471     // iterate over all simple types where the item type shall be resolved
       
   472     for (int i = 0; i < m_simpleListTypes.count(); ++i) {
       
   473         const SimpleListType item = m_simpleListTypes.at(i);
       
   474 
       
   475         // try to resolve the name
       
   476         SchemaType::Ptr type = m_schema->type(item.typeName);
       
   477         if (!type) {
       
   478             // maybe it's a basic type...
       
   479             type = m_context->schemaTypeFactory()->createSchemaType(item.typeName);
       
   480             if (!type) {
       
   481                 m_context->error(QtXmlPatterns::tr("Item type %1 of %2 element cannot be resolved.")
       
   482                                                   .arg(formatType(m_namePool, item.typeName))
       
   483                                                   .arg(formatElement("list")),
       
   484                                  XsdSchemaContext::XSDError, item.location);
       
   485                 return;
       
   486             }
       
   487         }
       
   488 
       
   489         item.simpleType->setItemType(type);
       
   490     }
       
   491 }
       
   492 
       
   493 void XsdSchemaResolver::resolveSimpleUnionTypes()
       
   494 {
       
   495     // iterate over all simple types where the union member types shall be resolved
       
   496     for (int i = 0; i < m_simpleUnionTypes.count(); ++i) {
       
   497         const SimpleUnionType item = m_simpleUnionTypes.at(i);
       
   498 
       
   499         AnySimpleType::List memberTypes;
       
   500 
       
   501         // iterate over all union member type names
       
   502         const QList<QXmlName> typeNames = item.typeNames;
       
   503         for (int j = 0; j < typeNames.count(); ++j) {
       
   504             const QXmlName typeName = typeNames.at(j);
       
   505 
       
   506             // try to resolve the name
       
   507             SchemaType::Ptr type = m_schema->type(typeName);
       
   508             if (!type) {
       
   509                 // maybe it's a basic type...
       
   510                 type = m_context->schemaTypeFactory()->createSchemaType(typeName);
       
   511                 if (!type) {
       
   512                     m_context->error(QtXmlPatterns::tr("Member type %1 of %2 element cannot be resolved.")
       
   513                                                       .arg(formatType(m_namePool, typeName))
       
   514                                                       .arg(formatElement("union")),
       
   515                                      XsdSchemaContext::XSDError, item.location);
       
   516                     return;
       
   517                 }
       
   518             }
       
   519 
       
   520             memberTypes.append(type);
       
   521         }
       
   522 
       
   523         // append the types that have been defined as <simpleType> children
       
   524         memberTypes << item.simpleType->memberTypes();
       
   525 
       
   526         item.simpleType->setMemberTypes(memberTypes);
       
   527     }
       
   528 }
       
   529 
       
   530 void XsdSchemaResolver::resolveElementTypes()
       
   531 {
       
   532     for (int i = 0; i < m_elementTypes.count(); ++i) {
       
   533         const ElementType item = m_elementTypes.at(i);
       
   534 
       
   535         SchemaType::Ptr type = m_schema->type(item.typeName);
       
   536         if (!type) {
       
   537             // maybe it's a basic type...
       
   538             type = m_context->schemaTypeFactory()->createSchemaType(item.typeName);
       
   539             if (!type) {
       
   540                 m_context->error(QtXmlPatterns::tr("Type %1 of %2 element cannot be resolved.")
       
   541                                                   .arg(formatType(m_namePool, item.typeName))
       
   542                                                   .arg(formatElement("element")),
       
   543                                  XsdSchemaContext::XSDError, item.location);
       
   544                 return;
       
   545             }
       
   546         }
       
   547 
       
   548         item.element->setType(type);
       
   549     }
       
   550 }
       
   551 
       
   552 void XsdSchemaResolver::resolveComplexBaseTypes()
       
   553 {
       
   554     for (int i = 0; i < m_complexBaseTypes.count(); ++i) {
       
   555         const ComplexBaseType item = m_complexBaseTypes.at(i);
       
   556 
       
   557         SchemaType::Ptr type = m_schema->type(item.baseName);
       
   558         if (!type) {
       
   559             // maybe it's a basic type...
       
   560             type = m_context->schemaTypeFactory()->createSchemaType(item.baseName);
       
   561             if (!type) {
       
   562                 m_context->error(QtXmlPatterns::tr("Base type %1 of complex type cannot be resolved.").arg(formatType(m_namePool, item.baseName)), XsdSchemaContext::XSDError, item.location);
       
   563                 return;
       
   564             }
       
   565         }
       
   566 
       
   567         if (item.complexType->contentType()->variety() == XsdComplexType::ContentType::Simple) {
       
   568             if (type->isComplexType() && type->isDefinedBySchema()) {
       
   569                 const XsdComplexType::Ptr baseType = type;
       
   570                 if (baseType->contentType()->variety() != XsdComplexType::ContentType::Simple) {
       
   571                     m_context->error(QtXmlPatterns::tr("%1 cannot have complex base type that has a %2.")
       
   572                                                       .arg(formatElement("simpleContent"))
       
   573                                                       .arg(formatElement("complexContent")),
       
   574                                      XsdSchemaContext::XSDError, item.location);
       
   575                     return;
       
   576                 }
       
   577             }
       
   578         }
       
   579 
       
   580         item.complexType->setWxsSuperType(type);
       
   581     }
       
   582 }
       
   583 
       
   584 void XsdSchemaResolver::resolveSimpleContentComplexTypes()
       
   585 {
       
   586     XsdComplexType::List complexTypes;
       
   587 
       
   588     // first collect the global complex types
       
   589     const SchemaType::List types = m_schema->types();
       
   590     for (int i = 0; i < types.count(); ++i) {
       
   591         if (types.at(i)->isComplexType() && types.at(i)->isDefinedBySchema())
       
   592             complexTypes.append(types.at(i));
       
   593     }
       
   594 
       
   595     // then collect all anonymous simple types
       
   596     const SchemaType::List anonymousTypes = m_schema->anonymousTypes();
       
   597     for (int i = 0; i < anonymousTypes.count(); ++i) {
       
   598         if (anonymousTypes.at(i)->isComplexType() && anonymousTypes.at(i)->isDefinedBySchema())
       
   599             complexTypes.append(anonymousTypes.at(i));
       
   600     }
       
   601 
       
   602     QSet<XsdComplexType::Ptr> visitedTypes;
       
   603     for (int i = 0; i < complexTypes.count(); ++i) {
       
   604         if (XsdComplexType::Ptr(complexTypes.at(i))->contentType()->variety() == XsdComplexType::ContentType::Simple)
       
   605             resolveSimpleContentComplexTypes(complexTypes.at(i), visitedTypes);
       
   606     }
       
   607 }
       
   608 
       
   609 void XsdSchemaResolver::resolveSimpleContentComplexTypes(const XsdComplexType::Ptr &complexType, QSet<XsdComplexType::Ptr> &visitedTypes)
       
   610 {
       
   611     if (visitedTypes.contains(complexType))
       
   612         return;
       
   613     else
       
   614         visitedTypes.insert(complexType);
       
   615 
       
   616     const SchemaType::Ptr baseType = complexType->wxsSuperType();
       
   617 
       
   618     // at this point simple types have been resolved already, so we care about
       
   619     // complex types here only
       
   620 
       
   621     // http://www.w3.org/TR/xmlschema11-1/#dcl.ctd.ctsc
       
   622     // 1
       
   623     if (baseType->isComplexType() && baseType->isDefinedBySchema()) {
       
   624         const XsdComplexType::Ptr complexBaseType = baseType;
       
   625 
       
   626         resolveSimpleContentComplexTypes(complexBaseType, visitedTypes);
       
   627 
       
   628         if (complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Simple) {
       
   629             if (complexType->derivationMethod() == XsdComplexType::DerivationRestriction) {
       
   630                 if (complexType->contentType()->simpleType()) {
       
   631                     // 1.1 contains the content of the <simpleType> already
       
   632                 } else {
       
   633                     // 1.2
       
   634                     const XsdSimpleType::Ptr anonType(new XsdSimpleType());
       
   635                     anonType->setCategory(complexBaseType->contentType()->simpleType()->category());
       
   636                     anonType->setDerivationMethod(XsdSimpleType::DerivationRestriction);
       
   637                     anonType->setWxsSuperType(complexBaseType->contentType()->simpleType());
       
   638                     anonType->setFacets(complexTypeFacets(complexType));
       
   639 
       
   640                     QSet<AnySimpleType::Ptr> visitedPrimitiveTypes;
       
   641                     const AnySimpleType::Ptr primitiveType = findPrimitiveType(anonType->wxsSuperType(), visitedPrimitiveTypes);
       
   642                     anonType->setPrimitiveType(primitiveType);
       
   643 
       
   644                     complexType->contentType()->setSimpleType(anonType);
       
   645 
       
   646                     m_schema->addAnonymousType(anonType);
       
   647                     m_componentLocationHash.insert(anonType, m_componentLocationHash.value(complexType));
       
   648                 }
       
   649             } else if (complexBaseType->derivationMethod() == XsdComplexType::DerivationExtension) { // 3
       
   650                 complexType->contentType()->setSimpleType(complexBaseType->contentType()->simpleType());
       
   651             }
       
   652         } else if (complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Mixed &&
       
   653                    complexType->derivationMethod() == XsdComplexType::DerivationRestriction &&
       
   654                    XsdSchemaHelper::isParticleEmptiable(complexBaseType->contentType()->particle())) { // 2
       
   655             // simple type was already set in parser
       
   656 
       
   657             const XsdSimpleType::Ptr anonType(new XsdSimpleType());
       
   658             anonType->setCategory(complexType->contentType()->simpleType()->category());
       
   659             anonType->setDerivationMethod(XsdSimpleType::DerivationRestriction);
       
   660             anonType->setWxsSuperType(complexType->contentType()->simpleType());
       
   661             anonType->setFacets(complexTypeFacets(complexType));
       
   662 
       
   663             QSet<AnySimpleType::Ptr> visitedPrimitiveTypes;
       
   664             const AnySimpleType::Ptr primitiveType = findPrimitiveType(anonType->wxsSuperType(), visitedPrimitiveTypes);
       
   665             anonType->setPrimitiveType(primitiveType);
       
   666 
       
   667             complexType->contentType()->setSimpleType(anonType);
       
   668 
       
   669             m_schema->addAnonymousType(anonType);
       
   670             m_componentLocationHash.insert(anonType, m_componentLocationHash.value(complexType));
       
   671         } else {
       
   672             complexType->contentType()->setSimpleType(BuiltinTypes::xsAnySimpleType);
       
   673         }
       
   674     } else if (baseType->isSimpleType()) { // 4
       
   675         complexType->contentType()->setSimpleType(baseType);
       
   676     } else { // 5
       
   677         complexType->contentType()->setSimpleType(BuiltinTypes::xsAnySimpleType);
       
   678     }
       
   679 }
       
   680 
       
   681 void XsdSchemaResolver::resolveComplexContentComplexTypes()
       
   682 {
       
   683     XsdComplexType::List complexTypes;
       
   684 
       
   685     // first collect the global complex types
       
   686     const SchemaType::List types = m_schema->types();
       
   687     for (int i = 0; i < types.count(); ++i) {
       
   688         if (types.at(i)->isComplexType() && types.at(i)->isDefinedBySchema())
       
   689             complexTypes.append(types.at(i));
       
   690     }
       
   691 
       
   692     // then collect all anonymous simple types
       
   693     const SchemaType::List anonymousTypes = m_schema->anonymousTypes();
       
   694     for (int i = 0; i < anonymousTypes.count(); ++i) {
       
   695         if (anonymousTypes.at(i)->isComplexType() && anonymousTypes.at(i)->isDefinedBySchema())
       
   696             complexTypes.append(anonymousTypes.at(i));
       
   697     }
       
   698 
       
   699     QSet<XsdComplexType::Ptr> visitedTypes;
       
   700     for (int i = 0; i < complexTypes.count(); ++i) {
       
   701         if (XsdComplexType::Ptr(complexTypes.at(i))->contentType()->variety() != XsdComplexType::ContentType::Simple)
       
   702             resolveComplexContentComplexTypes(complexTypes.at(i), visitedTypes);
       
   703     }
       
   704 }
       
   705 
       
   706 void XsdSchemaResolver::resolveComplexContentComplexTypes(const XsdComplexType::Ptr &complexType, QSet<XsdComplexType::Ptr> &visitedTypes)
       
   707 {
       
   708     if (visitedTypes.contains(complexType))
       
   709         return;
       
   710     else
       
   711         visitedTypes.insert(complexType);
       
   712 
       
   713     ComplexContentType item;
       
   714     bool foundCorrespondingItem = false;
       
   715     for (int i = 0; i < m_complexContentTypes.count(); ++i) {
       
   716         if (m_complexContentTypes.at(i).complexType == complexType) {
       
   717             item = m_complexContentTypes.at(i);
       
   718             foundCorrespondingItem = true;
       
   719             break;
       
   720         }
       
   721     }
       
   722 
       
   723     if (!foundCorrespondingItem)
       
   724         return;
       
   725 
       
   726     const SchemaType::Ptr baseType = complexType->wxsSuperType();
       
   727 
       
   728     // at this point simple types have been resolved already, so we care about
       
   729     // complex types here only
       
   730     if (baseType->isComplexType() && baseType->isDefinedBySchema())
       
   731         resolveComplexContentComplexTypes(XsdComplexType::Ptr(baseType), visitedTypes);
       
   732 
       
   733 
       
   734     // @see http://www.w3.org/TR/xmlschema11-1/#dcl.ctd.ctcc.common
       
   735 
       
   736     // 3
       
   737     XsdParticle::Ptr effectiveContent;
       
   738     if (!item.explicitContent) { // 3.1
       
   739         if (item.effectiveMixed == true) { // 3.1.1
       
   740             const XsdParticle::Ptr particle(new XsdParticle());
       
   741             particle->setMinimumOccurs(1);
       
   742             particle->setMaximumOccurs(1);
       
   743             particle->setMaximumOccursUnbounded(false);
       
   744 
       
   745             const XsdModelGroup::Ptr sequence(new XsdModelGroup());
       
   746             sequence->setCompositor(XsdModelGroup::SequenceCompositor);
       
   747             particle->setTerm(sequence);
       
   748 
       
   749             effectiveContent = particle;
       
   750         } else { // 3.1.2
       
   751             effectiveContent = XsdParticle::Ptr();
       
   752         }
       
   753     } else { // 3.2
       
   754         effectiveContent = item.explicitContent;
       
   755     }
       
   756 
       
   757     // 4
       
   758     XsdComplexType::ContentType::Ptr explicitContentType(new XsdComplexType::ContentType());
       
   759     if (item.complexType->derivationMethod() == XsdComplexType::DerivationRestriction) { // 4.1
       
   760         if (!effectiveContent) { // 4.1.1
       
   761             explicitContentType->setVariety(XsdComplexType::ContentType::Empty);
       
   762         } else { // 4.1.2
       
   763             if (item.effectiveMixed == true)
       
   764                 explicitContentType->setVariety(XsdComplexType::ContentType::Mixed);
       
   765             else
       
   766                 explicitContentType->setVariety(XsdComplexType::ContentType::ElementOnly);
       
   767 
       
   768             explicitContentType->setParticle(effectiveContent);
       
   769         }
       
   770     } else if (item.complexType->derivationMethod() == XsdComplexType::DerivationExtension) { // 4.2
       
   771         const SchemaType::Ptr baseType = item.complexType->wxsSuperType();
       
   772         if (baseType->isSimpleType() || (baseType->isComplexType() && baseType->isDefinedBySchema() && (XsdComplexType::Ptr(baseType)->contentType()->variety() == XsdComplexType::ContentType::Empty ||
       
   773                                                                                                         XsdComplexType::Ptr(baseType)->contentType()->variety() == XsdComplexType::ContentType::Simple))) { // 4.2.1
       
   774             if (!effectiveContent) {
       
   775                 explicitContentType->setVariety(XsdComplexType::ContentType::Empty);
       
   776             } else {
       
   777                 if (item.effectiveMixed == true)
       
   778                     explicitContentType->setVariety(XsdComplexType::ContentType::Mixed);
       
   779                 else
       
   780                     explicitContentType->setVariety(XsdComplexType::ContentType::ElementOnly);
       
   781 
       
   782                 explicitContentType->setParticle(effectiveContent);
       
   783             }
       
   784         } else if (baseType->isComplexType() && baseType->isDefinedBySchema() && (XsdComplexType::Ptr(baseType)->contentType()->variety() == XsdComplexType::ContentType::ElementOnly ||
       
   785                                                  XsdComplexType::Ptr(baseType)->contentType()->variety() == XsdComplexType::ContentType::Mixed) && !effectiveContent) { // 4.2.2
       
   786             const XsdComplexType::Ptr complexBaseType(baseType);
       
   787 
       
   788             explicitContentType = complexBaseType->contentType();
       
   789         } else { // 4.2.3
       
   790             explicitContentType->setVariety(item.effectiveMixed ? XsdComplexType::ContentType::Mixed : XsdComplexType::ContentType::ElementOnly);
       
   791 
       
   792             XsdParticle::Ptr baseParticle;
       
   793             if (baseType == BuiltinTypes::xsAnyType) {
       
   794                 // we need a workaround here, since the xsAnyType is no real (aka XsdComplexType) complex type...
       
   795 
       
   796                 baseParticle = XsdParticle::Ptr(new XsdParticle());
       
   797                 baseParticle->setMinimumOccurs(1);
       
   798                 baseParticle->setMaximumOccurs(1);
       
   799                 baseParticle->setMaximumOccursUnbounded(false);
       
   800 
       
   801                 const XsdModelGroup::Ptr group(new XsdModelGroup());
       
   802                 group->setCompositor(XsdModelGroup::SequenceCompositor);
       
   803 
       
   804                 const XsdParticle::Ptr particle(new XsdParticle());
       
   805                 particle->setMinimumOccurs(0);
       
   806                 particle->setMaximumOccursUnbounded(true);
       
   807 
       
   808                 const XsdWildcard::Ptr wildcard(new XsdWildcard());
       
   809                 wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
       
   810                 wildcard->setProcessContents(XsdWildcard::Lax);
       
   811 
       
   812                 particle->setTerm(wildcard);
       
   813                 XsdParticle::List particles;
       
   814                 particles.append(particle);
       
   815                 group->setParticles(particles);
       
   816                 baseParticle->setTerm(group);
       
   817             } else {
       
   818                 const XsdComplexType::Ptr complexBaseType(baseType);
       
   819                 baseParticle = complexBaseType->contentType()->particle();
       
   820             }
       
   821             if (baseParticle && baseParticle->term()->isModelGroup() && (XsdModelGroup::Ptr(baseParticle->term())->compositor() == XsdModelGroup::AllCompositor) &&
       
   822                 (!item.explicitContent)) { // 4.2.3.1
       
   823 
       
   824                 explicitContentType->setParticle(baseParticle);
       
   825             } else if (baseParticle && baseParticle->term()->isModelGroup() && (XsdModelGroup::Ptr(baseParticle->term())->compositor() == XsdModelGroup::AllCompositor) &&
       
   826                        (effectiveContent->term()->isModelGroup() && (XsdModelGroup::Ptr(effectiveContent->term())->compositor() == XsdModelGroup::AllCompositor))) { // 4.2.3.2
       
   827                 const XsdParticle::Ptr particle(new XsdParticle());
       
   828                 particle->setMinimumOccurs(effectiveContent->minimumOccurs());
       
   829                 particle->setMaximumOccurs(1);
       
   830                 particle->setMaximumOccursUnbounded(false);
       
   831 
       
   832                 const XsdModelGroup::Ptr group(new XsdModelGroup());
       
   833                 group->setCompositor(XsdModelGroup::AllCompositor);
       
   834                 XsdParticle::List particles = XsdModelGroup::Ptr(baseParticle->term())->particles();
       
   835                 particles << XsdModelGroup::Ptr(effectiveContent->term())->particles();
       
   836                 group->setParticles(particles);
       
   837                 particle->setTerm(group);
       
   838 
       
   839                 explicitContentType->setParticle(particle);
       
   840             } else { // 4.2.3.3
       
   841                 const XsdParticle::Ptr particle(new XsdParticle());
       
   842                 particle->setMinimumOccurs(1);
       
   843                 particle->setMaximumOccurs(1);
       
   844                 particle->setMaximumOccursUnbounded(false);
       
   845 
       
   846                 const XsdModelGroup::Ptr group(new XsdModelGroup());
       
   847                 group->setCompositor(XsdModelGroup::SequenceCompositor);
       
   848 
       
   849                 if (effectiveContent && effectiveContent->term()->isModelGroup() && XsdModelGroup::Ptr(effectiveContent->term())->compositor() == XsdModelGroup::AllCompositor) {
       
   850                     m_context->error(QtXmlPatterns::tr("Content model of complex type %1 contains %2 element so it cannot be derived by extension from a non-empty type.")
       
   851                                                       .arg(formatType(m_namePool, complexType)).arg(formatKeyword("all")), XsdSchemaContext::XSDError, sourceLocation(complexType));
       
   852                     return;
       
   853                 }
       
   854 
       
   855                 if (baseParticle && baseParticle->term()->isModelGroup() && XsdModelGroup::Ptr(baseParticle->term())->compositor() == XsdModelGroup::AllCompositor) {
       
   856                     m_context->error(QtXmlPatterns::tr("Complex type %1 cannot be derived by extension from %2 as the latter contains %3 element in its content model.")
       
   857                                                       .arg(formatType(m_namePool, complexType))
       
   858                                                       .arg(formatType(m_namePool, baseType))
       
   859                                                       .arg(formatKeyword("all")), XsdSchemaContext::XSDError, sourceLocation(complexType));
       
   860                     return;
       
   861                 }
       
   862 
       
   863                 XsdParticle::List particles;
       
   864                 if (baseParticle)
       
   865                     particles << baseParticle;
       
   866                 if (effectiveContent)
       
   867                     particles << effectiveContent;
       
   868                 group->setParticles(particles);
       
   869                 particle->setTerm(group);
       
   870 
       
   871                 explicitContentType->setParticle(particle);
       
   872             }
       
   873 
       
   874             if (baseType->isDefinedBySchema()) { // xs:anyType has no open content
       
   875                 const XsdComplexType::Ptr complexBaseType(baseType);
       
   876                 explicitContentType->setOpenContent(complexBaseType->contentType()->openContent());
       
   877             }
       
   878         }
       
   879     }
       
   880 
       
   881     // 5
       
   882     XsdComplexType::OpenContent::Ptr wildcardElement;
       
   883     if (item.complexType->contentType()->openContent()) { // 5.1
       
   884         wildcardElement = item.complexType->contentType()->openContent();
       
   885     } else {
       
   886         if (m_defaultOpenContent) { // 5.2
       
   887             if ((explicitContentType->variety() != XsdComplexType::ContentType::Empty) || // 5.2.1
       
   888                 (explicitContentType->variety() == XsdComplexType::ContentType::Empty && m_defaultOpenContentAppliesToEmpty)) { // 5.2.2
       
   889                 wildcardElement = m_defaultOpenContent;
       
   890             }
       
   891         }
       
   892     }
       
   893 
       
   894     // 6
       
   895     if (!wildcardElement) { // 6.1
       
   896         item.complexType->setContentType(explicitContentType);
       
   897     } else {
       
   898         if (wildcardElement->mode() == XsdComplexType::OpenContent::None) { // 6.2
       
   899             const XsdComplexType::ContentType::Ptr contentType(new XsdComplexType::ContentType());
       
   900             contentType->setVariety(explicitContentType->variety());
       
   901             contentType->setParticle(explicitContentType->particle());
       
   902 
       
   903             item.complexType->setContentType(contentType);
       
   904         } else { // 6.3
       
   905             const XsdComplexType::ContentType::Ptr contentType(new XsdComplexType::ContentType());
       
   906 
       
   907             if (explicitContentType->variety() == XsdComplexType::ContentType::Empty)
       
   908                 contentType->setVariety(XsdComplexType::ContentType::ElementOnly);
       
   909             else
       
   910                 contentType->setVariety(explicitContentType->variety());
       
   911 
       
   912             if (explicitContentType->variety() == XsdComplexType::ContentType::Empty) {
       
   913                 const XsdParticle::Ptr particle(new XsdParticle());
       
   914                 particle->setMinimumOccurs(1);
       
   915                 particle->setMaximumOccurs(1);
       
   916                 const XsdModelGroup::Ptr sequence(new XsdModelGroup());
       
   917                 sequence->setCompositor(XsdModelGroup::SequenceCompositor);
       
   918                 particle->setTerm(sequence);
       
   919                 contentType->setParticle(particle);
       
   920             } else {
       
   921                 contentType->setParticle(explicitContentType->particle());
       
   922             }
       
   923 
       
   924             const XsdComplexType::OpenContent::Ptr openContent(new XsdComplexType::OpenContent());
       
   925             if (wildcardElement)
       
   926                 openContent->setMode(wildcardElement->mode());
       
   927             else
       
   928                 openContent->setMode(XsdComplexType::OpenContent::Interleave);
       
   929 
       
   930             if (wildcardElement)
       
   931                 openContent->setWildcard(wildcardElement->wildcard());
       
   932 
       
   933             item.complexType->setContentType(contentType);
       
   934         }
       
   935     }
       
   936 }
       
   937 
       
   938 void XsdSchemaResolver::resolveAttributeTypes()
       
   939 {
       
   940     for (int i = 0; i < m_attributeTypes.count(); ++i) {
       
   941         const AttributeType item = m_attributeTypes.at(i);
       
   942 
       
   943         SchemaType::Ptr type = m_schema->type(item.typeName);
       
   944         if (!type) {
       
   945             // maybe it's a basic type...
       
   946             type = m_context->schemaTypeFactory()->createSchemaType(item.typeName);
       
   947             if (!type) {
       
   948                 m_context->error(QtXmlPatterns::tr("Type %1 of %2 element cannot be resolved.")
       
   949                                                   .arg(formatType(m_namePool, item.typeName))
       
   950                                                   .arg(formatElement("attribute")),
       
   951                                  XsdSchemaContext::XSDError, item.location);
       
   952                 return;
       
   953             }
       
   954         }
       
   955 
       
   956         if (!type->isSimpleType() && type->category() != SchemaType::None) {
       
   957             m_context->error(QtXmlPatterns::tr("Type of %1 element must be a simple type, %2 is not.")
       
   958                                               .arg(formatElement("attribute"))
       
   959                                               .arg(formatType(m_namePool, item.typeName)),
       
   960                              XsdSchemaContext::XSDError, item.location);
       
   961             return;
       
   962         }
       
   963 
       
   964         item.attribute->setType(type);
       
   965     }
       
   966 }
       
   967 
       
   968 void XsdSchemaResolver::resolveAlternativeTypes()
       
   969 {
       
   970     for (int i = 0; i < m_alternativeTypes.count(); ++i) {
       
   971         const AlternativeType item = m_alternativeTypes.at(i);
       
   972 
       
   973         SchemaType::Ptr type = m_schema->type(item.typeName);
       
   974         if (!type) {
       
   975             // maybe it's a basic type...
       
   976             type = m_context->schemaTypeFactory()->createSchemaType(item.typeName);
       
   977             if (!type) {
       
   978                 m_context->error(QtXmlPatterns::tr("Type %1 of %2 element cannot be resolved.")
       
   979                                                   .arg(formatType(m_namePool, item.typeName))
       
   980                                                   .arg(formatElement("alternative")),
       
   981                                  XsdSchemaContext::XSDError, item.location);
       
   982                 return;
       
   983             }
       
   984         }
       
   985 
       
   986         item.alternative->setType(type);
       
   987     }
       
   988 
       
   989     for (int i = 0; i < m_alternativeTypeElements.count(); ++i) {
       
   990         const AlternativeTypeElement item = m_alternativeTypeElements.at(i);
       
   991         item.alternative->setType(item.element->type());
       
   992     }
       
   993 }
       
   994 
       
   995 bool hasCircularSubstitutionGroup(const XsdElement::Ptr &current, const XsdElement::Ptr &head, const NamePool::Ptr &namePool)
       
   996 {
       
   997     if (current == head)
       
   998         return true;
       
   999     else {
       
  1000         const XsdElement::List elements = current->substitutionGroupAffiliations();
       
  1001         for (int i = 0; i < elements.count(); ++i) {
       
  1002             if (hasCircularSubstitutionGroup(elements.at(i), head, namePool))
       
  1003                 return true;
       
  1004         }
       
  1005     }
       
  1006 
       
  1007     return false;
       
  1008 }
       
  1009 
       
  1010 void XsdSchemaResolver::resolveSubstitutionGroupAffiliations()
       
  1011 {
       
  1012     for (int i = 0; i < m_substitutionGroupAffiliations.count(); ++i) {
       
  1013         const SubstitutionGroupAffiliation item = m_substitutionGroupAffiliations.at(i);
       
  1014 
       
  1015         XsdElement::List affiliations;
       
  1016         for (int j = 0; j < item.elementNames.count(); ++j) {
       
  1017             const XsdElement::Ptr element = m_schema->element(item.elementNames.at(j));
       
  1018             if (!element) {
       
  1019                 m_context->error(QtXmlPatterns::tr("Substitution group %1 of %2 element cannot be resolved.")
       
  1020                                                   .arg(formatKeyword(m_namePool, item.elementNames.at(j)))
       
  1021                                                   .arg(formatElement("element")),
       
  1022                                  XsdSchemaContext::XSDError, item.location);
       
  1023                 return;
       
  1024             }
       
  1025 
       
  1026             // @see http://www.w3.org/TR/xmlschema11-1/#e-props-correct 5)
       
  1027             if (hasCircularSubstitutionGroup(element, item.element, m_namePool)) {
       
  1028                 m_context->error(QtXmlPatterns::tr("Substitution group %1 has circular definition.").arg(formatKeyword(m_namePool, item.elementNames.at(j))), XsdSchemaContext::XSDError, item.location);
       
  1029                 return;
       
  1030             }
       
  1031 
       
  1032             affiliations.append(element);
       
  1033         }
       
  1034 
       
  1035         item.element->setSubstitutionGroupAffiliations(affiliations);
       
  1036     }
       
  1037 
       
  1038     for (int i = 0; i < m_substitutionGroupTypes.count(); ++i) {
       
  1039         const XsdElement::Ptr element = m_substitutionGroupTypes.at(i);
       
  1040         element->setType(element->substitutionGroupAffiliations().first()->type());
       
  1041     }
       
  1042 }
       
  1043 
       
  1044 bool isSubstGroupHeadOf(const XsdElement::Ptr &head, const XsdElement::Ptr &element, const NamePool::Ptr &namePool)
       
  1045 {
       
  1046     if (head->name(namePool) == element->name(namePool))
       
  1047         return true;
       
  1048 
       
  1049     const XsdElement::List affiliations = element->substitutionGroupAffiliations();
       
  1050     for (int i = 0; i < affiliations.count(); ++i) {
       
  1051         if (isSubstGroupHeadOf(head, affiliations.at(i), namePool))
       
  1052             return true;
       
  1053     }
       
  1054 
       
  1055     return false;
       
  1056 }
       
  1057 
       
  1058 void XsdSchemaResolver::resolveSubstitutionGroups()
       
  1059 {
       
  1060     const XsdElement::List elements = m_schema->elements();
       
  1061     for (int i = 0; i < elements.count(); ++i) {
       
  1062         const XsdElement::Ptr element = elements.at(i);
       
  1063 
       
  1064         // the element is always itself in the substitution group
       
  1065         element->addSubstitutionGroup(element);
       
  1066 
       
  1067         for (int j = 0; j < elements.count(); ++j) {
       
  1068             if (i == j)
       
  1069                 continue;
       
  1070 
       
  1071             if (isSubstGroupHeadOf(element, elements.at(j), m_namePool))
       
  1072                 element->addSubstitutionGroup(elements.at(j));
       
  1073         }
       
  1074     }
       
  1075 }
       
  1076 
       
  1077 void XsdSchemaResolver::resolveTermReferences()
       
  1078 {
       
  1079     // first the global complex types
       
  1080     const SchemaType::List types = m_schema->types();
       
  1081     for (int i = 0; i < types.count(); ++i) {
       
  1082         if (!(types.at(i)->isComplexType()) || !types.at(i)->isDefinedBySchema())
       
  1083             continue;
       
  1084 
       
  1085         const XsdComplexType::Ptr complexType = types.at(i);
       
  1086         if (complexType->contentType()->variety() != XsdComplexType::ContentType::ElementOnly && complexType->contentType()->variety() != XsdComplexType::ContentType::Mixed)
       
  1087             continue;
       
  1088 
       
  1089         resolveTermReference(complexType->contentType()->particle(), QSet<QXmlName>());
       
  1090     }
       
  1091 
       
  1092     // then all anonymous complex types
       
  1093     const SchemaType::List anonymousTypes = m_schema->anonymousTypes();
       
  1094     for (int i = 0; i < anonymousTypes.count(); ++i) {
       
  1095         if (!(anonymousTypes.at(i)->isComplexType()) || !anonymousTypes.at(i)->isDefinedBySchema())
       
  1096             continue;
       
  1097 
       
  1098         const XsdComplexType::Ptr complexType = anonymousTypes.at(i);
       
  1099         if (complexType->contentType()->variety() != XsdComplexType::ContentType::ElementOnly && complexType->contentType()->variety() != XsdComplexType::ContentType::Mixed)
       
  1100             continue;
       
  1101 
       
  1102         resolveTermReference(complexType->contentType()->particle(), QSet<QXmlName>());
       
  1103     }
       
  1104 
       
  1105     const XsdModelGroup::List groups = m_schema->elementGroups();
       
  1106     for (int i = 0; i < groups.count(); ++i) {
       
  1107         const XsdParticle::Ptr particle(new XsdParticle());
       
  1108         particle->setTerm(groups.at(i));
       
  1109         resolveTermReference(particle, QSet<QXmlName>());
       
  1110     }
       
  1111 }
       
  1112 
       
  1113 void XsdSchemaResolver::resolveTermReference(const XsdParticle::Ptr &particle, QSet<QXmlName> visitedGroups)
       
  1114 {
       
  1115     if (!particle)
       
  1116         return;
       
  1117 
       
  1118     const XsdTerm::Ptr term = particle->term();
       
  1119 
       
  1120     // if it is a model group, we iterate over it recursive...
       
  1121     if (term->isModelGroup()) {
       
  1122         const XsdModelGroup::Ptr modelGroup = term;
       
  1123         const XsdParticle::List particles = modelGroup->particles();
       
  1124 
       
  1125         for (int i = 0; i < particles.count(); ++i) {
       
  1126             resolveTermReference(particles.at(i), visitedGroups);
       
  1127         }
       
  1128 
       
  1129         // check for unique names of elements inside all compositor
       
  1130         if (modelGroup->compositor() != XsdModelGroup::ChoiceCompositor) {
       
  1131             for (int i = 0; i < particles.count(); ++i) {
       
  1132                 const XsdParticle::Ptr particle = particles.at(i);
       
  1133                 const XsdTerm::Ptr term = particle->term();
       
  1134 
       
  1135                 if (!(term->isElement()))
       
  1136                     continue;
       
  1137 
       
  1138                 for (int j = 0; j < particles.count(); ++j) {
       
  1139                     const XsdParticle::Ptr otherParticle = particles.at(j);
       
  1140                     const XsdTerm::Ptr otherTerm = otherParticle->term();
       
  1141 
       
  1142                     if (otherTerm->isElement() && i != j) {
       
  1143                         const XsdElement::Ptr element = term;
       
  1144                         const XsdElement::Ptr otherElement = otherTerm;
       
  1145 
       
  1146                         if (element->name(m_namePool) == otherElement->name(m_namePool)) {
       
  1147                             if (modelGroup->compositor() == XsdModelGroup::AllCompositor) {
       
  1148                                 m_context->error(QtXmlPatterns::tr("Duplicated element names %1 in %2 element.")
       
  1149                                                                   .arg(formatKeyword(element->displayName(m_namePool)))
       
  1150                                                                   .arg(formatElement("all")),
       
  1151                                                  XsdSchemaContext::XSDError, sourceLocation(modelGroup));
       
  1152                                 return;
       
  1153                             } else if (modelGroup->compositor() == XsdModelGroup::SequenceCompositor) {
       
  1154                                 if (element->type() != otherElement->type()) {  // not same variety
       
  1155                                     m_context->error(QtXmlPatterns::tr("Duplicated element names %1 in %2 element.")
       
  1156                                                                       .arg(formatKeyword(element->displayName(m_namePool)))
       
  1157                                                                       .arg(formatElement("sequence")),
       
  1158                                                      XsdSchemaContext::XSDError, sourceLocation(modelGroup));
       
  1159                                     return;
       
  1160                                 }
       
  1161                             }
       
  1162                         }
       
  1163                     }
       
  1164                 }
       
  1165             }
       
  1166         }
       
  1167 
       
  1168         return;
       
  1169     }
       
  1170 
       
  1171     // ...otherwise we have reached the end of recursion...
       
  1172     if (!term->isReference())
       
  1173         return;
       
  1174 
       
  1175     // ...or we have reached a reference term that must be resolved
       
  1176     const XsdReference::Ptr reference = term;
       
  1177     switch (reference->type()) {
       
  1178         case XsdReference::Element:
       
  1179                 {
       
  1180                     const XsdElement::Ptr element = m_schema->element(reference->referenceName());
       
  1181                     if (element) {
       
  1182                         particle->setTerm(element);
       
  1183                     } else {
       
  1184                         m_context->error(QtXmlPatterns::tr("Reference %1 of %2 element cannot be resolved.")
       
  1185                                                           .arg(formatKeyword(m_namePool, reference->referenceName()))
       
  1186                                                           .arg(formatElement("element")),
       
  1187                                          XsdSchemaContext::XSDError, reference->sourceLocation());
       
  1188                         return;
       
  1189                     }
       
  1190                 }
       
  1191             break;
       
  1192         case XsdReference::ModelGroup:
       
  1193                 {
       
  1194                     const XsdModelGroup::Ptr modelGroup = m_schema->elementGroup(reference->referenceName());
       
  1195                     if (modelGroup) {
       
  1196                         if (visitedGroups.contains(modelGroup->name(m_namePool))) {
       
  1197                             m_context->error(QtXmlPatterns::tr("Circular group reference for %1.").arg(formatKeyword(modelGroup->displayName(m_namePool))),
       
  1198                                              XsdSchemaContext::XSDError, reference->sourceLocation());
       
  1199                         } else {
       
  1200                             visitedGroups.insert(modelGroup->name(m_namePool));
       
  1201                         }
       
  1202 
       
  1203                         particle->setTerm(modelGroup);
       
  1204 
       
  1205                         // start recursive iteration here as well to get all references resolved
       
  1206                         const XsdParticle::List particles = modelGroup->particles();
       
  1207                         for (int i = 0; i < particles.count(); ++i) {
       
  1208                             resolveTermReference(particles.at(i), visitedGroups);
       
  1209                         }
       
  1210 
       
  1211                         if (modelGroup->compositor() == XsdModelGroup::AllCompositor) {
       
  1212                             if (m_allGroups.contains(reference)) {
       
  1213                                 m_context->error(QtXmlPatterns::tr("%1 element is not allowed in this scope").arg(formatElement("all.")),
       
  1214                                                  XsdSchemaContext::XSDError, reference->sourceLocation());
       
  1215                                 return;
       
  1216                             }
       
  1217                             if (particle->maximumOccursUnbounded() || particle->maximumOccurs() != 1) {
       
  1218                                 m_context->error(QtXmlPatterns::tr("%1 element cannot have %2 attribute with value other than %3.")
       
  1219                                                                   .arg(formatElement("all"))
       
  1220                                                                   .arg(formatAttribute("maxOccurs"))
       
  1221                                                                   .arg(formatData("1")),
       
  1222                                                  XsdSchemaContext::XSDError, reference->sourceLocation());
       
  1223                                 return;
       
  1224                             }
       
  1225                             if (particle->minimumOccurs() != 0 && particle->minimumOccurs() != 1) {
       
  1226                                 m_context->error(QtXmlPatterns::tr("%1 element cannot have %2 attribute with value other than %3 or %4.")
       
  1227                                                                   .arg(formatElement("all"))
       
  1228                                                                   .arg(formatAttribute("minOccurs"))
       
  1229                                                                   .arg(formatData("0"))
       
  1230                                                                   .arg(formatData("1")),
       
  1231                                                  XsdSchemaContext::XSDError, reference->sourceLocation());
       
  1232                                 return;
       
  1233                             }
       
  1234                         }
       
  1235                     } else {
       
  1236                         m_context->error(QtXmlPatterns::tr("Reference %1 of %2 element cannot be resolved.")
       
  1237                                                           .arg(formatKeyword(m_namePool, reference->referenceName()))
       
  1238                                                           .arg(formatElement("group")),
       
  1239                                          XsdSchemaContext::XSDError, reference->sourceLocation());
       
  1240                         return;
       
  1241                     }
       
  1242                 }
       
  1243             break;
       
  1244     }
       
  1245 }
       
  1246 
       
  1247 void XsdSchemaResolver::resolveAttributeTermReferences()
       
  1248 {
       
  1249     // first all global attribute groups
       
  1250     const XsdAttributeGroup::List attributeGroups = m_schema->attributeGroups();
       
  1251     for (int i = 0; i < attributeGroups.count(); ++i) {
       
  1252         XsdWildcard::Ptr wildcard = attributeGroups.at(i)->wildcard();
       
  1253         const XsdAttributeUse::List uses = resolveAttributeTermReferences(attributeGroups.at(i)->attributeUses(), wildcard, QSet<QXmlName>());
       
  1254         attributeGroups.at(i)->setAttributeUses(uses);
       
  1255         attributeGroups.at(i)->setWildcard(wildcard);
       
  1256     }
       
  1257 
       
  1258     // then the global complex types
       
  1259     const SchemaType::List types = m_schema->types();
       
  1260     for (int i = 0; i < types.count(); ++i) {
       
  1261         if (!(types.at(i)->isComplexType()) || !types.at(i)->isDefinedBySchema())
       
  1262             continue;
       
  1263 
       
  1264         const XsdComplexType::Ptr complexType = types.at(i);
       
  1265         const XsdAttributeUse::List attributeUses = complexType->attributeUses();
       
  1266 
       
  1267         XsdWildcard::Ptr wildcard = complexType->attributeWildcard();
       
  1268         const XsdAttributeUse::List uses = resolveAttributeTermReferences(attributeUses, wildcard, QSet<QXmlName>());
       
  1269         complexType->setAttributeUses(uses);
       
  1270         complexType->setAttributeWildcard(wildcard);
       
  1271     }
       
  1272 
       
  1273     // and afterwards all anonymous complex types
       
  1274     const SchemaType::List anonymousTypes = m_schema->anonymousTypes();
       
  1275     for (int i = 0; i < anonymousTypes.count(); ++i) {
       
  1276         if (!(anonymousTypes.at(i)->isComplexType()) || !anonymousTypes.at(i)->isDefinedBySchema())
       
  1277             continue;
       
  1278 
       
  1279         const XsdComplexType::Ptr complexType = anonymousTypes.at(i);
       
  1280         const XsdAttributeUse::List attributeUses = complexType->attributeUses();
       
  1281 
       
  1282         XsdWildcard::Ptr wildcard = complexType->attributeWildcard();
       
  1283         const XsdAttributeUse::List uses = resolveAttributeTermReferences(attributeUses, wildcard, QSet<QXmlName>());
       
  1284         complexType->setAttributeUses(uses);
       
  1285         complexType->setAttributeWildcard(wildcard);
       
  1286     }
       
  1287 }
       
  1288 
       
  1289 XsdAttributeUse::List XsdSchemaResolver::resolveAttributeTermReferences(const XsdAttributeUse::List &attributeUses, XsdWildcard::Ptr &wildcard, QSet<QXmlName> visitedAttributeGroups)
       
  1290 {
       
  1291     XsdAttributeUse::List resolvedAttributeUses;
       
  1292 
       
  1293     for (int i = 0; i < attributeUses.count(); ++i) {
       
  1294         const XsdAttributeUse::Ptr attributeUse = attributeUses.at(i);
       
  1295         if (attributeUse->isAttributeUse()) {
       
  1296             // it is a real attribute use, so no need to resolve it
       
  1297             resolvedAttributeUses.append(attributeUse);
       
  1298         } else if (attributeUse->isReference()) {
       
  1299             // it is just a reference, so resolve it to the real attribute use
       
  1300 
       
  1301             const XsdAttributeReference::Ptr reference = attributeUse;
       
  1302             if (reference->type() == XsdAttributeReference::AttributeUse) {
       
  1303 
       
  1304                 // lookup the real attribute
       
  1305                 const XsdAttribute::Ptr attribute = m_schema->attribute(reference->referenceName());
       
  1306                 if (!attribute) {
       
  1307                     m_context->error(QtXmlPatterns::tr("Reference %1 of %2 element cannot be resolved.")
       
  1308                                                       .arg(formatKeyword(m_namePool, reference->referenceName()))
       
  1309                                                       .arg(formatElement("attribute")),
       
  1310                                      XsdSchemaContext::XSDError, reference->sourceLocation());
       
  1311                     return XsdAttributeUse::List();
       
  1312                 }
       
  1313 
       
  1314                 // if both, reference and definition have a fixed or default value set, then they must be equal
       
  1315                 if (attribute->valueConstraint() && attributeUse->valueConstraint()) {
       
  1316                     if (attribute->valueConstraint()->value() != attributeUse->valueConstraint()->value()) {
       
  1317                         m_context->error(QtXmlPatterns::tr("%1 or %2 attribute of reference %3 does not match with the attribute declaration %4.")
       
  1318                                                           .arg(formatAttribute("fixed"))
       
  1319                                                           .arg(formatAttribute("default"))
       
  1320                                                           .arg(formatKeyword(m_namePool, reference->referenceName()))
       
  1321                                                           .arg(formatKeyword(attribute->displayName(m_namePool))),
       
  1322                                          XsdSchemaContext::XSDError, reference->sourceLocation());
       
  1323                         return XsdAttributeUse::List();
       
  1324                     }
       
  1325                 }
       
  1326 
       
  1327                 attributeUse->setAttribute(attribute);
       
  1328                 if (!attributeUse->valueConstraint() && attribute->valueConstraint())
       
  1329                     attributeUse->setValueConstraint(XsdAttributeUse::ValueConstraint::fromAttributeValueConstraint(attribute->valueConstraint()));
       
  1330 
       
  1331                 resolvedAttributeUses.append(attributeUse);
       
  1332             } else if (reference->type() == XsdAttributeReference::AttributeGroup) {
       
  1333                 const XsdAttributeGroup::Ptr attributeGroup = m_schema->attributeGroup(reference->referenceName());
       
  1334                 if (!attributeGroup) {
       
  1335                     m_context->error(QtXmlPatterns::tr("Reference %1 of %2 element cannot be resolved.")
       
  1336                                                       .arg(formatKeyword(m_namePool, reference->referenceName()))
       
  1337                                                       .arg(formatElement("attributeGroup")),
       
  1338                                      XsdSchemaContext::XSDError, reference->sourceLocation());
       
  1339                     return XsdAttributeUse::List();
       
  1340                 }
       
  1341                 if (visitedAttributeGroups.contains(attributeGroup->name(m_namePool))) {
       
  1342                     m_context->error(QtXmlPatterns::tr("Attribute group %1 has circular reference.").arg(formatKeyword(m_namePool, reference->referenceName())),
       
  1343                                      XsdSchemaContext::XSDError, reference->sourceLocation());
       
  1344                     return XsdAttributeUse::List();
       
  1345                 } else {
       
  1346                     visitedAttributeGroups.insert(attributeGroup->name(m_namePool));
       
  1347                 }
       
  1348 
       
  1349                 // resolve attribute wildcards as defined in http://www.w3.org/TR/xmlschema11-1/#declare-attributeGroup-wildcard
       
  1350                 XsdWildcard::Ptr childWildcard;
       
  1351                 resolvedAttributeUses << resolveAttributeTermReferences(attributeGroup->attributeUses(), childWildcard, visitedAttributeGroups);
       
  1352                 if (!childWildcard) {
       
  1353                     if (attributeGroup->wildcard()) {
       
  1354                         if (wildcard) {
       
  1355                             const XsdWildcard::ProcessContents contents = wildcard->processContents();
       
  1356                             wildcard = XsdSchemaHelper::wildcardIntersection(wildcard, attributeGroup->wildcard());
       
  1357                             wildcard->setProcessContents(contents);
       
  1358                         } else {
       
  1359                             wildcard = attributeGroup->wildcard();
       
  1360                         }
       
  1361                     }
       
  1362                 } else {
       
  1363                     XsdWildcard::Ptr newWildcard;
       
  1364                     if (attributeGroup->wildcard()) {
       
  1365                         const XsdWildcard::ProcessContents contents = attributeGroup->wildcard()->processContents();
       
  1366                         newWildcard = XsdSchemaHelper::wildcardIntersection(attributeGroup->wildcard(), childWildcard);
       
  1367                         newWildcard->setProcessContents(contents);
       
  1368                     } else {
       
  1369                         newWildcard = childWildcard;
       
  1370                     }
       
  1371 
       
  1372                     if (wildcard) {
       
  1373                         const XsdWildcard::ProcessContents contents = wildcard->processContents();
       
  1374                         wildcard = XsdSchemaHelper::wildcardIntersection(wildcard, newWildcard);
       
  1375                         wildcard->setProcessContents(contents);
       
  1376                     } else {
       
  1377                         wildcard = newWildcard;
       
  1378                     }
       
  1379                 }
       
  1380             }
       
  1381         }
       
  1382     }
       
  1383 
       
  1384     return resolvedAttributeUses;
       
  1385 }
       
  1386 
       
  1387 void XsdSchemaResolver::resolveAttributeInheritance()
       
  1388 {
       
  1389     // collect the global and anonymous complex types
       
  1390     SchemaType::List types = m_schema->types();
       
  1391     types << m_schema->anonymousTypes();
       
  1392 
       
  1393     QSet<XsdComplexType::Ptr> visitedTypes;
       
  1394     for (int i = 0; i < types.count(); ++i) {
       
  1395         if (!(types.at(i)->isComplexType()) || !types.at(i)->isDefinedBySchema())
       
  1396             continue;
       
  1397 
       
  1398         const XsdComplexType::Ptr complexType = types.at(i);
       
  1399 
       
  1400         resolveAttributeInheritance(complexType, visitedTypes);
       
  1401     }
       
  1402 }
       
  1403 
       
  1404 bool isValidWildcardRestriction(const XsdWildcard::Ptr &wildcard, const XsdWildcard::Ptr &baseWildcard)
       
  1405 {
       
  1406     if (wildcard->namespaceConstraint()->variety() == baseWildcard->namespaceConstraint()->variety()) {
       
  1407         if (!XsdSchemaHelper::checkWildcardProcessContents(baseWildcard, wildcard))
       
  1408             return false;
       
  1409     }
       
  1410 
       
  1411     if (wildcard->namespaceConstraint()->variety() == XsdWildcard::NamespaceConstraint::Any &&
       
  1412         baseWildcard->namespaceConstraint()->variety() != XsdWildcard::NamespaceConstraint::Any ) {
       
  1413         return false;
       
  1414     }
       
  1415     if (baseWildcard->namespaceConstraint()->variety() == XsdWildcard::NamespaceConstraint::Not &&
       
  1416         wildcard->namespaceConstraint()->variety() == XsdWildcard::NamespaceConstraint::Enumeration) {
       
  1417         if (!baseWildcard->namespaceConstraint()->namespaces().intersect(wildcard->namespaceConstraint()->namespaces()).isEmpty())
       
  1418             return false;
       
  1419     }
       
  1420     if (baseWildcard->namespaceConstraint()->variety() == XsdWildcard::NamespaceConstraint::Enumeration &&
       
  1421         wildcard->namespaceConstraint()->variety() == XsdWildcard::NamespaceConstraint::Enumeration) {
       
  1422         if (!wildcard->namespaceConstraint()->namespaces().subtract(baseWildcard->namespaceConstraint()->namespaces()).isEmpty())
       
  1423             return false;
       
  1424     }
       
  1425 
       
  1426     return true;
       
  1427 }
       
  1428 
       
  1429 /*
       
  1430  * Since we inherit the attributes from our base class we have to walk up in the
       
  1431  * inheritance hierarchy first and resolve the attribute inheritance top-down.
       
  1432  */
       
  1433 void XsdSchemaResolver::resolveAttributeInheritance(const XsdComplexType::Ptr &complexType, QSet<XsdComplexType::Ptr> &visitedTypes)
       
  1434 {
       
  1435     if (visitedTypes.contains(complexType))
       
  1436         return;
       
  1437     else
       
  1438         visitedTypes.insert(complexType);
       
  1439 
       
  1440     const SchemaType::Ptr baseType = complexType->wxsSuperType();
       
  1441     Q_ASSERT(baseType);
       
  1442 
       
  1443     if (!(baseType->isComplexType()) || !baseType->isDefinedBySchema())
       
  1444         return;
       
  1445 
       
  1446     const XsdComplexType::Ptr complexBaseType = baseType;
       
  1447 
       
  1448     resolveAttributeInheritance(complexBaseType, visitedTypes);
       
  1449 
       
  1450     // @see http://www.w3.org/TR/xmlschema11-1/#dcl.ctd.attuses
       
  1451 
       
  1452     // 1 and 2 (the attribute groups have been resolved here already)
       
  1453     const XsdAttributeUse::List uses = complexBaseType->attributeUses();
       
  1454 
       
  1455     if (complexType->derivationMethod() == XsdComplexType::DerivationRestriction) { // 3.2
       
  1456         const XsdAttributeUse::List currentUses = complexType->attributeUses();
       
  1457 
       
  1458         // 3.2.1 and 3.2.2 As we also keep the prohibited attributes as objects, the algorithm below
       
  1459         // handles both the same way
       
  1460 
       
  1461         // add only these attribute uses of the base type that match one of the following criteria:
       
  1462         //   1: there is no attribute use with the same name in type
       
  1463         //   2: there is no attribute with the same name marked as prohibited in type
       
  1464         for (int j = 0; j < uses.count(); ++j) {
       
  1465             const XsdAttributeUse::Ptr use = uses.at(j);
       
  1466             bool found = false;
       
  1467             for (int k = 0; k < currentUses.count(); ++k) {
       
  1468                 if (use->attribute()->name(m_namePool) == currentUses.at(k)->attribute()->name(m_namePool)) {
       
  1469                     found = true;
       
  1470 
       
  1471                     // check if prohibited usage is violated
       
  1472                     if ((use->useType() == XsdAttributeUse::ProhibitedUse) && (currentUses.at(k)->useType() != XsdAttributeUse::ProhibitedUse)) {
       
  1473                         m_context->error(QtXmlPatterns::tr("%1 attribute in %2 must have %3 use like in base type %4.")
       
  1474                                                             .arg(formatAttribute(use->attribute()->displayName(m_namePool)))
       
  1475                                                             .arg(formatType(m_namePool, complexType))
       
  1476                                                             .arg(formatData("prohibited"))
       
  1477                                                             .arg(formatType(m_namePool, complexBaseType)),
       
  1478                                                              XsdSchemaContext::XSDError, sourceLocation(complexType));
       
  1479                         return;
       
  1480                     }
       
  1481 
       
  1482                     break;
       
  1483                 }
       
  1484             }
       
  1485 
       
  1486             if (!found && uses.at(j)->useType() != XsdAttributeUse::ProhibitedUse) {
       
  1487                 complexType->addAttributeUse(uses.at(j));
       
  1488             }
       
  1489         }
       
  1490     } else if (complexType->derivationMethod() == XsdComplexType::DerivationExtension) { // 3.1
       
  1491         QHash<QXmlName, XsdAttributeUse::Ptr> availableUses;
       
  1492 
       
  1493         // fill hash with attribute uses of current type for faster lookup
       
  1494         {
       
  1495             const XsdAttributeUse::List attributeUses = complexType->attributeUses();
       
  1496 
       
  1497             for (int i = 0; i < attributeUses.count(); ++i) {
       
  1498                 availableUses.insert(attributeUses.at(i)->attribute()->name(m_namePool), attributeUses.at(i));
       
  1499             }
       
  1500         }
       
  1501 
       
  1502         // just add the attribute uses of the base type
       
  1503         for (int i = 0; i < uses.count(); ++i) {
       
  1504             const XsdAttributeUse::Ptr currentAttributeUse = uses.at(i);
       
  1505 
       
  1506             // if the base type defines the attribute as prohibited but we override it in current type, then don't copy the prohibited attribute use
       
  1507             if ((currentAttributeUse->useType() == XsdAttributeUse::ProhibitedUse) && availableUses.contains(currentAttributeUse->attribute()->name(m_namePool)))
       
  1508                 continue;
       
  1509 
       
  1510             complexType->addAttributeUse(uses.at(i));
       
  1511         }
       
  1512     }
       
  1513 
       
  1514     // handle attribute wildcards: @see http://www.w3.org/TR/xmlschema11-1/#dcl.ctd.anyatt
       
  1515 
       
  1516     // 1
       
  1517     const XsdWildcard::Ptr completeWildcard(complexType->attributeWildcard());
       
  1518 
       
  1519     if (complexType->derivationMethod() == XsdComplexType::DerivationRestriction) {
       
  1520         if (complexType->wxsSuperType()->isComplexType() && complexType->wxsSuperType()->isDefinedBySchema()) {
       
  1521             const XsdComplexType::Ptr complexBaseType(complexType->wxsSuperType());
       
  1522             if (complexType->attributeWildcard()) {
       
  1523                 if (complexBaseType->attributeWildcard()) {
       
  1524                     if (!isValidWildcardRestriction(complexType->attributeWildcard(), complexBaseType->attributeWildcard())) {
       
  1525                         m_context->error(QtXmlPatterns::tr("Attribute wildcard of %1 is not a valid restriction of attribute wildcard of base type %2.")
       
  1526                                                             .arg(formatType(m_namePool, complexType))
       
  1527                                                             .arg(formatType(m_namePool, complexBaseType)),
       
  1528                                                              XsdSchemaContext::XSDError, sourceLocation(complexType));
       
  1529                         return;
       
  1530                     }
       
  1531                 } else {
       
  1532                     m_context->error(QtXmlPatterns::tr("%1 has attribute wildcard but its base type %2 has not.")
       
  1533                                                         .arg(formatType(m_namePool, complexType))
       
  1534                                                         .arg(formatType(m_namePool, complexBaseType)),
       
  1535                                                          XsdSchemaContext::XSDError, sourceLocation(complexType));
       
  1536                     return;
       
  1537                 }
       
  1538             }
       
  1539         }
       
  1540         complexType->setAttributeWildcard(completeWildcard); // 2.1
       
  1541     } else if (complexType->derivationMethod() == XsdComplexType::DerivationExtension) {
       
  1542         XsdWildcard::Ptr baseWildcard; // 2.2.1
       
  1543         if (complexType->wxsSuperType()->isComplexType() && complexType->wxsSuperType()->isDefinedBySchema())
       
  1544             baseWildcard = XsdComplexType::Ptr(complexType->wxsSuperType())->attributeWildcard(); // 2.2.1.1
       
  1545         else
       
  1546             baseWildcard = XsdWildcard::Ptr(); // 2.2.1.2
       
  1547 
       
  1548         if (!baseWildcard) {
       
  1549             complexType->setAttributeWildcard(completeWildcard); // 2.2.2.1
       
  1550         } else if (!completeWildcard) {
       
  1551             complexType->setAttributeWildcard(baseWildcard); // 2.2.2.2
       
  1552         } else {
       
  1553             XsdWildcard::Ptr unionWildcard = XsdSchemaHelper::wildcardUnion(completeWildcard, baseWildcard);
       
  1554             if (unionWildcard) {
       
  1555                 unionWildcard->setProcessContents(completeWildcard->processContents());
       
  1556                 complexType->setAttributeWildcard(unionWildcard); // 2.2.2.3
       
  1557             } else {
       
  1558                 m_context->error(QtXmlPatterns::tr("Union of attribute wildcard of type %1 and attribute wildcard of its base type %2 is not expressible.")
       
  1559                                                     .arg(formatType(m_namePool, complexType))
       
  1560                                                     .arg(formatType(m_namePool, complexBaseType)),
       
  1561                                                      XsdSchemaContext::XSDError, sourceLocation(complexType));
       
  1562                 return;
       
  1563             }
       
  1564         }
       
  1565     }
       
  1566 }
       
  1567 
       
  1568 void XsdSchemaResolver::resolveEnumerationFacetValues()
       
  1569 {
       
  1570     XsdSimpleType::List simpleTypes;
       
  1571 
       
  1572     // first collect the global simple types
       
  1573     const SchemaType::List types = m_schema->types();
       
  1574     for (int i = 0; i < types.count(); ++i) {
       
  1575         if (types.at(i)->isSimpleType())
       
  1576             simpleTypes.append(types.at(i));
       
  1577     }
       
  1578 
       
  1579     // then collect all anonymous simple types
       
  1580     const SchemaType::List anonymousTypes = m_schema->anonymousTypes();
       
  1581     for (int i = 0; i < anonymousTypes.count(); ++i) {
       
  1582         if (anonymousTypes.at(i)->isSimpleType())
       
  1583             simpleTypes.append(anonymousTypes.at(i));
       
  1584     }
       
  1585     // process all simple types
       
  1586     for (int i = 0; i < simpleTypes.count(); ++i) {
       
  1587         const XsdSimpleType::Ptr simpleType = simpleTypes.at(i);
       
  1588 
       
  1589         // we resolve the enumeration values only for xs:QName and xs:NOTATION based types
       
  1590         if (BuiltinTypes::xsQName->wxsTypeMatches(simpleType) ||
       
  1591             BuiltinTypes::xsNOTATION->wxsTypeMatches(simpleType)) {
       
  1592             const XsdFacet::Hash facets = simpleType->facets();
       
  1593             if (facets.contains(XsdFacet::Enumeration)) {
       
  1594                 AtomicValue::List newValues;
       
  1595 
       
  1596                 const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
       
  1597                 const AtomicValue::List values = facet->multiValue();
       
  1598                 for (int j = 0; j < values.count(); ++j) {
       
  1599                     const AtomicValue::Ptr value = values.at(j);
       
  1600 
       
  1601                     Q_ASSERT(m_enumerationFacetValues.contains(value));
       
  1602                     const NamespaceSupport support( m_enumerationFacetValues.value(value) );
       
  1603 
       
  1604                     const QString qualifiedName = value->as<DerivedString<TypeString> >()->stringValue();
       
  1605                     if (!XPathHelper::isQName(qualifiedName)) {
       
  1606                         m_context->error(QtXmlPatterns::tr("Enumeration facet contains invalid content: {%1} is not a value of type %2.")
       
  1607                                                           .arg(formatData(qualifiedName))
       
  1608                                                           .arg(formatType(m_namePool, BuiltinTypes::xsQName)),
       
  1609                                          XsdSchemaContext::XSDError, sourceLocation(simpleType));
       
  1610                         return;
       
  1611                     }
       
  1612 
       
  1613                     QXmlName qNameValue;
       
  1614                     bool result = support.processName(qualifiedName, NamespaceSupport::ElementName, qNameValue);
       
  1615                     if (!result) {
       
  1616                         m_context->error(QtXmlPatterns::tr("Namespace prefix of qualified name %1 is not defined.").arg(formatData(qualifiedName)),
       
  1617                                          XsdSchemaContext::XSDError, sourceLocation(simpleType));
       
  1618                         return;
       
  1619                     }
       
  1620 
       
  1621                     newValues.append(QNameValue::fromValue(m_namePool, qNameValue));
       
  1622                 }
       
  1623                 facet->setMultiValue(newValues);
       
  1624             }
       
  1625         }
       
  1626     }
       
  1627 }
       
  1628 
       
  1629 QSourceLocation XsdSchemaResolver::sourceLocation(const NamedSchemaComponent::Ptr component) const
       
  1630 {
       
  1631     if (m_componentLocationHash.contains(component)) {
       
  1632         return m_componentLocationHash.value(component);
       
  1633     } else {
       
  1634         QSourceLocation location;
       
  1635         location.setLine(1);
       
  1636         location.setColumn(1);
       
  1637         location.setUri(QString::fromLatin1("dummyUri"));
       
  1638 
       
  1639         return location;
       
  1640     }
       
  1641 }
       
  1642 
       
  1643 XsdFacet::Hash XsdSchemaResolver::complexTypeFacets(const XsdComplexType::Ptr &complexType) const
       
  1644 {
       
  1645     for (int i = 0; i < m_complexBaseTypes.count(); ++i) {
       
  1646         if (m_complexBaseTypes.at(i).complexType == complexType)
       
  1647             return m_complexBaseTypes.at(i).facets;
       
  1648     }
       
  1649 
       
  1650     return XsdFacet::Hash();
       
  1651 }
       
  1652 
       
  1653 void XsdSchemaResolver::checkRedefinedGroups()
       
  1654 {
       
  1655     for (int i = 0; i < m_redefinedGroups.count(); ++i) {
       
  1656         const RedefinedGroups item = m_redefinedGroups.at(i);
       
  1657 
       
  1658         // create dummy particles...
       
  1659         const XsdParticle::Ptr redefinedParticle(new XsdParticle());
       
  1660         redefinedParticle->setTerm(item.redefinedGroup);
       
  1661         const XsdParticle::Ptr particle(new XsdParticle());
       
  1662         particle->setTerm(item.group);
       
  1663 
       
  1664         // so that we can pass them to XsdParticleChecker::subsumes()
       
  1665         QString errorMsg;
       
  1666         if (!XsdParticleChecker::subsumes(particle, redefinedParticle, m_context, errorMsg)) {
       
  1667             m_context->error(QtXmlPatterns::tr("%1 element %2 is not a valid restriction of the %3 element it redefines: %4.")
       
  1668                                               .arg(formatElement("group"))
       
  1669                                               .arg(formatData(item.redefinedGroup->displayName(m_namePool)))
       
  1670                                               .arg(formatElement("group"))
       
  1671                                               .arg(errorMsg),
       
  1672                              XsdSchemaContext::XSDError, sourceLocation(item.redefinedGroup));
       
  1673             return;
       
  1674         }
       
  1675     }
       
  1676 }
       
  1677 
       
  1678 void XsdSchemaResolver::checkRedefinedAttributeGroups()
       
  1679 {
       
  1680     for (int i = 0; i < m_redefinedAttributeGroups.count(); ++i) {
       
  1681         const RedefinedAttributeGroups item = m_redefinedAttributeGroups.at(i);
       
  1682 
       
  1683         QString errorMsg;
       
  1684         if (!XsdSchemaHelper::isValidAttributeGroupRestriction(item.redefinedGroup, item.group, m_context, errorMsg)) {
       
  1685             m_context->error(QtXmlPatterns::tr("%1 element %2 is not a valid restriction of the %3 element it redefines: %4.")
       
  1686                                               .arg(formatElement("attributeGroup"))
       
  1687                                               .arg(formatData(item.redefinedGroup->displayName(m_namePool)))
       
  1688                                               .arg(formatElement("attributeGroup"))
       
  1689                                               .arg(errorMsg),
       
  1690                              XsdSchemaContext::XSDError, sourceLocation(item.redefinedGroup));
       
  1691             return;
       
  1692         }
       
  1693     }
       
  1694 }
       
  1695 
       
  1696 AnySimpleType::Ptr XsdSchemaResolver::findPrimitiveType(const AnySimpleType::Ptr &type, QSet<AnySimpleType::Ptr> &visitedTypes)
       
  1697 {
       
  1698     if (visitedTypes.contains(type)) {
       
  1699         // found invalid circular reference...
       
  1700         return AnySimpleType::Ptr();
       
  1701     } else {
       
  1702         visitedTypes.insert(type);
       
  1703     }
       
  1704 
       
  1705     const QXmlName typeName = type->name(m_namePool);
       
  1706     if (typeName == BuiltinTypes::xsString->name(m_namePool) ||
       
  1707         typeName == BuiltinTypes::xsBoolean->name(m_namePool) ||
       
  1708         typeName == BuiltinTypes::xsFloat->name(m_namePool) ||
       
  1709         typeName == BuiltinTypes::xsDouble->name(m_namePool) ||
       
  1710         typeName == BuiltinTypes::xsDecimal->name(m_namePool) ||
       
  1711         typeName == BuiltinTypes::xsDuration->name(m_namePool) ||
       
  1712         typeName == BuiltinTypes::xsDateTime->name(m_namePool) ||
       
  1713         typeName == BuiltinTypes::xsTime->name(m_namePool) ||
       
  1714         typeName == BuiltinTypes::xsDate->name(m_namePool) ||
       
  1715         typeName == BuiltinTypes::xsGYearMonth->name(m_namePool) ||
       
  1716         typeName == BuiltinTypes::xsGYear->name(m_namePool) ||
       
  1717         typeName == BuiltinTypes::xsGMonthDay->name(m_namePool) ||
       
  1718         typeName == BuiltinTypes::xsGDay->name(m_namePool) ||
       
  1719         typeName == BuiltinTypes::xsGMonth->name(m_namePool) ||
       
  1720         typeName == BuiltinTypes::xsHexBinary->name(m_namePool) ||
       
  1721         typeName == BuiltinTypes::xsBase64Binary->name(m_namePool) ||
       
  1722         typeName == BuiltinTypes::xsAnyURI->name(m_namePool) ||
       
  1723         typeName == BuiltinTypes::xsQName->name(m_namePool) ||
       
  1724         typeName == BuiltinTypes::xsNOTATION->name(m_namePool) ||
       
  1725         typeName == BuiltinTypes::xsAnySimpleType->name(m_namePool))
       
  1726         return type;
       
  1727     else {
       
  1728         if (type->wxsSuperType())
       
  1729             return findPrimitiveType(type->wxsSuperType(), visitedTypes);
       
  1730         else {
       
  1731             return AnySimpleType::Ptr();
       
  1732         }
       
  1733     }
       
  1734 }
       
  1735 
       
  1736 QT_END_NAMESPACE