/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** 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 #include "qaxisstep_p.h" #include "qcommonsequencetypes_p.h" #include "qcommonvalues_p.h" #include "qitemmappingiterator_p.h" #include "qsequencemappingiterator_p.h" #include "qpatternistlocale_p.h" #include "qapplytemplate_p.h" QT_BEGIN_NAMESPACE using namespace QPatternist; ApplyTemplate::ApplyTemplate(const TemplateMode::Ptr &mode, const WithParam::Hash &withParams, const TemplateMode::Ptr &defaultMode) : TemplateInvoker(withParams) , m_mode(mode) , m_defaultMode(defaultMode) { Q_ASSERT_X(m_mode || m_defaultMode, Q_FUNC_INFO, "Either a mode, or the default mode must be supplied."); } Item ApplyTemplate::mapToItem(const QXmlNodeModelIndex &node, const DynamicContext::Ptr &) const { return Item(node); } Item::Iterator::Ptr ApplyTemplate::mapToSequence(const Item &item, const DynamicContext::Ptr &context) const { Q_UNUSED(item); return evaluateSequence(context); } TemplateMode::Ptr ApplyTemplate::effectiveMode(const DynamicContext::Ptr &context) const { if(m_mode) return m_mode; else { const TemplateMode::Ptr currentMode(context->currentTemplateMode()); if(currentMode) return currentMode; else return m_defaultMode; } } Template::Ptr ApplyTemplate::findTemplate(const DynamicContext::Ptr &context, const TemplateMode::Ptr &templateMode) const { const int count = templateMode->templatePatterns.count(); Template::Ptr result; /* It's redundant to initialize these values, but it suppresses false * positives with GCC. */ PatternPriority priority = 0; TemplatePattern::ID id = -1; /* Possible optimization: detecting ambiguous rule matches could be forked off to a * low prioirity thread. */ for(int i = 0; i < count; ++i) { const TemplatePattern::Ptr &candidate = templateMode->templatePatterns.at(i); if(candidate->matchPattern()->evaluateEBV(context)) { if(result) { if( candidate->id() != id && candidate->priority() == priority && candidate->templateTarget()->importPrecedence == result->importPrecedence) { context->error(QtXmlPatterns::tr("Ambiguous rule match."), ReportContext::XTRE0540, this); } else break; } else { result = candidate->templateTarget(); priority = candidate->priority(); id = candidate->id(); } } } return result; } Item::Iterator::Ptr ApplyTemplate::evaluateSequence(const DynamicContext::Ptr &context) const { const TemplateMode::Ptr templateMode(effectiveMode(context)); const Template::Ptr &templateMatch = findTemplate(context, templateMode); if(templateMatch) return templateMatch->body->evaluateSequence(templateMatch->createContext(this, context, false)); else { /* None of our templates matched. Proceed with a built-in. */ const Item current(context->contextItem()); // TODO it can be an atomic value? const QXmlNodeModelIndex::NodeKind kind(current.asNode().kind()); if(kind == QXmlNodeModelIndex::Element || kind == QXmlNodeModelIndex::Document) { pDebug() << "No template match, using builtin template for element() | document-node()"; const Item::Iterator::Ptr focusIterator(makeItemMappingIterator(ConstPtr(this), current.asNode().iterate(QXmlNodeModelIndex::AxisChild), context)); const DynamicContext::Ptr focus(context->createFocus()); focus->setFocusIterator(focusIterator); return makeSequenceMappingIterator(ConstPtr(this), focusIterator, focus); } return CommonValues::emptyIterator; } } Expression::Ptr ApplyTemplate::compress(const StaticContext::Ptr &context) { /* If we have a mode, we will never need the default mode. */ if(m_mode) m_defaultMode.reset(); return TemplateInvoker::compress(context); } SequenceType::Ptr ApplyTemplate::staticType() const { return CommonSequenceTypes::ZeroOrMoreItems; } ExpressionVisitorResult::Ptr ApplyTemplate::accept(const ExpressionVisitor::Ptr &visitor) const { return visitor->visit(this); } Expression::Properties ApplyTemplate::properties() const { return RequiresFocus | DisableElimination; } bool ApplyTemplate::configureRecursion(const CallTargetDescription::Ptr &sign) { Q_ASSERT_X(false, Q_FUNC_INFO, "We're not expected to be called."); Q_UNUSED(sign); return false; } Expression::Ptr ApplyTemplate::body() const { Q_ASSERT_X(false, Q_FUNC_INFO, "We're not expected to be called."); return Expression::Ptr(); } CallTargetDescription::Ptr ApplyTemplate::callTargetDescription() const { Q_ASSERT_X(false, Q_FUNC_INFO, "We're not expected to be called."); return CallTargetDescription::Ptr(); } QT_END_NAMESPACE