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: DTMNodeList.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.DTMIterator;
025 import org.w3c.dom.Node;
026
027 /**
028 * <code>DTMNodeList</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 DTMNodeList extends DTMNodeListBase {
057 private DTMIterator m_iter;
058
059 //================================================================
060 // Methods unique to this class
061 private DTMNodeList() {
062 }
063
064 /**
065 * Public constructor: Wrap a DTMNodeList around an existing
066 * and preconfigured DTMIterator
067 *
068 * WARNING: THIS HAS THE SIDE EFFECT OF ISSUING setShouldCacheNodes(true)
069 * AGAINST THE DTMIterator.
070 *
071 */
072 public DTMNodeList(DTMIterator dtmIterator) {
073 if (dtmIterator != null) {
074 int pos = dtmIterator.getCurrentPos();
075 try {
076 m_iter=(DTMIterator)dtmIterator.cloneWithReset();
077 } catch(CloneNotSupportedException cnse) {
078 m_iter = dtmIterator;
079 }
080 m_iter.setShouldCacheNodes(true);
081 m_iter.runTo(-1);
082 m_iter.setCurrentPos(pos);
083 }
084 }
085
086 /**
087 * Access the wrapped DTMIterator. I'm not sure whether anyone will
088 * need this or not, but let's write it and think about it.
089 *
090 */
091 public DTMIterator getDTMIterator() {
092 return m_iter;
093 }
094
095 //================================================================
096 // org.w3c.dom.NodeList API follows
097
098 /**
099 * Returns the <code>index</code>th item in the collection. If
100 * <code>index</code> is greater than or equal to the number of nodes in
101 * the list, this returns <code>null</code>.
102 * @param index Index into the collection.
103 * @return The node at the <code>index</code>th position in the
104 * <code>NodeList</code>, or <code>null</code> if that is not a valid
105 * index.
106 */
107 public Node item(int index)
108 {
109 if (m_iter != null) {
110 int handle=m_iter.item(index);
111 if (handle == DTM.NULL) {
112 return null;
113 }
114 return m_iter.getDTM(handle).getNode(handle);
115 } else {
116 return null;
117 }
118 }
119
120 /**
121 * The number of nodes in the list. The range of valid child node indices
122 * is 0 to <code>length-1</code> inclusive.
123 */
124 public int getLength() {
125 return (m_iter != null) ? m_iter.getLength() : 0;
126 }
127 }