All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.saxon.expr.instruct.LocalParam Maven / Gradle / Ivy

There is a newer version: 10.5
Show newest version
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2013 Saxonica Limited.
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

package net.sf.saxon.expr.instruct;

import net.sf.saxon.expr.Expression;
import net.sf.saxon.expr.MonoIterator;
import net.sf.saxon.expr.PairIterator;
import net.sf.saxon.expr.XPathContext;
import net.sf.saxon.expr.parser.ExpressionTool;
import net.sf.saxon.om.Sequence;
import net.sf.saxon.om.StandardNames;
import net.sf.saxon.trace.ExpressionPresenter;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.value.IntegerValue;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
 * The compiled form of an xsl:param element within a template in an XSLT stylesheet.
 *
 * 

The xsl:param element in XSLT has mandatory attribute name and optional attribute select. It can also * be specified as required="yes" or required="no".

* *

This is used only for parameters to XSLT templates. For function calls, the caller of the function * places supplied arguments onto the callee's stackframe and the callee does not need to do anything. * Global parameters (XQuery external variables) are handled using {@link GlobalParam}.

* *

The LocalParam class is also used to represent parameters with the saxon:iterate instruction

*/ public final class LocalParam extends GeneralVariable { private int parameterId; /*@Nullable*/ private Expression conversion = null; private int conversionEvaluationMode = ExpressionTool.UNDECIDED; /** * Allocate a number which is essentially an alias for the parameter name, * unique within a stylesheet * @param id the parameter id */ public void setParameterId(int id) { parameterId = id; } /** * Get the parameter id, which is essentially an alias for the parameter name, * unique within a stylesheet * @return the parameter id */ public int getParameterId() { return parameterId; } /** * Define a conversion that is to be applied to the supplied parameter value. * @param convertor The expression to be applied. This performs type checking, * and the basic conversions implied by function calling rules, for example * numeric promotion, atomization, and conversion of untyped atomic values to * a required type. The conversion uses the actual parameter value as input, * referencing it using a VariableReference. The argument can be null to indicate * that no conversion is required. */ public void setConversion(/*@Nullable*/ Expression convertor) { conversion = convertor; if (convertor != null) { conversionEvaluationMode = ExpressionTool.eagerEvaluationMode(conversion); } } /** * Get the conversion expression * @return the expression used to convert the value to the required type, * or null if there is none */ /*@Nullable*/ public Expression getConversion() { return conversion; } public int getConversionEvaluationMode() { return conversionEvaluationMode; } /** * Get the name of this instruction for diagnostic and tracing purposes */ public int getInstructionNameCode() { return StandardNames.XSL_PARAM; } /** * Get all the XPath expressions associated with this instruction * (in XSLT terms, the expression present on attributes of the instruction, * as distinct from the child instructions in a sequence construction) */ public Iterator iterateSubExpressions() { if (select != null && conversion != null) { return new PairIterator(select, conversion); } else if (select != null) { return new MonoIterator(select); } else if (conversion != null) { return new MonoIterator(conversion); } else { final List list = Collections.emptyList(); return list.iterator(); } } /** * Replace one subexpression by a replacement subexpression * @param original the original subexpression * @param replacement the replacement subexpression * @return true if the original subexpression is found */ public boolean replaceSubExpression(Expression original, Expression replacement) { boolean found = false; if (select == original) { select = replacement; found = true; } if (conversion == original) { conversion = replacement; found = true; } return found; } /** * Process the local parameter declaration * @param context the dynamic context * @return either null if processing is complete, or a tailcall if one is left outstanding * @throws net.sf.saxon.trans.XPathException if a dynamic error occurs in the evaluation */ public TailCall processLeavingTail(XPathContext context) throws XPathException { int wasSupplied = context.useLocalParameter(parameterId, slotNumber, isTunnelParam()); switch (wasSupplied) { case ParameterSet.SUPPLIED_AND_CHECKED: // No action needed break; case ParameterSet.SUPPLIED: // if a parameter was supplied by the caller, with no type-checking by the caller, // then we may need to convert it to the type required if (conversion != null) { context.setLocalVariable(slotNumber, ExpressionTool.evaluate(conversion, conversionEvaluationMode, context, 10)); // We do an eager evaluation here for safety, because the result of the // type conversion overwrites the slot where the actual supplied parameter // is contained. } break; // don't evaluate the default if a value has been supplied or if it has already been // evaluated by virtue of a forwards reference case ParameterSet.NOT_SUPPLIED: if (isImplicitlyRequiredParam()) { String name = "$" + getVariableQName().getDisplayName(); XPathException e = new XPathException("A value must be supplied for parameter " + name + " because " + "the default value is not a valid instance of the required type"); e.setXPathContext(context); e.setErrorCode("XTDE0610"); throw e; } else if (isRequiredParam()) { String name = "$" + getVariableQName().getDisplayName(); XPathException e = new XPathException("No value supplied for required parameter " + name); e.setXPathContext(context); e.setErrorCode("XTDE0700"); throw e; } context.setLocalVariable(slotNumber, getSelectValue(context)); } return null; } /** * If the variable is bound to an integer, get the minimum and maximum possible values. * Return null if unknown or not applicable */ @Override public IntegerValue[] getIntegerBoundsForVariable() { return null; } /** * Evaluate the variable */ public Sequence evaluateVariable(XPathContext c) { return c.evaluateLocalVariable(slotNumber); } /** * Diagnostic print of expression structure. The abstract expression tree * is written to the supplied output destination. */ public void explain(ExpressionPresenter out) { out.startElement("param"); out.emitAttribute("name", variableQName.getDisplayName()); if (select != null) { select.explain(out); } if (conversion != null) { Expression exp = conversion; out.startElement("conversion"); exp.explain(out); out.endElement(); } out.endElement(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy