001: package net.sf.saxon.xpath;
002:
003: import net.sf.saxon.expr.Binding;
004: import net.sf.saxon.expr.BindingReference;
005: import net.sf.saxon.expr.VariableDeclaration;
006: import net.sf.saxon.expr.XPathContext;
007: import net.sf.saxon.trans.XPathException;
008: import net.sf.saxon.value.EmptySequence;
009: import net.sf.saxon.value.QNameValue;
010: import net.sf.saxon.value.SequenceType;
011: import net.sf.saxon.value.Value;
012: import net.sf.saxon.om.ValueRepresentation;
013:
014: import javax.xml.namespace.QName;
015: import javax.xml.xpath.XPathVariableResolver;
016:
017: /**
018: * An object representing an XPath variable for use in the JAXP XPath API. The object
019: * is created at compile time when the parser tries to bind a variable reference; the
020: * value is fetched at run-time from the XPathVariableResolver. With this interface,
021: * there is no way of reporting a static error if the variable has not been declared.
022: * <p>
023: * In Saxon terms, this class is both a VariableDeclaration and a Binding. Unlike
024: * a normal VariableDeclaration, it isn't created in advance, but is created on demand
025: * when the parser encounters a variable reference. This actually means that if the
026: * XPath expression contains two references to the same variable, two VariableDeclarations
027: * will be created; however, they will be indistinguishable to the VariableResolver.
028: * Acting as a VariableDeclaration, the object goes through the motions of fixing up
029: * a binding to a variable reference (in practice, of course, there is exactly one
030: * reference to the variable). Acting as a run-time binding, it then evaluates the
031: * variable by calling the XPathVariableResolver supplied by the API caller. If no
032: * XPathVariableResolver was supplied, an error is reported when a variable is encountered;
033: * but if the variable resolver doesn't recognize the variable name, it returns null,
034: * which is treated as an empty sequence.
035: * </p>
036: */
037:
038: public final class JAXPVariable implements VariableDeclaration, Binding {
039:
040: private QNameValue name;
041: private XPathVariableResolver resolver;
042:
043: /**
044: * Private constructor: for use only be the protected factory method make()
045: */
046:
047: public JAXPVariable(QNameValue name, XPathVariableResolver resolver) {
048: this .name = name;
049: this .resolver = resolver;
050: };
051:
052: /**
053: * Indicate whether the binding is local or global. A global binding is one that has a fixed
054: * value for the life of a query or transformation; any other binding is local.
055: */
056:
057: public boolean isGlobal() {
058: return true;
059: }
060:
061: /**
062: * Test whether it is permitted to assign to the variable using the saxon:assign
063: * extension element. This will only be for an XSLT global variable where the extra
064: * attribute saxon:assignable="yes" is present.
065: */
066:
067: public final boolean isAssignable() {
068: return false;
069: }
070:
071: /**
072: * If this is a local variable held on the local stack frame, return the corresponding slot number.
073: * In other cases, return -1.
074: */
075:
076: public int getLocalSlotNumber() {
077: return -1;
078: }
079:
080: /**
081: * Get the name of the variable. Used for diagnostic purposes only.
082: * @return the name of the variable, as a string (containing the raw QName)
083: */
084:
085: public String getVariableName() {
086: return name.getStringValue();
087: }
088:
089: /**
090: * Establish the fingerprint of the name of this variable.
091: * Dummy implementation, not used.
092: * @return -1, always
093: */
094:
095: public int getNameCode() {
096: return -1;
097: }
098:
099: /**
100: * Method called by the XPath expression parser to register a reference to this variable.
101: * This method should not be called by users of the API.
102: */
103:
104: public void registerReference(BindingReference ref) {
105: ref.setStaticType(SequenceType.ANY_SEQUENCE, null, 0);
106: ref.fixup(this );
107: }
108:
109: /**
110: * Get the value of the variable. This method is used by the XPath execution engine
111: * to retrieve the value.
112: * @param context The dynamic evaluation context
113: * @return The value of the variable
114: */
115:
116: public ValueRepresentation evaluateVariable(XPathContext context)
117: throws XPathException {
118: Object value = resolver.resolveVariable((QName) name
119: .makeQName(context.getConfiguration()));
120: if (value == null) {
121: return EmptySequence.getInstance();
122: }
123: return Value.convertJavaObjectToXPath(value,
124: SequenceType.ANY_SEQUENCE, context.getConfiguration());
125: }
126:
127: QName makeQName(QNameValue in) {
128: return new QName(in.getNamespaceURI(), in.getLocalName(), in
129: .getPrefix());
130: }
131: }
132:
133: //
134: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
135: // you may not use this file except in compliance with the License. You may obtain a copy of the
136: // License at http://www.mozilla.org/MPL/
137: //
138: // Software distributed under the License is distributed on an "AS IS" basis,
139: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
140: // See the License for the specific language governing rights and limitations under the License.
141: //
142: // The Original Code is: all this file.
143: //
144: // The Initial Developer of the Original Code is Michael H. Kay
145: //
146: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
147: //
148: // Contributor(s): none.
149: //
|