cocoon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jheym...@apache.org
Subject svn commit: r330548 [60/132] - in /cocoon/whiteboard/maven2/cocoon-flat-layout: ./ cocoon-ajax-block/ cocoon-ajax-block/api/ cocoon-ajax-block/api/src/ cocoon-ajax-block/api/src/main/ cocoon-ajax-block/api/src/main/java/ cocoon-ajax-block/api/src/main/...
Date Thu, 03 Nov 2005 14:00:48 GMT
Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/SimpleFormInstanceExtractionTransformer.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/SimpleFormInstanceExtractionTransformer.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/SimpleFormInstanceExtractionTransformer.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/SimpleFormInstanceExtractionTransformer.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,250 @@
+/*
+ * Copyright 1999-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.cocoon.transformation;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.avalon.framework.configuration.Configurable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.ServiceSelector;
+import org.apache.avalon.framework.service.Serviceable;
+
+import org.apache.avalon.excalibur.pool.Recyclable;
+
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.components.modules.output.OutputModule;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.cocoon.xml.dom.DocumentWrapper;
+
+import org.w3c.dom.Document;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+/**
+ * @cocoon.sitemap.component.documentation
+ * This transformer sieves an incoming stream of xml and extracts a
+ * document fragment from it depending on a given tag and stores the
+ * fragment using an OutputModule with a name based an attribute of
+ * another enclosing tag. Default configuration fires on
+ * <form-instance/> and uses @name of enclosing <form/>
+ * tag. Default OutputModule is request-attr. This is usefull in
+ * conjunction with the SimpleFormTransformer when setting the
+ * InputModule for it to a chain of request-param and request-attr so
+ * that the extracted form instance data is used only when no similar
+ * request parameter exists.
+ * 
+ * @cocoon.sitemap.component.name   simple-form-instance
+ * @cocoon.sitemap.component.logger sitemap.transformer.simple-form-instance
+ * 
+ * @author <a href="mailto:haul@apache.org">Christian Haul</a>
+ * @version CVS $Id: SimpleFormInstanceExtractionTransformer.java 30941 2004-07-29 19:56:58Z vgritsenko $
+ */
+public class SimpleFormInstanceExtractionTransformer extends AbstractExtractionTransformer 
+    implements Configurable, Serviceable, Recyclable {
+
+    protected class ElementData {
+        public String uri = null;
+        public String loc = null;
+        public String raw = null;
+
+        public ElementData() {
+        }
+
+        public ElementData(String uri, String loc, String raw) {
+            this.uri = uri;
+            this.loc = loc;
+            this.raw =raw;
+        }
+
+        public boolean equals(String uri, String loc, String raw) {
+
+            if (!this.uri.equals(uri))
+                return false;
+            if (!this.loc.equals(loc))
+                return false;
+            if (!this.raw.equals(raw))
+                return false;
+            return true;
+        }
+
+    }
+
+    protected final static String OUTPUT_MODULE_SELECTOR = OutputModule.ROLE+"Selector";
+
+    ElementData startElement = null;
+    ElementData nameElement = null;
+    String qname = "name";
+
+    String instanceName = null;
+    boolean nameAsRoot = true;
+
+    String outputModuleName = "request-attr";
+    Configuration outputConf = null;
+
+    ServiceManager manager = null;
+    Map objectModel = null;
+
+    public void configure(Configuration config) throws ConfigurationException {
+        this.startElement = new ElementData();
+        this.startElement.uri = config.getChild("start").getAttribute("uri", "");
+        this.startElement.loc = config.getChild("start").getAttribute("local-name", "form-instance");
+        this.startElement.raw = config.getChild("start").getAttribute("raw-name", "form-instance");
+
+        this.nameElement = new ElementData();
+        this.nameElement.uri = config.getChild("name").getAttribute("uri", "");
+        this.nameElement.loc = config.getChild("name").getAttribute("local-name", "form");
+        this.nameElement.raw = config.getChild("name").getAttribute("raw-name", "form");
+        this.qname = config.getChild("name").getAttribute("name-attribute", "name");
+
+        this.nameAsRoot = config.getChild("name-as-root").getValueAsBoolean(this.nameAsRoot);
+
+        this.outputConf = config.getChild("output");
+        this.outputModuleName = this.outputConf.getAttribute("name",this.outputModuleName);
+    }
+
+    public void service(ServiceManager manager) throws ServiceException {
+        this.manager = manager;
+    }
+
+    /** Setup the transformer. */
+    public void setup(SourceResolver resolver, Map objectModel, String src, Parameters parameters)
+            throws ProcessingException, SAXException, IOException {
+        super.setup(resolver, objectModel, src, parameters);
+        this.objectModel = objectModel;
+    }
+
+    public void recycle() {
+        super.recycle();
+        this.instanceName = null;
+    }
+
+    /**
+     * Receive notification of the beginning of an element.
+     *
+     * @param uri The Namespace URI, or the empty string if the element has no
+     *            Namespace URI or if Namespace
+     *            processing is not being performed.
+     * @param loc The local name (without prefix), or the empty string if
+     *            Namespace processing is not being performed.
+     * @param raw The raw XML 1.0 name (with prefix), or the empty string if
+     *            raw names are not available.
+     * @param a The attributes attached to the element. If there are no
+     *          attributes, it shall be an empty Attributes object.
+     * @return a <code>boolean</code> value to signal to start extracting
+     */
+    public boolean startExtracting(String uri, String loc, String raw, Attributes a) {
+        if (this.nameElement.equals(uri,loc,raw)) {
+            this.instanceName = a.getValue(this.qname);
+        }
+        boolean res = this.startElement.equals(uri,loc,raw);
+        return res;
+    }
+
+    /**
+     * Receive notification of the beginning of an element.
+     *
+     * @param uri The Namespace URI, or the empty string if the element has no
+     *            Namespace URI or if Namespace
+     *            processing is not being performed.
+     * @param loc The local name (without prefix), or the empty string if
+     *            Namespace processing is not being performed.
+     * @param raw The raw XML 1.0 name (with prefix), or the empty string if
+     * @return a <code>boolean</code> value to signal to stop extracting
+     */
+    public boolean endExtracting(String uri, String loc, String raw) {
+        boolean res = this.startElement.equals(uri,loc,raw);
+        return res;
+    }
+
+
+    /**
+     * Start root element and replace it with the instance name.
+     * @see org.apache.cocoon.transformation.AbstractExtractionTransformer#startExtractingDocument(String, String, String, Attributes)
+     */
+    public void startExtractingDocument(String uri, String loc, String raw, Attributes a) throws SAXException {
+        if (this.nameAsRoot) {
+            loc = this.instanceName;
+            if (uri != null && !uri.equals("")) {
+                int pos = raw.indexOf(':');
+                raw = raw.substring(0, pos+1) + this.instanceName;
+            } else {
+                raw = loc;
+            }
+        }
+        this.currentBuilder.startElement(uri,loc,raw,a);
+    }
+
+    /**
+     * End root element and replace it with the instance name.
+     * @see org.apache.cocoon.transformation.AbstractExtractionTransformer#endExtractingDocument(String, String, String)
+     */
+    public void endExtractingDocument(String uri, String loc, String raw) throws SAXException{
+        if(this.nameAsRoot){
+            loc = this.instanceName;
+            if (uri != null && !uri.equals("")) {
+                int pos = raw.indexOf(':');
+                raw = raw.substring(0, pos+1) + this.instanceName;
+            } else {
+                raw = loc;
+            }
+        }
+        this.currentBuilder.endElement(uri, loc, raw);
+    }
+
+
+    /**
+     * Receive notification of the end of the extracted Document.
+     *
+     * @param doc a <code>Document</code> value
+     */
+    public void handleExtractedDocument(Document doc) {
+        
+        ServiceSelector outputSelector = null;
+        OutputModule output = null;
+
+        try {
+            if (getLogger().isDebugEnabled())
+                getLogger().debug("wrote ['"+this.instanceName+"'] to "+output+" using "+outputConf);
+            outputSelector = (ServiceSelector) this.manager.lookup(OUTPUT_MODULE_SELECTOR);
+            if (outputSelector.isSelectable(this.outputModuleName)) {
+                output = (OutputModule) outputSelector.select(this.outputModuleName);
+            }
+            output.setAttribute(outputConf, this.objectModel, this.instanceName, new DocumentWrapper(doc));
+            output.commit(outputConf, this.objectModel);
+            if (getLogger().isDebugEnabled())
+                getLogger().debug("wrote ['"+this.instanceName+"'] to "+output+" using "+outputConf);
+
+        } catch (Exception e) {
+            if (getLogger().isWarnEnabled())
+                getLogger().warn("Problem writing document data: "+e.getMessage());
+        } finally {
+            if (outputSelector != null) {
+                if (output != null) {
+                    outputSelector.release(output);
+                    output = null;
+                }
+                this.manager.release(outputSelector);
+            }
+        }
+        this.instanceName = null;
+    }
+
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/SimpleFormInstanceExtractionTransformer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/SimpleFormTransformer.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/SimpleFormTransformer.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/SimpleFormTransformer.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/SimpleFormTransformer.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,1205 @@
+/*
+ * Copyright 1999-2005 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.cocoon.transformation;
+
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.avalon.framework.service.ServiceSelector;
+import org.apache.avalon.framework.thread.ThreadSafe;
+
+import org.apache.avalon.excalibur.pool.Recyclable;
+
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.acting.ValidatorActionResult;
+import org.apache.cocoon.transformation.helpers.FormValidatorHelper;
+import org.apache.cocoon.components.modules.input.InputModule;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.cocoon.util.HashMap;
+import org.apache.cocoon.xml.dom.DOMStreamer;
+import org.apache.commons.lang.BooleanUtils;
+
+import org.w3c.dom.DocumentFragment;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @cocoon.sitemap.component.documentation
+ * Eliminates the need for XSP to use FormValidatorAction or HTML forms.
+ * Caveat: Select options need a value attribute to work correctly.
+ *
+ * @cocoon.sitemap.component.name   simple-form
+ * @cocoon.sitemap.component.logger sitemap.transformer.simple-form
+ *
+ *
+ * <p>This transformer fills all HTML 4 form elements with values from
+ * an InputModule, e.g. request, with the same name. It handles select
+ * boxes, textareas, checkboxes, radio buttons, password and text
+ * fields, and buttons. Form elements and complete forms can be protected
+ * from substitution by adding an attribute fixed="true" to them.</p>
+ *
+ * <p>In addition, it handles FormValidatorAction results by
+ * selectively omitting &lt;error/&gt; elements. These elements need a
+ * "name" attribute corresponding to the name of the form element, and
+ * either a "when" or a "when-ge" attribute.</p>
+ *
+ * <p>An error element is send down the pipeline if validation results
+ * are available and either the results equals the "when" attribute or
+ * the result is greater or equal to the "when-ge" attribute.</p>
+ *
+ * <p>Names for validation results are "ok", "not-present", "error",
+ * "is-null", "too-small", "too-large", and "no-match" for the similar
+ * named values from ValidatorActionResult.</p>
+ *
+ * <p>There need not to be an "error" element for every form element,
+ * multiple error elements for the same form element may be
+ * present.</p>
+ *
+ * <p><em>Names of error elements are never augmented by prefix, suffix or
+ * form name.</em></p>
+ *
+ * <p>Page parts with multiple occurrences depending on the number of
+ * actual parameters can be enclosed in &lt;repeat on="expr" using="var"/&gt;
+ * elements. <em>expr</em> is used to determine the number of occurrences
+ * and <em>var</em> will be expanded with the ordinary number. Repeat elements
+ * can be nested.</p>
+ *
+ * <p>Example:</p>
+ * <pre>
+ *  <repeat on="mult" using="i"><input type="text" name="mult[${i}]"/></repeat>
+ * </pre>
+ * <p>Will include as many input elements as mult parameters are present. Adding
+ * the repeater variable to the elements name is necessary only with structured
+ * parameters or when they should be numbered. See also the <em>strip-number</em>
+ * configuration parameter.</p>
+ *
+ * <p>To use this transformer, add the following to your
+ * transformation pipeline: <pre>
+ *   &lt;map:transform type="simple-form"/&gt;
+ * </pre></p>
+ *
+ * <p>Configuration elements:
+ * <table>
+ *   <tr><td>input-module</td><td>(String) InputModule configuration,
+ *           defaults to an empty configuration and the "request-param" module</td></tr>
+ *   <tr><td>fixed-attribute</td><td>(String) Name of the attribute used to
+ *           indicate that this element should not be changed. ("fixed")</td></tr>
+ *   <tr><td>use-form-name</td><td>(boolean) Add the name of the form to the
+ *           name of form elements. Uses default Separator , if default separator is null
+ *           or empty, separator is set to "/". ("false")</td></tr>
+ *   <tr><td>use-form-name-twice</td><td>(boolean) Add the name of the form twice to the
+ *           name of form elements. This is useful when the form instance has no
+ *           all enclosing root tag and the form name is used instead <em>and</em> the
+ *           form name needs to be used to find the form data. Uses default Separator ,
+ *           if default separator is null or empty, separator is set to "/".("false")</td></tr>
+ *   <tr><td>separator</td><td>(String) Separator between form name and element name ("/")
+ *           </td></tr>
+ *   <tr><td>prefix</td><td>(String) Prefix to add to element name for value lookup. No
+ *           separator will be added between prefix and rest of the name. Default
+ *           is "", when use-form-name is set, defaults to separator.</td></tr>
+ *   <tr><td>suffix</td><td>(String) Added to the input element's name. No
+ *           separator will be added between rest of the name and suffix. ("")</td></tr>
+ *   <tr><td>ignore-validation</td><td>(boolean) If set to true, all error
+ *           tags are copied as is regardless of the validation results.("false")</td></tr>
+ *   <tr><td>decoration</td><td>(int) Length of decorations around repeat variable. Example:
+ *           when using JXPath based module, decoration would be "[" and "]", hence 1. (1)</td></tr>
+ *   <tr><td>strip-number</td><td>(boolean) If set to false, element names of repeated
+ *           elements will contain the expanded repeater variable. ("true")</td></tr>
+ * </table>
+ * </p>
+ *
+ * <p>Sitemap parameters:
+ * <table>
+ *   <tr><td>fixed</td><td>(boolean) Do not change values</td></tr>
+ *   <tr><td>prefix</td><td>(String) Added to the input element's name</td></tr>
+ *   <tr><td>suffix</td><td>(String) Added to the input element's name</td></tr>
+ *   <tr><td>input</td><td>(String) InputModule name</td></tr>
+ *   <tr><td>decoration</td><td>(int) Length of decorations around repeat variable.</td></tr>
+ *   <tr><td>strip-number</td><td>(boolean) Expanded repeater variable.</td></tr>
+ * </table>
+ * </p>
+ *
+ * <p>Example:<pre>
+ *     &lt;input name="user.name" size="50" maxlength="60"/&gt;
+ *     &lt;error name="user.name" when-ge="error"&gt;required&lt;/error&gt;
+ * </pre></p>
+ *
+ * @author <a href="mailto:haul@apache.org">Christian Haul</a>
+ * @version $Id: SimpleFormTransformer.java 168368 2005-05-05 18:28:46Z vgritsenko $
+ */
+public class SimpleFormTransformer extends AbstractSAXTransformer implements Recyclable {
+
+    /** strip numbers from repeated element name attributes */
+    private boolean stripNumber = true;
+
+    /** Symbolic names for elements */
+    /** unknown element */
+    private static final int ELEMENT_DEFAULT = 0;
+    /** input element */
+    private static final int ELEMENT_INPUT = 1;
+    /** select element */
+    private static final int ELEMENT_SELECT = 2;
+    /** option element */
+    private static final int ELEMENT_OPTION = 3;
+    /** textarea element */
+    private static final int ELEMENT_TXTAREA = 4;
+    /** error element */
+    private static final int ELEMENT_ERROR = 5;
+    /** form element */
+    private static final int ELEMENT_FORM = 6;
+    /** repeat element */
+    private static final int ELEMENT_REPEAT = 7;
+    /** default element as Integer (needed as default in org.apache.cocoon.util.HashMap.get()) */
+    private static final Integer defaultElement = new Integer(ELEMENT_DEFAULT);
+
+    /** input type unknown */
+    private static final int TYPE_DEFAULT = 0;
+    /** input type checkbox */
+    private static final int TYPE_CHECKBOX = 1;
+    /** input type radio */
+    private static final int TYPE_RADIO = 2;
+    /** default input type as Integer (needed as default in org.apache.cocoon.util.HashMap.get()) */
+    private static final Integer defaultType = new Integer(TYPE_DEFAULT);
+
+    protected static final String INPUT_MODULE_ROLE = InputModule.ROLE;
+    protected static final String INPUT_MODULE_SELECTOR = INPUT_MODULE_ROLE + "Selector";
+
+    /** map element name string to symbolic name */
+    private static final HashMap elementNames;
+    /** map input type string to symbolic name */
+    private static final HashMap inputTypes;
+    /** map ValidatorActionResult to name string */
+    private static final HashMap validatorResults;
+    /** map name string to ValidatorActionResult */
+    private static final HashMap validatorResultLabel;
+
+    /** setup mapping tables */
+    static {
+        HashMap names = new HashMap();
+        names.put("input", new Integer(ELEMENT_INPUT));
+        names.put("select", new Integer(ELEMENT_SELECT));
+        names.put("option", new Integer(ELEMENT_OPTION));
+        names.put("textarea", new Integer(ELEMENT_TXTAREA));
+        names.put("error", new Integer(ELEMENT_ERROR));
+        names.put("form", new Integer(ELEMENT_FORM));
+        names.put("repeat", new Integer(ELEMENT_REPEAT));
+        elementNames = names;
+        names = null;
+
+        names = new HashMap();
+        names.put("checkbox", new Integer(TYPE_CHECKBOX));
+        names.put("radio", new Integer(TYPE_RADIO));
+        inputTypes = names;
+        names = null;
+
+        names = new HashMap();
+        names.put("ok", ValidatorActionResult.OK);
+        names.put("not-present", ValidatorActionResult.NOTPRESENT);
+        names.put("error", ValidatorActionResult.ERROR);
+        names.put("is-null", ValidatorActionResult.ISNULL);
+        names.put("too-small", ValidatorActionResult.TOOSMALL);
+        names.put("too-large", ValidatorActionResult.TOOLARGE);
+        names.put("no-match", ValidatorActionResult.NOMATCH);
+        validatorResultLabel = names;
+
+        names = new HashMap();
+        names.put(ValidatorActionResult.OK, "ok");
+        names.put(ValidatorActionResult.NOTPRESENT, "not-present");
+        names.put(ValidatorActionResult.ERROR, "error");
+        names.put(ValidatorActionResult.ISNULL, "is-null");
+        names.put(ValidatorActionResult.TOOSMALL, "too-small");
+        names.put(ValidatorActionResult.TOOLARGE, "too-large");
+        names.put(ValidatorActionResult.NOMATCH, "no-match");
+        validatorResults = names;
+        names = null;
+    }
+
+    /** current element's request parameter values */
+    protected Object[] values;
+
+    /** current request's validation results (all validated elements) */
+    protected Map validationResults;
+
+    /** Should we skip inserting values? */
+    private boolean fixed;
+    /** Is the complete document protected? */
+    private boolean documentFixed;
+
+    private String fixedName = "fixed";
+    private String prefix;
+    private String suffix;
+    private String defaultPrefix;
+    private String defaultSuffix;
+    private String separator;
+    private String formName;
+    private boolean useFormName;
+    private boolean useFormNameTwice;
+    private boolean ignoreValidation;
+    private int decorationSize = 1;
+
+    private String defaultInput = "request-param";
+    private Configuration defaultInputConf;
+    private Configuration inputConf;
+    private InputModule input;
+    private ServiceSelector inputSelector;
+    private String inputName;
+
+    /** Skip element's content only. Otherwise skip also surrounding element. */
+    protected boolean skipChildrenOnly;
+
+    /** Count nested repeat elements. */
+    protected int recordingCount;
+
+    /** List of {@link RepeaterStatus} elements keeping track of nested repeat blocks. */
+    protected List repeater;
+
+    /** Map of {@link ValueList} to track multiple parameters. */
+    protected Map formValues;
+
+
+    /**
+     * Keep track of repeater status.
+     */
+    protected class RepeaterStatus {
+        public String var = null;
+        public String expr = null;
+        public int count = 0;
+
+        public RepeaterStatus(String var, int count, String expr) {
+            this.var = var;
+            this.count = count;
+            this.expr = expr;
+        }
+
+        public String toString() {
+            return "[" + this.var + "," + this.expr + "," + this.count + "]";
+        }
+    }
+
+    /**
+     * Keep track of multiple values.
+     */
+    protected static class ValueList {
+        private int current = -1;
+        private Object[] values = null;
+
+        public ValueList(Object[] values) {
+            this.values = values;
+            this.current = (values != null && values.length > 0 ? 0 : -1);
+        }
+
+        public Object getNext() {
+            Object result = null;
+            if (this.values != null) {
+                if (this.current < this.values.length) {
+                    result = this.values[this.current++];
+                }
+            }
+            return result;
+        }
+    }
+
+
+    /**
+     * Constructor. Set the namespace.
+     */
+    public SimpleFormTransformer() {
+        super.defaultNamespaceURI = "";
+    }
+
+    /** set per instance variables to defaults */
+    private void reset() {
+        this.skipChildrenOnly = false;
+        this.values = null;
+        this.validationResults = null;
+        this.documentFixed = false;
+        this.fixed = false;
+        this.formName = null;
+        this.recordingCount = 0;
+        this.repeater = new LinkedList();
+        this.formValues = new HashMap();
+
+        if (this.inputSelector != null) {
+            if (this.input != null)
+                this.inputSelector.release(this.input);
+            this.manager.release(this.inputSelector);
+        }
+    }
+
+    /**
+     * Avalon Configurable Interface
+     */
+    public void configure(Configuration config) throws ConfigurationException {
+        super.configure(config);
+
+        this.defaultInputConf = config.getChild("input-module");
+        this.defaultInput = this.defaultInputConf.getAttribute("name", this.defaultInput);
+        this.separator = config.getChild("separator").getValue(this.separator);
+        this.defaultPrefix = config.getChild("prefix").getValue(this.defaultPrefix);
+        this.defaultSuffix = config.getChild("suffix").getValue(this.defaultSuffix);
+        this.fixedName = config.getChild("fixed-attribute").getValue(this.fixedName);
+        this.useFormName = config.getChild("use-form-name").getValueAsBoolean(this.useFormName);
+        this.useFormNameTwice =
+            config.getChild("use-form-name-twice").getValueAsBoolean(this.useFormNameTwice);
+        this.useFormName = this.useFormName || this.useFormNameTwice;
+        if (this.useFormName) {
+            this.separator =
+                (this.separator == null || this.separator.equals("") ? "/" : this.separator);
+            this.defaultPrefix = this.separator;
+        }
+        this.ignoreValidation =
+            config.getChild("ignore-validation").getValueAsBoolean(this.ignoreValidation);
+        this.decorationSize = config.getChild("decoration").getValueAsInteger(this.decorationSize);
+        this.stripNumber = config.getChild("strip-number").getValueAsBoolean(this.stripNumber);
+    }
+
+    /**
+     * Read sitemap parameters and set properties accordingly.
+     */
+    private void evaluateParameters() {
+        this.documentFixed = this.parameters.getParameterAsBoolean("fixed", false);
+        this.fixed = this.documentFixed;
+        this.prefix = this.parameters.getParameter("prefix", this.defaultPrefix);
+        this.suffix = this.parameters.getParameter("suffix", this.defaultSuffix);
+        this.inputName = this.parameters.getParameter("input", null);
+        this.decorationSize =
+            this.parameters.getParameterAsInteger("decoration", this.decorationSize);
+        this.stripNumber = this.parameters.getParameterAsBoolean("strip-number", this.stripNumber);
+    }
+
+    /**
+     * Setup the next round.
+     * The instance variables are initialised.
+     * @param resolver The current SourceResolver
+     * @param objectModel The objectModel of the environment.
+     * @param src The value of the src attribute in the sitemap.
+     * @param par The parameters from the sitemap.
+     */
+    public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par)
+        throws ProcessingException, SAXException, IOException {
+
+        this.reset();
+
+        super.setup(resolver, objectModel, src, par);
+
+        if (request == null) {
+            getLogger().debug("no request object");
+            throw new ProcessingException("no request object");
+        }
+        this.evaluateParameters();
+        this.setupInputModule();
+
+    }
+
+    /**
+     * Setup and obtain reference to the input module.
+     */
+    private void setupInputModule() {
+        this.inputConf = null;
+        if (this.ignoreValidation) {
+            this.validationResults = null;
+        } else {
+            this.validationResults = FormValidatorHelper.getResults(this.objectModel);
+        }
+
+        if (this.inputName == null) {
+            this.inputName = this.defaultInput;
+            this.inputConf = this.defaultInputConf;
+        }
+
+        try {
+            // obtain input module
+            this.inputSelector = (ServiceSelector) this.manager.lookup(INPUT_MODULE_SELECTOR);
+            if (this.inputName != null
+                && this.inputSelector != null
+                && this.inputSelector.isSelectable(this.inputName)) {
+                this.input = (InputModule) this.inputSelector.select(this.inputName);
+                if (!(this.input instanceof ThreadSafe
+                    && this.inputSelector instanceof ThreadSafe)) {
+                    this.inputSelector.release(this.input);
+                    this.manager.release(this.inputSelector);
+                    this.input = null;
+                    this.inputSelector = null;
+                }
+            } else {
+                if (this.inputName != null)
+                    if (getLogger().isErrorEnabled())
+                        getLogger().error(
+                            "A problem occurred setting up '"
+                                + this.inputName
+                                + "': Selector is "
+                                + (this.inputSelector != null ? "not " : "")
+                                + "null, Component is "
+                                + (this.inputSelector != null
+                                    && this.inputSelector.isSelectable(this.inputName)
+                                        ? "known"
+                                        : "unknown"));
+            }
+        } catch (Exception e) {
+            if (getLogger().isWarnEnabled())
+                getLogger().warn(
+                    "A problem occurred setting up '" + this.inputName + "': " + e.getMessage());
+        }
+    }
+
+    /**
+     *  Recycle this component.
+     */
+    public void recycle() {
+        reset();
+        super.recycle();
+    }
+
+    /**
+     * Generate string representation of attributes. For debug only.
+     */
+    protected String printAttributes(Attributes attr) {
+        StringBuffer sb = new StringBuffer();
+        sb.append('[');
+        for (int i = 0; i < attr.getLength(); i++) {
+            sb.append('@').append(attr.getLocalName(i)).append("='").append(
+                attr.getValue(i)).append(
+                "' ");
+        }
+        sb.append(']');
+        return sb.toString();
+    }
+
+    /**
+     * Handle input elements that may have a "checked" attributes,
+     * i.e. checkbox and radio.
+     */
+    protected void startCheckableElement(
+        String aName,
+        String uri,
+        String name,
+        String raw,
+        AttributesImpl attributes)
+        throws SAXException {
+
+        // @fixed and this.fixed already considered in startInputElement
+        this.values = this.getValues(aName);
+        String checked = attributes.getValue("checked");
+        String value = attributes.getValue("value");
+        boolean found = false;
+
+        if (getLogger().isDebugEnabled())
+            getLogger().debug(
+                "startCheckableElement "
+                    + name
+                    + " attributes "
+                    + this.printAttributes(attributes));
+        if (this.values != null) {
+            if (getLogger().isDebugEnabled())
+                getLogger().debug("replacing");
+            for (int i = 0; i < this.values.length; i++) {
+                if (this.values[i].equals(value)) {
+                    found = true;
+                    if (checked == null) {
+                        attributes.addAttribute("", "checked", "checked", "CDATA", "");
+                    }
+                    break;
+                }
+            }
+            if (!found && checked != null) {
+                attributes.removeAttribute(attributes.getIndex("checked"));
+            }
+        }
+        this.relayStartElement(uri, name, raw, attributes);
+    }
+
+    /**
+     * Handle input elements that may don't have a "checked"
+     * attributes, e.g. text, password, button.
+     */
+    protected void startNonCheckableElement(
+        String aName,
+        String uri,
+        String name,
+        String raw,
+        AttributesImpl attributes)
+        throws SAXException {
+
+        // @fixed and this.fixed already considered in startInputElement
+        Object fValue = this.getNextValue(aName);
+        String value = attributes.getValue("value");
+        if (getLogger().isDebugEnabled())
+            getLogger().debug(
+                "startNonCheckableElement "
+                    + name
+                    + " attributes "
+                    + this.printAttributes(attributes));
+        if (fValue != null) {
+            if (getLogger().isDebugEnabled())
+                getLogger().debug("replacing");
+            if (value != null) {
+                attributes.setValue(attributes.getIndex("value"), String.valueOf(fValue));
+            } else {
+                attributes.addAttribute("", "value", "value", "CDATA", String.valueOf(fValue));
+            }
+        }
+        this.relayStartElement(uri, name, raw, attributes);
+    }
+
+    /**
+     * Handle input elements. Calls startCheckableElement or
+     * startNonCheckableElement.
+     */
+    protected void startInputElement(String uri, String name, String raw, Attributes attr)
+        throws SAXException {
+
+        // @value = request.getParameterValues(@name)
+        String aName = getName(attr.getValue("name"));
+        String fixed = attr.getValue(this.fixedName);
+
+        if (getLogger().isDebugEnabled())
+            getLogger().debug(
+                "startInputElement " + name + " attributes " + this.printAttributes(attr));
+        if (aName == null || this.fixed || (fixed != null && BooleanUtils.toBoolean(fixed))) {
+            this.relayStartElement(uri, name, raw, attr);
+
+        } else {
+            if (getLogger().isDebugEnabled())
+                getLogger().debug("replacing");
+
+            attr = this.normalizeAttributes(attr);
+
+            AttributesImpl attributes = null;
+            if (attr instanceof AttributesImpl) {
+                attributes = (AttributesImpl) attr;
+            } else {
+                attributes = new AttributesImpl(attr);
+            }
+            String type = attributes.getValue("type");
+            switch (((Integer) inputTypes.get(type, defaultType)).intValue()) {
+                case TYPE_CHECKBOX :
+                case TYPE_RADIO :
+                    this.startCheckableElement(aName, uri, name, raw, attributes);
+                    break;
+
+                case TYPE_DEFAULT :
+                    this.startNonCheckableElement(aName, uri, name, raw, attributes);
+                    break;
+            }
+            this.values = null;
+        }
+    }
+
+    /**
+     * Handle select elements. Sets up some instance variables for
+     * following option elements.
+     */
+    protected void startSelectElement(String uri, String name, String raw, Attributes attr)
+        throws SAXException {
+
+        // this.values = request.getParameterValues(@name)
+        String aName = getName(attr.getValue("name"));
+        String fixed = attr.getValue(this.fixedName);
+        this.values = null;
+        if (getLogger().isDebugEnabled())
+            getLogger().debug(
+                "startSelectElement " + name + " attributes " + this.printAttributes(attr));
+        if (aName != null && !(this.fixed || (fixed != null && BooleanUtils.toBoolean(fixed)))) {
+            if (attr.getIndex("multiple") > -1) {
+                this.values = this.getValues(aName);
+            } else {
+                Object val = this.getNextValue(aName);
+                if (val != null) {
+                    this.values = new Object[1];
+                    this.values[0] = val;
+                } else {
+                    this.values = null;
+                }
+            }
+            attr = this.normalizeAttributes(attr);
+        }
+        this.relayStartElement(uri, name, raw, attr);
+    }
+
+    /**
+     * Handle option elements. Uses instance variables set up by
+     * startSelectElement. Relies on option having a "value"
+     * attribute, i.e. does not check following characters if "value"
+     * is not present.
+     */
+    protected void startOptionElement(String uri, String name, String raw, Attributes attr)
+        throws SAXException {
+
+        // add @selected if @value in request.getParameterValues(@name)
+        if (getLogger().isDebugEnabled())
+            getLogger().debug(
+                "startOptionElement " + name + " attributes " + this.printAttributes(attr));
+        if (this.values == null || this.fixed) {
+            this.relayStartElement(uri, name, raw, attr);
+        } else {
+            if (getLogger().isDebugEnabled())
+                getLogger().debug("replacing");
+            AttributesImpl attributes = null;
+            if (attr instanceof AttributesImpl) {
+                attributes = (AttributesImpl) attr;
+            } else {
+                attributes = new AttributesImpl(attr);
+            }
+            String selected = attributes.getValue("selected");
+            String value = attributes.getValue("value");
+            boolean found = false;
+
+            for (int i = 0; i < this.values.length; i++) {
+                if (this.values[i].equals(value)) {
+                    found = true;
+                    if (selected == null) {
+                        attributes.addAttribute("", "selected", "selected", "CDATA", "");
+                    }
+                    break;
+                }
+            }
+            if (!found && selected != null) {
+                attributes.removeAttribute(attributes.getIndex("selected"));
+            }
+
+            this.relayStartElement(uri, name, raw, attributes);
+        }
+    }
+
+    /**
+     * Handles textarea elements. Skips nested events if request
+     * parameter with same name exists.
+     */
+    protected void startTextareaElement(String uri, String name, String raw, Attributes attributes)
+        throws SAXException {
+
+        String aName = getName(attributes.getValue("name"));
+        String fixed = attributes.getValue(this.fixedName);
+        Object value = null;
+        if (getLogger().isDebugEnabled())
+            getLogger().debug(
+                "startTextareaElement " + name + " attributes " + this.printAttributes(attributes));
+        if (aName != null) {
+            value = this.getNextValue(aName);
+        }
+        if (value == null || this.fixed || (fixed != null && BooleanUtils.toBoolean(fixed))) {
+            this.relayStartElement(uri, name, raw, attributes);
+        } else {
+            if (getLogger().isDebugEnabled())
+                getLogger().debug("replacing");
+            this.relayStartElement(uri, name, raw, this.normalizeAttributes(attributes));
+            String valString = String.valueOf(value);
+            this.characters(valString.toCharArray(), 0, valString.length());
+            // well, this doesn't really work out nicely. do it the hard way.
+            if (this.ignoreEventsCount == 0)
+                this.skipChildrenOnly = true;
+            this.ignoreEventsCount++;
+        }
+    }
+
+    /**
+     * Handle error elements. If validation results are available,
+     * compares validation result for parameter with the same name as
+     * the "name" attribute with the result names is "when" and
+     * "when-ge". Drops element and all nested events when error
+     * condition is not met.
+     */
+    protected void startErrorElement(String uri, String name, String raw, Attributes attr)
+        throws SAXException {
+
+        if (getLogger().isDebugEnabled())
+            getLogger().debug(
+                "startErrorElement " + name + " attributes " + this.printAttributes(attr));
+        if (this.ignoreValidation) {
+            this.relayStartElement(uri, name, raw, attr);
+        } else if (this.validationResults == null || this.fixed) {
+            this.relayStartElement(true, false, uri, name, raw, attr);
+        } else {
+            String aName = attr.getValue("name");
+            if (aName == null) {
+                this.relayStartElement(uri, name, raw, attr);
+            } else {
+                ValidatorActionResult validation =
+                    FormValidatorHelper.getParamResult(this.objectModel, aName);
+                String when = attr.getValue("when");
+                String when_ge = attr.getValue("when-ge");
+
+                if ((when != null && when.equals(validatorResults.get(validation)))
+                    || (when_ge != null
+                        && validation.ge(
+                            (ValidatorActionResult) validatorResultLabel.get(
+                                when_ge,
+                                ValidatorActionResult.MAXERROR)))) {
+                    AttributesImpl attributes = null;
+                    if (attr instanceof AttributesImpl) {
+                        attributes = (AttributesImpl) attr;
+                    } else {
+                        attributes = new AttributesImpl(attr);
+                    }
+                    // remove attributes not meant for client
+                    attributes.removeAttribute(attributes.getIndex("name"));
+                    if (when != null)
+                        attributes.removeAttribute(attributes.getIndex("when"));
+                    if (when_ge != null)
+                        attributes.removeAttribute(attributes.getIndex("when-ge"));
+                    this.relayStartElement(uri, name, raw, this.normalizeAttributes(attributes));
+                } else {
+                    this.relayStartElement(true, true, uri, name, raw, attr);
+                }
+            }
+        }
+    }
+
+    /**
+     * Start processing a form element. Sets protection indicator if attribute
+     * "fixed" is present and either "true" or "yes". Removes attribute "fixed"
+     * if present.
+     * @param uri The namespace of the element.
+     * @param name The local name of the element.
+     * @param raw The qualified name of the element.
+     * @param attr The attributes of the element.
+     */
+    protected void startFormElement(String uri, String name, String raw, Attributes attr)
+        throws SAXException {
+
+        String fixed = attr.getValue(this.fixedName);
+        if (this.useFormName) {
+            this.formName = attr.getValue("name");
+        }
+        if (fixed == null) {
+            this.relayStartElement(uri, name, raw, attr);
+        } else {
+            if (!this.fixed && BooleanUtils.toBoolean(fixed)) {
+                this.fixed = true;
+            }
+            // remove attributes not meant for client
+            AttributesImpl attributes = null;
+            if (attr instanceof AttributesImpl) {
+                attributes = (AttributesImpl) attr;
+            } else {
+                attributes = new AttributesImpl(attr);
+            }
+            attributes.removeAttribute(attributes.getIndex(this.fixedName));
+            this.relayStartElement(uri, name, raw, this.normalizeAttributes(attributes));
+        }
+    }
+
+    /**
+     * Start recording repeat element contents and push repeat expression and
+     * variable to repeater stack. Only start recording, if no other recorder is
+     * currently running.
+     *
+     * @param uri
+     * @param name
+     * @param raw
+     * @param attr
+     * @throws SAXException
+     */
+    protected void startRepeatElement(String uri, String name, String raw, Attributes attr)
+        throws SAXException {
+
+        if (this.recordingCount == 0) {
+            if (!(this.fixed || BooleanUtils.toBoolean(attr.getValue(this.fixedName)))) {
+                RepeaterStatus status =
+                    new RepeaterStatus("${" + attr.getValue("using") + "}", 0, attr.getValue("on"));
+                this.repeater.add(status);
+                this.startRecording();
+                this.recordingCount++;
+            } else {
+                this.relayStartElement(uri, name, raw, attr);
+            }
+        } else {
+            this.relayStartElement(uri, name, raw, attr);
+            this.recordingCount++;
+        }
+    }
+
+    /**
+     * Stop recording repeat contents and replay required number of times.
+     * Stop only if outmost repeat element is ending.
+     *
+     * @param uri
+     * @param name
+     * @param raw
+     * @throws SAXException
+     */
+    protected void endRepeatElement(String uri, String name, String raw) throws SAXException {
+        this.recordingCount--;
+        if (this.recordingCount == 0) {
+            DocumentFragment fragment = this.endRecording();
+            RepeaterStatus status = (RepeaterStatus) this.repeater.get(this.repeater.size() - 1);
+            Object[] vals = this.getValues(this.getName(status.expr));
+            int count = (vals != null ? vals.length : 0);
+            for (status.count = 1; status.count <= count; status.count++) {
+                DOMStreamer streamer = new DOMStreamer(this, this);
+                streamer.stream(fragment);
+            }
+            this.repeater.remove(this.repeater.size() - 1);
+        } else {
+            this.relayEndElement(uri, name, raw);
+            if (this.recordingCount < 0) {
+                this.recordingCount = 0;
+            }
+        }
+    }
+
+    /**
+     * Start processing elements of our namespace.
+     * This hook is invoked for each sax event with our namespace.
+     * @param uri The namespace of the element.
+     * @param name The local name of the element.
+     * @param raw The qualified name of the element.
+     * @param attr The attributes of the element.
+     */
+    public void startTransformingElement(String uri, String name, String raw, Attributes attr)
+        throws SAXException {
+
+        if (this.ignoreEventsCount == 0 && this.recordingCount == 0) {
+            switch (((Integer) elementNames.get(name, defaultElement)).intValue()) {
+                case ELEMENT_INPUT :
+                    this.startInputElement(uri, name, raw, attr);
+                    break;
+
+                case ELEMENT_SELECT :
+                    this.startSelectElement(uri, name, raw, attr);
+                    break;
+
+                case ELEMENT_OPTION :
+                    this.startOptionElement(uri, name, raw, attr);
+                    break;
+
+                case ELEMENT_TXTAREA :
+                    this.startTextareaElement(uri, name, raw, attr);
+                    break;
+
+                case ELEMENT_ERROR :
+                    this.startErrorElement(uri, name, raw, attr);
+                    break;
+
+                case ELEMENT_FORM :
+                    this.startFormElement(uri, name, raw, attr);
+                    break;
+
+                case ELEMENT_REPEAT :
+                    this.startRepeatElement(uri, name, raw, attr);
+                    break;
+
+                default :
+                    this.relayStartElement(uri, name, raw, attr);
+            }
+
+        } else if (this.recordingCount > 0) {
+            switch (((Integer) elementNames.get(name, defaultElement)).intValue()) {
+                case ELEMENT_REPEAT :
+                    this.startRepeatElement(uri, name, raw, attr);
+                    break;
+
+                default :
+                    this.relayStartElement(uri, name, raw, attr);
+            }
+        } else {
+            this.relayStartElement(uri, name, raw, attr);
+        }
+    }
+
+    /**
+     * Start processing elements of our namespace.
+     * This hook is invoked for each sax event with our namespace.
+     * @param uri The namespace of the element.
+     * @param name The local name of the element.
+     * @param raw The qualified name of the element.
+     */
+    public void endTransformingElement(String uri, String name, String raw) throws SAXException {
+
+        if (this.ignoreEventsCount > 0) {
+            this.relayEndElement(uri, name, raw);
+        } else if (this.recordingCount > 0) {
+            switch (((Integer) elementNames.get(name, defaultElement)).intValue()) {
+                case ELEMENT_REPEAT :
+                    this.endRepeatElement(uri, name, raw);
+                    break;
+
+                default :
+                    this.relayEndElement(uri, name, raw);
+            }
+        } else {
+            switch (((Integer) elementNames.get(name, defaultElement)).intValue()) {
+                case ELEMENT_SELECT :
+                    this.values = null;
+                    this.relayEndElement(uri, name, raw);
+                    break;
+                case ELEMENT_INPUT :
+                case ELEMENT_OPTION :
+                case ELEMENT_TXTAREA :
+                case ELEMENT_ERROR :
+                    this.relayEndElement(uri, name, raw);
+                    break;
+                case ELEMENT_FORM :
+                    this.fixed = this.documentFixed;
+                    this.formName = null;
+                    this.relayEndElement(uri, name, raw);
+                    break;
+
+                case ELEMENT_REPEAT :
+                    this.endRepeatElement(uri, name, raw);
+                    break;
+
+                default :
+                    this.relayEndElement(uri, name, raw);
+            }
+        }
+    }
+
+    /**
+     * Remove extra information from element's attributes. Currently only removes
+     * the repeater variable from the element's name attribute if present.
+     *
+     * @param attr
+     * @return modified attributes
+     */
+    private Attributes normalizeAttributes(Attributes attr) {
+        Attributes result = attr;
+        if (this.stripNumber && this.repeater.size() > 0) {
+            String name = attr.getValue("name");
+            if (name != null) {
+                for (Iterator i = this.repeater.iterator(); i.hasNext();) {
+                    RepeaterStatus status = (RepeaterStatus) i.next();
+                    int pos = name.indexOf(status.var);
+                    if (pos >= 0) {
+                        AttributesImpl attributes;
+                        if (result instanceof AttributesImpl) {
+                            attributes = (AttributesImpl) result;
+                        } else {
+                            attributes = new AttributesImpl(result);
+                        }
+                        name =
+                            name.substring(0, pos - this.decorationSize)
+                                + name.substring(pos + status.var.length() + this.decorationSize);
+                        attributes.setValue(attributes.getIndex("name"), name);
+                        result = attributes;
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Generate the "real" name of an element for value lookup.
+     * @param name
+     * @return "real" name.
+     */
+    private String getName(String name) {
+        String result = name;
+        if (this.useFormName && this.formName != null) {
+            if (this.separator != null) {
+                if (this.useFormNameTwice) {
+                    result =
+                        this.formName + this.separator + this.formName + this.separator + result;
+                } else {
+                    result = this.formName + this.separator + result;
+                }
+            } else {
+                if (this.useFormNameTwice) {
+                    result = this.formName + result;
+                } else {
+                    // does this make sense ?
+                    result = this.formName + this.formName + result;
+                }
+            }
+        }
+        if (this.prefix != null) {
+            result = this.prefix + result;
+        }
+        if (this.suffix != null) {
+            result = result + this.prefix;
+        }
+        if (this.repeater.size() > 0) {
+            for (Iterator i = this.repeater.iterator(); i.hasNext();) {
+                RepeaterStatus status = (RepeaterStatus) i.next();
+                int pos = result.indexOf(status.var);
+                if (pos != -1) {
+                    result =
+                        result.substring(0, pos)
+                            + status.count
+                            + result.substring(pos + status.var.length());
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Obtain values from used InputModule if not done already and return the
+     * next value. If no more values exist, returns null.
+     *
+     * @param name
+     * @return
+     */
+    private Object getNextValue(String name) {
+        Object result = null;
+        if (this.formValues.containsKey(name)) {
+            ValueList vList = (ValueList) this.formValues.get(name);
+            result = vList.getNext();
+        } else {
+            ValueList vList = new ValueList(this.getValues(name));
+            result = vList.getNext();
+            this.formValues.put(name, vList);
+        }
+        return result;
+    }
+
+    /**
+     * Obtain values from the used InputModule.
+     */
+    private Object[] getValues(String name) {
+        Object[] values = null;
+        ServiceSelector iputSelector = null;
+        InputModule iput = null;
+        try {
+            if (this.input != null) {
+                // input module is thread safe
+                // thus we still have a reference to it
+                values = input.getAttributeValues(name, this.inputConf, objectModel);
+                if (getLogger().isDebugEnabled())
+                    getLogger().debug("cached module " + this.input
+                                      + " attribute " + name
+                                      + " returns " + values);
+            } else {
+                // input was not thread safe
+                // so acquire it again
+                iputSelector = (ServiceSelector)this.manager.lookup(INPUT_MODULE_SELECTOR);
+                if (this.inputName != null
+                    && iputSelector != null
+                    && iputSelector.isSelectable(this.inputName)) {
+
+                    iput = (InputModule) iputSelector.select(this.inputName);
+                }
+                if (iput != null) {
+                    values = iput.getAttributeValues(name, this.inputConf, objectModel);
+                }
+                if (getLogger().isDebugEnabled())
+                    getLogger().debug(
+                        "fresh module " + iput + " attribute " + name + " returns " + values);
+            }
+        } catch (Exception e) {
+            if (getLogger().isWarnEnabled())
+                getLogger().warn(
+                    "A problem occurred acquiring a value from '"
+                        + this.inputName
+                        + "' for '"
+                        + name
+                        + "': "
+                        + e.getMessage());
+        } finally {
+            // release components if necessary
+            if (iputSelector != null) {
+                if (iput != null)
+                    iputSelector.release(iput);
+                this.manager.release(iputSelector);
+            }
+        }
+
+        return values;
+    }
+
+    /**
+     * Calls the super's method startTransformingElement.
+     *
+     * @param uri
+     * @param name
+     * @param raw
+     * @param attr
+     * @throws SAXException
+     */
+    protected void relayStartElement(String uri, String name, String raw, Attributes attr)
+        throws SAXException {
+        this.relayStartElement(false, false, uri, name, raw, attr);
+    }
+
+    /**
+     * Calls the super's method startTransformingElement and increments the
+     * ignoreEventsCount if skip is true. Increment can be done either before
+     * invoking super's method, so that the element itself is skipped, or afterwards,
+     * so that only the children are skipped.
+     *
+     * @param skip
+     * @param skipChildrenOnly
+     * @param uri
+     * @param name
+     * @param raw
+     * @param attr
+     * @throws SAXException
+     */
+    protected void relayStartElement(
+        boolean skip,
+        boolean skipChildrenOnly,
+        String uri,
+        String name,
+        String raw,
+        Attributes attr)
+        throws SAXException {
+
+        try {
+            if (this.ignoreEventsCount > 0) {
+                this.ignoreEventsCount++;
+                super.startTransformingElement(uri, name, raw, attr);
+            } else {
+                if (skip)
+                    this.skipChildrenOnly = skipChildrenOnly;
+                if (skip && !skipChildrenOnly)
+                    this.ignoreEventsCount++;
+                super.startTransformingElement(uri, name, raw, attr);
+                if (skip && skipChildrenOnly)
+                    this.ignoreEventsCount++;
+            }
+        } catch (ProcessingException e) {
+            throw new SAXException(e);
+        } catch (IOException e) {
+            throw new SAXException(e);
+        }
+    }
+
+    /**
+     * Calls the super's method endTransformingElement and decrements the
+     * ignoreEventsCount if larger than zero.
+     *
+     * @param uri
+     * @param name
+     * @param raw
+     * @throws SAXException
+     */
+    protected void relayEndElement(String uri, String name, String raw) throws SAXException {
+
+        if (this.ignoreEventsCount == 1 && this.skipChildrenOnly)
+            this.ignoreEventsCount--;
+        try {
+            super.endTransformingElement(uri, name, raw);
+        } catch (ProcessingException e) {
+            throw new SAXException(e);
+        } catch (IOException e) {
+            throw new SAXException(e);
+        } catch (Exception e) {
+            getLogger().error("exception", e);
+        }
+
+        if (this.ignoreEventsCount > 0)
+            this.ignoreEventsCount--;
+    }
+
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/SimpleFormTransformer.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message