morten 01/08/17 06:17:45
Modified: java/src/org/apache/xalan/xsltc/compiler IdKeyPattern.java
Key.java KeyCall.java Parser.java Sort.java
xpath.cup
java/src/org/apache/xalan/xsltc/compiler/util
CompareGenerator.java NodeSortRecordGenerator.java
java/src/org/apache/xalan/xsltc/dom DTDMonitor.java
DupFilterIterator.java KeyIndex.java
NodeSortRecord.java NodeSortRecordFactory.java
java/src/org/apache/xalan/xsltc/runtime
AbstractTranslet.java BasisLibrary.java
Log:
Major update for id() and key(). Patterns containing id() and key() are
now 100% supported (about time), and id() and key() expressions should
now work in all (at least most) combinations.
PR: bugzilla 1376 (!!!) and 2624
Obtained from: n/a
Submitted by: [EMAIL PROTECTED]
Reviewed by: [EMAIL PROTECTED]
Revision Changes Path
1.5 +3 -3
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/IdKeyPattern.java
Index: IdKeyPattern.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/IdKeyPattern.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- IdKeyPattern.java 2001/08/16 12:17:15 1.4
+++ IdKeyPattern.java 2001/08/17 13:17:44 1.5
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: IdKeyPattern.java,v 1.4 2001/08/16 12:17:15 morten Exp $
+ * @(#)$Id: IdKeyPattern.java,v 1.5 2001/08/17 13:17:44 morten Exp $
*
* The Apache Software License, Version 1.1
*
@@ -123,10 +123,10 @@
// Initialises a KeyIndex to return nodes with specific values
final int lookupId = cpg.addMethodref(KEY_INDEX_CLASS,
"containsID",
- "(ILjava/lang/String;)I");
+ "(ILjava/lang/Object;)I");
final int lookupKey = cpg.addMethodref(KEY_INDEX_CLASS,
"containsKey",
- "(ILjava/lang/String;)I");
+ "(ILjava/lang/Object;)I");
// Call getKeyIndex in AbstractTranslet with the name of the key
// to get the index for this key (which is also a node iterator).
1.7 +57 -28 xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Key.java
Index: Key.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Key.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- Key.java 2001/08/01 11:52:58 1.6
+++ Key.java 2001/08/17 13:17:44 1.7
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: Key.java,v 1.6 2001/08/01 11:52:58 morten Exp $
+ * @(#)$Id: Key.java,v 1.7 2001/08/17 13:17:44 morten Exp $
*
* The Apache Software License, Version 1.1
*
@@ -74,18 +74,31 @@
import org.apache.xalan.xsltc.dom.Axis;
final class Key extends TopLevelElement {
- private QName _name;
- private Pattern _match;
- private Expression _use;
- private Type _useType;
+ private QName _name; // The name of this key (ie. index)
+ private Pattern _match; // The nodes to generate index keys from
+ private Expression _use; // The nodes to include in the key
+ private Type _useType; // The data type of the key's contents
+
+ private final String USE_TYPE_ERR =
+ "The use-attribute of <key> must be node, node-set, string or number.";
+
+ /**
+ * Parse the <xsl:key> element and attributes
+ * @param parser A reference to the stylesheet parser
+ */
public void parseContents(Parser parser) {
- // make sure values are provided
+
+ // Get the required attributes and parser XPath expressions
_name = parser.getQName(getAttribute("name"));
_match = parser.parsePattern(this, "match", null);
_use = parser.parseExpression(this, "use", null);
- // make sure required attribute(s) have been set
+ // Make sure required attribute(s) have been set
+ if (_name == null) {
+ reportError(this, parser, ErrorMsg.NREQATTR_ERR, "name");
+ return;
+ }
if (_match.isDummy()) {
reportError(this, parser, ErrorMsg.NREQATTR_ERR, "match");
return;
@@ -96,16 +109,9 @@
}
}
- public Pattern getPattern() {
- return(_match);
- }
-
- public StepPattern getKernelPattern() {
- return(((LocationPathPattern)_match).getKernelPattern());
- }
-
/**
- *
+ * Returns a String-representation of this key's name
+ * @return The key's name (from the <xsl:key> elements 'name' attribute).
*/
public String getName() {
String name;
@@ -119,22 +125,28 @@
/**
* Run type check on the "use" attribute and make sure it is something
* we can use to extract some value from nodes.
+ * @param stable The stylesheet parser's symbol table
+ * @return The data-type of this key (always void)
+ * @throws TypeCheckError If the use attribute does not represent a string,
+ * a node-set or a number
*/
public Type typeCheck(SymbolTable stable) throws TypeCheckError {
_match.typeCheck(stable);
_useType = _use.typeCheck(stable);
- // If the 'use' attribute is not a string...
- if (!(_useType instanceof StringType)) {
+
+ // Cast node values to string values
+ if (_useType instanceof NodeType) {
+ _use = new CastExpr(_use, Type.String);
+ _useType = Type.String;
+ }
- // ...it must hold an expression for a node...
- if (_useType instanceof NodeType) {
- _use = new CastExpr(_use, Type.String);
- }
- // ...or a node-set.
- else if (!(_useType instanceof NodeSetType)) {
- throw new TypeCheckError(this);
- }
+ // If the 'use' attribute is not a string, node-set or number
+ if (!(_useType instanceof StringType) &&
+ !(_useType instanceof NodeSetType) &&
+ !(_useType instanceof RealType)) {
+ throw new TypeCheckError(new ErrorMsg(USE_TYPE_ERR));
}
+
return Type.Void;
}
@@ -142,6 +154,8 @@
* This method is called if the "use" attribute of the key contains a
* node set. In this case we must traverse all nodes in the set and
* create one entry in this key's index for each node in the set.
+ * @param classGen The Java class generator
+ * @param methodGen The method generator
*/
public void traverseNodeSet(ClassGenerator classGen,
MethodGenerator methodGen,
@@ -205,6 +219,8 @@
/**
* Gather all nodes that match the expression in the attribute "match"
* and add one (or more) entries in this key's index.
+ * @param classGen The Java class generator
+ * @param methodGen The method generator
*/
public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
@@ -215,7 +231,7 @@
// AbstractTranslet.buildKeyIndex(name,node_id,value) => void
final int key = cpg.addMethodref(TRANSLET_CLASS,
"buildKeyIndex",
- "("+STRING_SIG+"I"+STRING_SIG+")V");
+ "("+STRING_SIG+"I"+OBJECT_SIG+")V");
// DOM.getAxisIterator(root) => NodeIterator
final int git = cpg.addMethodref(classGen.getDOMClass(),
@@ -247,7 +263,20 @@
// If this is just a single node we should convert that to a string
// and use that string as the value in the index for this key.
- if ((_useType instanceof NodeType) || (_useType instanceof StringType)) {
+ if (_useType instanceof RealType) {
+ final int dbl = cpg.addMethodref(DOUBLE_CLASS,"<init>", "(D)V");
+
+ il.append(classGen.loadTranslet());
+ il.append(new PUSH(cpg, _name.toString()));
+ il.append(methodGen.loadCurrentNode());
+ il.append(new NEW(cpg.addClass(DOUBLE_CLASS)));
+ il.append(DUP);
+ _use.translate(classGen,methodGen);
+ il.append(new INVOKESPECIAL(dbl));
+ il.append(new INVOKEVIRTUAL(key));
+
+ }
+ else if (_useType instanceof StringType) {
il.append(classGen.loadTranslet());
il.append(new PUSH(cpg, _name.toString()));
il.append(methodGen.loadCurrentNode());
1.5 +46 -18 xml-xalan/java/src/org/apache/xalan/xsltc/compiler/KeyCall.java
Index: KeyCall.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/KeyCall.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- KeyCall.java 2001/08/16 12:17:15 1.4
+++ KeyCall.java 2001/08/17 13:17:44 1.5
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: KeyCall.java,v 1.4 2001/08/16 12:17:15 morten Exp $
+ * @(#)$Id: KeyCall.java,v 1.5 2001/08/17 13:17:44 morten Exp $
*
* The Apache Software License, Version 1.1
*
@@ -69,11 +69,11 @@
import org.apache.xalan.xsltc.compiler.util.*;
final class KeyCall extends FunctionCall {
- private final Expression _name;
- private Expression _value;
- private Type _valueType;
- private String _expandedName;
+ private Expression _name; // The name of this key
+ private Expression _value; // The value to look up in the key/index
+ private Type _valueType; // The value's data type
+
/**
* Get the parameters passed to function:
* key(String name, String value)
@@ -82,6 +82,9 @@
* one holding the key name and one holding the value(s) to look up. The
* vector has only one parameter for id() calls (the key name is always
* "##id" for id() calls).
+ *
+ * @param fname The function name (should be 'key' or 'id')
+ * @param arguments A vector containing the arguments the the function
*/
public KeyCall(QName fname, Vector arguments) {
super(fname, arguments);
@@ -104,14 +107,18 @@
* Type check the parameters for the id() or key() function.
* The index name (for key() call only) must be a string or convertable
* to a string, and the lookup-value must be a string or a node-set.
+ * @param stable The parser's symbol table
+ * @throws TypeCheckError When the parameters have illegal type
*/
public Type typeCheck(SymbolTable stable) throws TypeCheckError {
final Type returnType = super.typeCheck(stable);
- // Run type check on the key name (first argument) - must be a string
+
+ // Run type check on the key name (first argument) - must be a string,
+ // and if it is not it must be converted to one using string() rules.
if (_name != null) {
final Type nameType = _name.typeCheck(stable);
if (!(nameType instanceof StringType)) {
- throw new TypeCheckError(this);
+ _name = new CastExpr(_name, Type.String);
}
}
@@ -126,8 +133,10 @@
if ((_valueType != Type.NodeSet) &&
(_valueType != Type.ResultTree) &&
- (_valueType != Type.String)) {
- _value = new CastExpr(_value,Type.String);
+ (_valueType != Type.String) &&
+ (_valueType != Type.Real) &&
+ (_valueType != Type.Int)) {
+ _value = new CastExpr(_value, Type.String);
}
return returnType;
@@ -136,30 +145,36 @@
/**
* This method is called when the constructor is compiled in
* Stylesheet.compileConstructor() and not as the syntax tree is traversed.
+ * This method is a wrapper for the real translation method, which is
+ * the private method translateCall() below. All this method does is to
+ * wrap the KeyIndex that this function returns inside a duplicate filter.
+ * The duplicate filter is used both to eliminate duplicates and to
+ * cache the nodes in the index.
+ * @param classGen The Java class generator
+ * @param methodGen The method generator
*/
public void translate(ClassGenerator classGen,
MethodGenerator methodGen) {
final ConstantPoolGen cpg = classGen.getConstantPool();
final InstructionList il = methodGen.getInstructionList();
+ // Wrap the KeyIndex (iterator) inside a duplicate filter iterator
+ // to pre-read the indexed nodes and cache them.
final int dupInit = cpg.addMethodref(DUP_FILTERED_ITERATOR,
"<init>",
"("+NODE_ITERATOR_SIG+")V");
-
- // Wrap the KeyIndex (iterator) inside a duplicate filter iterator to
- // pre-read the indexed nodes and cache them.
il.append(new NEW(cpg.addClass(DUP_FILTERED_ITERATOR)));
il.append(DUP);
-
translateCall(classGen, methodGen);
-
il.append(new INVOKESPECIAL(dupInit));
}
/**
* Translate the actual index lookup - leaves KeyIndex (iterator) on stack
+ * @param classGen The Java class generator
+ * @param methodGen The method generator
*/
- public void translateCall(ClassGenerator classGen,
+ private void translateCall(ClassGenerator classGen,
MethodGenerator methodGen) {
final ConstantPoolGen cpg = classGen.getConstantPool();
@@ -179,10 +194,10 @@
// Initialises a KeyIndex to return nodes with specific values
final int lookupId = cpg.addMethodref(KEY_INDEX_CLASS,
"lookupId",
- "(Ljava/lang/String;)V");
+ "(Ljava/lang/Object;)V");
final int lookupKey = cpg.addMethodref(KEY_INDEX_CLASS,
"lookupKey",
- "(Ljava/lang/String;)V");
+ "(Ljava/lang/Object;)V");
// Merges the nodes in two KeyIndex objects
final int merge = cpg.addMethodref(KEY_INDEX_CLASS,
@@ -289,7 +304,20 @@
// Now use the value in the second argument to determine what nodes
// the iterator should return.
il.append(DUP);
- _value.translate(classGen, methodGen);
+
+ if (_valueType == Type.Int || _valueType == Type.Real) {
+ final int dbl = cpg.addMethodref(DOUBLE_CLASS,"<init>", "(D)V");
+ il.append(new NEW(cpg.addClass(DOUBLE_CLASS)));
+ il.append(DUP);
+ _value.translate(classGen, methodGen);
+ if (_valueType == Type.Int)
+ il.append(new I2D());
+ il.append(new INVOKESPECIAL(dbl));
+ }
+ else {
+ _value.translate(classGen, methodGen);
+ }
+
if (_name == null)
il.append(new INVOKEVIRTUAL(lookupId));
else
1.24 +2 -15 xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Parser.java
Index: Parser.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Parser.java,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- Parser.java 2001/08/16 12:17:15 1.23
+++ Parser.java 2001/08/17 13:17:44 1.24
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: Parser.java,v 1.23 2001/08/16 12:17:15 morten Exp $
+ * @(#)$Id: Parser.java,v 1.24 2001/08/17 13:17:44 morten Exp $
*
* The Apache Software License, Version 1.1
*
@@ -1023,16 +1023,13 @@
public void startPrefixMapping(String prefix, String uri) {
if (_prefixMapping == null) _prefixMapping = new Hashtable();
_prefixMapping.put(prefix, uri);
- //System.err.println("starting mapping for \""+prefix+"\"=\""+uri+"\"");
}
/**
* SAX2: End the scope of a prefix-URI Namespace mapping.
* This has to be passed on to the symbol table!
*/
- public void endPrefixMapping(String prefix) {
- //System.err.println("ending mapping for \""+prefix+"\"");
- }
+ public void endPrefixMapping(String prefix) { }
/**
* SAX2: Receive notification of the beginning of an element.
@@ -1042,11 +1039,6 @@
public void startElement(String uri, String localname,
String qname, Attributes attributes)
throws SAXException {
- /*
- System.err.println("start element uri=\""+uri+
- "\", local=\""+localname+
- "\", qname=\""+qname+"\"");
- */
final int col = qname.lastIndexOf(':');
final String prefix;
if (col == -1)
@@ -1093,11 +1085,6 @@
* SAX2: Receive notification of the end of an element.
*/
public void endElement(String uri, String localname, String qname) {
- /*
- System.err.println("end element uri=\""+uri+
- "\", local=\""+localname+
- "\", qname=\""+qname+"\"");
- */
_parentStack.pop();
}
1.5 +3 -2 xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Sort.java
Index: Sort.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Sort.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- Sort.java 2001/07/23 15:24:00 1.4
+++ Sort.java 2001/08/17 13:17:44 1.5
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: Sort.java,v 1.4 2001/07/23 15:24:00 morten Exp $
+ * @(#)$Id: Sort.java,v 1.5 2001/08/17 13:17:44 morten Exp $
*
* The Apache Software License, Version 1.1
*
@@ -83,6 +83,7 @@
final class Sort extends Instruction {
+
private Expression _select;
private AttributeValue _order;
private AttributeValue _caseOrder;
@@ -419,7 +420,7 @@
Util.getJCRefType(DOM_INTF_SIG),
de.fub.bytecode.generic.Type.INT,
de.fub.bytecode.generic.Type.INT,
- Util.getJCRefType(TRANSLET_INTF_SIG),
+ Util.getJCRefType(TRANSLET_SIG),
de.fub.bytecode.generic.Type.INT
},
new String[] { "dom",
1.10 +3 -3 xml-xalan/java/src/org/apache/xalan/xsltc/compiler/xpath.cup
Index: xpath.cup
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/xpath.cup,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- xpath.cup 2001/08/16 14:10:49 1.9
+++ xpath.cup 2001/08/17 13:17:44 1.10
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: xpath.cup,v 1.9 2001/08/16 14:10:49 tmiller Exp $
+ * @(#)$Id: xpath.cup,v 1.10 2001/08/17 13:17:44 morten Exp $
*
* Copyright 2000 Sun Microsystems, Inc. All Rights Reserved.
*
@@ -494,12 +494,12 @@
// CASE I: no filtering, nodes OK but have dups,
// results of test suite in file: 'REP_UNFILT'
- //RESULT = path;
+ RESULT = path;
// CASE II: Filtered Abs Loc Path -
// all tests fail except desOrSelf test,
// results of test suite in file: 'REP-FILT'
- RESULT = new FilteredAbsoluteLocationPath(path);
+ //RESULT = new FilteredAbsoluteLocationPath(path);
// CASE III: Filtered Parent Loc Path -
1.3 +24 -1
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/util/CompareGenerator.java
Index: CompareGenerator.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/util/CompareGenerator.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- CompareGenerator.java 2001/08/01 11:52:59 1.2
+++ CompareGenerator.java 2001/08/17 13:17:44 1.3
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: CompareGenerator.java,v 1.2 2001/08/01 11:52:59 morten Exp $
+ * @(#)$Id: CompareGenerator.java,v 1.3 2001/08/17 13:17:44 morten Exp $
*
* The Apache Software License, Version 1.1
*
@@ -65,6 +65,8 @@
import de.fub.bytecode.generic.Type;
import de.fub.bytecode.generic.*;
+
+import org.apache.xalan.xsltc.compiler.Constants;
import org.apache.xalan.xsltc.compiler.Template;
public final class CompareGenerator extends MethodGenerator {
@@ -74,11 +76,14 @@
private static int LEVEL_INDEX = 3;
private static int TRANSLET_INDEX = 4;
private static int LAST_INDEX = 5;
+ private int ITERATOR_INDEX = 6;
private final Instruction _iloadCurrent;
private final Instruction _istoreCurrent;
private final Instruction _aloadDom;
private final Instruction _iloadLast;
+ private final Instruction _aloadIterator;
+ private final Instruction _astoreIterator;
public CompareGenerator(int access_flags, Type return_type,
Type[] arg_types, String[] arg_names,
@@ -91,6 +96,16 @@
_istoreCurrent = new ISTORE(CURRENT_INDEX);
_aloadDom = new ALOAD(DOM_INDEX);
_iloadLast = new ILOAD(LAST_INDEX);
+
+ LocalVariableGen iterator =
+ addLocalVariable("iterator",
+ Util.getJCRefType(Constants.NODE_ITERATOR_SIG),
+ null, null);
+ ITERATOR_INDEX = iterator.getIndex();
+ _aloadIterator = new ALOAD(ITERATOR_INDEX);
+ _astoreIterator = new ASTORE(ITERATOR_INDEX);
+ il.append(new ACONST_NULL());
+ il.append(storeIterator());
}
public Instruction loadLastNode() {
@@ -115,6 +130,14 @@
public int getIteratorIndex() {
return INVALID_INDEX;
+ }
+
+ public Instruction storeIterator() {
+ return _astoreIterator;
+ }
+
+ public Instruction loadIterator() {
+ return _aloadIterator;
}
//??? may not be used anymore
1.3 +4 -1
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/util/NodeSortRecordGenerator.java
Index: NodeSortRecordGenerator.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/util/NodeSortRecordGenerator.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- NodeSortRecordGenerator.java 2001/06/28 15:36:33 1.2
+++ NodeSortRecordGenerator.java 2001/08/17 13:17:44 1.3
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: NodeSortRecordGenerator.java,v 1.2 2001/06/28 15:36:33 morten Exp $
+ * @(#)$Id: NodeSortRecordGenerator.java,v 1.3 2001/08/17 13:17:44 morten Exp $
*
* The Apache Software License, Version 1.1
*
@@ -64,7 +64,10 @@
package org.apache.xalan.xsltc.compiler.util;
+import org.apache.xalan.xsltc.compiler.util.Type;
import de.fub.bytecode.generic.*;
+import org.apache.xalan.xsltc.compiler.util.*;
+
import org.apache.xalan.xsltc.compiler.Stylesheet;
/**
1.4 +2 -2 xml-xalan/java/src/org/apache/xalan/xsltc/dom/DTDMonitor.java
Index: DTDMonitor.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/dom/DTDMonitor.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- DTDMonitor.java 2001/05/22 17:26:37 1.3
+++ DTDMonitor.java 2001/08/17 13:17:45 1.4
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: DTDMonitor.java,v 1.3 2001/05/22 17:26:37 morten Exp $
+ * @(#)$Id: DTDMonitor.java,v 1.4 2001/08/17 13:17:45 morten Exp $
*
* The Apache Software License, Version 1.1
*
@@ -214,7 +214,7 @@
while (( node = niter.next()) != NodeIterator.END) {
// get id value for the node
- String idValue = dom.getAttributeValue(attributeType, node);
+ Object idValue = dom.getAttributeValue(attributeType, node);
// add entry into ##id index for KeyCall to handle
translet.buildKeyIndex(ID_INDEX_NAME, mask|node, idValue);
}
1.5 +5 -1
xml-xalan/java/src/org/apache/xalan/xsltc/dom/DupFilterIterator.java
Index: DupFilterIterator.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/dom/DupFilterIterator.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- DupFilterIterator.java 2001/08/16 15:28:29 1.4
+++ DupFilterIterator.java 2001/08/17 13:17:45 1.5
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: DupFilterIterator.java,v 1.4 2001/08/16 15:28:29 morten Exp $
+ * @(#)$Id: DupFilterIterator.java,v 1.5 2001/08/17 13:17:45 morten Exp $
*
* The Apache Software License, Version 1.1
*
@@ -107,6 +107,10 @@
* @return A reference to this node iterator
*/
public NodeIterator setStartNode(int node) {
+ // KeyIndex iterators are always relative to the root node, so there
+ // is never any point in re-reading the iterator (and we SHOULD NOT).
+ if ((_source instanceof KeyIndex) && (_data != null)) return this;
+
// If the _data array is populated, and the current start node is
// equal to the new start node, we know we already have what we need.
if ((_data == null) || (node != _startNode)) {
1.4 +33 -29 xml-xalan/java/src/org/apache/xalan/xsltc/dom/KeyIndex.java
Index: KeyIndex.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/dom/KeyIndex.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- KeyIndex.java 2001/07/09 10:17:50 1.3
+++ KeyIndex.java 2001/08/17 13:17:45 1.4
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: KeyIndex.java,v 1.3 2001/07/09 10:17:50 morten Exp $
+ * @(#)$Id: KeyIndex.java,v 1.4 2001/08/17 13:17:45 morten Exp $
*
* The Apache Software License, Version 1.1
*
@@ -90,7 +90,7 @@
* Adds a node to the node list for a given value.
* The BitArray object makes sure duplicate nodes are eliminated.
*/
- public void add(String value, int node) {
+ public void add(Object value, int node) {
if ((_nodes = (BitArray)_index.get(value)) == null) {
_nodes = new BitArray(_arraySize);
_nodes.setMask(node & 0xff000000);
@@ -127,29 +127,31 @@
* list of tokens for the id() function, but a single string for the
* key() function.
*/
- public void lookupId(String value) {
- if (value.indexOf(' ') > -1) {
- StringTokenizer values = new StringTokenizer(value);
- while (values.hasMoreElements()) {
- BitArray nodes = (BitArray)_index.get(values.nextElement());
- if (nodes != null) {
- if (_nodes == null)
- _nodes = nodes;
- else
- _nodes = _nodes.merge(nodes);
+ public void lookupId(Object value) {
+ if (value instanceof String) {
+ final String string = (String)value;
+ if (string.indexOf(' ') > -1) {
+ StringTokenizer values = new StringTokenizer(string);
+ while (values.hasMoreElements()) {
+ BitArray nodes = (BitArray)_index.get(values.nextElement());
+ if (nodes != null) {
+ if (_nodes == null)
+ _nodes = nodes;
+ else
+ _nodes = _nodes.merge(nodes);
+ }
}
+ return;
}
}
- else {
- _nodes = (BitArray)_index.get(value);
- }
+ _nodes = (BitArray)_index.get(value);
}
/**
* This method must be called by the code generated by the key() function
* prior to returning the node iterator.
*/
- public void lookupKey(String value) {
+ public void lookupKey(Object value) {
_nodes = (BitArray)_index.get(value);
}
@@ -163,23 +165,25 @@
return(_node | _nodes.getMask());
}
- public int containsID(int node, String value) {
- if (value.indexOf(' ') > -1) {
- StringTokenizer values = new StringTokenizer(value);
- while (values.hasMoreElements()) {
- BitArray nodes = (BitArray)_index.get(values.nextElement());
- if ((nodes != null) && (nodes.getBit(node))) return(1);
+ public int containsID(int node, Object value) {
+ if (value instanceof String) {
+ final String string = (String)value;
+ if (string.indexOf(' ') > -1) {
+ StringTokenizer values = new StringTokenizer(string);
+ while (values.hasMoreElements()) {
+ BitArray nodes = (BitArray)_index.get(values.nextElement());
+ if ((nodes != null) && (nodes.getBit(node))) return(1);
+ }
+ return(0);
}
- return(0);
}
- else {
- BitArray nodes = (BitArray)_index.get(value);
- if ((nodes != null) && (nodes.getBit(node))) return(1);
- return(0);
- }
+
+ BitArray nodes = (BitArray)_index.get(value);
+ if ((nodes != null) && (nodes.getBit(node))) return(1);
+ return(0);
}
- public int containsKey(int node, String value) {
+ public int containsKey(int node, Object value) {
BitArray nodes = (BitArray)_index.get(value);
if ((nodes != null) && (nodes.getBit(node))) return(1);
return(0);
1.3 +8 -5
xml-xalan/java/src/org/apache/xalan/xsltc/dom/NodeSortRecord.java
Index: NodeSortRecord.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/dom/NodeSortRecord.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- NodeSortRecord.java 2001/07/23 15:24:00 1.2
+++ NodeSortRecord.java 2001/08/17 13:17:45 1.3
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: NodeSortRecord.java,v 1.2 2001/07/23 15:24:00 morten Exp $
+ * @(#)$Id: NodeSortRecord.java,v 1.3 2001/08/17 13:17:45 morten Exp $
*
* The Apache Software License, Version 1.1
*
@@ -69,7 +69,7 @@
import java.text.CollationKey;
import org.apache.xalan.xsltc.DOM;
-import org.apache.xalan.xsltc.Translet;
+import org.apache.xalan.xsltc.runtime.AbstractTranslet;
/**
* Base class for sort records containing application specific sort keys
@@ -86,7 +86,8 @@
protected static int[] _sortOrder;
protected static int _levels = 1;
- private Translet _translet = null;
+ private AbstractTranslet _translet = null;
+
private DOM _dom = null;
private int _node; // The position in the current iterator
private int _last = 0; // Number of nodes in the current iterator
@@ -112,7 +113,8 @@
* This method allows the caller to set the values that could not be passed
* to the default constructor.
*/
- public final void initialize(int node,int last,DOM dom,Translet translet) {
+ public final void initialize(int node, int last, DOM dom,
+ AbstractTranslet translet) {
_dom = dom;
_node = node;
_last = last;
@@ -217,6 +219,7 @@
* Extract the sort value for a level of this key.
*/
public abstract String extractValueFromDOM(DOM dom, int current, int level,
- Translet translet, int last);
+ AbstractTranslet translet,
+ int last);
}
1.3 +5 -3
xml-xalan/java/src/org/apache/xalan/xsltc/dom/NodeSortRecordFactory.java
Index: NodeSortRecordFactory.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/dom/NodeSortRecordFactory.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- NodeSortRecordFactory.java 2001/07/23 15:24:00 1.2
+++ NodeSortRecordFactory.java 2001/08/17 13:17:45 1.3
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: NodeSortRecordFactory.java,v 1.2 2001/07/23 15:24:00 morten Exp $
+ * @(#)$Id: NodeSortRecordFactory.java,v 1.3 2001/08/17 13:17:45 morten Exp $
*
* The Apache Software License, Version 1.1
*
@@ -67,13 +67,15 @@
import org.apache.xalan.xsltc.DOM;
import org.apache.xalan.xsltc.Translet;
import org.apache.xalan.xsltc.TransletException;
+import org.apache.xalan.xsltc.runtime.AbstractTranslet;
public class NodeSortRecordFactory {
private final DOM _dom;
private final Class _class;
private final String _className;
- private final Translet _translet;
+ private final AbstractTranslet _translet;
+
/**
* Creates a NodeSortRecord producing object. The DOM specifies which tree
* to get the nodes to sort from, the class name specifies what auxillary
@@ -87,7 +89,7 @@
_dom = dom;
_className = className;
_class = Class.forName(className);
- _translet = translet;
+ _translet = (AbstractTranslet)translet;
}
catch (ClassNotFoundException e) {
throw new TransletException("Could not find class " + className);
1.19 +3 -3
xml-xalan/java/src/org/apache/xalan/xsltc/runtime/AbstractTranslet.java
Index: AbstractTranslet.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/runtime/AbstractTranslet.java,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- AbstractTranslet.java 2001/08/16 12:29:19 1.18
+++ AbstractTranslet.java 2001/08/17 13:17:45 1.19
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: AbstractTranslet.java,v 1.18 2001/08/16 12:29:19 morten Exp $
+ * @(#)$Id: AbstractTranslet.java,v 1.19 2001/08/17 13:17:45 morten Exp $
*
* The Apache Software License, Version 1.1
*
@@ -395,9 +395,9 @@
* @node is the node id of the node to insert
* @value is the value that will look up the node in the given index
*/
- public void buildKeyIndex(String name, int node, String value) {
+ public void buildKeyIndex(String name, int node, Object value) {
if (_keyIndexes == null) _keyIndexes = new Hashtable();
-
+
KeyIndex index = (KeyIndex)_keyIndexes.get(name);
if (index == null) {
_keyIndexes.put(name, index = new KeyIndex(_indexSize));
1.9 +46 -27
xml-xalan/java/src/org/apache/xalan/xsltc/runtime/BasisLibrary.java
Index: BasisLibrary.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/runtime/BasisLibrary.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- BasisLibrary.java 2001/07/10 17:46:26 1.8
+++ BasisLibrary.java 2001/08/17 13:17:45 1.9
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: BasisLibrary.java,v 1.8 2001/07/10 17:46:26 morten Exp $
+ * @(#)$Id: BasisLibrary.java,v 1.9 2001/08/17 13:17:45 morten Exp $
*
* The Apache Software License, Version 1.1
*
@@ -82,8 +82,11 @@
* and the DOM as their last two arguments.
*/
public final class BasisLibrary implements Operators {
+
+ private final static String EMPTYSTRING = "";
+
/**
- * XSLT Standard function count(node-set)
+ * Standard function count(node-set)
*/
public static int countF(NodeIterator iterator) {
int counter = 0;
@@ -211,7 +214,7 @@
return ((Boolean) obj).booleanValue();
}
else if (obj instanceof String) {
- return !((String) obj).equals("");
+ return !((String) obj).equals(EMPTYSTRING);
}
else if (obj instanceof NodeIterator) {
NodeIterator iter = (NodeIterator) obj;
@@ -222,7 +225,7 @@
}
else if (obj instanceof DOM) {
String temp = ((DOM) obj).getStringValue();
- return !temp.equals("");
+ return !temp.equals(EMPTYSTRING);
}
else {
runTimeError("Invalid argument type in call to number().");
@@ -236,13 +239,14 @@
*/
public static String substringF(String value, double start) {
try {
- final int valuel = value.length();
- final int istart = (int)Math.round(start);
+ final int strlen = value.length();
+ int istart = (int)Math.round(start);
- if (Double.isNaN(start)) return("");
+ if (Double.isNaN(start)) return(EMPTYSTRING);
- return value.substring(istart < 1 ? 0 :
- istart > valuel ? valuel : istart - 1);
+ if ((istart < 1) || (istart > strlen)) istart = 0;
+
+ return value.substring(istart);
}
catch (IndexOutOfBoundsException e) {
runTimeInternalError();
@@ -256,18 +260,19 @@
*/
public static String substringF(String value, double start, double length) {
try {
- final int valuel = value.length();
- final int istart = (int)Math.round(start);
- final int ilength = (int)Math.round(length);
- final int isum = istart + ilength;
-
- if (Double.isNaN(start) || Double.isNaN(length)) return("");
-
- return value.substring(istart < 1 || istart > valuel
- ? 0 : istart - 1,
- ilength < 0
- ? 0 : isum - 1 > valuel
- ? valuel : isum < 1 ? 0 : isum - 1);
+ final int strlen = value.length();
+ int istart = (int)Math.round(start) - 1;
+ int isum = istart + (int)Math.round(length);
+
+ if (Double.isNaN(start) || Double.isNaN(length))
+ return(EMPTYSTRING);
+
+ if ((istart < 1) || (istart > strlen)) istart = 0;
+
+ if ((isum < 0) || (isum > strlen))
+ return value.substring(istart);
+ else
+ return value.substring(istart, isum);
}
catch (IndexOutOfBoundsException e) {
runTimeInternalError();
@@ -280,7 +285,10 @@
*/
public static String substring_afterF(String value, String substring) {
final int index = value.indexOf(substring);
- return index >= 0 ? value.substring(index + substring.length()) : "";
+ if (index >= 0)
+ return value.substring(index + substring.length());
+ else
+ return EMPTYSTRING;
}
/**
@@ -288,7 +296,10 @@
*/
public static String substring_beforeF(String value, String substring) {
final int index = value.indexOf(substring);
- return index >= 0 ? value.substring(0, index) : "";
+ if (index >= 0)
+ return value.substring(0, index);
+ else
+ return EMPTYSTRING;
}
/**
@@ -351,7 +362,12 @@
* XSLT Standard function generate-id().
*/
public static String generate_idF(int node) {
- return "N" + node;
+ if (node > 0)
+ // Only generate ID if node exists
+ return "N" + node;
+ else
+ // Otherwise return an empty string
+ return EMPTYSTRING;
}
/**
@@ -398,7 +414,7 @@
runTimeError("Invalid argument type '"+name+
"' in call to system-property().");
- return("");
+ return(EMPTYSTRING);
}
/**
@@ -407,7 +423,10 @@
public static String namespace_uriF(int node, DOM dom) {
final String value = dom.getNodeName(node);
final int colon = value.lastIndexOf(':');
- return colon >= 0 ? value.substring(0, colon) : "";
+ if (colon >= 0)
+ return value.substring(0, colon);
+ else
+ return EMPTYSTRING;
}
//-- Begin utility functions
@@ -821,7 +840,7 @@
catch (IllegalArgumentException e) {
runTimeError("Attempting to format number '"+ number +
"' using pattern '" + pattern + "'.");
- return("");
+ return(EMPTYSTRING);
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]