santiagopg    2002/10/14 10:07:52

  Modified:    java/src/org/apache/xalan/xsltc/compiler Key.java
                        KeyCall.java
               java/src/org/apache/xalan/xsltc/dom KeyIndex.java
               java/src/org/apache/xalan/xsltc/util IntegerArray.java
  Log:
  (1) Fixed some dynamic typing problems with idkeys. Values are now properly
  converted to strings before they are compared.
  (2) Eliminated the use of BitArrays in KeyIndex (better space efficiency).
  (3) All idkey tests now pass with flavor=stream (the 6 failures that are
  reported are due to the use of a different algorithm to generate ids).
  
  Revision  Changes    Path
  1.12      +33 -52    
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.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- Key.java  10 May 2002 15:40:02 -0000      1.11
  +++ Key.java  14 Oct 2002 17:07:52 -0000      1.12
  @@ -57,6 +57,7 @@
    * <http://www.apache.org/>.
    *
    * @author Morten Jorgensen
  + * @author Santiago Pericas-Geertsen
    *
    */
   
  @@ -75,10 +76,25 @@
   
   final class Key extends TopLevelElement {
   
  -    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
  +    /**
  +     * The name of this key as defined in xsl:key.
  +     */
  +    private QName _name;
  +
  +    /**
  +     * The pattern to match starting at the root node.
  +     */
  +    private Pattern _match; 
  +
  +    /**
  +     * The expression that generates the values for this key.
  +     */
  +    private Expression _use;
  +
  +    /**
  +     * The type of the _use expression.
  +     */
  +    private Type _useType;
   
       /**
        * Parse the <xsl:key> element and attributes
  @@ -114,30 +130,16 @@
        return _name.toString();
       }
   
  -    /**
  -     * 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 {
  +     // Type check match pattern
        _match.typeCheck(stable);
  -     _useType = _use.typeCheck(stable);
   
  -     // Cast node values to string values
  -     if (_useType instanceof NodeType) {
  +     // Cast node values to string values (except for nodesets)
  +     _useType = _use.typeCheck(stable);
  +     if (_useType instanceof StringType == false &&
  +         _useType instanceof NodeSetType == false) 
  +     {
            _use = new CastExpr(_use, Type.String);
  -         _useType = Type.String;
  -     }
  -
  -     // If the 'use' attribute is not a string, node-set or number
  -     if (!(_useType instanceof StringType) &&
  -         !(_useType instanceof NodeSetType) &&
  -         !(_useType instanceof RealType)) {
  -         ErrorMsg err = new ErrorMsg(ErrorMsg.KEY_USE_ATTR_ERR, this);
  -         throw new TypeCheckError(err);
        }
   
        return Type.Void;
  @@ -147,8 +149,6 @@
        * 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,
  @@ -186,7 +186,6 @@
   
        // Prepare to call buildKeyIndex(String name, int node, String value);
        il.append(classGen.loadTranslet());
  -     // il.append(new PUSH(cpg, getName()));
        il.append(new PUSH(cpg, _name.toString()));
        il.append(new ILOAD(parentNode.getIndex()));
   
  @@ -213,8 +212,6 @@
       /**
        * 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) {
   
  @@ -255,34 +252,18 @@
        _match.synthesize(classGen, methodGen); // Leaves 0 or 1 on stack
        final BranchHandle skipNode = il.append(new IFEQ(null));
        
  -     // 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 RealType) {
  -         final int dbl = cpg.addMethodref(DOUBLE_CLASS,"<init>", "(D)V");
  -
  -         il.append(classGen.loadTranslet());
  -         il.append(new PUSH(cpg, _name.toString()));
  +     // If this is a node-set we must go through each node in the set
  +     if (_useType instanceof NodeSetType) {
  +         // Pass current node as parameter (we're indexing on that node)
            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));
  -
  +         traverseNodeSet(classGen, methodGen, key);
        }
  -     else if (_useType instanceof StringType) {
  +     else {
            il.append(classGen.loadTranslet());
            il.append(new PUSH(cpg, _name.toString()));
            il.append(methodGen.loadCurrentNode());
  -         _use.translate(classGen,methodGen);
  +         _use.translate(classGen, methodGen);
            il.append(new INVOKEVIRTUAL(key));
  -     }
  -     // If this is a node-set we must go through each node in the set
  -     // and create one entry in the key index for each node in the set.
  -     else {
  -         // Pass current node as parameter (we're indexing on that node)
  -         il.append(methodGen.loadCurrentNode());
  -         traverseNodeSet(classGen,methodGen,key);
        }
        
        // Get the next node from the iterator and do loop again...
  
  
  
  1.9       +25 -22    
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.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- KeyCall.java      10 May 2002 15:40:02 -0000      1.8
  +++ KeyCall.java      14 Oct 2002 17:07:52 -0000      1.9
  @@ -57,6 +57,7 @@
    * <http://www.apache.org/>.
    *
    * @author Morten Jorgensen
  + * @author Santiago Pericas-Geertsen
    *
    */
   
  @@ -70,10 +71,25 @@
   
   final class KeyCall extends FunctionCall {
   
  -    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
  -    private QName      _resolvedQName = null;
  +    /**
  +     * The name of the key.
  +     */
  +    private Expression _name;
  +
  +    /**
  +     * The value to look up in the key/index.
  +     */
  +    private Expression _value;
  +
  +    /**
  +     * The value's data type.
  +     */
  +    private Type _valueType; // The value's data type
  +
  +    /**
  +     * Expanded qname when name is literal.
  +     */
  +    private QName _resolvedQName = null;
   
       /**
        * Get the parameters passed to function:
  @@ -138,11 +154,9 @@
        // be added to the resulting node-set.
        _valueType = _value.typeCheck(stable);
   
  -     if ((_valueType != Type.NodeSet) &&
  -         (_valueType != Type.ResultTree) &&
  -         (_valueType != Type.String) &&
  -         (_valueType != Type.Real) &&
  -         (_valueType != Type.Int)) {
  +     if (_valueType != Type.NodeSet && _valueType != Type.ResultTree
  +             && _valueType != Type.String) 
  +     {
            _value = new CastExpr(_value, Type.String);
        }
   
  @@ -324,18 +338,7 @@
            // the iterator should return.
            il.append(DUP);
   
  -         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);
  -         }
  +         _value.translate(classGen, methodGen);
   
            if (_name == null) {
                il.append(new INVOKEVIRTUAL(lookupId));
  
  
  
  1.9       +58 -62    
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.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- KeyIndex.java     8 Oct 2002 21:44:14 -0000       1.8
  +++ KeyIndex.java     14 Oct 2002 17:07:52 -0000      1.9
  @@ -57,12 +57,14 @@
    * <http://www.apache.org/>.
    *
    * @author Morten Jorgensen
  + * @author Santiago Pericas-Geertsen
    *
    */
   
   package org.apache.xalan.xsltc.dom;
   
   import java.util.Vector;
  +import java.util.Enumeration;
   import java.util.StringTokenizer;
   
   import org.apache.xalan.xsltc.DOM;
  @@ -73,34 +75,41 @@
   
   public class KeyIndex extends NodeIteratorBase {
   
  +    /**
  +     * A mapping between values and nodesets.
  +     */
       private Hashtable _index = new Hashtable();
  -    // private BitArray  _nodes = null;
  +
  +    /**
  +     * The node set associated to the current value passed
  +     * to lookupKey();
  +     */
       private IntegerArray _nodes = null;
  -    private int       _mark = 0;
  -    private int       _save = 0;
  -    private int       _start = 0;
  -    private int       _node = -1;
  +
  +    /**
  +     * Store position after call to setMark()
  +     */
  +    private int _markedPosition = 0;
   
       public KeyIndex(int dummy) {
       }
   
       /**
  -     * Adds a node to the node list for a given value.
  +     * Adds a node to the node list for a given value. Nodes will
  +     * always be added in document order.
        */
       public void add(Object value, int node) {
  -// System.out.println("KeyIndex.add() value = " + value + " node = " + node);
  -
  -     if ((_nodes = (IntegerArray) _index.get(value)) == null) {
  -         _index.put(value, _nodes = new IntegerArray());
  +     IntegerArray nodes;
  +     if ((nodes = (IntegerArray) _index.get(value)) == null) {
  +         _index.put(value, nodes = new IntegerArray());
        }
  -     _nodes.add(node);
  +     nodes.add(node);
       }
   
       /**
  -     * Merge this node set with nodes from another index
  +     * Merge the current value's nodeset set by lookupKey() with _nodes.
        */
       public void merge(KeyIndex other) {
  -// System.out.println("KeyIndex.merge()");
        if (other == null) return;
   
        if (other._nodes != null) {
  @@ -121,29 +130,23 @@
        * key() function.
        */
       public void lookupId(Object value) {
  -// System.out.println("KeyIndex.lookupId()");
  -     if (value instanceof String) {
  -         final String string = (String)value;
  -         if (string.indexOf(' ') > -1) {
  -             StringTokenizer values = new StringTokenizer(string);
  -
  -             while (values.hasMoreElements()) {
  -                 final IntegerArray nodes = 
  -                     (IntegerArray)_index.get(values.nextElement());
  -
  -                 if (nodes != null) {
  -                     if (_nodes == null) {
  -                         _nodes = nodes;
  -                     }
  -                     else {
  -                         _nodes.merge(nodes);
  -                     }
  -                 }
  -             }
  -             return;
  +     // Clear _nodes array
  +     _nodes = null;
  +
  +     final StringTokenizer values = new StringTokenizer((String) value);
  +     while (values.hasMoreElements()) {
  +         final IntegerArray nodes = 
  +             (IntegerArray) _index.get(values.nextElement());
  +
  +         if (nodes == null) continue;
  +
  +         if (_nodes == null) {
  +             _nodes = nodes;
  +         }
  +         else {
  +             _nodes.merge(nodes);
            }
        }
  -     _nodes = (IntegerArray) _index.get(value);
       }
   
       /**
  @@ -151,7 +154,6 @@
        * prior to returning the node iterator.
        */
       public void lookupKey(Object value) {
  -// System.out.println("KeyIndex.lookupKey() value = " + value);
        _nodes = (IntegerArray) _index.get(value);
        _position = 0;
       }
  @@ -160,7 +162,6 @@
        * Callers should not call next() after it returns END.
        */
       public int next() {
  -// System.out.println("KeyIndex.next() _nodes = " + _nodes);
        if (_nodes == null) return END;
   
        return (_position < _nodes.cardinality()) ? 
  @@ -168,24 +169,24 @@
       }
   
       public int containsID(int node, Object value) { 
  -     if (value instanceof String) {
  -         final String string = (String)value;
  -         if (string.indexOf(' ') > -1) {
  -             final StringTokenizer values = new StringTokenizer(string);
  -
  -             while (values.hasMoreElements()) {
  -                 final IntegerArray nodes = 
  -                     (IntegerArray) _index.get(values.nextElement());
  -                 if (nodes != null && nodes.indexOf(node) >= 0) {
  -                     return 1;
  -                 }
  +     final String string = (String)value;
  +     if (string.indexOf(' ') > -1) {
  +         final StringTokenizer values = new StringTokenizer(string);
  +
  +         while (values.hasMoreElements()) {
  +             final IntegerArray nodes = 
  +                 (IntegerArray) _index.get(values.nextElement());
  +
  +             if (nodes != null && nodes.indexOf(node) >= 0) {
  +                 return 1;
                }
  -             return 0;
            }
  +         return 0;
  +     }
  +     else {
  +         final IntegerArray nodes = (IntegerArray) _index.get(value);
  +         return (nodes != null && nodes.indexOf(node) >= 0) ? 1 : 0;
        }
  -
  -     final IntegerArray nodes = (IntegerArray) _index.get(value);
  -     return (nodes != null && nodes.indexOf(node) >= 0) ? 1 : 0;
       }
   
       public int containsKey(int node, Object value) { 
  @@ -197,8 +198,7 @@
        * Resets the iterator to the last start node.
        */
       public NodeIterator reset() {
  -     _position = _start;
  -     _node = _start - 1;
  +     _position = 0;
        return this;
       }
   
  @@ -220,16 +220,14 @@
        * Remembers the current node for the next call to gotoMark().
        */
       public void setMark() {
  -     _mark = _position;
  -     _save = _node;
  +     _markedPosition = _position;
       }
   
       /**
        * Restores the current node remembered by setMark().
        */
       public void gotoMark() {
  -     _position = _mark;
  -     _node = _save;
  +     _position = _markedPosition;
       }
   
       /** 
  @@ -252,10 +250,8 @@
       public NodeIterator cloneIterator() {
        KeyIndex other = new KeyIndex(0);
        other._index = _index;
  -     other._nodes = (_nodes == null) ? _nodes : (IntegerArray)_nodes.clone();
  -     other._start = _start;
  -     other._node  = _node;
  +     other._nodes = _nodes;
  +     other._position = _position;
        return other;
       }
  -
   }
  
  
  
  1.4       +44 -6     
xml-xalan/java/src/org/apache/xalan/xsltc/util/IntegerArray.java
  
  Index: IntegerArray.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/util/IntegerArray.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- IntegerArray.java 8 Oct 2002 21:44:15 -0000       1.3
  +++ IntegerArray.java 14 Oct 2002 17:07:52 -0000      1.4
  @@ -141,12 +141,50 @@
        }
       }
   
  -    public void merge(IntegerArray array) {
  -     final int n = array._free;
  -     for (int i = 0; i < n; i++) {
  -         addNew(array.at(i));
  +    /**
  +     * Merge two sorted arrays and eliminate duplicates. 
  +     */
  +    public void merge(IntegerArray other) {
  +     final int newSize = _free + other._free;
  +// System.out.println("IntegerArray.merge() begin newSize = " + newSize);
  +     int[] newArray = new int[newSize];
  +
  +     // Merge the two arrays
  +     int i = 0, j = 0, k;
  +     for (k = 0; i < _free && j < other._free; k++) {
  +         int x = _array[i];
  +         int y = other._array[j];
  +
  +         if (x < y) {
  +             newArray[k] = x;
  +             i++;
  +         }
  +         else if (x > y) {
  +             newArray[k] = y;
  +             j++;
  +         }
  +         else {
  +             newArray[k] = x;
  +             i++; j++;
  +         }
        }
  -     sort();         // must be sorted
  +
  +     // Copy the rest if of different lengths
  +     if (i >= _free) {
  +         while (j < other._free) {
  +             newArray[k++] = other._array[j++];
  +         }
  +     }
  +     else {
  +         while (i < _free) {
  +             newArray[k++] = _array[i++];
  +         }
  +     }
  +
  +     // Update reference to this array
  +     _array = newArray;
  +     _free = _size = newSize;
  +// System.out.println("IntegerArray.merge() end");
       }
   
       public void sort() {
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to