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