View Javadoc

1   /* $Id: SetNestedPropertiesRuleTestCase.java 1197969 2011-11-05 15:15:10Z simonetripodi $
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one or more
4    * contributor license agreements.  See the NOTICE file distributed with
5    * this work for additional information regarding copyright ownership.
6    * The ASF licenses this file to You under the Apache License, Version 2.0
7    * (the "License"); you may not use this file except in compliance with
8    * the License.  You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.commons.digester3;
20  
21  import static org.apache.commons.digester3.binder.DigesterLoader.newLoader;
22  import static org.junit.Assert.assertEquals;
23  import static org.junit.Assert.assertNotNull;
24  import static org.junit.Assert.fail;
25  
26  import java.io.IOException;
27  import java.io.Reader;
28  import java.io.StringReader;
29  
30  import org.apache.commons.digester3.binder.AbstractRulesModule;
31  import org.junit.Test;
32  import org.xml.sax.SAXException;
33  
34  /**
35   * <p>
36   * Test case for <code>SetNestedPropertiesRule</code>. This contains tests for the main applications of the rule and two
37   * more general tests of digester functionality used by this rule.
38   */
39  public class SetNestedPropertiesRuleTestCase
40  {
41  
42      // ----------------------------------------------------- Instance Variables
43  
44      /**
45       * Simple test xml document used in the tests.
46       */
47      protected final static String TEST_XML = "<?xml version='1.0'?>" + "<root>ROOT BODY" + "<alpha>ALPHA BODY</alpha>"
48          + "<beta>BETA BODY</beta>" + "<gamma>GAMMA BODY</gamma>" + "<delta>DELTA BODY</delta>" + "</root>";
49  
50      // ------------------------------------------------ Individual Test Methods
51  
52      /**
53       * Test that you can successfully automatically set properties.
54       */
55      @Test
56      public void testAutomaticallySetProperties()
57          throws SAXException, IOException
58      {
59          Digester digester = newLoader( new AbstractRulesModule()
60          {
61  
62              @Override
63              protected void configure()
64              {
65                  forPattern( "root" ).createObject().ofType( "org.apache.commons.digester3.SimpleTestBean" )
66                      .then()
67                      .setNestedProperties();
68              }
69  
70          }).newDigester();
71  
72          SimpleTestBean bean = digester.parse( xmlTestReader() );
73  
74          // check properties are set correctly
75          assertEquals( "Property alpha not set correctly", "ALPHA BODY", bean.getAlpha() );
76  
77          assertEquals( "Property beta not set correctly", "BETA BODY", bean.getBeta() );
78  
79          assertEquals( "Property gamma not set correctly", "GAMMA BODY", bean.getGamma() );
80  
81          assertEquals( "Property delta not set correctly", "DELTA BODY", bean.getDeltaValue() );
82      }
83  
84      /**
85       * Test that it is an error when a child element exists but no corresponding java property exists.
86       */
87      @Test
88      public void testMandatoryProperties()
89          throws SAXException, IOException
90      {
91          Digester digester = newLoader( new AbstractRulesModule()
92          {
93  
94              @Override
95              protected void configure()
96              {
97                  forPattern( "root" ).createObject().ofType( "org.apache.commons.digester3.SimpleTestBean" )
98                      .then()
99                      .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 }