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_XsdValidatingInstanceReader_H |
51 | #define Patternist_XsdValidatingInstanceReader_H |
52 | |
53 | #include <private/qxsdidchelper_p.h> |
54 | #include <private/qxsdinstancereader_p.h> |
55 | #include <private/qxsdstatemachine_p.h> |
56 | #include <private/qxsdvalidatedxmlnodemodel_p.h> |
57 | |
58 | #include <QtCore/QStack> |
59 | |
60 | QT_BEGIN_NAMESPACE |
61 | |
62 | class QXmlQuery; |
63 | |
64 | namespace QPatternist |
65 | { |
66 | /** |
67 | * @short The validating schema instance reader. |
68 | * |
69 | * This class reads in a xml instance document from a QAbstractXmlNodeModel and |
70 | * validates it against a given xml schema. |
71 | * |
72 | * @ingroup Patternist_schema |
73 | * @author Tobias Koenig <tobias.koenig@nokia.com> |
74 | */ |
75 | class XsdValidatingInstanceReader : public XsdInstanceReader |
76 | { |
77 | public: |
78 | typedef QExplicitlySharedDataPointer<XsdValidatingInstanceReader> Ptr; |
79 | |
80 | /** |
81 | * Creates a new validating instance reader that reads the data from |
82 | * the given @p model. |
83 | * |
84 | * @param model The model the data shall be read from. |
85 | * @param documentUri The uri of the document the model is from. |
86 | * @param context The context that is used to report errors etc. |
87 | */ |
88 | XsdValidatingInstanceReader(XsdValidatedXmlNodeModel *model, const QUrl &documentUri, const XsdSchemaContext::Ptr &context); |
89 | |
90 | /** |
91 | * Adds a new @p schema to the pool of schemas that shall be used |
92 | * for validation. |
93 | * The schema is located at the given @p url. |
94 | */ |
95 | void addSchema(const XsdSchema::Ptr &schema, const QUrl &url); |
96 | |
97 | /** |
98 | * Reads and validates the instance document. |
99 | */ |
100 | bool read(); |
101 | |
102 | private: |
103 | /** |
104 | * Loads a schema with the given @p targetNamespace from the given @p location |
105 | * and adds it to the pool of schemas that are used for validation. |
106 | * |
107 | * This method is used to load schemas defined in the xsi:schemaLocation or |
108 | * xsi:noNamespaceSchemaLocation attributes in the instance document. |
109 | */ |
110 | bool loadSchema(const QString &targetNamespace, const QUrl &location); |
111 | |
112 | /** |
113 | * Reports an error via the report context. |
114 | */ |
115 | void error(const QString &msg) const; |
116 | |
117 | /** |
118 | * Validates the current element tag of the instance document. |
119 | * |
120 | * @param hasStateMachine Used to remember whether this element represents the start tag |
121 | * of a complex type and therefore pushes a new state machine on the stack. |
122 | * @param element Used to remember which element has been validated in this step. |
123 | */ |
124 | bool validate(bool &hasStateMachine, XsdElement::Ptr &element); |
125 | |
126 | /** |
127 | * Validates the current tag of the instance document against the given element @p declaration. |
128 | * |
129 | * @param declaration The element declaration to validate against. |
130 | * @param hasStateMachine Used to remember whether this element represents the start tag |
131 | * of a complex type and therefore pushes a new state machine on the stack. |
132 | */ |
133 | bool validateElement(const XsdElement::Ptr &declaration, bool &hasStateMachine); |
134 | |
135 | /** |
136 | * Validates the current tag of the instance document against the given @p type of the element @p declaration. |
137 | * |
138 | * @param declaration The element declaration to validate against. |
139 | * @param type The type to validate against. |
140 | * @param isNilled Defines whether the element is nilled by the instance document. |
141 | * @param hasStateMachine Used to remember whether this element represents the start tag |
142 | * of a complex type and therefore pushes a new state machine on the stack. |
143 | * |
144 | * @note The @p type can differ from the element @p declaration type if the instance document has defined |
145 | * it via xsi:type attribute. |
146 | */ |
147 | bool validateElementType(const XsdElement::Ptr &declaration, const SchemaType::Ptr &type, bool isNilled, bool &hasStateMachine); |
148 | |
149 | /** |
150 | * Validates the current tag of the instance document against the given simple @p type of the element @p declaration. |
151 | * |
152 | * @param declaration The element declaration to validate against. |
153 | * @param type The type to validate against. |
154 | * @param isNilled Defines whether the element is nilled by the instance document. |
155 | * |
156 | * @note The @p type can differ from the element @p declaration type if the instance document has defined |
157 | * it via xsi:type attribute. |
158 | */ |
159 | bool validateElementSimpleType(const XsdElement::Ptr &declaration, const SchemaType::Ptr &type, bool isNilled); |
160 | |
161 | /** |
162 | * Validates the current tag of the instance document against the given complex @p type of the element @p declaration. |
163 | * |
164 | * @param declaration The element declaration to validate against. |
165 | * @param type The type to validate against. |
166 | * @param isNilled Defines whether the element is nilled by the instance document. |
167 | * @param hasStateMachine Used to remember whether this element represents the start tag |
168 | * of a complex type and therefore pushes a new state machine on the stack. |
169 | * |
170 | * @note The @p type can differ from the element @p declaration type if the instance document has defined |
171 | * it via xsi:type attribute. |
172 | */ |
173 | bool validateElementComplexType(const XsdElement::Ptr &declaration, const SchemaType::Ptr &type, bool isNilled, bool &hasStateMachine); |
174 | |
175 | /** |
176 | * Validates the given @p value against the attribute use @p declaration. |
177 | */ |
178 | bool validateAttribute(const XsdAttributeUse::Ptr &declaration, const QString &value); |
179 | |
180 | /** |
181 | * Validates the given @p value against the attribute @p declaration. |
182 | */ |
183 | bool validateAttribute(const XsdAttribute::Ptr &declaration, const QString &value); |
184 | |
185 | /** |
186 | * Validates the given @p attributeName against the @p wildcard. |
187 | */ |
188 | bool validateAttributeWildcard(const QXmlName &attributeName, const XsdWildcard::Ptr &wildcard); |
189 | |
190 | /** |
191 | * Validates the identity constraints of an @p element. |
192 | */ |
193 | bool validateIdentityConstraint(const XsdElement::Ptr &element, const QXmlItem ¤tItem); |
194 | |
195 | /** |
196 | * Validates the <em>unique</em> identity @p constraint of the @p element. |
197 | */ |
198 | bool validateUniqueIdentityConstraint(const XsdElement::Ptr &element, const XsdIdentityConstraint::Ptr &constraint, const TargetNode::Set &qualifiedNodeSet); |
199 | |
200 | /** |
201 | * Validates the <em>key</em> identity @p constraint of the @p element. |
202 | */ |
203 | bool validateKeyIdentityConstraint(const XsdElement::Ptr &element, const XsdIdentityConstraint::Ptr &constraint, const TargetNode::Set &targetNodeSet, const TargetNode::Set &qualifiedNodeSet); |
204 | |
205 | /** |
206 | * Validates the <em>keyref</em> identity @p constraint of the @p element. |
207 | */ |
208 | bool validateKeyRefIdentityConstraint(const XsdElement::Ptr &element, const XsdIdentityConstraint::Ptr &constraint, const TargetNode::Set &qualifiedNodeSet); |
209 | |
210 | /** |
211 | * Selects two sets of nodes that match the given identity @p constraint. |
212 | * |
213 | * @param element The element the identity constraint belongs to. |
214 | * @param currentItem The current element that will be used as focus for the XQuery. |
215 | * @param constraint The constraint (selector and fields) that describe the two sets. |
216 | * @param targetNodeSet The target node set as defined by the schema specification. |
217 | * @param qualifiedNodeSet The qualified node set as defined by the schema specification. |
218 | */ |
219 | bool selectNodeSets(const XsdElement::Ptr &element, const QXmlItem ¤tItem, const XsdIdentityConstraint::Ptr &constraint, TargetNode::Set &targetNodeSet, TargetNode::Set &qualifiedNodeSet); |
220 | |
221 | /** |
222 | * Creates an QXmlQuery object with the defined @p namespaceBindings that has the @p contextNode as focus |
223 | * and will execute @p query. |
224 | */ |
225 | QXmlQuery createXQuery(const QList<QXmlName> &namespaceBindings, const QXmlItem &contextNode, const QString &query) const; |
226 | |
227 | /** |
228 | * Returns the element declaration with the given @p name from the pool of all schemas. |
229 | */ |
230 | XsdElement::Ptr elementByName(const QXmlName &name) const; |
231 | |
232 | /** |
233 | * Returns the attribute declaration with the given @p name from the pool of all schemas. |
234 | */ |
235 | XsdAttribute::Ptr attributeByName(const QXmlName &name) const; |
236 | |
237 | /** |
238 | * Returns the type declaration with the given @p name from the pool of all schemas. |
239 | */ |
240 | SchemaType::Ptr typeByName(const QXmlName &name) const; |
241 | |
242 | /** |
243 | * Adds the ID/IDREF binding to the validated model and checks for duplicates. |
244 | */ |
245 | void addIdIdRefBinding(const QString &id, const NamedSchemaComponent::Ptr &binding); |
246 | |
247 | /** |
248 | * Helper method that reads an attribute of type xs:QName and does |
249 | * syntax checking. |
250 | */ |
251 | QString qNameAttribute(const QXmlName &attributeName); |
252 | |
253 | /** |
254 | * Returns the xs:anyType that is used to build up the state machine. |
255 | * We need that as the BuiltinTypes::xsAnyType is not a XsdComplexType. |
256 | */ |
257 | XsdComplexType::Ptr anyType(); |
258 | |
259 | /** |
260 | * Helper method that creates a state machine for the given @p particle |
261 | * and pushes it on the state machine stack. |
262 | */ |
263 | void createAndPushStateMachine(const XsdParticle::Ptr &particle); |
264 | |
265 | typedef QHash<QUrl, QStringList> MergedSchemas; |
266 | |
267 | XsdValidatedXmlNodeModel::Ptr m_model; |
268 | MergedSchemas m_mergedSchemas; |
269 | XsdSchema::Ptr m_schema; |
270 | const NamePool::Ptr m_namePool; |
271 | const QXmlName m_xsiNilName; |
272 | const QXmlName m_xsiTypeName; |
273 | const QXmlName m_xsiSchemaLocationName; |
274 | const QXmlName m_xsiNoNamespaceSchemaLocationName; |
275 | |
276 | QStack<XsdStateMachine<XsdTerm::Ptr> > m_stateMachines; |
277 | QUrl m_documentUri; |
278 | XsdComplexType::Ptr m_anyType; |
279 | QSet<QString> m_processedNamespaces; |
280 | QSet<QString> m_processedSchemaLocations; |
281 | QSet<QString> m_idRefs; |
282 | QHash<QXmlName, TargetNode::Set> m_idcKeys; |
283 | SchemaType::Ptr m_idRefsType; |
284 | }; |
285 | } |
286 | |
287 | QT_END_NAMESPACE |
288 | |
289 | #endif |
290 | |