001: /* $Id: VariableExpansionTestCase.java 471661 2006-11-06 08:09:25Z skitching $
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:
019: package org.apache.commons.digester.substitution;
020:
021: import org.apache.commons.digester.CallMethodRule;
022: import org.apache.commons.digester.Digester;
023: import org.apache.commons.digester.SimpleTestBean;
024:
025: import java.io.IOException;
026: import java.io.StringReader;
027: import java.util.HashMap;
028: import java.util.LinkedList;
029:
030: import junit.framework.Test;
031: import junit.framework.TestCase;
032: import junit.framework.TestSuite;
033:
034: import org.xml.sax.SAXException;
035:
036: /**
037: * <p>Test Case for the variable expansion facility in Digester.
038: *
039: * @author Simon Kitching
040: * @version $Revision: 471661 $ $Date: 2006-11-06 00:09:25 -0800 (Mon, 06 Nov 2006) $
041: */
042:
043: public class VariableExpansionTestCase extends TestCase {
044:
045: // ----------------------------------------------------------- Constructors
046:
047: /**
048: * Construct a new instance of this test case.
049: *
050: * @param name Name of the test case
051: */
052: public VariableExpansionTestCase(String name) {
053:
054: super (name);
055:
056: }
057:
058: // --------------------------------------------------- Overall Test Methods
059:
060: /**
061: * Set up instance variables required by this test case.
062: */
063: public void setUp() {
064: }
065:
066: /**
067: * Return the tests included in this test suite.
068: */
069: public static Test suite() {
070: return (new TestSuite(VariableExpansionTestCase.class));
071: }
072:
073: /**
074: * Tear down instance variables required by this test case.
075: */
076: public void tearDown() {
077: }
078:
079: // method used in tests4
080: private LinkedList simpleTestBeans = new LinkedList();
081:
082: public void addSimpleTestBean(SimpleTestBean bean) {
083: simpleTestBeans.add(bean);
084: }
085:
086: // implementation of source shared by the variable expander and
087: // is updatable during digesting via an Ant-like property element
088: private HashMap mutableSource = new HashMap();
089:
090: /**
091: * Used in test case "testExpansionWithMutableSource", where the
092: * set of variables available to be substituted into the xml is
093: * updated as the xml is parsed.
094: */
095: public void addProperty(String key, String value) {
096: mutableSource.put(key, value);
097: }
098:
099: /**
100: * Creates a Digester configured to show Ant-like capability.
101: *
102: * @return a Digester with rules and variable substitutor
103: */
104: private Digester createDigesterThatCanDoAnt() {
105: Digester digester = new Digester();
106:
107: MultiVariableExpander expander = new MultiVariableExpander();
108: expander.addSource("$", mutableSource);
109: digester.setSubstitutor(new VariableSubstitutor(expander));
110:
111: int useRootObj = -1;
112: Class[] callerArgTypes = new Class[] { String.class,
113: String.class };
114: CallMethodRule caller = new CallMethodRule(useRootObj,
115: "addProperty", callerArgTypes.length, callerArgTypes);
116: digester.addRule("root/property", caller);
117: digester.addCallParam("root/property", 0, "name");
118: digester.addCallParam("root/property", 1, "value");
119:
120: digester.addObjectCreate("root/bean", SimpleTestBean.class);
121: digester.addSetProperties("root/bean");
122: digester.addSetNext("root/bean", "addSimpleTestBean");
123: return digester;
124: }
125:
126: // ------------------------------------------------ Individual Test Methods
127:
128: /**
129: * Test that by default no expansion occurs.
130: */
131: public void testNoExpansion() throws SAXException, IOException {
132:
133: String xml = "<root alpha='${attr1}' beta='var{attr2}'/>";
134: StringReader input = new StringReader(xml);
135: Digester digester = new Digester();
136:
137: // Configure the digester as required
138: digester.addObjectCreate("root", SimpleTestBean.class);
139: digester.addSetProperties("root");
140:
141: // Parse our test input.
142: Object root = digester.parse(input);
143:
144: assertNotNull("Digester returned no object", root);
145: SimpleTestBean bean = (SimpleTestBean) root;
146:
147: assertEquals("${attr1}", bean.getAlpha());
148: assertEquals("var{attr2}", bean.getBeta());
149: }
150:
151: /**
152: * Test that a MultiVariableExpander with no sources does no expansion.
153: */
154: public void testExpansionWithNoSource() throws SAXException,
155: IOException {
156:
157: String xml = "<root alpha='${attr1}' beta='var{attr2}'/>";
158: StringReader input = new StringReader(xml);
159: Digester digester = new Digester();
160:
161: // Configure the digester as required
162: MultiVariableExpander expander = new MultiVariableExpander();
163: digester.setSubstitutor(new VariableSubstitutor(expander));
164: digester.addObjectCreate("root", SimpleTestBean.class);
165: digester.addSetProperties("root");
166:
167: // Parse our test input.
168: Object root = digester.parse(input);
169:
170: assertNotNull("Digester returned no object", root);
171: SimpleTestBean bean = (SimpleTestBean) root;
172:
173: assertEquals("${attr1}", bean.getAlpha());
174: assertEquals("var{attr2}", bean.getBeta());
175: }
176:
177: /**
178: * Test that a MultiVariableExpander with multiple sources works.
179: * It also tests that expansion works ok where multiple elements
180: * exist.
181: */
182: public void testExpansionWithMultipleSources() throws SAXException,
183: IOException {
184:
185: String xml = "<root>"
186: + "<bean alpha='${attr1}' beta='var{attr1}'/>"
187: + "<bean alpha='${attr2}' beta='var{attr2}'/>"
188: + "</root>";
189:
190: StringReader input = new StringReader(xml);
191: Digester digester = new Digester();
192:
193: // Configure the digester as required
194: HashMap source1 = new HashMap();
195: source1.put("attr1", "source1.attr1");
196: source1.put("attr2", "source1.attr2"); // should not be used
197:
198: HashMap source2 = new HashMap();
199: source2.put("attr1", "source2.attr1"); // should not be used
200: source2.put("attr2", "source2.attr2");
201:
202: MultiVariableExpander expander = new MultiVariableExpander();
203: expander.addSource("$", source1);
204: expander.addSource("var", source2);
205:
206: digester.setSubstitutor(new VariableSubstitutor(expander));
207: digester.addObjectCreate("root/bean", SimpleTestBean.class);
208: digester.addSetProperties("root/bean");
209: digester.addSetNext("root/bean", "addSimpleTestBean");
210:
211: // Parse our test input.
212: this .simpleTestBeans.clear();
213: digester.push(this );
214: digester.parse(input);
215:
216: assertEquals(2, this .simpleTestBeans.size());
217:
218: {
219: SimpleTestBean bean = (SimpleTestBean) this .simpleTestBeans
220: .get(0);
221: assertEquals("source1.attr1", bean.getAlpha());
222: assertEquals("source2.attr1", bean.getBeta());
223: }
224:
225: {
226: SimpleTestBean bean = (SimpleTestBean) this .simpleTestBeans
227: .get(1);
228: assertEquals("source1.attr2", bean.getAlpha());
229: assertEquals("source2.attr2", bean.getBeta());
230: }
231: }
232:
233: /**
234: * Test expansion of text in element bodies.
235: */
236: public void testBodyExpansion() throws SAXException, IOException {
237:
238: String xml = "<root>" + "Twas noun{1} and the noun{2}"
239: + " did verb{1} and verb{2} in the noun{3}" + "</root>";
240:
241: StringReader input = new StringReader(xml);
242: Digester digester = new Digester();
243:
244: // Configure the digester as required
245: HashMap nouns = new HashMap();
246: nouns.put("1", "brillig");
247: nouns.put("2", "slithy toves");
248: nouns.put("3", "wabe");
249:
250: HashMap verbs = new HashMap();
251: verbs.put("1", "gyre");
252: verbs.put("2", "gimble");
253:
254: MultiVariableExpander expander = new MultiVariableExpander();
255: expander.addSource("noun", nouns);
256: expander.addSource("verb", verbs);
257: digester.setSubstitutor(new VariableSubstitutor(expander));
258:
259: digester.addObjectCreate("root", SimpleTestBean.class);
260: digester.addCallMethod("root", "setAlpha", 0);
261:
262: // Parse our test input.
263: Object root = digester.parse(input);
264:
265: assertNotNull("Digester returned no object", root);
266: SimpleTestBean bean = (SimpleTestBean) root;
267:
268: assertEquals("Twas brillig and the slithy toves"
269: + " did gyre and gimble in the wabe", bean.getAlpha());
270: }
271:
272: /**
273: * Test that an unknown variable causes a RuntimeException.
274: */
275: public void testExpansionException() throws IOException {
276:
277: String xml = "<root alpha='${attr1}'/>";
278: StringReader input = new StringReader(xml);
279: Digester digester = new Digester();
280:
281: // Configure the digester as required
282: MultiVariableExpander expander = new MultiVariableExpander();
283: expander.addSource("$", new HashMap());
284: digester.setSubstitutor(new VariableSubstitutor(expander));
285:
286: digester.addObjectCreate("root", SimpleTestBean.class);
287: digester.addSetProperties("root");
288:
289: // Parse our test input.
290: try {
291: digester.parse(input);
292: fail("Exception expected due to unknown variable.");
293: } catch (SAXException e) {
294: // expected, due to reference to undefined variable
295: }
296: }
297:
298: /**
299: * First of two tests added to verify that the substitution
300: * framework is capable of processing Ant-like properties.
301: *
302: * The tests above essentially verify that if a property
303: * was pre-set (e.g. using the "-D" option to Ant), then
304: * the property could be expanded via a variable used either
305: * in an attribute or in body text.
306: *
307: * This test shows that if properties were also set while
308: * processing a document, you could still perform variable
309: * expansion (i.e. just like using the "property" task in Ant).
310: *
311: * @throws IOException
312: * @throws SAXException
313: */
314: public void testExpansionWithMutableSource() throws SAXException,
315: IOException {
316: String xml = "<root>"
317: + "<property name='attr' value='prop.value'/>"
318: + "<bean alpha='${attr}'/>" + "</root>";
319: StringReader input = new StringReader(xml);
320: Digester digester = createDigesterThatCanDoAnt();
321:
322: simpleTestBeans.clear();
323: digester.push(this );
324: digester.parse(input);
325:
326: assertEquals(1, simpleTestBeans.size());
327: SimpleTestBean bean = (SimpleTestBean) simpleTestBeans.get(0);
328: assertEquals("prop.value", bean.getAlpha());
329: }
330:
331: /**
332: * Second of two tests added to verify that the substitution
333: * framework is capable of processing Ant-like properties.
334: *
335: * This test shows that if properties were also set while
336: * processing a document, the resulting variables could also
337: * be expanded within a property element. This is thus
338: * effectively a "closure" test, since it shows that the
339: * mechanism used to bind properties is also capable of
340: * having property values that are driven by property variables.
341: *
342: * @throws IOException
343: * @throws SAXException
344: */
345: public void testExpansionOfPropertyInProperty()
346: throws SAXException, IOException {
347: String xml = "<root>"
348: + "<property name='attr1' value='prop.value1'/>"
349: + "<property name='attr2' value='substituted-${attr1}'/>"
350: + "<bean alpha='${attr2}'/>" + "</root>";
351: StringReader input = new StringReader(xml);
352: Digester digester = createDigesterThatCanDoAnt();
353:
354: simpleTestBeans.clear();
355: digester.push(this );
356: digester.parse(input);
357:
358: assertEquals(1, simpleTestBeans.size());
359: SimpleTestBean bean = (SimpleTestBean) simpleTestBeans.get(0);
360: assertEquals("substituted-prop.value1", bean.getAlpha());
361: }
362:
363: }
|