cocoon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jheym...@apache.org
Subject svn commit: r330548 [102/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-forms-block/impl/src/main/java/org/apache/cocoon/forms/transformation/FormsPipelineConfig.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/transformation/FormsPipelineConfig.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/transformation/FormsPipelineConfig.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/transformation/FormsPipelineConfig.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,388 @@
+/*
+ * 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.forms.transformation;
+
+import org.apache.avalon.framework.parameters.Parameters;
+
+import org.apache.cocoon.components.flow.FlowHelper;
+import org.apache.cocoon.components.flow.WebContinuation;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Request;
+import org.apache.cocoon.environment.Session;
+import org.apache.cocoon.forms.formmodel.Form;
+import org.apache.cocoon.i18n.I18nUtils;
+import org.apache.cocoon.util.Deprecation;
+
+import org.apache.commons.jxpath.JXPathContext;
+import org.apache.commons.jxpath.JXPathException;
+import org.apache.commons.jxpath.Variables;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * @version $Id: FormsPipelineConfig.java 289538 2005-09-16 13:46:22Z sylvain $
+ */
+public class FormsPipelineConfig {
+
+    /**
+     * Default key under which the Cocoon Forms form instance is stored in the JXPath context.
+     */
+    public static final String CFORMSKEY = "CocoonFormsInstance";
+
+    /**
+     * Name of the request attribute under which the Cocoon Form is stored (optional). */
+    private final String attributeName;
+
+    /**
+     * Pointer to the current request object.
+     */
+    private final Request request;
+
+    /**
+     * Initialized jxpathcontext to evaluate passed expressions with.
+     */
+    private final JXPathContext jxpathContext;
+
+    /**
+     * Containts locale specified as a parameter to the transformer, if any.
+     */
+    private final Locale localeParameter;
+
+    /**
+     * The locale currently used by the transformer.
+     */
+    private Locale locale;
+
+    /**
+     * Value for the action attribute of the form.
+     */
+    private String formAction;
+
+    /**
+     * Value for the method attribute of the form.
+     */
+    private String formMethod;
+
+
+    private FormsPipelineConfig(JXPathContext jxpc, Request req, Locale localeParam,
+                                String attName, String actionExpression, String method) {
+        this.attributeName = attName;
+        this.request = req;
+        this.jxpathContext =jxpc;
+        this.localeParameter = localeParam;
+        this.formAction = translateText(actionExpression);
+        this.formMethod = method;
+    }
+
+    /**
+     * Creates and initializes a FormsPipelineConfig object based on the passed
+     * arguments of the setup() of the specific Pipeline-component.
+     *
+     * @param objectModel the objectmodel as passed in the setup()
+     * @param parameters the parameters as passed in the setup()
+     * @return an instance of FormsPipelineConfig initialized according to the
+     * settings in the sitemap.
+     */
+    public static FormsPipelineConfig createConfig(Map objectModel, Parameters parameters) {
+        // create and set the jxpathContext...
+        Object flowContext = FlowHelper.getContextObject(objectModel);
+        WebContinuation wk = FlowHelper.getWebContinuation(objectModel);
+        JXPathContext jxpc = JXPathContext.newContext(flowContext);
+        // We manually create a cocoon object here to provide the same way
+        // of accessing things as in the jxtg
+        // as soon as we have our unified om, we should use that
+        Request request = ObjectModelHelper.getRequest(objectModel);
+        Session session = request.getSession(false);
+        final Map cocoonOM = new HashMap();
+        cocoonOM.put("continuation", wk);
+        cocoonOM.put("request", request);
+        if ( session != null ) {
+            cocoonOM.put("session", session);
+        }
+        cocoonOM.put("parameters", parameters);
+
+        FormsVariables vars = new FormsVariables();
+        vars.declareVariable("cocoon", cocoonOM);
+        // These four are deprecated!
+        vars.declareVariable("continuation", wk);
+        vars.declareVariable("request", request);
+        vars.declareVariable("session", session);
+        vars.declareVariable("parameters", parameters);
+        vars.addDeprecatedVariable("continuation");
+        vars.addDeprecatedVariable("request");
+        vars.addDeprecatedVariable("session");
+        vars.addDeprecatedVariable("parameters");
+        jxpc.setVariables(vars);
+
+        Locale localeParameter = null;
+        String localeStr = parameters.getParameter("locale", null);
+        if (localeStr != null) {
+            localeParameter = I18nUtils.parseLocale(localeStr);
+        }
+
+        String attributeName = parameters.getParameter("attribute-name", null);
+        String actionExpression = parameters.getParameter("form-action", null);
+        String formMethod = parameters.getParameter("form-method", null);
+        //TODO (20031223 mpo)think about adding form-encoding for the Generator.
+        // Note generator will also need some text to go on the submit-button?
+        // Alternative to adding more here is to apply xinclude ?
+
+        return new FormsPipelineConfig(jxpc, request, localeParameter,
+                attributeName, actionExpression, formMethod);
+    }
+
+    /**
+     * Overloads {@link #findForm(String)} by setting the jxpath-expression to null
+     */
+    public Form findForm() throws SAXException {
+        return this.findForm(null);
+    }
+
+    /**
+     * Finds the form from the current request-context based on the settings of
+     * this configuration object.  The fall-back search-procedure is as follows:
+     * <ol><li>Use the provided jxpathExpression (if not null)</li>
+     * <li>Use the setting of the 'attribute-name' parameter on the request</li>
+     * <li>Obtain the form from it's default location in the flow context</li>
+     * </ol>
+     *
+     * @param jxpathExpression that should be pointing to the form
+     * @return the found form if found
+     * @throws SAXException in any of the following cases:
+     * <ul><li>The provided jxpathExpression (if not null) not point to a
+     * {@link Form} instance.</li>
+     * <li>The request is not holding a {@link Form} instance under the key
+     * specified by 'attribute-name' (if specified)</li>
+     * <li>Both jxpathExpression and 'attribute-name' were not specified AND
+     * also the default location was not holding a valid {@link Form} instance.</li>
+     * </ol>
+     */
+    public Form findForm(String jxpathExpression) throws SAXException {
+        Object form = null;
+        if (jxpathExpression != null) {
+            form = this.jxpathContext.getValue(jxpathExpression);
+            if (form == null) {
+                throw new SAXException("No Cocoon Form found at location \"" + jxpathExpression + "\".");
+            } else if (!(form instanceof Form)) {
+                throw new SAXException("Object returned by expression \"" + jxpathExpression + "\" is not a Cocoon Form.");
+            }
+        } else if (this.attributeName != null) { // then see if an attribute-name was specified
+            form = this.request.getAttribute(this.attributeName);
+            if (form == null) {
+                throw new SAXException("No Cocoon Form found in request attribute with name \"" + this.attributeName + "\"");
+            } else if (!(form instanceof Form)) {
+                throw new SAXException("Object found in request (attribute = '" + this.attributeName + "') is not a Cocoon Form.");
+            }
+        } else { // and then see if we got a form from the flow
+            jxpathExpression = "/" + FormsPipelineConfig.CFORMSKEY;
+            try {
+                form = this.jxpathContext.getValue(jxpathExpression);
+            } catch (JXPathException e) { /* do nothing */ }
+            if (form == null) {
+                throw new SAXException("No Cocoon Form found.");
+            }
+        }
+        return (Form)form;
+    }
+
+    /**
+     * Replaces JXPath expressions embedded inside #{ and } by their value.
+     * This will parse the passed String looking for #{} occurences and then
+     * uses the {@link #evaluateExpression(String)} to evaluate the found expression.
+     *
+     * @return the original String with it's #{}-parts replaced by the evaulated results.
+     */
+    public String translateText(String original) {
+        if (original==null) {
+            return null;
+        }
+
+        StringBuffer expression;
+        StringBuffer translated = new StringBuffer();
+        StringReader in = new StringReader(original);
+        int chr;
+        try {
+            while ((chr = in.read()) != -1) {
+                char c = (char) chr;
+                if (c == '#') {
+                    chr = in.read();
+                    if (chr != -1) {
+                        c = (char) chr;
+                        if (c == '{') {
+                            expression = new StringBuffer();
+                            boolean more = true;
+                            while ( more ) {
+                                more = false;
+                                if ((chr = in.read()) != -1) {
+                                    c = (char)chr;
+                                    if (c != '}') {
+                                        expression.append(c);
+                                        more = true;
+                                    } else {
+                                        translated.append(evaluateExpression(expression.toString()).toString());
+                                    }
+                                } else {
+                                    translated.append('#').append('{').append(expression);
+                                }
+                            }
+                        }
+                    } else {
+                        translated.append((char) chr);
+                    }
+                } else {
+                    translated.append(c);
+                }
+            }
+        } catch (IOException ignored) {
+            ignored.printStackTrace();
+        }
+        return translated.toString();
+    }
+
+    /**
+     * Evaluates the passed xpath expression using the internal jxpath context
+     * holding the declared variables:
+     * <ol><li>continuation: as made available by flowscript</li>
+     * <li>request: as present in the cocoon processing environment</li>
+     * <li>session: as present in the cocoon processing environment</li>
+     * <li>parameters: as present in the cocoon sitemap node of the pipeline component</li></ol>
+     *
+     * @param expression
+     * @return the object-value resulting the expression evaluation.
+     */
+    public Object evaluateExpression(String expression) {
+        return this.jxpathContext.getValue(expression);
+    }
+
+    public Locale getLocale() {
+        return locale;
+    }
+
+    public void setLocale(Locale locale) {
+        this.locale = locale;
+    }
+
+    public Locale getLocaleParameter() {
+        return localeParameter;
+    }
+
+    /**
+     * The value for the wi:form-generated/@action.
+     * Note: wi:form-template copies this from its wt:form-template counterpart.
+     *
+     * @return the {@link #translateText(String)} result of the 'form-action' sitemap
+     * parameter to the pipeline component, or null if that parameter was not set.
+     */
+    public String getFormAction() {
+        return formAction;
+    }
+
+    /**
+     * The value for the wi:form-generated/@method.
+     * Note: wi:form-template copies this from its wt:form-template counterpart.
+     *
+     * @return the value of the 'form-method' sitemap parameter to the pipeline
+     * component. (or 'null' if it was not set.)
+     */
+    public String getFormMethod() {
+        return formMethod;
+    }
+
+
+    /**
+     * Sets the form method to use in the generator/transformer that uses this.
+     *
+     * @param method to use in the generated form should be "POST", "GET" or null
+     */
+    public void setFormMethod(String method) {
+        this.formMethod = method;
+    }
+
+    /**
+     * The grouped attributes to set on the wi:form-generated element.
+     * Note: wi:form-template copies this from its wt:form-template counterpart.
+     *
+     * @see #getFormAction()
+     * @see #getFormMethod()
+     */
+    public Attributes getFormAttributes() {
+        AttributesImpl attrs = new org.apache.cocoon.xml.AttributesImpl();
+        addFormAttributes(attrs);
+        return attrs;
+    }
+
+    public void addFormAttributes(AttributesImpl attrs) {
+        if (getFormAction() != null) {
+            attrs.addAttribute("", "action", "action", "CDATA", getFormAction());
+        }
+        if (getFormMethod() != null){
+            attrs.addAttribute("", "method", "method", "CDATA", getFormMethod());
+        }
+    }
+
+    public static final class FormsVariables implements Variables {
+
+        final Map vars = new HashMap();
+        final List deprecatedNames = new ArrayList();
+
+        public void addDeprecatedVariable(String name) {
+            this.deprecatedNames.add(name);
+        }
+
+        /* (non-Javadoc)
+         * @see org.apache.commons.jxpath.Variables#declareVariable(java.lang.String, java.lang.Object)
+         */
+        public void declareVariable(String name, Object value) {
+            this.vars.put(name, value);
+        }
+
+        /* (non-Javadoc)
+         * @see org.apache.commons.jxpath.Variables#getVariable(java.lang.String)
+         */
+        public Object getVariable(String name) {
+            Object value = this.vars.get(name);
+            if ( deprecatedNames.contains(name) ) {
+                Deprecation.logger.warn("CForms: usage of the variable '" + name + "' is deprecated."+
+                                        "Please use 'cocoon/" + name + "' instead. The usage of just '"+
+                                        name+"' will be removed in Cocoon 2.2.");
+            }
+            return value;
+        }
+
+        /* (non-Javadoc)
+         * @see org.apache.commons.jxpath.Variables#isDeclaredVariable(java.lang.String)
+         */
+        public boolean isDeclaredVariable(String name) {
+            return this.vars.containsKey(name);
+        }
+
+        /* (non-Javadoc)
+         * @see org.apache.commons.jxpath.Variables#undeclareVariable(java.lang.String)
+         */
+        public void undeclareVariable(String name) {
+            this.vars.remove(name);
+        }
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/transformation/FormsPipelineConfig.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/transformation/FormsTemplateTransformer.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/transformation/FormsTemplateTransformer.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/transformation/FormsTemplateTransformer.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/transformation/FormsTemplateTransformer.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,42 @@
+/*
+ * 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.forms.transformation;
+
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.cocoon.transformation.Transformer;
+
+import org.apache.avalon.framework.parameters.Parameters;
+
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * See description of {@link EffectWidgetReplacingPipe}.
+ *
+ * @version $Id: FormsTemplateTransformer.java 170955 2005-05-19 16:28:58Z vgritsenko $
+ */
+public class FormsTemplateTransformer extends EffectWidgetReplacingPipe implements Transformer {
+
+    public void setup(SourceResolver resolver, Map objectModel, String src, Parameters parameters)
+    throws ProcessingException, SAXException, IOException {
+
+        FormsPipelineConfig pipeContext = FormsPipelineConfig.createConfig(objectModel, parameters);
+        super.init(null, pipeContext);
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/transformation/FormsTemplateTransformer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/CombiningMap.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/CombiningMap.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/CombiningMap.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/CombiningMap.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,176 @@
+/*
+ * Copyright 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.forms.util;
+
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * A read-only implementation of <code>Map</code> that combines several other maps.
+ * 
+ * @version $Id: CombiningMap.java 327577 2005-10-21 20:59:14Z sylvain $
+ */
+public class CombiningMap extends AbstractMap {
+
+    private List maps = new ArrayList();
+    private boolean locked = false;
+
+    /**
+     * Adds a <code>Map</code> in the combined map, with the lowest lookup priority.
+     * <p>
+     * New maps cannot be added if this object was already iterated.
+     * 
+     * @param map the new map
+     * @return this object, as a convenience to write <code>combiner.add(map1).add(map2).add(map3)</code>
+     * @throw IllegalStateException if this object was already iterated.
+     */
+    public CombiningMap add(Map map) {
+        if (locked) {
+            throw new IllegalStateException("Cannot add new Maps to a CombiningMap once it has been iterated");
+        }
+        maps.add(map);
+        
+        return this;
+    }
+    
+    public Object get(Object key) {
+        // Faster implemetation than the default in AbstractMap
+        for (int i = 0; i < maps.size(); i++) {
+            Map map = (Map)maps.get(i);
+            Object result = map.get(key);
+
+            if (result != null) {
+                return result;
+            }
+
+            if (map.containsKey(key)) {
+                return null;
+            }
+        }
+        
+        return null;
+    }
+    
+    public boolean containsKey(Object key) {
+        // Faster implemetation than the default in AbstractMap
+        for (int i = 0; i < maps.size(); i++) {
+            Map map = (Map)maps.get(i);
+            if (map.containsKey(key)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public Set entrySet() {
+        locked = true;
+        return new CombiningEntrySet();
+    }
+
+    private class CombiningEntrySet extends AbstractSet {
+
+        public Iterator iterator() {
+            return new CombiningIterator();
+        }
+
+        /**
+         * Super inefficient way, but this implementation is meant to be super-lightweight
+         * and efficient at iterations.
+         */
+        public int size() {
+           
+            int size = 0;
+            Iterator iter = iterator();
+            while (iter.hasNext()) {
+                size++;
+                iter.next();
+            }
+            return size;
+        }
+    }
+    
+    private class CombiningIterator implements Iterator {
+        
+        private int index;
+        private Iterator delegate;
+        private Map.Entry next;
+
+        public CombiningIterator() {
+            // Initialize the first result
+            if (!maps.isEmpty()) {
+                delegate = ((Map)maps.get(0)).entrySet().iterator();
+                if (delegate.hasNext()) {
+                    next = (Map.Entry)delegate.next();
+                }
+            }
+            
+        }
+        public boolean hasNext() {
+            return next != null;
+        }
+
+        public Object next() {
+            if (next == null) {
+                throw new NoSuchElementException();
+            }
+            Object result = next;
+            fetchNext();
+            return result;
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+        
+        private void fetchNext() {
+            boolean skip;
+            do {
+                // Get an iterator that has more values
+                while (delegate != null && !delegate.hasNext()) {
+                    // Ended iteration on the previous map
+                    index++;
+                    if (index < maps.size()) {
+                        delegate = ((Map)maps.get(index)).entrySet().iterator();
+                    } else {
+                        // Iteration finished
+                        next = null;
+                        delegate = null;
+                        return;
+                    }
+                }
+                
+                // Get the next entry
+                next = (Map.Entry)delegate.next();
+                
+                // Skip it if its key doesn't exist in the previous Maps
+                Object key = next.getKey();
+                skip = false;
+                for (int i = 0; i < index-1; i++) {
+                    if (((Map)maps.get(i)).containsKey(key)) {
+                        skip = true;
+                        continue;
+                    }
+                }
+            } while(skip);
+        }
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/CombiningMap.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/ContainerWidgetAsMap.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/ContainerWidgetAsMap.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/ContainerWidgetAsMap.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/ContainerWidgetAsMap.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,226 @@
+/*
+ * 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.forms.util;
+
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.cocoon.forms.formmodel.AbstractContainerWidget;
+import org.apache.cocoon.forms.formmodel.ContainerWidget;
+import org.apache.cocoon.forms.formmodel.Repeater;
+import org.apache.cocoon.forms.formmodel.Widget;
+import org.apache.commons.collections.iterators.AbstractIteratorDecorator;
+
+/**
+ * A <code>Map</code> view of a container widget, keys being children names and values either
+ * maps (for container children), objects (for terminal children) or lists (for repeaters).
+ * <p>
+ * The returned map is non-modifiable, except using the <code>put()</code> method, which much
+ * refer to an existing child widget, and <code>putAll(Map)</code> that will silently ignore keys
+ * that don't refer to existing child widgets.
+ * <p>
+ * Also, this map accepts getting and setting values for keys that correspond to value-less widgets
+ * such as {@link org.apache.cocoon.forms.formmodel.Action}. The result in that case is always
+ * <code>null</code>. This is to allow global retrieving or filling of the map values.
+ * 
+ * @since 2.1.8
+ * @version $Id: ContainerWidgetAsMap.java 327865 2005-10-23 22:03:06Z sylvain $
+ */
+public class ContainerWidgetAsMap extends AbstractMap {
+    private AbstractContainerWidget container;
+    private boolean lowerCase;
+
+    /**
+     * Wraps a container widget in a <code>Map</code>.
+     * <p>
+     * The <code>keysToLowerCase</code> argument specifies if input keys given in <code>get()</code>,
+     * <code>put()</code> and <code>putAll()</code> should be converted to lower case before searching for
+     * the corresponding widget. This feature allows to directly feed widgets with <code>Map</code>s coming
+     * from JDBC resultset rows where keys are uppercase (see <a href="http://jdbi.codehaus.org">JDBI</a>).
+     * 
+     * @param container the container to wrap
+     * @param keysToLowerCase should we convert keys to lower case?
+     */
+    public ContainerWidgetAsMap(AbstractContainerWidget container, boolean keysToLowerCase) {
+        this.container = container;
+        this.lowerCase = keysToLowerCase;
+    }
+
+    /**
+     * Same as <code>ContainerWidgetAsMap(container, false)</code>
+     */
+    public ContainerWidgetAsMap(AbstractContainerWidget container) {
+        this(container, false);
+    }
+
+    /**
+     * Get the container widget that is wrapped by this <code>Map</code>.
+     * 
+     * @return the wrapped {@link ContainerWidget}
+     */
+    public ContainerWidget getWidget() {
+        return this.container;
+    }
+    
+    /**
+     * Get a widget relative to the container wrapped by this <code>Map</code>
+     * 
+     * @param path a widget lookup path
+     * @return the widget pointed to by <code>path</code> or <code>null</code> if it doesn't exist.
+     * @see Widget#lookupWidget(String)
+     */
+    public Widget getWidget(String path) {
+        return this.container.lookupWidget(path);
+    }
+
+    /**
+     * Put a value in a child widget. The value must be compatible with the datatype
+     * expected by the child widget. In the case of repeaters and containers, this
+     * datatype is <code>Collection</code> and <code>Map</code> respectively, which
+     * will be used to fill the rows and child widgets.
+     * <p>
+     * Note also that the contract of <code>put</code> requires the previous value
+     * to be returned. In the case of repeaters and containers, the value is a live
+     * wrapper around the actual widget, meaning that it's not different from the
+     * current value.
+     */
+    public Object put(Object key, Object value) {
+        String name = (String)key;
+        if (lowerCase) name = name.toLowerCase();
+        
+        Widget w = container.getChild(name);
+        if (w != null) {
+            return setValue(w, value);
+        } else {
+            throw new UnsupportedOperationException(container + " has no child named '" + key + "'");
+        }
+    }
+
+    public void putAll(Map map) {
+        Iterator iter = map.entrySet().iterator();
+        while(iter.hasNext()) {
+            Map.Entry entry = (Map.Entry)iter.next();
+            String name = (String)entry.getKey();
+            if (lowerCase) name = name.toLowerCase();
+            Widget w = container.getChild(name);
+            if (w != null) {
+                setValue(w, entry.getValue());
+            }
+        }
+    }
+
+    public Object get(Object key) {
+        String name = (String)key;
+        if (lowerCase) name = name.toLowerCase();
+        Widget w = container.getChild(name);
+        return w == null ? null : asValueOrMap(w);
+    }
+
+    public Set entrySet() {
+        return new ContainerEntrySet();
+    }
+
+    private Object asValueOrMap(Widget w) {
+        if (w instanceof Repeater) {
+            return new RepeaterAsList((Repeater)w, lowerCase);
+        } else if (w instanceof AbstractContainerWidget) {
+            return new ContainerWidgetAsMap((AbstractContainerWidget)w, lowerCase);
+        } else {
+            try {
+                return w.getValue();
+            } catch (UnsupportedOperationException uoe) {
+                // This widget doesn't hold a value
+                return null;
+            }
+        }
+    }
+
+    /**
+     * Set a widget's value and returns the previous value as required by put().
+     */
+    private Object setValue(Widget w, Object value) {
+        if (w instanceof Repeater) {
+            // Must be a collection
+            if (!(value instanceof Collection)) {
+                throw new IllegalArgumentException("A repeater cannot be filled with " + value);
+            }
+            List result = new RepeaterAsList((Repeater)w, lowerCase);
+            result.addAll((Collection)value);
+            return result;
+
+        } else if (w instanceof AbstractContainerWidget) {
+            // Must be a map
+            if (!(value instanceof Map)) {
+                throw new IllegalArgumentException("A container cannot be filled with " + value);
+            }
+            Map result = new ContainerWidgetAsMap((AbstractContainerWidget)w);
+            result.putAll((Map)value);
+            return result;
+        } else {
+            try {
+                Object result = w.getValue();
+                w.setValue(value);
+                return result;
+            } catch (UnsupportedOperationException uoe) {
+                // This widget doesn't hold a value
+                return null;
+            }
+        }
+    }
+
+    private class ContainerEntrySet extends AbstractSet {
+        public Iterator iterator() {
+            return new ContainerEntryIterator();
+        }
+
+        public int size() {
+            return container.getSize();
+        }
+    }
+
+    private class ContainerEntryIterator extends AbstractIteratorDecorator {
+        public ContainerEntryIterator() {
+            super(container.getChildren());
+        }
+
+        public Object next() {
+            return new ContainerEntry((Widget)super.next());
+        }
+    }
+
+    private class ContainerEntry implements Map.Entry {
+        Widget widget;
+        public ContainerEntry(Widget w) {
+            widget = w;
+        }
+        public Object getKey() {
+            return widget.getName();
+        }
+        public Object getValue() {
+            return asValueOrMap(widget);
+        }
+        public Object setValue(Object value) {
+            Object result = asValueOrMap(widget);
+            ContainerWidgetAsMap.this.setValue(widget, value);
+            return result;
+        }
+    }
+}
\ No newline at end of file

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/ContainerWidgetAsMap.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/DomHelper.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/DomHelper.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/DomHelper.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/DomHelper.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,361 @@
+/*
+ * 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.forms.util;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.cocoon.util.location.Location;
+import org.apache.cocoon.util.location.LocationAttributes;
+import org.apache.cocoon.xml.SaxBuffer;
+import org.apache.cocoon.xml.dom.DOMBuilder;
+import org.apache.cocoon.xml.dom.DOMStreamer;
+import org.apache.commons.lang.BooleanUtils;
+import org.apache.excalibur.xml.sax.SAXParser;
+import org.apache.excalibur.xml.sax.XMLizable;
+import org.w3c.dom.Attr;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotSupportedException;
+
+/**
+ * Helper class to create and retrieve information from DOM-trees. It provides
+ * some functionality comparable to what's found in Avalon's Configuration
+ * objects. These lasts one could however not be used by Cocoon Forms because they
+ * don't provide an accurate model of an XML file (no mixed content,
+ * no namespaced attributes, no namespace declarations, ...).
+ *
+ * <p>This class depends specifically on the Xerces DOM implementation to be
+ * able to provide information about the location of elements in their source
+ * XML file. See the {@link #getLocation(Element)} method.
+ * 
+ * @version $Id: DomHelper.java 289538 2005-09-16 13:46:22Z sylvain $
+ */
+public class DomHelper {
+
+    public static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/";
+
+    public static Location getLocationObject(Element element) {
+        return LocationAttributes.getLocation(element);
+    }
+
+    /**
+     * Retrieves the location of an element node in the source file from which
+     * the Document was created. This will only work for Document's created
+     * with the method {@link #parse(InputSource)} of this class.
+     */
+    public static String getLocation(Element element) {
+        return LocationAttributes.getLocationString(element);
+    }
+    
+    public static String getSystemIdLocation(Element element) {
+        return LocationAttributes.getURI(element);
+    }
+    
+    public static int getLineLocation(Element element) {
+        return LocationAttributes.getLine(element);
+    }
+
+    public static int getColumnLocation(Element element) {
+        return LocationAttributes.getColumn(element);
+    }
+
+    /**
+     * Returns all Element children of an Element that belong to the given
+     * namespace.
+     */
+    public static Element[] getChildElements(Element element, String namespace) {
+        ArrayList elements = new ArrayList();
+        NodeList nodeList = element.getChildNodes();
+        for (int i = 0; i < nodeList.getLength(); i++) {
+            Node node = nodeList.item(i);
+            if (node instanceof Element
+                    && namespace.equals(node.getNamespaceURI()))
+                elements.add(node);
+        }
+        return (Element[])elements.toArray(new Element[elements.size()]);
+    }
+
+    /**
+     * Returns all Element children of an Element that belong to the given
+     * namespace and have the given local name.
+     */
+    public static Element[] getChildElements(Element element,
+            String namespace, String localName) {
+        ArrayList elements = new ArrayList();
+        NodeList nodeList = element.getChildNodes();
+        for (int i = 0; i < nodeList.getLength(); i++) {
+            Node node = nodeList.item(i);
+            if (node instanceof Element
+                    && namespace.equals(node.getNamespaceURI()) 
+                    && localName.equals(node.getLocalName())) {
+                elements.add(node);
+            }
+        }
+        return (Element[])elements.toArray(new Element[elements.size()]);
+    }
+
+    /**
+     * Returns the first child element with the given namespace and localName,
+     * or null if there is no such element.
+     */
+    public static Element getChildElement(Element element, String namespace, 
+            String localName) {
+        Element node = null;
+        try {
+            node = getChildElement(element, namespace, localName, false);
+        } catch (Exception e) {
+            node = null;
+        }
+        return node;
+    }
+
+    /**
+     * Returns the first child element with the given namespace and localName,
+     * or null if there is no such element and required flag is unset or
+     * throws an Exception if the "required" flag is set.
+     */
+    public static Element getChildElement(Element element, String namespace, 
+            String localName, boolean required) throws Exception {
+        NodeList nodeList = element.getChildNodes();
+        for (int i = 0; i < nodeList.getLength(); i++) {
+            Node node = nodeList.item(i);
+            if (node instanceof Element
+                    && namespace.equals(node.getNamespaceURI()) 
+                    && localName.equals(node.getLocalName())) {
+                return (Element)node;
+            }
+        }
+        if (required) {
+            throw new Exception("Missing element \"" + localName +
+                    "\" as child of element \"" + element.getTagName() + 
+                    "\" at " + DomHelper.getLocation(element));
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value of an element's attribute, but throws an exception
+     * if the element has no such attribute.
+     */
+    public static String getAttribute(Element element, String attributeName)
+            throws Exception {
+        String attrValue = element.getAttribute(attributeName);
+        if (attrValue.equals("")) {
+            throw new Exception("Missing attribute \"" + attributeName + 
+                    "\" on element \"" + element.getTagName() + 
+                    "\" at " + getLocation(element));
+        }
+        return attrValue;
+    }
+
+    /**
+     * Returns the value of an element's attribute, or a default value if the 
+     * element has no such attribute.
+     */
+    public static String getAttribute(Element element, String attributeName, 
+            String defaultValue) {
+        String attrValue = element.getAttribute(attributeName);
+        if (attrValue.equals("")) {
+            return defaultValue;
+        }
+        return attrValue;
+    }
+
+    public static int getAttributeAsInteger(Element element, 
+            String attributeName) throws Exception {
+        String attrValue = getAttribute(element, attributeName);
+        try {
+            return Integer.parseInt(attrValue);
+        } catch (NumberFormatException e) {
+            throw new Exception("Cannot parse the value \"" + attrValue + 
+                    "\" as an integer in the attribute \"" + attributeName + 
+                    "\" on the element \"" + element.getTagName() + 
+                    "\" at " + getLocation(element));
+        }
+    }
+
+    public static int getAttributeAsInteger(Element element, 
+            String attributeName, int defaultValue) throws Exception {
+        String attrValue = element.getAttribute(attributeName);
+        if (attrValue.equals("")) {
+            return defaultValue;
+        } else {
+            try {
+                return Integer.parseInt(attrValue);
+            } catch (NumberFormatException e) {
+                throw new Exception("Cannot parse the value \"" + attrValue + 
+                        "\" as an integer in the attribute \"" + 
+                        attributeName + "\" on the element \"" +
+                        element.getTagName() + "\" at " +
+                        getLocation(element));
+            }
+        }
+    }
+
+    public static boolean getAttributeAsBoolean(Element element, 
+                String attributeName, boolean defaultValue) {
+        String attrValue = element.getAttribute(attributeName);
+        Boolean result;
+        try {
+            result = BooleanUtils.toBooleanObject(attrValue, "true", "false", null);
+        } catch (IllegalArgumentException iae) {
+            result = null;
+        }
+        if (result != null) {
+            return result.booleanValue();
+        }
+        try {
+            result = BooleanUtils.toBooleanObject(attrValue, "yes", "no", null);
+        } catch (IllegalArgumentException iae) {
+            result = null;
+        }
+        if (result != null) {
+            return result.booleanValue();
+        }
+        return defaultValue;    
+    }
+
+    public static String getElementText(Element element) {
+        StringBuffer value = new StringBuffer();
+        NodeList nodeList = element.getChildNodes();
+        for (int i = 0; i < nodeList.getLength(); i++) {
+            Node node = nodeList.item(i);
+            if (node instanceof Text || node instanceof CDATASection) {
+                value.append(node.getNodeValue());
+            }
+        }
+        return value.toString();
+    }
+
+    /**
+     * Returns the content of the given Element as an object implementing the
+     * XMLizable interface. Practically speaking, the implementation uses the
+     * {@link SaxBuffer} class. The XMLizable object will be a standalone blurb
+     * of SAX events, not producing start/endDocument calls and containing all
+     * necessary namespace declarations.
+     */
+    public static XMLizable compileElementContent(Element element) {
+        SaxBuffer saxBuffer = new SaxBuffer();
+        DOMStreamer domStreamer = new DOMStreamer();
+        domStreamer.setContentHandler(saxBuffer);
+
+        NodeList childNodes = element.getChildNodes();
+        for (int i = 0; i < childNodes.getLength(); i++) {
+            try {
+                domStreamer.stream(childNodes.item(i));
+            } catch (SAXException e) {
+                // It's unlikely that an exception will occur here,
+                // so use a runtime exception
+                throw new RuntimeException(
+                        "Error in DomHelper.compileElementContent: " + 
+                        e.toString());
+            }
+        }
+        return saxBuffer;
+    }
+
+    /**
+     * Creates a W3C Document that remembers the location of each element in
+     * the source file. The location of element nodes can then be retrieved
+     * using the {@link #getLocation(Element)} method.
+     *
+     * @param inputSource the inputSource to read the document from
+     * @param manager the service manager where to lookup the entity resolver
+     */
+    public static Document parse(InputSource inputSource, ServiceManager manager)
+            throws SAXException, SAXNotSupportedException, IOException, ServiceException {
+        
+        SAXParser parser = (SAXParser)manager.lookup(SAXParser.ROLE);
+        DOMBuilder builder = new DOMBuilder();
+        
+        // Enhance the sax stream with location information
+        ContentHandler locationHandler = new LocationAttributes.Pipe(builder);
+        
+        try {
+            parser.parse(inputSource, locationHandler);
+        } finally {
+            manager.release(parser);
+        }
+        
+        return builder.getDocument();
+    }
+
+    public static Map getLocalNSDeclarations(Element elm)
+    {
+        return addLocalNSDeclarations(elm, null);
+    }
+    
+    private static Map addLocalNSDeclarations(Element elm, Map nsDeclarations)
+    {
+        NamedNodeMap atts = elm.getAttributes();
+        int attsSize = atts.getLength();
+
+        for (int i = 0; i < attsSize; i++)
+        {
+            Attr attr = (Attr)atts.item(i);
+            if (XMLNS_URI.equals(attr.getNamespaceURI()))
+            {
+                String nsUri = attr.getValue();
+                String pfx = attr.getLocalName();
+                if (nsDeclarations == null)
+                    nsDeclarations = new HashMap();
+                nsDeclarations.put(nsUri, pfx);
+            }
+        }        
+        return nsDeclarations;    }
+    
+    public static Map getInheritedNSDeclarations(Element elm)
+    {
+        List ancestorsAndSelf = new LinkedList();
+        Element current = elm;
+        while (current != null) 
+        {
+            ancestorsAndSelf.add(current);
+            Node parent = current.getParentNode();
+            if (parent.getNodeType() == Node.ELEMENT_NODE)
+                current = (Element)parent;
+            else 
+                current = null;
+        }
+        
+        Map nsDeclarations = null;
+        ListIterator iter = ancestorsAndSelf.listIterator(ancestorsAndSelf.size());
+        while (iter.hasPrevious())
+        {
+            Element element = (Element) iter.previous();
+            nsDeclarations = addLocalNSDeclarations(element, nsDeclarations);
+        }
+        
+        return nsDeclarations;
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/DomHelper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/I18nMessage.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/I18nMessage.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/I18nMessage.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/I18nMessage.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,149 @@
+/*
+ * 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.forms.util;
+
+import java.util.Arrays;
+
+import org.apache.cocoon.transformation.I18nTransformer;
+import org.apache.cocoon.xml.AttributesImpl;
+import org.apache.cocoon.xml.XMLUtils;
+import org.apache.commons.lang.ObjectUtils;
+import org.apache.excalibur.xml.sax.XMLizable;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * A XMLizable implementation that will produce SAX events for the
+ * I18nTransformer in its toSAX method, based on the information
+ * given in the constructor.
+ *
+ * <p>This generates an autonomous SAX-blurb, i.e. all necessary namespace
+ * declarations will be made, and no start/endDocument events will be generated.
+ *
+ * @version $Id: I18nMessage.java 177978 2005-05-23 13:27:51Z sylvain $
+ */
+public class I18nMessage implements XMLizable {
+    private String key;
+    private String catalogue;
+    private String[] parameters;
+    private boolean[] keys;
+
+    /**
+     * @param key a message key, to be translated by the I18nTransformer
+     */
+    public I18nMessage(String key) {
+        this(key, (String) null);
+    }
+
+    /**
+     * @param key a message key, to be translated by the I18nTransformer
+     * @param catalogue a named I18nTransformer catalogue to use
+     */
+    public I18nMessage(String key, String catalogue) {
+        this.key = key;
+        this.catalogue = catalogue;
+    }
+
+    /**
+     * @param key a message key, to be translated by the I18nTransformer
+     * @param parameters parameters to be substituted in the errorMessage (will be
+     * done by the I18nTransformer)
+     */
+    public I18nMessage(String key, String[] parameters) {
+        this(key, parameters, (String)null);
+    }
+
+    /**
+     * @param key a message key, to be translated by the I18nTransformer
+     * @param parameters parameters to be substituted in the errorMessage (will be
+     * done by the I18nTransformer)
+     * @param catalogue a named I18nTransformer catalogue to use
+     */
+    public I18nMessage(String key, String[] parameters, String catalogue) {
+        this.key = key;
+        this.parameters = parameters;
+        this.catalogue = catalogue;
+    }
+
+    /**
+     * @param key a message key, to be translated by the I18nTransformer
+     * @param parameters parameters to be substituted in the errorMessage (will be
+     * done by the I18nTransformer)
+     * @param keys Each element in the keys array corresponds to a string in the parameters array
+     * and indicates whether that parameter is in itself again a key.
+     */
+    public I18nMessage(String key, String[] parameters, boolean[] keys) {
+        this(key, parameters, keys, null);
+    }
+
+    /**
+     * @param key a message key, to be translated by the I18nTransformer
+     * @param parameters parameters to be substituted in the errorMessage (will be
+     * done by the I18nTransformer)
+     * @param keys Each element in the keys array corresponds to a string in the parameters array
+     * and indicates whether that parameter is in itself again a key.
+     * @param catalogue a named I18nTransformer catalogue to use
+     */
+    public I18nMessage(String key, String[] parameters, boolean[] keys, String catalogue) {
+        this.key = key;
+        this.parameters = parameters;
+        this.keys = keys;
+        this.catalogue = catalogue;
+    }
+
+    public void toSAX(ContentHandler contentHandler) throws SAXException {
+        contentHandler.startPrefixMapping("i18n", I18nTransformer.I18N_NAMESPACE_URI);
+        if (parameters != null) {
+            contentHandler.startElement(I18nTransformer.I18N_NAMESPACE_URI, I18nTransformer.I18N_TRANSLATE_ELEMENT, "i18n:" + I18nTransformer.I18N_TRANSLATE_ELEMENT, XMLUtils.EMPTY_ATTRIBUTES);
+        }
+
+        AttributesImpl i18nAttrs = new AttributesImpl();
+        if (catalogue != null) {
+            i18nAttrs.addCDATAAttribute(I18nTransformer.I18N_NAMESPACE_URI, I18nTransformer.I18N_CATALOGUE_ATTRIBUTE, "i18n:" + I18nTransformer.I18N_CATALOGUE_ATTRIBUTE, catalogue);
+        }
+
+        contentHandler.startElement(I18nTransformer.I18N_NAMESPACE_URI, I18nTransformer.I18N_TEXT_ELEMENT, "i18n:" + I18nTransformer.I18N_TEXT_ELEMENT, i18nAttrs);
+        contentHandler.characters(key.toCharArray(), 0, key.length());
+        contentHandler.endElement(I18nTransformer.I18N_NAMESPACE_URI, I18nTransformer.I18N_TEXT_ELEMENT, "i18n:" + I18nTransformer.I18N_TEXT_ELEMENT);
+
+        // the parameters
+        if (parameters != null) {
+            for (int i = 0; i < parameters.length; i++) {
+                contentHandler.startElement(I18nTransformer.I18N_NAMESPACE_URI, I18nTransformer.I18N_PARAM_ELEMENT, "i18n:" + I18nTransformer.I18N_PARAM_ELEMENT, XMLUtils.EMPTY_ATTRIBUTES);
+                if (keys != null && keys[i])
+                    contentHandler.startElement(I18nTransformer.I18N_NAMESPACE_URI, I18nTransformer.I18N_TEXT_ELEMENT, "i18n:" + I18nTransformer.I18N_TEXT_ELEMENT, i18nAttrs);
+                contentHandler.characters(parameters[i].toCharArray(), 0, parameters[i].length());
+                if (keys != null && keys[i])
+                    contentHandler.endElement(I18nTransformer.I18N_NAMESPACE_URI, I18nTransformer.I18N_TEXT_ELEMENT, "i18n:" + I18nTransformer.I18N_TEXT_ELEMENT);
+                contentHandler.endElement(I18nTransformer.I18N_NAMESPACE_URI, I18nTransformer.I18N_PARAM_ELEMENT, "i18n:" + I18nTransformer.I18N_PARAM_ELEMENT);
+            }
+            contentHandler.endElement(I18nTransformer.I18N_NAMESPACE_URI, I18nTransformer.I18N_TRANSLATE_ELEMENT, "i18n:" + I18nTransformer.I18N_TRANSLATE_ELEMENT);
+        }
+        contentHandler.endPrefixMapping("i18n");
+    }
+    
+    public boolean equals(Object obj) {
+        if (obj instanceof I18nMessage) {
+            I18nMessage other = (I18nMessage)obj;
+            return ObjectUtils.equals(this.catalogue, other.catalogue) &&
+                   ObjectUtils.equals(this.key, other.key) &&
+                   Arrays.equals(this.keys, other.keys) &&
+                   Arrays.equals(this.parameters, other.parameters);
+        } else {
+            return false;
+        }
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/I18nMessage.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/JavaScriptHelper.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/JavaScriptHelper.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/JavaScriptHelper.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/JavaScriptHelper.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,223 @@
+/*
+ * 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.forms.util;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.avalon.framework.CascadingRuntimeException;
+import org.apache.cocoon.components.flow.FlowHelper;
+import org.apache.cocoon.components.flow.javascript.fom.FOM_JavaScriptFlowHelper;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.JavaScriptException;
+import org.mozilla.javascript.Script;
+import org.mozilla.javascript.Scriptable;
+import org.w3c.dom.Element;
+
+/**
+ * Helper methods to use JavaScript in various locations of the Cocoon Forms configuration files
+ * such as event listeners and bindings.
+ * 
+ * @author <a href="http://www.apache.org/~sylvain/">Sylvain Wallez</a>
+ * @version $Id: JavaScriptHelper.java 289538 2005-09-16 13:46:22Z sylvain $
+ */
+public class JavaScriptHelper {
+
+    /**
+     * A shared root scope, avoiding to recreate a new one each time.
+     */
+    private static Scriptable _rootScope = null;
+
+    /**
+     * Build a script with the content of a DOM element.
+     * 
+     * @param element the element containing the script
+     * @return the compiled script
+     * @throws IOException
+     */
+    public static Script buildScript(Element element) throws IOException {
+        String jsText = DomHelper.getElementText(element);
+        String sourceName = DomHelper.getSystemIdLocation(element);
+
+        Context ctx = Context.enter();
+        Script script;
+        try {
+            script = ctx.compileReader(
+                getRootScope(), //scope
+                new StringReader(jsText), // in
+                sourceName == null ? "<unknown>" : sourceName, // sourceName
+                DomHelper.getLineLocation(element), // lineNo
+                null // securityDomain
+             );
+        } finally {
+            Context.exit();
+        }
+        return script;
+    }
+
+    /**
+     * Build a function with the content of a DOM element.
+     * 
+     * @param element the element containing the function body
+     * @param name the name of the function
+     * @param argumentNames names of the function arguments
+     * @return the compiled function
+     * @throws IOException
+     */
+    public static Function buildFunction(Element element, String name, String[] argumentNames) throws IOException {
+        // Enclose the script text with a function declaration
+        StringBuffer buffer = new StringBuffer("function ").append(name).append("(");
+        for (int i = 0; i < argumentNames.length; i++) {
+            if (i > 0) {
+                buffer.append(',');
+            }
+            buffer.append(argumentNames[i]);
+        }
+        buffer.append(") {\n").append(DomHelper.getElementText(element)).append("\n}");
+        
+        String jsText = buffer.toString();
+        String sourceName = DomHelper.getSystemIdLocation(element);
+
+        Context ctx = Context.enter();
+        Function func;
+        try {
+            func = ctx.compileFunction(
+                getRootScope(), //scope
+                jsText, // in
+                sourceName == null ? "<unknown>" : sourceName, // sourceName
+                DomHelper.getLineLocation(element) - 1, // lineNo, "-1" because we added "function..."
+                null // securityDomain
+             );
+        } finally {
+            Context.exit();
+        }
+        return func;
+    }
+
+    /**
+     * Get a root scope for building child scopes.
+     * 
+     * @return an appropriate root scope
+     */
+    public static Scriptable getRootScope() {
+        // FIXME: TemplateOMH should be used in 2.2
+        //return TemplateObjectModelHelper.getScope();
+        
+        
+        if (_rootScope == null) {
+            // Create it if never used up to now
+            Context ctx = Context.enter();
+            try {
+                _rootScope = ctx.initStandardObjects(null);
+            } finally {
+                Context.exit();
+            }
+        }
+        return _rootScope;
+    }
+
+    /**
+     * Get a parent scope for building a child scope. The request is searched for an existing scope
+     * that can be provided by a flowscript higher in the call stack, giving visibility to flowscript
+     * functions and global (session) variables.
+     * 
+     * @param objectModel the object model where the flowscript scope will be searched (can be <code>null</code>).
+     * @return an appropriate parent scope.
+     */
+    public static Scriptable getParentScope(Map objectModel) {
+        // Try to get the flowscript scope
+        Scriptable parentScope = null;
+        if (objectModel != null) {
+            parentScope = FOM_JavaScriptFlowHelper.getFOM_FlowScope(objectModel);
+        }
+
+        if (parentScope != null) {
+            return parentScope;
+        } else {
+            return getRootScope();
+        }
+    }
+
+    public static Object execScript(Script script, Map values, Map objectModel) throws JavaScriptException {
+        Context ctx = Context.enter();
+        try {
+            Scriptable parentScope = getParentScope(objectModel);
+
+            // Create a new local scope
+            Scriptable scope;
+            try {
+                scope = ctx.newObject(parentScope);
+            } catch (Exception e) {
+                // Should normally not happen
+                throw new CascadingRuntimeException("Cannont create script scope", e);
+            }
+            scope.setParentScope(parentScope);
+
+            // Populate the scope
+            Iterator iter = values.entrySet().iterator();
+            while(iter.hasNext()) {
+                Map.Entry entry = (Map.Entry)iter.next();
+                String key = (String)entry.getKey();
+                Object value = entry.getValue();
+                scope.put(key, scope, Context.toObject(value, scope));
+            }
+            
+            if (objectModel != null) {
+                Object viewData = FlowHelper.getContextObject(objectModel);
+                if (viewData != null) {
+                    scope.put("viewData", scope, Context.toObject(viewData, scope));
+                }
+            }
+
+            Object result = script.exec(ctx, scope);
+            return FlowHelper.unwrap(result);
+        } finally {
+            Context.exit();
+        }
+    }
+    
+    public static Object callFunction(Function func, Object thisObject, Object[] arguments, Map objectModel) throws JavaScriptException {
+        Context ctx = Context.enter();
+        try {
+            Scriptable scope = getParentScope(objectModel);
+
+            if (objectModel != null) {
+                Object viewData = FlowHelper.getContextObject(objectModel);
+                if (viewData != null) {
+                    // Create a new local scope to hold the view data
+                    Scriptable newScope;
+                    try {
+                        newScope = ctx.newObject(scope);
+                    } catch (Exception e) {
+                        // Should normally not happen
+                        throw new CascadingRuntimeException("Cannont create function scope", e);
+                    }
+                    newScope.setParentScope(scope);
+                    scope = newScope;
+            
+                    scope.put("viewData", scope, Context.toObject(viewData, scope));
+                }
+            }
+            Object result = func.call(ctx, scope, thisObject == null? null: Context.toObject(thisObject, scope), arguments);
+            return FlowHelper.unwrap(result);
+        } finally {
+            Context.exit();
+        }
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/JavaScriptHelper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/RepeaterAsList.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/RepeaterAsList.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/RepeaterAsList.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/RepeaterAsList.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,126 @@
+/*
+ * 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.forms.util;
+
+import java.util.AbstractList;
+import java.util.Map;
+
+import org.apache.cocoon.forms.formmodel.AbstractContainerWidget;
+import org.apache.cocoon.forms.formmodel.Repeater;
+import org.apache.cocoon.forms.formmodel.Widget;
+
+/**
+ * A <code>List</code> view of a {@link Repeater}, each element of the list being a <code>Map</code>
+ * wrapping a repeater row, as defined by {@link ContainerWidgetAsMap}.
+ * <p>
+ * This implementation of list supports all methods, with the following restrictions:
+ * <ul>
+ * <li>values stored in the list must be <code>Map</code>s, that will be used with {@link ContainerWidgetAsMap#putAll(Map)}
+ *     on the <code>Map</code> representation of the repeater rows,</li>
+ * <li>operations that involve testing equality with the list contents (e.g. <code>contains(Object)</code>) will
+ *     not function properly, the <code>Map</code> wrapping the rows being created on demand.</li>
+ * </ul>
+ * 
+ * @since 2.1.8
+ * @version $Id: RepeaterAsList.java 327865 2005-10-23 22:03:06Z sylvain $
+ */
+public class RepeaterAsList extends AbstractList {
+    
+    private Repeater repeater;
+    private boolean lowerCase;
+
+    /**
+     * Create a <code>List<code> view around a repeater. The <code>keysToLowerCase</code> parameter
+     * specifies if <code>Map</code>s wrapping rows should convert input keys to lower case, as
+     * specified by {@link ContainerWidgetAsMap#ContainerWidgetAsMap(AbstractContainerWidget, boolean)}.
+     * 
+     * @param repeater the repeater to wrap
+     * @param keysToLowerCase should we convert input keys to lower case?
+     */
+    public RepeaterAsList(Repeater repeater, boolean keysToLowerCase) {
+        this.repeater = repeater;
+        this.lowerCase = keysToLowerCase;
+    }
+    
+    /**
+     * Same as <code>RepeaterAsList(repeater, false)</code>.
+     */
+    public RepeaterAsList(Repeater repeater) {
+        this(repeater, false);
+    }
+
+    /**
+     * Get the repeater widget that is wrapped by this <code>List</code>.
+     * 
+     * @return the wrapped {@link Repeater}
+     */
+    public Repeater getWidget() {
+        return this.repeater;
+    }
+    
+    /**
+     * Get a widget relative to the repeater wrapped by this <code>List</code>
+     * 
+     * @param path a widget lookup path
+     * @return the widget pointed to by <code>path</code> or <code>null</code> if it doesn't exist.
+     * @see Widget#lookupWidget(String)
+     */
+    public Widget getWidget(String path) {
+        return this.repeater.lookupWidget(path);
+    }
+
+    public Object get(int index) {
+        return new ContainerWidgetAsMap(repeater.getRow(index), lowerCase);
+    }
+
+    public int size() {
+        return repeater.getSize();
+    }
+    
+    public Object set(int index, Object o) {
+        if (o == null) {
+            throw new NullPointerException("Cannot set null to a repeater");
+        }
+        if (!(o instanceof Map)) {
+            throw new IllegalArgumentException("Cannot set a '" + o.getClass().toString() + "' to a repeater");
+        }
+        Map result = new ContainerWidgetAsMap(repeater.getRow(index));
+        result.putAll((Map)o);
+        return result;
+    }
+    
+    public void add(int index, Object o) {
+        if (o == null) {
+            throw new NullPointerException("Cannot add null to a repeater");
+        }
+        if (!(o instanceof Map)) {
+            throw new IllegalArgumentException("Cannot add a '" + o.getClass().toString() + "' to a repeater");
+        }
+        Repeater.RepeaterRow row = repeater.addRow(index);
+        new ContainerWidgetAsMap(row).putAll((Map)o);
+    }
+    
+    public Object remove(int index) {
+        Map result = new ContainerWidgetAsMap(repeater.getRow(index));
+        repeater.removeRow(index);
+        return result;
+    }
+    
+    // Not mandated by the abstract class, but will speed up things
+    public void clear() {
+        repeater.clear();
+    }
+}
\ No newline at end of file

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/RepeaterAsList.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/SimpleServiceSelector.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/SimpleServiceSelector.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/SimpleServiceSelector.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/SimpleServiceSelector.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,124 @@
+/*
+ * 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.forms.util;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.avalon.framework.activity.Disposable;
+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.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.logger.LogEnabled;
+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.framework.context.Contextualizable;
+import org.apache.avalon.framework.context.Context;
+import org.apache.avalon.framework.context.ContextException;
+import org.apache.cocoon.components.LifecycleHelper;
+
+/**
+ * A very simple ServiceSelector for ThreadSafe services.
+ * 
+ * @version $Id: SimpleServiceSelector.java 76175 2004-11-17 21:45:08Z upayavira $
+ */
+public class SimpleServiceSelector extends AbstractLogEnabled implements ServiceSelector, Configurable, LogEnabled,
+        Serviceable, Disposable, Contextualizable {
+    private final String hintShortHand;
+    private final Class componentClass;
+    private Map components = new HashMap();
+    private ServiceManager serviceManager;
+    private Context context;
+
+    public SimpleServiceSelector(String hintShortHand, Class componentClass) {
+        this.hintShortHand = hintShortHand;
+        this.componentClass = componentClass;
+    }
+
+    public void service(ServiceManager serviceManager) throws ServiceException {
+        this.serviceManager = serviceManager;
+    }
+
+    public void contextualize(Context context) throws ContextException {
+        this.context = context;
+    }
+
+    public void configure(Configuration configuration) throws ConfigurationException {
+        Configuration[] componentConfs = configuration.getChildren(hintShortHand);
+        for (int i = 0; i < componentConfs.length; i++) {
+            String name = componentConfs[i].getAttribute("name");
+            String src = componentConfs[i].getAttribute("src");
+
+            Class clazz = null;
+            try {
+                clazz = Class.forName(src);
+            } catch (ClassNotFoundException e) {
+                throw new ConfigurationException("Class not found: " + src + ", declared at " + componentConfs[i].getLocation(), e);
+            }
+
+            if (!componentClass.isAssignableFrom(clazz))
+                throw new ConfigurationException("The class \"" + src + "\" is of an incorrect type, it should implement or extend " + componentClass.getName());
+
+            Object component = null;
+            try {
+                component = clazz.newInstance();
+                LifecycleHelper.setupComponent(
+                		component,
+					getLogger(),
+					context,
+					serviceManager,
+					componentConfs[i]);
+            } catch (Exception e) {
+                throw new ConfigurationException("Error creating " + hintShortHand + " declared at " + componentConfs[i].getLocation(), e);
+            }
+
+            components.put(name, component);
+        }
+    }
+
+    public Object select(Object hint) throws ServiceException {
+        if (!isSelectable(hint))
+            throw new ServiceException((String)hint, "Non-existing component for this hint");
+        String stringHint = (String)hint;
+        return components.get(stringHint);
+    }
+
+    public boolean isSelectable(Object hint) {
+        String stringHint = (String)hint;
+        return components.containsKey(stringHint);
+    }
+
+    public void release(Object o) {
+    }
+
+    public void dispose() {
+        Iterator serviceIt = components.values().iterator();
+        while (serviceIt.hasNext()) {
+            Object service = serviceIt.next();
+            if (service instanceof Disposable) {
+                try {
+                    ((Disposable)service).dispose();
+                } catch (Exception e) {
+                    getLogger().error("Error disposing service " + service, e);
+                }
+            }
+        }
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/SimpleServiceSelector.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/StringMessage.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/StringMessage.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/StringMessage.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/StringMessage.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,50 @@
+/*
+ * 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.forms.util;
+
+import java.util.Arrays;
+
+import org.apache.excalibur.xml.sax.XMLizable;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * A string in an XMLizable form.
+ *
+ * Will produce exactly one characters call, no start/endDocument calls.
+ * 
+ * @version $Id: StringMessage.java 177978 2005-05-23 13:27:51Z sylvain $
+ */
+public class StringMessage implements XMLizable {
+    private char[] ch;
+
+    public StringMessage(String message) {
+        this.ch = message.toCharArray();
+    }
+
+    public void toSAX(ContentHandler contentHandler) throws SAXException {
+        contentHandler.characters(ch, 0, ch.length);
+    }
+    
+    public boolean equals(Object obj) {
+        if (obj instanceof StringMessage) {
+            // Compare char arrays
+            return Arrays.equals(this.ch, ((StringMessage)obj).ch);
+        } else {
+            return false;
+        }
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/util/StringMessage.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message