source: trunk/src/xmlpatterns/schema/qxsdschemaresolver.cpp@ 728

Last change on this file since 728 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

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