Clover coverage report - Clover results for XOM 1.2d1
Coverage timestamp: Wed Feb 8 2006 08:31:33 EST
file stats: LOC: 409   Methods: 14
NCLOC: 46   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
NodeFactory.java - 100% 100% 100%
coverage
 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>&lt;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    }