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: DTMNodeIterator.java 468653 2006-10-28 07:07:05Z minchau $ 20 */ 21 package org.apache.xml.dtm.ref; 22 23 import org.apache.xml.dtm.DTM; 24 import org.apache.xml.dtm.DTMDOMException; 25 import org.apache.xml.dtm.DTMIterator; 26 27 import org.w3c.dom.DOMException; 28 import org.w3c.dom.Node; 29 import org.w3c.dom.traversal.NodeFilter; 30 31 /** 32 * <code>DTMNodeIterator</code> gives us an implementation of the 33 * DTMNodeIterator which returns DOM nodes. 34 * 35 * Please note that this is not necessarily equivlaent to a DOM 36 * NodeIterator operating over the same document. In particular: 37 * <ul> 38 * 39 * <li>If there are several Text nodes in logical succession (ie, 40 * across CDATASection and EntityReference boundaries), we will return 41 * only the first; the caller is responsible for stepping through 42 * them. 43 * (%REVIEW% Provide a convenience routine here to assist, pending 44 * proposed DOM Level 3 getAdjacentText() operation?) </li> 45 * 46 * <li>Since the whole XPath/XSLT architecture assumes that the source 47 * document is not altered while we're working with it, we do not 48 * promise to implement the DOM NodeIterator's "maintain current 49 * position" response to document mutation. </li> 50 * 51 * <li>Since our design for XPath NodeIterators builds a stateful 52 * filter directly into the traversal object, getNodeFilter() is not 53 * supported.</li> 54 * 55 * </ul> 56 * 57 * <p>State: In progress!!</p> 58 * */ 59 public class DTMNodeIterator implements org.w3c.dom.traversal.NodeIterator 60 { 61 private DTMIterator dtm_iter; 62 private boolean valid=true; 63 64 //================================================================ 65 // Methods unique to this class 66 67 /** Public constructor: Wrap a DTMNodeIterator around an existing 68 * and preconfigured DTMIterator 69 * */ 70 public DTMNodeIterator(DTMIterator dtmIterator) 71 { 72 try 73 { 74 dtm_iter=(DTMIterator)dtmIterator.clone(); 75 } 76 catch(CloneNotSupportedException cnse) 77 { 78 throw new org.apache.xml.utils.WrappedRuntimeException(cnse); 79 } 80 } 81 82 /** Access the wrapped DTMIterator. I'm not sure whether anyone will 83 * need this or not, but let's write it and think about it. 84 * */ 85 public DTMIterator getDTMIterator() 86 { 87 return dtm_iter; 88 } 89 90 91 //================================================================ 92 // org.w3c.dom.traversal.NodeFilter API follows 93 94 /** Detaches the NodeIterator from the set which it iterated over, 95 * releasing any computational resources and placing the iterator in 96 * the INVALID state. 97 * */ 98 public void detach() 99 { 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 } 187