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