- /*
- * Copyright 2001-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /*
- * $Id: KeyIndex.java,v 1.13 2004/02/16 22:54:59 minchau Exp $
- */
-
- package com.sun.org.apache.xalan.internal.xsltc.dom;
-
- import java.util.StringTokenizer;
-
- import com.sun.org.apache.xalan.internal.xsltc.DOM;
- import com.sun.org.apache.xalan.internal.xsltc.DOMEnhancedForDTM;
- import com.sun.org.apache.xalan.internal.xsltc.runtime.Hashtable;
- import com.sun.org.apache.xalan.internal.xsltc.util.IntegerArray;
- import com.sun.org.apache.xml.internal.dtm.DTM;
- import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
- import com.sun.org.apache.xml.internal.dtm.ref.DTMAxisIteratorBase;
-
- /**
- * @author Morten Jorgensen
- * @author Santiago Pericas-Geertsen
- */
- public class KeyIndex extends DTMAxisIteratorBase {
-
- /**
- * A mapping between values and nodesets.
- */
- private Hashtable _index = new Hashtable();
-
- /**
- * The node set associated to the current value passed
- * to lookupKey();
- */
- private IntegerArray _nodes = null;
-
- /**
- * The XSLTC DOM object if this KeyIndex is being used to implement the
- * id() function.
- */
- private DOM _dom;
-
- private DOMEnhancedForDTM _enhancedDOM;
-
- /**
- * Store position after call to setMark()
- */
- private int _markedPosition = 0;
-
- public KeyIndex(int dummy) {
- }
-
- public void setRestartable(boolean flag) {
- }
-
- /**
- * 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) {
- IntegerArray nodes;
- if ((nodes = (IntegerArray) _index.get(value)) == null) {
- _index.put(value, nodes = new IntegerArray());
- }
- nodes.add(node);
- }
-
- /**
- * Merge the current value's nodeset set by lookupKey() with _nodes.
- */
- public void merge(KeyIndex other) {
- if (other == null) return;
-
- if (other._nodes != null) {
- if (_nodes == null) {
- _nodes = other._nodes;
- }
- else {
- _nodes.merge(other._nodes);
- }
- }
- }
-
- /**
- * This method must be called by the code generated by the id() function
- * prior to returning the node iterator. The lookup code for key() and
- * id() differ in the way the lookup value can be whitespace separated
- * list of tokens for the id() function, but a single string for the
- * key() function.
- */
- public void lookupId(Object value) {
- // Clear _nodes array
- _nodes = null;
-
- final StringTokenizer values = new StringTokenizer((String) value);
- while (values.hasMoreElements()) {
- final String token = (String) values.nextElement();
- IntegerArray nodes = (IntegerArray) _index.get(token);
-
- if (nodes == null && _enhancedDOM != null
- && _enhancedDOM.hasDOMSource()) {
- nodes = getDOMNodeById(token);
- }
-
- if (nodes == null) continue;
-
- if (_nodes == null) {
- _nodes = nodes;
- }
- else {
- _nodes.merge(nodes);
- }
- }
- }
-
- /**
- * Return an IntegerArray for the DOM Node which has the given id.
- *
- * @param id The id
- * @return A IntegerArray representing the Node whose id is the given value.
- */
- public IntegerArray getDOMNodeById(String id) {
- IntegerArray nodes = null;
- if (_enhancedDOM != null) {
- int ident = _enhancedDOM.getElementById(id);
- if (ident != DTM.NULL) {
- nodes = new IntegerArray();
- _index.put(id, nodes);
- nodes.add(ident);
- }
- }
- return nodes;
- }
-
- /**
- * This method must be called by the code generated by the key() function
- * prior to returning the node iterator.
- */
- public void lookupKey(Object value) {
- _nodes = (IntegerArray) _index.get(value);
- _position = 0;
- }
-
- /**
- * Callers should not call next() after it returns END.
- */
- public int next() {
- if (_nodes == null) return DTMAxisIterator.END;
-
- return (_position < _nodes.cardinality()) ?
- _dom.getNodeHandle(_nodes.at(_position++)) : DTMAxisIterator.END;
- }
-
- public int containsID(int node, Object value) {
- final String string = (String)value;
- if (string.indexOf(' ') > -1) {
- final StringTokenizer values = new StringTokenizer(string);
-
- while (values.hasMoreElements()) {
- final String token = (String) values.nextElement();
- IntegerArray nodes = (IntegerArray) _index.get(token);
-
- if (nodes == null && _enhancedDOM != null
- && _enhancedDOM.hasDOMSource()) {
- nodes = getDOMNodeById(token);
- }
- if (nodes != null && nodes.indexOf(node) >= 0) {
- return 1;
- }
- }
- return 0;
- }
- else {
- IntegerArray nodes = (IntegerArray) _index.get(value);
- if (nodes == null && _enhancedDOM != null && _enhancedDOM.hasDOMSource()) {
- nodes = getDOMNodeById(string);
- }
- return (nodes != null && nodes.indexOf(node) >= 0) ? 1 : 0;
- }
- }
-
- public int containsKey(int node, Object value) {
- final IntegerArray nodes = (IntegerArray) _index.get(value);
- return (nodes != null && nodes.indexOf(node) >= 0) ? 1 : 0;
- }
-
- /**
- * Resets the iterator to the last start node.
- */
- public DTMAxisIterator reset() {
- _position = 0;
- return this;
- }
-
- /**
- * Returns the number of elements in this iterator.
- */
- public int getLast() {
- return (_nodes == null) ? 0 : _nodes.cardinality();
- }
-
- /**
- * Returns the position of the current node in the set.
- */
- public int getPosition() {
- return _position;
- }
-
- /**
- * Remembers the current node for the next call to gotoMark().
- */
- public void setMark() {
- _markedPosition = _position;
- }
-
- /**
- * Restores the current node remembered by setMark().
- */
- public void gotoMark() {
- _position = _markedPosition;
- }
-
- /**
- * Set start to END should 'close' the iterator,
- * i.e. subsequent call to next() should return END.
- */
- public DTMAxisIterator setStartNode(int start) {
- if (start == DTMAxisIterator.END) {
- _nodes = null;
- }
- else if (_nodes != null) {
- _position = 0;
- }
- return (DTMAxisIterator) this;
- }
-
- /**
- * Get start to END should 'close' the iterator,
- * i.e. subsequent call to next() should return END.
- */
- public int getStartNode() {
- return 0;
- }
-
- /**
- * True if this iterator has a reversed axis.
- */
- public boolean isReverse() {
- return(false);
- }
-
- /**
- * Returns a deep copy of this iterator.
- */
- public DTMAxisIterator cloneIterator() {
- KeyIndex other = new KeyIndex(0);
- other._index = _index;
- other._nodes = _nodes;
- other._position = _position;
- return (DTMAxisIterator) other;
- }
-
- public void setDom(DOM dom) {
- _dom = dom;
- if (dom instanceof DOMEnhancedForDTM) {
- _enhancedDOM = (DOMEnhancedForDTM)dom;
- }
- else if (dom instanceof DOMAdapter) {
- DOM idom = ((DOMAdapter)dom).getDOMImpl();
- if (idom instanceof DOMEnhancedForDTM) {
- _enhancedDOM = (DOMEnhancedForDTM)idom;
- }
- }
- }
- }