1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22 package com.sun.org.apache.xml.internal.dtm.ref; 23 24 import com.sun.org.apache.xml.internal.dtm.DTM; 25 26 import org.w3c.dom.DOMException; 27 import org.w3c.dom.NamedNodeMap; 28 import org.w3c.dom.Node; 29 30 /** 31 * DTMNamedNodeMap is a quickie (as opposed to quick) implementation of the DOM's 32 * NamedNodeMap interface, intended to support DTMProxy's getAttributes() 33 * call. 34 * <p> 35 * ***** Note: this does _not_ current attempt to cache any of the data; 36 * if you ask for attribute 27 and then 28, you'll have to rescan the first 37 * 27. It should probably at least keep track of the last one retrieved, 38 * and possibly buffer the whole array. 39 * <p> 40 * ***** Also note that there's no fastpath for the by-name query; we search 41 * linearly until we find it or fail to find it. Again, that could be 42 * optimized at some cost in object creation/storage. 43 * @xsl.usage internal 44 */ 45 public class DTMNamedNodeMap implements NamedNodeMap 46 { 47 48 /** The DTM for this node. */ 49 DTM dtm; 50 51 /** The DTM element handle. */ 52 int element; 53 54 /** The number of nodes in this map. */ 55 short m_count = -1; 56 57 /** 58 * Create a getAttributes NamedNodeMap for a given DTM element node 59 * 60 * @param dtm The DTM Reference, must be non-null. 61 * @param element The DTM element handle. 62 */ DTMNamedNodeMap(DTM dtm, int element)63 public DTMNamedNodeMap(DTM dtm, int element) 64 { 65 this.dtm = dtm; 66 this.element = element; 67 } 68 69 /** 70 * Return the number of Attributes on this Element 71 * 72 * @return The number of nodes in this map. 73 */ getLength()74 public int getLength() 75 { 76 77 if (m_count == -1) 78 { 79 short count = 0; 80 81 for (int n = dtm.getFirstAttribute(element); n != -1; 82 n = dtm.getNextAttribute(n)) 83 { 84 ++count; 85 } 86 87 m_count = count; 88 } 89 90 return (int) m_count; 91 } 92 93 /** 94 * Retrieves a node specified by name. 95 * @param name The <code>nodeName</code> of a node to retrieve. 96 * @return A <code>Node</code> (of any type) with the specified 97 * <code>nodeName</code>, or <code>null</code> if it does not identify 98 * any node in this map. 99 */ getNamedItem(String name)100 public Node getNamedItem(String name) 101 { 102 103 for (int n = dtm.getFirstAttribute(element); n != DTM.NULL; 104 n = dtm.getNextAttribute(n)) 105 { 106 if (dtm.getNodeName(n).equals(name)) 107 return dtm.getNode(n); 108 } 109 110 return null; 111 } 112 113 /** 114 * Returns the <code>index</code>th item in the map. If <code>index</code> 115 * is greater than or equal to the number of nodes in this map, this 116 * returns <code>null</code>. 117 * @param i The index of the requested item. 118 * @return The node at the <code>index</code>th position in the map, or 119 * <code>null</code> if that is not a valid index. 120 */ item(int i)121 public Node item(int i) 122 { 123 124 int count = 0; 125 126 for (int n = dtm.getFirstAttribute(element); n != -1; 127 n = dtm.getNextAttribute(n)) 128 { 129 if (count == i) 130 return dtm.getNode(n); 131 else 132 ++count; 133 } 134 135 return null; 136 } 137 138 /** 139 * Adds a node using its <code>nodeName</code> attribute. If a node with 140 * that name is already present in this map, it is replaced by the new 141 * one. 142 * <br>As the <code>nodeName</code> attribute is used to derive the name 143 * which the node must be stored under, multiple nodes of certain types 144 * (those that have a "special" string value) cannot be stored as the 145 * names would clash. This is seen as preferable to allowing nodes to be 146 * aliased. 147 * @param newNode node to store in this map. The node will later be 148 * accessible using the value of its <code>nodeName</code> attribute. 149 * 150 * @return If the new <code>Node</code> replaces an existing node the 151 * replaced <code>Node</code> is returned, otherwise <code>null</code> 152 * is returned. 153 * @exception DOMException 154 * WRONG_DOCUMENT_ERR: Raised if <code>arg</code> was created from a 155 * different document than the one that created this map. 156 * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly. 157 * <br>INUSE_ATTRIBUTE_ERR: Raised if <code>arg</code> is an 158 * <code>Attr</code> that is already an attribute of another 159 * <code>Element</code> object. The DOM user must explicitly clone 160 * <code>Attr</code> nodes to re-use them in other elements. 161 */ setNamedItem(Node newNode)162 public Node setNamedItem(Node newNode) 163 { 164 throw new DTMException(DTMException.NO_MODIFICATION_ALLOWED_ERR); 165 } 166 167 /** 168 * Removes a node specified by name. When this map contains the attributes 169 * attached to an element, if the removed attribute is known to have a 170 * default value, an attribute immediately appears containing the 171 * default value as well as the corresponding namespace URI, local name, 172 * and prefix when applicable. 173 * @param name The <code>nodeName</code> of the node to remove. 174 * 175 * @return The node removed from this map if a node with such a name 176 * exists. 177 * @exception DOMException 178 * NOT_FOUND_ERR: Raised if there is no node named <code>name</code> in 179 * this map. 180 * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly. 181 */ removeNamedItem(String name)182 public Node removeNamedItem(String name) 183 { 184 throw new DTMException(DTMException.NO_MODIFICATION_ALLOWED_ERR); 185 } 186 187 /** 188 * Retrieves a node specified by local name and namespace URI. HTML-only 189 * DOM implementations do not need to implement this method. 190 * @param namespaceURI The namespace URI of the node to retrieve. 191 * @param localName The local name of the node to retrieve. 192 * 193 * @return A <code>Node</code> (of any type) with the specified local 194 * name and namespace URI, or <code>null</code> if they do not 195 * identify any node in this map. 196 * @since DOM Level 2 197 */ getNamedItemNS(String namespaceURI, String localName)198 public Node getNamedItemNS(String namespaceURI, String localName) 199 { 200 Node retNode = null; 201 for (int n = dtm.getFirstAttribute(element); n != DTM.NULL; 202 n = dtm.getNextAttribute(n)) 203 { 204 if (localName.equals(dtm.getLocalName(n))) 205 { 206 String nsURI = dtm.getNamespaceURI(n); 207 if ((namespaceURI == null && nsURI == null) 208 || (namespaceURI != null && namespaceURI.equals(nsURI))) 209 { 210 retNode = dtm.getNode(n); 211 break; 212 } 213 } 214 } 215 return retNode; 216 } 217 218 /** 219 * Adds a node using its <code>namespaceURI</code> and 220 * <code>localName</code>. If a node with that namespace URI and that 221 * local name is already present in this map, it is replaced by the new 222 * one. 223 * <br>HTML-only DOM implementations do not need to implement this method. 224 * @param arg A node to store in this map. The node will later be 225 * accessible using the value of its <code>namespaceURI</code> and 226 * <code>localName</code> attributes. 227 * 228 * @return If the new <code>Node</code> replaces an existing node the 229 * replaced <code>Node</code> is returned, otherwise <code>null</code> 230 * is returned. 231 * @exception DOMException 232 * WRONG_DOCUMENT_ERR: Raised if <code>arg</code> was created from a 233 * different document than the one that created this map. 234 * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly. 235 * <br>INUSE_ATTRIBUTE_ERR: Raised if <code>arg</code> is an 236 * <code>Attr</code> that is already an attribute of another 237 * <code>Element</code> object. The DOM user must explicitly clone 238 * <code>Attr</code> nodes to re-use them in other elements. 239 * @since DOM Level 2 240 */ setNamedItemNS(Node arg)241 public Node setNamedItemNS(Node arg) throws DOMException 242 { 243 throw new DTMException(DTMException.NO_MODIFICATION_ALLOWED_ERR); 244 } 245 246 /** 247 * Removes a node specified by local name and namespace URI. A removed 248 * attribute may be known to have a default value when this map contains 249 * the attributes attached to an element, as returned by the attributes 250 * attribute of the <code>Node</code> interface. If so, an attribute 251 * immediately appears containing the default value as well as the 252 * corresponding namespace URI, local name, and prefix when applicable. 253 * <br>HTML-only DOM implementations do not need to implement this method. 254 * 255 * @param namespaceURI The namespace URI of the node to remove. 256 * @param localName The local name of the node to remove. 257 * 258 * @return The node removed from this map if a node with such a local 259 * name and namespace URI exists. 260 * @exception DOMException 261 * NOT_FOUND_ERR: Raised if there is no node with the specified 262 * <code>namespaceURI</code> and <code>localName</code> in this map. 263 * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly. 264 * @since DOM Level 2 265 */ removeNamedItemNS(String namespaceURI, String localName)266 public Node removeNamedItemNS(String namespaceURI, String localName) 267 throws DOMException 268 { 269 throw new DTMException(DTMException.NO_MODIFICATION_ALLOWED_ERR); 270 } 271 272 /** 273 * Simple implementation of DOMException. 274 * @xsl.usage internal 275 */ 276 public class DTMException extends org.w3c.dom.DOMException 277 { 278 static final long serialVersionUID = -8290238117162437678L; 279 /** 280 * Constructs a DOM/DTM exception. 281 * 282 * @param code 283 * @param message 284 */ DTMException(short code, String message)285 public DTMException(short code, String message) 286 { 287 super(code, message); 288 } 289 290 /** 291 * Constructor DTMException 292 * 293 * 294 * @param code 295 */ DTMException(short code)296 public DTMException(short code) 297 { 298 super(code, ""); 299 } 300 } 301 } 302