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