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/06/27 17:44:37 UTC

svn commit: r1140212 - in /commons/proper/digester/trunk: ./ src/changes/ src/main/java/org/apache/commons/digester3/ src/main/java/org/apache/commons/digester3/annotations/handlers/ src/main/java/org/apache/commons/digester3/annotations/rules/ src/mai...

Author: simonetripodi
Date: Mon Jun 27 15:44:36 2011
New Revision: 1140212

URL: http://svn.apache.org/viewvc?rev=1140212&view=rev
Log:
[DIGESTER-72] Allow SetNextRule to fire on begin

I added an abstraction layer in order to support the same feature not only for SetNext, also for SetRoot and SetTop.
xmlrules and annotations are supported as well

Added:
    commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/AbstractMethodRule.java   (with props)
Modified:
    commons/proper/digester/trunk/RELEASE-NOTES.txt
    commons/proper/digester/trunk/src/changes/changes.xml
    commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/SetNextRule.java
    commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/SetRootRule.java
    commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/SetTopRule.java
    commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/handlers/AbstractMethodHandler.java
    commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/handlers/SetNextHandler.java
    commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/handlers/SetRootHandler.java
    commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/handlers/SetTopHandler.java
    commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/rules/SetNext.java
    commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/rules/SetRoot.java
    commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/rules/SetTop.java
    commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/utils/AnnotationUtils.java
    commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/binder/AbstractParamTypeBuilder.java
    commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/binder/SetNextBuilder.java
    commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/binder/SetRootBuilder.java
    commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/binder/SetTopBuilder.java
    commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/xmlrules/AbstractXmlMethodRule.java
    commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/xmlrules/SetNextRule.java
    commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/xmlrules/SetRootRule.java
    commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/xmlrules/SetTopRule.java
    commons/proper/digester/trunk/src/main/resources/org/apache/commons/digester3/xmlrules/digester-rules.dtd
    commons/proper/digester/trunk/src/site/resources/dtds/digester-rules-3.0.dtd
    commons/proper/digester/trunk/src/test/java/org/apache/commons/digester3/annotations/addressbook/Person.java
    commons/proper/digester/trunk/src/test/resources/org/apache/commons/digester3/xmlrules/atom-rules.xml

Modified: commons/proper/digester/trunk/RELEASE-NOTES.txt
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/RELEASE-NOTES.txt?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/RELEASE-NOTES.txt (original)
+++ commons/proper/digester/trunk/RELEASE-NOTES.txt Mon Jun 27 15:44:36 2011
@@ -87,6 +87,8 @@ BUGS FROM PREVIOUS RELEASE
 IMPROVEMENTS OVER PREVIOUS RELEASE
 ===================================
 
+ * [DIGESTER-72] Allow SetNextRule to fire on begin
+
  * [DIGESTER-85] Include filename or uri if Digester.parse(File file or String uri throws a SAXException
 
  * [DIGESTER-90] xmlrules does not support setNamespaceURI

Modified: commons/proper/digester/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/changes/changes.xml?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/changes/changes.xml (original)
+++ commons/proper/digester/trunk/src/changes/changes.xml Mon Jun 27 15:44:36 2011
@@ -26,6 +26,9 @@
     <action dev="simonetripodi" type="fix" issue="DIGESTER-28">
       Default ClassLoader policy unusable in EAR archive
     </action>
+    <action dev="simonetripodi" type="add" issue="DIGESTER-72">
+      Allow SetNextRule to fire on begin
+    </action>
     <action dev="simonetripodi" type="add" issue="DIGESTER-85">
       Include filename or uri if Digester.parse(File file or String uri throws a SAXException
     </action>

Added: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/AbstractMethodRule.java
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/AbstractMethodRule.java?rev=1140212&view=auto
==============================================================================
--- commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/AbstractMethodRule.java (added)
+++ commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/AbstractMethodRule.java Mon Jun 27 15:44:36 2011
@@ -0,0 +1,259 @@
+package org.apache.commons.digester3;
+
+import static java.lang.String.format;
+
+import org.apache.commons.beanutils.MethodUtils;
+import org.apache.commons.digester3.annotations.rules.SetNext;
+import org.apache.commons.digester3.annotations.rules.SetRoot;
+import org.apache.commons.digester3.annotations.rules.SetTop;
+import org.xml.sax.Attributes;
+
+/*
+ * 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.
+ */
+
+/**
+ * Abstarct implementation for {@link SetNext}, {@link SetRoot} and {@link SetTop} rules.
+ *
+ * @since 3.0
+ */
+public abstract class AbstractMethodRule
+    extends Rule
+{
+
+    /**
+     * The method name to call on the parent object.
+     */
+    protected String methodName = null;
+
+    /**
+     * The Java class name of the parameter type expected by the method.
+     */
+    protected String paramTypeName = null;
+
+    /**
+     * The Java class name of the parameter type expected by the method.
+     */
+    protected Class<?> paramType;
+
+    /**
+     * Should we use exact matching. Default is no.
+     */
+    protected boolean useExactMatch = false;
+
+    /**
+     * Should this rule be invoked when {@link #begin(String, String, Attributes)} (true)
+     * or {@link #end(String, String)} (false) methods are invoked, false by default.
+     */
+    protected boolean fireOnBegin = false;
+
+    /**
+     * Construct a "set next" rule with the specified method name. The method's argument type is assumed to be the class
+     * of the child object.
+     * 
+     * @param methodName Method name of the parent method to call
+     */
+    public AbstractMethodRule( String methodName )
+    {
+        this( methodName, (String) null );
+    }
+
+    /**
+     * Construct a "set next" rule with the specified method name.
+     * 
+     * @param methodName Method name of the parent method to call
+     * @param paramType Java class of the parent method's argument (if you wish to use a primitive type, specify the
+     *            corresonding Java wrapper class instead, such as <code>java.lang.Boolean</code> for a
+     *            <code>boolean</code> parameter)
+     */
+    public AbstractMethodRule( String methodName, Class<?> paramType )
+    {
+        this( methodName, paramType.getName() );
+        this.paramType = paramType;
+    }
+
+    /**
+     * Construct a "set next" rule with the specified method name.
+     * 
+     * @param methodName Method name of the parent method to call
+     * @param paramTypeName Java class of the parent method's argument (if you wish to use a primitive type, specify the
+     *            corresonding Java wrapper class instead, such as <code>java.lang.Boolean</code> for a
+     *            <code>boolean</code> parameter)
+     */
+    public AbstractMethodRule( String methodName, String paramTypeName )
+    {
+        this.methodName = methodName;
+        this.paramTypeName = paramTypeName;
+    }
+
+    /**
+     * <p>
+     * Is exact matching being used.
+     * </p>
+     * <p>
+     * This rule uses <code>org.apache.commons.beanutils.MethodUtils</code> to introspect the relevent objects so that
+     * the right method can be called. Originally, <code>MethodUtils.invokeExactMethod</code> was used. This matches
+     * methods very strictly and so may not find a matching method when one exists. This is still the behaviour when
+     * exact matching is enabled.
+     * </p>
+     * <p>
+     * When exact matching is disabled, <code>MethodUtils.invokeMethod</code> is used. This method finds more methods
+     * but is less precise when there are several methods with correct signatures. So, if you want to choose an exact
+     * signature you might need to enable this property.
+     * </p>
+     * <p>
+     * The default setting is to disable exact matches.
+     * </p>
+     * 
+     * @return true if exact matching is enabled
+     * @since Digester Release 1.1.1
+     */
+    public boolean isExactMatch()
+    {
+        return useExactMatch;
+    }
+
+    /**
+     * Sets this rule be invoked when {@link #begin(String, String, Attributes)} (true)
+     * or {@link #end(String, String)} (false) methods are invoked, false by default.
+     *
+     * @param fireOnBegin flag to mark this rule be invoked when {@link #begin(String, String, Attributes)} (true)
+     *                    or {@link #end(String, String)} (false) methods are invoked, false by default.
+     */
+    public void setFireOnBegin( boolean fireOnBegin )
+    {
+        this.fireOnBegin = fireOnBegin;
+    }
+
+    /**
+     * Returns the flag this rule be invoked when {@link #begin(String, String, Attributes)} (true)
+     * or {@link #end(String, String)} (false) methods are invoked, false by default.
+     *
+     * @return the flag this rule be invoked when {@link #begin(String, String, Attributes)} (true)
+     * or {@link #end(String, String)} (false) methods are invoked, false by default.
+     */
+    public boolean isFireOnBegin()
+    {
+        return fireOnBegin;
+    }
+
+    /**
+     * <p>
+     * Set whether exact matching is enabled.
+     * </p>
+     * <p>
+     * See {@link #isExactMatch()}.
+     * </p>
+     * 
+     * @param useExactMatch should this rule use exact method matching
+     * @since Digester Release 1.1.1
+     */
+    public void setExactMatch( boolean useExactMatch )
+    {
+        this.useExactMatch = useExactMatch;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void begin( String namespace, String name, Attributes attributes )
+        throws Exception
+    {
+        if ( fireOnBegin )
+        {
+            invoke();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void end( String namespace, String name )
+        throws Exception
+    {
+        if ( !fireOnBegin )
+        {
+            invoke();
+        }
+    }
+
+    private void invoke()
+        throws Exception
+    {
+        // Identify the objects to be used
+        Object child = getChild();
+        Object parent = getParent();
+        if ( getDigester().getLogger().isDebugEnabled() )
+        {
+            if ( parent == null )
+            {
+                getDigester().getLogger().debug( format( "[%s]{%s} Call [NULL PARENT].%s(%s)",
+                                                         getClass().getSimpleName(),
+                                                         getDigester().getMatch(),
+                                                         methodName,
+                                                         child ) );
+            }
+            else
+            {
+                getDigester().getLogger().debug( format( "[%s]{%s} Call %s.%s(%s)",
+                                                         getClass().getSimpleName(),
+                                                         getDigester().getMatch(),
+                                                         parent.getClass().getName(),
+                                                         methodName,
+                                                         child ) );
+            }
+        }
+
+        // Call the specified method
+        Class<?> paramTypes[] = new Class<?>[1];
+        if ( paramType != null )
+        {
+            paramTypes[0] = getDigester().getClassLoader().loadClass( paramTypeName );
+        }
+        else
+        {
+            paramTypes[0] = child.getClass();
+        }
+
+        if ( useExactMatch )
+        {
+            MethodUtils.invokeExactMethod( parent, methodName, new Object[] { child }, paramTypes );
+        }
+        else
+        {
+            MethodUtils.invokeMethod( parent, methodName, new Object[] { child }, paramTypes );
+        }
+    }
+
+    protected abstract Object getChild();
+
+    protected abstract Object getParent();
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public final String toString()
+    {
+        return format( "%s[methodName=%s, paramType=%s, paramTypeName=%s, useExactMatch=%s, fireOnBegin=%s]",
+                       getClass().getSimpleName(), methodName, paramType, paramTypeName, useExactMatch, fireOnBegin );
+    }
+
+}

Propchange: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/AbstractMethodRule.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/AbstractMethodRule.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/AbstractMethodRule.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/SetNextRule.java
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/SetNextRule.java?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/SetNextRule.java (original)
+++ commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/SetNextRule.java Mon Jun 27 15:44:36 2011
@@ -19,9 +19,6 @@ package org.apache.commons.digester3;
  * under the License.
  */
 
-import static java.lang.String.format;
-
-import org.apache.commons.beanutils.MethodUtils;
 
 /**
  * <p>
@@ -40,7 +37,7 @@ import org.apache.commons.beanutils.Meth
  * </p>
  */
 public class SetNextRule
-    extends Rule
+    extends AbstractMethodRule
 {
 
     // ----------------------------------------------------------- Constructors
@@ -53,142 +50,51 @@ public class SetNextRule
      */
     public SetNextRule( String methodName )
     {
-        this( methodName, null );
+        super( methodName );
     }
 
     /**
      * Construct a "set next" rule with the specified method name.
      * 
      * @param methodName Method name of the parent method to call
-     * @param paramType Java class of the parent method's argument (if you wish to use a primitive type, specify the
+     * @param paramType Java class name of the parent method's argument (if you wish to use a primitive type, specify the
      *            corresonding Java wrapper class instead, such as <code>java.lang.Boolean</code> for a
      *            <code>boolean</code> parameter)
      */
     public SetNextRule( String methodName, String paramType )
     {
-        this.methodName = methodName;
-        this.paramType = paramType;
-    }
-
-    // ----------------------------------------------------- Instance Variables
-
-    /**
-     * The method name to call on the parent object.
-     */
-    protected String methodName = null;
-
-    /**
-     * The Java class name of the parameter type expected by the method.
-     */
-    protected String paramType = null;
-
-    /**
-     * Should we use exact matching. Default is no.
-     */
-    protected boolean useExactMatch = false;
-
-    // --------------------------------------------------------- Public Methods
-
-    /**
-     * <p>
-     * Is exact matching being used.
-     * </p>
-     * <p>
-     * This rule uses <code>org.apache.commons.beanutils.MethodUtils</code> to introspect the relevent objects so that
-     * the right method can be called. Originally, <code>MethodUtils.invokeExactMethod</code> was used. This matches
-     * methods very strictly and so may not find a matching method when one exists. This is still the behaviour when
-     * exact matching is enabled.
-     * </p>
-     * <p>
-     * When exact matching is disabled, <code>MethodUtils.invokeMethod</code> is used. This method finds more methods
-     * but is less precise when there are several methods with correct signatures. So, if you want to choose an exact
-     * signature you might need to enable this property.
-     * </p>
-     * <p>
-     * The default setting is to disable exact matches.
-     * </p>
-     * 
-     * @return true iff exact matching is enabled
-     * @since Digester Release 1.1.1
-     */
-    public boolean isExactMatch()
-    {
-        return useExactMatch;
+        super( methodName, paramType );
     }
 
     /**
-     * <p>
-     * Set whether exact matching is enabled.
-     * </p>
-     * <p>
-     * See {@link #isExactMatch()}.
-     * </p>
+     * Construct a "set next" rule with the specified method name.
      * 
-     * @param useExactMatch should this rule use exact method matching
-     * @since Digester Release 1.1.1
+     * @param methodName Method name of the parent method to call
+     * @param paramType Java class of the parent method's argument (if you wish to use a primitive type, specify the
+     *            corresonding Java wrapper class instead, such as <code>java.lang.Boolean</code> for a
+     *            <code>boolean</code> parameter)
      */
-    public void setExactMatch( boolean useExactMatch )
+    public SetNextRule( String methodName, Class<?> paramType )
     {
-        this.useExactMatch = useExactMatch;
+        super( methodName, paramType );
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public void end( String namespace, String name )
-        throws Exception
+    protected Object getChild()
     {
-        // Identify the objects to be used
-        Object child = getDigester().peek( 0 );
-        Object parent = getDigester().peek( 1 );
-        if ( getDigester().getLogger().isDebugEnabled() )
-        {
-            if ( parent == null )
-            {
-                getDigester().getLogger().debug( format( "[SetNextRule]{%s} Call [NULL PARENT].%s(%s)",
-                                                         getDigester().getMatch(),
-                                                         methodName,
-                                                         child ) );
-            }
-            else
-            {
-                getDigester().getLogger().debug( format( "[SetNextRule]{%s} Call %s.%s(%s)",
-                                                         getDigester().getMatch(),
-                                                         parent.getClass().getName(),
-                                                         methodName,
-                                                         child ) );
-            }
-        }
-
-        // Call the specified method
-        Class<?> paramTypes[] = new Class<?>[1];
-        if ( paramType != null )
-        {
-            paramTypes[0] = getDigester().getClassLoader().loadClass( paramType );
-        }
-        else
-        {
-            paramTypes[0] = child.getClass();
-        }
-
-        if ( useExactMatch )
-        {
-            MethodUtils.invokeExactMethod( parent, methodName, new Object[] { child }, paramTypes );
-        }
-        else
-        {
-            MethodUtils.invokeMethod( parent, methodName, new Object[] { child }, paramTypes );
-        }
+        return getDigester().peek( 0 );
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public String toString()
+    protected Object getParent()
     {
-        return format( "SetNextRule[methodName=%s, paramType=%s]", methodName, paramType );
+        return getDigester().peek( 1 );
     }
 
 }

Modified: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/SetRootRule.java
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/SetRootRule.java?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/SetRootRule.java (original)
+++ commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/SetRootRule.java Mon Jun 27 15:44:36 2011
@@ -19,9 +19,6 @@ package org.apache.commons.digester3;
  * under the License.
  */
 
-import static java.lang.String.format;
-
-import org.apache.commons.beanutils.MethodUtils;
 
 /**
  * <p>
@@ -34,7 +31,7 @@ import org.apache.commons.beanutils.Meth
  * </p>
  */
 public class SetRootRule
-    extends Rule
+    extends AbstractMethodRule
 {
 
     // ----------------------------------------------------------- Constructors
@@ -47,142 +44,51 @@ public class SetRootRule
      */
     public SetRootRule( String methodName )
     {
-        this( methodName, null );
+        super( methodName );
     }
 
     /**
      * Construct a "set root" rule with the specified method name.
      * 
      * @param methodName Method name of the parent method to call
-     * @param paramType Java class of the parent method's argument (if you wish to use a primitive type, specify the
+     * @param paramType Java class name of the parent method's argument (if you wish to use a primitive type, specify the
      *            corresonding Java wrapper class instead, such as <code>java.lang.Boolean</code> for a
      *            <code>boolean</code> parameter)
      */
     public SetRootRule( String methodName, String paramType )
     {
-        this.methodName = methodName;
-        this.paramType = paramType;
-    }
-
-    // ----------------------------------------------------- Instance Variables
-
-    /**
-     * The method name to call on the parent object.
-     */
-    protected String methodName = null;
-
-    /**
-     * The Java class name of the parameter type expected by the method.
-     */
-    protected String paramType = null;
-
-    /**
-     * Should we use exact matching. Default is no.
-     */
-    protected boolean useExactMatch = false;
-
-    // --------------------------------------------------------- Public Methods
-
-    /**
-     * <p>
-     * Is exact matching being used.
-     * </p>
-     * <p>
-     * This rule uses <code>org.apache.commons.beanutils.MethodUtils</code> to introspect the relevent objects so that
-     * the right method can be called. Originally, <code>MethodUtils.invokeExactMethod</code> was used. This matches
-     * methods very strictly and so may not find a matching method when one exists. This is still the behaviour when
-     * exact matching is enabled.
-     * </p>
-     * <p>
-     * When exact matching is disabled, <code>MethodUtils.invokeMethod</code> is used. This method finds more methods
-     * but is less precise when there are several methods with correct signatures. So, if you want to choose an exact
-     * signature you might need to enable this property.
-     * </p>
-     * <p>
-     * The default setting is to disable exact matches.
-     * </p>
-     * 
-     * @return true if exact matching is enabled
-     * @since 1.1.1
-     */
-    public boolean isExactMatch()
-    {
-        return useExactMatch;
+        super( methodName, paramType );
     }
 
     /**
-     * <p>
-     * Set whether exact matching is enabled.
-     * </p>
-     * <p>
-     * See {@link #isExactMatch()}.
-     * </p>
+     * Construct a "set root" rule with the specified method name.
      * 
-     * @param useExactMatch should this rule use exact method matching
-     * @since 1.1.1
+     * @param methodName Method name of the parent method to call
+     * @param paramType Java class of the parent method's argument (if you wish to use a primitive type, specify the
+     *            corresonding Java wrapper class instead, such as <code>java.lang.Boolean</code> for a
+     *            <code>boolean</code> parameter)
      */
-    public void setExactMatch( boolean useExactMatch )
+    public SetRootRule( String methodName, Class<?> paramType )
     {
-        this.useExactMatch = useExactMatch;
+        super( methodName, paramType );
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public void end( String namespace, String name )
-        throws Exception
+    protected Object getChild()
     {
-        // Identify the objects to be used
-        Object child = getDigester().peek( 0 );
-        Object parent = getDigester().getRoot();
-        if ( getDigester().getLogger().isDebugEnabled() )
-        {
-            if ( parent == null )
-            {
-                getDigester().getLogger().debug( format( "[SetRootRule]{%s} Call [NULL ROOT].%s(%s)",
-                                                         getDigester().getMatch(),
-                                                         methodName,
-                                                         child ) );
-            }
-            else
-            {
-                getDigester().getLogger().debug( format( "[SetRootRule]{%s} Call %s.%s(%s)",
-                                                         getDigester().getMatch(),
-                                                         parent.getClass().getName(),
-                                                         methodName,
-                                                         child ) );
-            }
-        }
-
-        // Call the specified method
-        Class<?> paramTypes[] = new Class<?>[1];
-        if ( paramType != null )
-        {
-            paramTypes[0] = getDigester().getClassLoader().loadClass( paramType );
-        }
-        else
-        {
-            paramTypes[0] = child.getClass();
-        }
-
-        if ( useExactMatch )
-        {
-            MethodUtils.invokeExactMethod( parent, methodName, new Object[] { child }, paramTypes );
-        }
-        else
-        {
-            MethodUtils.invokeMethod( parent, methodName, new Object[] { child }, paramTypes );
-        }
+        return getDigester().peek( 0 );
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public String toString()
+    protected Object getParent()
     {
-        return format( "SetRootRule[methodName=%s, paramType=%s]", methodName, paramType );
+        return getDigester().getRoot();
     }
 
 }

Modified: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/SetTopRule.java
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/SetTopRule.java?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/SetTopRule.java (original)
+++ commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/SetTopRule.java Mon Jun 27 15:44:36 2011
@@ -19,9 +19,6 @@ package org.apache.commons.digester3;
  * under the License.
  */
 
-import static java.lang.String.format;
-
-import org.apache.commons.beanutils.MethodUtils;
 
 /**
  * <p>
@@ -34,152 +31,64 @@ import org.apache.commons.beanutils.Meth
  * </p>
  */
 public class SetTopRule
-    extends Rule
+    extends AbstractMethodRule
 {
 
     // ----------------------------------------------------------- Constructors
 
     /**
-     * Construct a "set parent" rule with the specified method name. The "set parent" method's argument type is assumed
-     * to be the class of the parent object.
+     * Construct a "set top" rule with the specified method name. The method's argument type is assumed to be the class
+     * of the child object.
      * 
-     * @param methodName Method name of the "set parent" method to call
+     * @param methodName Method name of the parent method to call
      */
     public SetTopRule( String methodName )
     {
-        this( methodName, null );
+        super( methodName );
     }
 
     /**
-     * Construct a "set parent" rule with the specified method name.
+     * Construct a "set top" rule with the specified method name.
      * 
-     * @param methodName Method name of the "set parent" method to call
-     * @param paramType Java class of the "set parent" method's argument (if you wish to use a primitive type, specify
-     *            the corresonding Java wrapper class instead, such as <code>java.lang.Boolean</code> for a
+     * @param methodName Method name of the parent method to call
+     * @param paramType Java class name of the parent method's argument (if you wish to use a primitive type, specify the
+     *            corresonding Java wrapper class instead, such as <code>java.lang.Boolean</code> for a
      *            <code>boolean</code> parameter)
      */
     public SetTopRule( String methodName, String paramType )
     {
-        this.methodName = methodName;
-        this.paramType = paramType;
+        super( methodName, paramType );
     }
 
-    // ----------------------------------------------------- Instance Variables
-
-    /**
-     * The method name to call on the child object.
-     */
-    protected String methodName = null;
-
     /**
-     * The Java class name of the parameter type expected by the method.
-     */
-    protected String paramType = null;
-
-    /**
-     * Should we use exact matching. Default is no.
-     */
-    protected boolean useExactMatch = false;
-
-    // --------------------------------------------------------- Public Methods
-
-    /**
-     * <p>
-     * Is exact matching being used.
-     * </p>
-     * <p>
-     * This rule uses <code>org.apache.commons.beanutils.MethodUtils</code> to introspect the relevent objects so that
-     * the right method can be called. Originally, <code>MethodUtils.invokeExactMethod</code> was used. This matches
-     * methods very strictly and so may not find a matching method when one exists. This is still the behaviour when
-     * exact matching is enabled.
-     * </p>
-     * <p>
-     * When exact matching is disabled, <code>MethodUtils.invokeMethod</code> is used. This method finds more methods
-     * but is less precise when there are several methods with correct signatures. So, if you want to choose an exact
-     * signature you might need to enable this property.
-     * </p>
-     * <p>
-     * The default setting is to disable exact matches.
-     * </p>
+     * Construct a "set top" rule with the specified method name.
      * 
-     * @return true iff exact matching is enabled
-     * @since 1.1.1
-     */
-    public boolean isExactMatch()
-    {
-        return useExactMatch;
-    }
-
-    /**
-     * <p>
-     * Set whether exact matching is enabled.
-     * </p>
-     * <p>
-     * See {@link #isExactMatch()}.
-     * </p>
-     * 
-     * @param useExactMatch should this rule use exact method matching
-     * @since 1.1.1
+     * @param methodName Method name of the parent method to call
+     * @param paramType Java class of the parent method's argument (if you wish to use a primitive type, specify the
+     *            corresonding Java wrapper class instead, such as <code>java.lang.Boolean</code> for a
+     *            <code>boolean</code> parameter)
      */
-    public void setExactMatch( boolean useExactMatch )
+    public SetTopRule( String methodName, Class<?> paramType )
     {
-        this.useExactMatch = useExactMatch;
+        super( methodName, paramType );
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public void end( String namespace, String name )
-        throws Exception
+    protected Object getChild()
     {
-        // Identify the objects to be used
-        Object child = getDigester().peek( 0 );
-        Object parent = getDigester().peek( 1 );
-
-        if ( getDigester().getLogger().isDebugEnabled() )
-        {
-            if ( child == null )
-            {
-                getDigester().getLogger().debug( "[SetTopRule]{" + getDigester().getMatch() + "} Call [NULL CHILD]."
-                                                     + methodName + "(" + parent + ")" );
-            }
-            else
-            {
-                getDigester().getLogger().debug( "[SetTopRule]{" + getDigester().getMatch() + "} Call "
-                                                     + child.getClass().getName() + "." + methodName + "(" + parent
-                                                     + ")" );
-            }
-        }
-
-        // Call the specified method
-        Class<?> paramTypes[] = new Class<?>[1];
-        if ( paramType != null )
-        {
-            paramTypes[0] = getDigester().getClassLoader().loadClass( paramType );
-        }
-        else
-        {
-            paramTypes[0] = parent.getClass();
-        }
-
-        if ( useExactMatch )
-        {
-            MethodUtils.invokeExactMethod( child, methodName, new Object[] { parent }, paramTypes );
-        }
-        else
-        {
-            MethodUtils.invokeMethod( child, methodName, new Object[] { parent }, paramTypes );
-        }
+        return getDigester().peek( 1 );
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public String toString()
+    protected Object getParent()
     {
-        return format( "SetTopRule[methodName=%s, paramType=%s]", methodName, paramType );
+        return getDigester().peek( 0 );
     }
 
 }

Modified: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/handlers/AbstractMethodHandler.java
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/handlers/AbstractMethodHandler.java?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/handlers/AbstractMethodHandler.java (original)
+++ commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/handlers/AbstractMethodHandler.java Mon Jun 27 15:44:36 2011
@@ -23,6 +23,7 @@ import static org.apache.commons.digeste
 import static org.apache.commons.digester3.annotations.utils.AnnotationUtils.getAnnotationPattern;
 import static org.apache.commons.digester3.annotations.utils.AnnotationUtils.getAnnotationValue;
 import static org.apache.commons.digester3.annotations.utils.AnnotationUtils.getAnnotationsArrayValue;
+import static org.apache.commons.digester3.annotations.utils.AnnotationUtils.getFireOnBegin;
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
@@ -76,6 +77,7 @@ abstract class AbstractMethodHandler<A e
 
         Class<?>[] explicitTypes = (Class<?>[]) explicitTypesObject;
         Class<?> paramType = element.getParameterTypes()[0];
+        boolean fireOnBegin = getFireOnBegin( annotation );
 
         if ( explicitTypes.length > 0 )
         {
@@ -89,16 +91,16 @@ abstract class AbstractMethodHandler<A e
                     return;
                 }
 
-                doHandle( annotation, element, explicitType, rulesBinder );
+                doHandle( annotation, element, explicitType, fireOnBegin, rulesBinder );
             }
         }
         else
         {
-            doHandle( annotation, element, paramType, rulesBinder );
+            doHandle( annotation, element, paramType, fireOnBegin, rulesBinder );
         }
     }
 
-    private void doHandle( A methodAnnotation, Method method, Class<?> type, RulesBinder rulesBinder )
+    private void doHandle( A methodAnnotation, Method method, Class<?> type, boolean fireOnBegin, RulesBinder rulesBinder )
     {
         if ( type.isInterface() && Modifier.isAbstract( type.getModifiers() ) )
         {
@@ -109,12 +111,12 @@ abstract class AbstractMethodHandler<A e
 
         for ( Annotation annotation : type.getAnnotations() )
         {
-            doHandle( methodAnnotation, annotation, method, type, rulesBinder );
+            doHandle( methodAnnotation, annotation, method, type, fireOnBegin, rulesBinder );
         }
     }
 
     private void doHandle( A methodAnnotation, Annotation annotation, Method method, final Class<?> type,
-                           RulesBinder rulesBinder )
+                           boolean fireOnBegin, RulesBinder rulesBinder )
     {
         if ( annotation.annotationType().isAnnotationPresent( DigesterRule.class )
             && annotation.annotationType().isAnnotationPresent( CreationRule.class ) )
@@ -132,7 +134,7 @@ abstract class AbstractMethodHandler<A e
 
             String pattern = getAnnotationPattern( annotation );
             String namespaceURI = getAnnotationNamespaceURI( annotation );
-            doBind( pattern, namespaceURI, method, type, rulesBinder );
+            doBind( pattern, namespaceURI, method, type, fireOnBegin, rulesBinder );
         }
         else if ( annotation.annotationType().isAnnotationPresent( DigesterRuleList.class ) )
         {
@@ -143,13 +145,13 @@ abstract class AbstractMethodHandler<A e
                 // if it is an annotations array, process them
                 for ( Annotation ptr : annotations )
                 {
-                    doHandle( methodAnnotation, ptr, method, type, rulesBinder );
+                    doHandle( methodAnnotation, ptr, method, type, fireOnBegin, rulesBinder );
                 }
             }
         }
     }
 
     protected abstract void doBind( String pattern, String namespaceURI, Method method, Class<?> type,
-                                    RulesBinder rulesBinder );
+                                    boolean fireOnBegin, RulesBinder rulesBinder );
 
 }

Modified: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/handlers/SetNextHandler.java
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/handlers/SetNextHandler.java?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/handlers/SetNextHandler.java (original)
+++ commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/handlers/SetNextHandler.java Mon Jun 27 15:44:36 2011
@@ -37,12 +37,14 @@ public final class SetNextHandler
      * {@inheritDoc}
      */
     @Override
-    protected void doBind( String pattern, String namespaceURI, Method method, Class<?> type, RulesBinder rulesBinder )
+    protected void doBind( String pattern, String namespaceURI, Method method, Class<?> type, boolean fireOnBegin,
+                           RulesBinder rulesBinder )
     {
         rulesBinder.forPattern( pattern )
                    .withNamespaceURI( namespaceURI )
                    .setNext( method.getName() )
-                   .withParameterType( type );
+                   .withParameterType( type )
+                   .fireOnBegin( fireOnBegin );
     }
 
 }

Modified: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/handlers/SetRootHandler.java
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/handlers/SetRootHandler.java?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/handlers/SetRootHandler.java (original)
+++ commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/handlers/SetRootHandler.java Mon Jun 27 15:44:36 2011
@@ -37,12 +37,14 @@ public final class SetRootHandler
      * {@inheritDoc}
      */
     @Override
-    protected void doBind( String pattern, String namespaceURI, Method method, Class<?> type, RulesBinder rulesBinder )
+    protected void doBind( String pattern, String namespaceURI, Method method, Class<?> type, boolean fireOnBegin,
+                           RulesBinder rulesBinder )
     {
         rulesBinder.forPattern( pattern )
                    .withNamespaceURI( namespaceURI )
                    .setRoot( method.getName() )
-                   .withParameterType( type );
+                   .withParameterType( type )
+                   .fireOnBegin( fireOnBegin );
     }
 
 }

Modified: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/handlers/SetTopHandler.java
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/handlers/SetTopHandler.java?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/handlers/SetTopHandler.java (original)
+++ commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/handlers/SetTopHandler.java Mon Jun 27 15:44:36 2011
@@ -50,7 +50,8 @@ public final class SetTopHandler
             .forPattern( annotation.pattern() )
             .withNamespaceURI( annotation.namespaceURI().length() > 0 ? annotation.namespaceURI() : null )
             .setTop( element.getName() )
-            .withParameterType( element.getParameterTypes()[0] );
+            .withParameterType( element.getParameterTypes()[0] )
+            .fireOnBegin( annotation.fireOnBegin() );
     }
 
 }

Modified: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/rules/SetNext.java
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/rules/SetNext.java?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/rules/SetNext.java (original)
+++ commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/rules/SetNext.java Mon Jun 27 15:44:36 2011
@@ -47,4 +47,9 @@ public @interface SetNext
      */
     Class<?>[] value() default { };
 
+    /**
+     * Marks the rule be invoked when {@code begin} or {@code end} events match.
+     */
+    boolean fireOnBegin() default false;
+
 }

Modified: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/rules/SetRoot.java
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/rules/SetRoot.java?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/rules/SetRoot.java (original)
+++ commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/rules/SetRoot.java Mon Jun 27 15:44:36 2011
@@ -47,4 +47,9 @@ public @interface SetRoot
      */
     Class<?>[] value() default { };
 
+    /**
+     * Marks the rule be invoked when {@code begin} or {@code end} events match.
+     */
+    boolean fireOnBegin() default false;
+
 }

Modified: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/rules/SetTop.java
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/rules/SetTop.java?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/rules/SetTop.java (original)
+++ commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/rules/SetTop.java Mon Jun 27 15:44:36 2011
@@ -49,6 +49,11 @@ public @interface SetTop
     String pattern();
 
     /**
+     * Marks the rule be invoked when {@code begin} or {@code end} events match.
+     */
+    boolean fireOnBegin() default false;
+
+    /**
      * The namespace URI for which this Rule is relevant, if any.
      *
      * @since 3.0

Modified: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/utils/AnnotationUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/utils/AnnotationUtils.java?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/utils/AnnotationUtils.java (original)
+++ commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/annotations/utils/AnnotationUtils.java Mon Jun 27 15:44:36 2011
@@ -47,6 +47,11 @@ public class AnnotationUtils
     private static final String NAMESPACE_URI = "namespaceURI";
 
     /**
+     * The {@code namespaceURI} string constant.
+     */
+    private static final String FIRE_ON_BEGIN = "fireOnBegin";
+
+    /**
      * This class can't be instantiated.
      */
     private AnnotationUtils()
@@ -98,6 +103,22 @@ public class AnnotationUtils
     }
 
     /**
+     * Extract the {@code fireOnBegin()} from annotation.
+     *
+     * @param annotation The annotation has to be introspected
+     * @return The annotation {@code fireOnBegin()}
+     */
+    public static boolean getFireOnBegin( Annotation annotation )
+    {
+        Object ret = invokeAnnotationMethod( annotation, FIRE_ON_BEGIN );
+        if ( ret != null )
+        {
+            return (Boolean) ret;
+        }
+        return false;
+    }
+
+    /**
      * Extract the Annotations array {@code value()} from annotation if present, nul otherwise.
      * 
      * @param annotation the annotation has to be introspected.

Modified: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/binder/AbstractParamTypeBuilder.java
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/binder/AbstractParamTypeBuilder.java?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/binder/AbstractParamTypeBuilder.java (original)
+++ commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/binder/AbstractParamTypeBuilder.java Mon Jun 27 15:44:36 2011
@@ -21,7 +21,7 @@ package org.apache.commons.digester3.bin
 
 import static java.lang.String.format;
 
-import org.apache.commons.digester3.Rule;
+import org.apache.commons.digester3.AbstractMethodRule;
 
 /**
  * Builder chained when invoking {@link LinkedRuleBuilder#setNext(String)},
@@ -29,7 +29,7 @@ import org.apache.commons.digester3.Rule
  *
  * @since 3.0
  */
-abstract class AbstractParamTypeBuilder<R extends Rule>
+public abstract class AbstractParamTypeBuilder<R extends AbstractMethodRule>
     extends AbstractBackToLinkedRuleBuilder<R>
 {
 
@@ -41,6 +41,8 @@ abstract class AbstractParamTypeBuilder<
 
     private Class<?> paramType;
 
+    private boolean fireOnBegin = false;
+
     AbstractParamTypeBuilder( String keyPattern, String namespaceURI, RulesBinder mainBinder,
                               LinkedRuleBuilder mainBuilder, String methodName, ClassLoader classLoader )
     {
@@ -66,6 +68,7 @@ abstract class AbstractParamTypeBuilder<
             reportError( format( ".%s.withParameterType( Class<?> )", methodName ), "NULL Java type not allowed" );
             return this;
         }
+        this.paramType = paramType;
         return withParameterType( paramType.getName() );
     }
 
@@ -87,14 +90,17 @@ abstract class AbstractParamTypeBuilder<
             return this;
         }
 
-        try
-        {
-            this.paramType = classLoader.loadClass( paramType );
-        }
-        catch ( ClassNotFoundException e )
+        if ( this.paramType == null )
         {
-            this.reportError( format( ".%s.withParameterType( Class<?> )", methodName ),
-                              format( "class '%s' cannot be load", paramType ) );
+            try
+            {
+                this.paramType = classLoader.loadClass( paramType );
+            }
+            catch ( ClassNotFoundException e )
+            {
+                this.reportError( format( ".%s.withParameterType( Class<?> )", methodName ),
+                                  format( "class '%s' cannot be load", paramType ) );
+            }
         }
         return this;
     }
@@ -111,6 +117,18 @@ abstract class AbstractParamTypeBuilder<
         return this;
     }
 
+    /**
+     * Marks the rule be invoked when {@code begin} or {@code end} events match.
+     *
+     * @param fireOnBegin true, to invoke the rule at {@code begin}, false for {@code end}
+     * @return this builder instance
+     */
+    public final AbstractParamTypeBuilder<R> fireOnBegin( boolean fireOnBegin )
+    {
+        this.fireOnBegin = fireOnBegin;
+        return this;
+    }
+
     final String getMethodName()
     {
         return methodName;
@@ -126,4 +144,9 @@ abstract class AbstractParamTypeBuilder<
         return useExactMatch;
     }
 
+    final boolean isFireOnBegin()
+    {
+        return fireOnBegin;
+    }
+
 }

Modified: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/binder/SetNextBuilder.java
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/binder/SetNextBuilder.java?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/binder/SetNextBuilder.java (original)
+++ commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/binder/SetNextBuilder.java Mon Jun 27 15:44:36 2011
@@ -46,7 +46,7 @@ public final class SetNextBuilder
 
         if ( getParamType() != null )
         {
-            rule = new SetNextRule( getMethodName(), getParamType().getName() );
+            rule = new SetNextRule( getMethodName(), getParamType() );
         }
         else
         {
@@ -54,6 +54,7 @@ public final class SetNextBuilder
         }
 
         rule.setExactMatch( isUseExactMatch() );
+        rule.setFireOnBegin( isFireOnBegin() );
         return rule;
     }
 

Modified: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/binder/SetRootBuilder.java
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/binder/SetRootBuilder.java?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/binder/SetRootBuilder.java (original)
+++ commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/binder/SetRootBuilder.java Mon Jun 27 15:44:36 2011
@@ -46,7 +46,7 @@ public final class SetRootBuilder
 
         if ( getParamType() != null )
         {
-            rule = new SetRootRule( getMethodName(), getParamType().getName() );
+            rule = new SetRootRule( getMethodName(), getParamType() );
         }
         else
         {
@@ -54,6 +54,7 @@ public final class SetRootBuilder
         }
 
         rule.setExactMatch( isUseExactMatch() );
+        rule.setFireOnBegin( isFireOnBegin() );
         return rule;
     }
 

Modified: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/binder/SetTopBuilder.java
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/binder/SetTopBuilder.java?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/binder/SetTopBuilder.java (original)
+++ commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/binder/SetTopBuilder.java Mon Jun 27 15:44:36 2011
@@ -46,7 +46,7 @@ public final class SetTopBuilder
 
         if ( getParamType() != null )
         {
-            rule = new SetTopRule( getMethodName(), getParamType().getName() );
+            rule = new SetTopRule( getMethodName(), getParamType() );
         }
         else
         {
@@ -54,6 +54,7 @@ public final class SetTopBuilder
         }
 
         rule.setExactMatch( isUseExactMatch() );
+        rule.setFireOnBegin( isFireOnBegin() );
         return rule;
     }
 

Modified: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/xmlrules/AbstractXmlMethodRule.java
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/xmlrules/AbstractXmlMethodRule.java?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/xmlrules/AbstractXmlMethodRule.java (original)
+++ commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/xmlrules/AbstractXmlMethodRule.java Mon Jun 27 15:44:36 2011
@@ -45,8 +45,9 @@ abstract class AbstractXmlMethodRule
         String methodName = attributes.getValue( "methodname" );
         String paramType = attributes.getValue( "paramtype" );
         String exactMatch = attributes.getValue( "exactMatch" );
+        String fireOnBegin = attributes.getValue( "fireOnBegin" );
 
-        bindRule( linkedRuleBuilder, methodName, paramType, "true".equals( exactMatch ) );
+        bindRule( linkedRuleBuilder, methodName, paramType, "true".equals( exactMatch ), "true".equals( fireOnBegin ) );
     }
 
     /**
@@ -54,6 +55,6 @@ abstract class AbstractXmlMethodRule
      * @return
      */
     protected abstract void bindRule( LinkedRuleBuilder linkedRuleBuilder, String methodName, String paramType,
-                                      boolean exactMatch );
+                                      boolean exactMatch, boolean fireOnBegin );
 
 }

Modified: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/xmlrules/SetNextRule.java
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/xmlrules/SetNextRule.java?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/xmlrules/SetNextRule.java (original)
+++ commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/xmlrules/SetNextRule.java Mon Jun 27 15:44:36 2011
@@ -44,7 +44,7 @@ final class SetNextRule
      */
     @Override
     protected void bindRule( LinkedRuleBuilder linkedRuleBuilder, String methodName, String paramType,
-                             boolean exactMatch )
+                             boolean exactMatch, boolean fireOnBegin )
     {
         SetNextBuilder builder = linkedRuleBuilder.setNext( methodName );
 
@@ -54,6 +54,7 @@ final class SetNextRule
         }
 
         builder.useExactMatch( exactMatch );
+        builder.fireOnBegin( fireOnBegin );
     }
 
 }

Modified: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/xmlrules/SetRootRule.java
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/xmlrules/SetRootRule.java?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/xmlrules/SetRootRule.java (original)
+++ commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/xmlrules/SetRootRule.java Mon Jun 27 15:44:36 2011
@@ -44,7 +44,7 @@ final class SetRootRule
      */
     @Override
     protected void bindRule( LinkedRuleBuilder linkedRuleBuilder, String methodName, String paramType,
-                             boolean exactMatch )
+                             boolean exactMatch, boolean fireOnBegin )
     {
         SetRootBuilder builder = linkedRuleBuilder.setRoot( methodName );
 
@@ -54,6 +54,7 @@ final class SetRootRule
         }
 
         builder.useExactMatch( exactMatch );
+        builder.fireOnBegin( fireOnBegin );
     }
 
 }

Modified: commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/xmlrules/SetTopRule.java
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/xmlrules/SetTopRule.java?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/xmlrules/SetTopRule.java (original)
+++ commons/proper/digester/trunk/src/main/java/org/apache/commons/digester3/xmlrules/SetTopRule.java Mon Jun 27 15:44:36 2011
@@ -44,7 +44,7 @@ final class SetTopRule
      */
     @Override
     protected void bindRule( LinkedRuleBuilder linkedRuleBuilder, String methodName, String paramType,
-                             boolean exactMatch )
+                             boolean exactMatch, boolean fireOnBegin )
     {
         SetTopBuilder builder = linkedRuleBuilder.setTop( methodName );
 
@@ -54,6 +54,7 @@ final class SetTopRule
         }
 
         builder.useExactMatch( exactMatch );
+        builder.fireOnBegin( fireOnBegin );
     }
 
 }

Modified: commons/proper/digester/trunk/src/main/resources/org/apache/commons/digester3/xmlrules/digester-rules.dtd
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/main/resources/org/apache/commons/digester3/xmlrules/digester-rules.dtd?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/main/resources/org/apache/commons/digester3/xmlrules/digester-rules.dtd (original)
+++ commons/proper/digester/trunk/src/main/resources/org/apache/commons/digester3/xmlrules/digester-rules.dtd Mon Jun 27 15:44:36 2011
@@ -218,23 +218,26 @@
 <!-- SetTopRule -->
 <!ELEMENT set-top-rule EMPTY>
 <!ATTLIST set-top-rule
-    pattern    CDATA #IMPLIED
-    methodname CDATA #REQUIRED
-    paramtype  CDATA #IMPLIED
-    exactMatch CDATA #IMPLIED>
+    pattern     CDATA #IMPLIED
+    methodname  CDATA #REQUIRED
+    paramtype   CDATA #IMPLIED
+    exactMatch  CDATA #IMPLIED
+    fireOnBegin CDATA #IMPLIED>
 
 <!-- SetNextRule -->
 <!ELEMENT set-next-rule EMPTY>
 <!ATTLIST set-next-rule
-    pattern    CDATA #IMPLIED
-    methodname CDATA #REQUIRED
-    paramtype  CDATA #IMPLIED
-    exactMatch CDATA #IMPLIED>
+    pattern     CDATA #IMPLIED
+    methodname  CDATA #REQUIRED
+    paramtype   CDATA #IMPLIED
+    exactMatch  CDATA #IMPLIED
+    fireOnBegin CDATA #IMPLIED>
 
 <!-- SetRootRule -->
 <!ELEMENT set-root-rule EMPTY>
 <!ATTLIST set-root-rule
-    pattern    CDATA #IMPLIED
-    methodname CDATA #REQUIRED
-    paramtype  CDATA #IMPLIED
-    exactMatch CDATA #IMPLIED>
+    pattern     CDATA #IMPLIED
+    methodname  CDATA #REQUIRED
+    paramtype   CDATA #IMPLIED
+    exactMatch  CDATA #IMPLIED
+    fireOnBegin CDATA #IMPLIED>

Modified: commons/proper/digester/trunk/src/site/resources/dtds/digester-rules-3.0.dtd
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/site/resources/dtds/digester-rules-3.0.dtd?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/site/resources/dtds/digester-rules-3.0.dtd (original)
+++ commons/proper/digester/trunk/src/site/resources/dtds/digester-rules-3.0.dtd Mon Jun 27 15:44:36 2011
@@ -218,23 +218,26 @@
 <!-- SetTopRule -->
 <!ELEMENT set-top-rule EMPTY>
 <!ATTLIST set-top-rule
-    pattern    CDATA #IMPLIED
-    methodname CDATA #REQUIRED
-    paramtype  CDATA #IMPLIED
-    exactMatch CDATA #IMPLIED>
+    pattern     CDATA #IMPLIED
+    methodname  CDATA #REQUIRED
+    paramtype   CDATA #IMPLIED
+    exactMatch  CDATA #IMPLIED
+    fireOnBegin CDATA #IMPLIED>
 
 <!-- SetNextRule -->
 <!ELEMENT set-next-rule EMPTY>
 <!ATTLIST set-next-rule
-    pattern    CDATA #IMPLIED
-    methodname CDATA #REQUIRED
-    paramtype  CDATA #IMPLIED
-    exactMatch CDATA #IMPLIED>
+    pattern     CDATA #IMPLIED
+    methodname  CDATA #REQUIRED
+    paramtype   CDATA #IMPLIED
+    exactMatch  CDATA #IMPLIED
+    fireOnBegin CDATA #IMPLIED>
 
 <!-- SetRootRule -->
 <!ELEMENT set-root-rule EMPTY>
 <!ATTLIST set-root-rule
-    pattern    CDATA #IMPLIED
-    methodname CDATA #REQUIRED
-    paramtype  CDATA #IMPLIED
-    exactMatch CDATA #IMPLIED>
+    pattern     CDATA #IMPLIED
+    methodname  CDATA #REQUIRED
+    paramtype   CDATA #IMPLIED
+    exactMatch  CDATA #IMPLIED
+    fireOnBegin CDATA #IMPLIED>

Modified: commons/proper/digester/trunk/src/test/java/org/apache/commons/digester3/annotations/addressbook/Person.java
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/test/java/org/apache/commons/digester3/annotations/addressbook/Person.java?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/test/java/org/apache/commons/digester3/annotations/addressbook/Person.java (original)
+++ commons/proper/digester/trunk/src/test/java/org/apache/commons/digester3/annotations/addressbook/Person.java Mon Jun 27 15:44:36 2011
@@ -96,7 +96,7 @@ public class Person
         this.emails.put( type, address );
     }
 
-    @SetNext
+    @SetNext( fireOnBegin = true )
     public void addAddress( Address addr )
     {
         this.addresses.add( addr );

Modified: commons/proper/digester/trunk/src/test/resources/org/apache/commons/digester3/xmlrules/atom-rules.xml
URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/test/resources/org/apache/commons/digester3/xmlrules/atom-rules.xml?rev=1140212&r1=1140211&r2=1140212&view=diff
==============================================================================
--- commons/proper/digester/trunk/src/test/resources/org/apache/commons/digester3/xmlrules/atom-rules.xml (original)
+++ commons/proper/digester/trunk/src/test/resources/org/apache/commons/digester3/xmlrules/atom-rules.xml Mon Jun 27 15:44:36 2011
@@ -35,7 +35,7 @@
       <set-properties-rule pattern="link">
         <alias attr-name="href" prop-name="link" />
       </set-properties-rule>
-      <set-next-rule methodname="addEntry" />
+      <set-next-rule methodname="addEntry" fireOnBegin="true" />
     </pattern>
   </pattern>
 </digester-rules>