package client.net.sf.saxon.ce.style; import client.net.sf.saxon.ce.expr.Expression; import client.net.sf.saxon.ce.expr.RoleLocator; import client.net.sf.saxon.ce.expr.SuppliedParameterReference; import client.net.sf.saxon.ce.expr.TypeChecker; import client.net.sf.saxon.ce.expr.instruct.*; import client.net.sf.saxon.ce.om.Axis; import client.net.sf.saxon.ce.tree.iter.AxisIterator; import client.net.sf.saxon.ce.om.NodeInfo; import client.net.sf.saxon.ce.trans.XPathException; import client.net.sf.saxon.ce.value.SequenceType; import client.net.sf.saxon.ce.value.Whitespace; /** * An xsl:param element in the stylesheet. <br> * The xsl:param element has mandatory attribute name and optional attributes * select, required, as, ... */ public class XSLParam extends XSLVariableDeclaration { Expression conversion = null; protected boolean allowsValue() { return !(getParent() instanceof XSLFunction); // function parameters cannot take a default value } protected boolean allowsRequired() { return ((StyleElement)getParent()).mayContainParam("required"); } protected boolean allowsTunnelAttribute() { return true; } public void validate(Declaration decl) throws XPathException { NodeInfo parent = getParent(); global = (parent instanceof XSLStylesheet); if (!((parent instanceof StyleElement) && ((StyleElement)parent).mayContainParam(null))) { compileError("xsl:param must be immediately within a template, function or stylesheet", "XTSE0010"); } if (!global) { AxisIterator preceding = iterateAxis(Axis.PRECEDING_SIBLING); while (true) { NodeInfo node = (NodeInfo)preceding.next(); if (node == null) { break; } if (node instanceof XSLParam) { if (this.getVariableQName().equals(((XSLParam)node).getVariableQName())) { compileError("The name of the parameter is not unique", "XTSE0580"); } } else if (node instanceof StyleElement) { compileError("xsl:param must not be preceded by other instructions", "XTSE0010"); } else { // it must be a text node; allow it if all whitespace if (!Whitespace.isWhite(node.getStringValueCS())) { compileError("xsl:param must not be preceded by text", "XTSE0010"); } } } SlotManager p = getContainingSlotManager(); if (p==null) { compileError("Local variable must be declared within a template or function", "XTSE0010"); } else { setSlotNumber(p.allocateSlotNumber(getVariableQName())); } } if (requiredParam) { if (select != null) { // NB, we do this test before setting the default select attribute compileError("The select attribute should be omitted when required='yes'", "XTSE0010"); } if (hasChildNodes()) { compileError("A parameter specifying required='yes' must have empty content", "XTSE0010"); } } super.validate(decl); } /** * Compile: this ensures space is available for local variables declared within * this global variable */ public Expression compile(Executable exec, Declaration decl) throws XPathException { if (redundant) { return null; } if (getParent() instanceof XSLFunction) { // Do nothing. We did everything necessary while compiling the XSLFunction element. return null; } else { int slot = getSlotNumber(); if (requiredType != null) { SuppliedParameterReference pref = new SuppliedParameterReference(slot); pref.setSourceLocator(this); RoleLocator role = new RoleLocator(RoleLocator.PARAM, getVariableDisplayName(), 0); //role.setSourceLocator(new ExpressionLocation(this)); role.setErrorCode("XTTE0590"); conversion = TypeChecker.staticTypeCheck( pref, requiredType, false, role, makeExpressionVisitor()); } GeneralVariable inst; if (global) { inst = new GlobalParam(); ((GlobalParam)inst).setExecutable(getExecutable()); inst.setContainer(((GlobalParam)inst)); if (isRequiredParam()) { getExecutable().addRequiredParam(getVariableQName()); } if (select != null) { select.setContainer(((GlobalVariable)inst)); } compiledVariable = inst; } else { PrincipalStylesheetModule psm = getPrincipalStylesheetModule(); inst = new LocalParam(); ((LocalParam)inst).setConversion(conversion); ((LocalParam)inst).setParameterId(psm.allocateUniqueParameterNumber(getVariableQName())); } initializeInstruction(exec, decl, inst); inst.setVariableQName(getVariableQName()); inst.setSlotNumber(slot); inst.setRequiredType(getRequiredType()); fixupBinding(inst); compiledVariable = inst; return inst; } } /** * Get the static type of the parameter. This is the declared type, because we cannot know * the actual value in advance. */ public SequenceType getRequiredType() { if (requiredType!=null) { return requiredType; } else { return SequenceType.ANY_SEQUENCE; } } } // 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.