source: trunk/src/xmlpatterns/api/qvariableloader.cpp@ 256

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

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

File size: 8.9 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 <QVariant>
43#include <QStringList>
44
45#include "qanyuri_p.h"
46#include "qatomicstring_p.h"
47#include "qbuiltintypes_p.h"
48#include "qcommonsequencetypes_p.h"
49#include "qgenericsequencetype_p.h"
50#include "qinteger_p.h"
51#include "qitem_p.h"
52#include "qsequencetype_p.h"
53#include "qvariableloader_p.h"
54#include "qxmlquery_p.h"
55
56QT_BEGIN_NAMESPACE
57
58namespace QPatternist
59{
60
61 class VariantListIterator : public ListIteratorPlatform<QVariant, Item, VariantListIterator>
62 {
63 public:
64 inline VariantListIterator(const QVariantList &list) : ListIteratorPlatform<QVariant, Item, VariantListIterator>(list)
65 {
66 }
67
68 private:
69 friend class ListIteratorPlatform<QVariant, Item, VariantListIterator>;
70
71 inline Item inputToOutputItem(const QVariant &inputType) const
72 {
73 return AtomicValue::toXDM(inputType);
74 }
75 };
76
77 class StringListIterator : public ListIteratorPlatform<QString, Item, StringListIterator>
78 {
79 public:
80 inline StringListIterator(const QStringList &list) : ListIteratorPlatform<QString, Item, StringListIterator>(list)
81 {
82 }
83
84 private:
85 friend class ListIteratorPlatform<QString, Item, StringListIterator>;
86
87 static inline Item inputToOutputItem(const QString &inputType)
88 {
89 return AtomicString::fromValue(inputType);
90 }
91 };
92
93 /**
94 * Takes two DynamicContext instances, and redirects the storage of temporary trees
95 * to one of them.
96 *
97 * @since 4.5
98 */
99 class TemporaryTreesRedirectingContext : public DelegatingDynamicContext
100 {
101 public:
102 TemporaryTreesRedirectingContext(const DynamicContext::Ptr &other,
103 const DynamicContext::Ptr &modelStorage) : DelegatingDynamicContext(other)
104 , m_modelStorage(modelStorage)
105 {
106 Q_ASSERT(m_modelStorage);
107 }
108
109 virtual void addNodeModel(const QAbstractXmlNodeModel::Ptr &nodeModel)
110 {
111 m_modelStorage->addNodeModel(nodeModel);
112 }
113
114 private:
115 const DynamicContext::Ptr m_modelStorage;
116 };
117}
118
119using namespace QPatternist;
120
121SequenceType::Ptr VariableLoader::announceExternalVariable(const QXmlName name,
122 const SequenceType::Ptr &declaredType)
123{
124 Q_UNUSED(declaredType);
125 const QVariant &variant = m_bindingHash.value(name);
126
127
128 if(variant.isNull())
129 return SequenceType::Ptr();
130 else if(variant.userType() == qMetaTypeId<QIODevice *>())
131 return CommonSequenceTypes::ExactlyOneAnyURI;
132 else if(variant.userType() == qMetaTypeId<QXmlQuery>())
133 {
134 const QXmlQuery variableQuery(qVariantValue<QXmlQuery>(variant));
135 return variableQuery.d->expression()->staticType();
136 }
137 else
138 {
139 return makeGenericSequenceType(AtomicValue::qtToXDMType(qVariantValue<QXmlItem>(variant)),
140 Cardinality::exactlyOne());
141 }
142}
143
144Item::Iterator::Ptr VariableLoader::evaluateSequence(const QXmlName name,
145 const DynamicContext::Ptr &context)
146{
147
148 const QVariant &variant = m_bindingHash.value(name);
149 Q_ASSERT_X(!variant.isNull(), Q_FUNC_INFO,
150 "We assume that we have a binding.");
151
152 /* Same code as in the default clause below. */
153 if(variant.userType() == qMetaTypeId<QIODevice *>())
154 return makeSingletonIterator(itemForName(name));
155 else if(variant.userType() == qMetaTypeId<QXmlQuery>())
156 {
157 const QXmlQuery variableQuery(qVariantValue<QXmlQuery>(variant));
158
159 return variableQuery.d->expression()->evaluateSequence(DynamicContext::Ptr(new TemporaryTreesRedirectingContext(variableQuery.d->dynamicContext(), context)));
160 }
161
162 const QVariant v(qVariantValue<QXmlItem>(variant).toAtomicValue());
163
164 switch(v.type())
165 {
166 case QVariant::StringList:
167 return Item::Iterator::Ptr(new StringListIterator(v.toStringList()));
168 case QVariant::List:
169 return Item::Iterator::Ptr(new VariantListIterator(v.toList()));
170 default:
171 return makeSingletonIterator(itemForName(name));
172 }
173}
174
175Item VariableLoader::itemForName(const QXmlName &name) const
176{
177 const QVariant &variant = m_bindingHash.value(name);
178
179 if(variant.userType() == qMetaTypeId<QIODevice *>())
180 return Item(AnyURI::fromValue(QLatin1String("tag:trolltech.com,2007:QtXmlPatterns:QIODeviceVariable:") + m_namePool->stringForLocalName(name.localName())));
181
182 const QXmlItem item(qVariantValue<QXmlItem>(variant));
183
184 if(item.isNode())
185 return Item::fromPublic(item);
186 else
187 {
188 const QVariant atomicValue(item.toAtomicValue());
189 /* If the atomicValue is null it means it doesn't exist in m_bindingHash, and therefore it must
190 * be a QIODevice, since Patternist guarantees to only ask for variables that announceExternalVariable()
191 * has accepted. */
192 if(atomicValue.isNull())
193 return Item(AnyURI::fromValue(QLatin1String("tag:trolltech.com,2007:QtXmlPatterns:QIODeviceVariable:") + m_namePool->stringForLocalName(name.localName())));
194 else
195 return AtomicValue::toXDM(atomicValue);
196 }
197}
198
199Item VariableLoader::evaluateSingleton(const QXmlName name,
200 const DynamicContext::Ptr &)
201{
202 return itemForName(name);
203}
204
205bool VariableLoader::isSameType(const QVariant &v1,
206 const QVariant &v2) const
207{
208 /* Are both of type QIODevice *? */
209 if(v1.userType() == qMetaTypeId<QIODevice *>() && v1.userType() == v2.userType())
210 return true;
211
212 /* Ok, we have two QXmlItems. */
213 const QXmlItem i1(qVariantValue<QXmlItem>(v1));
214 const QXmlItem i2(qVariantValue<QXmlItem>(v2));
215
216 if(i1.isNode())
217 {
218 Q_ASSERT(false);
219 return false;
220 }
221 else if(i2.isAtomicValue())
222 return i1.toAtomicValue().type() == i2.toAtomicValue().type();
223 else
224 {
225 /* One is an atomic, the other is a node or they are null. */
226 return false;
227 }
228}
229
230void VariableLoader::removeBinding(const QXmlName &name)
231{
232 m_bindingHash.remove(name);
233}
234
235bool VariableLoader::hasBinding(const QXmlName &name) const
236{
237 return m_bindingHash.contains(name)
238 || (m_previousLoader && m_previousLoader->hasBinding(name));
239}
240
241QVariant VariableLoader::valueFor(const QXmlName &name) const
242{
243 if(m_bindingHash.contains(name))
244 return m_bindingHash.value(name);
245 else if(m_previousLoader)
246 return m_previousLoader->valueFor(name);
247 else
248 return QVariant();
249}
250
251void VariableLoader::addBinding(const QXmlName &name,
252 const QVariant &value)
253{
254 m_bindingHash.insert(name, value);
255}
256
257bool VariableLoader::invalidationRequired(const QXmlName &name,
258 const QVariant &variant) const
259{
260 return hasBinding(name) && !isSameType(valueFor(name), variant);
261}
262
263QT_END_NAMESPACE
264
Note: See TracBrowser for help on using the repository browser.