001: package net.sf.saxon.style;
002:
003: import net.sf.saxon.expr.*;
004: import net.sf.saxon.instruct.SlotManager;
005: import net.sf.saxon.instruct.GeneralVariable;
006: import net.sf.saxon.trans.XPathException;
007: import net.sf.saxon.type.TypeHierarchy;
008: import net.sf.saxon.value.SequenceType;
009: import net.sf.saxon.value.Value;
010:
011: import java.util.ArrayList;
012: import java.util.Iterator;
013: import java.util.List;
014:
015: /**
016: * Generic class for xsl:variable and xsl:param elements. <br>
017: */
018:
019: public abstract class XSLVariableDeclaration extends XSLGeneralVariable
020: implements VariableDeclaration, StylesheetProcedure {
021:
022: // The slot number for the variable is allocated at this level (a) for global variables, and
023: // (b) for local parameters. For local variables, slot numbers are allocated only after an entire
024: // template or function has been compiled.
025:
026: private int slotNumber = -9876; // initial value designed solely to show up when debugging
027:
028: // List of VariableReference objects that reference this XSLVariableDeclaration
029: protected List references = new ArrayList(10);
030:
031: /**
032: * Get the SlotManager associated with this stylesheet construct. The SlotManager contains the
033: * information needed to manage the local stack frames used by run-time instances of the code.
034: * @return the associated SlotManager object
035: */
036:
037: public SlotManager getSlotManager() {
038: return slotManager;
039: }
040:
041: public int getSlotNumber() {
042: return slotNumber;
043: }
044:
045: public void setSlotNumber(int slot) {
046: slotNumber = slot;
047: }
048:
049: /**
050: * Get the static type of the variable.
051: */
052:
053: public abstract SequenceType getRequiredType();
054:
055: /**
056: * Method called by VariableReference to register the variable reference for
057: * subsequent fixup
058: */
059:
060: public void registerReference(BindingReference ref) {
061: references.add(ref);
062: }
063:
064: /**
065: * Get the list of references to this variable or parameter. The items in the list are
066: * of class BindingReference.
067: */
068:
069: public List getReferences() {
070: return references;
071: }
072:
073: /**
074: * Determine whether this node is an instruction.
075: * @return true - it is an instruction (well, it can be, anyway)
076: */
077:
078: public boolean isInstruction() {
079: return true;
080: }
081:
082: /**
083: * Get the list of references
084: */
085:
086: public List getReferenceList() {
087: return references;
088: }
089:
090: /**
091: * Notify all references to this variable of the data type
092: */
093:
094: public void fixupReferences() throws XPathException {
095: final SequenceType type = getRequiredType();
096: final TypeHierarchy th = getNamePool().getTypeHierarchy();
097: final Iterator iter = references.iterator();
098: while (iter.hasNext()) {
099: Value constantValue = null;
100: int properties = 0;
101: if (this instanceof XSLVariable && !isAssignable()) {
102: if (select instanceof Value) {
103: // we can't rely on the constant value because it hasn't yet been type-checked,
104: // which could change it (eg by numeric promotion). Rather than attempt all the type-checking
105: // now, we do a quick check. See test bug64
106: int relation = th.relationship(select
107: .getItemType(th), type.getPrimaryType());
108: if (relation == TypeHierarchy.SAME_TYPE
109: || relation == TypeHierarchy.SUBSUMED_BY) {
110: constantValue = (Value) select;
111: }
112: }
113: if (select != null) {
114: properties = select.getSpecialProperties();
115: }
116: }
117: ((BindingReference) iter.next()).setStaticType(type,
118: constantValue, properties);
119: }
120: super .fixupReferences();
121: }
122:
123: /**
124: * Check that the variable is not already declared, and allocate a slot number
125: */
126:
127: public void validate() throws XPathException {
128: super .validate();
129: if (global) {
130: if (!redundant) {
131: slotNumber = getPrincipalStylesheet()
132: .allocateGlobalSlot(getVariableFingerprint());
133: }
134: } else {
135: checkWithinTemplate();
136: }
137: }
138:
139: /**
140: * Notify all variable references of the Binding instruction
141: */
142:
143: protected void fixupBinding(Binding binding) {
144: Iterator iter = references.iterator();
145: while (iter.hasNext()) {
146: ((BindingReference) iter.next()).fixup(binding);
147: }
148: }
149:
150: protected void setReferenceCount(GeneralVariable var) {
151: int referenceCount = RangeVariableDeclaration
152: .getReferenceCount(references, var, getStaticContext(),
153: false);
154: if (referenceCount < 10) {
155: // allow for the fact that the references may be in functions that are executed repeatedly
156: referenceCount = 10;
157: }
158: var.setReferenceCount(referenceCount);
159: }
160:
161: }
162:
163: //
164: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
165: // you may not use this file except in compliance with the License. You may obtain a copy of the
166: // License at http://www.mozilla.org/MPL/
167: //
168: // Software distributed under the License is distributed on an "AS IS" basis,
169: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
170: // See the License for the specific language governing rights and limitations under the License.
171: //
172: // The Original Code is: all this file.
173: //
174: // The Initial Developer of the Original Code is Michael H. Kay.
175: //
176: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
177: //
178: // Contributor(s): none.
179: //
|