source: trunk/src/xmlpatterns/api/qabstractxmlnodemodel.cpp@ 168

Last change on this file since 168 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 54.3 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtXmlPatterns module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <QVector>
43
44#include "qabstractxmlnodemodel_p.h"
45#include "qabstractxmlreceiver.h"
46#include "qcommonvalues_p.h"
47#include "qemptyiterator_p.h"
48#include "qitemmappingiterator_p.h"
49#include "qitem_p.h"
50#include "qnamespaceresolver_p.h"
51#include "qsequencemappingiterator_p.h"
52#include "qsingletoniterator_p.h"
53
54#include "qabstractxmlnodemodel.h"
55
56QT_BEGIN_NAMESPACE
57
58using namespace QPatternist;
59
60typedef QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<QXmlNodeModelIndex> > QXmlNodeModelIndexIteratorPointer;
61
62/**
63 * @file
64 * @short Contains the implementation of QAbstractXmlNodeModel.
65 */
66
67bool QAbstractXmlNodeModel::isIgnorableInDeepEqual(const QXmlNodeModelIndex &n)
68{
69 Q_ASSERT(!n.isNull());
70 const QXmlNodeModelIndex::NodeKind nk = n.kind();
71 return nk == QXmlNodeModelIndex::ProcessingInstruction ||
72 nk == QXmlNodeModelIndex::Comment;
73}
74
75
76/*!
77 \class QAbstractXmlNodeModel
78 \brief The QAbstractXmlNodeModel class is an abstract base class for modeling non-XML data to look like XML for QXmlQuery.
79 \threadsafe
80 \since 4.4
81 \ingroup xml-tools
82
83 The QAbstractXmlNodeModel specifies the interface that a node model
84 must implement for that node model be accessible to the query engine
85 for processing XQuery queries. A node model represents data as a
86 structure that can be queried as if the data were XML.
87
88 The node model represented by a subclass of QAbstractXmlNodeModel is
89 meant to be accessed by the QtXmlPatterns query engine. If the API
90 seems a little strange in a few places, it is because the member
91 functions are called by the query engine as it evaluates an
92 XQuery. They aren't meant to be used programatically.
93
94 \section1 Usage
95
96 QAbstractXmlNodeModel bridges the gap between the arbitrary structure
97 of the non-XML data to be queried and the well-defined structure of
98 XML data understood by QXmlQuery.
99
100 Consider a chemistry application that reads the file \c
101 chemistryData, which contains non-XML data that represents a
102 chemical structure composed of molecules and atoms. The application
103 will query this chemistry data with an XQuery it reads from file \c
104 queryFile. We write a custom subclass of QAbstractXmlNodeModel (\c
105 ChemistryNodeModel) that reads \c chemistryData and builds a data
106 structure, perhaps composed of objects of our own classes \c
107 molecule and \c atom. Clearly, this data structure is not XML. Our
108 custom subclass will know how to traverse this non-XML structure and
109 present it through the \l
110 {http://www.w3.org/TR/xpath-datamodel/}{XPath Data Model interface}.
111
112 \snippet doc/src/snippets/code/src_xmlpatterns_api_qabstractxmlnodemodel.cpp 1
113
114 The application first creates an instance of QXmlQuery and calls \l
115 {QXmlQuery::setQuery()}{setQuery()} to read \c queryFile containing
116 the XQuery we want to run. Then it creates an instance of our custom
117 node model class, \c ChemistryNodeModel, which is a subclass of
118 QAbstractXmlNodeModel. Its constructor is called with the \l
119 {QXmlNamePool} {name pool} obtained from our QXmlQuery, and with the
120 \c chemistryFile containing the structure of molecules and atoms to
121 be queried. The \l {QXmlNamePool} {name pool} is required because
122 our custom node model has the member function \l
123 {QAbstractXmlNodeModel::name()} {name()}, which returns the \l
124 {QXmlName} {name} of any node in the model. The \l {QXmlQuery}
125 {query} and the custom node model must use the same name pool for
126 constructing these \l {QXmlName} {names}. The constructor would then
127 read \c chemistryFile and build the custom node model structure.
128
129 To connect the \c query to the custom node model, we must bind a
130 variable name used in the query to a node in the model. The variable
131 can then be used in the query as a starting node. First, an \l
132 {QXmlNodeModelIndex} {index} for the desired starting node is
133 retrieved by calling QAbstractXmlNodeModel::createIndex(). Then the
134 index is bound to a variable name, in this case \c queryRoot, by
135 passing the name and the index to QXmlQuery::bindVariable(). The
136 query can then use a variable reference \c $queryRoot to refer to
137 the starting node. Note that if the \l {QXmlQuery} {query} uses
138 multiple variable references, a call to QXmlQuery::bindVariable()
139 is required to bind each different variable name to a node in the
140 model.
141
142 The query is executed when the application calls one of the
143 QXmlQuery evaluation functions. The application uses
144 QXmlQuery::evaluateTo(QAbstractXmlReceiver *), because it then uses
145 a \l {QXmlSerializer} {serializer} to out the query result as XML to
146 \c stdout. We could have used QXmlQuery::evaluateTo(QXmlResultItems
147 *) to get a list of result items, or
148 QXmlQuery::evaluateTo(QStringList *) if the query evaluated to a
149 sequence of \c {xs:string} values.
150
151 During query execution, the engine iterates over the node model
152 using nextFromSimpleAxis() to get the \l {QXmlNodeModelIndex}
153 {index} of the next node to be visited. The engine can get the name
154 of a node by calling name() with the node's \l {QXmlNodeModelIndex}
155 {index}. stringValue(), baseUri(), documentUri() and kind() are also
156 called as needed with a node \l {QXmlNodeModelIndex} {index}.
157
158 The example demonstrates the standard pattern for using a subclass
159 of QAbstractXmlNodeModel in combination with QXmlQuery to perform
160 an XQuery.
161
162 \list 1
163
164 \o Instantiate QXmlQuery and give it the XQuery to be run;
165
166 \o Instantiate a subclass of QAbstractXmlNodeModel or
167 QSimpleXmlNodeModel;
168
169 \o Retrieve a QXmlNodeModelIndex for the node in the model where
170 the QXmlQuery should start the query;
171
172 \o Use QXmlQuery::bindVariable() to bind the QXmlNodeModelIndex
173 to \c {$variable name};
174
175 \o Call one of the QXmlQuery evaluation functions to run the
176 query.
177
178 \endlist
179
180 \section1 Subclassing
181
182 Because the \l {http://www.w3.org/TR/xpath-datamodel/}{XPath Data Model
183 interface} presented by QAbstractXmlNodeModel allows QXmlQuery to
184 operate on non-XML data as if it were XML, implementing subclasses
185 of QAbstractXmlNodeModel can involve a significant amount of
186 work. The QSimpleXmlNodeModel class is provided to simplify the
187 implementation for many common use cases.
188
189 \section1 Thread Safety
190
191 Because the node model can be accessed concurrently by threads in
192 the QtXmlPatterns module, subclasses of QAbstractXmlNodeModel must
193 be written to be \l{Thread Support in Qt#Reentrancy and Thread-Safety}
194 {thread-safe}.
195 Classes that simplify implementing thread-safety include QReadLocker
196 and QWriteLocker.
197
198 See the example \l{File System Example} for a demonstration.
199 */
200
201/*!
202 \enum QXmlNodeModelIndex::Constants
203
204 \value ForwardAxis All forward axes include this flag.
205 \value ReverseAxis All reverse axes include this flag.
206 */
207
208/*!
209 \enum QXmlNodeModelIndex::DocumentOrder
210
211 Identifies the specific node comparison operator that should be
212 used.
213
214 \value Precedes Signifies the \c \<\< operator. Test whether the
215 first operand precedes the second in the document.
216
217 \value Follows Signifies the \c \>\> operator. Test whether the
218 first operand follows the second in the document.
219
220 \value Is Signifies the \c is operator. Test whether two nodes have
221 the same node identity.
222 */
223
224/*!
225 \enum QAbstractXmlNodeModel::SimpleAxis
226
227 Four axes that each contain one node only.
228
229 \value Parent The parent of the context node
230 \value FirstChild The first child of the context node
231 \value PreviousSibling The previous child of the context node
232 \value NextSibling The next child of the context node
233*/
234
235/*!
236 \enum QXmlNodeModelIndex::Axis
237 \internal
238
239 Identify the axes emanating from a node.
240
241 The axes AxisChild, AxisDescendant, AxisAttribute, AxisSelf,
242 AxisDescendantOrSelf, AxisFollowingSibling, and AxisFollowing are
243 forward axes.
244
245 The axes AxisParent, AxisAncestor, AxisPrecedingSibling,
246 AxisPreceding and AxisAncestorOrSelf are reverse axes.
247
248 \sa {http://www.w3.org/TR/xquery/#axes}{XQuery 1.0: An XML Query Language, 3.2.1.1 Axes}
249
250 \value AxisChild The \c child axis.
251
252 \value AxisDescendant The \c descendant axis.
253
254 \value AxisAttribute The \c attribute axis. Note: There
255 is a node kind named \c{Attribute}.
256
257 \value AxisSelf The \c self axis.
258
259 \value AxisDescendantOrSelf The \c descendant-or-self axis.
260
261 \value AxisFollowingSibling The \c following-sibling axis.
262
263 \value AxisNamespace The \c namespace axis. Note: Does
264 not exist in XQuery; deprecated in
265 XPath 2.0 (optionally supported);
266 mandatory in XPath 1.0.
267
268 \value AxisFollowing The \c following axis.
269
270 \value AxisParent The \c parent axis.
271
272 \value AxisAncestor The \c ancestor axis.
273
274 \value AxisPrecedingSibling The \c preceding-sibling axis.
275
276 \value AxisPreceding The \c preceding axis.
277
278 \value AxisAncestorOrSelf The \c ancestor-or-self axis.
279*/
280
281using namespace QPatternist;
282
283/*!
284 Default constructor.
285 */
286QAbstractXmlNodeModel::QAbstractXmlNodeModel() : d_ptr(0)
287{
288}
289
290/*!
291 \internal
292
293 Takes the d-pointer.
294
295 */
296QAbstractXmlNodeModel::QAbstractXmlNodeModel(QAbstractXmlNodeModelPrivate *d) : d_ptr(d)
297{
298}
299
300/*!
301 Destructor.
302 */
303QAbstractXmlNodeModel::~QAbstractXmlNodeModel()
304{
305 delete d_ptr;
306}
307
308/*!
309 \typedef QAbstractXmlNodeModel::List
310
311 A \l{QList}{list} of \l{QExplicitlySharedDataPointer} {smart
312 pointers} to instances of QAbstractXmlNodeModel.
313
314 \sa QExplicitlySharedDataPointer
315 */
316
317/*!
318 \typedef QAbstractXmlNodeModel::Ptr
319
320 A \l {QExplicitlySharedDataPointer} {smart pointer} to an
321 instance of QAbstractXmlNodeModel.
322
323 \sa QExplicitlySharedDataPointer
324 */
325
326/*!
327 \fn QUrl QAbstractXmlNodeModel::baseUri(const QXmlNodeModelIndex &n) const
328
329 Returns the base URI for the node whose index is \a n. The caller
330 guarantees that \a n is not \c null and that it belongs to a node
331 in this node model.
332
333 The base URI of a node can be extracted using the \c fn:base-uri()
334 function. The base URI is typically used for resolving relative URIs
335 that appear in the node or its children. It is conformant to just
336 return the document URI, although that might not properly reflect
337 the underlying data.
338
339 This function maps to the \c dm:base-uri accessor, which returns
340 a base URI according to the following:
341
342 \list
343
344 \o For document nodes, the base URI and the document URI are the same.
345
346 \o For elements, the base URI is the URI appearing in the element's
347 \c xml:base attribute, if present, or it is resolved to the
348 parent element's base URI.
349
350 \o Namespace nodes have no base URI.
351
352 \o The base URI for a processing instruction, comment, attribute,
353 or text node is the base URI of the node's parent element.
354
355 \endlist
356
357 The implementation guarantees to return a valid QUrl, or a default
358 constructed QUrl. If a node has no base URI, as in the case where a
359 comment has no parent, a default constructed QUrl is returned.
360
361 \sa {http://www.w3.org/TR/xpath-datamodel/#dm-base-uri}{XQuery 1.0 and XPath 2.0 Data Model (XDM), 5.2 base-uri Accessor}
362 */
363
364/*!
365 \fn QUrl QAbstractXmlNodeModel::documentUri(const QXmlNodeModelIndex &n) const
366
367 Returns the document URI of \a n. The document URI identifies the
368 resource which is the document. For example, the document could be a
369 regular file, e.g., \c{file:/}, or it could be the \c{http://} URL of
370 the location of a file. The document URI is used for resolving URIs
371 and to simply know where the document is.
372
373 If the node model maps to a URI in a natural way, return that URI.