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
53QT_BEGIN_NAMESPACE
54
55using namespace QPatternist;
56
57XsdSchemaResolver::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(asize: 20);
64 m_simpleRestrictionBases.reserve(asize: 20);
65 m_simpleListTypes.reserve(asize: 20);
66 m_simpleUnionTypes.reserve(asize: 20);
67 m_elementTypes.reserve(asize: 20);
68 m_complexBaseTypes.reserve(asize: 20);
69 m_attributeTypes.reserve(asize: 20);
70 m_alternativeTypes.reserve(asize: 20);
71 m_alternativeTypeElements.reserve(asize: 20);
72 m_substitutionGroupAffiliations.reserve(asize: 20);
73
74 m_predefinedSchemaTypes = m_context->schemaTypeFactory()->types().values();
75}
76
77XsdSchemaResolver::~XsdSchemaResolver()
78{
79}
80
81void XsdSchemaResolver::resolve()
82{
83 m_checker->addComponentLocationHash(hash: 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(hash: m_componentLocationHash);
126
127 m_checker->check();
128}
129
130void 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(t: item);
139}
140
141void 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(t: item);
149}
150
151void 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
161void 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(t: item);
169}
170
171void 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(t: item);
179}
180
181void 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(t: item);
189}
190
191void 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(t: item);
200}
201
202void 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
212void 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(t: item);
219}
220
221void 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(t: item);
229}
230
231void 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(t: item);
239}
240
241void 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(t: item);
248}
249
250void 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(t: item);
258}
259
260void XsdSchemaResolver::addSubstitutionGroupType(const XsdElement::Ptr &element)
261{
262 m_substitutionGroupTypes.append(t: element);
263}
264
265void XsdSchemaResolver::addComponentLocationHash(const ComponentLocationHash &hash)
266{
267 m_componentLocationHash.insert(hash);
268}
269
270void XsdSchemaResolver::addEnumerationFacetValue(const AtomicValue::Ptr &facetValue, const NamespaceSupport &namespaceSupport)
271{
272 m_enumerationFacetValues.insert(akey: facetValue, avalue: namespaceSupport);
273}
274
275void 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(t: item);
282}
283
284void 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(t: item);
291}
292
293void XsdSchemaResolver::addAllGroupCheck(const XsdReference::Ptr &reference)
294{
295 m_allGroups.insert(value: reference);
296}
297
298void 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
314QXmlName 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
329QXmlName 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
339void XsdSchemaResolver::setDefaultOpenContent(const XsdComplexType::OpenContent::Ptr &openContent, bool appliesToEmpty)
340{
341 m_defaultOpenContent = openContent;
342 m_defaultOpenContentAppliesToEmpty = appliesToEmpty;
343}
344
345void 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(name: ref.reference);
351 if (!constraint) {
352 m_context->error(message: QtXmlPatterns::tr(sourceText: "%1 references unknown %2 or %3 element %4.")
353 .arg(a: formatKeyword(keyword: ref.keyRef->displayName(namePool: m_namePool)))
354 .arg(a: formatElement(element: "key"))
355 .arg(a: formatElement(element: "unique"))
356 .arg(a: formatKeyword(np: m_namePool, name: ref.reference)),
357 errorCode: XsdSchemaContext::XSDError, sourceLocation: 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(message: QtXmlPatterns::tr(sourceText: "%1 references identity constraint %2 that is no %3 or %4 element.")
363 .arg(a: formatKeyword(keyword: ref.keyRef->displayName(namePool: m_namePool)))
364 .arg(a: formatKeyword(np: m_namePool, name: ref.reference))
365 .arg(a: formatElement(element: "key"))
366 .arg(a: formatElement(element: "unique")),
367 errorCode: XsdSchemaContext::XSDError, sourceLocation: ref.location);
368 return;
369 }
370
371 if (constraint->fields().count() != ref.keyRef->fields().count()) {
372 m_context->error(message: QtXmlPatterns::tr(sourceText: "%1 has a different number of fields from the identity constraint %2 that it references.")
373 .arg(a: formatKeyword(keyword: ref.keyRef->displayName(namePool: m_namePool)))
374 .arg(a: formatKeyword(np: m_namePool, name: ref.reference)),
375 errorCode: XsdSchemaContext::XSDError, sourceLocation: ref.location);
376 return;
377 }
378
379 ref.keyRef->setReferencedKey(constraint);
380 }
381}
382
383void 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(name: item.baseName);
391 if (!type) {
392 // maybe it's a basic type...
393 type = m_context->schemaTypeFactory()->createSchemaType(name: item.baseName);
394 if (!type) {
395 m_context->error(message: QtXmlPatterns::tr(sourceText: "Base type %1 of %2 element cannot be resolved.")
396 .arg(a: formatType(np: m_namePool, name: item.baseName))
397 .arg(a: formatElement(element: "restriction")),
398 errorCode: XsdSchemaContext::XSDError, sourceLocation: item.location);
399 return;
400 }
401 }
402
403 item.simpleType->setWxsSuperType(type);
404 }
405}
406
407void 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(t: 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(t: anonymousTypes.at(i));
423 }
424
425 QSet<XsdSimpleType::Ptr> visitedTypes;
426 for (int i = 0; i < simpleTypes.count(); ++i) {
427 resolveSimpleRestrictions(simpleType: simpleTypes.at(i), visitedTypes);
428 }
429}
430
431void XsdSchemaResolver::resolveSimpleRestrictions(const XsdSimpleType::Ptr &simpleType, QSet<XsdSimpleType::Ptr> &visitedTypes)
432{
433 if (visitedTypes.contains(value: simpleType))
434 return;
435 else
436 visitedTypes.insert(value: 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(t: simpleType))
444 return;
445
446 const SchemaType::Ptr baseType = simpleType->wxsSuperType();
447 Q_ASSERT(baseType);
448
449 if (baseType->isDefinedBySchema())
450 resolveSimpleRestrictions(simpleType: 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(type: baseType, visitedTypes&: 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
467void 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(name: item.typeName);
475 if (!type) {
476 // maybe it's a basic type...
477 type = m_context->schemaTypeFactory()->createSchemaType(name: item.typeName);
478 if (!type) {
479 m_context->error(message: QtXmlPatterns::tr(sourceText: "Item type %1 of %2 element cannot be resolved.")
480 .arg(a: formatType(np: m_namePool, name: item.typeName))
481 .arg(a: formatElement(element: "list")),
482 errorCode: XsdSchemaContext::XSDError, sourceLocation: item.location);
483 return;
484 }
485 }
486
487 item.simpleType->setItemType(type);
488 }
489}
490
491void 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(i: j);
503
504 // try to resolve the name
505 SchemaType::Ptr type = m_schema->type(name: typeName);
506 if (!type) {
507 // maybe it's a basic type...
508 type = m_context->schemaTypeFactory()->createSchemaType(name: typeName);
509 if (!type) {
510 m_context->error(message: QtXmlPatterns::tr(sourceText: "Member type %1 of %2 element cannot be resolved.")
511 .arg(a: formatType(np: m_namePool, name: typeName))
512 .arg(a: formatElement(element: "union")),
513 errorCode: XsdSchemaContext::XSDError, sourceLocation: item.location);
514 return;
515 }
516 }
517
518 memberTypes.append(t: 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
528void 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(name: item.typeName);
534 if (!type) {
535 // maybe it's a basic type...
536 type = m_context->schemaTypeFactory()->createSchemaType(name: item.typeName);
537 if (!type) {
538 m_context->error(message: QtXmlPatterns::tr(sourceText: "Type %1 of %2 element cannot be resolved.")
539 .arg(a: formatType(np: m_namePool, name: item.typeName))
540 .arg(a: formatElement(element: "element")),
541 errorCode: XsdSchemaContext::XSDError, sourceLocation: item.location);
542 return;
543 }
544 }
545
546 item.element->setType(type);
547 }
548}
549
550void 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(name: item.baseName);
556 if (!type) {
557 // maybe it's a basic type...
558 type = m_context->schemaTypeFactory()->createSchemaType(name: item.baseName);
559 if (!type) {
560 m_context->error(message: QtXmlPatterns::tr(sourceText: "Base type %1 of complex type cannot be resolved.").arg(a: formatType(np: m_namePool, name: item.baseName)), errorCode: XsdSchemaContext::XSDError, sourceLocation: 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(message: QtXmlPatterns::tr(sourceText: "%1 cannot have complex base type that has a %2.")
570 .arg(a: formatElement(element: "simpleContent"))
571 .arg(a: formatElement(element: "complexContent")),
572 errorCode: XsdSchemaContext::XSDError, sourceLocation: item.location);
573 return;
574 }
575 }
576 }
577
578 item.complexType->setWxsSuperType(type);
579 }
580}
581
582void 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(t: 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(t: 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(complexType: complexTypes.at(i), visitedTypes);
604 }
605}
606
607void XsdSchemaResolver::resolveSimpleContentComplexTypes(const XsdComplexType::Ptr &complexType, QSet<XsdComplexType::Ptr> &visitedTypes)
608{
609 if (visitedTypes.contains(value: complexType))
610 return;
611 else
612 visitedTypes.insert(value: 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(complexType: 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(type: anonType->wxsSuperType(), visitedTypes&: visitedPrimitiveTypes);
647 anonType->setPrimitiveType(primitiveType);
648
649 complexType->contentType()->setSimpleType(anonType);
650
651 m_schema->addAnonymousType(type: anonType);
652 m_componentLocationHash.insert(akey: anonType, avalue: m_componentLocationHash.value(akey: 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(particle: 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(type: anonType->wxsSuperType(), visitedTypes&: visitedPrimitiveTypes);
670 anonType->setPrimitiveType(primitiveType);
671
672 complexType->contentType()->setSimpleType(anonType);
673
674 m_schema->addAnonymousType(type: anonType);
675 m_componentLocationHash.insert(akey: anonType, avalue: m_componentLocationHash.value(akey: 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
686void 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(t: 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(t: 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(complexType: complexTypes.at(i), visitedTypes);
708 }
709}
710
711void XsdSchemaResolver::resolveComplexContentComplexTypes(const XsdComplexType::Ptr &complexType, QSet<XsdComplexType::Ptr> &visitedTypes)
712{
713 if (visitedTypes.contains(value: complexType))
714 return;
715 else
716 visitedTypes.insert(value: 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(complexType: 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(t: 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(message: QtXmlPatterns::tr(sourceText: "Content model of complex type %1 contains %2 element so it cannot be derived by extension from a non-empty type.")
856 .arg(a: formatType(np: m_namePool, type: complexType)).arg(a: formatKeyword(keyword: "all")), errorCode: XsdSchemaContext::XSDError, sourceLocation: sourceLocation(component: complexType));
857 return;
858 }
859
860 if (baseParticle && baseParticle->term()->isModelGroup() && XsdModelGroup::Ptr(baseParticle->term())->compositor() == XsdModelGroup::AllCompositor) {
861 m_context->error(message: QtXmlPatterns::tr(sourceText: "Complex type %1 cannot be derived by extension from %2 as the latter contains %3 element in its content model.")
862 .arg(a: formatType(np: m_namePool, type: complexType))
863 .arg(a: formatType(np: m_namePool, type: baseType))
864 .arg(a: formatKeyword(keyword: "all")), errorCode: XsdSchemaContext::XSDError, sourceLocation: sourceLocation(component: 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
943void 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(name: item.typeName);
949 if (!type) {
950 // maybe it's a basic type...
951 type = m_context->schemaTypeFactory()->createSchemaType(name: item.typeName);
952 if (!type) {
953 m_context->error(message: QtXmlPatterns::tr(sourceText: "Type %1 of %2 element cannot be resolved.")
954 .arg(a: formatType(np: m_namePool, name: item.typeName))
955 .arg(a: formatElement(element: "attribute")),
956 errorCode: XsdSchemaContext::XSDError, sourceLocation: item.location);
957 return;
958 }
959 }
960
961 if (!type->isSimpleType() && type->category() != SchemaType::None) {
962 m_context->error(message: QtXmlPatterns::tr(sourceText: "Type of %1 element must be a simple type, %2 is not.")
963 .arg(a: formatElement(element: "attribute"))
964 .arg(a: formatType(np: m_namePool, name: item.typeName)),
965 errorCode: XsdSchemaContext::XSDError, sourceLocation: item.location);
966 return;
967 }
968
969 item.attribute->setType(type);
970 }
971}
972
973void 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(name: item.typeName);
979 if (!type) {
980 // maybe it's a basic type...
981 type = m_context->schemaTypeFactory()->createSchemaType(name: item.typeName);
982 if (!type) {
983 m_context->error(message: QtXmlPatterns::tr(sourceText: "Type %1 of %2 element cannot be resolved.")
984 .arg(a: formatType(np: m_namePool, name: item.typeName))
985 .arg(a: formatElement(element: "alternative")),
986 errorCode: XsdSchemaContext::XSDError, sourceLocation: 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
1000bool 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(current: elements.at(i), head, namePool))
1008 return true;
1009 }
1010 }
1011
1012 return false;
1013}
1014
1015void 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(name: item.elementNames.at(i: j));
1023 if (!element) {
1024 m_context->error(message: QtXmlPatterns::tr(sourceText: "Substitution group %1 of %2 element cannot be resolved.")
1025 .arg(a: formatKeyword(np: m_namePool, name: item.elementNames.at(i: j)))
1026 .arg(a: formatElement(element: "element")),
1027 errorCode: XsdSchemaContext::XSDError, sourceLocation: item.location);
1028 return;
1029 }
1030
1031 // @see http://www.w3.org/TR/xmlschema11-1/#e-props-correct 5)
1032 if (hasCircularSubstitutionGroup(current: element, head: item.element, namePool: m_namePool)) {
1033 m_context->error(message: QtXmlPatterns::tr(sourceText: "Substitution group %1 has circular definition.").arg(a: formatKeyword(np: m_namePool, name: item.elementNames.at(i: j))), errorCode: XsdSchemaContext::XSDError, sourceLocation: item.location);
1034 return;
1035 }
1036
1037 affiliations.append(t: 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
1049bool 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, element: affiliations.at(i), namePool))
1057 return true;
1058 }
1059
1060 return false;
1061}
1062
1063void 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(elements: element);
1071
1072 for (int j = 0; j < elements.count(); ++j) {
1073 if (i == j)
1074 continue;
1075
1076 if (isSubstGroupHeadOf(head: element, element: elements.at(i: j), namePool: m_namePool))
1077 element->addSubstitutionGroup(elements: elements.at(i: j));
1078 }
1079 }
1080}
1081
1082void 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(particle: complexType->contentType()->particle(), visitedGroups: 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(particle: complexType->contentType()->particle(), visitedGroups: 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, visitedGroups: QSet<QXmlName>());
1115 }
1116}
1117
1118void 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(particle: 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(i: 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(namePool: m_namePool) == otherElement->name(namePool: m_namePool)) {
1152 if (modelGroup->compositor() == XsdModelGroup::AllCompositor) {
1153 m_context->error(message: QtXmlPatterns::tr(sourceText: "Duplicated element names %1 in %2 element.")
1154 .arg(a: formatKeyword(keyword: element->displayName(namePool: m_namePool)))
1155 .arg(a: formatElement(element: "all")),
1156 errorCode: XsdSchemaContext::XSDError, sourceLocation: sourceLocation(component: modelGroup));
1157 return;
1158 } else if (modelGroup->compositor() == XsdModelGroup::SequenceCompositor) {
1159 if (element->type() != otherElement->type()) { // not same variety
1160 m_context->error(message: QtXmlPatterns::tr(sourceText: "Duplicated element names %1 in %2 element.")
1161 .arg(a: formatKeyword(keyword: element->displayName(namePool: m_namePool)))
1162 .arg(a: formatElement(element: "sequence")),
1163 errorCode: XsdSchemaContext::XSDError, sourceLocation: sourceLocation(component: 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(name: reference->referenceName());
1186 if (element) {
1187 particle->setTerm(element);
1188 } else {
1189 m_context->error(message: QtXmlPatterns::tr(sourceText: "Reference %1 of %2 element cannot be resolved.")
1190 .arg(a: formatKeyword(np: m_namePool, name: reference->referenceName()))
1191 .arg(a: formatElement(element: "element")),
1192 errorCode: XsdSchemaContext::XSDError, sourceLocation: reference->sourceLocation());
1193 return;
1194 }
1195 }
1196 break;
1197 case XsdReference::ModelGroup:
1198 {
1199 const XsdModelGroup::Ptr modelGroup = m_schema->elementGroup(name: reference->referenceName());
1200 if (modelGroup) {
1201 if (visitedGroups.contains(value: modelGroup->name(namePool: m_namePool))) {
1202 m_context->error(message: QtXmlPatterns::tr(sourceText: "Circular group reference for %1.").arg(a: formatKeyword(keyword: modelGroup->displayName(namePool: m_namePool))),
1203 errorCode: XsdSchemaContext::XSDError, sourceLocation: reference->sourceLocation());
1204 } else {
1205 visitedGroups.insert(value: modelGroup->name(namePool: 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(particle: particles.at(i), visitedGroups);
1214 }
1215
1216 if (modelGroup->compositor() == XsdModelGroup::AllCompositor) {
1217 if (m_allGroups.contains(value: reference)) {
1218 m_context->error(message: QtXmlPatterns::tr(sourceText: "%1 element is not allowed in this scope").arg(a: formatElement(element: "all.")),
1219 errorCode: XsdSchemaContext::XSDError, sourceLocation: reference->sourceLocation());
1220 return;
1221 }
1222 if (particle->maximumOccursUnbounded() || particle->maximumOccurs() != 1) {
1223 m_context->error(message: QtXmlPatterns::tr(sourceText: "%1 element cannot have %2 attribute with value other than %3.")
1224 .arg(a: formatElement(element: "all"))
1225 .arg(a: formatAttribute(attribute: "maxOccurs"))
1226 .arg(a: formatData(data: "1")),
1227 errorCode: XsdSchemaContext::XSDError, sourceLocation: reference->sourceLocation());
1228 return;
1229 }
1230 if (particle->minimumOccurs() != 0 && particle->minimumOccurs() != 1) {
1231 m_context->error(message: QtXmlPatterns::tr(sourceText: "%1 element cannot have %2 attribute with value other than %3 or %4.")
1232 .arg(a: formatElement(element: "all"))
1233 .arg(a: formatAttribute(attribute: "minOccurs"))
1234 .arg(a: formatData(data: "0"))
1235 .arg(a: formatData(data: "1")),
1236 errorCode: XsdSchemaContext::XSDError, sourceLocation: reference->sourceLocation());
1237 return;
1238 }
1239 }
1240 } else {
1241 m_context->error(message: QtXmlPatterns::tr(sourceText: "Reference %1 of %2 element cannot be resolved.")
1242 .arg(a: formatKeyword(np: m_namePool, name: reference->referenceName()))
1243 .arg(a: formatElement(element: "group")),
1244 errorCode: XsdSchemaContext::XSDError, sourceLocation: reference->sourceLocation());
1245 return;
1246 }
1247 }
1248 break;
1249 }
1250}
1251
1252void 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(attributeUses: attributeGroups.at(i)->attributeUses(), wildcard, visitedAttributeGroups: 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, visitedAttributeGroups: 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, visitedAttributeGroups: QSet<QXmlName>());
1289 complexType->setAttributeUses(uses);
1290 complexType->setAttributeWildcard(wildcard);
1291 }
1292}
1293
1294XsdAttributeUse::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(t: 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(name: reference->referenceName());
1311 if (!attribute) {
1312 m_context->error(message: QtXmlPatterns::tr(sourceText: "Reference %1 of %2 element cannot be resolved.")
1313 .arg(a: formatKeyword(np: m_namePool, name: reference->referenceName()))
1314 .arg(a: formatElement(element: "attribute")),
1315 errorCode: XsdSchemaContext::XSDError, sourceLocation: 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(message: QtXmlPatterns::tr(sourceText: "%1 or %2 attribute of reference %3 does not match with the attribute declaration %4.")
1323 .arg(a: formatAttribute(attribute: "fixed"))
1324 .arg(a: formatAttribute(attribute: "default"))
1325 .arg(a: formatKeyword(np: m_namePool, name: reference->referenceName()))
1326 .arg(a: formatKeyword(keyword: attribute->displayName(namePool: m_namePool))),
1327 errorCode: XsdSchemaContext::XSDError, sourceLocation: 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(constraint: attribute->valueConstraint()));
1335
1336 resolvedAttributeUses.append(t: attributeUse);
1337 } else if (reference->type() == XsdAttributeReference::AttributeGroup) {
1338 const XsdAttributeGroup::Ptr attributeGroup = m_schema->attributeGroup(name: reference->referenceName());
1339 if (!attributeGroup) {
1340 m_context->error(message: QtXmlPatterns::tr(sourceText: "Reference %1 of %2 element cannot be resolved.")
1341 .arg(a: formatKeyword(np: m_namePool, name: reference->referenceName()))
1342 .arg(a: formatElement(element: "attributeGroup")),
1343 errorCode: XsdSchemaContext::XSDError, sourceLocation: reference->sourceLocation());
1344 return XsdAttributeUse::List();
1345 }
1346 if (visitedAttributeGroups.contains(value: attributeGroup->name(namePool: m_namePool))) {
1347 m_context->error(message: QtXmlPatterns::tr(sourceText: "Attribute group %1 has circular reference.").arg(a: formatKeyword(np: m_namePool, name: reference->referenceName())),
1348 errorCode: XsdSchemaContext::XSDError, sourceLocation: reference->sourceLocation());
1349 return XsdAttributeUse::List();
1350 } else {
1351 visitedAttributeGroups.insert(value: attributeGroup->name(namePool: 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(attributeUses: attributeGroup->attributeUses(), wildcard&: childWildcard, visitedAttributeGroups);
1357 if (!childWildcard) {
1358 if (attributeGroup->wildcard()) {
1359 if (wildcard) {
1360 const XsdWildcard::ProcessContents contents = wildcard->processContents();
1361 wildcard = XsdSchemaHelper::wildcardIntersection(wildcard, otherWildcard: 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(wildcard: attributeGroup->wildcard(), otherWildcard: 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, otherWildcard: newWildcard);
1380 wildcard->setProcessContents(contents);
1381 } else {
1382 wildcard = newWildcard;
1383 }
1384 }
1385 }
1386 }
1387 }
1388
1389 return resolvedAttributeUses;
1390}
1391
1392void 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
1409bool isValidWildcardRestriction(const XsdWildcard::Ptr &wildcard, const XsdWildcard::Ptr &baseWildcard)
1410{
1411 if (wildcard->namespaceConstraint()->variety() == baseWildcard->namespaceConstraint()->variety()) {
1412 if (!XsdSchemaHelper::checkWildcardProcessContents(baseWildcard, derivedWildcard: 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(other: 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(other: 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 */
1438void XsdSchemaResolver::resolveAttributeInheritance(const XsdComplexType::Ptr &complexType, QSet<XsdComplexType::Ptr> &visitedTypes)
1439{
1440 if (visitedTypes.contains(value: complexType))
1441 return;
1442 else
1443 visitedTypes.insert(value: 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(complexType: 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(i: j);
1471 bool found = false;
1472 for (int k = 0; k < currentUses.count(); ++k) {
1473 if (use->attribute()->name(namePool: m_namePool) == currentUses.at(i: k)->attribute()->name(namePool: m_namePool)) {
1474 found = true;
1475
1476 // check if prohibited usage is violated
1477 if ((use->useType() == XsdAttributeUse::ProhibitedUse) && (currentUses.at(i: k)->useType() != XsdAttributeUse::ProhibitedUse)) {
1478 m_context->error(message: QtXmlPatterns::tr(sourceText: "%1 attribute in %2 must have %3 use like in base type %4.")
1479 .arg(a: formatAttribute(attribute: use->attribute()->displayName(namePool: m_namePool)))
1480 .arg(a: formatType(np: m_namePool, type: complexType))
1481 .arg(a: formatData(data: "prohibited"))
1482 .arg(a: formatType(np: m_namePool, type: complexBaseType)),
1483 errorCode: XsdSchemaContext::XSDError, sourceLocation: sourceLocation(component: complexType));
1484 return;
1485 }
1486
1487 break;
1488 }
1489 }
1490
1491 if (!found && uses.at(i: j)->useType() != XsdAttributeUse::ProhibitedUse) {
1492 complexType->addAttributeUse(use: uses.at(i: 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(akey: attributeUses.at(i)->attribute()->name(namePool: m_namePool), avalue: 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(akey: currentAttributeUse->attribute()->name(namePool: m_namePool)))
1513 continue;
1514
1515 complexType->addAttributeUse(use: 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(wildcard: complexType->attributeWildcard(), baseWildcard: complexBaseType->attributeWildcard())) {
1530 m_context->error(message: QtXmlPatterns::tr(sourceText: "Attribute wildcard of %1 is not a valid restriction of attribute wildcard of base type %2.")
1531 .arg(a: formatType(np: m_namePool, type: complexType))
1532 .arg(a: formatType(np: m_namePool, type: complexBaseType)),
1533 errorCode: XsdSchemaContext::XSDError, sourceLocation: sourceLocation(component: complexType));
1534 return;
1535 }
1536 } else {
1537 m_context->error(message: QtXmlPatterns::tr(sourceText: "%1 has attribute wildcard but its base type %2 has not.")
1538 .arg(a: formatType(np: m_namePool, type: complexType))
1539 .arg(a: formatType(np: m_namePool, type: complexBaseType)),
1540 errorCode: XsdSchemaContext::XSDError, sourceLocation: sourceLocation(component: 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(wildcard: completeWildcard, otherWildcard: baseWildcard);
1559 if (unionWildcard) {
1560 unionWildcard->setProcessContents(completeWildcard->processContents());
1561 complexType->setAttributeWildcard(unionWildcard); // 2.2.2.3
1562 } else {
1563 m_context->error(message: QtXmlPatterns::tr(sourceText: "Union of attribute wildcard of type %1 and attribute wildcard of its base type %2 is not expressible.")
1564 .arg(a: formatType(np: m_namePool, type: complexType))
1565 .arg(a: formatType(np: m_namePool, type: complexBaseType)),
1566 errorCode: XsdSchemaContext::XSDError, sourceLocation: sourceLocation(component: complexType));
1567 return;
1568 }
1569 }
1570 }
1571}
1572
1573void 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(t: 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(t: 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(other: simpleType) ||
1596 BuiltinTypes::xsNOTATION->wxsTypeMatches(other: simpleType)) {
1597 const XsdFacet::Hash facets = simpleType->facets();
1598 if (facets.contains(akey: XsdFacet::Enumeration)) {
1599 AtomicValue::List newValues;
1600
1601 const XsdFacet::Ptr facet = facets.value(akey: 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(i: j);
1605
1606 Q_ASSERT(m_enumerationFacetValues.contains(value));
1607 const NamespaceSupport support( m_enumerationFacetValues.value(akey: value) );
1608
1609 const QString qualifiedName = value->as<DerivedString<TypeString> >()->stringValue();
1610 if (!XPathHelper::isQName(qName: qualifiedName)) {
1611 m_context->error(message: QtXmlPatterns::tr(sourceText: "Enumeration facet contains invalid content: {%1} is not a value of type %2.")
1612 .arg(a: formatData(data: qualifiedName))
1613 .arg(a: formatType(np: m_namePool, type: BuiltinTypes::xsQName)),
1614 errorCode: XsdSchemaContext::XSDError, sourceLocation: sourceLocation(component: simpleType));
1615 return;
1616 }
1617
1618 QXmlName qNameValue;
1619 bool result = support.processName(qualifiedName, type: NamespaceSupport::ElementName, name&: qNameValue);
1620 if (!result) {
1621 m_context->error(message: QtXmlPatterns::tr(sourceText: "Namespace prefix of qualified name %1 is not defined.").arg(a: formatData(data: qualifiedName)),
1622 errorCode: XsdSchemaContext::XSDError, sourceLocation: sourceLocation(component: simpleType));
1623 return;
1624 }
1625
1626 newValues.append(t: QNameValue::fromValue(np: m_namePool, name: qNameValue));
1627 }
1628 facet->setMultiValue(newValues);
1629 }
1630 }
1631 }
1632}
1633
1634QSourceLocation XsdSchemaResolver::sourceLocation(const NamedSchemaComponent::Ptr component) const
1635{
1636 if (m_componentLocationHash.contains(akey: component)) {
1637 return m_componentLocationHash.value(akey: component);
1638 } else {
1639 QSourceLocation location;
1640 location.setLine(1);
1641 location.setColumn(1);
1642 location.setUri(QString::fromLatin1(str: "dummyUri"));
1643
1644 return location;
1645 }
1646}
1647
1648XsdFacet::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
1658void 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, derivedParticle: redefinedParticle, context: m_context, errorMsg)) {
1672 m_context->error(message: QtXmlPatterns::tr(sourceText: "%1 element %2 is not a valid restriction of the %3 element it redefines: %4.")
1673 .arg(a: formatElement(element: "group"))
1674 .arg(a: formatData(data: item.redefinedGroup->displayName(namePool: m_namePool)))
1675 .arg(a: formatElement(element: "group"))
1676 .arg(a: errorMsg),
1677 errorCode: XsdSchemaContext::XSDError, sourceLocation: sourceLocation(component: item.redefinedGroup));
1678 return;
1679 }
1680 }
1681}
1682
1683void 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(derivedAttributeGroup: item.redefinedGroup, attributeGroup: item.group, context: m_context, errorMsg)) {
1690 m_context->error(message: QtXmlPatterns::tr(sourceText: "%1 element %2 is not a valid restriction of the %3 element it redefines: %4.")
1691 .arg(a: formatElement(element: "attributeGroup"))
1692 .arg(a: formatData(data: item.redefinedGroup->displayName(namePool: m_namePool)))
1693 .arg(a: formatElement(element: "attributeGroup"))
1694 .arg(a: errorMsg),
1695 errorCode: XsdSchemaContext::XSDError, sourceLocation: sourceLocation(component: item.redefinedGroup));
1696 return;
1697 }
1698 }
1699}
1700
1701AnySimpleType::Ptr XsdSchemaResolver::findPrimitiveType(const AnySimpleType::Ptr &type, QSet<AnySimpleType::Ptr> &visitedTypes)
1702{
1703 if (visitedTypes.contains(value: type)) {
1704 // found invalid circular reference...
1705 return AnySimpleType::Ptr();
1706 } else {
1707 visitedTypes.insert(value: type);
1708 }
1709
1710 const QXmlName typeName = type->name(np: m_namePool);
1711 if (typeName == BuiltinTypes::xsString->name(np: m_namePool) ||
1712 typeName == BuiltinTypes::xsBoolean->name(np: m_namePool) ||
1713 typeName == BuiltinTypes::xsFloat->name(np: m_namePool) ||
1714 typeName == BuiltinTypes::xsDouble->name(np: m_namePool) ||
1715 typeName == BuiltinTypes::xsDecimal->name(np: m_namePool) ||
1716 typeName == BuiltinTypes::xsDuration->name(np: m_namePool) ||
1717 typeName == BuiltinTypes::xsDateTime->name(np: m_namePool) ||
1718 typeName == BuiltinTypes::xsTime->name(np: m_namePool) ||
1719 typeName == BuiltinTypes::xsDate->name(np: m_namePool) ||
1720 typeName == BuiltinTypes::xsGYearMonth->name(np: m_namePool) ||
1721 typeName == BuiltinTypes::xsGYear->name(np: m_namePool) ||
1722 typeName == BuiltinTypes::xsGMonthDay->name(np: m_namePool) ||
1723 typeName == BuiltinTypes::xsGDay->name(np: m_namePool) ||
1724 typeName == BuiltinTypes::xsGMonth->name(np: m_namePool) ||
1725 typeName == BuiltinTypes::xsHexBinary->name(np: m_namePool) ||
1726 typeName == BuiltinTypes::xsBase64Binary->name(np: m_namePool) ||
1727 typeName == BuiltinTypes::xsAnyURI->name(np: m_namePool) ||
1728 typeName == BuiltinTypes::xsQName->name(np: m_namePool) ||
1729 typeName == BuiltinTypes::xsNOTATION->name(np: m_namePool) ||
1730 typeName == BuiltinTypes::xsAnySimpleType->name(np: m_namePool))
1731 return type;
1732 else {
1733 if (type->wxsSuperType())
1734 return findPrimitiveType(type: type->wxsSuperType(), visitedTypes);
1735 else {
1736 return AnySimpleType::Ptr();
1737 }
1738 }
1739}
1740
1741QT_END_NAMESPACE
1742

source code of qtxmlpatterns/src/xmlpatterns/schema/qxsdschemaresolver.cpp