001/* $Id: NodeCreateRuleTestCase.java 1212599 2011-12-09 19:46:42Z simonetripodi $ 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one or more 004 * contributor license agreements. See the NOTICE file distributed with 005 * this work for additional information regarding copyright ownership. 006 * The ASF licenses this file to You under the Apache License, Version 2.0 007 * (the "License"); you may not use this file except in compliance with 008 * the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.commons.digester3; 020 021import static org.apache.commons.digester3.binder.DigesterLoader.newLoader; 022import static org.junit.Assert.assertEquals; 023import static org.junit.Assert.assertNotNull; 024import static org.junit.Assert.assertNull; 025import static org.junit.Assert.assertTrue; 026import static org.junit.Assert.fail; 027 028import java.io.IOException; 029import java.io.InputStream; 030import java.io.StringReader; 031import java.util.ArrayList; 032import java.util.List; 033 034import javax.xml.parsers.DocumentBuilder; 035import javax.xml.parsers.DocumentBuilderFactory; 036import javax.xml.parsers.ParserConfigurationException; 037 038import org.apache.commons.digester3.binder.AbstractRulesModule; 039import org.apache.commons.digester3.binder.NodeCreateRuleProvider.NodeType; 040import org.junit.Test; 041import org.w3c.dom.Document; 042import org.w3c.dom.DocumentFragment; 043import org.w3c.dom.Element; 044import org.w3c.dom.Node; 045import org.xml.sax.SAXException; 046 047/** 048 * <p> 049 * Test case for the <code>NodeCreateRule</code>. 050 * 051 * @author Christopher Lenz 052 */ 053public class NodeCreateRuleTestCase 054{ 055 056 // ----------------------------------------------------- Instance Variables 057 058 /** 059 * Simple test xml document used in the tests. 060 */ 061 protected final static String TEST_XML = "<?xml version='1.0'?><root>ROOT BODY<alpha>ALPHA BODY</alpha>" 062 + "<beta>BETA BODY</beta><gamma>GAMMA BODY</gamma></root>"; 063 064 // ------------------------------------------------ Individual Test Methods 065 066 /** 067 * Tests simple element construction, using the {@link #TEST_XML} XML input data. 068 */ 069 @Test 070 public void testInvalidNodeTypes() 071 throws Exception 072 { 073 074 try 075 { 076 Rule rule = new NodeCreateRule( Node.ATTRIBUTE_NODE ); 077 fail( "IllegalArgumentException expected for type ATTRIBUTE_NODE" ); 078 assertNotNull( rule ); // just to prevent compiler warning on unused var 079 } 080 catch ( IllegalArgumentException iae ) 081 { 082 // expected 083 } 084 try 085 { 086 Rule rule = new NodeCreateRule( Node.CDATA_SECTION_NODE ); 087 fail( "IllegalArgumentException expected for type " + "CDATA_SECTION_NODE" ); 088 assertNotNull( rule ); // just to prevent compiler warning on unused var 089 } 090 catch ( IllegalArgumentException iae ) 091 { 092 // expected 093 } 094 try 095 { 096 Rule rule = new NodeCreateRule( Node.COMMENT_NODE ); 097 fail( "IllegalArgumentException expected for type COMMENT_NODE" ); 098 assertNotNull( rule ); // just to prevent compiler warning on unused var 099 } 100 catch ( IllegalArgumentException iae ) 101 { 102 // expected 103 } 104 try 105 { 106 Rule rule = new NodeCreateRule( Node.DOCUMENT_NODE ); 107 fail( "IllegalArgumentException expected for type DOCUMENT_NODE" ); 108 assertNotNull( rule ); // just to prevent compiler warning on unused var 109 } 110 catch ( IllegalArgumentException iae ) 111 { 112 // expected 113 } 114 try 115 { 116 Rule rule = new NodeCreateRule( Node.DOCUMENT_TYPE_NODE ); 117 fail( "IllegalArgumentException expected for type " + "DOCUMENT_TYPE_NODE" ); 118 assertNotNull( rule ); // just to prevent compiler warning on unused var 119 } 120 catch ( IllegalArgumentException iae ) 121 { 122 // expected 123 } 124 try 125 { 126 Rule rule = new NodeCreateRule( Node.ENTITY_NODE ); 127 fail( "IllegalArgumentException expected for type ENTITY_NODE" ); 128 assertNotNull( rule ); // just to prevent compiler warning on unused var 129 } 130 catch ( IllegalArgumentException iae ) 131 { 132 // expected 133 } 134 try 135 { 136 Rule rule = new NodeCreateRule( Node.ENTITY_REFERENCE_NODE ); 137 fail( "IllegalArgumentException expected for type " + "ENTITY_REFERENCE_NODE" ); 138 assertNotNull( rule ); // just to prevent compiler warning on unused var 139 } 140 catch ( IllegalArgumentException iae ) 141 { 142 // expected 143 } 144 try 145 { 146 Rule rule = new NodeCreateRule( Node.NOTATION_NODE ); 147 fail( "IllegalArgumentException expected for type NOTATION_NODE" ); 148 assertNotNull( rule ); // just to prevent compiler warning on unused var 149 } 150 catch ( IllegalArgumentException iae ) 151 { 152 // expected 153 } 154 try 155 { 156 Rule rule = new NodeCreateRule( Node.PROCESSING_INSTRUCTION_NODE ); 157 fail( "IllegalArgumentException expected for type " + "PROCESSING_INSTRUCTION_NODE" ); 158 assertNotNull( rule ); // just to prevent compiler warning on unused var 159 } 160 catch ( IllegalArgumentException iae ) 161 { 162 // expected 163 } 164 try 165 { 166 Rule rule = new NodeCreateRule( Node.TEXT_NODE ); 167 fail( "IllegalArgumentException expected for type TEXT_NODE" ); 168 assertNotNull( rule ); // just to prevent compiler warning on unused var 169 } 170 catch ( IllegalArgumentException iae ) 171 { 172 // expected 173 } 174 175 } 176 177 /** 178 * Tests simple element construction, using the {@link #TEST_XML} XML input data. 179 */ 180 @Test 181 public void testElement() 182 throws SAXException, IOException 183 { 184 Digester digester = newLoader( new AbstractRulesModule() 185 { 186 187 @Override 188 protected void configure() 189 { 190 forPattern( "root/alpha" ).createNode(); 191 } 192 193 }).newDigester(); 194 195 Element element = digester.parse( new StringReader( TEST_XML ) ); 196 197 assertNotNull( element ); 198 assertEquals( "alpha", element.getNodeName() ); 199 assertNull( element.getLocalName() ); 200 assertNull( element.getNamespaceURI() ); 201 assertEquals( 1, element.getChildNodes().getLength() ); 202 assertEquals( "ALPHA BODY", element.getFirstChild().getNodeValue() ); 203 204 } 205 206 /** 207 * Tests simple fragment construction, using the {@link #TEST_XML} XML input data. 208 */ 209 @Test 210 public void testDocumentFragment() 211 throws SAXException, IOException 212 { 213 Digester digester = newLoader( new AbstractRulesModule() 214 { 215 216 @Override 217 protected void configure() 218 { 219 forPattern( "root" ).createNode().ofType( NodeType.DOCUMENT_FRAGMENT ); 220 } 221 222 }).newDigester(); 223 224 DocumentFragment fragment = digester.parse( new StringReader( TEST_XML ) ); 225 226 assertNotNull( fragment ); 227 assertEquals( 4, fragment.getChildNodes().getLength() ); 228 229 Node rootBody = fragment.getFirstChild(); 230 assertEquals( Node.TEXT_NODE, rootBody.getNodeType() ); 231 assertEquals( "ROOT BODY", rootBody.getNodeValue() ); 232 233 Node alpha = fragment.getChildNodes().item( 1 ); 234 assertEquals( Node.ELEMENT_NODE, alpha.getNodeType() ); 235 assertEquals( "alpha", alpha.getNodeName() ); 236 assertNull( ( (Element) alpha ).getLocalName() ); 237 assertNull( ( (Element) alpha ).getNamespaceURI() ); 238 assertEquals( 1, alpha.getChildNodes().getLength() ); 239 assertEquals( "ALPHA BODY", alpha.getFirstChild().getNodeValue() ); 240 241 Node beta = fragment.getChildNodes().item( 2 ); 242 assertEquals( Node.ELEMENT_NODE, beta.getNodeType() ); 243 assertEquals( "beta", beta.getNodeName() ); 244 assertNull( ( (Element) beta ).getLocalName() ); 245 assertNull( ( (Element) beta ).getNamespaceURI() ); 246 assertEquals( 1, beta.getChildNodes().getLength() ); 247 assertEquals( "BETA BODY", beta.getFirstChild().getNodeValue() ); 248 249 Node gamma = fragment.getChildNodes().item( 3 ); 250 assertEquals( Node.ELEMENT_NODE, gamma.getNodeType() ); 251 assertEquals( "gamma", gamma.getNodeName() ); 252 assertNull( ( (Element) gamma ).getLocalName() ); 253 assertNull( ( (Element) gamma ).getNamespaceURI() ); 254 assertEquals( 1, gamma.getChildNodes().getLength() ); 255 assertEquals( "GAMMA BODY", gamma.getFirstChild().getNodeValue() ); 256 257 } 258 259 /** 260 * Tests whether control is returned to digester after fragment construction. 261 */ 262 @Test 263 public void testNested() 264 throws SAXException, IOException 265 { 266 Digester digester = newLoader( new AbstractRulesModule() 267 { 268 269 @Override 270 protected void configure() 271 { 272 forPattern( "root" ).createObject().ofType( ArrayList.class ); 273 forPattern( "root/a/b" ).createNode().ofType( NodeType.DOCUMENT_FRAGMENT ) 274 .then() 275 .setRoot( "add" ); 276 forPattern( "root/b" ).createObject().ofType( String.class ) 277 .then() 278 .setRoot( "add" ); 279 } 280 281 }).newDigester(); 282 283 List<?> list = digester.parse( getInputStream( "Test4.xml" ) ); 284 285 assertNotNull( list ); 286 assertEquals( 2, list.size() ); 287 288 assertTrue( list.get( 0 ) instanceof DocumentFragment ); 289 DocumentFragment fragment = (DocumentFragment) list.get( 0 ); 290 291 assertEquals( Node.ELEMENT_NODE, fragment.getFirstChild().getNodeType() ); 292 Element a = (Element) fragment.getFirstChild(); 293 assertEquals( "a", a.getNodeName() ); 294 assertEquals( 1, a.getAttributes().getLength() ); 295 assertEquals( "THREE", a.getAttribute( "name" ) ); 296 297 assertTrue( list.get( 1 ) instanceof String ); 298 299 } 300 301 /** 302 * Tests whether attributes are correctly imported into the fragment, using the example in the Test1 XML file. 303 */ 304 @Test 305 public void testAttributes() 306 throws SAXException, IOException 307 { 308 Digester digester = newLoader( new AbstractRulesModule() 309 { 310 311 @Override 312 protected void configure() 313 { 314 forPattern( "employee" ).createNode().ofType( NodeType.DOCUMENT_FRAGMENT ); 315 } 316 317 }).newDigester(); 318 319 DocumentFragment fragment = digester.parse( getInputStream( "Test1.xml" ) ); 320 321 assertNotNull( fragment ); 322 assertEquals( 2, fragment.getChildNodes().getLength() ); 323 324 assertEquals( Node.ELEMENT_NODE, fragment.getFirstChild().getNodeType() ); 325 Element address1 = (Element) fragment.getFirstChild(); 326 assertEquals( "address", address1.getNodeName() ); 327 assertEquals( 5, address1.getAttributes().getLength() ); 328 assertEquals( "home", address1.getAttribute( "type" ) ); 329 assertEquals( "Home Street", address1.getAttribute( "street" ) ); 330 assertEquals( "Home City", address1.getAttribute( "city" ) ); 331 assertEquals( "HS", address1.getAttribute( "state" ) ); 332 assertEquals( "HmZip", address1.getAttribute( "zipCode" ) ); 333 334 assertEquals( Node.ELEMENT_NODE, fragment.getLastChild().getNodeType() ); 335 Element address2 = (Element) fragment.getLastChild(); 336 assertEquals( "address", address2.getNodeName() ); 337 assertEquals( 5, address2.getAttributes().getLength() ); 338 assertEquals( "office", address2.getAttribute( "type" ) ); 339 assertEquals( "Office Street", address2.getAttribute( "street" ) ); 340 assertEquals( "Office City", address2.getAttribute( "city" ) ); 341 assertEquals( "OS", address2.getAttribute( "state" ) ); 342 assertEquals( "OfZip", address2.getAttribute( "zipCode" ) ); 343 344 } 345 346 /** 347 * Tests whether namespaces are handled correctly, using the example from the file Test3 XML file. 348 */ 349 @Test 350 public void testNamespaces() 351 throws SAXException, IOException 352 { 353 Digester digester = newLoader( new AbstractRulesModule() 354 { 355 356 @Override 357 protected void configure() 358 { 359 forPattern( "employee" ).createNode().ofType( NodeType.DOCUMENT_FRAGMENT ); 360 } 361 362 }) 363 .setNamespaceAware( true ) 364 .newDigester(); 365 366 DocumentFragment fragment = digester.parse( getInputStream( "Test3.xml" ) ); 367 368 assertNotNull( fragment ); 369 assertEquals( 2, fragment.getChildNodes().getLength() ); 370 371 assertEquals( Node.ELEMENT_NODE, fragment.getFirstChild().getNodeType() ); 372 Element address1 = (Element) fragment.getFirstChild(); 373 assertEquals( "address", address1.getNodeName() ); 374 assertEquals( "http://commons.apache.org/digester/Bar", address1.getNamespaceURI() ); 375 assertEquals( "address", address1.getLocalName() ); 376 assertEquals( 5, address1.getAttributes().getLength() ); 377 assertEquals( "home", address1.getAttribute( "type" ) ); 378 assertEquals( "Home Street", address1.getAttribute( "street" ) ); 379 assertEquals( "Home City", address1.getAttribute( "city" ) ); 380 assertEquals( "HS", address1.getAttribute( "state" ) ); 381 assertEquals( "HmZip", address1.getAttribute( "zipCode" ) ); 382 383 assertEquals( Node.ELEMENT_NODE, fragment.getLastChild().getNodeType() ); 384 Element address2 = (Element) fragment.getLastChild(); 385 assertEquals( "address", address2.getNodeName() ); 386 assertEquals( "http://commons.apache.org/digester/Bar", address2.getNamespaceURI() ); 387 assertEquals( "address", address2.getLocalName() ); 388 assertEquals( 5, address2.getAttributes().getLength() ); 389 assertEquals( "office", address2.getAttribute( "type" ) ); 390 assertEquals( "Office Street", address2.getAttribute( "street" ) ); 391 assertEquals( "Office City", address2.getAttribute( "city" ) ); 392 assertEquals( "OS", address2.getAttribute( "state" ) ); 393 assertEquals( "OfZip", address2.getAttribute( "zipCode" ) ); 394 395 } 396 397 /** 398 * Tests whether namespaced attributes are handled correctly, using the example from the file Test10 XML file. 399 */ 400 @Test 401 public void testNamespacedAttribute() 402 throws SAXException, IOException 403 { 404 Digester digester = newLoader( new AbstractRulesModule() 405 { 406 407 @Override 408 protected void configure() 409 { 410 forPattern( "employee" ).createNode().ofType( NodeType.ELEMENT ); 411 } 412 413 }) 414 .setNamespaceAware( true ) 415 .newDigester(); 416 417 Element element = digester.parse( getInputStream( "Test10.xml" ) ); 418 419 assertNotNull( element ); 420 421 assertNotNull( element.getAttributeNodeNS( "http://commons.apache.org/digester/Bar", "test" ) ); 422 assertEquals( "MyTestAttribute", 423 element.getAttributeNodeNS( "http://commons.apache.org/digester/Bar", "test" ).getNodeValue() ); 424 assertEquals( "test", 425 element.getAttributeNodeNS( "http://commons.apache.org/digester/Bar", "test" ).getLocalName() ); 426 assertEquals( "bar", element.getAttributeNodeNS( "http://commons.apache.org/digester/Bar", "test" ).getPrefix() ); 427 assertEquals( "bar:test", 428 element.getAttributeNodeNS( "http://commons.apache.org/digester/Bar", "test" ).getName() ); 429 430 } 431 432 /** 433 * Tests whether non-namespaced attributes are handled correctly, using the example from the file Test11 XML file. 434 */ 435 @Test 436 public void testNonNamespacedAttribute() 437 throws SAXException, IOException 438 { 439 Digester digester = newLoader( new AbstractRulesModule() 440 { 441 442 @Override 443 protected void configure() 444 { 445 forPattern( "employee" ).createNode().ofType( NodeType.ELEMENT ); 446 } 447 448 }) 449 .setNamespaceAware( true ) 450 .newDigester(); 451 452 Element element = digester.parse( getInputStream( "Test10.xml" ) ); 453 454 assertNotNull( element ); 455 456 assertNotNull( element.getAttributeNode( "firstName" ) ); 457 assertEquals( "First Name", element.getAttributeNode( "firstName" ).getNodeValue() ); 458 assertEquals( "firstName", element.getAttributeNode( "firstName" ).getLocalName() ); 459 assertEquals( null, element.getAttributeNode( "firstName" ).getPrefix() ); 460 assertEquals( "firstName", element.getAttributeNode( "firstName" ).getName() ); 461 462 } 463 464 /** 465 * Tests whether the created fragment can be imported into an existing document. 466 */ 467 @Test 468 public void testImport() 469 throws SAXException, ParserConfigurationException, IOException 470 { 471 Digester digester = newLoader( new AbstractRulesModule() 472 { 473 474 @Override 475 protected void configure() 476 { 477 forPattern( "root" ).createNode().ofType( NodeType.DOCUMENT_FRAGMENT ); 478 } 479 480 }) 481 .newDigester(); 482 483 DocumentFragment fragment = digester.parse( new StringReader( TEST_XML ) ); 484 485 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 486 DocumentBuilder builder = factory.newDocumentBuilder(); 487 Document doc = builder.newDocument(); 488 Node importedFragment = doc.importNode( fragment, true ); 489 doc.appendChild( doc.createElement( "root" ) ); 490 doc.getFirstChild().appendChild( importedFragment ); 491 492 } 493 494 /** 495 * This unit test checks that text nodes are correctly created when xml entities are used. In particular, this 496 * usually causes the xml parser to make multiple invocations of the characters(..) sax callback, rather than just 497 * one. 498 */ 499 @Test 500 public void testEntityText() 501 throws Exception 502 { 503 String TEST_XML2 = "<?xml version='1.0'?><root><alpha>A A</alpha></root>"; 504 505 Digester digester = newLoader( new AbstractRulesModule() 506 { 507 508 @Override 509 protected void configure() 510 { 511 forPattern( "root/alpha" ).createNode(); 512 } 513 514 }) 515 .newDigester(); 516 517 Element element = digester.parse( new StringReader( TEST_XML2 ) ); 518 519 assertNotNull( element ); 520 assertEquals( "alpha", element.getNodeName() ); 521 assertNull( element.getLocalName() ); 522 assertNull( element.getNamespaceURI() ); 523 assertEquals( 1, element.getChildNodes().getLength() ); 524 assertEquals( "A A", element.getFirstChild().getNodeValue() ); 525 } 526 527 // ------------------------------------------------ Utility Support Methods 528 529 /** 530 * Return an appropriate InputStream for the specified test file (which must be inside our current package. 531 * 532 * @param name Name of the test file we want 533 * @exception IOException if an input/output error occurs 534 */ 535 protected InputStream getInputStream( String name ) 536 throws IOException 537 { 538 539 return ( this.getClass().getResourceAsStream( "/org/apache/commons/digester3/" + name ) ); 540 541 } 542 543}