1/* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18/* 19 * $Id: DTMAxisIterNodeList.java 468653 2006-10-28 07:07:05Z minchau $ 20 */ 21package org.apache.xml.dtm.ref; 22 23import org.apache.xml.dtm.DTM; 24import org.apache.xml.dtm.DTMAxisIterator; 25import org.apache.xml.utils.IntVector; 26 27import org.w3c.dom.Node; 28 29/** 30 * <code>DTMAxisNodeList</code> gives us an implementation of the DOM's 31 * NodeList interface wrapped around a DTM Iterator. The author 32 * considers this something of an abominations, since NodeList was not 33 * intended to be a general purpose "list of nodes" API and is 34 * generally considered by the DOM WG to have be a mistake... but I'm 35 * told that some of the XPath/XSLT folks say they must have this 36 * solution. 37 * 38 * Please note that this is not necessarily equivlaent to a DOM 39 * NodeList operating over the same document. In particular: 40 * <ul> 41 * 42 * <li>If there are several Text nodes in logical succession (ie, 43 * across CDATASection and EntityReference boundaries), we will return 44 * only the first; the caller is responsible for stepping through 45 * them. 46 * (%REVIEW% Provide a convenience routine here to assist, pending 47 * proposed DOM Level 3 getAdjacentText() operation?) </li> 48 * 49 * <li>Since the whole XPath/XSLT architecture assumes that the source 50 * document is not altered while we're working with it, we do not 51 * promise to implement the DOM NodeList's "live view" response to 52 * document mutation. </li> 53 * 54 * </ul> 55 * 56 * <p>State: In progress!!</p> 57 * */ 58public class DTMAxisIterNodeList extends DTMNodeListBase { 59 private DTM m_dtm; 60 private DTMAxisIterator m_iter; 61 private IntVector m_cachedNodes; 62 private int m_last = -1; 63 //================================================================ 64 // Methods unique to this class 65 private DTMAxisIterNodeList() { 66 } 67 68 /** 69 * Public constructor: Wrap a DTMNodeList around an existing 70 * and preconfigured DTMAxisIterator 71 */ 72 public DTMAxisIterNodeList(DTM dtm, DTMAxisIterator dtmAxisIterator) { 73 if (dtmAxisIterator == null) { 74 m_last = 0; 75 } else { 76 m_cachedNodes = new IntVector(); 77 m_dtm = dtm; 78 } 79 m_iter = dtmAxisIterator; 80 } 81 82 /** 83 * Access the wrapped DTMIterator. I'm not sure whether anyone will 84 * need this or not, but let's write it and think about it. 85 * 86 */ 87 public DTMAxisIterator getDTMAxisIterator() { 88 return m_iter; 89 } 90 91 92 //================================================================ 93 // org.w3c.dom.NodeList API follows 94 95 /** 96 * Returns the <code>index</code>th item in the collection. If 97 * <code>index</code> is greater than or equal to the number of nodes in 98 * the list, this returns <code>null</code>. 99 * @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} 143