sboag 00/11/09 11:13:52
Modified: java/src/org/apache/xalan/templates ElemParam.java
java/src/org/apache/xalan/transformer TransformerImpl.java
java/src/org/apache/xpath VariableStack.java
XPathContext.java
java/src/org/apache/xpath/compiler Compiler.java
OpCodes.java XPathParser.java
java/src/org/apache/xpath/objects XObject.java
Added: java/src/org/apache/xalan/templates XUnresolvedVariable.java
Log:
Fixed variable problems. Including forward references with globals,
and QNames with variables now work. I don't thing that cyclic
variables are tested for yet.
Revision Changes Path
1.4 +2 -1
xml-xalan/java/src/org/apache/xalan/templates/ElemParam.java
Index: ElemParam.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemParam.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- ElemParam.java 2000/10/30 18:49:54 1.3
+++ ElemParam.java 2000/11/09 19:13:49 1.4
@@ -138,8 +138,9 @@
throws SAXException
{
+ VariableStack vars = transformer.getXPathContext().getVarStack();
Object obj =
-
transformer.getXPathContext().getVarStack().getParamVariable(getName());
+ vars.getParamVariable(transformer.getXPathContext(), getName());
if (null == obj)
{
1.1
xml-xalan/java/src/org/apache/xalan/templates/XUnresolvedVariable.java
Index: XUnresolvedVariable.java
===================================================================
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xalan" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 1999, Lotus
* Development Corporation., http://www.lotus.com. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.xalan.templates;
import org.apache.xpath.XPath;
import org.apache.xpath.XPathContext;
import org.apache.xpath.VariableStack;
import org.apache.xpath.objects.XObject;
import org.apache.xpath.objects.XRTreeFrag;
import org.apache.xpath.objects.XString;
import org.apache.xalan.transformer.TransformerImpl;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Node;
/**
* An instance of this class holds unto a variable until
* it is executed. It is used at this time for global
* variables which must (we think) forward reference.
*/
public class XUnresolvedVariable extends XObject
{
/** The node context for execution. */
private Node m_context;
/** The transformer context for execution. */
private TransformerImpl m_transformer;
/** An index to the point in the variable stack where we should
* begin variable searches for evaluation of expressions.
* This is -1 if m_isTopLevel is false.
**/
private int m_varStackPos = -1;
/** An index into the variable stack where the variable context
* ends, i.e. at the point we should terminate the search.
**/
private int m_varStackContext;
/** true if this variable or parameter is a global. */
private boolean m_isGlobal;
/**
* Create an XUnresolvedVariable, that may be executed at a later time.
* This is primarily used so that forward referencing works with
* global variables. An XUnresolvedVariable is initially pushed
* into the global variable stack, and then replaced with the real
* thing when it is accessed.
*
* @param obj Must be a non-null reference to an ElemVariable.
* @param sourceNode The node context for execution.
* @param transformer The transformer execution context.
* @param varStackPos An index to the point in the variable stack where we
should
* begin variable searches for evaluation of expressions.
* @param varStackContext An index into the variable stack where the
variable context
* ends, i.e. at the point we should terminate the search.
* @param isGlobal true if this is a global variable.
*/
public XUnresolvedVariable(ElemVariable obj, Node sourceNode,
TransformerImpl transformer,
int varStackPos, int varStackContext,
boolean isGlobal)
{
super(obj);
m_context = sourceNode;
m_transformer = transformer;
// For globals, this value will have to be updated once we
// have determined how many global variables have been pushed.
m_varStackPos = varStackPos;
// For globals, this should zero.
m_varStackContext = varStackContext;
m_isGlobal = isGlobal;
}
/**
* For support of literal objects in xpaths.
*
* @param xctxt The XPath execution context.
*
* @return This object.
*
* @throws org.xml.sax.SAXException
*/
public XObject execute(XPathContext xctxt) throws org.xml.sax.SAXException
{
VariableStack vars = xctxt.getVarStack();
// These three statements need to be combined into one operation.
int savedStart = vars.getSearchStart();
vars.setSearchStart(m_varStackPos);
vars.pushContextPosition(m_varStackContext);
ElemVariable velem = (ElemVariable)m_obj;
XObject var = velem.getValue(m_transformer, m_context);
// These two statements need to be combined into one operation.
vars.setSearchStart(savedStart);
vars.popContextPosition();
return var;
}
/**
* Set an index to the point in the variable stack where we should
* begin variable searches for evaluation of expressions.
* This is -1 if m_isTopLevel is false.
*
* @param top A valid value that specifies where in the variable
* stack the search should begin.
*/
public void setVarStackPos(int top)
{
m_varStackPos = top;
}
/**
* Set an index into the variable stack where the variable context
* ends, i.e. at the point we should terminate the search.
*
* @param The point at which the search should terminate, normally
* zero for global variables.
*/
public void setVarStackContext(int bottom)
{
m_varStackContext = bottom;
}
/**
* Tell what kind of class this is.
*
* @return CLASS_UNRESOLVEDVARIABLE
*/
public int getType()
{
return CLASS_UNRESOLVEDVARIABLE;
}
/**
* Given a request type, return the equivalent string.
* For diagnostic purposes.
*
* @return An informational string.
*/
public String getTypeString()
{
return "XUnresolvedVariable (" + object().getClass().getName() + ")";
}
}
1.46 +17 -6
xml-xalan/java/src/org/apache/xalan/transformer/TransformerImpl.java
Index: TransformerImpl.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/transformer/TransformerImpl.java,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -r1.45 -r1.46
--- TransformerImpl.java 2000/11/09 00:00:38 1.45
+++ TransformerImpl.java 2000/11/09 19:13:49 1.46
@@ -86,6 +86,7 @@
import org.apache.xalan.templates.ElemCallTemplate;
import org.apache.xalan.templates.ElemTemplate;
import org.apache.xalan.templates.TemplateList;
+import org.apache.xalan.templates.XUnresolvedVariable;
import org.apache.xalan.trace.TraceManager;
import org.apache.xalan.utils.DOMBuilder;
import org.apache.xalan.utils.NodeVector;
@@ -1346,7 +1347,7 @@
qname = new QName(s1, s2);
try
{
- return varstack.getVariable(qname);
+ return varstack.getVariable(m_xcontext, qname);
}
catch(SAXException se)
{
@@ -1498,23 +1499,33 @@
StylesheetRoot sr = getStylesheet();
Vector vars = sr.getVariablesAndParamsComposed();
+ int startGlobals = vs.size();
int i = vars.size();
while (--i >= 0)
{
ElemVariable v = (ElemVariable) vars.elementAt(i);
- Object val = vs.getVariable(v.getName());
- if (null != val)
+ if (vs.variableIsDeclared(v.getName()))
continue;
- XObject xobj = v.getValue(this, contextNode);
+ // XObject xobj = v.getValue(this, contextNode);
+ XObject xobj = new XUnresolvedVariable(v, contextNode,
+ this, vs.getSearchStartOrTop(), 0, true);
vs.pushVariable(v.getName(), xobj);
vs.markGlobalStackFrame();
}
-
-
vs.markGlobalStackFrame();
+
+ int endGlobals = vs.size();
+ for(i = startGlobals; i < endGlobals; i++)
+ {
+ Arg arg = (Arg)vs.elementAt(i);
+ XUnresolvedVariable uv = (XUnresolvedVariable)arg.getVal();
+ uv.setVarStackPos(endGlobals);
+ }
+
+ vs.pushContextMarker();
}
/**
1.9 +119 -29 xml-xalan/java/src/org/apache/xpath/VariableStack.java
Index: VariableStack.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/VariableStack.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- VariableStack.java 2000/11/08 17:14:52 1.8
+++ VariableStack.java 2000/11/09 19:13:50 1.9
@@ -104,14 +104,21 @@
*/
private IntStack m_contextPositions = new IntStack();
- /** NEEDSDOC Field m_globalStackFrameIndex */
+ /** The top of the globals space. */
private int m_globalStackFrameIndex = -1;
- /** NEEDSDOC */
+ /** Where to start the current search for a variable.
+ * If this is -1, the search should start at the top
+ * of the stack. */
private int m_searchStart = -1;
/**
- * NEEDSDOC
+ * Set where to start the current search for a variable.
+ * If this is -1, the search should start at the top
+ * of the stack.
+ *
+ * @param startPos The position to start the search, or -1
+ * if the search should start from the top.
*/
public void setSearchStart(int startPos)
{
@@ -119,7 +126,12 @@
}
/**
- * NEEDSDOC
+ * Get the position from where the search should start,
+ * which is either the searchStart property, or the top
+ * of the stack if that value is -1.
+ *
+ * @return The position from where the search should start, which
+ * is always greater than or equal to zero.
*/
public int getSearchStartOrTop()
{
@@ -127,7 +139,11 @@
}
/**
- * NEEDSDOC
+ * Get the position to start the search, or -1
+ * if the search should start from the top.
+ *
+ * @return The position to start the search, or -1
+ * if the search should start from the top.
*/
public int getSearchStart()
{
@@ -147,11 +163,10 @@
m_globalStackFrameIndex = this.size();
}
- // Push a context marker onto the stack to let us know when
- // to stop searching for a var.
-
/**
- * NEEDSDOC Method pushContextPosition
+ * Push a context marker onto the contextPositions stack to let us know
when
+ * to stop searching for a var. This operation
+ * usually corresponds to the start of a template.
*/
public void pushContextPosition(int pos)
{
@@ -159,7 +174,8 @@
}
/**
- * NEEDSDOC Method popContextPosition
+ * Pop the current context position onto the contextPositions. This
operation
+ * usually corresponds to the ending of a template.
*/
public void popContextPosition()
{
@@ -167,7 +183,10 @@
}
/**
- * NEEDSDOC Method pushContextMarker
+ * Get the current context position.
+ *
+ * @return The context marker into the stack to let us know when
+ * to stop searching for a var.
*/
public int getContextPos()
{
@@ -175,8 +194,10 @@
}
/**
- * NEEDSDOC Method pushContextMarker
- *
+ * Push the current top of the stack as
+ * a context marker into the variables stack to let us know when
+ * to stop searching for a var. This operation
+ * usually corresponds to the start of a template.
*/
public void pushContextMarker()
{
@@ -199,25 +220,69 @@
* to call startContext before pushing a series of
* arguments for a given macro call.
*
- * NEEDSDOC @param qname
- * NEEDSDOC @param val
+ * @param qname The qualified name of the variable.
+ * @param val The wrapped value of the variable.
*/
public void pushVariable(QName qname, XObject val)
{
push(new Arg(qname, val, false));
}
+
+ /**
+ * Tell if a variable or parameter is already declared,
+ * either in the current context or in the global space.
+ *
+ * @param qname The qualified name of the variable.
+ *
+ * @return true if the variable is already declared.
+ *
+ * @throws SAXException
+ */
+ public boolean variableIsDeclared(QName qname) throws SAXException
+ {
+
+ int nElems = (-1 == m_searchStart) ? this.size() : m_searchStart;
+ int endContextPos = m_contextPositions.peek();
+
+ for (int i = (nElems - 1); i >= endContextPos; i--)
+ {
+ Object obj = elementAt(i);
+
+ if (((Arg) obj).equals(qname))
+ {
+ return true;
+ }
+ }
+
+ if(endContextPos < m_globalStackFrameIndex)
+ return false;
+
+ // Look in the global space
+ for (int i = (m_globalStackFrameIndex - 1); i >= 0; i--)
+ {
+ Object obj = elementAt(i);
+
+ if (((Arg) obj).equals(qname))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
/**
* Same as getVariable, except don't look in the
* global space.
*
- * NEEDSDOC @param qname
+ * @param qname The qualified name of the variable.
*
- * NEEDSDOC ($objectName$) @return
+ * @return The wrapped value of the variable.
*
* @throws SAXException
*/
- public XObject getParamVariable(QName qname) throws SAXException
+ public XObject getParamVariable(XPathContext xctxt, QName qname) throws
SAXException
{
XObject val = null;
@@ -226,11 +291,17 @@
for (int i = (nElems - 1); i >= endContextPos; i--)
{
- Object obj = elementAt(i);
+ Arg arg = (Arg)elementAt(i);
- if (((Arg) obj).equals(qname))
+ if (arg.equals(qname))
{
- val = ((Arg) obj).getVal();
+ val = arg.getVal();
+
+ if(val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
+ {
+ val = val.execute(xctxt);
+ arg.setVal(val);
+ }
break;
}
@@ -240,16 +311,16 @@
}
/**
- * Given a name, return a string representing
+ * Given a name, return an object representing
* the value.
*
- * NEEDSDOC @param name
+ * @param qname The qualified name of the variable.
*
- * NEEDSDOC ($objectName$) @return
+ * @return The wrapped value of the variable.
*
* @throws SAXException
*/
- public Object getVariable(QName name) throws SAXException
+ public Object getVariable(XPathContext xctxt, QName name) throws
SAXException
{
int nElems = (-1 == m_searchStart) ? this.size() : m_searchStart;
@@ -260,16 +331,35 @@
Arg arg = (Arg) elementAt(i);
if (arg.equals(name))
- return arg.getVal();
+ {
+ XObject val = arg.getVal();
+ if(val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
+ {
+ val = val.execute(xctxt);
+ arg.setVal(val);
+ }
+ return val;
+ }
}
+
+ if(endContextPos < m_globalStackFrameIndex)
+ return null;
// Look in the global space
for (int i = (m_globalStackFrameIndex - 1); i >= 0; i--)
{
- Object obj = elementAt(i);
+ Arg arg = (Arg)elementAt(i);
- if (((Arg) obj).equals(name))
- return ((Arg) obj).getVal();
+ if (arg.equals(name))
+ {
+ XObject val = arg.getVal();
+ if(val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
+ {
+ val = val.execute(xctxt);
+ arg.setVal(val);
+ }
+ return val;
+ }
}
return null;
1.11 +1 -1 xml-xalan/java/src/org/apache/xpath/XPathContext.java
Index: XPathContext.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/XPathContext.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- XPathContext.java 2000/11/03 23:28:14 1.10
+++ XPathContext.java 2000/11/09 19:13:50 1.11
@@ -249,7 +249,7 @@
public XObject getVariable(QName qname) throws org.xml.sax.SAXException
{
- Object obj = getVarStack().getVariable(qname);
+ Object obj = getVarStack().getVariable(this, qname);
if ((null != obj) &&!(obj instanceof XObject))
{
1.13 +7 -3
xml-xalan/java/src/org/apache/xpath/compiler/Compiler.java
Index: Compiler.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xpath/compiler/Compiler.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- Compiler.java 2000/11/09 02:25:07 1.12
+++ Compiler.java 2000/11/09 19:13:50 1.13
@@ -591,9 +591,13 @@
opPos = getFirstChildPos(opPos);
- java.lang.String varName =
- (java.lang.String) m_tokenQueue[m_opMap[opPos]];
- QName qname = new QName(varName, getNamespaceContext());
+ int nsPos = m_opMap[opPos];
+ java.lang.String namespace
+ = (OpCodes.EMPTY == nsPos) ? null
+ : (java.lang.String) m_tokenQueue[nsPos];
+ java.lang.String localname
+ = (java.lang.String) m_tokenQueue[m_opMap[opPos+1]];
+ QName qname = new QName(namespace, localname);
var.setQName(qname);
1.5 +3 -2 xml-xalan/java/src/org/apache/xpath/compiler/OpCodes.java
Index: OpCodes.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xpath/compiler/OpCodes.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- OpCodes.java 2000/10/30 18:59:23 1.4
+++ OpCodes.java 2000/11/09 19:13:50 1.5
@@ -354,8 +354,9 @@
/**
* <meta name="usage" content="advanced"/>
* [OP_VARIABLE]
- * [3]
- * [index to token]
+ * [4]
+ * [index to namespace token, or EMPTY]
+ * [index to function name token]
*
* returns:
* XString
1.6 +17 -8
xml-xalan/java/src/org/apache/xpath/compiler/XPathParser.java
Index: XPathParser.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xpath/compiler/XPathParser.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- XPathParser.java 2000/11/03 23:28:16 1.5
+++ XPathParser.java 2000/11/09 19:13:50 1.6
@@ -1377,8 +1377,8 @@
{
nextToken(); // consume '$'
appendOp(2, OpCodes.OP_VARIABLE);
- NCName();
-
+ QName();
+
m_ops.m_opMap[opPos + OpMap.MAPINDEX_LENGTH] =
m_ops.m_opMap[OpMap.MAPINDEX_LENGTH] - opPos;
}
@@ -1888,13 +1888,22 @@
*/
protected void QName() throws org.xml.sax.SAXException
{
-
- m_ops.m_opMap[m_ops.m_opMap[OpMap.MAPINDEX_LENGTH]] = m_queueMark - 1;
- m_ops.m_opMap[OpMap.MAPINDEX_LENGTH] += 1;
-
- nextToken();
- consumeExpected(':');
+ // Namespace
+ if(lookahead(':', 1))
+ {
+ m_ops.m_opMap[m_ops.m_opMap[OpMap.MAPINDEX_LENGTH]] = m_queueMark - 1;
+ m_ops.m_opMap[OpMap.MAPINDEX_LENGTH] += 1;
+ nextToken();
+ consumeExpected(':');
+ }
+ else
+ {
+ m_ops.m_opMap[m_ops.m_opMap[OpMap.MAPINDEX_LENGTH]] = OpCodes.EMPTY;
+ m_ops.m_opMap[OpMap.MAPINDEX_LENGTH] += 1;
+ }
+
+ // Local name
m_ops.m_opMap[m_ops.m_opMap[OpMap.MAPINDEX_LENGTH]] = m_queueMark - 1;
m_ops.m_opMap[OpMap.MAPINDEX_LENGTH] += 1;
1.5 +9 -6 xml-xalan/java/src/org/apache/xpath/objects/XObject.java
Index: XObject.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/objects/XObject.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- XObject.java 2000/10/30 19:00:25 1.4
+++ XObject.java 2000/11/09 19:13:52 1.5
@@ -80,7 +80,7 @@
public class XObject extends Expression implements Serializable
{
- /** NEEDSDOC Field m_obj */
+ /** The java object which this object wraps. */
protected Object m_obj; // This may be NULL!!!
/**
@@ -91,7 +91,8 @@
/**
* Create an XObject.
*
- * NEEDSDOC @param obj
+ * @param obj Can be any object, should be a specific type
+ * for derived classes, or null.
*/
public XObject(Object obj)
{
@@ -100,11 +101,10 @@
/**
* For support of literal objects in xpaths.
- * @returns This object.
*
- * NEEDSDOC @param xctxt
+ * @param xctxt The XPath execution context.
*
- * NEEDSDOC ($objectName$) @return
+ * @return This object.
*
* @throws org.xml.sax.SAXException
*/
@@ -183,10 +183,13 @@
/** NEEDSDOC Field CLASS_RTREEFRAG */
public static final int CLASS_RTREEFRAG = 5;
+ /** Represents an unresolved variable type as an integer. */
+ public static final int CLASS_UNRESOLVEDVARIABLE = 600;
+
/**
* Tell what kind of class this is.
*
- * NEEDSDOC ($objectName$) @return
+ * @return CLASS_UNKNOWN
*/
public int getType()
{