You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by si...@apache.org on 2011/02/11 17:58:50 UTC
svn commit: r1069886 -
/commons/sandbox/digester3/trunk/src/test/java/org/apache/commons/digester3/CallMethodRuleTestCase.java
Author: simonetripodi
Date: Fri Feb 11 16:58:49 2011
New Revision: 1069886
URL: http://svn.apache.org/viewvc?rev=1069886&view=rev
Log:
first checkin of CallMethodRuleTestCase, a tidy version of the proper one on /trunk
old tests continue to pass!
Added:
commons/sandbox/digester3/trunk/src/test/java/org/apache/commons/digester3/CallMethodRuleTestCase.java (with props)
Added: commons/sandbox/digester3/trunk/src/test/java/org/apache/commons/digester3/CallMethodRuleTestCase.java
URL: http://svn.apache.org/viewvc/commons/sandbox/digester3/trunk/src/test/java/org/apache/commons/digester3/CallMethodRuleTestCase.java?rev=1069886&view=auto
==============================================================================
--- commons/sandbox/digester3/trunk/src/test/java/org/apache/commons/digester3/CallMethodRuleTestCase.java (added)
+++ commons/sandbox/digester3/trunk/src/test/java/org/apache/commons/digester3/CallMethodRuleTestCase.java Fri Feb 11 16:58:49 2011
@@ -0,0 +1,706 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.digester3;
+
+import static org.apache.commons.digester3.DigesterLoader.newLoader;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Set;
+
+import org.apache.commons.digester3.rule.CallMethodRule;
+import org.apache.commons.digester3.rules.ExtendedBaseRules;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+/**
+ * <p>Tests for the <code>CallMethodRule</code> and associated
+ * <code>CallParamRule</code>.
+ *
+ * @author Christopher Lenz
+ */
+public class CallMethodRuleTestCase extends AbstractTestCase {
+
+ /**
+ * Test method calls with the CallMethodRule rule. It should be possible
+ * to call a method with no arguments using several rule syntaxes.
+ */
+ @Test
+ public void testBasic() throws SAXException, IOException {
+ Object root1 = newBasicDigester(new AbstractRulesModule() {
+
+ @Override
+ protected void configure() {
+ forPattern("employee")
+ .createObject().ofType(Employee.class)
+ .then()
+ .callMethod("toString")
+ .then()
+ .callMethod("toString");
+ }
+
+ }).parse(getInputStream("Test5.xml"));
+ assertNotNull(root1);
+ }
+
+
+ /**
+ * Test method calls with the CallMethodRule reading from the element
+ * body, with no CallParamMethod rules added.
+ */
+ @Test
+ public void testCallMethodOnly() throws Throwable {
+ Employee employee = (Employee) newBasicDigesterAndParse("Test9.xml", new AbstractRulesModule() {
+
+ @Override
+ protected void configure() {
+ forPattern("employee").createObject().ofType(Employee.class);
+ forPattern("employee/firstName").callMethod("setFirstName").usingElementBodyAsArgument();
+ forPattern("employee/lastName").callMethod("setLastName").usingElementBodyAsArgument();
+ }
+
+ });
+
+ assertNotNull("parsed an employee", employee);
+
+ // Validate that the property setters were called
+ assertEquals("Set first name", "First Name", employee.getFirstName());
+ assertEquals("Set last name", "Last Name", employee.getLastName());
+ }
+
+
+ /**
+ * Test CallMethodRule variants which specify the classes of the
+ * parameters to target methods. String, int, boolean, float should all
+ * be acceptable as parameter types.
+ */
+ @Test
+ public void testSetLastNameProperty() throws Throwable {
+ Employee employee = (Employee) newBasicDigesterAndParse("Test5.xml", new AbstractRulesModule() {
+
+ @Override
+ protected void configure() {
+ forPattern("employee")
+ .createObject().ofType(Employee.class)
+ .then()
+ .callMethod("setLastName").withParamTypes(String.class);
+ forPattern("employee/lastName").callParam();
+ }
+
+ });
+ assertEquals("Failed to call Employee.setLastName", "Last Name", employee.getLastName());
+ }
+
+ @Test
+ public void testSetAgeProperty() throws Throwable {
+ Employee employee = (Employee) newBasicDigesterAndParse("Test5.xml", new AbstractRulesModule() {
+
+ @Override
+ protected void configure() {
+ forPattern("employee")
+ .createObject().ofType(Employee.class)
+ .then()
+ .callMethod("setAge").withParamTypes(int.class);
+ forPattern("employee/age").callParam().ofIndex(0);
+ }
+
+ });
+ assertEquals("Failed to call Employee.setAge", 21, employee.getAge());
+ }
+
+ @Test
+ public void testSetActiveProperty() throws Throwable {
+ Employee employee = (Employee) newBasicDigesterAndParse("Test5.xml", new AbstractRulesModule() {
+
+ @Override
+ protected void configure() {
+ forPattern("employee")
+ .createObject().ofType(Employee.class)
+ .then()
+ .callMethod("setActive").withParamTypes(boolean.class);
+ forPattern("employee/active").callParam();
+ }
+
+ });
+ assertEquals("Failed to call Employee.setActive",
+ true, employee.isActive());
+ }
+
+ @Test
+ public void testSetSalaryProperty() throws Throwable {
+ Employee employee = (Employee) newBasicDigesterAndParse("Test5.xml", new AbstractRulesModule() {
+
+ @Override
+ protected void configure() {
+ forPattern("employee")
+ .createObject().ofType(Employee.class)
+ .then()
+ .callMethod("setSalary").withParamTypes(float.class);
+ forPattern("employee/salary").callParam();
+ }
+
+ });
+ assertEquals("Failed to call Employee.setSalary",
+ 1000000.0f, employee.getSalary(), 0.1f);
+ }
+
+
+ /**
+ * This tests the call methods params enhancement that provides
+ * for more complex stack-based calls.
+ */
+ @Test
+ public void testParamsFromStack() throws SAXException, IOException {
+ StringBuffer xml = new StringBuffer().
+ append("<?xml version='1.0'?>").
+ append("<map>").
+ append(" <key name='The key'/>").
+ append(" <value name='The value'/>").
+ append("</map>");
+
+ HashMap<AlphaBean, BetaBean> map = (HashMap<AlphaBean, BetaBean>) newBasicDigester(new AbstractRulesModule() {
+
+ @Override
+ protected void configure() {
+ forPattern("map")
+ .createObject().ofType(HashMap.class)
+ .then()
+ .callMethod("put").withParamTypes(AlphaBean.class, BetaBean.class);
+ forPattern("map/key")
+ .createObject().ofType(AlphaBean.class)
+ .then()
+ .setProperties()
+ .then()
+ .callParam().fromStack(true);
+ forPattern("map/value")
+ .createObject().ofType(BetaBean.class)
+ .then()
+ .setProperties()
+ .then()
+ .callParam().fromStack(true).ofIndex(1);
+ }
+
+ }).parse(new StringReader(xml.toString()));
+
+ assertNotNull(map);
+ assertEquals(1, map.size());
+ assertEquals("The key",
+ map.keySet().iterator().next().getName());
+ assertEquals("The value",
+ map.values().iterator().next().getName());
+ }
+
+
+ /**
+ * Test that the target object for a CallMethodRule is the object that was
+ * on top of the object stack when the CallMethodRule fired, even when other
+ * rules fire between the CallMethodRule and its associated CallParamRules.
+ * <p>
+ * The current implementation of CallMethodRule ensures this works by
+ * firing only at the end of the tag that CallMethodRule triggered on.
+ */
+ @Test
+ public void testOrderNestedPartA() throws Exception {
+ NamedBean root1 = null;
+ try {
+ // an exception will be thrown if the method can't be found
+ root1 = (NamedBean) newBasicDigesterAndParse("Test8.xml", new AbstractRulesModule() {
+
+ @Override
+ protected void configure() {
+ // Here, we use the "grandchild element name" as a parameter to
+ // the created element, to ensure that all the params aren't
+ // avaiable to the CallMethodRule until some other rules have fired,
+ // in particular an ObjectCreateRule. The CallMethodRule should still
+ // function correctly in this scenario.
+ forPattern("toplevel/element")
+ .createObject().ofType(NamedBean.class)
+ .then()
+ .callMethod("setName").withParamCount(1);
+ forPattern("toplevel/element/element/element").callParam().fromAttribute("name");
+ forPattern("toplevel/element/element").createObject().ofType(NamedBean.class);
+ }
+
+ });
+ } catch (Throwable t) {
+ // this means that the method can't be found and so the test fails
+ fail("Digester threw Exception: " + t);
+ }
+
+ // if the CallMethodRule were to incorrectly invoke the method call
+ // on the second-created NamedBean instance, then the root one would
+ // have a null name. If it works correctly, the target element will
+ // be the first-created (root) one, despite the fact that a second
+ // object instance was created between the firing of the
+ // CallMethodRule and its associated CallParamRule.
+ assertEquals("Wrong method call order", "C", root1.getName());
+ }
+
+ /**
+ * Test nested CallMethod rules.
+ * <p>
+ * The current implementation of CallMethodRule, in which the method is
+ * invoked in its end() method, causes behaviour which some users find
+ * non-intuitive. In this test it can be seen to "reverse" the order of
+ * data processed. However this is the way CallMethodRule has always
+ * behaved, and it is expected that apps out there rely on this call order
+ * so this test is present to ensure that no-one changes this behaviour.
+ */
+ @Test
+ public void testOrderNestedPartB() throws Exception {
+ // Configure the digester as required
+ StringBuffer word = new StringBuffer();
+
+ Digester digester = newBasicDigester(new AbstractRulesModule() {
+
+ @Override
+ protected void configure() {
+ forPattern("*/element")
+ .callMethod("append").withParamCount(1)
+ .then()
+ .callParam().fromAttribute("name");
+ }
+
+ });
+
+ digester.push(word);
+
+ // Parse our test input
+ Object root1 = null;
+ try {
+ // an exception will be thrown if the method can't be found
+ root1 = digester.parse(getInputStream("Test8.xml"));
+ assertNotNull(root1);
+ } catch (Throwable t) {
+ // this means that the method can't be found and so the test fails
+ fail("Digester threw Exception: " + t);
+ }
+
+ assertEquals("Wrong method call order", "CBA", word.toString());
+ }
+
+ @Test
+ public void testPrimitiveReading() throws Exception {
+ StringReader reader = new StringReader(
+ "<?xml version='1.0' ?><root><bean good='true'/><bean good='false'/><bean/>"
+ + "<beanie bad='Fee Fie Foe Fum' good='true'/><beanie bad='Fee Fie Foe Fum' good='false'/>"
+ + "<beanie bad='Fee Fie Foe Fum'/></root>");
+
+ Digester digester = newBasicDigester(new AbstractRulesModule() {
+
+ @Override
+ protected void configure() {
+ forPattern("root/bean")
+ .createObject().ofType(PrimitiveBean.class)
+ .then()
+ .callMethod("setBoolean").withParamTypes(Boolean.TYPE)
+ .then()
+ .callParam().fromAttribute("good")
+ .then()
+ .setNext("add");
+ forPattern("root/beanie")
+ .createObject().ofType(PrimitiveBean.class)
+ .then()
+ .callMethod("testSetBoolean").withParamTypes(String.class, Boolean.TYPE)
+ .then()
+ .callParam().ofIndex(0).fromAttribute("bad")
+ .then()
+ .callParam().ofIndex(1).fromAttribute("good")
+ .then()
+ .setNext("add");
+ }
+
+ });
+
+ ArrayList<PrimitiveBean> list = new ArrayList<PrimitiveBean>();
+ digester.push(list);
+ digester.parse(reader);
+
+ assertEquals("Wrong number of beans in list", 6, list.size());
+ PrimitiveBean bean = list.get(0);
+ assertTrue("Bean 0 property not called", bean.getSetBooleanCalled());
+ assertEquals("Bean 0 property incorrect", true, bean.getBoolean());
+ bean = list.get(1);
+ assertTrue("Bean 1 property not called", bean.getSetBooleanCalled());
+ assertEquals("Bean 1 property incorrect", false, bean.getBoolean());
+ bean = list.get(2);
+ // no attibute, no call is what's expected
+ assertTrue("Bean 2 property called", !bean.getSetBooleanCalled());
+ bean = list.get(3);
+ assertTrue("Bean 3 property not called", bean.getSetBooleanCalled());
+ assertEquals("Bean 3 property incorrect", true, bean.getBoolean());
+ bean = list.get(4);
+ assertTrue("Bean 4 property not called", bean.getSetBooleanCalled());
+ assertEquals("Bean 4 property incorrect", false, bean.getBoolean());
+ bean = list.get(5);
+ assertTrue("Bean 5 property not called", bean.getSetBooleanCalled());
+ assertEquals("Bean 5 property incorrect", false, bean.getBoolean());
+ }
+
+ @Test
+ public void testFromStack() throws Exception {
+ StringReader reader = new StringReader(
+ "<?xml version='1.0' ?><root><one/><two/><three/><four/><five/></root>");
+
+ Digester digester = newBasicDigester(new AbstractRulesModule() {
+
+ @Override
+ protected void configure() {
+ int stackIndex = 2;
+ for (String element : new String[]{ "one", "two", "three", "four" }) {
+ forPattern(String.format("root/%s", element))
+ .createObject().ofType(NamedBean.class)
+ .then()
+ .setNext("add")
+ .then()
+ .callMethod("setName").withParamTypes(String.class)
+ .then()
+ .callParam().withStackIndex(stackIndex++);
+ }
+
+ forPattern("root/five")
+ .createObject().ofType(NamedBean.class)
+ .then()
+ .setNext("add")
+ .then()
+ .callMethod("test").withParamTypes(String.class, String.class)
+ .then()
+ .callParam().ofIndex(0).withStackIndex(10)
+ .then()
+ .callParam().ofIndex(1).withStackIndex(3);
+ }
+
+ });
+
+ // prepare stack
+ digester.push("That lamb was sure to go.");
+ digester.push("And everywhere that Mary went,");
+ digester.push("It's fleece was white as snow.");
+ digester.push("Mary had a little lamb,");
+
+ ArrayList<NamedBean> list = new ArrayList<NamedBean>();
+ digester.push(list);
+ digester.parse(reader);
+
+ assertEquals("Wrong number of beans in list", 5, list.size());
+ NamedBean bean = list.get(0);
+ assertEquals("Parameter not set from stack (1)", "Mary had a little lamb,", bean.getName());
+ bean = list.get(1);
+ assertEquals("Parameter not set from stack (2)", "It's fleece was white as snow.", bean.getName());
+ bean = list.get(2);
+ assertEquals("Parameter not set from stack (3)", "And everywhere that Mary went,", bean.getName());
+ bean = list.get(3);
+ assertEquals("Parameter not set from stack (4)", "That lamb was sure to go.", bean.getName());
+ bean = list.get(4);
+ assertEquals("Out of stack not set to null", null , bean.getName());
+ }
+
+ @Test
+ public void testTwoCalls() throws Exception {
+ StringReader reader = new StringReader(
+ "<?xml version='1.0' ?><root>"
+ + "<param class='int' coolness='true'>25</param>"
+ + "<param class='long'>50</param>"
+ + "<param class='float' coolness='false'>90</param></root>");
+
+ Digester digester = newBasicDigester(new AbstractRulesModule() {
+
+ @Override
+ protected void configure() {
+ forPattern("root/param")
+ .createObject().ofType(ParamBean.class).then()
+ .setNext("add").then()
+ .callMethod("setThisAndThat").withParamCount(2).then()
+ .callParam().ofIndex(0).fromAttribute("class").then()
+ .callParam().ofIndex(1).then()
+ .callMethod("setCool").withParamTypes(boolean.class).then()
+ .callParam().ofIndex(0).fromAttribute("coolness");
+ }
+
+ });
+
+ ArrayList<ParamBean> list = new ArrayList<ParamBean>();
+ digester.push(list);
+ digester.parse(reader);
+
+ assertEquals("Wrong number of objects created", 3, list.size());
+ ParamBean bean = list.get(0);
+ assertEquals("Coolness wrong (1)", true, bean.isCool());
+ assertEquals("This wrong (1)", "int", bean.getThis());
+ assertEquals("That wrong (1)", "25", bean.getThat());
+ bean = list.get(1);
+ assertEquals("Coolness wrong (2)", false, bean.isCool());
+ assertEquals("This wrong (2)", "long", bean.getThis());
+ assertEquals("That wrong (2)", "50", bean.getThat());
+ bean = list.get(2);
+ assertEquals("Coolness wrong (3)", false, bean.isCool());
+ assertEquals("This wrong (3)", "float", bean.getThis());
+ assertEquals("That wrong (3)", "90", bean.getThat());
+ }
+
+ @Test
+ public void testNestedBody() throws Exception {
+ StringReader reader = new StringReader(
+ "<?xml version='1.0' ?><root>"
+ + "<spam>Simple</spam>"
+ + "<spam>Complex<spam>Deep<spam>Deeper<spam>Deepest</spam></spam></spam></spam>"
+ + "</root>");
+
+ Digester digester = newBasicDigester(new AbstractRulesModule() {
+
+ @Override
+ protected void configure() {
+ forPattern("root/spam")
+ .createObject().ofType(NamedBean.class)
+ .then()
+ .callMethod("setName").withParamCount(1)
+ .then()
+ .callParam()
+ .then()
+ .setRoot("add");
+
+ forPattern("root/spam/spam")
+ .createObject().ofType(NamedBean.class)
+ .then()
+ .callMethod("setName").withParamCount(1)
+ .then()
+ .callParam()
+ .then()
+ .setRoot("add");
+
+ forPattern("root/spam/spam/spam")
+ .createObject().ofType(NamedBean.class)
+ .then()
+ .callMethod("setName").withParamCount(1)
+ .then()
+ .callParam()
+ .then()
+ .setRoot("add");
+
+ forPattern("root/spam/spam/spam/spam")
+ .createObject().ofType(NamedBean.class)
+ .then()
+ .callMethod("setName").withParamCount(1)
+ .then()
+ .callParam()
+ .then()
+ .setRoot("add");
+ }
+
+ });
+
+ ArrayList<NamedBean> list = new ArrayList<NamedBean>();
+ digester.push(list);
+ digester.parse(reader);
+
+ NamedBean bean = list.get(0);
+ assertEquals("Wrong name (1)", "Simple", bean.getName());
+ // these are added in deepest first order by the addRootRule
+ bean = list.get(4);
+ assertEquals("Wrong name (2)", "Complex", bean.getName());
+ bean = list.get(3);
+ assertEquals("Wrong name (3)", "Deep", bean.getName());
+ bean = list.get(2);
+ assertEquals("Wrong name (4)", "Deeper", bean.getName());
+ bean = list.get(1);
+ assertEquals("Wrong name (5)", "Deepest", bean.getName());
+ }
+
+ @Test
+ public void testProcessingHook() throws Exception {
+ class TestCallMethodRule extends CallMethodRule {
+
+ Object result;
+
+ TestCallMethodRule(String methodName, int paramCount) {
+ super(0, methodName, paramCount, new Class<?>[]{ String.class, String.class }, false);
+ }
+
+ @Override
+ protected void processMethodCallResult(Object result) {
+ this.result = result;
+ }
+
+ }
+
+ final TestCallMethodRule rule = new TestCallMethodRule( "setThisAndThat" , 2 );
+ StringReader reader = new StringReader(
+ "<?xml version='1.0' ?><root>"
+ + "<param class='float' coolness='false'>90</param></root>");
+
+ Digester digester = newBasicDigester(new AbstractRulesModule() {
+
+ @Override
+ protected void configure() {
+ forPattern("root/param")
+ .createObject().ofType(ParamBean.class).then()
+ .setNext("add").then()
+ .addRule(rule).then()
+ .callParam().fromAttribute("class").then()
+ .callParam().ofIndex(1).fromAttribute("coolness");
+ }
+
+ });
+
+ ArrayList<ParamBean> list = new ArrayList<ParamBean>();
+ digester.push(list);
+ digester.parse(reader);
+
+ assertEquals("Wrong number of objects created", 1, list.size());
+ assertEquals("Result not passed into hook", "The Other", rule.result);
+ }
+
+ /**
+ * Test for the PathCallParamRule
+ */
+ @Test
+ public void testPathCallParam() throws Exception {
+ String xml = "<?xml version='1.0'?><main>"
+ + "<alpha><beta>Ignore this</beta></alpha>"
+ + "<beta><epsilon><gamma>Ignore that</gamma></epsilon></beta>"
+ + "</main>";
+
+ SimpleTestBean bean = new SimpleTestBean();
+ bean.setAlphaBeta("[UNSET]", "[UNSET]");
+
+ StringReader in = new StringReader(xml);
+ Digester digester = newLoader(new AbstractRulesModule() {
+
+ @Override
+ protected void configure() {
+ forPattern("*/alpha/?").callParamPath().ofIndex(0);
+ forPattern("*/epsilon/?").callParamPath().ofIndex(1);
+ forPattern("main").callMethod("setAlphaBeta").withParamCount(2);
+ }
+
+ }).newDigester(new ExtendedBaseRules());
+
+ digester.push(bean);
+
+ digester.parse(in);
+
+ assertEquals("Test alpha property setting", "main/alpha/beta" , bean.getAlpha());
+ assertEquals("Test beta property setting", "main/beta/epsilon/gamma" , bean.getBeta());
+ }
+
+ /**
+ * Test invoking an object which does not exist on the stack.
+ */
+ @Test
+ public void testCallInvalidTarget() throws Exception {
+ Digester digester = newBasicDigester(new AbstractRulesModule() {
+
+ @Override
+ protected void configure() {
+ forPattern("employee")
+ .createObject().ofType(HashMap.class).then()
+ .callMethod("put").withTargetOffset(1).withParamCount(0);
+ }
+
+ });
+
+ try {
+ digester.parse(getInputStream("Test5.xml"));
+ fail("Exception should be thrown for invalid target offset");
+ }
+ catch(SAXException e) {
+ // ok, exception expected
+ }
+ }
+
+ /**
+ * Test invoking an object which is at top-1 on the stack, like
+ * SetNextRule does...
+ */
+ @Test
+ public void testCallNext() throws Exception {
+ Digester digester = newBasicDigester(new AbstractRulesModule() {
+
+ @Override
+ protected void configure() {
+ forPattern("employee").createObject().ofType(HashMap.class);
+ forPattern("employee/address")
+ .createObject().ofType(Address.class)
+ .then()
+ .setNestedProperties()
+ .then()
+ .callMethod("put").withParamTypes(String.class, Address.class).withTargetOffset(1)
+ .then()
+ .callParam().ofIndex(1).fromStack(true);
+ forPattern("employee/address/type").callParam();
+ }
+
+ });
+
+ HashMap<String, Address> map = (HashMap<String, Address>) digester.parse(getInputStream("Test5.xml"));
+
+ assertNotNull(map);
+ Set<String> keys = map.keySet();
+ assertEquals(2, keys.size());
+ Address home = map.get("home");
+ assertNotNull(home);
+ assertEquals("HmZip", home.getZipCode());
+ Address office = map.get("office");
+ assertNotNull(office);
+ assertEquals("OfZip", office.getZipCode());
+ }
+
+ /**
+ * Test invoking an object which is at the root of the stack, like
+ * SetRoot does...
+ */
+ @Test
+ public void testCallRoot() throws Exception {
+ Digester digester = newBasicDigester(new AbstractRulesModule() {
+
+ @Override
+ protected void configure() {
+ forPattern("employee").createObject().ofType(HashMap.class);
+ forPattern("employee/address")
+ .createObject().ofType(Address.class)
+ .then()
+ .setNestedProperties()
+ .then()
+ .callMethod("put").withParamTypes(String.class, Address.class).withTargetOffset(-1)
+ .then()
+ .callParam().ofIndex(1).fromStack(true);
+ forPattern("employee/address/type").callParam().ofIndex(0);
+ }
+
+ });
+
+ HashMap<String, Address> map = (HashMap<String, Address>) digester.parse(getInputStream("Test5.xml"));
+
+ assertNotNull(map);
+ Set<String> keys = map.keySet();
+ assertEquals(2, keys.size());
+ Address home = map.get("home");
+ assertNotNull(home);
+ assertEquals("HmZip", home.getZipCode());
+ Address office = map.get("office");
+ assertNotNull(office);
+ assertEquals("OfZip", office.getZipCode());
+ }
+
+}
Propchange: commons/sandbox/digester3/trunk/src/test/java/org/apache/commons/digester3/CallMethodRuleTestCase.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/digester3/trunk/src/test/java/org/apache/commons/digester3/CallMethodRuleTestCase.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/digester3/trunk/src/test/java/org/apache/commons/digester3/CallMethodRuleTestCase.java
------------------------------------------------------------------------------
svn:mime-type = text/plain