Qt 4.8
qsequencegeneratingfns.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include <QStack>
43 #include <QStringList>
44 #include <QFileInfo>
45 
46 #include "qanyuri_p.h"
47 #include "qboolean_p.h"
48 #include "qcommonsequencetypes_p.h"
49 #include "qcommonvalues_p.h"
50 #include "qemptysequence_p.h"
51 #include "qitemmappingiterator_p.h"
52 #include "qnodesort_p.h"
53 #include "qpatternistlocale_p.h"
54 #include "private/qxmlutils_p.h"
55 
57 
59 
60 using namespace QPatternist;
61 
62 IdFN::IdFN() : m_hasCreatedSorter(false)
63 {
64 }
65 
67  const IDContext &context) const
68 {
69  return context.second->elementById(context.first->namePool()->allocateQName(QString(), id));
70 }
71 
90 {
91 public:
92  StringSplitter(const Item::Iterator::Ptr &source);
93  virtual QString next();
94  virtual QString current() const;
95  virtual qint64 position() const;
96 private:
97  QString loadNext();
103 };
104 
105 StringSplitter::StringSplitter(const Item::Iterator::Ptr &source) : m_source(source)
106  , m_position(0)
107  , m_sourceAtEnd(false)
108 {
111 }
112 
114 {
115  /* We also check m_position, we want to load on our first run. */
116  if(!m_buffer.isEmpty())
117  {
118  ++m_position;
119  m_current = m_buffer.pop();
120  return m_current;
121  }
122  else if(m_sourceAtEnd)
123  {
124  m_current.clear();
125  m_position = -1;
126  return QString();
127  }
128 
129  return loadNext();
130 }
131 
133 {
134  const Item sourceNext(m_source->next());
135 
136  if(sourceNext.isNull())
137  {
138  m_sourceAtEnd = true;
139  /* We might have strings in m_buffer, let's empty it. */
140  return next();
141  }
142 
143  const QStringList candidates(sourceNext.stringValue().simplified().split(QLatin1Char(' ')));
144  const int count = candidates.length();
145 
146  for(int i = 0; i < count; ++i)
147  {
148  const QString &at = candidates.at(i);
149 
150  if(QXmlUtils::isNCName(at))
151  m_buffer.push(at);
152  }
153 
154  /* So, now we have populated m_buffer, let's start from the beginning. */
155  return next();
156 }
157 
159 {
160  return m_current;
161 }
162 
164 {
165  return m_position;
166 }
167 
168 Item::Iterator::Ptr IdFN::evaluateSequence(const DynamicContext::Ptr &context) const
169 {
170  const Item::Iterator::Ptr idrefs(m_operands.first()->evaluateSequence(context));
171  const Item node(m_operands.last()->evaluateSingleton(context));
172 
173  checkTargetNode(node.asNode(), context, ReportContext::FODC0001);
174 
175  return makeItemMappingIterator<Item,
176  QString,
178  IDContext>(ConstPtr(this),
179  StringSplitter::Ptr(new StringSplitter(idrefs)),
180  qMakePair(context, node.asNode().model()));
181 }
182 
183 Expression::Ptr IdFN::typeCheck(const StaticContext::Ptr &context,
184  const SequenceType::Ptr &reqType)
185 {
186  if(m_hasCreatedSorter)
187  return FunctionCall::typeCheck(context, reqType);
188  else
189  {
190  const Expression::Ptr newMe(new NodeSortExpression(Expression::Ptr(this)));
191  context->wrapExpressionWith(this, newMe);
192  m_hasCreatedSorter = true;
193  return newMe->typeCheck(context, reqType);
194  }
195 }
196 
197 Item::Iterator::Ptr IdrefFN::evaluateSequence(const DynamicContext::Ptr &context) const
198 {
199  const Item::Iterator::Ptr ids(m_operands.first()->evaluateSequence(context));
200 
201  Item mId(ids->next());
202  if(!mId)
203  return CommonValues::emptyIterator;
204 
205  const Item node(m_operands.last()->evaluateSingleton(context));
206  checkTargetNode(node.asNode(), context, ReportContext::FODC0001);
207 
208  return CommonValues::emptyIterator; /* TODO Haven't implemented further. */
209 }
210 
214 static QUrl resolveScheme(const QUrl &url)
215 {
216  // On Windows and Symbian the drive letter is detected as the scheme.
217  if (url.scheme().isEmpty() || (url.scheme().length() == 1)) {
218  QString filename = url.toString();
219  QFileInfo file(filename);
220  if (file.exists())
221  return QUrl::fromLocalFile(filename);
222  }
223  return url;
224 }
225 
226 Item DocFN::evaluateSingleton(const DynamicContext::Ptr &context) const
227 {
228  const Item itemURI(m_operands.first()->evaluateSingleton(context));
229 
230  if(!itemURI)
231  return Item();
232 
233  /* These two lines were previously in a separate function but are now duplicated
234  * in DocAvailableFN::evaluateEBV() and DocFN::typeCheck(),
235  * as part of a workaround for solaris-cc-64. DocFN::typeCheck() is in qsequencefns.cpp
236  * as part of that workaround. */
237  const QUrl mayRela(AnyURI::toQUrl<ReportContext::FODC0005>(itemURI.stringValue(), context, this));
238  const QUrl uri(resolveScheme(context->resolveURI(mayRela, staticBaseURI())));
239 
240  Q_ASSERT(uri.isValid());
241  Q_ASSERT(!uri.isRelative());
242 
243  const Item doc(context->resourceLoader()->openDocument(uri, context));
244 
245  return doc;
246 }
247 
248 SequenceType::Ptr DocFN::staticType() const
249 {
250  if(m_type)
251  return m_type;
252  else
253  return CommonSequenceTypes::ZeroOrOneDocumentNode;
254 }
255 
256 bool DocAvailableFN::evaluateEBV(const DynamicContext::Ptr &context) const
257 {
258  const Item itemURI(m_operands.first()->evaluateSingleton(context));
259 
260  /* 15.5.4 fn:doc reads: "If $uri is the empty sequence, the result is an empty sequence."
261  * Hence, we return false for the empty sequence, because this doesn't hold true:
262  * "If this function returns true, then calling fn:doc($uri) within
263  * the same execution scope must return a document node."(15.5.5 fn:doc-available) */
264  if(!itemURI)
265  return false;
266 
267  /* These two lines are duplicated in DocFN::evaluateSingleton(), as part
268  * of a workaround for solaris-cc-64. */
269  const QUrl mayRela(AnyURI::toQUrl<ReportContext::FODC0005>(itemURI.stringValue(), context, this));
270  const QUrl uri(resolveScheme(context->resolveURI(mayRela, staticBaseURI())));
271 
272  Q_ASSERT(!uri.isRelative());
273  return context->resourceLoader()->isDocumentAvailable(uri);
274 }
275 
276 Item::Iterator::Ptr CollectionFN::evaluateSequence(const DynamicContext::Ptr &context) const
277 {
278  // TODO resolve with URI resolve
279  if(m_operands.isEmpty())
280  {
281  // TODO check default collection
282  context->error(QtXmlPatterns::tr("The default collection is undefined"),
283  ReportContext::FODC0002, this);
284  return CommonValues::emptyIterator;
285  }
286  else
287  {
288  const Item itemURI(m_operands.first()->evaluateSingleton(context));
289 
290  if(itemURI)
291  {
292  const QUrl uri(AnyURI::toQUrl<ReportContext::FODC0004>(itemURI.stringValue(), context, this));
293 
294  // TODO 2. Resolve against static context base URI(store base URI at compile time)
295  context->error(QtXmlPatterns::tr("%1 cannot be retrieved").arg(formatResourcePath(uri)),
296  ReportContext::FODC0004, this);
297  return CommonValues::emptyIterator;
298  }
299  else
300  {
301  /* This is out default collection currently, */
302  return CommonValues::emptyIterator;
303  }
304  }
305 }
306 
virtual bool isDocumentAvailable(const QUrl &uri)
Calls to this function are generated by calls to the fn:doc-available() function. ...
bool isValid() const
Returns true if the URL is valid; otherwise returns false.
Definition: qurl.cpp:4303
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
static QString formatResourcePath(const QUrl &uri)
Formats uri as a path to a resource, typically it&#39;s a filename or a URI.
StringSplitter(const Item::Iterator::Ptr &source)
QString toString(FormattingOptions options=None) const
Returns the human-displayable string representation of the URL.
Definition: qurl.cpp:5896
static QUrl resolveScheme(const QUrl &url)
Attemps to resolve scheme if URL does not have scheme defined.
QUrl resolveURI(const QUrl &relative, const QUrl &baseURI) const
#define at(className, varName)
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
T1 first
Definition: qpair.h:65
static qreal position(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine)
T2 second
Definition: qpair.h:66
The QExplicitlySharedDataPointer class represents a pointer to an explicitly shared object...
Definition: qshareddata.h:136
virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, const SequenceType::Ptr &reqType)
Definition: qexpression.cpp:70
bool exists() const
Returns true if the file exists; otherwise returns false.
Definition: qfileinfo.cpp:675
The QUrl class provides a convenient interface for working with URLs.
Definition: qurl.h:61
The QString class provides a Unicode character string.
Definition: qstring.h:83
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
virtual QString next()
Returns the next item in the sequence, or a null object if the end has been reached.
bool isRelative() const
Returns true if the URL is relative; otherwise returns false.
Definition: qurl.cpp:5880
QStack< QString > m_buffer
De-duplicates and sorts in document order the content that its operand returns.
Definition: qnodesort_p.h:70
QExplicitlySharedDataPointer< QAbstractXmlForwardIterator< QString > > Ptr
A smart pointer wrapping an instance of a QAbstractXmlForwardIterator subclass.
T pop()
Removes the top item from the stack and returns it.
Definition: qstack.h:67
virtual QString current() const
Returns the current item in the sequence.
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
void error(const QString &message, const ReportContext::ErrorCode errorCode, const QSourceLocation &sourceLocation)
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
Item mapToItem(const QString &id, const IDContext &context) const
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
The QAbstractXmlForwardIterator class is a base class for forward iterators.
The namespace for the internal API of QtXmlPatterns.
__int64 qint64
Definition: qglobal.h:942
virtual qint64 count()
Determines the number of items this QAbstractXmlForwardIterator represents.
void push(const T &t)
Adds element t to the top of the stack.
Definition: qstack.h:60
Contains classes implementing the functions found in XQuery 1.0 and XPath 2.0 Functions and Operators...
QString scheme() const
Returns the scheme of the URL.
Definition: qurl.cpp:4550
Contains functions used for formatting arguments, such as keywords and paths, in translated strings...
Represents an item in the XPath 2.0 Data Model.
Definition: qitem_p.h:182
void clear()
Clears the contents of the string and makes it empty.
Definition: qstring.h:723
const Item::Iterator::Ptr m_source
Q_OUTOFLINE_TEMPLATE QPair< T1, T2 > qMakePair(const T1 &x, const T2 &y)
Definition: qpair.h:102
virtual qint64 position() const
Returns the current position in the sequence represented by this.
static QUrl fromLocalFile(const QString &localfile)
Returns a QUrl representation of localFile, interpreted as a local file.
Definition: qurl.cpp:6374
bool isEmpty() const
Returns true if the vector has size 0; otherwise returns false.
Definition: qvector.h:139
The QFileInfo class provides system-independent file information.
Definition: qfileinfo.h:60
void wrapExpressionWith(const SourceLocationReflection *const existingNode, const QExplicitlySharedDataPointer< Expression > &newNode)
Ensures source locations are handled in such a manner that existingNode wraps newNode.
Helper class for IdFN.
virtual ResourceLoader::Ptr resourceLoader() const =0
static bool isNCName(const QStringRef &ncName)
Determines whether c is a valid instance of production [4]NCName in the XML 1.0 Namespaces specificat...
Definition: qxmlutils.cpp:377
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
virtual Item openDocument(const QUrl &uri, const ReportContext::Ptr &context)
Calls to this function are generated by calls to the fn:document() or fn:doc() function.