View Javadoc

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 }