001: package net.sf.saxon.style;
002:
003: import net.sf.saxon.expr.*;
004: import net.sf.saxon.instruct.*;
005: import net.sf.saxon.om.Axis;
006: import net.sf.saxon.om.AxisIterator;
007: import net.sf.saxon.om.NodeInfo;
008: import net.sf.saxon.trans.XPathException;
009: import net.sf.saxon.value.SequenceType;
010: import net.sf.saxon.value.Whitespace;
011:
012: /**
013: * An xsl:param element in the stylesheet. <br>
014: * The xsl:param element has mandatory attribute name and optional attributes
015: * select, required, as, ...
016: */
017:
018: public class XSLParam extends XSLVariableDeclaration {
019:
020: Expression conversion = null;
021:
022: protected boolean allowsValue() {
023: return !(getParent() instanceof XSLFunction);
024: // function parameters cannot take a default value
025: }
026:
027: protected boolean allowsRequired() {
028: return !(getParent() instanceof XSLFunction);
029: // function parameters cannot take the "required" attribute
030: }
031:
032: protected boolean allowsTunnelAttribute() {
033: return true;
034: }
035:
036: public void validate() throws XPathException {
037:
038: NodeInfo parent = getParent();
039: boolean local = (parent instanceof XSLTemplate || parent instanceof XSLFunction);
040: global = (parent instanceof XSLStylesheet);
041:
042: if (!local && !global) {
043: compileError(
044: "xsl:param must be immediately within a template, function or stylesheet",
045: "XTSE0010");
046: }
047:
048: if (!global) {
049: AxisIterator preceding = iterateAxis(Axis.PRECEDING_SIBLING);
050: while (true) {
051: NodeInfo node = (NodeInfo) preceding.next();
052: if (node == null) {
053: break;
054: }
055: if (node instanceof XSLParam) {
056: if (this .getVariableFingerprint() == ((XSLParam) node)
057: .getVariableFingerprint()) {
058: compileError(
059: "The name of the parameter is not unique",
060: "XTSE0580");
061: }
062: } else if (node instanceof StyleElement) {
063: compileError(
064: "xsl:param must be the first element within a template or function",
065: "XTSE0010");
066: } else {
067: // it must be a text node; allow it if all whitespace
068: if (!Whitespace.isWhite(node.getStringValueCS())) {
069: compileError(
070: "xsl:param must not be preceded by text",
071: "XTSE0010");
072: }
073: }
074: }
075:
076: SlotManager p = getContainingSlotManager();
077: if (p == null) {
078: compileError(
079: "Local variable must be declared within a template or function",
080: "XTSE0010");
081: } else {
082: setSlotNumber(p
083: .allocateSlotNumber(getVariableFingerprint()));
084: }
085:
086: }
087:
088: if (requiredParam) {
089: if (select != null) {
090: // NB, we do this test before setting the default select attribute
091: compileError(
092: "The select attribute should be omitted when required='yes'",
093: "XTSE0010");
094: }
095: if (hasChildNodes()) {
096: compileError(
097: "A parameter specifying required='yes' must have empty content",
098: "XTSE0010");
099: }
100: }
101:
102: super .validate();
103: }
104:
105: /**
106: * Compile: this ensures space is available for local variables declared within
107: * this global variable
108: */
109:
110: public Expression compile(Executable exec) throws XPathException {
111:
112: if (getParent() instanceof XSLFunction) {
113: // Do nothing. We did everything necessary while compiling the XSLFunction element.
114: return null;
115: } else {
116: int slot = getSlotNumber();
117: if (requiredType != null) {
118: SuppliedParameterReference pref = new SuppliedParameterReference(
119: slot);
120: pref.setLocationId(staticContext.getLocationMap()
121: .allocateLocationId(getSystemId(),
122: getLineNumber()));
123: RoleLocator role = new RoleLocator(
124: RoleLocator.VARIABLE, getVariableName(), 0,
125: null);
126: role.setSourceLocator(new ExpressionLocation(this ));
127: conversion = TypeChecker.staticTypeCheck(pref,
128: requiredType, false, role, getStaticContext());
129: }
130:
131: GeneralVariable inst;
132: if (global) {
133: inst = new GlobalParam();
134: ((GlobalParam) inst).setExecutable(getExecutable());
135: if (isRequiredParam()) {
136: getExecutable().addRequiredParam(
137: getVariableFingerprint());
138: }
139: if (select instanceof ComputedExpression) {
140: ((ComputedExpression) select)
141: .setParentExpression(inst);
142: }
143: } else {
144: inst = new LocalParam();
145: ((LocalParam) inst).setConversion(conversion);
146: }
147: initializeInstruction(exec, inst);
148: inst.setVariableName(getVariableName());
149: inst.setSlotNumber(slot);
150: inst.setRequiredType(getRequiredType());
151: ExpressionTool.makeParentReferences(inst);
152: fixupBinding(inst);
153: return inst;
154: }
155: }
156:
157: /**
158: * Get the static type of the parameter. This is the declared type, because we cannot know
159: * the actual value in advance.
160: */
161:
162: public SequenceType getRequiredType() {
163: if (requiredType != null) {
164: return requiredType;
165: } else {
166: return SequenceType.ANY_SEQUENCE;
167: }
168: }
169:
170: }
171:
172: //
173: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
174: // you may not use this file except in compliance with the License. You may obtain a copy of the
175: // License at http://www.mozilla.org/MPL/
176: //
177: // Software distributed under the License is distributed on an "AS IS" basis,
178: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
179: // See the License for the specific language governing rights and limitations under the License.
180: //
181: // The Original Code is: all this file.
182: //
183: // The Initial Developer of the Original Code is Michael H. Kay.
184: //
185: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
186: //
187: // Contributor(s): none.
188: //
|