001/* $Id: BeanPropertySetterRuleTestCase.java 1140140 2011-06-27 12:34:56Z 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.assertTrue;
025import static org.junit.Assert.fail;
026
027import java.io.IOException;
028import java.io.Reader;
029import java.io.StringReader;
030import java.lang.reflect.InvocationTargetException;
031import java.util.ArrayList;
032import java.util.List;
033
034import org.apache.commons.digester3.binder.AbstractRulesModule;
035import org.junit.Test;
036import org.xml.sax.SAXException;
037
038/**
039 * <p>
040 * Test case for <code>BeanPropertySetterRule</code>. This contains tests for the main applications of the rule and two
041 * more general tests of digester functionality used by this rule.
042 */
043public class BeanPropertySetterRuleTestCase
044{
045
046    // ----------------------------------------------------- Instance Variables
047
048    /**
049     * Simple test xml document used in the tests.
050     */
051    protected final static String TEST_XML = "<?xml version='1.0'?>" + "<root>ROOT BODY" + "<alpha>ALPHA BODY</alpha>"
052        + "<beta>BETA BODY</beta>" + "<gamma>GAMMA BODY</gamma>" + "<delta>DELTA BODY</delta>" + "</root>";
053
054    // ------------------------------------------------ Individual Test Methods
055
056    /**
057     * This is a general digester test but it fits into here pretty well. This tests that the rule calling order is
058     * properly enforced.
059     */
060    @Test
061    public void testDigesterRuleCallOrder()
062        throws SAXException, IOException
063    {
064
065        final List<Rule> callOrder = new ArrayList<Rule>();
066
067        Digester digester = newLoader( new AbstractRulesModule()
068        {
069
070            @Override
071            protected void configure()
072            {
073                // add first test rule
074                forPattern( "root/alpha" ).addRuleCreatedBy( new TestRule.TestRuleProvider( "first", callOrder ) );
075                // add second test rule
076                forPattern( "root/alpha" ).addRuleCreatedBy( new TestRule.TestRuleProvider( "second", callOrder ) );
077                // add third test rule
078                forPattern( "root/alpha" ).addRuleCreatedBy( new TestRule.TestRuleProvider( "third", callOrder ) );
079            }
080
081        }).newDigester();
082
083        digester.parse( xmlTestReader() );
084
085        // we should have nine entries in our list of calls
086
087        assertEquals( "Nine calls should have been made.", 9, callOrder.size() );
088
089        // begin should be called in the order added
090        assertEquals( "First rule begin not called first.", "first", ( (TestRule) callOrder.get( 0 ) ).getIdentifier() );
091
092        assertEquals( "Second rule begin not called second.", "second",
093                      ( (TestRule) callOrder.get( 1 ) ).getIdentifier() );
094
095        assertEquals( "Third rule begin not called third.", "third", ( (TestRule) callOrder.get( 2 ) ).getIdentifier() );
096
097        // body text should be called in the order added
098        assertEquals( "First rule body text not called first.", "first",
099                      ( (TestRule) callOrder.get( 3 ) ).getIdentifier() );
100
101        assertEquals( "Second rule body text not called second.", "second",
102                      ( (TestRule) callOrder.get( 4 ) ).getIdentifier() );
103
104        assertEquals( "Third rule body text not called third.", "third",
105                      ( (TestRule) callOrder.get( 5 ) ).getIdentifier() );
106
107        // end should be called in reverse order
108        assertEquals( "Third rule end not called first.", "third", ( (TestRule) callOrder.get( 6 ) ).getIdentifier() );
109
110        assertEquals( "Second rule end not called second.", "second", ( (TestRule) callOrder.get( 7 ) ).getIdentifier() );
111
112        assertEquals( "First rule end not called third.", "first", ( (TestRule) callOrder.get( 8 ) ).getIdentifier() );
113
114    }
115
116    /**
117     * This is a general digester test but it fits into here pretty well. This tests that the body text stack is
118     * functioning correctly.
119     */
120    @Test
121    public void testDigesterBodyTextStack()
122        throws SAXException, IOException
123    {
124        final List<Rule> callOrder = new ArrayList<Rule>();
125
126        Digester digester = newLoader(new AbstractRulesModule()
127        {
128
129            @Override
130            protected void configure()
131            {
132                forPattern( "root" ).addRuleCreatedBy( new TestRule.TestRuleProvider( "root", callOrder ) );
133                forPattern( "root/alpha" ).addRuleCreatedBy( new TestRule.TestRuleProvider( "root/alpha", callOrder ) );
134                forPattern( "root/beta" ).addRuleCreatedBy( new TestRule.TestRuleProvider( "root/beta", callOrder ) );
135                forPattern( "root/gamma" ).addRuleCreatedBy( new TestRule.TestRuleProvider( "root/gamma", callOrder ) );
136            }
137
138        }).newDigester();
139
140        digester.parse( xmlTestReader() );
141
142        assertEquals( "Root body text not set correct.", "ROOT BODY", ( (TestRule) callOrder.get( 0 ) ).getBodyText() );
143
144        assertEquals( "Alpha body text not set correct.", "ALPHA BODY", ( (TestRule) callOrder.get( 1 ) ).getBodyText() );
145
146        assertEquals( "Beta body text not set correct.", "BETA BODY", ( (TestRule) callOrder.get( 4 ) ).getBodyText() );
147
148        assertEquals( "Gamma body text not set correct.", "GAMMA BODY", ( (TestRule) callOrder.get( 7 ) ).getBodyText() );
149
150    }
151
152    /**
153     * Test that you can successfully set a given property
154     */
155    @Test
156    public void testSetGivenProperty()
157        throws SAXException, IOException
158    {
159        Digester digester = newLoader(new AbstractRulesModule()
160        {
161
162            @Override
163            protected void configure()
164            {
165                forPattern( "root" ).createObject().ofType( SimpleTestBean.class );
166                forPattern( "root" ).setBeanProperty().withName( "alpha" );
167
168                // we'll set property beta with the body text of child element alpha
169                forPattern( "root/alpha" ).setBeanProperty().withName( "beta" );
170                // we'll leave property gamma alone
171
172                // we'll set property delta (a write-only property) also
173                forPattern( "root/delta" ).setBeanProperty().withName( "delta" );
174            }
175
176        }).newDigester();
177
178        SimpleTestBean bean = digester.parse( xmlTestReader() );
179
180        // check properties are set correctly
181        assertEquals( "Property alpha not set correctly", "ROOT BODY", bean.getAlpha() );
182
183        assertEquals( "Property beta not set correctly", "ALPHA BODY", bean.getBeta() );
184
185        assertTrue( "Property gamma not set correctly", bean.getGamma() == null );
186
187        assertEquals( "Property delta not set correctly", "DELTA BODY", bean.getDeltaValue() );
188
189    }
190
191    /**
192     * Test that trying to set an unknown property throws an exception.
193     */
194    @Test
195    public void testSetUnknownProperty()
196    {
197        Digester digester = newLoader(new AbstractRulesModule()
198        {
199
200            @Override
201            protected void configure()
202            {
203                forPattern( "root" ).createObject().ofType( "org.apache.commons.digester3.SimpleTestBean" );
204                forPattern( "root" ).setBeanProperty().withName( "alpha" );
205
206                // attempt to set an unknown property name
207                forPattern( "root/alpha" ).setBeanProperty().withName( "unknown" );
208            }
209
210        }).newDigester();
211
212        // Attempt to parse the input
213        try
214        {
215            SimpleTestBean bean = digester.parse( xmlTestReader() );
216            fail( "Should have thrown NoSuchMethodException" );
217            assertNotNull( bean ); // just to avoid compiler warning on unused variable
218        }
219        catch ( Exception e )
220        {
221            if ( e instanceof InvocationTargetException )
222            {
223                Throwable t = ( (InvocationTargetException) e ).getTargetException();
224                if ( t instanceof NoSuchMethodException )
225                {
226                    // Expected result
227                }
228                else
229                {
230                    fail( "Should have thrown NoSuchMethodException, threw " + t );
231                }
232            }
233        }
234
235    }
236
237    /**
238     * Test that you can successfully automatically set properties.
239     */
240    @Test
241    public void testAutomaticallySetProperties()
242        throws SAXException, IOException
243    {
244        Digester digester = newLoader(new AbstractRulesModule()
245        {
246
247            @Override
248            protected void configure()
249            {
250                forPattern( "root" ).createObject().ofType( "org.apache.commons.digester3.SimpleTestBean" );
251                forPattern( "root/?" ).setBeanProperty();
252            }
253
254        }).newDigester( new ExtendedBaseRules() );
255
256        SimpleTestBean bean = digester.parse( xmlTestReader() );
257
258        // check properties are set correctly
259        assertEquals( "Property alpha not set correctly", "ALPHA BODY", bean.getAlpha() );
260
261        assertEquals( "Property beta not set correctly", "BETA BODY", bean.getBeta() );
262
263        assertEquals( "Property gamma not set correctly", "GAMMA BODY", bean.getGamma() );
264
265    }
266
267    @Test
268    public void extractPropertyNameFromAttribute() throws Exception
269    {
270        Employee expected = new Employee( "John", "Doe" );
271
272        Employee actual = newLoader( new AbstractRulesModule()
273        {
274
275            @Override
276            protected void configure()
277            {
278                forPattern( "employee" ).createObject().ofType( Employee.class );
279                forPattern( "employee/property" ).setBeanProperty().extractPropertyNameFromAttribute( "name" );
280            }
281
282        } )
283        .newDigester()
284        .parse( getClass().getResource( "extractPropertyNameFromAttribute.xml" ) );
285
286        assertEquals( expected.getFirstName(), actual.getFirstName() );
287        assertEquals( expected.getLastName(), actual.getLastName() );
288    }
289
290    /**
291     * Get input stream from {@link #TEST_XML}.
292     */
293    private Reader xmlTestReader()
294    {
295        return new StringReader( TEST_XML );
296    }
297
298}