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 }