garyp 01/03/06 20:27:18
Modified: java/src/org/apache/xalan/templates ElemParam.java
java/src/org/apache/xpath Arg.java VariableStack.java
Log:
The field Arg.isParamVar was attempting to serve two functions: to indicate
variable Frame entries which are not currently activated and to indicate Frames
containing parameters passed with xsl:with-param. When processing was finished
for a node in a node-set, the isParamVar flag was turned on to indicate the
Frame slot was available. Unfortunately, this also indicated that the item was
passed as a parameter which it wasn't. This fix changes isParamVar into to
fields, isAvailable which indicates that the slot is available and
isFromWithParam indicating the Frame slot came from an xsl:with-param or a
top-level parameter passed in via the tranformerImpl.setParameter() API.
I have tested this change against the conformance suite and had no
regression. I've also submitted a test case which fails on the existing
codebase but works okay after this fix.
It is possible that I've missed something with regard to the API setParameter
calls but we can fix those if problems are reported.
Revision Changes Path
1.10 +1 -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.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- ElemParam.java 2000/12/21 01:41:35 1.9
+++ ElemParam.java 2001/03/07 04:27:17 1.10
@@ -149,7 +149,7 @@
}
else
{
- arg.setIsParamVar(false);
+ arg.setIsVisible(true);
if (TransformerImpl.S_DEBUG)
transformer.getTraceManager().fireTraceEvent(sourceNode, mode, this);
}
1.11 +43 -21 xml-xalan/java/src/org/apache/xpath/Arg.java
Index: Arg.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/Arg.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- Arg.java 2001/01/02 03:47:13 1.10
+++ Arg.java 2001/03/07 04:27:18 1.11
@@ -154,31 +154,49 @@
}
/**
- * True if this is a parameter variable.
- * Set at the time the object is constructed.
+ * True if this variable was added with an xsl:with-param or
+ * is added via setParameter.
*/
- private boolean m_isParamVar;
-
+ private boolean m_isFromWithParam;
+
+ /**
+ * Tell if this variable is a parameter passed with a with-param or as
+ * a top-level parameter.
+ */
+ public boolean isFromWithParam()
+ {
+ return m_isFromWithParam;
+ }
+
+ /**
+ * True if this variable is currently visible. To be visible,
+ * a variable needs to come either from xsl:variable or be
+ * a "received" parameter, ie one for which an xsl:param has
+ * been encountered.
+ * Set at the time the object is constructed and updated as needed.
+ */
+ private boolean m_isVisible;
+
/**
- * Tell if this variable is a param var.
+ * Tell if this variable is currently visible.
*/
- public boolean isParamVar()
+ public boolean isVisible()
{
- return m_isParamVar;
+ return m_isVisible;
}
/**
- * Tell if this variable is a param var.
+ * Update visibility status of this variable.
*/
- public void setIsParamVar(boolean b)
+ public void setIsVisible(boolean b)
{
- m_isParamVar = b;
+ m_isVisible = b;
}
/**
* Construct a dummy parameter argument, with no QName and no
- * value (either expression string or value XObject). isParameterVar
- * defaults to false.
+ * value (either expression string or value XObject). isVisible
+ * defaults to true.
*/
public Arg()
{
@@ -187,7 +205,8 @@
; // so that string compares can be done.
m_val = null;
m_expression = null;
- m_isParamVar = false;
+ m_isVisible = true;
+ m_isFromWithParam = false;
}
/**
@@ -195,20 +214,21 @@
*
* @param qname Name of the argument, expressed as a QName object.
* @param expression String to be stored as this argument's value
expression.
- * @param isParamVar True if this is a parameter variable.
+ * @param isFromWithParam True if this is a parameter variable.
*/
- public Arg(QName qname, String expression, boolean isParamVar)
+ public Arg(QName qname, String expression, boolean isFromWithParam)
{
m_qname = qname;
m_val = null;
m_expression = expression;
- m_isParamVar = isParamVar;
+ m_isFromWithParam = isFromWithParam;
+ m_isVisible = !isFromWithParam;
}
/**
* Construct a parameter argument which has an XObject value.
- * isParamVar defaults to false.
+ * isVisible defaults to true.
*
* @param qname Name of the argument, expressed as a QName object.
* @param val Value of the argument, expressed as an XObject
@@ -218,7 +238,8 @@
m_qname = qname;
m_val = val;
- m_isParamVar = false;
+ m_isVisible = true;
+ m_isFromWithParam = false;
m_expression = null;
}
@@ -245,14 +266,15 @@
*
* @param qname Name of the argument, expressed as a QName object.
* @param val Value of the argument, expressed as an XObject
- * @param isParamVar True if this is a parameter variable.
+ * @param isFromWithParam True if this is a parameter variable.
*/
- public Arg(QName qname, XObject val, boolean isParamVar)
+ public Arg(QName qname, XObject val, boolean isFromWithParam)
{
m_qname = qname;
m_val = val;
- m_isParamVar = isParamVar;
+ m_isFromWithParam = isFromWithParam;
+ m_isVisible = !isFromWithParam;
m_expression = null;
}
}
1.26 +16 -6 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.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- VariableStack.java 2001/01/02 03:47:13 1.25
+++ VariableStack.java 2001/03/07 04:27:18 1.26
@@ -277,13 +277,13 @@
for (int i = (frame.size() - 1); i >= 0; i--)
{
Arg arg = (Arg)frame.elementAt(i);
- if(arg.getQName().equals(qname) && arg.isParamVar())
+ if(arg.getQName().equals(qname) && arg.isFromWithParam())
{
- frame.setElementAt(new Arg(qname, xval), i);
+ frame.setElementAt(new Arg(qname, xval, true), i);
return;
}
}
- frame.push(new Arg(qname, xval, false));
+ frame.push(new Arg(qname, xval, true));
}
/**
@@ -297,7 +297,7 @@
for (int i = (frame.size() - 1); i >= 0; i--)
{
Arg arg = (Arg)frame.elementAt(i);
- arg.setIsParamVar(true);
+ arg.setIsVisible(false);
}
}
@@ -310,6 +310,16 @@
* @param qname The qualified name of the variable.
* @param val The wrapped value of the variable.
*/
+ // Note that this method will push an Arg onto the Frame even
+ // if an Arg for this qname already exists, effectively hiding that
+ // previous stack entry. That entry is never reclaimed. This could lead
to
+ // objects in the Frame that will never be used. Hopefully, this situation
+ // will be short lived since the frame is released after the node-set is
+ // in the apply-templates is completed. However, for large node-sets, we
+ // will be putting a lot of unusable entries in the Frame. If this becomes
+ // a problem, we should replace those matching entries provided that
+ // isFromWithParam is false. I'm not sure that the overhead of searching
+ // for matching entries is worth it at this point. GLP
public void pushVariable(QName qname, XObject val)
{
Stack frame = getCurrentFrame();
@@ -396,7 +406,7 @@
{
Arg arg = (Arg)frame.elementAt(i);
- if (arg.getQName().equals(qname) && arg.isParamVar())
+ if (arg.getQName().equals(qname) && arg.isFromWithParam())
{
return arg;
}
@@ -427,7 +437,7 @@
{
Arg arg = (Arg)frame.elementAt(i);
- if (arg.getQName().equals(name) && !arg.isParamVar())
+ if (arg.getQName().equals(name) && arg.isVisible())
{
XObject val = arg.getVal();
if(val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)