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 QXMLQUERY_P_H |
51 | #define QXMLQUERY_P_H |
52 | |
53 | #include <QAbstractMessageHandler> |
54 | #include <QAbstractUriResolver> |
55 | #include <QPointer> |
56 | #include <QSourceLocation> |
57 | #include <QUrl> |
58 | #include <QVariant> |
59 | #include <QXmlName> |
60 | #include <QXmlNamePool> |
61 | #include <QXmlQuery> |
62 | |
63 | #include <private/qacceltreebuilder_p.h> |
64 | #include <private/qacceltreeresourceloader_p.h> |
65 | #include <private/qcoloringmessagehandler_p.h> |
66 | #include <private/qcommonsequencetypes_p.h> |
67 | #include <private/qexpressionfactory_p.h> |
68 | #include <private/qfocus_p.h> |
69 | #include <private/qfunctionfactorycollection_p.h> |
70 | #include <private/qgenericdynamiccontext_p.h> |
71 | #include <private/qgenericstaticcontext_p.h> |
72 | #include <private/qnamepool_p.h> |
73 | #include <private/qnetworkaccessdelegator_p.h> |
74 | #include <private/qreferencecountedvalue_p.h> |
75 | #include <private/qresourcedelegator_p.h> |
76 | #include <private/qstaticfocuscontext_p.h> |
77 | #include <private/quriloader_p.h> |
78 | #include <private/qvariableloader_p.h> |
79 | |
80 | QT_BEGIN_NAMESPACE |
81 | |
82 | class QXmlQueryPrivate |
83 | { |
84 | public: |
85 | |
86 | inline QXmlQueryPrivate(const QXmlNamePool &np = QXmlNamePool()) : namePool(np) |
87 | , messageHandler(0) |
88 | , uriResolver(0) |
89 | , queryLanguage(QXmlQuery::XQuery10) |
90 | , m_networkAccessDelegator(new QPatternist::NetworkAccessDelegator(0, 0)) |
91 | { |
92 | m_networkAccessDelegator->m_variableURIManager = new QPatternist::URILoader(ownerObject(), namePool.d, variableLoader()); |
93 | } |
94 | |
95 | void detach() |
96 | { |
97 | if(m_variableLoader) |
98 | m_variableLoader = QPatternist::VariableLoader::Ptr(new QPatternist::VariableLoader(namePool.d, m_variableLoader)); |
99 | |
100 | delete m_networkAccessDelegator->m_variableURIManager; |
101 | m_networkAccessDelegator->m_variableURIManager = new QPatternist::URILoader(ownerObject(), namePool.d, m_variableLoader); |
102 | |
103 | if(m_resourceLoader) |
104 | { |
105 | const QPatternist::AccelTreeResourceLoader::Ptr nev(new QPatternist::AccelTreeResourceLoader(namePool.d, |
106 | m_networkAccessDelegator)); |
107 | m_resourceLoader = QPatternist::DeviceResourceLoader::Ptr(new QPatternist::ResourceDelegator(m_resourceLoader->deviceURIs(), |
108 | m_resourceLoader, |
109 | nev)); |
110 | } |
111 | } |
112 | |
113 | bool isValid() |
114 | { |
115 | return expression(); |
116 | } |
117 | |
118 | inline void recompileRequired() |
119 | { |
120 | m_expr.reset(); |
121 | } |
122 | |
123 | inline QPatternist::VariableLoader::Ptr variableLoader() |
124 | { |
125 | if(!m_variableLoader) |
126 | m_variableLoader = QPatternist::VariableLoader::Ptr(new QPatternist::VariableLoader(namePool.d)); |
127 | |
128 | return m_variableLoader; |
129 | } |
130 | |
131 | inline QPatternist::StaticContext::Ptr staticContext() |
132 | { |
133 | if(m_staticContext && m_expr) |
134 | return m_staticContext; |
135 | /* Else, re-create the staticContext. */ |
136 | |
137 | if(!messageHandler) |
138 | messageHandler = new QPatternist::ColoringMessageHandler(ownerObject()); |
139 | |
140 | if(!m_functionFactory) |
141 | { |
142 | if(queryLanguage == QXmlQuery::XSLT20) |
143 | m_functionFactory = QPatternist::FunctionFactoryCollection::xslt20Factory(np: namePool.d); |
144 | else |
145 | m_functionFactory = QPatternist::FunctionFactoryCollection::xpath20Factory(np: namePool.d); |
146 | } |
147 | |
148 | const QPatternist::GenericStaticContext::Ptr genericStaticContext(new QPatternist::GenericStaticContext(namePool.d, |
149 | messageHandler, |
150 | queryURI, |
151 | m_functionFactory, |
152 | queryLanguage)); |
153 | genericStaticContext->setResourceLoader(resourceLoader()); |
154 | |
155 | genericStaticContext->setExternalVariableLoader(variableLoader()); |
156 | |
157 | m_staticContext = genericStaticContext; |
158 | |
159 | if(!contextItem.isNull()) |
160 | m_staticContext = QPatternist::StaticContext::Ptr(new QPatternist::StaticFocusContext(QPatternist::AtomicValue::qtToXDMType(item: contextItem), m_staticContext)); |
161 | else if( queryLanguage == QXmlQuery::XmlSchema11IdentityConstraintField |
162 | || queryLanguage == QXmlQuery::XmlSchema11IdentityConstraintSelector |
163 | || queryLanguage == QXmlQuery::XPath20) |
164 | m_staticContext = QPatternist::StaticContext::Ptr(new QPatternist::StaticFocusContext(QPatternist::BuiltinTypes::node, m_staticContext)); |
165 | |
166 | for (int i = 0; i < m_additionalNamespaceBindings.count(); ++i) { |
167 | m_staticContext->namespaceBindings()->addBinding(nb: m_additionalNamespaceBindings.at(i)); |
168 | } |
169 | |
170 | return m_staticContext; |
171 | } |
172 | |
173 | inline QPatternist::DynamicContext::Ptr dynamicContext(QAbstractXmlReceiver *const callback = 0) |
174 | { |
175 | const QPatternist::StaticContext::Ptr statContext(staticContext()); |
176 | Q_ASSERT(statContext); |
177 | |
178 | QPatternist::GenericDynamicContext::Ptr dynContext(new QPatternist::GenericDynamicContext(namePool.d, statContext->messageHandler(), |
179 | statContext->sourceLocations())); |
180 | |
181 | QPatternist::AutoPtr<QPatternist::NodeBuilder> nodeBuilder(new QPatternist::AccelTreeBuilder<false>(QUrl(), QUrl(), namePool.d, |
182 | dynContext.data())); |
183 | dynContext->setNodeBuilder(nodeBuilder); |
184 | |
185 | dynContext->setResourceLoader(statContext->resourceLoader()); |
186 | dynContext->setExternalVariableLoader(statContext->externalVariableLoader()); |
187 | dynContext->setUriResolver(uriResolver); |
188 | |
189 | if(callback) |
190 | dynContext->setOutputReceiver(callback); |
191 | |
192 | if(contextItem.isNull()) |
193 | return dynContext; |
194 | else |
195 | { |
196 | QPatternist::DynamicContext::Ptr focus(new QPatternist::Focus(dynContext)); |
197 | QPatternist::Item::Iterator::Ptr it(QPatternist::makeSingletonIterator(item: QPatternist::Item::fromPublic(i: contextItem))); |
198 | it->next(); |
199 | focus->setFocusIterator(it); |
200 | return focus; |
201 | } |
202 | } |
203 | |
204 | inline QPatternist::AccelTreeResourceLoader::Ptr resourceLoader() |
205 | { |
206 | if(!m_resourceLoader) |
207 | m_resourceLoader = (new QPatternist::AccelTreeResourceLoader(namePool.d, m_networkAccessDelegator)); |
208 | |
209 | return m_resourceLoader; |
210 | } |
211 | |
212 | void setRequiredType(const QPatternist::SequenceType::Ptr &seqType) |
213 | { |
214 | Q_ASSERT(seqType); |
215 | if(!m_requiredType || m_requiredType->is(other: seqType)) |
216 | return; |
217 | |
218 | m_requiredType = seqType; |
219 | m_staticContext.reset(); |
220 | } |
221 | |
222 | QPatternist::SequenceType::Ptr requiredType() |
223 | { |
224 | if(m_requiredType) |
225 | return m_requiredType; |
226 | else |
227 | { |
228 | m_requiredType = QPatternist::CommonSequenceTypes::ZeroOrMoreItems; |
229 | return m_requiredType; |
230 | } |
231 | } |
232 | |
233 | QPatternist::Expression::Ptr expression(QIODevice *const queryDevice = 0) |
234 | { |
235 | if(m_expr && !queryDevice) |
236 | return m_expr; |
237 | |
238 | /* If we need to update, but we don't have any source code, we can |
239 | * never create an Expression. */ |
240 | if(!queryDevice) |
241 | return QPatternist::Expression::Ptr(); |
242 | |
243 | try |
244 | { |
245 | /* The static context has source locations, and they need to be |
246 | * updated to the new query. */ |
247 | m_staticContext.reset(); |
248 | |
249 | if(!m_expressionFactory) |
250 | m_expressionFactory = QPatternist::ExpressionFactory::Ptr(new QPatternist::ExpressionFactory()); |
251 | |
252 | m_expr = m_expressionFactory->createExpression(device: queryDevice, context: staticContext(), |
253 | lang: queryLanguage, |
254 | requiredType: requiredType(), |
255 | queryURI, |
256 | initialTemplateName); |
257 | } |
258 | catch(const QPatternist::Exception) |
259 | { |
260 | m_expr.reset(); |
261 | |
262 | /* We don't call m_staticContext.reset() because it shouldn't be |
263 | * necessary, since m_staticContext is changed when the expression |
264 | * is changed. */ |
265 | } |
266 | |
267 | return m_expr; |
268 | } |
269 | |
270 | inline void addAdditionalNamespaceBinding(const QXmlName &binding) |
271 | { |
272 | m_additionalNamespaceBindings.append(t: binding); |
273 | } |
274 | |
275 | QXmlNamePool namePool; |
276 | QPointer<QAbstractMessageHandler> messageHandler; |
277 | /** |
278 | * Must be absolute and valid. |
279 | */ |
280 | QUrl queryURI; |
281 | const QAbstractUriResolver * uriResolver; |
282 | QXmlItem contextItem; |
283 | QXmlName initialTemplateName; |
284 | |
285 | inline void setExpressionFactory(const QPatternist::ExpressionFactory::Ptr &expr) |
286 | { |
287 | m_expressionFactory = expr; |
288 | } |
289 | |
290 | QXmlQuery::QueryLanguage queryLanguage; |
291 | QPointer<QNetworkAccessManager> userNetworkManager; |
292 | |
293 | inline QObject *ownerObject() |
294 | { |
295 | if(!m_owner) |
296 | m_owner = new QPatternist::ReferenceCountedValue<QObject>(new QObject()); |
297 | |
298 | return m_owner->value; |
299 | } |
300 | |
301 | QPatternist::ExpressionFactory::Ptr m_expressionFactory; |
302 | QPatternist::StaticContext::Ptr m_staticContext; |
303 | QPatternist::VariableLoader::Ptr m_variableLoader; |
304 | QPatternist::DeviceResourceLoader::Ptr m_resourceLoader; |
305 | /** |
306 | * This is the AST for the query. |
307 | */ |
308 | QPatternist::Expression::Ptr m_expr; |
309 | QPatternist::ReferenceCountedValue<QObject>::Ptr m_owner; |
310 | |
311 | /** |
312 | * This is our effective network manager, that we end up using. The one the |
313 | * user sets is userNetworkManager. |
314 | */ |
315 | QPatternist::SequenceType::Ptr m_requiredType; |
316 | QPatternist::FunctionFactory::Ptr m_functionFactory; |
317 | QPatternist::NetworkAccessDelegator::Ptr m_networkAccessDelegator; |
318 | |
319 | QList<QXmlName> m_additionalNamespaceBindings; |
320 | }; |
321 | |
322 | QT_END_NAMESPACE |
323 | |
324 | #endif |
325 | |