diff options
author | Qt by Nokia <qt-info@nokia.com> | 2011-04-27 12:05:43 +0200 |
---|---|---|
committer | axis <qt-info@nokia.com> | 2011-04-27 12:05:43 +0200 |
commit | e1b2c9deb5943faae2b29be6a5c006f75bb73f06 (patch) | |
tree | fc79e45367c0a8fc71185e9afc33f7503a58653c /src/xmlpatterns/api/qvariableloader.cpp | |
download | qtxmlpatterns-e1b2c9deb5943faae2b29be6a5c006f75bb73f06.tar.gz |
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you
want to look at revision history older than this, please refer to the
Qt Git wiki for how to use Git history grafting. At the time of
writing, this wiki is located here:
http://qt.gitorious.org/qt/pages/GitIntroductionWithQt
If you have already performed the grafting and you don't see any
history beyond this commit, try running "git log" with the "--follow"
argument.
Branched from the monolithic repo, Qt master branch, at commit
896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'src/xmlpatterns/api/qvariableloader.cpp')
-rw-r--r-- | src/xmlpatterns/api/qvariableloader.cpp | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/src/xmlpatterns/api/qvariableloader.cpp b/src/xmlpatterns/api/qvariableloader.cpp new file mode 100644 index 0000000..9909508 --- /dev/null +++ b/src/xmlpatterns/api/qvariableloader.cpp @@ -0,0 +1,264 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtXmlPatterns module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QVariant> +#include <QStringList> + +#include "qanyuri_p.h" +#include "qatomicstring_p.h" +#include "qbuiltintypes_p.h" +#include "qcommonsequencetypes_p.h" +#include "qgenericsequencetype_p.h" +#include "qinteger_p.h" +#include "qitem_p.h" +#include "qsequencetype_p.h" +#include "qvariableloader_p.h" +#include "qxmlquery_p.h" + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + + class VariantListIterator : public ListIteratorPlatform<QVariant, Item, VariantListIterator> + { + public: + inline VariantListIterator(const QVariantList &list) : ListIteratorPlatform<QVariant, Item, VariantListIterator>(list) + { + } + + private: + friend class ListIteratorPlatform<QVariant, Item, VariantListIterator>; + + inline Item inputToOutputItem(const QVariant &inputType) const + { + return AtomicValue::toXDM(inputType); + } + }; + + class StringListIterator : public ListIteratorPlatform<QString, Item, StringListIterator> + { + public: + inline StringListIterator(const QStringList &list) : ListIteratorPlatform<QString, Item, StringListIterator>(list) + { + } + + private: + friend class ListIteratorPlatform<QString, Item, StringListIterator>; + + static inline Item inputToOutputItem(const QString &inputType) + { + return AtomicString::fromValue(inputType); + } + }; + + /** + * Takes two DynamicContext instances, and redirects the storage of temporary trees + * to one of them. + * + * @since 4.5 + */ + class TemporaryTreesRedirectingContext : public DelegatingDynamicContext + { + public: + TemporaryTreesRedirectingContext(const DynamicContext::Ptr &other, + const DynamicContext::Ptr &modelStorage) : DelegatingDynamicContext(other) + , m_modelStorage(modelStorage) + { + Q_ASSERT(m_modelStorage); + } + + virtual void addNodeModel(const QAbstractXmlNodeModel::Ptr &nodeModel) + { + m_modelStorage->addNodeModel(nodeModel); + } + + private: + const DynamicContext::Ptr m_modelStorage; + }; +} + +using namespace QPatternist; + +SequenceType::Ptr VariableLoader::announceExternalVariable(const QXmlName name, + const SequenceType::Ptr &declaredType) +{ + Q_UNUSED(declaredType); + const QVariant &variant = m_bindingHash.value(name); + + + if(variant.isNull()) + return SequenceType::Ptr(); + else if(variant.userType() == qMetaTypeId<QIODevice *>()) + return CommonSequenceTypes::ExactlyOneAnyURI; + else if(variant.userType() == qMetaTypeId<QXmlQuery>()) + { + const QXmlQuery variableQuery(qvariant_cast<QXmlQuery>(variant)); + return variableQuery.d->expression()->staticType(); + } + else + { + return makeGenericSequenceType(AtomicValue::qtToXDMType(qvariant_cast<QXmlItem>(variant)), + Cardinality::exactlyOne()); + } +} + +Item::Iterator::Ptr VariableLoader::evaluateSequence(const QXmlName name, + const DynamicContext::Ptr &context) +{ + + const QVariant &variant = m_bindingHash.value(name); + Q_ASSERT_X(!variant.isNull(), Q_FUNC_INFO, + "We assume that we have a binding."); + + /* Same code as in the default clause below. */ + if(variant.userType() == qMetaTypeId<QIODevice *>()) + return makeSingletonIterator(itemForName(name)); + else if(variant.userType() == qMetaTypeId<QXmlQuery>()) + { + const QXmlQuery variableQuery(qvariant_cast<QXmlQuery>(variant)); + + return variableQuery.d->expression()->evaluateSequence(DynamicContext::Ptr(new TemporaryTreesRedirectingContext(variableQuery.d->dynamicContext(), context))); + } + + const QVariant v(qvariant_cast<QXmlItem>(variant).toAtomicValue()); + + switch(v.type()) + { + case QVariant::StringList: + return Item::Iterator::Ptr(new StringListIterator(v.toStringList())); + case QVariant::List: + return Item::Iterator::Ptr(new VariantListIterator(v.toList())); + default: + return makeSingletonIterator(itemForName(name)); + } +} + +Item VariableLoader::itemForName(const QXmlName &name) const +{ + const QVariant &variant = m_bindingHash.value(name); + + if(variant.userType() == qMetaTypeId<QIODevice *>()) + return Item(AnyURI::fromValue(QLatin1String("tag:trolltech.com,2007:QtXmlPatterns:QIODeviceVariable:") + m_namePool->stringForLocalName(name.localName()))); + + const QXmlItem item(qvariant_cast<QXmlItem>(variant)); + + if(item.isNode()) + return Item::fromPublic(item); + else + { + const QVariant atomicValue(item.toAtomicValue()); + /* If the atomicValue is null it means it doesn't exist in m_bindingHash, and therefore it must + * be a QIODevice, since Patternist guarantees to only ask for variables that announceExternalVariable() + * has accepted. */ + if(atomicValue.isNull()) + return Item(AnyURI::fromValue(QLatin1String("tag:trolltech.com,2007:QtXmlPatterns:QIODeviceVariable:") + m_namePool->stringForLocalName(name.localName()))); + else + return AtomicValue::toXDM(atomicValue); + } +} + +Item VariableLoader::evaluateSingleton(const QXmlName name, + const DynamicContext::Ptr &) +{ + return itemForName(name); +} + +bool VariableLoader::isSameType(const QVariant &v1, + const QVariant &v2) const +{ + /* Are both of type QIODevice *? */ + if(v1.userType() == qMetaTypeId<QIODevice *>() && v1.userType() == v2.userType()) + return true; + + /* Ok, we have two QXmlItems. */ + const QXmlItem i1(qvariant_cast<QXmlItem>(v1)); + const QXmlItem i2(qvariant_cast<QXmlItem>(v2)); + + if(i1.isNode()) + { + Q_ASSERT(false); + return false; + } + else if(i2.isAtomicValue()) + return i1.toAtomicValue().type() == i2.toAtomicValue().type(); + else + { + /* One is an atomic, the other is a node or they are null. */ + return false; + } +} + +void VariableLoader::removeBinding(const QXmlName &name) +{ + m_bindingHash.remove(name); +} + +bool VariableLoader::hasBinding(const QXmlName &name) const +{ + return m_bindingHash.contains(name) + || (m_previousLoader && m_previousLoader->hasBinding(name)); +} + +QVariant VariableLoader::valueFor(const QXmlName &name) const +{ + if(m_bindingHash.contains(name)) + return m_bindingHash.value(name); + else if(m_previousLoader) + return m_previousLoader->valueFor(name); + else + return QVariant(); +} + +void VariableLoader::addBinding(const QXmlName &name, + const QVariant &value) +{ + m_bindingHash.insert(name, value); +} + +bool VariableLoader::invalidationRequired(const QXmlName &name, + const QVariant &variant) const +{ + return hasBinding(name) && !isSameType(valueFor(name), variant); +} + +QT_END_NAMESPACE + |