rdonkin 2003/12/02 15:21:16 Modified: digester build.xml digester/src/java/org/apache/commons/digester Digester.java digester/src/test/org/apache/commons/digester DigesterTestCase.java Added: digester/src/java/org/apache/commons/digester Substitutor.java Log: Added support for substitution of variables (and anything else that people want ;). This is a first cut, hopefully I'll be back with more documentation and Remy's peculiar implementation tommorrow. Contains contributions by Simon Kitching. Revision Changes Path 1.50 +17 -2 jakarta-commons/digester/build.xml Index: build.xml =================================================================== RCS file: /home/cvs/jakarta-commons/digester/build.xml,v retrieving revision 1.49 retrieving revision 1.50 diff -u -r1.49 -r1.50 --- build.xml 19 Nov 2003 21:07:06 -0000 1.49 +++ build.xml 2 Dec 2003 23:21:16 -0000 1.50 @@ -273,7 +273,8 @@ test.regex, test.wdrules, test.plugins, - test.others + test.others, + test.substitution " description="Run all unit test cases"> </target> @@ -503,6 +504,20 @@ failonerror="${test.failonerror}"> <jvmarg value="-D${logopt}"/> <arg value="org.apache.commons.digester.TestOthers"/> + <classpath refid="test.classpath"/> + </java> + </target> + + <target name="test.substitution" depends="compile.tests" + description="Run Substitutions tests ..."> + <echo message="Running Substitutions tests ..."/> + <condition property="logopt" value="${log.factoryopt}=${log.class}"> + <istrue value="${suppressLogOutputDuringTests}"/> + </condition> + <java classname="${test.runner}" fork="yes" + failonerror="${test.failonerror}"> + <jvmarg value="-D${logopt}"/> + <arg value="org.apache.commons.digester.substitution.TestAll"/> <classpath refid="test.classpath"/> </java> </target> 1.87 +35 -8 jakarta-commons/digester/src/java/org/apache/commons/digester/Digester.java Index: Digester.java =================================================================== RCS file: /home/cvs/jakarta-commons/digester/src/java/org/apache/commons/digester/Digester.java,v retrieving revision 1.86 retrieving revision 1.87 diff -u -r1.86 -r1.87 --- Digester.java 19 Nov 2003 21:05:19 -0000 1.86 +++ Digester.java 2 Dec 2003 23:21:16 -0000 1.87 @@ -360,7 +360,11 @@ protected static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema"; - + /** + * An optional class that substitutes values in attributes and body text. + * This may be null and so a null check is always required before use. + */ + protected Substitutor substitutor; // ------------------------------------------------------------- Properties @@ -934,6 +938,22 @@ return reader; } + /** + * Gets the <code>Substitutor</code> used to convert attributes and body text. + * @return Substitutor, null if not substitutions are to be performed. + */ + public Substitutor getSubstitutor() { + return substitutor; + } + + /** + * Sets the <code>Substitutor</code> to be used to convert attributes and body text. + * @param substitutor the Substitutor to be used to convert attributes and body text + * or null if not substitution of these values is to be performed. + */ + public void setSubstitutor(Substitutor substitutor) { + this.substitutor = substitutor; + } // ------------------------------------------------- ContentHandler Methods @@ -1038,6 +1058,10 @@ List rules = getRules().match(namespaceURI, match); if ((rules != null) && (rules.size() > 0)) { String bodyText = this.bodyText.toString(); + Substitutor substitutor = getSubstitutor(); + if (substitutor!= null) { + bodyText = substitutor.substitute(bodyText); + } for (int i = 0; i < rules.size(); i++) { try { Rule rule = (Rule) rules.get(i); @@ -1282,7 +1306,10 @@ // Fire "begin" events for all relevant rules List rules = getRules().match(namespaceURI, match); if ((rules != null) && (rules.size() > 0)) { - String bodyText = this.bodyText.toString(); + Substitutor substitutor = getSubstitutor(); + if (substitutor!= null) { + list = substitutor.substitute(list); + } for (int i = 0; i < rules.size(); i++) { try { Rule rule = (Rule) rules.get(i); @@ -2182,7 +2209,7 @@ } /** - * Adds an [EMAIL PROTECTED] SetNestPropertiesRule}. + * Adds an [EMAIL PROTECTED] SetNestedPropertiesRule}. * * @param pattern register the rule with this pattern * @param elementName elment name that a property maps to @@ -2194,7 +2221,7 @@ } /** - * Adds an [EMAIL PROTECTED] SetNestPropertiesRule}. + * Adds an [EMAIL PROTECTED] SetNestedPropertiesRule}. * * @param pattern register the rule with this pattern * @param elementNames elment names that (in order) map to properties 1.1 jakarta-commons/digester/src/java/org/apache/commons/digester/Substitutor.java Index: Substitutor.java =================================================================== /* * $Header: /home/cvs/jakarta-commons/digester/src/java/org/apache/commons/digester/Substitutor.java,v 1.1 2003/12/02 23:21:16 rdonkin Exp $ * $Revision: 1.1 $ * $Date: 2003/12/02 23:21:16 $ * * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 2001-2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgement may appear in the software itself, * if and wherever such third-party acknowledgements normally appear. * * 4. The names "Apache", "The Jakarta Project", "Commons", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior * written permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ package org.apache.commons.digester; import org.xml.sax.Attributes; /** * <p>(Logical) Interface for substitution strategies. * (It happens to be implemented as a Java abstract class to allow * future additions to be made without breaking backwards compatibility.) * </p> * <p> * Usage: When [EMAIL PROTECTED] Digester#setSubstitutor} is set, <code>Digester</code> * calls the methods in this interface to create substitute values which will * be passed into the Rule implementations. * Of course, it is perfectly acceptable for implementations not to make * substitutions and simply return the inputs. * </p> * <p>Different strategies are supported for attributes and body text.</p> * * @author Robert Burrell Donkin * @version $Revision: 1.1 $ $Date: 2003/12/02 23:21:16 $ */ public abstract class Substitutor { /** * Substitutes the attributes (before they are passed to the * <code>Rule</code> implementations's) */ public abstract Attributes substitute(Attributes attributes); /** * Substitutes for the body text. * This method may substitute values into the body text of the * elements that Digester parses. * * @param the body text (as passed to <code>Digester</code>) * @return the body text to be passed to the <code>Rule</code> implementations */ public abstract String substitute(String bodyText); } 1.16 +60 -4 jakarta-commons/digester/src/test/org/apache/commons/digester/DigesterTestCase.java Index: DigesterTestCase.java =================================================================== RCS file: /home/cvs/jakarta-commons/digester/src/test/org/apache/commons/digester/DigesterTestCase.java,v retrieving revision 1.15 retrieving revision 1.16 diff -u -r1.15 -r1.16 --- DigesterTestCase.java 9 Oct 2003 21:09:48 -0000 1.15 +++ DigesterTestCase.java 2 Dec 2003 23:21:16 -0000 1.16 @@ -74,6 +74,9 @@ import junit.framework.TestSuite; import org.xml.sax.ErrorHandler; +import org.xml.sax.Attributes; +import org.xml.sax.helpers.AttributesImpl; +import org.xml.sax.InputSource; /** @@ -370,4 +373,57 @@ assertEquals("Initialize should be called once and only once", 1, digester.called); } + + public void testBasicSubstitution() throws Exception { + class TestSubRule extends Rule { + public String body; + public Attributes attributes; + + public void begin(String namespace, String name, Attributes attributes) { + this.attributes = new AttributesImpl(attributes); + } + + public void body(String namespace, String name, String text) { + this.body = text; + } + } + + TestSubRule tsr = new TestSubRule(); + Digester digester = new Digester(); + digester.addRule("alpha/beta", tsr); + + // it's not easy to transform dirty harry into the mighty circus - but let's give it a try + String xml = "<?xml version='1.0'?><alpha><beta forname='Dirty' surname='Harry'>Do you feel luck punk?</beta></alpha>"; + InputSource in = new InputSource(new StringReader(xml)); + + digester.parse(in); + + assertEquals("Unsubstituted body text", "Do you feel luck punk?", tsr.body); + assertEquals("Unsubstituted number of attributes", 2, tsr.attributes.getLength()); + assertEquals("Unsubstituted forname attribute value", "Dirty", tsr.attributes.getValue("forname")); + assertEquals("Unsubstituted surname attribute value", "Harry", tsr.attributes.getValue("surname")); + + digester.setSubstitutor( + new Substitutor() { + public Attributes substitute(Attributes attributes) { + AttributesImpl results = new AttributesImpl(); + results.addAttribute("", "python", "python", "CDATA", "Cleese"); + return results; + } + + public String substitute(String bodyText) { + return "And now for something completely different..."; + } + }); + + // now transform into the full monty + in = new InputSource(new StringReader(xml)); + digester.parse(in); + + assertEquals("Substituted body text", "And now for something completely different...", tsr.body); + assertEquals("Substituted number of attributes", 1, tsr.attributes.getLength()); + assertEquals("Substituted python attribute value", "Cleese", tsr.attributes.getValue("", "python")); + } + + }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]