| /* $Id: RuleTestCase.java,v 1.28 2004/05/07 01:29:59 skitching Exp $ |
| * |
| * Copyright 2001-2004 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| |
| package org.apache.commons.digester; |
| |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.ArrayList; |
| |
| import junit.framework.Test; |
| import junit.framework.TestCase; |
| import junit.framework.TestSuite; |
| |
| import org.xml.sax.SAXException; |
| |
| /** |
| * <p>Test Case for the Digester class. These tests perform parsing of |
| * XML documents to exercise the built-in rules.</p> |
| * |
| * @author Craig R. McClanahan |
| * @author Janek Bogucki |
| * @version $Revision: 1.28 $ $Date: 2004/05/07 01:29:59 $ |
| */ |
| |
| public class RuleTestCase extends TestCase { |
| |
| |
| // ----------------------------------------------------- Instance Variables |
| |
| |
| /** |
| * The digester instance we will be processing. |
| */ |
| protected Digester digester = null; |
| |
| |
| // ----------------------------------------------------------- Constructors |
| |
| |
| /** |
| * Construct a new instance of this test case. |
| * |
| * @param name Name of the test case |
| */ |
| public RuleTestCase(String name) { |
| |
| super(name); |
| |
| } |
| |
| |
| // --------------------------------------------------- Overall Test Methods |
| |
| |
| /** |
| * Set up instance variables required by this test case. |
| */ |
| public void setUp() { |
| |
| digester = new Digester(); |
| |
| } |
| |
| |
| /** |
| * Return the tests included in this test suite. |
| */ |
| public static Test suite() { |
| |
| return (new TestSuite(RuleTestCase.class)); |
| |
| } |
| |
| |
| /** |
| * Tear down instance variables required by this test case. |
| */ |
| public void tearDown() { |
| |
| digester = null; |
| |
| } |
| |
| |
| |
| // ------------------------------------------------ Individual Test Methods |
| |
| |
| /** |
| * Test object creation (and associated property setting) with nothing on |
| * the stack, which should cause an appropriate Employee object to be |
| * returned. |
| */ |
| public void testObjectCreate1() throws SAXException, IOException { |
| |
| // Configure the digester as required |
| digester.addObjectCreate("employee", |
| "org.apache.commons.digester.Employee"); |
| digester.addSetProperties("employee"); |
| |
| // Parse our test input. |
| Object root = null; |
| root = digester.parse(getInputStream("Test1.xml")); |
| |
| assertNotNull("Digester returned an object", root); |
| assertTrue("Digester returned an Employee", |
| root instanceof Employee); |
| Employee employee = (Employee) root; |
| assertEquals("First name is correct", |
| "First Name", |
| employee.getFirstName()); |
| assertEquals("Last name is correct", |
| "Last Name", |
| employee.getLastName()); |
| |
| |
| } |
| |
| |
| /** |
| * Test object creation (and associated property setting) with nothing on |
| * the stack, which should cause an appropriate Employee object to be |
| * returned. The processing rules will process the nested Address elements |
| * as well, but will not attempt to add them to the Employee. |
| */ |
| public void testObjectCreate2() throws SAXException, IOException { |
| |
| // Configure the digester as required |
| digester.addObjectCreate("employee", Employee.class); |
| digester.addSetProperties("employee"); |
| digester.addObjectCreate("employee/address", |
| "org.apache.commons.digester.Address"); |
| digester.addSetProperties("employee/address"); |
| |
| // Parse our test input. |
| Object root = null; |
| root = digester.parse(getInputStream("Test1.xml")); |
| |
| assertNotNull("Digester returned an object", root); |
| assertTrue("Digester returned an Employee", |
| root instanceof Employee); |
| Employee employee = (Employee) root; |
| assertEquals("First name is correct", |
| "First Name", |
| employee.getFirstName()); |
| assertEquals("Last name is correct", |
| "Last Name", |
| employee.getLastName()); |
| |
| |
| } |
| |
| |
| /** |
| * Test object creation (and associated property setting) with nothing on |
| * the stack, which should cause an appropriate Employee object to be |
| * returned. The processing rules will process the nested Address elements |
| * as well, and will add them to the owning Employee. |
| */ |
| public void testObjectCreate3() throws SAXException, IOException { |
| |
| // Configure the digester as required |
| digester.addObjectCreate("employee", Employee.class); |
| digester.addSetProperties("employee"); |
| digester.addObjectCreate("employee/address", |
| "org.apache.commons.digester.Address"); |
| digester.addSetProperties("employee/address"); |
| digester.addSetNext("employee/address", |
| "addAddress"); |
| |
| // Parse our test input once |
| Object root = null; |
| root = digester.parse(getInputStream("Test1.xml")); |
| |
| validateObjectCreate3(root); |
| |
| // Parse the same input again |
| try { |
| root = digester.parse(getInputStream("Test1.xml")); |
| } catch (Throwable t) { |
| fail("Digester threw IOException: " + t); |
| } |
| validateObjectCreate3(root); |
| |
| } |
| |
| |
| /** |
| * Same as testObjectCreate1(), except use individual call method rules |
| * to set the properties of the Employee. |
| */ |
| public void testObjectCreate4() throws SAXException, IOException { |
| |
| // Configure the digester as required |
| digester.addObjectCreate("employee", Employee.class); |
| digester.addCallMethod("employee", |
| "setFirstName", 1); |
| digester.addCallParam("employee", 0, "firstName"); |
| digester.addCallMethod("employee", |
| "setLastName", 1); |
| digester.addCallParam("employee", 0, "lastName"); |
| |
| |
| // Parse our test input. |
| Object root = null; |
| root = digester.parse(getInputStream("Test1.xml")); |
| |
| assertNotNull("Digester returned an object", root); |
| assertTrue("Digester returned an Employee", |
| root instanceof Employee); |
| Employee employee = (Employee) root; |
| assertEquals("First name is correct", |
| "First Name", |
| employee.getFirstName()); |
| assertEquals("Last name is correct", |
| "Last Name", |
| employee.getLastName()); |
| |
| } |
| |
| |
| /** |
| * Same as testObjectCreate1(), except use individual call method rules |
| * to set the properties of the Employee. Bean data are defined using |
| * elements instead of attributes. The purpose is to test CallMethod with |
| * a paramCount=0 (ie the body of the element is the argument of the |
| * method). |
| */ |
| public void testObjectCreate5() throws SAXException, IOException { |
| |
| // Configure the digester as required |
| digester.addObjectCreate("employee", Employee.class); |
| digester.addCallMethod("employee/firstName", "setFirstName", 0); |
| digester.addCallMethod("employee/lastName", "setLastName", 0); |
| |
| |
| // Parse our test input. |
| Object root = null; |
| root = digester.parse(getInputStream("Test5.xml")); |
| |
| assertNotNull("Digester returned an object", root); |
| assertTrue("Digester returned an Employee", |
| root instanceof Employee); |
| Employee employee = (Employee) root; |
| assertEquals("First name is correct", |
| "First Name", |
| employee.getFirstName()); |
| assertEquals("Last name is correct", |
| "Last Name", |
| employee.getLastName()); |
| |
| } |
| |
| |
| /** |
| * It should be possible to parse the same input twice, and get trees |
| * of objects that are isomorphic but not be identical object instances. |
| */ |
| public void testRepeatedParse() throws SAXException, IOException { |
| |
| // Configure the digester as required |
| digester.addObjectCreate("employee", Employee.class); |
| digester.addSetProperties("employee"); |
| digester.addObjectCreate("employee/address", |
| "org.apache.commons.digester.Address"); |
| digester.addSetProperties("employee/address"); |
| digester.addSetNext("employee/address", |
| "addAddress"); |
| |
| // Parse our test input the first time |
| Object root1 = null; |
| root1 = digester.parse(getInputStream("Test1.xml")); |
| |
| validateObjectCreate3(root1); |
| |
| // Parse our test input the second time |
| Object root2 = null; |
| root2 = digester.parse(getInputStream("Test1.xml")); |
| |
| validateObjectCreate3(root2); |
| |
| // Make sure that it was a different root |
| assertTrue("Different tree instances were returned", |
| root1 != root2); |
| |
| } |
| |
| |
| /** |
| * Test object creation (and associated property setting) with nothing on |
| * the stack, which should cause an appropriate Employee object to be |
| * returned. The processing rules will process the nested Address elements |
| * as well, but will not attempt to add them to the Employee. |
| */ |
| public void testRuleSet1() throws SAXException, IOException { |
| |
| // Configure the digester as required |
| RuleSet rs = new TestRuleSet(); |
| digester.addRuleSet(rs); |
| |
| // Parse our test input. |
| Object root = null; |
| root = digester.parse(getInputStream("Test1.xml")); |
| |
| assertNotNull("Digester returned an object", root); |
| assertTrue("Digester returned an Employee", |
| root instanceof Employee); |
| Employee employee = (Employee) root; |
| assertEquals("First name is correct", |
| "First Name", |
| employee.getFirstName()); |
| assertEquals("Last name is correct", |
| "Last Name", |
| employee.getLastName()); |
| assertNotNull("Can retrieve home address", |
| employee.getAddress("home")); |
| assertNotNull("Can retrieve office address", |
| employee.getAddress("office")); |
| |
| } |
| |
| |
| /** |
| * Same as <code>testRuleSet1</code> except using a single namespace. |
| */ |
| public void testRuleSet2() throws SAXException, IOException { |
| |
| // Configure the digester as required |
| digester.setNamespaceAware(true); |
| RuleSet rs = new TestRuleSet(null, |
| "http://jakarta.apache.org/digester/Foo"); |
| digester.addRuleSet(rs); |
| |
| // Parse our test input. |
| Object root = null; |
| root = digester.parse(getInputStream("Test2.xml")); |
| |
| assertNotNull("Digester returned an object", root); |
| assertTrue("Digester returned an Employee", |
| root instanceof Employee); |
| Employee employee = (Employee) root; |
| assertEquals("First name is correct", |
| "First Name", |
| employee.getFirstName()); |
| assertEquals("Last name is correct", |
| "Last Name", |
| employee.getLastName()); |
| assertNotNull("Can retrieve home address", |
| employee.getAddress("home")); |
| assertNotNull("Can retrieve office address", |
| employee.getAddress("office")); |
| |
| } |
| |
| |
| /** |
| * Same as <code>testRuleSet2</code> except using a namespace |
| * for employee that we should recognize, and a namespace for |
| * address that we should skip. |
| */ |
| public void testRuleSet3() throws SAXException, IOException { |
| |
| // Configure the digester as required |
| digester.setNamespaceAware(true); |
| RuleSet rs = new TestRuleSet(null, |
| "http://jakarta.apache.org/digester/Foo"); |
| digester.addRuleSet(rs); |
| |
| // Parse our test input. |
| Object root = null; |
| root = digester.parse(getInputStream("Test3.xml")); |
| |
| assertNotNull("Digester returned an object", root); |
| assertTrue("Digester returned an Employee", |
| root instanceof Employee); |
| Employee employee = (Employee) root; |
| assertEquals("First name is correct", |
| "First Name", |
| employee.getFirstName()); |
| assertEquals("Last name is correct", |
| "Last Name", |
| employee.getLastName()); |
| assertNull("Can not retrieve home address", |
| employee.getAddress("home")); |
| assertNull("Can not retrieve office address", |
| employee.getAddress("office")); |
| |
| } |
| |
| |
| /** |
| * Test the two argument version of the SetTopRule rule. This test is |
| * based on testObjectCreate3 and should result in the same tree of |
| * objects. Instead of using the SetNextRule rule which results in |
| * a method invocation on the (top-1) (parent) object with the top |
| * object (child) as an argument, this test uses the SetTopRule rule |
| * which results in a method invocation on the top object (child) |
| * with the top-1 (parent) object as an argument. The three argument |
| * form is tested in <code>testSetTopRule2</code>. |
| */ |
| public void testSetTopRule1() throws SAXException, IOException { |
| |
| // Configure the digester as required |
| digester.addObjectCreate("employee", |
| "org.apache.commons.digester.Employee"); |
| digester.addSetProperties("employee"); |
| digester.addObjectCreate("employee/address", |
| "org.apache.commons.digester.Address"); |
| digester.addSetProperties("employee/address"); |
| digester.addSetTop("employee/address", "setEmployee"); |
| |
| // Parse our test input. |
| Object root = null; |
| root = digester.parse(getInputStream("Test1.xml")); |
| validateObjectCreate3(root); |
| |
| } |
| |
| |
| /** |
| * Same as <code>testSetTopRule1</code> except using the three argument |
| * form of the SetTopRule rule. |
| */ |
| public void testSetTopRule2() throws SAXException, IOException { |
| |
| // Configure the digester as required |
| digester.addObjectCreate("employee", |
| "org.apache.commons.digester.Employee"); |
| digester.addSetProperties("employee"); |
| digester.addObjectCreate("employee/address", |
| "org.apache.commons.digester.Address"); |
| digester.addSetProperties("employee/address"); |
| digester.addSetTop("employee/address", "setEmployee", |
| "org.apache.commons.digester.Employee"); |
| |
| // Parse our test input. |
| Object root = null; |
| root = digester.parse(getInputStream("Test1.xml")); |
| |
| validateObjectCreate3(root); |
| |
| } |
| |
| /** |
| * Test rule addition - this boils down to making sure that |
| * digester is set properly on rule addition. |
| */ |
| public void testAddRule() { |
| Digester digester = new Digester(); |
| TestRule rule = new TestRule("Test"); |
| digester.addRule("/root", rule); |
| |
| assertEquals("Digester is not properly on rule addition.", |
| digester, rule.getDigester()); |
| |
| } |
| |
| |
| public void testSetNext() throws SAXException, IOException { |
| Digester digester = new Digester(); |
| digester.setRules(new ExtendedBaseRules()); |
| digester.setValidating(false); |
| |
| |
| digester.addObjectCreate("!*/b", BetaBean.class); |
| digester.addObjectCreate("!*/a", AlphaBean.class); |
| digester.addObjectCreate("root", ArrayList.class); |
| digester.addSetProperties("!*"); |
| digester.addSetNext("!*/b/?", "setChild"); |
| digester.addSetNext("!*/a/?", "setChild"); |
| digester.addSetNext("!root/?", "add"); |
| ArrayList root = |
| (ArrayList) digester.parse(getInputStream("Test4.xml")); |
| |
| assertEquals("Wrong array size", 2, root.size()); |
| AlphaBean one = (AlphaBean) root.get(0); |
| assertTrue(one.getChild() instanceof BetaBean); |
| BetaBean two = (BetaBean) one.getChild(); |
| assertEquals("Wrong name (1)", two.getName() , "TWO"); |
| assertTrue(two.getChild() instanceof AlphaBean); |
| AlphaBean three = (AlphaBean) two.getChild(); |
| assertEquals("Wrong name (2)", three.getName() , "THREE"); |
| BetaBean four = (BetaBean) root.get(1); |
| assertEquals("Wrong name (3)", four.getName() , "FOUR"); |
| assertTrue(four.getChild() instanceof BetaBean); |
| BetaBean five = (BetaBean) four.getChild(); |
| assertEquals("Wrong name (4)", five.getName() , "FIVE"); |
| |
| } |
| |
| |
| public void testSetTop() throws SAXException, IOException { |
| Digester digester = new Digester(); |
| digester.setRules(new ExtendedBaseRules()); |
| digester.setValidating(false); |
| |
| |
| digester.addObjectCreate("!*/b", BetaBean.class); |
| digester.addObjectCreate("!*/a", AlphaBean.class); |
| digester.addObjectCreate("root", ArrayList.class); |
| digester.addSetProperties("!*"); |
| digester.addSetTop("!*/b/?", "setParent"); |
| digester.addSetTop("!*/a/?", "setParent"); |
| digester.addSetRoot("!*/a", "add"); |
| digester.addSetRoot("!*/b", "add"); |
| ArrayList root = |
| (ArrayList) digester.parse(getInputStream("Test4.xml")); |
| |
| assertEquals("Wrong array size", 5, root.size()); |
| |
| // note that the array is in popped order (rather than pushed) |
| |
| Object obj = root.get(1); |
| assertTrue("TWO should be a BetaBean", obj instanceof BetaBean); |
| BetaBean two = (BetaBean) obj; |
| assertNotNull("Two's parent should not be null", two.getParent()); |
| assertEquals("Wrong name (1)", "TWO", two.getName()); |
| assertEquals("Wrong name (2)", "ONE", two.getParent().getName() ); |
| |
| obj = root.get(0); |
| assertTrue("THREE should be an AlphaBean", obj instanceof AlphaBean); |
| AlphaBean three = (AlphaBean) obj; |
| assertNotNull("Three's parent should not be null", three.getParent()); |
| assertEquals("Wrong name (3)", "THREE", three.getName()); |
| assertEquals("Wrong name (4)", "TWO", three.getParent().getName()); |
| |
| obj = root.get(3); |
| assertTrue("FIVE should be a BetaBean", obj instanceof BetaBean); |
| BetaBean five = (BetaBean) obj; |
| assertNotNull("Five's parent should not be null", five.getParent()); |
| assertEquals("Wrong name (5)", "FIVE", five.getName()); |
| assertEquals("Wrong name (6)", "FOUR", five.getParent().getName()); |
| |
| } |
| |
| |
| /** |
| */ |
| public void testSetCustomProperties() throws SAXException, IOException { |
| |
| Digester digester = new Digester(); |
| |
| digester.setValidating(false); |
| |
| digester.addObjectCreate("toplevel", ArrayList.class); |
| digester.addObjectCreate("toplevel/one", Address.class); |
| digester.addSetNext("toplevel/one", "add"); |
| digester.addObjectCreate("toplevel/two", Address.class); |
| digester.addSetNext("toplevel/two", "add"); |
| digester.addObjectCreate("toplevel/three", Address.class); |
| digester.addSetNext("toplevel/three", "add"); |
| digester.addObjectCreate("toplevel/four", Address.class); |
| digester.addSetNext("toplevel/four", "add"); |
| digester.addSetProperties("toplevel/one"); |
| digester.addSetProperties( |
| "toplevel/two", |
| new String[] {"alt-street", "alt-city", "alt-state"}, |
| new String[] {"street", "city", "state"}); |
| digester.addSetProperties( |
| "toplevel/three", |
| new String[] {"aCity", "state"}, |
| new String[] {"city"}); |
| digester.addSetProperties("toplevel/four", "alt-city", "city"); |
| |
| |
| ArrayList root = |
| (ArrayList) digester.parse(getInputStream("Test7.xml")); |
| |
| assertEquals("Wrong array size", 4, root.size()); |
| |
| // note that the array is in popped order (rather than pushed) |
| |
| Object |
| obj = root.get(0); |
| assertTrue("(1) Should be an Address ", obj instanceof Address); |
| Address addressOne = (Address) obj; |
| assertEquals("(1) Street attribute", "New Street", |
| addressOne.getStreet()); |
| assertEquals("(1) City attribute", "Las Vegas", addressOne.getCity()); |
| assertEquals("(1) State attribute", "Nevada", addressOne.getState()); |
| |
| obj = root.get(1); |
| assertTrue("(2) Should be an Address ", obj instanceof Address); |
| Address addressTwo = (Address) obj; |
| assertEquals("(2) Street attribute", "Old Street", |
| addressTwo.getStreet()); |
| assertEquals("(2) City attribute", "Portland", addressTwo.getCity()); |
| assertEquals("(2) State attribute", "Oregon", addressTwo.getState()); |
| |
| obj = root.get(2); |
| assertTrue("(3) Should be an Address ", obj instanceof Address); |
| Address addressThree = (Address) obj; |
| assertEquals("(3) Street attribute", "4th Street", |
| addressThree.getStreet()); |
| assertEquals("(3) City attribute", "Dayton", addressThree.getCity()); |
| assertEquals("(3) State attribute", "US" , addressThree.getState()); |
| |
| obj = root.get(3); |
| assertTrue("(4) Should be an Address ", obj instanceof Address); |
| Address addressFour = (Address) obj; |
| assertEquals("(4) Street attribute", "6th Street", |
| addressFour.getStreet()); |
| assertEquals("(4) City attribute", "Cleveland", addressFour.getCity()); |
| assertEquals("(4) State attribute", "Ohio", addressFour.getState()); |
| |
| } |
| |
| // ------------------------------------------------ Utility Support Methods |
| |
| |
| /** |
| * Return an appropriate InputStream for the specified test file (which |
| * must be inside our current package. |
| * |
| * @param name Name of the test file we want |
| * |
| * @exception IOException if an input/output error occurs |
| */ |
| protected InputStream getInputStream(String name) throws IOException { |
| |
| return (this.getClass().getResourceAsStream |
| ("/org/apache/commons/digester/" + name)); |
| |
| } |
| |
| |
| /** |
| * Validate the assertions for ObjectCreateRule3. |
| * |
| * @param object Root object returned by <code>digester.parse()</code> |
| */ |
| protected void validateObjectCreate3(Object root) { |
| |
| // Validate the retrieved Employee |
| assertNotNull("Digester returned an object", root); |
| assertTrue("Digester returned an Employee", |
| root instanceof Employee); |
| Employee employee = (Employee) root; |
| assertEquals("First name is correct", |
| "First Name", |
| employee.getFirstName()); |
| assertEquals("Last name is correct", |
| "Last Name", |
| employee.getLastName()); |
| |
| // Validate the corresponding "home" Address |
| Address home = employee.getAddress("home"); |
| assertNotNull("Retrieved home address", home); |
| assertEquals("Home street", "Home Street", |
| home.getStreet()); |
| assertEquals("Home city", "Home City", |
| home.getCity()); |
| assertEquals("Home state", "HS", |
| home.getState()); |
| assertEquals("Home zip", "HmZip", |
| home.getZipCode()); |
| |
| // Validate the corresponding "office" Address |
| Address office = employee.getAddress("office"); |
| assertNotNull("Retrieved office address", office); |
| assertEquals("Office street", "Office Street", |
| office.getStreet()); |
| assertEquals("Office city", "Office City", |
| office.getCity()); |
| assertEquals("Office state", "OS", |
| office.getState()); |
| assertEquals("Office zip", "OfZip", |
| office.getZipCode()); |
| |
| } |
| |
| |
| } |