|
|||||||||||||||||||
| Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
| NodeFactory.java | - | 100% | 100% | 100% |
|
||||||||||||||
| 1 | /* Copyright 2002-2005 Elliotte Rusty Harold | |
| 2 | ||
| 3 | This library is free software; you can redistribute it and/or modify | |
| 4 | it under the terms of version 2.1 of the GNU Lesser General Public | |
| 5 | License as published by the Free Software Foundation. | |
| 6 | ||
| 7 | This library is distributed in the hope that it will be useful, | |
| 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 10 | GNU Lesser General Public License for more details. | |
| 11 | ||
| 12 | You should have received a copy of the GNU Lesser General Public | |
| 13 | License along with this library; if not, write to the | |
| 14 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |
| 15 | Boston, MA 02111-1307 USA | |
| 16 | ||
| 17 | You can contact Elliotte Rusty Harold by sending e-mail to | |
| 18 | elharo@metalab.unc.edu. Please include the word "XOM" in the | |
| 19 | subject line. The XOM home page is located at http://www.xom.nu/ | |
| 20 | */ | |
| 21 | ||
| 22 | package nu.xom; | |
| 23 | ||
| 24 | /** | |
| 25 | * <p> | |
| 26 | * Builders use a <code>NodeFactory</code> object | |
| 27 | * to construct each <code>Node</code> object (<code>Element</code>, | |
| 28 | * <code>Text</code>, <code>Attribute</code>, etc.) they add to the | |
| 29 | * tree. The default implementation simply calls the relevant | |
| 30 | * constructor, stuffs the resulting <code>Node</code> object in a | |
| 31 | * length one <code>Nodes</code> object, and returns it. | |
| 32 | * </p> | |
| 33 | * | |
| 34 | * <p> | |
| 35 | * Subclassing this class allows builders to produce | |
| 36 | * instance of subclasses (for example, | |
| 37 | * <code>HTMLElement</code>) instead of the | |
| 38 | * base classes. | |
| 39 | * </p> | |
| 40 | * | |
| 41 | * <p> | |
| 42 | * Subclasses can also filter content while building. | |
| 43 | * For example, namespaces could be added to or changed | |
| 44 | * on all elements. Comments could be deleted. Processing | |
| 45 | * instructions can be changed into elements. An | |
| 46 | * <code>xinclude:include</code> element could be replaced | |
| 47 | * with the content it references. All such changes must be | |
| 48 | * consistent with the usual rules of well-formedness. For | |
| 49 | * example, the <code>makeDocType()</code> method should not | |
| 50 | * return a list containing two <code>DocType</code> objects | |
| 51 | * because an XML document can have at most one document type | |
| 52 | * declaration. Nor should it return a list containing an element, | |
| 53 | * because an element cannot appear in a document prolog. However, | |
| 54 | * it could return a list containing any number of comments and | |
| 55 | * processing instructions, and not more than one <code>DocType</code> | |
| 56 | * object. | |
| 57 | * </p> | |
| 58 | * | |
| 59 | * @author Elliotte Rusty Harold | |
| 60 | * @version 1.1d5 | |
| 61 | * | |
| 62 | */ | |
| 63 | public class NodeFactory { | |
| 64 | ||
| 65 | /** | |
| 66 | * <p> | |
| 67 | * Constructs a new node factory. | |
| 68 | * </p> | |
| 69 | * | |
| 70 | */ | |
| 71 | 1596 | public NodeFactory() {} |
| 72 | ||
| 73 | /** | |
| 74 | * <p> | |
| 75 | * Creates a new element in the specified namespace | |
| 76 | * with the specified name. The builder calls this | |
| 77 | * method to make the root element of the document. | |
| 78 | * </p> | |
| 79 | * | |
| 80 | * <p> | |
| 81 | * Subclasses may change the name, namespace, content, or other | |
| 82 | * characteristics of the element returned. | |
| 83 | * The default implementation merely calls | |
| 84 | * <code>startMakingElement</code>. However, when subclassing, it | |
| 85 | * is often useful to be able to easily distinguish between the | |
| 86 | * root element and a non-root element because the root element | |
| 87 | * cannot be detached. Therefore, subclasses must not return null | |
| 88 | * from this method. Doing so will cause a | |
| 89 | * <code>NullPointerException</code>. | |
| 90 | * </p> | |
| 91 | * | |
| 92 | * @param name the qualified name of the element | |
| 93 | * @param namespace the namespace URI of the element | |
| 94 | * | |
| 95 | * @return the new root element | |
| 96 | */ | |
| 97 | 142 | public Element makeRootElement(String name, String namespace) { |
| 98 | 142 | return startMakingElement(name, namespace); |
| 99 | } | |
| 100 | ||
| 101 | ||
| 102 | /** | |
| 103 | * <p> | |
| 104 | * Creates a new <code>Element</code> in the specified namespace | |
| 105 | * with the specified name. | |
| 106 | * </p> | |
| 107 | * | |
| 108 | * <p> | |
| 109 | * Subclasses may change the name, namespace, content, or other | |
| 110 | * characteristics of the <code>Element</code> returned. | |
| 111 | * Subclasses may return null to indicate the | |
| 112 | * <code>Element</code> should not be created. | |
| 113 | * However, doing so will only remove the element's start-tag and | |
| 114 | * end-tag from the result tree. Any content inside the element | |
| 115 | * will be attached to the element's parent by default, unless it | |
| 116 | * too is filtered. To remove an entire element, return an empty | |
| 117 | * <code>Nodes</code> object from the | |
| 118 | * <code>finishMakingElement()</code> method. | |
| 119 | * </p> | |
| 120 | * | |
| 121 | * @param name the qualified name of the element | |
| 122 | * @param namespace the namespace URI of the element | |
| 123 | * | |
| 124 | * @return the new element | |
| 125 | */ | |
| 126 | 105903 | public Element startMakingElement(String name, String namespace) { |
| 127 | 105903 | return new Element(name, namespace); |
| 128 | } | |
| 129 | ||
| 130 | ||
| 131 | /** | |
| 132 | * <p> | |
| 133 | * Signals the end of an element. This method should return | |
| 134 | * the <code>Nodes</code> to be added to the tree. | |
| 135 | * They need not contain the <code>Element</code> that | |
| 136 | * was passed to this method, though most often they will. | |
| 137 | * By default the <code>Nodes</code> returned contain | |
| 138 | * only the built element. However, subclasses may return | |
| 139 | * a list containing any number of nodes, all of which will be | |
| 140 | * added to the tree at the current position in the order given by | |
| 141 | * the list (subject to the usual well-formedness constraints, of | |
| 142 | * course. For instance, the list should not contain a | |
| 143 | * <code>DocType</code> object unless the element is the root | |
| 144 | * element, and the document does not already have a | |
| 145 | * <code>DocType</code>). All of the nodes returned must be | |
| 146 | * parentless. If this method returns an empty list, | |
| 147 | * then the element (including all its contents) is not included | |
| 148 | * in the finished document. | |
| 149 | * </p> | |
| 150 | * | |
| 151 | * <p> | |
| 152 | * To process an element at a time, override this method in a | |
| 153 | * subclass so that it functions as a callback. When you're done | |
| 154 | * processing the <code>Element</code>, return an empty list so | |
| 155 | * that it will be removed from the tree and garbage collected. | |
| 156 | * Be careful not to return an empty list for the root element | |
| 157 | * though. That is, when the element passed to this method is the | |
| 158 | * root element, the list returned must contain exactly one | |
| 159 | * <code>Element</code> object. The simplest way to check this | |
| 160 | * is testing if <code>element.getParent() instanceof | |
| 161 | * Document</code>. | |
| 162 | * </p> | |
| 163 | * | |
| 164 | * <p> | |
| 165 | * Do not detach <code>element</code> or any of its ancestors | |
| 166 | * while inside this method. Doing so can royally muck up the | |
| 167 | * build. | |
| 168 | * </p> | |
| 169 | * | |
| 170 | * @param element the finished <code>Element</code> | |
| 171 | * | |
| 172 | * @return the nodes to be added to the tree | |
| 173 | * | |
| 174 | */ | |
| 175 | 105725 | public Nodes finishMakingElement(Element element) { |
| 176 | 105725 | return new Nodes(element); |
| 177 | } | |
| 178 | ||
| 179 | ||
| 180 | /** | |
| 181 | * <p> | |
| 182 | * Creates a new <code>Document</code> object. | |
| 183 | * The root element of this document is initially set to | |
| 184 | * <code><root xmlns=http://www.xom.nu/fakeRoot""/></code>. | |
| 185 | * This is only temporary. As soon as the real root element's | |
| 186 | * start-tag is read, this element is replaced by the real root. | |
| 187 | * This fake root should never be exposed. | |
| 188 | * </p> | |
| 189 | * | |
| 190 | * <p> | |
| 191 | * The builder calls this method at the beginning of | |
| 192 | * each document, before it calls any other method in this class. | |
| 193 | * Thus this is a useful place to perform per-document | |
| 194 | * initialization tasks. | |
| 195 | * </p> | |
| 196 | * | |
| 197 | * <p> | |
| 198 | * Subclasses may change the root element, content, | |
| 199 | * or other characteristics of the document | |
| 200 | * returned. However, this method must not return null | |
| 201 | * or the builder will throw a <code>ParsingException</code>. | |
| 202 | * </p> | |
| 203 | * | |
| 204 | * @return the newly created <code>Document</code> | |
| 205 | */ | |
| 206 | 22273 | public Document startMakingDocument() { |
| 207 | 22273 | return new Document( |
| 208 | Element.build("root", "http://www.xom.nu/fakeRoot", "root") | |
| 209 | ); | |
| 210 | } | |
| 211 | ||
| 212 | ||
| 213 | /** | |
| 214 | * <p> | |
| 215 | * Signals the end of a document. The default implementation of | |
| 216 | * this method does nothing. The builder does not | |
| 217 | * call this method if an exception is thrown while building | |
| 218 | * a document. | |
| 219 | * </p> | |
| 220 | * | |
| 221 | * @param document the completed <code>Document</code> | |
| 222 | */ | |
| 223 | 21858 | public void finishMakingDocument(Document document) {} |
| 224 | ||
| 225 | ||
| 226 | /** | |
| 227 | * <p> | |
| 228 | * Returns a new <code>Nodes</code> object containing an | |
| 229 | * attribute in the specified namespace | |
| 230 | * with the specified name and type. | |
| 231 | * </p> | |
| 232 | * | |
| 233 | * <p> | |
| 234 | * Subclasses may change the nodes returned from this method. | |
| 235 | * They may return a <code>Nodes</code> object containing any | |
| 236 | * number of children and attributes which are appended and | |
| 237 | * added to the current parent element. This <code>Nodes</code> | |
| 238 | * object may not contain any <code>Document</code> objects. | |
| 239 | * All of the nodes returned must be parentless. | |
| 240 | * Subclasses may return an empty <code>Nodes</code> to indicate | |
| 241 | * the attribute should not be created. | |
| 242 | * </p> | |
| 243 | * | |
| 244 | * @param name the prefixed name of the attribute | |
| 245 | * @param URI the namespace URI | |
| 246 | * @param value the attribute value | |
| 247 | * @param type the attribute type | |
| 248 | * | |
| 249 | * @return the nodes to be added to the tree | |
| 250 | */ | |
| 251 | 319 | public Nodes makeAttribute(String name, String URI, |
| 252 | String value, Attribute.Type type) { | |
| 253 | 319 | return new Nodes(new Attribute(name, URI, value, type)); |
| 254 | } | |
| 255 | ||
| 256 | ||
| 257 | /** | |
| 258 | * <p> | |
| 259 | * Returns a new <code>Nodes</code> object containing a | |
| 260 | * comment with the specified text. | |
| 261 | * </p> | |
| 262 | * | |
| 263 | * <p> | |
| 264 | * Subclasses may change the content or other | |
| 265 | * characteristics of the comment returned. | |
| 266 | * Subclasses may change the nodes returned from this method. | |
| 267 | * They may return a <code>Nodes</code> object containing any | |
| 268 | * number of children and attributes which are appended and | |
| 269 | * added to the current parent element. This <code>Nodes</code> | |
| 270 | * object should not contain any <code>Document</code> objects. | |
| 271 | * All of the nodes returned must be parentless. | |
| 272 | * Subclasses may return an empty <code>Nodes</code> to indicate | |
| 273 | * the comment should not be included in the | |
| 274 | * finished document. | |
| 275 | * </p> | |
| 276 | * | |
| 277 | * @param data the complete text content of the comment | |
| 278 | * | |
| 279 | * @return the nodes to be added to the tree | |
| 280 | */ | |
| 281 | 64 | public Nodes makeComment(String data) { |
| 282 | 64 | return new Nodes(new Comment(data)); |
| 283 | } | |
| 284 | ||
| 285 | ||
| 286 | /** | |
| 287 | * <p> | |
| 288 | * Returns a new <code>Nodes</code> object containing a | |
| 289 | * <code>DocType</code> object with the specified root element | |
| 290 | * name, system ID, and public ID. | |
| 291 | * </p> | |
| 292 | * | |
| 293 | * <p> | |
| 294 | * Subclasses may change the root element name, public ID, | |
| 295 | * system ID, or other characteristics of the <code>DocType</code> | |
| 296 | * returned. Subclasses may change the nodes returned from this | |
| 297 | * method. They may return a <code>Nodes</code> object containing | |
| 298 | * any number of comments and processing instructions which are | |
| 299 | * appended to the current parent node. This <code>Nodes</code> | |
| 300 | * object may not contain any <code>Document</code>, | |
| 301 | * <code>Element</code>, <code>Attribute</code>, or | |
| 302 | * <code>Text</code> objects. All of the nodes returned must be | |
| 303 | * parentless. Subclasses may return an empty <code>Nodes</code> to | |
| 304 | * indicate the <code>DocType</code> should not be included in the | |
| 305 | * finished document. | |
| 306 | * </p> | |
| 307 | * | |
| 308 | * @param rootElementName the declared, qualified name | |
| 309 | * for the root element | |
| 310 | * @param publicID the public ID of the external DTD subset | |
| 311 | * @param systemID the URL of the external DTD subset | |
| 312 | * | |
| 313 | * @return the nodes to be added to the document | |
| 314 | */ | |
| 315 | 12 | public Nodes makeDocType(String rootElementName, |
| 316 | String publicID, String systemID) { | |
| 317 | 12 | return new Nodes(new DocType(rootElementName, publicID, systemID)); |
| 318 | } | |
| 319 | ||
| 320 | ||
| 321 | /** | |
| 322 | * <p> | |
| 323 | * Returns a new <code>Nodes</code> object containing a | |
| 324 | * text node with the specified content. | |
| 325 | * </p> | |
| 326 | * | |
| 327 | * <p> | |
| 328 | * Subclasses may change the content or other characteristics of | |
| 329 | * the text returned. Subclasses may also change the nodes | |
| 330 | * returned from this method. They may return a <code>Nodes</code> | |
| 331 | * object containing any number of nodes which are added or | |
| 332 | * appended to the current parent node. This <code>Nodes</code> | |
| 333 | * object must not contain any <code>Document</code> nodes. All of | |
| 334 | * the nodes returned must be parentless. Subclasses may return an | |
| 335 | * empty <code>Nodes</code> to indicate the text should not be | |
| 336 | * included in the finished document. | |
| 337 | * </p> | |
| 338 | * | |
| 339 | * @param data the complete text content of the node | |
| 340 | * | |
| 341 | * @return the nodes to be added to the tree | |
| 342 | */ | |
| 343 | 61014 | public Nodes makeText(String data) { |
| 344 | 61014 | return new Nodes(new Text(data)); |
| 345 | } | |
| 346 | ||
| 347 | ||
| 348 | /** | |
| 349 | * <p> | |
| 350 | * Returns a new <code>Nodes</code> object containing a | |
| 351 | * <code>CDATASection</code> node with the specified content. | |
| 352 | * </p> | |
| 353 | * | |
| 354 | * @param data the complete text content of the node | |
| 355 | * | |
| 356 | * @return the nodes to be added to the tree | |
| 357 | */ | |
| 358 | 1 | Nodes makeCDATASection(String data) { |
| 359 | 1 | return makeText(data); |
| 360 | } | |
| 361 | ||
| 362 | ||
| 363 | /** | |
| 364 | * <p> | |
| 365 | * Returns a new <code>Nodes</code> object containing a | |
| 366 | * new <code>ProcessingInstruction</code> object with | |
| 367 | * the specified target and data. | |
| 368 | * </p> | |
| 369 | * | |
| 370 | * <p> | |
| 371 | * Subclasses may change the target, data, or other | |
| 372 | * characteristics of the <code>ProcessingInstruction</code> | |
| 373 | * returned. Subclasses may change the nodes returned from this | |
| 374 | * method. They may return a <code>Nodes</code> object containing | |
| 375 | * any number of nodes which are added or | |
| 376 | * appended to the current parent node. This <code>Nodes</code> | |
| 377 | * object must not contain any <code>Document</code> nodes. | |
| 378 | * If the processing instruction appears in the prolog or epilog | |
| 379 | * of the document, then it must also not contain any | |
| 380 | * <code>Element</code>, <code>Attribute</code>, or | |
| 381 | * <code>Text</code> objects. | |
| 382 | * All of the nodes returned must be parentless. Subclasses | |
| 383 | * may return an empty <code>Nodes</code> to indicate the | |
| 384 | * processing instruction should not be included in the | |
| 385 | * finished document. | |
| 386 | * </p> | |
| 387 | * | |
| 388 | * @param target the target of the processing instruction | |
| 389 | * @param data the data of the processing instruction | |
| 390 | * | |
| 391 | * @return the nodes to be added to the tree | |
| 392 | */ | |
| 393 | 34 | public Nodes makeProcessingInstruction( |
| 394 | String target, String data) { | |
| 395 | 34 | return new Nodes(new ProcessingInstruction(target, data)); |
| 396 | } | |
| 397 | ||
| 398 | ||
| 399 | 133 | void addAttribute(Element element, Attribute attribute) { |
| 400 | 133 | element.addAttribute(attribute); |
| 401 | } | |
| 402 | ||
| 403 | ||
| 404 | 2 | void insertChild(Element element, Node child, int position) { |
| 405 | 2 | element.insertChild(child, position); |
| 406 | } | |
| 407 | ||
| 408 | ||
| 409 | } |
|
||||||||||