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