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 }