Clover coverage report - Clover results for XOM 1.2d1
Coverage timestamp: Wed Feb 8 2006 08:31:33 EST
file stats: LOC: 1,145   Methods: 93
NCLOC: 797   Classes: 15
 
 Source file Conditionals Statements Methods TOTAL
NodeFactoryTest.java 90% 94.5% 97.8% 94.9%
coverage coverage
 1    /* Copyright 2002-2004 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.tests;
 23   
 24    import java.io.File;
 25    import java.io.IOException;
 26   
 27    import nu.xom.ParsingException;
 28   
 29    import nu.xom.Attribute;
 30    import nu.xom.Builder;
 31    import nu.xom.Comment;
 32    import nu.xom.DocType;
 33    import nu.xom.Document;
 34    import nu.xom.Element;
 35    import nu.xom.Node;
 36    import nu.xom.NodeFactory;
 37    import nu.xom.Nodes;
 38    import nu.xom.ProcessingInstruction;
 39    import nu.xom.Text;
 40    import nu.xom.ValidityException;
 41    import nu.xom.XMLException;
 42   
 43    /**
 44    * <p>
 45    * Tests that subclasses of <code>NodeFactory</code> can filter
 46    * on building in various ways.
 47    * </p>
 48    *
 49    * @author Elliotte Rusty Harold
 50    * @version 1.1b2
 51    *
 52    */
 53    public class NodeFactoryTest extends XOMTestCase {
 54   
 55   
 56    private File data = new File("data");
 57   
 58   
 59  43 public NodeFactoryTest(String name) {
 60  43 super(name);
 61    }
 62   
 63   
 64  43 protected void setUp() {
 65  43 numNodesInExternalDTDSubset = 0;
 66    }
 67   
 68   
 69  1 public void testSkippingComment()
 70    throws IOException, ParsingException {
 71   
 72  1 String data = "<a>1<!--tetetwkfjkl-->8</a>";
 73  1 Builder builder = new Builder(new CommentFilter());
 74  1 Document doc = builder.build(data, "http://www.example.org/");
 75  1 Element root = doc.getRootElement();
 76  1 assertEquals("Skipped comment interrupted text node",
 77    2, root.getChildCount());
 78  1 assertEquals("18", doc.getValue());
 79  1 Node first = root.getChild(0);
 80  1 assertEquals(first.getValue(), "1");
 81  1 Node second = root.getChild(1);
 82  1 assertEquals(second.getValue(), "8");
 83   
 84    }
 85   
 86   
 87    static class CommentFilter extends NodeFactory {
 88   
 89  3 public Nodes makeComment(String data) {
 90  3 return new Nodes();
 91    }
 92   
 93    }
 94   
 95   
 96  1 public void testCantAddOneElementMultipleTimes()
 97    throws IOException, ParsingException {
 98   
 99  1 String data = "<a><b>18</b></a>";
 100  1 Builder builder = new Builder(new SingleElementFactory());
 101  1 try {
 102  1 builder.build(data, "http://www.example.org/");
 103  0 fail("Allowed one element in several places");
 104    }
 105    catch (ParsingException success) {
 106  1 assertNotNull(success.getMessage());
 107    }
 108   
 109    }
 110   
 111   
 112  1 public void testCantAddOneAttributeMultipleTimes()
 113    throws IOException, ParsingException {
 114   
 115  1 String data = "<a test=\"value\" name=\"data\"></a>";
 116  1 Builder builder = new Builder(new SingleAttributeFactory());
 117  1 try {
 118  1 builder.build(data, "http://www.example.org/");
 119  0 fail("Allowed one attribute twice");
 120    }
 121    catch (ParsingException success) {
 122  1 assertNotNull(success.getMessage());
 123    }
 124   
 125    }
 126   
 127   
 128    private static class SingleElementFactory extends NodeFactory {
 129   
 130    private Element test = new Element("test");
 131   
 132  2 public Element startMakingElement(String name, String namespace) {
 133  2 return test;
 134    }
 135   
 136    }
 137   
 138   
 139    private static class SingleAttributeFactory extends NodeFactory {
 140   
 141    private Attribute test = new Attribute("limit", "none");
 142   
 143  2 public Nodes makeAttribute(String name, String URI,
 144    String value, Attribute.Type type) {
 145  2 return new Nodes(test);
 146    }
 147   
 148    }
 149   
 150   
 151  1 public void testChangingElementName()
 152    throws IOException, ParsingException {
 153   
 154  1 String data
 155    = "<a>1<b>2<a>3<b>4<a>innermost</a>5</b>6</a>7</b>8</a>";
 156  1 Builder builder = new Builder(new CFactory());
 157  1 Document doc = builder.build(data, "http://www.example.org/");
 158  1 Element root = doc.getRootElement();
 159  1 assertEquals("1234innermost5678", doc.getValue());
 160  1 assertEquals("c", root.getQualifiedName());
 161  1 assertEquals(3, root.getChildCount());
 162  1 Element b = (Element) root.getChild(1);
 163  1 assertEquals("c", b.getQualifiedName());
 164   
 165    }
 166   
 167   
 168    static class CFactory extends NodeFactory {
 169   
 170  13 public Element startMakingElement(
 171    String name, String namespace) {
 172  13 return new Element("c");
 173    }
 174   
 175    }
 176   
 177   
 178  1 public void testMakeRoot() throws IOException, ParsingException {
 179   
 180  1 String data = "<a><b>18</b></a>";
 181  1 Builder builder = new Builder(new CallsMakeRoot());
 182  1 Document doc = builder.build(data, "http://www.example.org/");
 183  1 Element root = doc.getRootElement();
 184  1 assertEquals("rootSubstitute", root.getQualifiedName());
 185   
 186    // make sure the other elements aren't changed
 187  1 assertNotNull(root.getFirstChildElement("b"));
 188   
 189    }
 190   
 191   
 192    static class CallsMakeRoot extends NodeFactory {
 193   
 194  1 public Element makeRootElement(
 195    String name, String namepaceURI) {
 196  1 return new Element("rootSubstitute");
 197    }
 198   
 199    }
 200   
 201   
 202  1 public void testSkippingProcessingInstruction()
 203    throws IOException, ParsingException {
 204   
 205  1 String data = "<a>1<?test some data?>8</a>";
 206  1 Builder builder = new Builder(new ProcessingInstructionFilter());
 207  1 Document doc = builder.build(data, "http://www.example.org/");
 208  1 Element root = doc.getRootElement();
 209  1 assertEquals(
 210    "Skipped processing instruction interrupted text node",
 211    2, root.getChildCount()
 212    );
 213  1 assertEquals("18", doc.getValue());
 214  1 Node first = root.getChild(0);
 215  1 assertEquals(first.getValue(), "1");
 216  1 Node second = root.getChild(1);
 217  1 assertEquals(second.getValue(), "8");
 218   
 219    }
 220   
 221   
 222    static class ProcessingInstructionFilter extends NodeFactory {
 223   
 224  2 public Nodes makeProcessingInstruction(
 225    String target, String data) {
 226  2 return new Nodes();
 227    }
 228   
 229    }
 230   
 231   
 232  1 public void testSkipping2() throws IOException, ParsingException {
 233   
 234  1 String data
 235    = "<a>1<b>2<a>3<b>4<a>innermost</a>5</b>6</a>7</b>8</a>";
 236  1 Builder builder = new Builder(new BFilter());
 237  1 Document doc = builder.build(data, "http://www.example.org/");
 238  1 Element root = doc.getRootElement();
 239  1 assertEquals("1234innermost5678", doc.getValue());
 240  1 assertEquals(5, root.getChildCount());
 241  1 Node first = root.getChild(0);
 242  1 assertEquals("1", first.getValue());
 243  1 Node middle = root.getChild(2);
 244  1 assertEquals("34innermost56", middle.getValue());
 245  1 Node last = root.getChild(4);
 246  1 assertEquals("8", last.getValue());
 247   
 248  1 Node innermost = middle.getChild(2);
 249  1 assertEquals("innermost", innermost.getValue());
 250  1 Node inner1 = middle.getChild(0);
 251  1 assertEquals("3", inner1.getValue());
 252  1 Node inner3 = middle.getChild(4);
 253  1 assertEquals("6", inner3.getValue());
 254   
 255    }
 256   
 257   
 258    static class BFilter extends NodeFactory {
 259   
 260  12 public Element startMakingElement(
 261    String name, String namespaceURI) {
 262  5 if (name.equals("b")) return null;
 263  7 return super.startMakingElement(name, namespaceURI);
 264    }
 265   
 266    }
 267   
 268   
 269  1 public void testMinimalizedDocument()
 270    throws IOException, ParsingException {
 271   
 272  1 File input = new File(data, "entitytest.xml");
 273  1 Builder builder = new Builder(new MinimizingFactory());
 274  1 Document doc = builder.build(input);
 275  1 assertEquals(1, doc.getChildCount());
 276  1 Element root = doc.getRootElement();
 277  1 assertEquals("root", root.getQualifiedName());
 278  1 assertEquals("", root.getNamespaceURI());
 279  1 assertEquals(0, root.getChildCount());
 280  1 assertEquals(0, root.getAttributeCount());
 281   
 282    }
 283   
 284   
 285  1 public void testValidateWithFactory()
 286    throws ParsingException, IOException {
 287  1 Builder validator = new Builder(true, new MinimizingFactory());
 288  1 Document doc = validator.build("<!-- a comment --><!DOCTYPE root [" +
 289    "<!ELEMENT root EMPTY>" +
 290    "]>" +
 291    "<root/><?a processing instruction?>",
 292    "http://www.example.org/");
 293  1 assertEquals(1, doc.getChildCount());
 294    }
 295   
 296   
 297    // Throws away everything except the document and the
 298    // root element
 299    static class MinimizingFactory extends NodeFactory {
 300   
 301    private Nodes empty = new Nodes();
 302   
 303  4 public Nodes makeComment(String data) {
 304  4 return empty;
 305    }
 306   
 307  19 public Nodes makeText(String data) {
 308  19 return empty;
 309    }
 310   
 311  11 public Nodes finishMakingElement(Element element) {
 312  11 if (element.getParent() instanceof Document) {
 313  4 return new Nodes(element);
 314    }
 315  7 return empty;
 316    }
 317   
 318  3 public Nodes makeAttribute(String name, String URI,
 319    String value, Attribute.Type type) {
 320  3 return empty;
 321    }
 322   
 323  3 public Nodes makeDocType(String rootElementName,
 324    String publicID, String systemID) {
 325  3 return empty;
 326    }
 327   
 328  3 public Nodes makeProcessingInstruction(
 329    String target, String data) {
 330  3 return empty;
 331    }
 332   
 333    }
 334   
 335   
 336  1 public void testCDATASectionsCanBeOverridden()
 337    throws ValidityException, ParsingException, IOException {
 338   
 339  1 String data ="<root><![CDATA[text]]></root>";
 340  1 Builder builder = new Builder(new MinimizingFactory());
 341  1 Document doc = builder.build(data, "http://www.example.com");
 342  1 assertEquals("", doc.getValue());
 343   
 344    }
 345   
 346   
 347  1 public void testNullRootNotAllowed()
 348    throws IOException, ParsingException {
 349   
 350  1 File input = new File(data, "entitytest.xml");
 351  1 Builder builder = new Builder(new NullElementFactory());
 352  1 try {
 353  1 builder.build(input);
 354  0 fail("Allowed null root");
 355    }
 356    catch (ParsingException success) {
 357  1 assertNotNull(success.getMessage());
 358    }
 359   
 360    }
 361   
 362   
 363    // Returns null for all elements including the root.
 364    // This should cause an exception.
 365    static class NullElementFactory extends NodeFactory {
 366   
 367  1 public Element startMakingElement(
 368    String name, String namespaceURI) {
 369  1 return null;
 370    }
 371   
 372    }
 373   
 374   
 375  1 public void testNullDocumentNotAllowed()
 376    throws IOException, ParsingException {
 377   
 378  1 File input = new File(data, "entitytest.xml");
 379  1 Builder builder = new Builder(new NullDocumentFactory());
 380  1 try {
 381  1 builder.build(input);
 382  0 fail("Allowed null document");
 383    }
 384    catch (ParsingException success) {
 385  1 assertTrue(success.getCause() instanceof NullPointerException);
 386    }
 387   
 388    }
 389   
 390   
 391    // Returns null for all elements including the root.
 392    // This should cause an exception.
 393    static class NullDocumentFactory extends NodeFactory {
 394   
 395  1 public Document startMakingDocument() {
 396  1 return null;
 397    }
 398   
 399    }
 400   
 401   
 402  1 public void testSkipping() throws IOException, ParsingException {
 403   
 404  1 String data = "<a>data<b>data<a>data</a>data</b>data</a>";
 405  1 Builder builder = new Builder(new BFilter());
 406  1 Document doc = builder.build(data, "http://www.example.org/");
 407  1 Element root = doc.getRootElement();
 408  1 assertEquals(5, root.getChildCount());
 409  1 assertEquals("datadatadatadatadata", root.getValue());
 410  1 Element middle = (Element) root.getChild(2);
 411  1 assertEquals("data", middle.getValue());
 412  1 Node start = root.getChild(0);
 413  1 Node end = root.getChild(4);
 414  1 assertEquals("data", start.getValue());
 415  1 assertEquals("data", end.getValue());
 416   
 417    }
 418   
 419   
 420    int numNodesInExternalDTDSubset = 0;
 421   
 422  1 public void testDontReportCommentsAndProcessingInstructionsInExternalDTDSubset()
 423    throws IOException, ParsingException {
 424   
 425  1 File input = new File(data, "contentindtd.xml");
 426  1 Builder builder = new Builder(new Counter());
 427  1 builder.build(input);
 428  1 assertEquals(0, numNodesInExternalDTDSubset);
 429   
 430    }
 431   
 432   
 433    private class Counter extends NodeFactory {
 434   
 435  0 public Nodes makeComment(String data) {
 436  0 numNodesInExternalDTDSubset++;
 437  0 return super.makeComment(data);
 438    }
 439   
 440  0 public Nodes makeProcessingInstruction(String target, String data) {
 441  0 numNodesInExternalDTDSubset++;
 442  0 return super.makeProcessingInstruction(target, data);
 443    }
 444   
 445    }
 446   
 447   
 448  1 public void testDontCoalesceTextNodes()
 449    throws IOException, ParsingException {
 450   
 451  1 String data = "<a>data<!-- comment--> data</a>";
 452  1 Builder builder = new Builder(new CommentFilter());
 453  1 Document doc = builder.build(data, "http://www.example.org/");
 454  1 Element root = doc.getRootElement();
 455  1 assertEquals(2, root.getChildCount());
 456  1 assertEquals("data data", root.getValue());
 457  1 Text text = (Text) root.getChild(0);
 458  1 assertEquals("data", text.getValue());
 459   
 460    }
 461   
 462   
 463    static class TripleElementFilter extends NodeFactory {
 464   
 465  8 public Nodes finishMakingElement(Element element) {
 466  8 Nodes result = new Nodes(element);
 467  8 if (!(element.getParent() instanceof Document)) {
 468  6 result.append(element.copy());
 469  6 result.append(element.copy());
 470    }
 471  8 return result;
 472    }
 473   
 474    }
 475   
 476   
 477  1 public void testTriple()
 478    throws IOException, ParsingException {
 479   
 480  1 String data = "<a><b><c/></b></a>";
 481  1 Builder builder = new Builder(new TripleElementFilter());
 482  1 Document doc = builder.build(data, "http://www.example.org/");
 483  1 Element root = doc.getRootElement();
 484  1 assertEquals(3, root.getChildCount());
 485  1 assertEquals("", root.getValue());
 486  1 Element b = (Element) root.getChild(0);
 487  1 assertEquals("b", b.getLocalName());
 488  1 assertEquals(
 489    "<a><b><c /><c /><c /></b><b><c /><c /><c /></b><b><c /><c /><c /></b></a>",
 490    root.toXML());
 491   
 492    }
 493   
 494   
 495    static class UncommentFilter extends NodeFactory {
 496   
 497  2 public Nodes makeComment(String data) {
 498  2 Nodes result = new Nodes(new Text(data));
 499  2 return result;
 500    }
 501   
 502    }
 503   
 504   
 505  1 public void testUncomment()
 506    throws ParsingException, IOException {
 507   
 508  1 String data = "<!-- test --><a></a>";
 509  1 Builder builder = new Builder(new UncommentFilter());
 510  1 try {
 511  1 builder.build(data, "http://www.example.org/");
 512  0 fail("built Text into prolog");
 513    }
 514    catch (ParsingException success) {
 515  1 assertNotNull(success.getMessage());
 516    }
 517   
 518    }
 519   
 520   
 521    static class DocumentFilter extends NodeFactory {
 522   
 523  1 public Nodes makeComment(String data) {
 524  1 Element root = new Element("root");
 525  1 Nodes result = new Nodes(new Document(root));
 526  1 return result;
 527    }
 528   
 529    }
 530   
 531   
 532  1 public void testCantAddDocument()
 533    throws ParsingException, IOException {
 534   
 535  1 String data = "<a><!-- test --></a>";
 536  1 Builder builder = new Builder(new DocumentFilter());
 537  1 try {
 538  1 builder.build(data, "http://www.example.org/");
 539  0 fail("built document into document");
 540    }
 541    catch (ParsingException success) {
 542  1 assertNotNull(success.getMessage());
 543    }
 544   
 545    }
 546   
 547   
 548  1 public void testCantAddTwoDoctypes()
 549    throws ParsingException, IOException {
 550   
 551  1 String data = "<!DOCTYPE a><a></a>";
 552  1 Builder builder = new Builder(new NodeFactory() {
 553   
 554  1 public Nodes makeDocType(String name, String publicID, String systemID) {
 555  1 Nodes result = new Nodes();
 556  1 result.append(new DocType(name, publicID, systemID));
 557  1 result.append(new Comment("sajdha"));
 558  1 result.append(new DocType(name, publicID, systemID));
 559  1 return result;
 560    }
 561   
 562    });
 563  1 try {
 564  1 builder.build(data, "http://www.example.org/");
 565  0 fail("built two doctypes");
 566    }
 567    catch (ParsingException success) {
 568  1 assertNotNull(success.getMessage());
 569    }
 570   
 571    }
 572   
 573   
 574  1 public void testChangeAttributesToElements()
 575    throws ParsingException, IOException {
 576   
 577  1 String data = "<a name=\"test\" value=\"data\"/>";
 578  1 Builder builder = new Builder(new NodeFactory() {
 579   
 580  2 public Nodes makeAttribute(String name, String URI,
 581    String value, Attribute.Type type) {
 582  2 Nodes result = new Nodes();
 583  2 Element element = new Element(name, URI);
 584  2 element.appendChild(value);
 585  2 result.append(element);
 586  2 return result;
 587    }
 588   
 589    });
 590  1 Document doc = builder.build(data, "http://www.example.org/");
 591  1 Element root = doc.getRootElement();
 592  1 assertEquals(2, root.getChildCount());
 593  1 Element name = root.getFirstChildElement("name");
 594  1 Element value = root.getFirstChildElement("value");
 595  1 assertEquals("test", name.getValue());
 596  1 assertEquals("data", value.getValue());
 597  1 assertEquals("name", name.getLocalName());
 598  1 assertEquals("value", value.getQualifiedName());
 599   
 600    }
 601   
 602   
 603  1 public void testInsertElementsInInternalDTDSubsetViaProcessingInstruction()
 604    throws ParsingException, IOException {
 605   
 606  1 String data = "<!DOCTYPE a [<?target data?>]><a><b>data1</b><c>text</c></a>";
 607  1 Builder builder = new Builder(new NodeFactory() {
 608   
 609  1 public Nodes makeProcessingInstruction(String target, String data) {
 610  1 Nodes result = new Nodes();
 611  1 Element e = new Element(target);
 612  1 e.appendChild(data);
 613  1 result.append(e);
 614  1 return result;
 615    }
 616   
 617    });
 618  1 try {
 619  1 builder.build(data, "http://www.example.org/");
 620  0 fail("Allowed element in internal DTD subset via processing instruction");
 621    }
 622    catch (ParsingException success) {
 623  1 assertNotNull(success.getMessage());
 624    }
 625   
 626    }
 627   
 628   
 629  1 public void testInsertElementsInInternalDTDSubsetViaComment()
 630    throws ParsingException, IOException {
 631   
 632  1 String data = "<!DOCTYPE a [<!--data-->]><a><b>data1</b><c>text</c></a>";
 633  1 Builder builder = new Builder(new NodeFactory() {
 634   
 635  1 public Nodes makeComment(String data) {
 636  1 Nodes result = new Nodes();
 637  1 Element e = new Element("comment");
 638  1 e.appendChild(data);
 639  1 result.append(e);
 640  1 return result;
 641    }
 642   
 643    });
 644  1 try {
 645  1 builder.build(data, "http://www.example.org/");
 646  0 fail("Allowed element in internal DTD subset via comment");
 647    }
 648    catch (ParsingException success) {
 649  1 assertNotNull(success.getMessage());
 650    }
 651   
 652    }
 653   
 654   
 655  1 public void testChangeElementsToAttributes()
 656    throws ParsingException, IOException {
 657   
 658  1 String data = "<a><b>data1</b><c>text</c></a>";
 659  1 Builder builder = new Builder(new NodeFactory() {
 660   
 661  3 public Nodes finishMakingElement(Element element) {
 662  3 Nodes result = new Nodes();
 663  3 if (element.getParent() instanceof Document) {
 664  1 result.append(element);
 665    }
 666    else {
 667  2 result.append(new Attribute(element.getLocalName(), element.getValue()));
 668    }
 669  3 return result;
 670    }
 671   
 672    });
 673  1 Document doc = builder.build(data, "http://www.example.org/");
 674  1 Element root = doc.getRootElement();
 675  1 assertEquals(0, root.getChildCount());
 676  1 assertEquals(2, root.getAttributeCount());
 677  1 assertEquals("data1", root.getAttribute("b").getValue());
 678  1 assertEquals("text", root.getAttribute("c").getValue());
 679   
 680    }
 681   
 682   
 683  1 public void testChangeDefaultNamespaceFromEnd()
 684    throws ParsingException, IOException {
 685   
 686  1 String data = "<a><b xmlns='http://www.a.com'/></a>";
 687  1 Builder builder = new Builder(new NodeFactory() {
 688   
 689  2 public Nodes finishMakingElement(Element element) {
 690  2 Nodes result = new Nodes(element);
 691  2 element.setNamespaceURI("http://www.b.org/");
 692  2 return result;
 693    }
 694   
 695    });
 696  1 Document doc = builder.build(data, "http://www.example.org/");
 697  1 Element root = doc.getRootElement();
 698  1 Element child = (Element) root.getChild(0);
 699  1 assertEquals("http://www.b.org/", child.getNamespaceURI());
 700   
 701    }
 702   
 703   
 704    // XXX need to test changing namespaces of attributes too
 705  1 public void testChangePrefixedNamespaceFromEnd()
 706    throws ParsingException, IOException {
 707   
 708  1 String data = "<a><pre:b xmlns:pre='http://www.a.com'/></a>";
 709  1 Builder builder = new Builder(new NodeFactory() {
 710   
 711  2 public Nodes finishMakingElement(Element element) {
 712  2 Nodes result = new Nodes(element);
 713  2 element.setNamespaceURI("http://www.b.org/");
 714  2 return result;
 715    }
 716   
 717    });
 718  1 Document doc = builder.build(data, "http://www.example.org/");
 719  1 Element root = doc.getRootElement();
 720  1 Element child = (Element) root.getChild(0);
 721  1 assertEquals("http://www.b.org/", child.getNamespaceURI());
 722   
 723    }
 724   
 725   
 726  1 public void testChangeDefaultNamespaceFromBeginning()
 727    throws ParsingException, IOException {
 728   
 729  1 String data = "<a><b xmlns='http://www.a.com'/></a>";
 730  1 Builder builder = new Builder(new NodeFactory() {
 731   
 732  2 public Element startMakingElement(String name, String namespaceURI) {
 733  2 return new Element(name, "http://www.b.org/");
 734    }
 735   
 736    });
 737  1 Document doc = builder.build(data, "http://www.example.org/");
 738  1 Element root = doc.getRootElement();
 739  1 Element child = (Element) root.getChild(0);
 740  1 assertEquals("http://www.b.org/", child.getNamespaceURI());
 741   
 742    }
 743   
 744   
 745  1 public void testChangePrefixedNamespaceFromBeginning()
 746    throws ParsingException, IOException {
 747   
 748  1 String data = "<a><pre:b xmlns:pre='http://www.a.com'/></a>";
 749  1 Builder builder = new Builder(new NodeFactory() {
 750   
 751  2 public Element startMakingElement(String name, String namespaceURI) {
 752  2 return new Element(name, "http://www.b.org/");
 753    }
 754   
 755    });
 756  1 Document doc = builder.build(data, "http://www.example.org/");
 757  1 Element root = doc.getRootElement();
 758  1 Element child = (Element) root.getChild(0);
 759  1 assertEquals("http://www.b.org/", child.getNamespaceURI());
 760   
 761    }
 762   
 763   
 764  1 public void testChangeTextToAttributes()
 765    throws ParsingException, IOException {
 766   
 767  1 String data = "<a><b>data1</b><c>text</c></a>";
 768  1 Builder builder = new Builder(new NodeFactory() {
 769   
 770  2 public Nodes makeText(String text) {
 771  2 Nodes result = new Nodes();
 772  2 result.append(new Attribute("name", text));
 773  2 return result;
 774    }
 775   
 776    });
 777  1 Document doc = builder.build(data, "http://www.example.org/");
 778  1 Element root = doc.getRootElement();
 779  1 assertEquals(2, root.getChildCount());
 780  1 assertEquals(0, root.getAttributeCount());
 781  1 assertEquals("", root.getValue());
 782  1 Element b = root.getFirstChildElement("b");
 783  1 Element c = root.getFirstChildElement("c");
 784  1 assertEquals("data1", b.getAttribute("name").getValue());
 785  1 assertEquals("text", c.getAttribute("name").getValue());
 786   
 787    }
 788   
 789   
 790  1 public void testChangeRootElementsToAttribute()
 791    throws ParsingException, IOException {
 792   
 793  1 String data = "<a><b>data1</b><c>text</c></a>";
 794  1 Builder builder = new Builder(new NodeFactory() {
 795   
 796  3 public Nodes finishMakingElement(Element element) {
 797  3 Nodes result = new Nodes();
 798  3 result.append(new Attribute(element.getLocalName(), element.getValue()));
 799  3 return result;
 800    }
 801   
 802    });
 803  1 try {
 804  1 builder.build(data, "http://www.example.org/");
 805  0 fail("replaced root element with attribute");
 806    }
 807    catch (ParsingException success) {
 808  1 assertNotNull(success.getMessage());
 809    }
 810   
 811    }
 812   
 813   
 814  1 public void testCantBypassMultipleParentChecks()
 815    throws ParsingException, IOException {
 816   
 817  1 String doc = "<root><a/><a/></root>";
 818  1 Builder builder = new Builder(new NodeFactory() {
 819   
 820    private Element a = new Element("a");
 821   
 822  3 public Element startMakingElement(String name, String namespace) {
 823  2 if (name.equals("a")) return a;
 824  1 return new Element(name, namespace);
 825    }
 826   
 827    });
 828  1 try {
 829  1 builder.build(doc, "http://www.example.org/");
 830  0 fail("built with multiple parents");
 831    }
 832    catch (ParsingException success) {
 833  1 assertNotNull(success.getMessage());
 834    }
 835   
 836    }
 837   
 838   
 839  1 public void testCantBypassMultipleParentChecksFromFinishMakingElement()
 840    throws ParsingException, IOException {
 841   
 842  1 String doc = "<root><a/><a/></root>";
 843  1 Builder builder = new Builder(new NodeFactory() {
 844   
 845    private Element a = new Element("a");
 846   
 847  2 public Nodes finishMakingElement(Element element) {
 848  2 if (element.getLocalName().equals("a")) return new Nodes(a);
 849  0 else return new Nodes(element);
 850    }
 851   
 852    });
 853  1 try {
 854  1 builder.build(doc, "http://www.example.org/");
 855  0 fail("built with multiple parents");
 856    }
 857    catch (ParsingException success) {
 858  1 assertNotNull(success.getMessage());
 859    }
 860   
 861    }
 862   
 863   
 864  1 public void testFinishMakingElementIsCalledForRootElement()
 865    throws ParsingException, IOException {
 866   
 867  1 String doc = "<root/>";
 868  1 Builder builder = new Builder(new NodeFactory() {
 869   
 870  1 public Nodes finishMakingElement(Element element) {
 871  1 throw new XMLException("Method was called");
 872    }
 873   
 874    });
 875  1 try {
 876  1 builder.build(doc, "http://www.example.org/");
 877  0 fail("Did not call finishMakingElement for root");
 878    }
 879    catch (ParsingException success) {
 880  1 assertEquals("Method was called", success.getMessage());
 881    }
 882   
 883    }
 884   
 885   
 886  1 public void testCanReplaceRootElementFromFinishMakingElement()
 887    throws ParsingException, IOException {
 888   
 889  1 String data = "<root/>";
 890  1 Builder builder = new Builder(new NodeFactory() {
 891   
 892  1 public Nodes finishMakingElement(Element element) {
 893  1 Nodes result = new Nodes();
 894  1 result.append(new Comment("test"));
 895  1 result.append(new Element("newroot"));
 896  1 result.append(new ProcessingInstruction("test", "test"));
 897  1 return result;
 898    }
 899   
 900    });
 901  1 Document doc = builder.build(data, "http://www.example.org/");
 902  1 assertEquals("newroot", doc.getRootElement().getQualifiedName());
 903  1 assertEquals(3, doc.getChildCount());
 904   
 905    }
 906   
 907   
 908  1 public void testCanAddAroundExistingRootElementFromFinishMakingElement()
 909    throws ParsingException, IOException {
 910   
 911  1 String data = "<root/>";
 912  1 Builder builder = new Builder(new NodeFactory() {
 913   
 914  1 public Nodes finishMakingElement(Element element) {
 915  1 Nodes result = new Nodes();
 916  1 result.append(new Comment("test"));
 917  1 result.append(element);
 918  1 result.append(new ProcessingInstruction("test", "test"));
 919  1 return result;
 920    }
 921   
 922    });
 923  1 Document doc = builder.build(data, "http://www.example.org/");
 924  1 assertEquals("root", doc.getRootElement().getQualifiedName());
 925  1 assertEquals(3, doc.getChildCount());
 926   
 927    }
 928   
 929   
 930  1 public void testCantReplaceRootElementWithNoElement()
 931    throws ParsingException, IOException {
 932   
 933  1 String data = "<root/>";
 934  1 Builder builder = new Builder(new NodeFactory() {
 935   
 936  1 public Nodes finishMakingElement(Element element) {
 937  1 Nodes result = new Nodes();
 938  1 result.append(new Comment("test"));
 939  1 result.append(new ProcessingInstruction("test", "test"));
 940  1 return result;
 941    }
 942   
 943    });
 944  1 try {
 945  1 builder.build(data, "http://www.example.org/");
 946  0 fail("Built document without root element");
 947    }
 948    catch (ParsingException success) {
 949  1 assertNotNull(success.getMessage());
 950    }
 951   
 952    }
 953   
 954   
 955  1 public void testCantReplaceRootElementWithNothing()
 956    throws ParsingException, IOException {
 957   
 958  1 String data = "<root/>";
 959  1 Builder builder = new Builder(new NodeFactory() {
 960   
 961  1 public Nodes finishMakingElement(Element element) {
 962  1 return new Nodes();
 963    }
 964   
 965    });
 966  1 try {
 967  1 builder.build(data, "http://www.example.org/");
 968  0 fail("Built document without root element");
 969    }
 970    catch (ParsingException success) {
 971  1 assertNotNull(success.getMessage());
 972    }
 973   
 974    }
 975   
 976   
 977  1 public void testReplaceCommentWithAttribute()
 978    throws ParsingException, IOException {
 979   
 980  1 String data = "<root><!--comment--></root>";
 981  1 Builder builder = new Builder(new NodeFactory() {
 982   
 983  1 public Nodes makeComment(String data) {
 984  1 return new Nodes(new Attribute("name", "value"));
 985    }
 986   
 987    });
 988  1 Document doc = builder.build(data, "http://www.example.org/");
 989  1 Element root = doc.getRootElement();
 990  1 assertEquals(0, root.getChildCount());
 991  1 assertEquals(1, root.getAttributeCount());
 992  1 assertEquals("value", root.getAttribute("name").getValue());
 993   
 994    }
 995   
 996   
 997  1 public void testReplaceProcessingInstructionWithAttribute()
 998    throws ParsingException, IOException {
 999   
 1000  1 String data = "<root><?target data?></root>";
 1001  1 Builder builder = new Builder(new NodeFactory() {
 1002   
 1003  1 public Nodes makeProcessingInstruction(String target, String data) {
 1004  1 return new Nodes(new Attribute("name", "value"));
 1005    }
 1006   
 1007    });
 1008  1 Document doc = builder.build(data, "http://www.example.org/");
 1009  1 Element root = doc.getRootElement();
 1010  1 assertEquals(0, root.getChildCount());
 1011  1 assertEquals(1, root.getAttributeCount());
 1012  1 assertEquals("value", root.getAttribute("name").getValue());
 1013   
 1014    }
 1015   
 1016   
 1017  1 public void testReplaceProcessingInstructionWithText()
 1018    throws ParsingException, IOException {
 1019   
 1020  1 String data = "<root><?target data?></root>";
 1021  1 Builder builder = new Builder(new NodeFactory() {
 1022   
 1023  1 public Nodes makeProcessingInstruction(String target, String data) {
 1024  1 return new Nodes(new Text(data));
 1025    }
 1026   
 1027    });
 1028  1 Document doc = builder.build(data, "http://www.example.org/");
 1029  1 Element root = doc.getRootElement();
 1030  1 assertEquals(1, root.getChildCount());
 1031  1 assertEquals(0, root.getAttributeCount());
 1032  1 assertEquals("data", root.getValue());
 1033   
 1034    }
 1035   
 1036   
 1037  1 public void testCantReplaceRootElementWithTwoElements()
 1038    throws ParsingException, IOException {
 1039   
 1040  1 String data = "<root/>";
 1041  1 Builder builder = new Builder(new NodeFactory() {
 1042   
 1043  1 public Nodes finishMakingElement(Element element) {
 1044  1 Nodes result = new Nodes();
 1045  1 result.append(new Element("first"));
 1046  1 result.append(new Element("second"));
 1047  1 return result;
 1048    }
 1049   
 1050    });
 1051  1 try {
 1052  1 builder.build(data, "http://www.example.org/");
 1053  0 fail("Built document without root element");
 1054    }
 1055    catch (ParsingException success) {
 1056  1 assertNotNull(success.getMessage());
 1057    }
 1058   
 1059    }
 1060   
 1061   
 1062  1 public void testOrderOfCalls()
 1063    throws ParsingException, IOException {
 1064   
 1065  1 String data = "<root>1<child>2</child>3</root>";
 1066  1 Builder builder = new Builder(new NodeFactory() {
 1067   
 1068    String s = "";
 1069   
 1070  3 public Nodes makeText(String text) {
 1071  3 s += text;
 1072  3 return super.makeText(text);
 1073    }
 1074   
 1075  2 public Element startMakingElement(String name, String namespace) {
 1076   
 1077  1 if (name.equals("child")) assertEquals("1", s);
 1078  2 return super.startMakingElement(name, namespace);
 1079    }
 1080   
 1081  2 public Nodes finishMakingElement(Element element) {
 1082  1 if (element.getLocalName().equals("child")) assertEquals("12", s);
 1083  1 if (element.getLocalName().equals("root")) assertEquals("123", s);
 1084  2 return super.finishMakingElement(element);
 1085    }
 1086   
 1087    });
 1088  1 builder.build(data, null);
 1089    }
 1090   
 1091   
 1092  1 public void testOrderOfCallsWithPI()
 1093    throws ParsingException, IOException {
 1094   
 1095  1 String data = "<root>1<?data ?>2</root>";
 1096  1 Builder builder = new Builder(new NodeFactory() {
 1097   
 1098    String s = "";
 1099   
 1100  2 public Nodes makeText(String text) {
 1101  2 s += text;
 1102  2 return super.makeText(text);
 1103    }
 1104   
 1105  1 public Nodes makeProcessingInstruction(String target, String data) {
 1106   
 1107  1 assertEquals("1", s);
 1108  1 return new Nodes();
 1109    }
 1110   
 1111    });
 1112  1 Document doc = builder.build(data, null);
 1113  1 assertEquals(2, doc.getRootElement().getChildCount());
 1114   
 1115    }
 1116   
 1117   
 1118  1 public void testFinishMakingElementDetachesItsArgument()
 1119    throws ParsingException, IOException {
 1120   
 1121  1 String data = "<root><a><b /></a></root>";
 1122  1 Builder builder = new Builder(new NodeFactory() {
 1123   
 1124  1 public Nodes finishMakingElement(Element element) {
 1125   
 1126  1 if (element.getLocalName().equals("b")) {
 1127  1 element.detach();
 1128  1 return new Nodes();
 1129    }
 1130  0 return new Nodes(element);
 1131    }
 1132   
 1133    });
 1134   
 1135  1 try {
 1136  1 builder.build(data, null);
 1137  0 fail("Allowed finishmakingElement to detach its argument");
 1138    }
 1139    catch (ParsingException success) {
 1140  1 assertNotNull(success.getMessage());
 1141    }
 1142   
 1143    }
 1144   
 1145    }