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 | // |
41 | // W A R N I N G |
42 | // ------------- |
43 | // |
44 | // This file is not part of the Qt API. It exists purely as an |
45 | // implementation detail. This header file may change from version to |
46 | // version without notice, or even be removed. |
47 | // |
48 | // We mean it. |
49 | |
50 | #ifndef Patternist_XsdSchemaResolver_H |
51 | #define Patternist_XsdSchemaResolver_H |
52 | |
53 | #include <private/qnamespacesupport_p.h> |
54 | #include <private/qschematype_p.h> |
55 | #include <private/qschematypefactory_p.h> |
56 | #include <private/qxsdalternative_p.h> |
57 | #include <private/qxsdattribute_p.h> |
58 | #include <private/qxsdattributegroup_p.h> |
59 | #include <private/qxsdelement_p.h> |
60 | #include <private/qxsdmodelgroup_p.h> |
61 | #include <private/qxsdnotation_p.h> |
62 | #include <private/qxsdreference_p.h> |
63 | #include <private/qxsdschema_p.h> |
64 | #include <private/qxsdschemachecker_p.h> |
65 | #include <private/qxsdsimpletype_p.h> |
66 | |
67 | #include <QtCore/QExplicitlySharedDataPointer> |
68 | |
69 | QT_BEGIN_NAMESPACE |
70 | |
71 | namespace QPatternist |
72 | { |
73 | class XsdSchemaContext; |
74 | class XsdSchemaParserContext; |
75 | |
76 | /** |
77 | * @short Encapsulates the resolving of type/element references in a schema after parsing has finished. |
78 | * |
79 | * This class collects task for resolving types or element references. After the parsing has finished, |
80 | * one can start the resolve process by calling resolve(). |
81 | * |
82 | * @ingroup Patternist_schema |
83 | * @author Tobias Koenig <tobias.koenig@nokia.com> |
84 | */ |
85 | class XsdSchemaResolver : public QSharedData |
86 | { |
87 | public: |
88 | typedef QExplicitlySharedDataPointer<XsdSchemaResolver> Ptr; |
89 | |
90 | /** |
91 | * Creates a new schema resolver. |
92 | * |
93 | * @param context The schema context used for error reporting etc.. |
94 | * @param parserContext The schema parser context where all objects to resolve belong to. |
95 | */ |
96 | XsdSchemaResolver(const QExplicitlySharedDataPointer<XsdSchemaContext> &context, const XsdSchemaParserContext *parserContext); |
97 | |
98 | /** |
99 | * Destroys the schema resolver. |
100 | */ |
101 | ~XsdSchemaResolver(); |
102 | |
103 | /** |
104 | * Starts the resolve process. |
105 | */ |
106 | void resolve(); |
107 | |
108 | /** |
109 | * Adds a resolve task for key references. |
110 | * |
111 | * The resolver will try to set the referencedKey property of @p keyRef to the <em>key</em> or <em>unique</em> object |
112 | * of @p element that has the given @p name. |
113 | */ |
114 | void addKeyReference(const XsdElement::Ptr &element, const XsdIdentityConstraint::Ptr &keyRef, const QXmlName &name, const QSourceLocation &location); |
115 | |
116 | /** |
117 | * Adds a resolve task for the base type of restriction of a simple type. |
118 | * |
119 | * The resolver will set the base type of @p simpleType to the type named by @p baseName. |
120 | */ |
121 | void addSimpleRestrictionBase(const XsdSimpleType::Ptr &simpleType, const QXmlName &baseName, const QSourceLocation &location); |
122 | |
123 | /** |
124 | * Removes the resolve task for the base type of restriction of the simple @p type. |
125 | */ |
126 | void removeSimpleRestrictionBase(const XsdSimpleType::Ptr &type); |
127 | |
128 | /** |
129 | * Adds a resolve task for the list type of a simple type. |
130 | * |
131 | * The resolver will set the itemType property of @p simpleType to the type named by @p typeName. |
132 | */ |
133 | void addSimpleListType(const XsdSimpleType::Ptr &simpleType, const QXmlName &typeName, const QSourceLocation &location); |
134 | |
135 | /** |
136 | * Adds a resolve task for the member types of a simple type. |
137 | * |
138 | * The resolver will set the memberTypes property of @p simpleType to the types named by @p typeNames. |
139 | */ |
140 | void addSimpleUnionTypes(const XsdSimpleType::Ptr &simpleType, const QList<QXmlName> &typeNames, const QSourceLocation &location); |
141 | |
142 | /** |
143 | * Adds a resolve task for the type of an element. |
144 | * |
145 | * The resolver will set the type of the @p element to the type named by @p typeName. |
146 | */ |
147 | void addElementType(const XsdElement::Ptr &element, const QXmlName &typeName, const QSourceLocation &location); |
148 | |
149 | /** |
150 | * Adds a resolve task for the base type of a complex type. |
151 | * |
152 | * The resolver will set the base type of @p complexType to the type named by @p baseName. |
153 | */ |
154 | void addComplexBaseType(const XsdComplexType::Ptr &complexType, const QXmlName &baseName, const QSourceLocation &location, const XsdFacet::Hash &facets = XsdFacet::Hash()); |
155 | |
156 | /** |
157 | * Removes the resolve task for the base type of the complex @p type. |
158 | */ |
159 | void removeComplexBaseType(const XsdComplexType::Ptr &type); |
160 | |
161 | /** |
162 | * Adds a resolve task for the content type of a complex type. |
163 | * |
164 | * The resolver will set the content type properties for @p complexType based on the |
165 | * given explicit @p content and effective @p mixed value. |
166 | */ |
167 | void addComplexContentType(const XsdComplexType::Ptr &complexType, const XsdParticle::Ptr &content, bool mixed); |
168 | |
169 | /** |
170 | * Adds a resolve task for the type of an attribute. |
171 | * |
172 | * The resolver will set the type of the @p attribute to the type named by @p typeName. |
173 | */ |
174 | void addAttributeType(const XsdAttribute::Ptr &attribute, const QXmlName &typeName, const QSourceLocation &location); |
175 | |
176 | /** |
177 | * Adds a resolve task for the type of an alternative. |
178 | * |
179 | * The resolver will set the type of the @p alternative to the type named by @p typeName. |
180 | */ |
181 | void addAlternativeType(const XsdAlternative::Ptr &alternative, const QXmlName &typeName, const QSourceLocation &location); |
182 | |
183 | /** |
184 | * Adds a resolve task for the type of an alternative. |
185 | * |
186 | * The resolver will set the type of the @p alternative to the type of the @p element after |
187 | * the type of the @p element has been resolved. |
188 | */ |
189 | void addAlternativeType(const XsdAlternative::Ptr &alternative, const XsdElement::Ptr &element); |
190 | |
191 | /** |
192 | * Adds a resolve task for the substituion group affiliations of an element. |
193 | * |
194 | * The resolver will set the substitution group affiliations of the @p element to the |
195 | * top-level element named by @p elementNames. |
196 | */ |
197 | void addSubstitutionGroupAffiliation(const XsdElement::Ptr &element, const QList<QXmlName> &elementName, const QSourceLocation &location); |
198 | |
199 | /** |
200 | * Adds a resolve task for an element that has no type specified, only a substitution group |
201 | * affiliation. |
202 | * |
203 | * The resolver will set the type of the substitution group affiliation as type for the element. |
204 | */ |
205 | void addSubstitutionGroupType(const XsdElement::Ptr &element); |
206 | |
207 | /** |
208 | * Adds the component location hash, so the resolver is able to report meaning full |
209 | * error messages. |
210 | */ |
211 | void addComponentLocationHash(const QHash<NamedSchemaComponent::Ptr, QSourceLocation> &hash); |
212 | |
213 | /** |
214 | * Add a resolve task for enumeration facet values. |
215 | * |
216 | * In case the enumeration is of type QName or NOTATION, we have to resolve the QName later, |
217 | * so we store the namespace bindings together with the facet value here and resolve it as soon as |
218 | * we have all type information available. |
219 | */ |
220 | void addEnumerationFacetValue(const AtomicValue::Ptr &facetValue, const NamespaceSupport &namespaceSupport); |
221 | |
222 | /** |
223 | * Add a check job for redefined groups. |
224 | * |
225 | * When an element group is redefined, we have to check whether the redefined group is a valid |
226 | * restriction of the group it redefines. As we need all type information for that, we keep them |
227 | * here for later checking. |
228 | */ |
229 | void addRedefinedGroups(const XsdModelGroup::Ptr &redefinedGroup, const XsdModelGroup::Ptr &group); |
230 | |
231 | /** |
232 | * Add a check job for redefined attribute groups. |
233 | * |
234 | * When an attribute group is redefined, we have to check whether the redefined group is a valid |
235 | * restriction of the group it redefines. As we need all type information for that, we keep them |
236 | * here for later checking. |
237 | */ |
238 | void addRedefinedAttributeGroups(const XsdAttributeGroup::Ptr &redefinedGroup, const XsdAttributeGroup::Ptr &group); |
239 | |
240 | /** |
241 | * Adds a check for nested <em>all</em> groups. |
242 | */ |
243 | void addAllGroupCheck(const XsdReference::Ptr &reference); |
244 | |
245 | /** |
246 | * Copies the data to resolve to an @p other resolver. |
247 | * |
248 | * @note That functionality is only used by the redefine algorithm in the XsdSchemaParser. |
249 | */ |
250 | void copyDataTo(const XsdSchemaResolver::Ptr &other) const; |
251 | |
252 | /** |
253 | * Returns the to resolve base type name for the given @p type. |
254 | * |
255 | * @note That functionality is only used by the redefine algorithm in the XsdSchemaParser. |
256 | */ |
257 | QXmlName baseTypeNameOfType(const SchemaType::Ptr &type) const; |
258 | |
259 | /** |
260 | * Returns the to resolve type name for the given @p attribute. |
261 | * |
262 | * @note That functionality is only used by the redefine algorithm in the XsdSchemaParser. |
263 | */ |
264 | QXmlName typeNameOfAttribute(const XsdAttribute::Ptr &attribute) const; |
265 | |
266 | /** |
267 | * Sets the defaultOpenContent object from the schema parser. |
268 | */ |
269 | void setDefaultOpenContent(const XsdComplexType::OpenContent::Ptr &openContent, bool appliesToEmpty); |
270 | |
271 | private: |
272 | /** |
273 | * Resolves key references. |
274 | */ |
275 | void resolveKeyReferences(); |
276 | |
277 | /** |
278 | * Resolves the base types of simple types derived by restriction. |
279 | */ |
280 | void resolveSimpleRestrictionBaseTypes(); |
281 | |
282 | /** |
283 | * Resolves the other properties except the base type |
284 | * of all simple restrictions. |
285 | */ |
286 | void resolveSimpleRestrictions(); |
287 | |
288 | /** |
289 | * Resolves the other properties except the base type |
290 | * of the given simple restriction. |
291 | * |
292 | * @param simpleType The restricted type to resolve. |
293 | * @param visitedTypes A set of already resolved types, used for termination of recursion. |
294 | */ |
295 | void resolveSimpleRestrictions(const XsdSimpleType::Ptr &simpleType, QSet<XsdSimpleType::Ptr> &visitedTypes); |
296 | |
297 | /** |
298 | * Resolves the item type property of simple types derived by list. |
299 | */ |
300 | void resolveSimpleListType(); |
301 | |
302 | /** |
303 | * Resolves the member types property of simple types derived by union. |
304 | */ |
305 | void resolveSimpleUnionTypes(); |
306 | |
307 | /** |
308 | * Resolves element types. |
309 | */ |
310 | void resolveElementTypes(); |
311 | |
312 | /** |
313 | * Resolves base type of complex types. |
314 | */ |
315 | void resolveComplexBaseTypes(); |
316 | |
317 | /** |
318 | * Resolves the simple content model of a complex type |
319 | * depending on its base type. |
320 | */ |
321 | void resolveSimpleContentComplexTypes(); |
322 | |
323 | /** |
324 | * Resolves the complex content model of a complex type |
325 | * depending on its base type. |
326 | */ |
327 | void resolveComplexContentComplexTypes(); |
328 | |
329 | /** |
330 | * Resolves the simple content model of a complex type |
331 | * depending on its base type. |
332 | * |
333 | * @param complexType The complex type to resolve. |
334 | * @param visitedTypes A set of already resolved types, used for termination of recursion. |
335 | */ |
336 | void resolveSimpleContentComplexTypes(const XsdComplexType::Ptr &complexType, QSet<XsdComplexType::Ptr> &visitedTypes); |
337 | |
338 | /** |
339 | * Resolves the complex content model of a complex type |
340 | * depending on its base type. |
341 | * |
342 | * @param complexType The complex type to resolve. |
343 | * @param visitedTypes A set of already resolved types, used for termination of recursion. |
344 | */ |
345 | void resolveComplexContentComplexTypes(const XsdComplexType::Ptr &complexType, QSet<XsdComplexType::Ptr> &visitedTypes); |
346 | |
347 | /** |
348 | * Resolves attribute types. |
349 | */ |
350 | void resolveAttributeTypes(); |
351 | |
352 | /** |
353 | * Resolves alternative types. |
354 | */ |
355 | void resolveAlternativeTypes(); |
356 | |
357 | /** |
358 | * Resolves substitution group affiliations. |
359 | */ |
360 | void resolveSubstitutionGroupAffiliations(); |
361 | |
362 | /** |
363 | * Resolves substitution groups. |
364 | */ |
365 | void resolveSubstitutionGroups(); |
366 | |
367 | /** |
368 | * Resolves all XsdReferences in the schema by their corresponding XsdElement or XsdModelGroup terms. |
369 | */ |
370 | void resolveTermReferences(); |
371 | |
372 | /** |
373 | * Resolves all XsdReferences in the @p particle recursive by their corresponding XsdElement or XsdModelGroup terms. |
374 | */ |
375 | void resolveTermReference(const XsdParticle::Ptr &particle, QSet<QXmlName> visitedGroups); |
376 | |
377 | /** |
378 | * Resolves all XsdAttributeReferences in the schema by their corresponding XsdAttributeUse objects. |
379 | */ |
380 | void resolveAttributeTermReferences(); |
381 | |
382 | /** |
383 | * Resolves all XsdAttributeReferences in the list of @p attributeUses by their corresponding XsdAttributeUse objects. |
384 | */ |
385 | XsdAttributeUse::List resolveAttributeTermReferences(const XsdAttributeUse::List &attributeUses, XsdWildcard::Ptr &wildcard, QSet<QXmlName> visitedAttributeGroups); |
386 | |
387 | /** |
388 | * Resolves the attribute inheritance of complex types. |
389 | * |
390 | * @note This method must be called after all base types have been resolved. |
391 | */ |
392 | void resolveAttributeInheritance(); |
393 | |
394 | /** |
395 | * Resolves the attribute inheritance of the given complex types. |
396 | * |
397 | * @param complexType The complex type to resolve. |
398 | * @param visitedTypes A set of already resolved types, used for termination of recursion. |
399 | * |
400 | * @note This method must be called after all base types have been resolved. |
401 | */ |
402 | void resolveAttributeInheritance(const XsdComplexType::Ptr &complexType, QSet<XsdComplexType::Ptr> &visitedTypes); |
403 | |
404 | /** |
405 | * Resolves the enumeration facet values for QName and NOTATION based facets. |
406 | */ |
407 | void resolveEnumerationFacetValues(); |
408 | |
409 | /** |
410 | * Returns the source location of the given schema @p component or a dummy |
411 | * source location if the component is not found in the component location hash. |
412 | */ |
413 | QSourceLocation sourceLocation(const NamedSchemaComponent::Ptr component) const; |
414 | |
415 | /** |
416 | * Returns the facets that are marked for the given complex @p type with a simple |
417 | * type restriction. |
418 | */ |
419 | XsdFacet::Hash complexTypeFacets(const XsdComplexType::Ptr &complexType) const; |
420 | |
421 | /** |
422 | * Finds the primitive type for the given simple @p type. |
423 | * |
424 | * The type is found by walking up the inheritance tree, until one of the builtin |
425 | * primitive type definitions is reached. |
426 | */ |
427 | AnySimpleType::Ptr findPrimitiveType(const AnySimpleType::Ptr &type, QSet<AnySimpleType::Ptr> &visitedTypes); |
428 | |
429 | /** |
430 | * Checks the redefined groups. |
431 | */ |
432 | void checkRedefinedGroups(); |
433 | |
434 | /** |
435 | * Checks the redefined attribute groups. |
436 | */ |
437 | void checkRedefinedAttributeGroups(); |
438 | |
439 | class KeyReference |
440 | { |
441 | public: |
442 | XsdElement::Ptr element; |
443 | XsdIdentityConstraint::Ptr keyRef; |
444 | QXmlName reference; |
445 | QSourceLocation location; |
446 | }; |
447 | |
448 | class SimpleRestrictionBase |
449 | { |
450 | public: |
451 | XsdSimpleType::Ptr simpleType; |
452 | QXmlName baseName; |
453 | QSourceLocation location; |
454 | }; |
455 | |
456 | class SimpleListType |
457 | { |
458 | public: |
459 | XsdSimpleType::Ptr simpleType; |
460 | QXmlName typeName; |
461 | QSourceLocation location; |
462 | }; |
463 | |
464 | class SimpleUnionType |
465 | { |
466 | public: |
467 | XsdSimpleType::Ptr simpleType; |
468 | QList<QXmlName> typeNames; |
469 | QSourceLocation location; |
470 | }; |
471 | |
472 | class ElementType |
473 | { |
474 | public: |
475 | XsdElement::Ptr element; |
476 | QXmlName typeName; |
477 | QSourceLocation location; |
478 | }; |
479 | |
480 | class ComplexBaseType |
481 | { |
482 | public: |
483 | XsdComplexType::Ptr complexType; |
484 | QXmlName baseName; |
485 | QSourceLocation location; |
486 | XsdFacet::Hash facets; |
487 | }; |
488 | |
489 | class ComplexContentType |
490 | { |
491 | public: |
492 | XsdComplexType::Ptr complexType; |
493 | XsdParticle::Ptr explicitContent; |
494 | bool effectiveMixed; |
495 | }; |
496 | |
497 | class AttributeType |
498 | { |
499 | public: |
500 | XsdAttribute::Ptr attribute; |
501 | QXmlName typeName; |
502 | QSourceLocation location; |
503 | }; |
504 | |
505 | class AlternativeType |
506 | { |
507 | public: |
508 | XsdAlternative::Ptr alternative; |
509 | QXmlName typeName; |
510 | QSourceLocation location; |
511 | }; |
512 | |
513 | class AlternativeTypeElement |
514 | { |
515 | public: |
516 | XsdAlternative::Ptr alternative; |
517 | XsdElement::Ptr element; |
518 | }; |
519 | |
520 | class SubstitutionGroupAffiliation |
521 | { |
522 | public: |
523 | XsdElement::Ptr element; |
524 | QList<QXmlName> elementNames; |
525 | QSourceLocation location; |
526 | }; |
527 | |
528 | class RedefinedGroups |
529 | { |
530 | public: |
531 | XsdModelGroup::Ptr redefinedGroup; |
532 | XsdModelGroup::Ptr group; |
533 | }; |
534 | |
535 | class RedefinedAttributeGroups |
536 | { |
537 | public: |
538 | XsdAttributeGroup::Ptr redefinedGroup; |
539 | XsdAttributeGroup::Ptr group; |
540 | }; |
541 | |
542 | QVector<KeyReference> m_keyReferences; |
543 | QVector<SimpleRestrictionBase> m_simpleRestrictionBases; |
544 | QVector<SimpleListType> m_simpleListTypes; |
545 | QVector<SimpleUnionType> m_simpleUnionTypes; |
546 | QVector<ElementType> m_elementTypes; |
547 | QVector<ComplexBaseType> m_complexBaseTypes; |
548 | QVector<ComplexContentType> m_complexContentTypes; |
549 | QVector<AttributeType> m_attributeTypes; |
550 | QVector<AlternativeType> m_alternativeTypes; |
551 | QVector<AlternativeTypeElement> m_alternativeTypeElements; |
552 | QVector<SubstitutionGroupAffiliation> m_substitutionGroupAffiliations; |
553 | QVector<XsdElement::Ptr> m_substitutionGroupTypes; |
554 | QVector<RedefinedGroups> m_redefinedGroups; |
555 | QVector<RedefinedAttributeGroups> m_redefinedAttributeGroups; |
556 | QHash<AtomicValue::Ptr, NamespaceSupport> m_enumerationFacetValues; |
557 | QSet<XsdReference::Ptr> m_allGroups; |
558 | |
559 | QExplicitlySharedDataPointer<XsdSchemaContext> m_context; |
560 | QExplicitlySharedDataPointer<XsdSchemaChecker> m_checker; |
561 | NamePool::Ptr m_namePool; |
562 | XsdSchema::Ptr m_schema; |
563 | QHash<NamedSchemaComponent::Ptr, QSourceLocation> m_componentLocationHash; |
564 | XsdComplexType::OpenContent::Ptr m_defaultOpenContent; |
565 | bool m_defaultOpenContentAppliesToEmpty; |
566 | SchemaType::List m_predefinedSchemaTypes; |
567 | }; |
568 | } |
569 | |
570 | QT_END_NAMESPACE |
571 | |
572 | #endif |
573 | |