001: package net.sf.saxon.instruct;
002:
003: import net.sf.saxon.Controller;
004: import net.sf.saxon.Configuration;
005: import net.sf.saxon.expr.ErrorExpression;
006: import net.sf.saxon.expr.XPathContext;
007: import net.sf.saxon.om.ValueRepresentation;
008: import net.sf.saxon.style.StandardNames;
009: import net.sf.saxon.trans.DynamicError;
010: import net.sf.saxon.trans.XPathException;
011:
012: /**
013: * The compiled form of a global xsl:param element in the stylesheet or an
014: * external variable declared in the prolog of a Query. <br>
015: * The xsl:param element in XSLT has mandatory attribute name and optional attribute select. It can also
016: * be specified as required="yes" or required="no". In standard XQuery external variables are always required,
017: * and no default value can be specified; but Saxon provides an extension pragma that allows a query
018: * to specify a default.
019: */
020:
021: public final class GlobalParam extends GlobalVariable {
022:
023: /**
024: * Get the name of this instruction for diagnostic and tracing purposes
025: */
026:
027: public int getInstructionNameCode() {
028: return StandardNames.XSL_PARAM;
029: }
030:
031: /**
032: * Evaluate the variable
033: */
034:
035: public ValueRepresentation evaluateVariable(XPathContext context)
036: throws XPathException {
037: Controller controller = context.getController();
038: Bindery b = controller.getBindery();
039: boolean wasSupplied = b.useGlobalParameter(
040: getVariableFingerprint(), this , context);
041:
042: ValueRepresentation val = b.getGlobalVariableValue(this );
043: if (wasSupplied || val != null) {
044: return val;
045: } else {
046: if (isRequiredParam()) {
047: DynamicError e = new DynamicError(
048: "No value supplied for required parameter $"
049: + context.getNamePool().getDisplayName(
050: getVariableFingerprint()));
051: e.setXPathContext(context);
052: e.setLocator(getSourceLocator());
053: e.setErrorCode("XTDE0050");
054: throw e;
055: }
056:
057: // This is the first reference to a global variable; try to evaluate it now.
058: // But first set a flag to stop looping. This flag is set in the Bindery because
059: // the VariableReference itself can be used by multiple threads simultaneously
060:
061: try {
062: b.setExecuting(this , true);
063: ValueRepresentation value = getSelectValue(context);
064: b.defineGlobalVariable(this , value);
065: b.setExecuting(this , false);
066: return value;
067:
068: } catch (XPathException err) {
069: b.setExecuting(this , false);
070: if (err instanceof XPathException.Circularity) {
071: DynamicError e = new DynamicError(
072: "Circular definition of parameter "
073: + getVariableName());
074: e.setXPathContext(context);
075: int lang = context.getController().getExecutable()
076: .getHostLanguage();
077: e
078: .setErrorCode(lang == Configuration.XQUERY ? "XQST0054"
079: : "XTDE0640");
080: // Detect it more quickly the next time (in a pattern, the error is recoverable)
081: select = new ErrorExpression(e);
082: throw e;
083: } else {
084: throw err;
085: }
086: }
087: }
088: }
089: }
090:
091: //
092: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
093: // you may not use this file except in compliance with the License. You may obtain a copy of the
094: // License at http://www.mozilla.org/MPL/
095: //
096: // Software distributed under the License is distributed on an "AS IS" basis,
097: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
098: // See the License for the specific language governing rights and limitations under the License.
099: //
100: // The Original Code is: all this file.
101: //
102: // The Initial Developer of the Original Code is Michael H. Kay.
103: //
104: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
105: //
106: // Contributor(s): none.
107: //
|