001: package net.sf.saxon.style;
002:
003: import net.sf.saxon.expr.ComputedExpression;
004: import net.sf.saxon.expr.Expression;
005: import net.sf.saxon.expr.ExpressionTool;
006: import net.sf.saxon.expr.StaticProperty;
007: import net.sf.saxon.instruct.Executable;
008: import net.sf.saxon.instruct.GeneralVariable;
009: import net.sf.saxon.instruct.GlobalVariable;
010: import net.sf.saxon.instruct.LocalVariable;
011: import net.sf.saxon.pattern.NodeKindTest;
012: import net.sf.saxon.trans.XPathException;
013: import net.sf.saxon.value.EmptySequence;
014: import net.sf.saxon.value.SequenceType;
015: import net.sf.saxon.type.TypeHierarchy;
016:
017: /**
018: * Handler for xsl:variable elements in stylesheet. <br>
019: * The xsl:variable element has mandatory attribute name and optional attribute select
020: */
021:
022: public class XSLVariable extends XSLVariableDeclaration {
023:
024: private int state = 0;
025:
026: // 0 = before prepareAttributes()
027: // 1 = during prepareAttributes()
028: // 2 = after prepareAttributes()
029:
030: public void prepareAttributes() throws XPathException {
031: if (state == 2)
032: return;
033: if (state == 1) {
034: compileError("Circular reference to variable", "XTDE0640");
035: }
036: state = 1;
037: //System.err.println("Prepare attributes of $" + getVariableName());
038: super .prepareAttributes();
039: state = 2;
040: }
041:
042: /**
043: * Determine whether this node is an instruction.
044: * @return true - it is an instruction (well, it can be, anyway)
045: */
046:
047: public boolean isInstruction() {
048: return true;
049: }
050:
051: /**
052: * Get the static type of the variable. This is the declared type, unless the value
053: * is statically known and constant, in which case it is the actual type of the value.
054: */
055:
056: public SequenceType getRequiredType() {
057: // System.err.println("Get required type of $" + getVariableName());
058: final TypeHierarchy th = getNamePool().getTypeHierarchy();
059: SequenceType defaultType = (requiredType == null ? SequenceType.ANY_SEQUENCE
060: : requiredType);
061: if (assignable) {
062: return defaultType;
063: } else if (requiredType != null) {
064: return requiredType;
065: } else if (select != null) {
066: if (select instanceof EmptySequence) {
067: // returning Type.EMPTY gives problems with static type checking
068: return defaultType;
069: } else {
070: try {
071: // try to infer the type from the select expression
072: return SequenceType.makeSequenceType(select
073: .getItemType(th), select.getCardinality());
074: } catch (Exception err) {
075: // this may fail because the select expression references a variable or function
076: // whose type is not yet known, because of forwards (perhaps recursive) references.
077: return defaultType;
078: }
079: }
080: } else if (hasChildNodes()) {
081: return SequenceType.makeSequenceType(NodeKindTest.DOCUMENT,
082: StaticProperty.EXACTLY_ONE);
083: } else {
084: // no select attribute or content: value is an empty string
085: return SequenceType.SINGLE_STRING;
086: }
087: }
088:
089: /**
090: * Compile: used only for global variables.
091: * This method ensures space is available for local variables declared within
092: * this global variable
093: */
094:
095: public Expression compile(Executable exec) throws XPathException {
096:
097: if (references.size() == 0 && !assignable) {
098: redundant = true;
099: }
100:
101: if (!redundant) {
102: GeneralVariable inst;
103: if (global) {
104: inst = new GlobalVariable();
105: ((GlobalVariable) inst).setExecutable(getExecutable());
106: if (select instanceof ComputedExpression) {
107: ((ComputedExpression) select)
108: .setParentExpression(inst);
109: }
110: initializeInstruction(exec, inst);
111: inst.setVariableName(getVariableName());
112: inst.setSlotNumber(getSlotNumber());
113: inst.setRequiredType(getRequiredType());
114: ExpressionTool.makeParentReferences(inst);
115: fixupBinding(inst);
116: inst.setParentExpression(null);
117: return inst;
118: } else {
119: throw new AssertionError(
120: "Local variable found when compiling a global variable");
121: }
122: }
123:
124: return null;
125: }
126:
127: public Expression compileLocalVariable(Executable exec)
128: throws XPathException {
129:
130: if (references.size() == 0 && !assignable) {
131: redundant = true;
132: }
133:
134: if (!redundant) {
135: GeneralVariable inst;
136: if (global) {
137: throw new AssertionError(
138: "Global variable found when compiling local variable");
139: // inst = new GlobalVariable();
140: // ((GlobalVariable)inst).setExecutable(getExecutable());
141: // if (select instanceof ComputedExpression) {
142: // ((ComputedExpression)select).setParentExpression(inst);
143: // }
144: // initializeInstruction(exec, inst);
145: // inst.setVariableName(getVariableName());
146: // inst.setSlotNumber(getSlotNumber());
147: // inst.setRequiredType(getRequiredType());
148: // ExpressionTool.makeParentReferences(inst);
149: // fixupBinding(inst);
150: // return inst;
151: } else {
152: inst = new LocalVariable();
153: if (select instanceof ComputedExpression) {
154: ((ComputedExpression) select)
155: .setParentExpression(inst);
156: }
157: initializeInstruction(exec, inst);
158: inst.setVariableName(getVariableName());
159: inst.setRequiredType(getRequiredType());
160: ExpressionTool.makeParentReferences(inst);
161: return inst;
162: }
163: }
164:
165: return null;
166: }
167:
168: }
169:
170: //
171: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
172: // you may not use this file except in compliance with the License. You may obtain a copy of the
173: // License at http://www.mozilla.org/MPL/
174: //
175: // Software distributed under the License is distributed on an "AS IS" basis,
176: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
177: // See the License for the specific language governing rights and limitations under the License.
178: //
179: // The Original Code is: all this file.
180: //
181: // The Initial Developer of the Original Code is Michael H. Kay.
182: //
183: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
184: //
185: // Contributor(s): none.
186: //
|