001: /*
002: * Copyright 1999-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: /*
017: * $Id: DTMAxisIterNodeList.java,v 1.4 2005/01/24 00:34:35 mcnamara Exp $
018: */
019: package org.apache.xml.dtm.ref;
020:
021: import org.apache.xml.dtm.DTM;
022: import org.apache.xml.dtm.DTMAxisIterator;
023: import org.apache.xml.utils.IntVector;
024:
025: import org.w3c.dom.Node;
026:
027: /**
028: * <code>DTMAxisNodeList</code> gives us an implementation of the DOM's
029: * NodeList interface wrapped around a DTM Iterator. The author
030: * considers this something of an abominations, since NodeList was not
031: * intended to be a general purpose "list of nodes" API and is
032: * generally considered by the DOM WG to have be a mistake... but I'm
033: * told that some of the XPath/XSLT folks say they must have this
034: * solution.
035: *
036: * Please note that this is not necessarily equivlaent to a DOM
037: * NodeList operating over the same document. In particular:
038: * <ul>
039: *
040: * <li>If there are several Text nodes in logical succession (ie,
041: * across CDATASection and EntityReference boundaries), we will return
042: * only the first; the caller is responsible for stepping through
043: * them.
044: * (%REVIEW% Provide a convenience routine here to assist, pending
045: * proposed DOM Level 3 getAdjacentText() operation?) </li>
046: *
047: * <li>Since the whole XPath/XSLT architecture assumes that the source
048: * document is not altered while we're working with it, we do not
049: * promise to implement the DOM NodeList's "live view" response to
050: * document mutation. </li>
051: *
052: * </ul>
053: *
054: * <p>State: In progress!!</p>
055: * */
056: public class DTMAxisIterNodeList extends DTMNodeListBase {
057: private DTM m_dtm;
058: private DTMAxisIterator m_iter;
059: private IntVector m_cachedNodes;
060: private int m_last = -1;
061:
062: //================================================================
063: // Methods unique to this class
064: private DTMAxisIterNodeList() {
065: }
066:
067: /**
068: * Public constructor: Wrap a DTMNodeList around an existing
069: * and preconfigured DTMAxisIterator
070: */
071: public DTMAxisIterNodeList(DTM dtm, DTMAxisIterator dtmAxisIterator) {
072: if (dtmAxisIterator == null) {
073: m_last = 0;
074: } else {
075: m_cachedNodes = new IntVector();
076: m_dtm = dtm;
077: }
078: m_iter = dtmAxisIterator;
079: }
080:
081: /**
082: * Access the wrapped DTMIterator. I'm not sure whether anyone will
083: * need this or not, but let's write it and think about it.
084: *
085: */
086: public DTMAxisIterator getDTMAxisIterator() {
087: return m_iter;
088: }
089:
090: //================================================================
091: // org.w3c.dom.NodeList API follows
092:
093: /**
094: * Returns the <code>index</code>th item in the collection. If
095: * <code>index</code> is greater than or equal to the number of nodes in
096: * the list, this returns <code>null</code>.
097: * @param index Index into the collection.
098: * @return The node at the <code>index</code>th position in the
099: * <code>NodeList</code>, or <code>null</code> if that is not a valid
100: * index.
101: */
102: public Node item(int index) {
103: if (m_iter != null) {
104: int node;
105: int count = m_cachedNodes.size();
106:
107: if (count > index) {
108: node = m_cachedNodes.elementAt(index);
109: return m_dtm.getNode(node);
110: } else if (m_last == -1) {
111: while (((node = m_iter.next()) != DTMAxisIterator.END)
112: && count <= index) {
113: m_cachedNodes.addElement(node);
114: count++;
115: }
116: if (node == DTMAxisIterator.END) {
117: m_last = count;
118: } else {
119: return m_dtm.getNode(node);
120: }
121: }
122: }
123: return null;
124: }
125:
126: /**
127: * The number of nodes in the list. The range of valid child node indices
128: * is 0 to <code>length-1</code> inclusive.
129: */
130: public int getLength() {
131: if (m_last == -1) {
132: int node;
133: while ((node = m_iter.next()) != DTMAxisIterator.END) {
134: m_cachedNodes.addElement(node);
135: }
136: m_last = m_cachedNodes.size();
137: }
138: return m_last;
139: }
140: }
|