blob: 93b193f23b197af5ba3f4b9c6b5428c9976fe220 [file] [log] [blame]
/****************************************************************************
**
** 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$
** GNU Lesser General Public License Usage
** 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.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
#ifndef QXMLQUERY_P_H
#define QXMLQUERY_P_H
#include <QAbstractMessageHandler>
#include <QAbstractUriResolver>
#include <QPointer>
#include <QSourceLocation>
#include <QUrl>
#include <QVariant>
#include <QXmlName>
#include <QXmlNamePool>
#include <QXmlQuery>
#include "qacceltreebuilder_p.h"
#include "qacceltreeresourceloader_p.h"
#include "qcoloringmessagehandler_p.h"
#include "qcommonsequencetypes_p.h"
#include "qexpressionfactory_p.h"
#include "qfocus_p.h"
#include "qfunctionfactorycollection_p.h"
#include "qgenericdynamiccontext_p.h"
#include "qgenericstaticcontext_p.h"
#include "qnamepool_p.h"
#include "qnetworkaccessdelegator_p.h"
#include "qreferencecountedvalue_p.h"
#include "qresourcedelegator_p.h"
#include "qstaticfocuscontext_p.h"
#include "quriloader_p.h"
#include "qvariableloader_p.h"
QT_BEGIN_NAMESPACE
class QXmlQueryPrivate
{
public:
inline QXmlQueryPrivate(const QXmlNamePool &np = QXmlNamePool()) : namePool(np)
, messageHandler(0)
, uriResolver(0)
, queryLanguage(QXmlQuery::XQuery10)
, m_networkAccessDelegator(new QPatternist::NetworkAccessDelegator(0, 0))
{
m_networkAccessDelegator->m_variableURIManager = new QPatternist::URILoader(ownerObject(), namePool.d, variableLoader());
}
void detach()
{
if(m_variableLoader)
m_variableLoader = QPatternist::VariableLoader::Ptr(new QPatternist::VariableLoader(namePool.d, m_variableLoader));
delete m_networkAccessDelegator->m_variableURIManager;
m_networkAccessDelegator->m_variableURIManager = new QPatternist::URILoader(ownerObject(), namePool.d, m_variableLoader);
if(m_resourceLoader)
{
const QPatternist::AccelTreeResourceLoader::Ptr nev(new QPatternist::AccelTreeResourceLoader(namePool.d,
m_networkAccessDelegator));
m_resourceLoader = QPatternist::ResourceLoader::Ptr(new QPatternist::ResourceDelegator(m_resourceLoader->deviceURIs(),
m_resourceLoader,
nev));
}
}
bool isValid()
{
return expression();
}
inline void recompileRequired()
{
m_expr.reset();
}
inline QPatternist::VariableLoader::Ptr variableLoader()
{
if(!m_variableLoader)
m_variableLoader = QPatternist::VariableLoader::Ptr(new QPatternist::VariableLoader(namePool.d));
return m_variableLoader;
}
inline QPatternist::GenericStaticContext::Ptr staticContext()
{
if(m_staticContext && m_expr)
return m_staticContext;
/* Else, re-create the staticContext. */
if(!messageHandler)
messageHandler = new QPatternist::ColoringMessageHandler(ownerObject());
if(!m_functionFactory)
{
if(queryLanguage == QXmlQuery::XSLT20)
m_functionFactory = QPatternist::FunctionFactoryCollection::xslt20Factory(namePool.d);
else
m_functionFactory = QPatternist::FunctionFactoryCollection::xpath20Factory(namePool.d);
}
const QPatternist::GenericStaticContext::Ptr genericStaticContext(new QPatternist::GenericStaticContext(namePool.d,
messageHandler,
queryURI,
m_functionFactory,
queryLanguage));
genericStaticContext->setResourceLoader(resourceLoader());
genericStaticContext->setExternalVariableLoader(variableLoader());
m_staticContext = genericStaticContext;
if(!contextItem.isNull())
m_staticContext = QPatternist::StaticContext::Ptr(new QPatternist::StaticFocusContext(QPatternist::AtomicValue::qtToXDMType(contextItem), m_staticContext));
else if( queryLanguage == QXmlQuery::XmlSchema11IdentityConstraintField
|| queryLanguage == QXmlQuery::XmlSchema11IdentityConstraintSelector
|| queryLanguage == QXmlQuery::XPath20)
m_staticContext = QPatternist::StaticContext::Ptr(new QPatternist::StaticFocusContext(QPatternist::BuiltinTypes::node, m_staticContext));
for (int i = 0; i < m_additionalNamespaceBindings.count(); ++i) {
m_staticContext->namespaceBindings()->addBinding(m_additionalNamespaceBindings.at(i));
}
return m_staticContext;
}
inline QPatternist::DynamicContext::Ptr dynamicContext(QAbstractXmlReceiver *const callback = 0)
{
const QPatternist::StaticContext::Ptr statContext(staticContext());
Q_ASSERT(statContext);
QPatternist::GenericDynamicContext::Ptr dynContext(new QPatternist::GenericDynamicContext(namePool.d, statContext->messageHandler(),
statContext->sourceLocations()));
QPatternist::AutoPtr<QPatternist::NodeBuilder> nodeBuilder(new QPatternist::AccelTreeBuilder<false>(QUrl(), QUrl(), namePool.d,
dynContext.data()));
dynContext->setNodeBuilder(nodeBuilder);
dynContext->setResourceLoader(statContext->resourceLoader());
dynContext->setExternalVariableLoader(statContext->externalVariableLoader());
dynContext->setUriResolver(uriResolver);
if(callback)
dynContext->setOutputReceiver(callback);
if(contextItem.isNull())
return dynContext;
else
{
QPatternist::DynamicContext::Ptr focus(new QPatternist::Focus(dynContext));
QPatternist::Item::Iterator::Ptr it(QPatternist::makeSingletonIterator(QPatternist::Item::fromPublic(contextItem)));
it->next();
focus->setFocusIterator(it);
return focus;
}
}
inline QPatternist::AccelTreeResourceLoader::Ptr resourceLoader()
{
if(!m_resourceLoader)
m_resourceLoader = (new QPatternist::AccelTreeResourceLoader(namePool.d, m_networkAccessDelegator));
return m_resourceLoader;
}
void setRequiredType(const QPatternist::SequenceType::Ptr &seqType)
{
Q_ASSERT(seqType);
if(!m_requiredType || m_requiredType->is(seqType))
return;
m_requiredType = seqType;
m_staticContext.reset();
}
QPatternist::SequenceType::Ptr requiredType()
{
if(m_requiredType)
return m_requiredType;
else
{
m_requiredType = QPatternist::CommonSequenceTypes::ZeroOrMoreItems;
return m_requiredType;
}
}
QPatternist::Expression::Ptr expression(QIODevice *const queryDevice = 0)
{
if(m_expr && !queryDevice)
return m_expr;
/* If we need to update, but we don't have any source code, we can
* never create an Expression. */
if(!queryDevice)
return QPatternist::Expression::Ptr();
try
{
/* The static context has source locations, and they need to be
* updated to the new query. */
m_staticContext.reset();
if(!m_expressionFactory)
m_expressionFactory = QPatternist::ExpressionFactory::Ptr(new QPatternist::ExpressionFactory());
m_expr = m_expressionFactory->createExpression(queryDevice, staticContext(),
queryLanguage,
requiredType(),
queryURI,
initialTemplateName);
}
catch(const QPatternist::Exception)
{
m_expr.reset();
/* We don't call m_staticContext.reset() because it shouldn't be
* necessary, since m_staticContext is changed when the expression
* is changed. */
}
return m_expr;
}
inline void addAdditionalNamespaceBinding(const QXmlName &binding)
{
m_additionalNamespaceBindings.append(binding);
}
QXmlNamePool namePool;
QPointer<QAbstractMessageHandler> messageHandler;
/**
* Must be absolute and valid.
*/
QUrl queryURI;
const QAbstractUriResolver * uriResolver;
QXmlItem contextItem;
QXmlName initialTemplateName;
inline void setExpressionFactory(const QPatternist::ExpressionFactory::Ptr &expr)
{
m_expressionFactory = expr;
}
QXmlQuery::QueryLanguage queryLanguage;
QPointer<QNetworkAccessManager> userNetworkManager;
inline QObject *ownerObject()
{
if(!m_owner)
m_owner = new QPatternist::ReferenceCountedValue<QObject>(new QObject());
return m_owner->value;
}
QPatternist::ExpressionFactory::Ptr m_expressionFactory;
QPatternist::StaticContext::Ptr m_staticContext;
QPatternist::VariableLoader::Ptr m_variableLoader;
QPatternist::DeviceResourceLoader::Ptr m_resourceLoader;
/**
* This is the AST for the query.
*/
QPatternist::Expression::Ptr m_expr;
QPatternist::ReferenceCountedValue<QObject>::Ptr m_owner;
/**
* This is our effective network manager, that we end up using. The one the
* user sets is userNetworkManager.
*/
QPatternist::SequenceType::Ptr m_requiredType;
QPatternist::FunctionFactory::Ptr m_functionFactory;
QPatternist::NetworkAccessDelegator::Ptr m_networkAccessDelegator;
QList<QXmlName> m_additionalNamespaceBindings;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif