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: DTMNodeIterator.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.DTMDOMException;
025 import org.apache.xml.dtm.DTMIterator;
026
027 import org.w3c.dom.DOMException;
028 import org.w3c.dom.Node;
029 import org.w3c.dom.traversal.NodeFilter;
030
031 /**
032 * <code>DTMNodeIterator</code> gives us an implementation of the
033 * DTMNodeIterator which returns DOM nodes.
034 *
035 * Please note that this is not necessarily equivlaent to a DOM
036 * NodeIterator operating over the same document. In particular:
037 * <ul>
038 *
039 * <li>If there are several Text nodes in logical succession (ie,
040 * across CDATASection and EntityReference boundaries), we will return
041 * only the first; the caller is responsible for stepping through
042 * them.
043 * (%REVIEW% Provide a convenience routine here to assist, pending
044 * proposed DOM Level 3 getAdjacentText() operation?) </li>
045 *
046 * <li>Since the whole XPath/XSLT architecture assumes that the source
047 * document is not altered while we're working with it, we do not
048 * promise to implement the DOM NodeIterator's "maintain current
049 * position" response to document mutation. </li>
050 *
051 * <li>Since our design for XPath NodeIterators builds a stateful
052 * filter directly into the traversal object, getNodeFilter() is not
053 * supported.</li>
054 *
055 * </ul>
056 *
057 * <p>State: In progress!!</p>
058 * */
059 public class DTMNodeIterator implements org.w3c.dom.traversal.NodeIterator
060 {
061 private DTMIterator dtm_iter;
062 private boolean valid=true;
063
064 //================================================================
065 // Methods unique to this class
066
067 /** Public constructor: Wrap a DTMNodeIterator around an existing
068 * and preconfigured DTMIterator
069 * */
070 public DTMNodeIterator(DTMIterator dtmIterator)
071 {
072 try
073 {
074 dtm_iter=(DTMIterator)dtmIterator.clone();
075 }
076 catch(CloneNotSupportedException cnse)
077 {
078 throw new org.apache.xml.utils.WrappedRuntimeException(cnse);
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 public DTMIterator getDTMIterator()
086 {
087 return dtm_iter;
088 }
089
090
091 //================================================================
092 // org.w3c.dom.traversal.NodeFilter API follows
093
094 /** Detaches the NodeIterator from the set which it iterated over,
095 * releasing any computational resources and placing the iterator in
096 * the INVALID state.
097 * */
098 public void detach()
099 {
100 // Theoretically, we could release dtm_iter at this point. But
101 // some of the operations may still want to consult it even though
102 // navigation is now invalid.
103 valid=false;
104 }
105
106 /** The value of this flag determines whether the children
107 * of entity reference nodes are visible to the iterator.
108 *
109 * @return false, always (the DTM model flattens entity references)
110 * */
111 public boolean getExpandEntityReferences()
112 {
113 return false;
114 }
115
116 /** Return a handle to the filter used to screen nodes.
117 *
118 * This is ill-defined in Xalan's usage of Nodeiterator, where we have
119 * built stateful XPath-based filtering directly into the traversal
120 * object. We could return something which supports the NodeFilter interface
121 * and allows querying whether a given node would be permitted if it appeared
122 * as our next node, but in the current implementation that would be very
123 * complex -- and just isn't all that useful.
124 *
125 * @throws DOMException -- NOT_SUPPORTED_ERROR because I can't think
126 * of anything more useful to do in this case
127 * */
128 public NodeFilter getFilter()
129 {
130 throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
131 }
132
133
134 /** @return The root node of the NodeIterator, as specified
135 * when it was created.
136 * */
137 public Node getRoot()
138 {
139 int handle=dtm_iter.getRoot();
140 return dtm_iter.getDTM(handle).getNode(handle);
141 }
142
143
144 /** Return a mask describing which node types are presented via the
145 * iterator.
146 **/
147 public int getWhatToShow()
148 {
149 return dtm_iter.getWhatToShow();
150 }
151
152 /** @return the next node in the set and advance the position of the
153 * iterator in the set.
154 *
155 * @throws DOMException - INVALID_STATE_ERR Raised if this method is
156 * called after the detach method was invoked.
157 * */
158 public Node nextNode() throws DOMException
159 {
160 if(!valid)
161 throw new DTMDOMException(DOMException.INVALID_STATE_ERR);
162
163 int handle=dtm_iter.nextNode();
164 if (handle==DTM.NULL)
165 return null;
166 return dtm_iter.getDTM(handle).getNode(handle);
167 }
168
169
170 /** @return the next previous in the set and advance the position of the
171 * iterator in the set.
172 *
173 * @throws DOMException - INVALID_STATE_ERR Raised if this method is
174 * called after the detach method was invoked.
175 * */
176 public Node previousNode()
177 {
178 if(!valid)
179 throw new DTMDOMException(DOMException.INVALID_STATE_ERR);
180
181 int handle=dtm_iter.previousNode();
182 if (handle==DTM.NULL)
183 return null;
184 return dtm_iter.getDTM(handle).getNode(handle);
185 }
186 }