commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From skitch...@apache.org
Subject svn commit: r151287 [5/7] - in jakarta/commons/proper/digester/branches/digester2: ./ src/ src/conf/ src/examples/ src/examples/api/ src/examples/api/addressbook/ src/java/ src/java/org/ src/java/org/apache/ src/java/org/apache/commons/ src/java/org/apache/commons/digester2/ src/java/org/apache/commons/digester2/actions/ src/java/org/apache/commons/digester2/factory/ src/media/ src/test/ src/test/org/ src/test/org/apache/ src/test/org/apache/commons/ src/test/org/apache/commons/digester2/ xdocs/ xdocs/dtds/ xdocs/images/ xdocs/style/
Date Fri, 04 Feb 2005 01:51:54 GMT
Added: jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/CallParamAction.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/CallParamAction.java?view=auto&rev=151287
==============================================================================
--- jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/CallParamAction.java (added)
+++ jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/CallParamAction.java Thu Feb  3 17:51:43 2005
@@ -0,0 +1,233 @@
+/* $Id: $
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */ 
+
+
+package org.apache.commons.digester2.actions;
+
+import org.xml.sax.Attributes;
+
+import org.apache.commons.collections.ArrayStack;
+import org.apache.commons.logging.Log;
+
+import org.apache.commons.digester2.Context;
+import org.apache.commons.digester2.AbstractAction;
+import org.apache.commons.digester2.ParseException;
+
+/**
+ * <p>Action which saves a parameter for use by a surrounding 
+ * <code>ActionCallMethod<code>.</p>
+ *
+ * <p>This parameter may be:
+ * <ul>
+ * <li>from an attribute of the current element
+ * See {@link #CallParamAction(int paramIndex, String attributeName)}
+ * <li>from current the element body
+ * See {@link #CallParamAction(int paramIndex)}
+ * <li>from the top object on the stack. 
+ * See {@link #CallParamAction(int paramIndex, boolean fromStack)}
+ * <li>the current path being processed (separate <code>Rule</code>). 
+ * See {@link ActionPathCallParam}
+ * </ul>
+ * </p>
+ */
+
+public class CallParamAction extends AbstractAction {
+
+    // ----------------------------------------------------------- Constructors
+
+
+    /**
+     * Construct a "call parameter" rule that will save the body text of this
+     * element as the parameter value.
+     *
+     * @param paramIndex The zero-relative parameter number
+     */
+    public CallParamAction(int paramIndex) {
+        this(paramIndex, null);
+    }
+
+
+    /**
+     * Construct a "call parameter" rule that will save the value of the
+     * specified attribute as the parameter value.
+     *
+     * @param paramIndex The zero-relative parameter number
+     * @param attributeName The name of the attribute to save
+     */
+    public CallParamAction(int paramIndex,
+                         String attributeName) {
+
+        this.paramIndex = paramIndex;
+        this.attributeName = attributeName;
+
+    }
+
+
+    /**
+     * Construct a "call parameter" rule.
+     *
+     * @param paramIndex The zero-relative parameter number
+     * @param fromStack should this parameter be taken from the top of the stack?
+     */    
+    public CallParamAction(int paramIndex, boolean fromStack) {
+    
+        this.paramIndex = paramIndex;  
+        this.fromStack = fromStack;
+
+    }
+    
+    /**
+     * Constructs a "call parameter" rule which sets a parameter from the stack.
+     * If the stack contains too few objects, then the parameter will be set to null.
+     *
+     * @param paramIndex The zero-relative parameter number
+     * @param stackIndex the index of the object which will be passed as a parameter. 
+     * The zeroth object is the top of the stack, 1 is the next object down and so on.
+     */    
+    public CallParamAction(int paramIndex, int stackIndex) {
+    
+        this.paramIndex = paramIndex;  
+        this.fromStack = true;
+        this.stackIndex = stackIndex;
+    }
+ 
+    // ----------------------------------------------------- Instance Variables
+
+
+    /**
+     * The attribute from which to save the parameter value
+     */
+    protected String attributeName = null;
+
+
+    /**
+     * The zero-relative index of the parameter we are saving.
+     */
+    protected int paramIndex = 0;
+
+
+    /**
+     * Is the parameter to be set from the stack?
+     */
+    protected boolean fromStack = false;
+    
+    /**
+     * The position of the object from the top of the stack
+     */
+    protected int stackIndex = 0;
+
+    /** 
+     * Stack is used to allow nested body text to be processed.
+     * Lazy creation.
+     */
+    protected ArrayStack bodyTextStack;
+
+    // --------------------------------------------------------- Public Methods
+
+
+    /**
+     * Process the start of this element.
+     *
+     * @param attributes The attribute list for this element
+     */
+    public void begin(Context context, String namespace, String name, Attributes attributes) 
+    throws ParseException {
+
+        Object param = null;
+        
+        if (attributeName != null) {
+        
+            param = attributes.getValue(attributeName);
+            
+        } else if(fromStack) {
+        
+            param = context.peek(stackIndex);
+            
+            Log log = context.getLogger();
+            if (log.isDebugEnabled()) {
+            
+                StringBuffer sb = new StringBuffer("[CallParamAction]{");
+                sb.append(context.getMatchPath());
+                sb.append("} Save from stack; from stack?").append(fromStack);
+                sb.append("; object=").append(param);
+                log.debug(sb.toString());
+            }   
+        }
+        
+        // Have to save the param object to the param stack frame here.
+        // Can't wait until end(). Otherwise, the object will be lost.
+        // We can't save the object as instance variables, as 
+        // the instance variables will be overwritten
+        // if this CallParamAction is reused in subsequent nesting.
+        
+        if(param != null) {
+            Object parameters[] = (Object[]) context.peekParams();
+            parameters[paramIndex] = param;
+        }
+    }
+
+
+    /**
+     * Process the body text of this element.
+     *
+     * @param bodyText The body text of this element
+     */
+    public void body(Context context, String namespace, String name, String bodyText) 
+    throws ParseException {
+
+        if (attributeName == null && !fromStack) {
+            // We must wait to set the parameter until end
+            // so that we can make sure that the right set of parameters
+            // is at the top of the stack
+            if (bodyTextStack == null) {
+                bodyTextStack = new ArrayStack();
+            }
+            bodyTextStack.push(bodyText.trim());
+        }
+
+    }
+    
+    /**
+     * Process any body texts now.
+     */
+    public void end(Context context, String namespace, String name) {
+        if (bodyTextStack != null && !bodyTextStack.empty()) {
+            // what we do now is push one parameter onto the top set of parameters
+            Object parameters[] = (Object[]) context.peekParams();
+            parameters[paramIndex] = bodyTextStack.pop();
+        }
+    }
+
+    /**
+     * Render a printable version of this Rule.
+     */
+    public String toString() {
+
+        StringBuffer sb = new StringBuffer("CallParamAction[");
+        sb.append("paramIndex=");
+        sb.append(paramIndex);
+        sb.append(", attributeName=");
+        sb.append(attributeName);
+        sb.append(", from stack=");
+        sb.append(fromStack);
+        sb.append("]");
+        return (sb.toString());
+
+    }
+
+
+}

Added: jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/CreateObjectAction.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/CreateObjectAction.java?view=auto&rev=151287
==============================================================================
--- jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/CreateObjectAction.java (added)
+++ jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/CreateObjectAction.java Thu Feb  3 17:51:43 2005
@@ -0,0 +1,182 @@
+/* $Id: $
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */ 
+
+
+package org.apache.commons.digester2.actions;
+
+
+import org.xml.sax.Attributes;
+import org.apache.commons.logging.Log;
+
+
+import org.apache.commons.digester2.Context;
+import org.apache.commons.digester2.AbstractAction;
+import org.apache.commons.digester2.ParseException;
+
+/**
+ * Rule implementation that creates a new object and pushes it
+ * onto the object stack.  When the element is complete, the
+ * object will be popped
+ */
+
+public class CreateObjectAction extends AbstractAction {
+
+    // ----------------------------------------------------------- Constructors
+
+    /**
+     * Construct an object create rule with the specified class name.
+     *
+     * @param className Java class name of the object to be created
+     */
+    public CreateObjectAction(String className) {
+
+        this(className, (String) null);
+
+    }
+
+
+    /**
+     * Construct an object create rule with the specified class.
+     *
+     * @param clazz Java class name of the object to be created
+     */
+    public CreateObjectAction(Class clazz) {
+
+        this(clazz.getName(), (String) null);
+
+    }
+
+
+    /**
+     * Construct an object create rule with the specified class name and an
+     * optional attribute name containing an override.
+     *
+     * @param className Java class name of the object to be created
+     * @param attributeName Attribute name which, if present, contains an
+     *  override of the class name to create
+     */
+    public CreateObjectAction(String className,
+                            String attributeName) {
+
+        this.className = className;
+        this.attributeName = attributeName;
+
+    }
+
+
+    /**
+     * Construct an object create rule with the specified class and an
+     * optional attribute name containing an override.
+     *
+     * @param attributeName Attribute name which, if present, contains an
+     * @param clazz Java class name of the object to be created
+     *  override of the class name to create
+     */
+    public CreateObjectAction(String attributeName,
+                            Class clazz) {
+
+        this(clazz.getName(), attributeName);
+
+    }
+
+    // ----------------------------------------------------- Instance Variables
+
+
+    /**
+     * The attribute containing an override class name if it is present.
+     */
+    protected String attributeName = null;
+
+
+    /**
+     * The Java class name of the object to be created.
+     */
+    protected String className = null;
+
+
+    // --------------------------------------------------------- Public Methods
+
+
+    /**
+     * Process the beginning of this element.
+     *
+     * @param attributes The attribute list of this element
+     */
+    public void begin(Context context, String namespace, String name, Attributes attributes) 
+    throws ParseException {
+
+        // Identify the name of the class to instantiate
+        String realClassName = className;
+        if (attributeName != null) {
+            String value = attributes.getValue(attributeName);
+            if (value != null) {
+                realClassName = value;
+            }
+        }
+        
+        Log log = context.getLogger();
+        if (log.isDebugEnabled()) {
+            log.debug("[CreateObjectAction]{" + context.getMatchPath() +
+                    "}New " + realClassName);
+        }
+
+        // Instantiate the new object and push it on the context stack
+        try {
+            Class clazz = context.getClassLoader().loadClass(realClassName);
+            Object instance = clazz.newInstance();
+            context.push(instance);
+        } catch(Exception ex) {
+            throw new ParseException(
+                "Unable to create instance of class '" + realClassName + "'",
+                ex);
+        }
+    }
+
+
+    /**
+     * Process the end of this element.
+     */
+    public void end(Context context, String namespace, String name) 
+    throws ParseException {
+
+        Object top = context.pop();
+        Log log = context.getLogger();
+        if (log.isDebugEnabled()) {
+            log.debug("[CreateObjectAction]{" + context.getMatchPath() +
+                    "} Pop " + top.getClass().getName());
+        }
+
+    }
+
+
+    /**
+     * Render a printable version of this Rule.
+     */
+    public String toString() {
+
+        StringBuffer sb = new StringBuffer("CreateObjectAction[");
+        sb.append("className=");
+        sb.append(className);
+        sb.append(", attributeName=");
+        sb.append(attributeName);
+        sb.append("]");
+        return (sb.toString());
+
+    }
+
+
+}

Added: jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/CreateObjectWithFactoryAction.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/CreateObjectWithFactoryAction.java?view=auto&rev=151287
==============================================================================
--- jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/CreateObjectWithFactoryAction.java (added)
+++ jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/CreateObjectWithFactoryAction.java Thu Feb  3 17:51:43 2005
@@ -0,0 +1,397 @@
+/* $Id: $
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */ 
+
+
+package org.apache.commons.digester2.actions;
+
+import org.xml.sax.Attributes;
+
+import org.apache.commons.logging.Log;
+
+import org.apache.commons.digester2.Context;
+import org.apache.commons.digester2.AbstractAction;
+import org.apache.commons.digester2.ParseException;
+import org.apache.commons.digester2.ArrayStack;
+
+/**
+ * <p>Rule implementation that uses an {@link ObjectCreationFactory} to create
+ * a new object which it pushes onto the object stack.  When the element is
+ * complete, the object will be popped.</p>
+ *
+ * <p>This rule is intended in situations where the element's attributes are
+ * needed before the object can be created.  A common scenario is for the
+ * ObjectCreationFactory implementation to use the attributes  as parameters
+ * in a call to either a factory method or to a non-empty constructor.
+ */
+
+public class CreateObjectWithFactoryAction extends AbstractAction {
+
+    // ----------------------------------------------------------- Fields
+    
+    /** Should exceptions thrown by the factory be ignored? */
+    private boolean ignoreCreateExceptions;
+    /** Stock to manage */
+    private ArrayStack exceptionIgnoredStack;
+
+    // ----------------------------------------------------------- Constructors
+
+    /**
+     * <p>Construct a factory create rule that will use the specified
+     * class name to create an {@link ObjectCreationFactory} which will
+     * then be used to create an object and push it on the stack.</p>
+     *
+     * <p>Exceptions thrown during the object creation process will be propagated.</p>
+     *
+     * @param className Java class name of the object creation factory class
+     */
+    public CreateObjectWithFactoryAction(String className) {
+        this(className, false);
+    }
+
+    /**
+     * <p>Construct a factory create rule that will use the specified
+     * class to create an {@link ObjectCreationFactory} which will
+     * then be used to create an object and push it on the stack.</p>
+     *
+     * <p>Exceptions thrown during the object creation process will be propagated.</p>
+     *
+     * @param clazz Java class name of the object creation factory class
+     */
+    public CreateObjectWithFactoryAction(Class clazz) {
+        this(clazz, false);
+    }
+
+    /**
+     * <p>Construct a factory create rule that will use the specified
+     * class name (possibly overridden by the specified attribute if present)
+     * to create an {@link ObjectCreationFactory}, which will then be used
+     * to instantiate an object instance and push it onto the stack.</p>
+     *
+     * <p>Exceptions thrown during the object creation process will be propagated.</p>
+     *
+     * @param className Default Java class name of the factory class
+     * @param attributeName Attribute name which, if present, contains an
+     *  override of the class name of the object creation factory to create.
+     */
+    public CreateObjectWithFactoryAction(String className, String attributeName) {
+        this(className, attributeName, false);
+    }
+
+    /**
+     * <p>Construct a factory create rule that will use the specified
+     * class (possibly overridden by the specified attribute if present)
+     * to create an {@link ObjectCreationFactory}, which will then be used
+     * to instantiate an object instance and push it onto the stack.</p>
+     *
+     * <p>Exceptions thrown during the object creation process will be propagated.</p>
+     *
+     * @param clazz Default Java class name of the factory class
+     * @param attributeName Attribute name which, if present, contains an
+     *  override of the class name of the object creation factory to create.
+     */
+    public CreateObjectWithFactoryAction(Class clazz, String attributeName) {
+        this(clazz, attributeName, false);
+    }
+
+    /**
+     * <p>Construct a factory create rule using the given, already instantiated,
+     * {@link ObjectCreationFactory}.</p>
+     *
+     * <p>Exceptions thrown during the object creation process will be propagated.</p>
+     *
+     * @param creationFactory called on to create the object.
+     */
+    public CreateObjectWithFactoryAction(ObjectCreationFactory creationFactory) {
+        this(creationFactory, false);
+    }
+    
+    /**
+     * Construct a factory create rule that will use the specified
+     * class name to create an {@link ObjectCreationFactory} which will
+     * then be used to create an object and push it on the stack.
+     *
+     * @param className Java class name of the object creation factory class
+     * @param ignoreCreateExceptions if true, exceptions thrown by the object
+     *  creation factory
+     * will be ignored.
+     */
+    public CreateObjectWithFactoryAction(String className, boolean ignoreCreateExceptions) {
+        this(className, null, ignoreCreateExceptions);
+    }
+
+    /**
+     * Construct a factory create rule that will use the specified
+     * class to create an {@link ObjectCreationFactory} which will
+     * then be used to create an object and push it on the stack.
+     *
+     * @param clazz Java class name of the object creation factory class
+     * @param ignoreCreateExceptions if true, exceptions thrown by the
+     *  object creation factory
+     * will be ignored.
+     */
+    public CreateObjectWithFactoryAction(Class clazz, boolean ignoreCreateExceptions) {
+        this(clazz, null, ignoreCreateExceptions);
+    }
+
+    /**
+     * Construct a factory create rule that will use the specified
+     * class name (possibly overridden by the specified attribute if present)
+     * to create an {@link ObjectCreationFactory}, which will then be used
+     * to instantiate an object instance and push it onto the stack.
+     *
+     * @param className Default Java class name of the factory class
+     * @param attributeName Attribute name which, if present, contains an
+     *  override of the class name of the object creation factory to create.
+     * @param ignoreCreateExceptions if true, exceptions thrown by the object
+     *  creation factory will be ignored.
+     */
+    public CreateObjectWithFactoryAction(
+                                String className, 
+                                String attributeName,
+                                boolean ignoreCreateExceptions) {
+
+        this.className = className;
+        this.attributeName = attributeName;
+        this.ignoreCreateExceptions = ignoreCreateExceptions;
+
+    }
+
+
+    /**
+     * Construct a factory create rule that will use the specified
+     * class (possibly overridden by the specified attribute if present)
+     * to create an {@link ObjectCreationFactory}, which will then be used
+     * to instantiate an object instance and push it onto the stack.
+     *
+     * @param clazz Default Java class name of the factory class
+     * @param attributeName Attribute name which, if present, contains an
+     *  override of the class name of the object creation factory to create.
+     * @param ignoreCreateExceptions if true, exceptions thrown by the object
+     *  creation factory will be ignored.
+     */
+    public CreateObjectWithFactoryAction(
+                                Class clazz, 
+                                String attributeName,
+                                boolean ignoreCreateExceptions) {
+
+        this(clazz.getName(), attributeName, ignoreCreateExceptions);
+
+    }
+
+
+    /**
+     * Construct a factory create rule using the given, already instantiated,
+     * {@link ObjectCreationFactory}.
+     *
+     * @param creationFactory called on to create the object.
+     * @param ignoreCreateExceptions if true, exceptions thrown by the object
+     *  creation factory will be ignored.
+     */
+    public CreateObjectWithFactoryAction(
+                            ObjectCreationFactory creationFactory, 
+                            boolean ignoreCreateExceptions) {
+
+        this.creationFactory = creationFactory;
+        this.ignoreCreateExceptions = ignoreCreateExceptions;
+    }
+
+    // ----------------------------------------------------- Instance Variables
+
+
+    /**
+     * The attribute containing an override class name if it is present.
+     */
+    protected String attributeName = null;
+
+
+    /**
+     * The Java class name of the ObjectCreationFactory to be created.
+     * This class must have a no-arguments constructor.
+     */
+    protected String className = null;
+
+
+    /**
+     * The object creation factory we will use to instantiate objects
+     * as required based on the attributes specified in the matched XML
+     * element.
+     */
+    protected ObjectCreationFactory creationFactory = null;
+
+
+    // --------------------------------------------------------- Public Methods
+
+
+    /**
+     * Process the beginning of this element.
+     *
+     * @param attributes The attribute list of this element
+     */
+    public void begin(
+    Context context, String namespace, String name, Attributes attributes) 
+    throws ParseException {
+        
+        Log log = context.getLogger();
+        
+        if (ignoreCreateExceptions) {
+        
+            if (exceptionIgnoredStack == null) {
+                exceptionIgnoredStack = new ArrayStack();
+            }
+            
+            try {
+                Object instance = 
+                    getFactory(context, attributes).createObject(context, attributes);
+                
+                if (log.isDebugEnabled()) {
+                    log.debug("[CreateObjectWithFactoryAction]{" + context.getMatchPath() +
+                            "} New " + instance.getClass().getName());
+                }
+                context.push(instance);
+                exceptionIgnoredStack.push(Boolean.FALSE);
+                
+            } catch (Exception e) {
+                // log message and error
+                if (log.isInfoEnabled()) {
+                    log.info("[CreateObjectWithFactoryAction] Create exception ignored: " +
+                        ((e.getMessage() == null) ? e.getClass().getName() : e.getMessage()));
+                    if (log.isDebugEnabled()) {
+                        log.debug("[CreateObjectWithFactoryAction] Ignored exception:", e);
+                    }
+                }
+                exceptionIgnoredStack.push(Boolean.TRUE);
+            }
+            
+        } else {
+            Object instance = getFactory(context, attributes).createObject(context, attributes);
+            
+            if (log.isDebugEnabled()) {
+                log.debug("[CreateObjectWithFactoryAction]{" + context.getMatchPath() +
+                        "} New " + instance.getClass().getName());
+            }
+            context.push(instance);
+        }
+    }
+
+
+    /**
+     * Process the end of this element.
+     */
+    public void end(
+    Context context, String namespace, String name) 
+    throws ParseException {
+        
+        Log log = context.getLogger();
+
+        // check if object was created 
+        // this only happens if an exception was thrown and we're ignoring them
+        if (	
+                ignoreCreateExceptions &&
+                exceptionIgnoredStack != null &&
+                !(exceptionIgnoredStack.empty())) {
+                
+            if (((Boolean) exceptionIgnoredStack.pop()).booleanValue()) {
+                // creation exception was ignored
+                // nothing was put onto the stack
+                if (log.isTraceEnabled()) {
+                    log.trace("[CreateObjectWithFactoryAction] No creation so no push so no pop");
+                }
+                return;
+            }
+        } 
+
+        Object top = context.pop();
+        if (log.isDebugEnabled()) {
+            log.debug("[CreateObjectWithFactoryAction]{" + context.getMatchPath() +
+                    "} Pop " + top.getClass().getName());
+        }
+
+    }
+
+
+    /**
+     * Clean up after parsing is complete.
+     */
+    public void finishParse() throws ParseException {
+        if (attributeName != null) {
+            creationFactory = null;
+        }
+    }
+
+    /**
+     * Render a printable version of this Rule.
+     */
+    public String toString() {
+
+        StringBuffer sb = new StringBuffer("CreateObjectWithFactoryAction[");
+        sb.append("className=");
+        sb.append(className);
+        sb.append(", attributeName=");
+        sb.append(attributeName);
+        if (creationFactory != null) {
+            sb.append(", creationFactory=");
+            sb.append(creationFactory);
+        }
+        sb.append("]");
+        return (sb.toString());
+
+    }
+
+
+    // ------------------------------------------------------ Protected Methods
+
+    /**
+     * Return an instance of our associated object creation factory,
+     * creating one if necessary.
+     *
+     * @param attributes Attributes passed to our factory creation element
+     *
+     * @exception Exception if any error occurs
+     */
+    protected ObjectCreationFactory getFactory(
+    Context context, Attributes attributes)
+    throws ParseException {
+
+        Log log = context.getLogger();
+
+        if (creationFactory == null) {
+            String realClassName = className;
+            if (attributeName != null) {
+                String value = attributes.getValue(attributeName);
+                if (value != null) {
+                    realClassName = value;
+                }
+            }
+            if (log.isDebugEnabled()) {
+                log.debug("[CreateObjectWithFactoryAction]{" + context.getMatchPath() +
+                        "} New factory " + realClassName);
+            }
+            try {
+            Class clazz = context.getClassLoader().loadClass(realClassName);
+            creationFactory = (ObjectCreationFactory)
+                    clazz.newInstance();
+            } catch(ClassNotFoundException ex) {
+                throw new ParseException("Unable to load class '" + realClassName + "'", ex);
+            } catch(InstantiationException ex) {
+                throw new ParseException("Unable to create instance of class '" + realClassName + "'", ex);
+            } catch(IllegalAccessException ex) {
+                throw new ParseException("Unable to access constructor of class '" + realClassName + "'", ex);
+            }
+        }
+        return creationFactory;
+    }    
+}

Added: jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/NodeCreateAction.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/NodeCreateAction.java?view=auto&rev=151287
==============================================================================
--- jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/NodeCreateAction.java (added)
+++ jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/NodeCreateAction.java Thu Feb  3 17:51:43 2005
@@ -0,0 +1,446 @@
+/* $Id: $
+ *
+ * Copyright 2002-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */ 
+
+
+package org.apache.commons.digester2.actions;
+
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+
+
+import org.apache.commons.digester2.Context;
+import org.apache.commons.digester2.AbstractAction;
+import org.apache.commons.digester2.ParseException;
+import org.apache.commons.digester2.SAXHandler;
+
+/**
+ * A rule implementation that creates a DOM
+ * {@link org.w3c.dom.Node Node} containing the XML at the element that matched
+ * the rule. Two concrete types of nodes can be created by this rule:
+ * <ul>
+ *   <li>the default is to create an {@link org.w3c.dom.Element Element} node.
+ *   The created element will correspond to the element that matched the rule,
+ *   containing all XML content underneath that element.</li>
+ *   <li>alternatively, this rule can create nodes of type
+ *   {@link org.w3c.dom.DocumentFragment DocumentFragment}, which will contain
+ *   only the XML content under the element the rule was trigged on.</li>
+ * </ul>
+ * The created node will be normalized, meaning it will not contain text nodes 
+ * that only contain white space characters.
+ * 
+
+ * 
+ * <p>The created <code>Node</code> will be pushed on Digester's object stack
+ * when done. To use it in the context of another DOM
+ * {@link org.w3c.dom.Document Document}, it must be imported first, using the
+ * Document method
+ * {@link org.w3c.dom.Document#importNode(org.w3c.dom.Node, boolean) importNode()}.
+ * </p>
+ *
+ * <p><strong>Important Note:</strong> This is implemented by replacing the SAX
+ * {@link org.xml.sax.ContentHandler ContentHandler} in the parser used by 
+ * Digester, and resetting it when the matched element is closed. As a side 
+ * effect, rules that would match XML nodes under the element that matches 
+ * a <code>NodeCreateAction</code> will never be triggered by Digester, which 
+ * usually is the behavior one would expect.</p>
+ * 
+ * <p><strong>Note</strong> that the current implementation does not set the namespace prefixes
+ * in the exported nodes. The (usually more important) namespace URIs are set,
+ * of course.</p>
+ *
+ * @since Digester 1.4
+ */
+
+public class NodeCreateAction extends AbstractAction {
+
+
+    // ---------------------------------------------------------- Inner Classes
+
+
+    /**
+     * The SAX content handler that does all the actual work of assembling the 
+     * DOM node tree from the SAX events.
+     */
+    private class NodeBuilder
+        extends DefaultHandler {
+
+
+        // ------------------------------------------------------- Constructors
+
+
+        /**
+         * Constructor.
+         * 
+         * <p>Stores the content handler currently used by Digester so it can 
+         * be reset when done, and initializes the DOM objects needed to 
+         * build the node.</p>
+         * 
+         * @param doc the document to use to create nodes
+         * @param root the root node
+         * @throws ParserConfigurationException if the DocumentBuilderFactory 
+         *   could not be instantiated
+         * @throws SAXException if the XMLReader could not be instantiated by 
+         *   Digester (should not happen)
+         */
+        public NodeBuilder(Context context, Document doc, Node root)
+        throws SAXException {
+
+            this.doc = doc;
+            this.root = root;
+            this.top = root;
+            
+            oldSaxHandler = context.getSAXHandler();
+            oldContext = context;
+            reader = oldSaxHandler.getXMLReader();
+            // assert oldReader.getContentHandler() == oldSaxHandler
+        }
+
+
+        // ------------------------------------------------- Instance Variables
+
+
+        /**
+         * The content handler used by Digester before it was set to this 
+         * content handler.
+         */
+        protected SAXHandler oldSaxHandler = null;
+
+        /**
+         * The parsing context currently in use.
+         */
+        protected Context oldContext = null;
+        
+        /**
+         * The XMLReader being used to parse the input xml.
+         */
+        protected XMLReader reader;
+
+        /**
+         * Depth of the current node, relative to the element where the content
+         * handler was put into action.
+         */
+        protected int depth = 0;
+
+
+        /**
+         * A DOM Document used to create the various Node instances.
+         */
+        protected Document doc = null;
+
+
+        /**
+         * The DOM node that will be pushed on Digester's stack.
+         */
+        protected Node root = null;
+
+
+        /**
+         * The current top DOM mode.
+         */
+        protected Node top = null;
+
+
+        // --------------------------------------------- ContentHandler Methods
+
+
+        /**
+         * Appends a {@link org.w3c.dom.Text Text} node to the current node.
+         * 
+         * @param ch the characters from the XML document
+         * @param start the start position in the array
+         * @param length the number of characters to read from the array
+         * @throws SAXException if the DOM implementation throws an exception
+         */
+        public void characters(char[] ch, int start, int length)
+            throws SAXException {
+
+            try {
+                String str = new String(ch, start, length);
+                if (str.trim().length() > 0) { 
+                    top.appendChild(doc.createTextNode(str));
+                }
+            } catch (DOMException e) {
+                throw new SAXException(e.getMessage());
+            }
+
+        }
+
+
+        /**
+         * Checks whether control needs to be returned to Digester.
+         * 
+         * @param namespaceURI the namespace URI
+         * @param localName the local name
+         * @param qName the qualified (prefixed) name
+         * @throws SAXException if the DOM implementation throws an exception
+         */
+        public void endElement(String namespaceURI, String localName,
+                               String qName)
+            throws SAXException {
+            
+            try {
+                if (depth == 0) {
+                    // restore sax event handler
+                    reader.setContentHandler(oldSaxHandler);
+                    
+                    // push built node onto stack so that other rules can
+                    // access it. Note that this node gets popped in the
+                    // end method of the parent NodeCreateAction, so it won't
+                    // be there very long...
+                    oldContext.push(root);
+                    
+                    // and manually fire the rules that would have been fired
+                    // had the normal SAXHandler been receiving parse events
+                    // instead of this temporary handler.
+                    oldSaxHandler.endElement(namespaceURI, localName, qName);
+                }
+    
+                top = top.getParentNode();
+                depth--;
+            } catch (DOMException e) {
+                throw new SAXException(e.getMessage());
+            }
+
+        }
+
+
+        /**
+         * Adds a new
+         * {@link org.w3c.dom.ProcessingInstruction ProcessingInstruction} to 
+         * the current node.
+         * 
+         * @param target the processing instruction target
+         * @param data the processing instruction data, or null if none was 
+         *   supplied
+         * @throws SAXException if the DOM implementation throws an exception
+         */
+        public void processingInstruction(String target, String data)
+            throws SAXException {
+            
+            try {
+                top.appendChild(doc.createProcessingInstruction(target, data));
+            } catch (DOMException e) {
+                throw new SAXException(e.getMessage());
+            }
+
+        }
+
+
+        /**
+         * Adds a new child {@link org.w3c.dom.Element Element} to the current
+         * node.
+         * 
+         * @param namespaceURI the namespace URI
+         * @param localName the local name
+         * @param qName the qualified (prefixed) name
+         * @param atts the list of attributes
+         * @throws SAXException if the DOM implementation throws an exception
+         */
+        public void startElement(String namespaceURI, String localName,
+                                 String qName, Attributes atts)
+            throws SAXException {
+
+            try {
+                Node previousTop = top;
+                if ((localName == null) || (localName.length() == 0)) { 
+                    top = doc.createElement(qName);
+                } else {
+                    top = doc.createElementNS(namespaceURI, localName);
+                }
+                for (int i = 0; i < atts.getLength(); i++) {
+                    Attr attr = null;
+                    if ((atts.getLocalName(i) == null) ||
+                        (atts.getLocalName(i).length() == 0)) {
+                        attr = doc.createAttribute(atts.getQName(i));
+                        attr.setNodeValue(atts.getValue(i));
+                        ((Element)top).setAttributeNode(attr);
+                    } else {
+                        attr = doc.createAttributeNS(atts.getURI(i),
+                                                     atts.getLocalName(i));
+                        attr.setNodeValue(atts.getValue(i));
+                        ((Element)top).setAttributeNodeNS(attr);
+                    }
+                }
+                previousTop.appendChild(top);
+                depth++;
+            } catch (DOMException e) {
+                throw new SAXException(e.getMessage());
+            }
+
+        }
+
+    }
+
+
+    // ----------------------------------------------------------- Constructors
+
+
+    /**
+     * Default constructor. Creates an instance of this rule that will create a
+     * DOM {@link org.w3c.dom.Element Element}.
+     */
+    public NodeCreateAction() throws ParserConfigurationException {
+
+        this(Node.ELEMENT_NODE);
+
+    }
+
+
+    /**
+     * Constructor. Creates an instance of this rule that will create a DOM
+     * {@link org.w3c.dom.Element Element}, but lets you specify the JAXP 
+     * <code>DocumentBuilder</code> that should be used when constructing the
+     * node tree.
+     * 
+     * @param documentBuilder the JAXP <code>DocumentBuilder</code> to use
+     */
+    public NodeCreateAction(DocumentBuilder documentBuilder) {
+
+        this(Node.ELEMENT_NODE, documentBuilder);
+
+    }
+
+
+    /**
+     * Constructor. Creates an instance of this rule that will create either a 
+     * DOM {@link org.w3c.dom.Element Element} or a DOM 
+     * {@link org.w3c.dom.DocumentFragment DocumentFragment}, depending on the
+     * value of the <code>nodeType</code> parameter.
+     * 
+     * @param nodeType the type of node to create, which can be either
+     *   {@link org.w3c.dom.Node#ELEMENT_NODE Node.ELEMENT_NODE} or 
+     *   {@link org.w3c.dom.Node#DOCUMENT_FRAGMENT_NODE Node.DOCUMENT_FRAGMENT_NODE}
+     * @throws IllegalArgumentException if the node type is not supported
+     */
+    public NodeCreateAction(int nodeType) throws ParserConfigurationException {
+
+        this(nodeType,
+             DocumentBuilderFactory.newInstance().newDocumentBuilder());
+
+    }
+
+
+    /**
+     * Constructor. Creates an instance of this rule that will create either a 
+     * DOM {@link org.w3c.dom.Element Element} or a DOM 
+     * {@link org.w3c.dom.DocumentFragment DocumentFragment}, depending on the
+     * value of the <code>nodeType</code> parameter. This constructor lets you
+     * specify the JAXP <code>DocumentBuilder</code> that should be used when
+     * constructing the node tree.
+     * 
+     * @param nodeType the type of node to create, which can be either
+     *   {@link org.w3c.dom.Node#ELEMENT_NODE Node.ELEMENT_NODE} or 
+     *   {@link org.w3c.dom.Node#DOCUMENT_FRAGMENT_NODE Node.DOCUMENT_FRAGMENT_NODE}
+     * @param documentBuilder the JAXP <code>DocumentBuilder</code> to use
+     * @throws IllegalArgumentException if the node type is not supported
+     */
+    public NodeCreateAction(int nodeType, DocumentBuilder documentBuilder) {
+
+        if (!((nodeType == Node.DOCUMENT_FRAGMENT_NODE) ||
+              (nodeType == Node.ELEMENT_NODE))) {
+            throw new IllegalArgumentException(
+                "Can only create nodes of type DocumentFragment and Element");
+        }
+        this.nodeType = nodeType;
+        this.documentBuilder = documentBuilder;
+
+    }
+
+
+    // ----------------------------------------------------- Instance Variables
+
+
+    /**
+     * The JAXP <code>DocumentBuilder</code> to use.
+     */
+    private DocumentBuilder documentBuilder = null;
+
+
+    /**
+     * The type of the node that should be created. Must be one of the
+     * constants defined in {@link org.w3c.dom.Node Node}, but currently only
+     * {@link org.w3c.dom.Node#ELEMENT_NODE Node.ELEMENT_NODE} and 
+     * {@link org.w3c.dom.Node#DOCUMENT_FRAGMENT_NODE Node.DOCUMENT_FRAGMENT_NODE}
+     * are allowed values.
+     */
+    private int nodeType = Node.ELEMENT_NODE;
+
+
+    // ----------------------------------------------------------- Rule Methods
+
+
+    /**
+     * Implemented to replace the content handler currently in use by a 
+     * {@link NodeBuilder NodeCreateAction.NodeBuilder}.
+     * 
+     * @param namespaceURI the namespace URI of the matching element, or an 
+     *   empty string if the parser is not namespace aware or the element has
+     *   no namespace
+     * @param name the local name if the parser is namespace aware, or just 
+     *   the element name otherwise
+     * @param attributes The attribute list of this element
+     * @throws Exception indicates a JAXP configuration problem
+     */
+    public void begin(Context context, String namespaceURI, String name, Attributes attributes)
+        throws ParseException {
+
+        try {
+            Document doc = documentBuilder.newDocument();
+            NodeBuilder builder = null;
+            if (nodeType == Node.ELEMENT_NODE) {
+                Element element = null;
+                element =
+                    doc.createElementNS(namespaceURI, name);
+                for (int i = 0; i < attributes.getLength(); i++) {
+                    element.setAttributeNS(attributes.getURI(i),
+                                           attributes.getLocalName(i),
+                                           attributes.getValue(i));
+                }
+                builder = new NodeBuilder(context, doc, element);
+            } else {
+                builder = new NodeBuilder(context, doc, doc.createDocumentFragment());
+            }
+        
+            XMLReader reader = context.getSAXHandler().getXMLReader();
+            reader.setContentHandler(builder);
+        } catch(SAXException ex) {
+            throw new ParseException(ex);
+        }
+    }
+
+
+    /**
+     * Pop the Node off the top of the stack.
+     */
+    public void end(Context context, String namespaceURI, String name) 
+    throws ParseException {
+        Object top = context.pop();
+    }
+}

Added: jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/ObjectCreationFactory.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/ObjectCreationFactory.java?view=auto&rev=151287
==============================================================================
--- jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/ObjectCreationFactory.java (added)
+++ jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/ObjectCreationFactory.java Thu Feb  3 17:51:43 2005
@@ -0,0 +1,50 @@
+/* $Id: $
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */ 
+
+package org.apache.commons.digester2.actions;
+
+
+import org.xml.sax.Attributes;
+
+
+import org.apache.commons.digester2.Context;
+import org.apache.commons.digester2.AbstractAction;
+import org.apache.commons.digester2.ParseException;
+
+/**
+ * <p> Interface for use with {@link FactoryCreateAction}.
+ * The rule calls {@link #createObject} to create an object
+ * to be pushed onto the <code>Digester</code> stack
+ * whenever it is matched.</p>
+ *
+ * <p> {@link AbstractObjectCreationFactory} is an abstract
+ * implementation suitable for creating anonymous
+ * <code>ObjectCreationFactory</code> implementations.
+ */
+public interface ObjectCreationFactory {
+
+    /**
+     * <p>Factory method called by {@link FactoryCreateAction} to supply an
+     * object based on the element's attributes.
+     *
+     * @param attributes the element's attributes
+     *
+     * @throws Exception any exception thrown will be propagated upwards
+     */
+    public Object createObject(Context context, Attributes attributes) 
+        throws ParseException;
+}

Added: jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/SetNextAction.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/SetNextAction.java?view=auto&rev=151287
==============================================================================
--- jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/SetNextAction.java (added)
+++ jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/SetNextAction.java Thu Feb  3 17:51:43 2005
@@ -0,0 +1,136 @@
+/* $Id: $
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */ 
+
+
+package org.apache.commons.digester2.actions;
+
+import org.apache.commons.beanutils.MethodUtils;
+import org.apache.commons.logging.Log;
+
+import org.apache.commons.digester2.Context;
+import org.apache.commons.digester2.AbstractAction;
+import org.apache.commons.digester2.ParseException;
+
+/**
+ * <p>Rule implementation that calls a method on the (top-1) (parent)
+ * object, passing the top object (child) as an argument.  It is
+ * commonly used to establish parent-child relationships.</p>
+ */
+
+public class SetNextAction extends AbstractAction {
+
+    // ----------------------------------------------------------- Constructors
+
+    /**
+     * 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 SetNextAction(String methodName) {
+        this(methodName, 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 SetNextAction(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;
+
+    // --------------------------------------------------------- Public Methods
+
+    /**
+     * Process the end of this element.
+     */
+    public void end(Context context, String namespace, String nme) 
+    throws ParseException {
+        // Identify the objects to be used
+        Object child = context.peek(0);
+        Object parent = context.peek(1);
+        Log log = context.getLogger();
+        if (log.isDebugEnabled()) {
+            if (parent == null) {
+                log.debug("[SetNextRule]{" + context.getMatchPath() +
+                        "} Call [NULL PARENT]." +
+                        methodName + "(" + child + ")");
+            } else {
+                log.debug("[SetNextRule]{" + context.getMatchPath() +
+                        "} Call " + parent.getClass().getName() + "." +
+                        methodName + "(" + child + ")");
+            }
+        }
+
+        // Call the specified method
+        Class paramTypes[] = new Class[1];
+        if (paramType != null) {
+            try {
+                paramTypes[0] =
+                        context.getClassLoader().loadClass(paramType);
+            } catch(ClassNotFoundException ex) {
+                throw new ParseException(ex);
+            }
+        } else {
+            paramTypes[0] = child.getClass();
+        }
+        
+        try {
+            MethodUtils.invokeMethod(parent, methodName,
+                new Object[]{ child }, paramTypes);
+        } catch(NoSuchMethodException ex) {
+            throw new ParseException(ex);
+        } catch(IllegalAccessException ex) {
+            throw new ParseException(ex);
+        } catch(java.lang.reflect.InvocationTargetException ex) {
+            throw new ParseException(ex);
+        }
+    }
+
+    /**
+     * Render a printable version of this Rule.
+     */
+    public String toString() {
+        StringBuffer sb = new StringBuffer("SetNextRule[");
+        sb.append("methodName=");
+        sb.append(methodName);
+        sb.append(", paramType=");
+        sb.append(paramType);
+        sb.append("]");
+        return (sb.toString());
+    }
+}

Added: jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/SetPropertiesAction.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/SetPropertiesAction.java?view=auto&rev=151287
==============================================================================
--- jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/SetPropertiesAction.java (added)
+++ jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/actions/SetPropertiesAction.java Thu Feb  3 17:51:43 2005
@@ -0,0 +1,262 @@
+/* $Id: $
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */ 
+
+
+package org.apache.commons.digester2.actions;
+
+import org.xml.sax.Attributes;
+import java.util.HashMap;
+
+import org.apache.commons.beanutils.BeanUtils;
+import org.apache.commons.logging.Log;
+
+import org.apache.commons.digester2.Context;
+import org.apache.commons.digester2.AbstractAction;
+import org.apache.commons.digester2.ParseException;
+
+
+
+/**
+ * <p>Rule implementation that sets properties on the object at the top of the
+ * stack, based on attributes with corresponding names.</p>
+ *
+ * <p>This rule supports custom mapping of attribute names to property names.
+ * The default mapping for particular attributes can be overridden by using 
+ * {@link #ActionSetProperties(String[] attributeNames, String[] propertyNames)}.
+ * This allows attributes to be mapped to properties with different names.
+ * Certain attributes can also be marked to be ignored.</p>
+ */
+
+public class SetPropertiesAction extends AbstractAction {
+
+    // ----------------------------------------------------------- Constructors
+
+    /**
+     * Base constructor.
+     */
+    public SetPropertiesAction() {
+        // nothing to set up 
+    }
+    
+    /** 
+     * <p>Convenience constructor overrides the mapping for just one property.</p>
+     *
+     * <p>For details about how this works, see
+     * {@link #ActionSetProperties(String[] attributeNames, String[] propertyNames)}.</p>
+     *
+     * @param attributeName map this attribute 
+     * @param propertyName to a property with this name
+     */
+    public SetPropertiesAction(String attributeName, String propertyName) {
+        attributeNames = new String[1];
+        attributeNames[0] = attributeName;
+        propertyNames = new String[1];
+        propertyNames[0] = propertyName;
+    }
+    
+    /** 
+     * <p>Constructor allows attribute->property mapping to be overriden.</p>
+     *
+     * <p>Two arrays are passed in. 
+     * One contains the attribute names and the other the property names.
+     * The attribute name / property name pairs are match by position
+     * In order words, the first string in the attribute name list matches
+     * to the first string in the property name list and so on.</p>
+     *
+     * <p>If a property name is null or the attribute name has no matching
+     * property name, then this indicates that the attibute should be ignored.</p>
+     * 
+     * <h5>Example One</h5>
+     * <p> The following constructs a rule that maps the <code>alt-city</code>
+     * attribute to the <code>city</code> property and the <code>alt-state</code>
+     * to the <code>state</code> property. 
+     * All other attributes are mapped as usual using exact name matching.
+     * <code><pre>
+     *      SetPropertiesRule(
+     *                new String[] {"alt-city", "alt-state"}, 
+     *                new String[] {"city", "state"});
+     * </pre></code>
+     *
+     * <h5>Example Two</h5>
+     * <p> The following constructs a rule that maps the <code>class</code>
+     * attribute to the <code>className</code> property.
+     * The attribute <code>ignore-me</code> is not mapped.
+     * All other attributes are mapped as usual using exact name matching.
+     * <code><pre>
+     *      SetPropertiesRule(
+     *                new String[] {"class", "ignore-me"}, 
+     *                new String[] {"className"});
+     * </pre></code>
+     *
+     * @param attributeNames names of attributes to map
+     * @param propertyNames names of properties mapped to
+     */
+    public SetPropertiesAction(String[] attributeNames, String[] propertyNames) {
+        // create local copies
+        this.attributeNames = new String[attributeNames.length];
+        for (int i=0, size=attributeNames.length; i<size; i++) {
+            this.attributeNames[i] = attributeNames[i];
+        }
+        
+        this.propertyNames = new String[propertyNames.length];
+        for (int i=0, size=propertyNames.length; i<size; i++) {
+            this.propertyNames[i] = propertyNames[i];
+        } 
+    }
+        
+    // ----------------------------------------------------- Instance Variables
+    
+    /** 
+     * Attribute names used to override natural attribute->property mapping
+     */
+    private String [] attributeNames;
+
+    /** 
+     * Property names used to override natural attribute->property mapping
+     */    
+    private String [] propertyNames;
+
+
+    // --------------------------------------------------------- Public Methods
+
+    /**
+     * Process the beginning of this element.
+     *
+     * @param attributes The attribute list of this element
+     */
+    public void begin(
+    Context context, String namespace, String elementName, Attributes attributes) 
+    throws ParseException {
+        
+        Log log = context.getLogger();
+
+        // Build a set of attribute names and corresponding values
+        HashMap values = new HashMap();
+        
+        // set up variables for custom names mappings
+        int attNamesLength = 0;
+        if (attributeNames != null) {
+            attNamesLength = attributeNames.length;
+        }
+        int propNamesLength = 0;
+        if (propertyNames != null) {
+            propNamesLength = propertyNames.length;
+        }
+        
+        for (int i = 0; i < attributes.getLength(); i++) {
+            String name = attributes.getLocalName(i);
+            if ("".equals(name)) {
+                name = attributes.getQName(i);
+            }
+            String value = attributes.getValue(i);
+            
+            // we'll now check for custom mappings
+            for (int n = 0; n<attNamesLength; n++) {
+                if (name.equals(attributeNames[n])) {
+                    if (n < propNamesLength) {
+                        // set this to value from list
+                        name = propertyNames[n];
+                    
+                    } else {
+                        // set name to null
+                        // we'll check for this later
+                        name = null;
+                    }
+                    break;
+                }
+            } 
+
+            if (log.isDebugEnabled()) {
+                log.debug("[SetProperties]{" + context.getMatchPath() +
+                        "} Setting property '" + name + "' to '" +
+                        value + "'");
+            }
+            if (name != null) {
+                values.put(name, value);
+            } 
+        }
+
+        // Populate the corresponding properties of the top object
+        Object top = context.peek();
+        if (log.isDebugEnabled()) {
+            if (top != null) {
+                log.debug("[ActionSetProperties]{" + context.getMatchPath() +
+                                   "} Set " + top.getClass().getName() +
+                                   " properties");
+            } else {
+                log.debug("[ActionSetProperties]{" + context.getMatchPath() +
+                                   "} Set NULL properties");
+            }
+        }
+
+        try {
+            BeanUtils.populate(top, values);
+        } catch(IllegalAccessException ex) {
+            throw new ParseException(ex);
+        } catch(java.lang.reflect.InvocationTargetException ex) {
+            throw new ParseException(ex);
+        }
+    }
+
+
+    /**
+     * <p>Add an additional attribute name to property name mapping.
+     * This is intended to be used from the xml rules.
+     */
+    public void addAlias(String attributeName, String propertyName) {
+        
+        // this is a bit tricky.
+        // we'll need to resize the array.
+        // probably should be synchronized but digester's not thread safe anyway
+        if (attributeNames == null) {
+            
+            attributeNames = new String[1];
+            attributeNames[0] = attributeName;
+            propertyNames = new String[1];
+            propertyNames[0] = propertyName;        
+            
+        } else {
+            int length = attributeNames.length;
+            String [] tempAttributes = new String[length + 1];
+            for (int i=0; i<length; i++) {
+                tempAttributes[i] = attributeNames[i];
+            }
+            tempAttributes[length] = attributeName;
+            
+            String [] tempProperties = new String[length + 1];
+            for (int i=0; i<length && i< propertyNames.length; i++) {
+                tempProperties[i] = propertyNames[i];
+            }
+            tempProperties[length] = propertyName;
+            
+            propertyNames = tempProperties;
+            attributeNames = tempAttributes;
+        }        
+    }
+  
+
+    /**
+     * Render a printable version of this Rule.
+     */
+    public String toString() {
+
+        StringBuffer sb = new StringBuffer("SetPropertiesRule[");
+        sb.append("]");
+        return (sb.toString());
+
+    }
+}

Added: jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/factory/ActionFactory.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/factory/ActionFactory.java?view=auto&rev=151287
==============================================================================
--- jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/factory/ActionFactory.java (added)
+++ jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/factory/ActionFactory.java Thu Feb  3 17:51:43 2005
@@ -0,0 +1,405 @@
+/* $Id: ActionFactory.java,v 1.107 2004/09/18 09:51:03 skitching Exp $
+ *
+ * Copyright 2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */ 
+
+package org.apache.commons.digester2.factory;
+
+import org.apache.commons.digester2.Action;
+import org.apache.commons.digester2.RuleManager;
+import org.apache.commons.digester2.Digester;
+import org.apache.commons.digester2.InvalidRuleException;
+
+import org.apache.commons.digester2.actions.*;
+
+/**
+ * <p>A convenience class for creating new instances of the various Action
+ * classes bundled with the Digester distribution and adding them to a
+ * Digester or a RuleManager. Note that this class is entirely optional; 
+ * actions can equally well be created via direct instantiation and
+ * added via Digester.addRule or RuleManager.addRule methods. </p>
+ */
+
+public class ActionFactory {
+
+
+    // --------------------------------------------------------- Constructors
+
+
+    /**
+     * Construct a new ActionFactory. Equivalent to
+     * <pre>
+     * ActionFactory(digester.getRuleManager())
+     * </pre>
+     */
+    public ActionFactory(Digester digester) {
+        this.target = digester.getRuleManager();
+    }
+
+
+    /**
+     * Construct a new ActionFactory.
+     */
+    public ActionFactory(RuleManager ruleManager) {
+        this.target = ruleManager;
+    }
+
+
+    // --------------------------------------------------- Instance Variables
+
+
+    /**
+     * The destination RuleManager for created rules.
+     */
+    protected RuleManager target;
+
+
+    // ------------------------------------------------------------- Properties
+
+    /**
+     * <p>Register a new rule, ie (pattern, action) pair.</p>
+     *
+     * @param pattern Element matching pattern
+     * @param action Action to be registered
+     */
+    public Action addRule(String pattern, Action action) 
+    throws InvalidRuleException {
+        target.addRule(pattern, action);
+        return action;
+    }
+
+    /**
+     * Add a "create object" rule for the specified parameters.
+     *
+     * @param pattern Element matching pattern
+     * @param className Java class name to be created
+     * @see CreateObjectAction
+     */
+    public void addCreateObject(String pattern, String className)
+    throws InvalidRuleException {
+        addRule(pattern,
+                new CreateObjectAction(className));
+    }
+
+
+    /**
+     * Add a "create object" rule for the specified parameters.
+     *
+     * @param pattern Element matching pattern
+     * @param clazz Java class to be created
+     * @see CreateObjectAction
+     */
+    public void addCreateObject(String pattern, Class clazz)
+    throws InvalidRuleException {
+        addRule(pattern,
+                new CreateObjectAction(clazz));
+    }
+
+
+    /**
+     * Add a "create object" rule for the specified parameters.
+     *
+     * @param pattern Element matching pattern
+     * @param className Default Java class name to be created
+     * @param attributeName Attribute name that optionally overrides
+     *  the default Java class name to be created
+     * @see CreateObjectAction
+     */
+    public void addCreateObject(
+    String pattern, 
+    String className, 
+    String attributeName)
+    throws InvalidRuleException {
+        addRule(pattern,
+                new CreateObjectAction(className, attributeName));
+    }
+
+
+    /**
+     * Add a "create object" rule for the specified parameters.
+     *
+     * @param pattern Element matching pattern
+     * @param attributeName Attribute name that optionally overrides
+     * @param clazz Default Java class to be created
+     *  the default Java class name to be created
+     * @see CreateObjectAction
+     */
+    public void addCreateObject(
+    String pattern, 
+    String attributeName, 
+    Class clazz)
+    throws InvalidRuleException {
+        addRule(pattern,
+                new CreateObjectAction(attributeName, clazz));
+    }
+
+    /**
+     * Add a "set properties" rule for the specified parameters.
+     *
+     * @param pattern Element matching pattern
+     * @see SetPropertiesAction
+     */
+    public void addSetProperties(String pattern)
+    throws InvalidRuleException {
+        addRule(pattern,
+                new SetPropertiesAction());
+    }
+
+    /**
+     * Add a "set properties" rule with a single overridden parameter.
+     * See {@link SetPropertiesAction#SetPropertiesAction(String attributeName, String propertyName)}
+     *
+     * @param pattern Element matching pattern
+     * @param attributeName map this attribute
+     * @param propertyName to this property
+     * @see SetPropertiesAction
+     */
+    public void addSetProperties(
+    String pattern, 
+    String attributeName, 
+    String propertyName)
+    throws InvalidRuleException {
+        addRule(pattern,
+                new SetPropertiesAction(attributeName, propertyName));
+    }
+
+    /**
+     * Add a "set properties" rule with overridden parameters.
+     * See {@link SetPropertiesAction#SetPropertiesAction(String [] attributeNames, String [] propertyNames)}
+     *
+     * @param pattern Element matching pattern
+     * @param attributeNames names of attributes with custom mappings
+     * @param propertyNames property names these attributes map to
+     * @see SetPropertiesAction
+     */
+    public void addSetProperties(
+    String pattern, 
+    String [] attributeNames, 
+    String [] propertyNames)
+    throws InvalidRuleException {
+        addRule(pattern,
+                new SetPropertiesAction(attributeNames, propertyNames));
+    }
+
+    /**
+     * Add a "bean property setter" rule for the specified parameters.
+     *
+     * @param pattern Element matching pattern
+     * @see BeanPropertySetterAction
+     */
+    public Action addBeanPropertySetter(String pattern)
+    throws InvalidRuleException {
+        Action action = new BeanPropertySetterAction();
+        return addRule(pattern, action);
+    }
+
+    /**
+     * Add a "bean property setter" rule for the specified parameters.
+     *
+     * @param pattern Element matching pattern
+     * @param propertyName Name of property to set
+     * @see BeanPropertySetterAction
+     */
+    public Action addBeanPropertySetter(String pattern, String propertyName) 
+    throws InvalidRuleException {
+        Action action = new BeanPropertySetterAction(propertyName);
+        return addRule(pattern, action);
+    }
+
+    /**
+     * Add a "set next" rule for the specified parameters.
+     *
+     * @param pattern Element matching pattern
+     * @param methodName Method name to call on the parent element
+     * @see SetNextAction
+     */
+    public void addSetNext(String pattern, String methodName)
+    throws InvalidRuleException {
+        addRule(pattern,
+                new SetNextAction(methodName));
+    }
+
+    /**
+     * Add a "set next" rule for the specified parameters.
+     *
+     * @param pattern Element matching pattern
+     * @param methodName Method name to call on the parent element
+     * @param paramType Java class name of the expected parameter type
+     *  (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)
+     * @see SetNextAction
+     */
+    public void addSetNext(
+    String pattern, 
+    String methodName,
+    String paramType)
+    throws InvalidRuleException {
+        addRule(pattern,
+                new SetNextAction(methodName, paramType));
+    }
+
+    /**
+     * Add an "call method" rule for a method which accepts no arguments.
+     *
+     * @param pattern Element matching pattern
+     * @param methodName Method name to be called
+     * @see CallMethodAction
+     */
+    public Action addCallMethod(String pattern, String methodName)
+    throws InvalidRuleException {
+        Action action = new CallMethodAction(methodName); 
+        return addRule(pattern, action);
+    }
+
+    /**
+     * Add an "call method" rule for the specified parameters.
+     *
+     * @param pattern Element matching pattern
+     * @param methodName Method name to be called
+     * @param paramCount Number of expected parameters (or zero
+     *  for a single parameter from the body of this element)
+     * @see CallMethodAction
+     */
+    public Action addCallMethod(String pattern, String methodName, int paramCount)
+    throws InvalidRuleException {
+        Action action = new CallMethodAction(methodName, paramCount);
+        return addRule(pattern, action);
+    }
+
+
+    /**
+     * Add an "call method" rule for the specified parameters.
+     * If <code>paramCount</code> is set to zero the rule will use
+     * the body of the matched element as the single argument of the
+     * method, unless <code>paramTypes</code> is null or empty, in this
+     * case the rule will call the specified method with no arguments.
+     *
+     * @param pattern Element matching pattern
+     * @param methodName Method name to be called
+     * @param paramCount Number of expected parameters (or zero
+     *  for a single parameter from the body of this element)
+     * @param paramTypes Set of Java class names for the types
+     *  of the expected parameters
+     *  (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)
+     * @see CallMethodAction
+     */
+    public Action addCallMethod(
+    String pattern, String methodName,
+    int paramCount, String paramTypes[]) 
+    throws InvalidRuleException {
+        Action action = new CallMethodAction(methodName, paramCount, paramTypes);
+        return addRule(pattern, action);
+    }
+
+
+    /**
+     * Add an "call method" rule for the specified parameters.
+     * If <code>paramCount</code> is set to zero the rule will use
+     * the body of the matched element as the single argument of the
+     * method, unless <code>paramTypes</code> is null or empty, in this
+     * case the rule will call the specified method with no arguments.
+     *
+     * @param pattern Element matching pattern
+     * @param methodName Method name to be called
+     * @param paramCount Number of expected parameters (or zero
+     *  for a single parameter from the body of this element)
+     * @param paramTypes The Java class names of the arguments
+     *  (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)
+     * @see CallMethodAction
+     */
+    public Action addCallMethod(
+    String pattern, String methodName,
+    int paramCount, Class paramTypes[])
+    throws InvalidRuleException {
+        return addRule(pattern,
+                new CallMethodAction(
+                                    methodName,
+                                    paramCount, 
+                                    paramTypes));
+
+    }
+
+    /**
+     * Add a "call parameter" rule for the specified parameters.
+     *
+     * @param pattern Element matching pattern
+     * @param paramIndex Zero-relative parameter index to set
+     *  (from the body of this element)
+     * @see CallParamAction
+     */
+    public Action addCallParam(String pattern, int paramIndex)
+    throws InvalidRuleException {
+        Action action = new CallParamAction(paramIndex);
+        return addRule(pattern, action);
+    }
+
+    /**
+     * Add a "call parameter" rule for the specified parameters.
+     *
+     * @param pattern Element matching pattern
+     * @param paramIndex Zero-relative parameter index to set
+     *  (from the specified attribute)
+     * @param attributeName Attribute whose value is used as the
+     *  parameter value
+     * @see CallParamAction
+     */
+    public void addCallParam(
+    String pattern, 
+    int paramIndex, 
+    String attributeName)
+    throws InvalidRuleException {
+        addRule(pattern,
+                new CallParamAction(paramIndex, attributeName));
+    }
+
+
+    /**
+     * Add a "call parameter" rule.
+     * This will either take a parameter from the stack 
+     * or from the current element body text. 
+     *
+     * @param paramIndex The zero-relative parameter number
+     * @param fromStack Should the call parameter be taken from the top of the stack?
+     * @see CallParamAction
+     */    
+    public void addCallParam(
+    String pattern, 
+    int paramIndex, 
+    boolean fromStack)
+    throws InvalidRuleException {
+        addRule(pattern,
+                new CallParamAction(paramIndex, fromStack));
+    }
+
+    /**
+     * Add a "call parameter" rule that sets a parameter from the stack.
+     * This takes a parameter from the given position on the stack.
+     *
+     * @param paramIndex The zero-relative parameter number
+     * @param stackIndex set the call parameter to the stackIndex'th object down the stack,
+     * where 0 is the top of the stack, 1 the next element down and so on
+     * @see CallMethodAction
+     */    
+    public void addCallParam(String pattern, int paramIndex, int stackIndex)
+    throws InvalidRuleException {
+         addRule(pattern,
+                new CallParamAction(paramIndex, stackIndex));
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Mime
View raw message