1 /********************************************** 2 * Copyright (C) 2010 Lukas Laag 3 * This file is part of lib-gwt-svg. 4 * 5 * libgwtsvg is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU Lesser General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * libgwtsvg is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with libgwtsvg. If not, see http://www.gnu.org/licenses/ 17 **********************************************/ 18 /* 19 * Copyright (c) 2004 World Wide Web Consortium, 20 * 21 * (Massachusetts Institute of Technology, European Research Consortium for 22 * Informatics and Mathematics, Keio University). All Rights Reserved. This 23 * work is distributed under the W3C(r) Software License [1] in the hope that 24 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied 25 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 26 * 27 * [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 28 */ 29 package org.vectomatic.dom.svg; 30 31 import java.util.Iterator; 32 33 import org.vectomatic.dom.svg.impl.NamedNodeMap; 34 import org.w3c.dom.DOMException; 35 36 import com.google.gwt.core.client.JavaScriptException; 37 import com.google.gwt.dom.client.Node; 38 39 /** 40 * Wrapper class for DOM NamedNodeMap 41 * @author laaglu 42 */ 43 public class OMNamedNodeMap<T extends OMNode> implements Iterable<T> { 44 private NamedNodeMap<? extends Node> ot; 45 /** 46 * Constructor 47 * @param map The wrapped map 48 */ 49 protected OMNamedNodeMap(NamedNodeMap<? extends Node> map) { 50 this.ot = map; 51 } 52 53 /** 54 * Returns the wrapped {@link org.vectomatic.dom.svg.impl.NamedNodeMap} 55 * @return the wrapped {@link org.vectomatic.dom.svg.impl.NamedNodeMap} 56 */ 57 public NamedNodeMap<? extends Node> getNamedNodeMap() { 58 return ot; 59 } 60 61 /** 62 * Retrieves a node specified by name. 63 * @param name The <code>nodeName</code> of a node to retrieve. 64 * @return A <code>Node</code> (of any type) with the specified 65 * <code>nodeName</code>, or <code>null</code> if it does not identify 66 * any node in this map. 67 */ 68 public final T getNamedItem(String name) { 69 Node node = ot.getNamedItem(name); 70 return (node != null) ? OMNode.<T>convert(node) : null; 71 } 72 73 /** 74 * Adds a node using its <code>nodeName</code> attribute. If a node with 75 * that name is already present in this map, it is replaced by the new 76 * one. Replacing a node by itself has no effect. 77 * <br>As the <code>nodeName</code> attribute is used to derive the name 78 * which the node must be stored under, multiple nodes of certain types 79 * (those that have a "special" string value) cannot be stored as the 80 * names would clash. This is seen as preferable to allowing nodes to be 81 * aliased. 82 * @param arg A node to store in this map. The node will later be 83 * accessible using the value of its <code>nodeName</code> attribute. 84 * @return If the new <code>Node</code> replaces an existing node the 85 * replaced <code>Node</code> is returned, otherwise <code>null</code> 86 * is returned. 87 * @exception DOMException 88 * WRONG_DOCUMENT_ERR: Raised if <code>arg</code> was created from a 89 * different document than the one that created this map. 90 * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly. 91 * <br>INUSE_ATTRIBUTE_ERR: Raised if <code>arg</code> is an 92 * <code>Attr</code> that is already an attribute of another 93 * <code>Element</code> object. The DOM user must explicitly clone 94 * <code>Attr</code> nodes to re-use them in other elements. 95 * <br>HIERARCHY_REQUEST_ERR: Raised if an attempt is made to add a node 96 * doesn't belong in this NamedNodeMap. Examples would include trying 97 * to insert something other than an Attr node into an Element's map 98 * of attributes, or a non-Entity node into the DocumentType's map of 99 * Entities. 100 */ 101 public final T setNamedItem(T arg) throws JavaScriptException { 102 Node node = ot.setNamedItem(arg.getNode()); 103 return (node != null) ? OMNode.<T>convert(node) : null; 104 } 105 106 /** 107 * Removes a node specified by name. When this map contains the attributes 108 * attached to an element, if the removed attribute is known to have a 109 * default value, an attribute immediately appears containing the 110 * default value as well as the corresponding namespace URI, local name, 111 * and prefix when applicable. 112 * @param name The <code>nodeName</code> of the node to remove. 113 * @return The node removed from this map if a node with such a name 114 * exists. 115 * @exception DOMException 116 * NOT_FOUND_ERR: Raised if there is no node named <code>name</code> in 117 * this map. 118 * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly. 119 */ 120 public final T removeNamedItem(String name) throws JavaScriptException { 121 Node node = ot.removeNamedItem(name); 122 return (node != null) ? OMNode.<T>convert(node) : null; 123 } 124 125 /** 126 * Returns the <code>index</code>th item in the map. If <code>index</code> 127 * is greater than or equal to the number of nodes in this map, this 128 * returns <code>null</code>. 129 * @param index Index into this map. 130 * @return The node at the <code>index</code>th position in the map, or 131 * <code>null</code> if that is not a valid index. 132 */ 133 public final T item(int index) { 134 Node node = ot.item(index); 135 return (node != null) ? OMNode.<T>convert(node) : null; 136 } 137 138 /** 139 * The number of nodes in this map. The range of valid child node indices 140 * is <code>0</code> to <code>length-1</code> inclusive. 141 * @return The number of nodes in this map 142 */ 143 public final int getLength() { 144 return ot.getLength(); 145 } 146 147 /** 148 * Retrieves a node specified by local name and namespace URI. 149 * <br>Per [<a href='http://www.w3.org/TR/1999/REC-xml-names-19990114/'>XML Namespaces</a>] 150 * , applications must use the value null as the namespaceURI parameter 151 * for methods if they wish to have no namespace. 152 * @param namespaceURI The namespace URI of the node to retrieve. 153 * @param localName The local name of the node to retrieve. 154 * @return A <code>Node</code> (of any type) with the specified local 155 * name and namespace URI, or <code>null</code> if they do not 156 * identify any node in this map. 157 * @exception DOMException 158 * NOT_SUPPORTED_ERR: May be raised if the implementation does not 159 * support the feature "XML" and the language exposed through the 160 * Document does not support XML Namespaces (such as [<a href='http://www.w3.org/TR/1999/REC-html401-19991224/'>HTML 4.01</a>]). 161 */ 162 public final T getNamedItemNS(String namespaceURI, String localName) throws JavaScriptException { 163 Node node = ot.getNamedItemNS(namespaceURI, localName); 164 return (node != null) ? OMNode.<T>convert(node) : null; 165 } 166 167 /** 168 * Adds a node using its <code>namespaceURI</code> and 169 * <code>localName</code>. If a node with that namespace URI and that 170 * local name is already present in this map, it is replaced by the new 171 * one. Replacing a node by itself has no effect. 172 * <br>Per [<a href='http://www.w3.org/TR/1999/REC-xml-names-19990114/'>XML Namespaces</a>] 173 * , applications must use the value null as the namespaceURI parameter 174 * for methods if they wish to have no namespace. 175 * @param arg A node to store in this map. The node will later be 176 * accessible using the value of its <code>namespaceURI</code> and 177 * <code>localName</code> attributes. 178 * @return If the new <code>Node</code> replaces an existing node the 179 * replaced <code>Node</code> is returned, otherwise <code>null</code> 180 * is returned. 181 * @exception DOMException 182 * WRONG_DOCUMENT_ERR: Raised if <code>arg</code> was created from a 183 * different document than the one that created this map. 184 * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly. 185 * <br>INUSE_ATTRIBUTE_ERR: Raised if <code>arg</code> is an 186 * <code>Attr</code> that is already an attribute of another 187 * <code>Element</code> object. The DOM user must explicitly clone 188 * <code>Attr</code> nodes to re-use them in other elements. 189 * <br>HIERARCHY_REQUEST_ERR: Raised if an attempt is made to add a node 190 * doesn't belong in this NamedNodeMap. Examples would include trying 191 * to insert something other than an Attr node into an Element's map 192 * of attributes, or a non-Entity node into the DocumentType's map of 193 * Entities. 194 * <br>NOT_SUPPORTED_ERR: May be raised if the implementation does not 195 * support the feature "XML" and the language exposed through the 196 * Document does not support XML Namespaces (such as [<a href='http://www.w3.org/TR/1999/REC-html401-19991224/'>HTML 4.01</a>]). 197 */ 198 public final T setNamedItemNS(T arg) throws JavaScriptException { 199 Node node = ot.setNamedItemNS(arg.getNode()); 200 return (node != null) ? OMNode.<T>convert(node) : null; 201 } 202 203 /** 204 * Removes a node specified by local name and namespace URI. A removed 205 * attribute may be known to have a default value when this map contains 206 * the attributes attached to an element, as returned by the attributes 207 * attribute of the <code>Node</code> interface. If so, an attribute 208 * immediately appears containing the default value as well as the 209 * corresponding namespace URI, local name, and prefix when applicable. 210 * <br>Per [<a href='http://www.w3.org/TR/1999/REC-xml-names-19990114/'>XML Namespaces</a>] 211 * , applications must use the value null as the namespaceURI parameter 212 * for methods if they wish to have no namespace. 213 * @param namespaceURI The namespace URI of the node to remove. 214 * @param localName The local name of the node to remove. 215 * @return The node removed from this map if a node with such a local 216 * name and namespace URI exists. 217 * @exception DOMException 218 * NOT_FOUND_ERR: Raised if there is no node with the specified 219 * <code>namespaceURI</code> and <code>localName</code> in this map. 220 * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly. 221 * <br>NOT_SUPPORTED_ERR: May be raised if the implementation does not 222 * support the feature "XML" and the language exposed through the 223 * Document does not support XML Namespaces (such as [<a href='http://www.w3.org/TR/1999/REC-html401-19991224/'>HTML 4.01</a>]). 224 */ 225 public final T removeNamedItemNS(String namespaceURI, String localName) throws JavaScriptException { 226 Node node = ot.removeNamedItemNS(namespaceURI, localName); 227 return (node != null) ? OMNode.<T>convert(node) : null; 228 } 229 230 /** 231 * Returns an iterator over the {@link org.vectomatic.dom.svg.OMNode} 232 * elements in this map in proper sequence. 233 * 234 * <p>This implementation returns a straightforward implementation of the 235 * iterator interface, relying on the backing map's {@code getNumberOfItems()}, 236 * and {@code getItem(int)} methods. 237 * 238 * <p>Note that the iterator returned by this method will throw an 239 * {@code UnsupportedOperationException} in response to its 240 * {@code remove} method. 241 * 242 * @return an iterator over the {@link org.vectomatic.dom.svg.OMNode} 243 * elements in this map in proper sequence 244 */ 245 @Override 246 public Iterator<T> iterator() { 247 return new Iterator<T>() { 248 private int index; 249 250 @Override 251 public boolean hasNext() { 252 return index < getLength(); 253 } 254 255 @Override 256 public T next() { 257 return item(index++); 258 } 259 260 @Override 261 public void remove() { 262 throw new UnsupportedOperationException(); 263 } 264 }; 265 } 266 }