blob: 66f9c813d3802edcef9bf6b7f2117fb01cfa0e6c [file] [log] [blame]
/* $Id$
*
* 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$ $Date$
*/
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());
}
}