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
80QT_BEGIN_NAMESPACE
81
82class QXmlQueryPrivate
83{
84public:
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
322QT_END_NAMESPACE
323
324#endif
325

source code of qtxmlpatterns/src/xmlpatterns/api/qxmlquery_p.h