001/* $Id: SetNestedPropertiesRuleTestCase.java 1197969 2011-11-05 15:15:10Z 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.fail; 025 026import java.io.IOException; 027import java.io.Reader; 028import java.io.StringReader; 029 030import org.apache.commons.digester3.binder.AbstractRulesModule; 031import org.junit.Test; 032import org.xml.sax.SAXException; 033 034/** 035 * <p> 036 * Test case for <code>SetNestedPropertiesRule</code>. This contains tests for the main applications of the rule and two 037 * more general tests of digester functionality used by this rule. 038 */ 039public class SetNestedPropertiesRuleTestCase 040{ 041 042 // ----------------------------------------------------- Instance Variables 043 044 /** 045 * Simple test xml document used in the tests. 046 */ 047 protected final static String TEST_XML = "<?xml version='1.0'?>" + "<root>ROOT BODY" + "<alpha>ALPHA BODY</alpha>" 048 + "<beta>BETA BODY</beta>" + "<gamma>GAMMA BODY</gamma>" + "<delta>DELTA BODY</delta>" + "</root>"; 049 050 // ------------------------------------------------ Individual Test Methods 051 052 /** 053 * Test that you can successfully automatically set properties. 054 */ 055 @Test 056 public void testAutomaticallySetProperties() 057 throws SAXException, IOException 058 { 059 Digester digester = newLoader( new AbstractRulesModule() 060 { 061 062 @Override 063 protected void configure() 064 { 065 forPattern( "root" ).createObject().ofType( "org.apache.commons.digester3.SimpleTestBean" ) 066 .then() 067 .setNestedProperties(); 068 } 069 070 }).newDigester(); 071 072 SimpleTestBean bean = digester.parse( xmlTestReader() ); 073 074 // check properties are set correctly 075 assertEquals( "Property alpha not set correctly", "ALPHA BODY", bean.getAlpha() ); 076 077 assertEquals( "Property beta not set correctly", "BETA BODY", bean.getBeta() ); 078 079 assertEquals( "Property gamma not set correctly", "GAMMA BODY", bean.getGamma() ); 080 081 assertEquals( "Property delta not set correctly", "DELTA BODY", bean.getDeltaValue() ); 082 } 083 084 /** 085 * Test that it is an error when a child element exists but no corresponding java property exists. 086 */ 087 @Test 088 public void testMandatoryProperties() 089 throws SAXException, IOException 090 { 091 Digester digester = newLoader( new AbstractRulesModule() 092 { 093 094 @Override 095 protected void configure() 096 { 097 forPattern( "root" ).createObject().ofType( "org.apache.commons.digester3.SimpleTestBean" ) 098 .then() 099 .setNestedProperties(); 100 } 101 102 }).newDigester(); 103 104 String TEST_XML = "<?xml version='1.0'?>" + "<root>ROOT BODY" + "<badprop>ALPHA BODY</badprop>" + "</root>"; 105 106 try 107 { 108 SimpleTestBean bean = digester.parse( new StringReader( TEST_XML ) ); 109 110 // we should never get here... 111 fail( "No exception thrown by parse when unknown child element found." ); 112 assertNotNull( bean ); // just to prevent compiler warning on unused var 113 } 114 catch ( org.xml.sax.SAXParseException e ) 115 { 116 String msg = e.getMessage(); 117 if ( msg.indexOf( "badprop" ) >= 0 ) 118 { 119 // ok, this is expected; there is no "setBadprop" method on the 120 // SimpleTestBean class... 121 } 122 else 123 { 124 fail( "Unexpected parse exception:" + e.getMessage() ); 125 } 126 } 127 } 128 129 /** 130 * Test that you can customise the property mappings using the constructor which takes arrays-of-strings. 131 */ 132 @Test 133 public void testCustomisedProperties1() 134 throws SAXException, IOException 135 { 136 Digester digester = newLoader( new AbstractRulesModule() 137 { 138 139 @Override 140 protected void configure() 141 { 142 forPattern( "root" ).createObject().ofType( "org.apache.commons.digester3.SimpleTestBean" ) 143 .then() 144 .setNestedProperties() 145 .addAlias( "alpha" ).forProperty( null ) 146 .addAlias( "gamma-alt" ).forProperty( "gamma" ) 147 .addAlias( "delta" ).forProperty( null ); 148 } 149 150 }).newDigester(); 151 152 String TEST_XML = 153 "<?xml version='1.0'?>" + "<root>ROOT BODY" + "<alpha>ALPHA BODY</alpha>" + "<beta>BETA BODY</beta>" 154 + "<gamma-alt>GAMMA BODY</gamma-alt>" + "<delta>DELTA BODY</delta>" + "</root>"; 155 156 SimpleTestBean bean = digester.parse( new StringReader( TEST_XML ) ); 157 158 // check properties are set correctly 159 assertEquals( "Property alpha was not ignored (it should be)", null, bean.getAlpha() ); 160 161 assertEquals( "Property beta not set correctly", "BETA BODY", bean.getBeta() ); 162 163 assertEquals( "Property gamma not set correctly", "GAMMA BODY", bean.getGamma() ); 164 165 assertEquals( "Property delta was not ignored (it should be)", null, bean.getDeltaValue() ); 166 167 // check no bad rules object is left 168 assertEquals( "Digester rules object not reset.", RulesBase.class, digester.getRules().getClass() ); 169 } 170 171 /** 172 * Test that you can ignore a single input xml element using the constructor which takes a single remapping. 173 */ 174 @Test 175 public void testCustomisedProperties2a() 176 throws SAXException, IOException 177 { 178 Digester digester = newLoader( new AbstractRulesModule() 179 { 180 181 @Override 182 protected void configure() 183 { 184 forPattern( "root" ).createObject().ofType( "org.apache.commons.digester3.SimpleTestBean" ) 185 .then() 186 .setNestedProperties() 187 .addAlias( "alpha" ).forProperty( null ); 188 } 189 190 }).newDigester(); 191 192 String TEST_XML = 193 "<?xml version='1.0'?>" + "<root>ROOT BODY" + "<alpha>ALPHA BODY</alpha>" + "<beta>BETA BODY</beta>" 194 + "<gamma>GAMMA BODY</gamma>" + "<delta>DELTA BODY</delta>" + "</root>"; 195 196 SimpleTestBean bean = digester.parse( new StringReader( TEST_XML ) ); 197 198 // check properties are set correctly 199 assertEquals( "Property alpha was not ignored (it should be)", null, bean.getAlpha() ); 200 201 assertEquals( "Property beta not set correctly", "BETA BODY", bean.getBeta() ); 202 203 assertEquals( "Property gamma not set correctly", "GAMMA BODY", bean.getGamma() ); 204 205 assertEquals( "Property delta not set correctly", "DELTA BODY", bean.getDeltaValue() ); 206 207 // check no bad rules object is left 208 assertEquals( "Digester rules object not reset.", RulesBase.class, digester.getRules().getClass() ); 209 } 210 211 /** 212 * Test that you can customise the property mappings using the constructor which takes a single remapping. 213 */ 214 @Test 215 public void testCustomisedProperties2b() 216 throws SAXException, IOException 217 { 218 Digester digester = newLoader( new AbstractRulesModule() 219 { 220 221 @Override 222 protected void configure() 223 { 224 forPattern( "root" ).createObject().ofType( "org.apache.commons.digester3.SimpleTestBean" ) 225 .then() 226 .setNestedProperties() 227 .addAlias( "alpha-alt" ).forProperty( "alpha" ); 228 } 229 230 }).newDigester(); 231 232 String TEST_XML = 233 "<?xml version='1.0'?>" + "<root>ROOT BODY" + "<alpha-alt>ALPHA BODY</alpha-alt>" 234 + "<beta>BETA BODY</beta>" + "<gamma>GAMMA BODY</gamma>" + "<delta>DELTA BODY</delta>" + "</root>"; 235 236 SimpleTestBean bean = digester.parse( new StringReader( TEST_XML ) ); 237 238 // check properties are set correctly 239 assertEquals( "Property alpha not set correctly", "ALPHA BODY", bean.getAlpha() ); 240 241 assertEquals( "Property beta not set correctly", "BETA BODY", bean.getBeta() ); 242 243 assertEquals( "Property gamma not set correctly", "GAMMA BODY", bean.getGamma() ); 244 245 assertEquals( "Property delta not set correctly", "DELTA BODY", bean.getDeltaValue() ); 246 247 // check no bad rules object is left 248 assertEquals( "Digester rules object not reset.", RulesBase.class, digester.getRules().getClass() ); 249 } 250 251 /** 252 * Test that: 253 * <ul> 254 * <li>you can have rules matching the same pattern as the SetNestedPropertiesRule,</li> 255 * <li>you can have rules matching child elements of the rule,</li> 256 * <li>the Rules object is reset nicely.</li> 257 * </ul> 258 */ 259 @Test 260 public void testMultiRuleMatch() 261 throws SAXException, IOException 262 { 263 Digester digester = newLoader( new AbstractRulesModule() 264 { 265 266 @Override 267 protected void configure() 268 { 269 forPattern( "root/testbean" ).createObject().ofType( "org.apache.commons.digester3.SimpleTestBean" ) 270 .then() 271 .setProperties() 272 .then() 273 .setNestedProperties(); 274 forPattern( "root/testbean/gamma/prop" ).setProperty( "name" ).extractingValueFromAttribute( "value" ); 275 } 276 277 }).newDigester(); 278 279 String testXml = 280 "<?xml version='1.0'?>" + "<root>" + "<testbean alpha='alpha-attr'>ROOT BODY" + "<beta>BETA BODY</beta>" 281 + "<gamma>GAMMA " + "<prop name='delta' value='delta-prop'/>" + "BODY" + "</gamma>" + "</testbean>" 282 + "</root>"; 283 284 Reader reader = new StringReader( testXml ); 285 286 SimpleTestBean bean = digester.parse( reader ); 287 288 assertNotNull( "No object created", bean ); 289 290 // check properties are set correctly 291 assertEquals( "Property alpha not set correctly", "alpha-attr", bean.getAlpha() ); 292 293 assertEquals( "Property beta not set correctly", "BETA BODY", bean.getBeta() ); 294 295 assertEquals( "Property gamma not set correctly", "GAMMA BODY", bean.getGamma() ); 296 297 assertEquals( "Property delta not set correctly", "delta-prop", bean.getDeltaValue() ); 298 299 // check no bad rules object is left 300 assertEquals( "Digester rules object not reset.", RulesBase.class, digester.getRules().getClass() ); 301 } 302 303 /** 304 * Test that unknown child elements trigger an exception. 305 */ 306 @Test 307 public void testUnknownChildrenCausesException() 308 throws SAXException, IOException 309 { 310 Digester digester = newLoader( new AbstractRulesModule() 311 { 312 313 @Override 314 protected void configure() 315 { 316 forPattern( "root" ).createObject().ofType( "org.apache.commons.digester3.SimpleTestBean" ) 317 .then() 318 .setNestedProperties(); 319 } 320 321 }).newDigester(); 322 323 String testXml = 324 "<?xml version='1.0'?>" + "<root>" + "<testbean>" + "<beta>BETA BODY</beta>" + "<foo>GAMMA</foo>" 325 + "</testbean>" + "</root>"; 326 327 Reader reader = new StringReader( testXml ); 328 329 try 330 { 331 SimpleTestBean bean = digester.parse( reader ); 332 fail( "Expected to generate an exception." ); 333 assertNotNull( bean ); // just to prevent compiler warning on unused var 334 } 335 catch ( SAXException e ) 336 { 337 Exception nested = e.getException(); 338 if ( ( nested == null ) || !( nested instanceof NoSuchMethodException ) ) 339 { 340 // nope, not the sort of exception we expected 341 throw e; 342 } 343 } 344 } 345 346 /** 347 * Test that unknown child elements are allowed if the appropriate flag is set. 348 */ 349 @Test 350 public void testUnknownChildrenExceptionOverride() 351 throws SAXException, IOException 352 { 353 Digester digester = newLoader( new AbstractRulesModule() 354 { 355 356 @Override 357 protected void configure() 358 { 359 forPattern( "root" ).createObject().ofType( "org.apache.commons.digester3.SimpleTestBean" ) 360 .then() 361 .setNestedProperties().allowUnknownChildElements( true ); 362 } 363 364 }).newDigester(); 365 366 String testXml = 367 "<?xml version='1.0'?>" + "<root>" + "<testbean>" + "<beta>BETA BODY</beta>" + "<foo>GAMMA</foo>" 368 + "</testbean>" + "</root>"; 369 370 Reader reader = new StringReader( testXml ); 371 372 SimpleTestBean bean = digester.parse( reader ); 373 assertNotNull( bean ); 374 } 375 376 /** 377 * Test that the rule works in a sane manner when the associated pattern is a wildcard such that the rule matches 378 * one of its own child elements. 379 * <p> 380 * See bugzilla entry 31393. 381 */ 382 @Test 383 public void testRecursiveNestedProperties() 384 throws SAXException, IOException 385 { 386 Digester digester = newLoader( new AbstractRulesModule() 387 { 388 389 @Override 390 protected void configure() 391 { 392 forPattern( "*/testbean" ).createObject().ofType( "org.apache.commons.digester3.SimpleTestBean" ) 393 .then() 394 .setNestedProperties().allowUnknownChildElements( true ); 395 } 396 397 }).newDigester(); 398 399 String testXml = 400 "<?xml version='1.0'?>" + "<testbean>" + "<beta>BETA BODY</beta>" + "<testbean>" + "<beta>BETA BODY</beta>" 401 + "</testbean>" + "</testbean>"; 402 403 Reader reader = new StringReader( testXml ); 404 405 SimpleTestBean bean = digester.parse( reader ); 406 assertNotNull( bean ); 407 } 408 409 /** 410 * Get input stream from {@link #TEST_XML}. 411 */ 412 private Reader xmlTestReader() 413 { 414 return new StringReader( TEST_XML ); 415 } 416 417}