cocoon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jheym...@apache.org
Subject svn commit: r330548 [95/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/formmodel/AbstractWidgetDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/AbstractWidgetDefinitionBuilder.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/AbstractWidgetDefinitionBuilder.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/AbstractWidgetDefinitionBuilder.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,244 @@
+/*
+ * 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.formmodel;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.avalon.framework.CascadingException;
+import org.apache.avalon.framework.activity.Disposable;
+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.cocoon.forms.FormsConstants;
+import org.apache.cocoon.forms.datatype.DatatypeManager;
+import org.apache.cocoon.forms.event.CreateListener;
+import org.apache.cocoon.forms.event.WidgetListener;
+import org.apache.cocoon.forms.event.WidgetListenerBuilder;
+import org.apache.cocoon.forms.expression.ExpressionManager;
+import org.apache.cocoon.forms.util.DomHelper;
+import org.apache.cocoon.forms.validation.WidgetValidatorBuilder;
+import org.apache.excalibur.xml.sax.XMLizable;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Abstract base class for WidgetDefinitionBuilders. Provides functionality
+ * common to many implementations.
+ *
+ * @version $Id: AbstractWidgetDefinitionBuilder.java 326838 2005-10-20 06:26:53Z sylvain $
+ */
+public abstract class AbstractWidgetDefinitionBuilder implements WidgetDefinitionBuilder, Serviceable, Disposable {
+    protected ServiceSelector widgetDefinitionBuilderSelector;
+    protected ServiceSelector widgetValidatorBuilderSelector;
+    protected ServiceSelector widgetListenerBuilderSelector;
+    protected DatatypeManager datatypeManager;
+    protected ExpressionManager expressionManager;
+    protected ServiceManager serviceManager;
+    
+    protected WidgetDefinitionBuilderContext context = null;
+    
+    public WidgetDefinition buildWidgetDefinition(Element widgetElement, WidgetDefinitionBuilderContext context) throws Exception {
+    	// so changes don't pollute upper levels
+    	this.context = new WidgetDefinitionBuilderContext(context);
+    	
+    	
+    	WidgetDefinition def = buildWidgetDefinition(widgetElement);
+    	
+    	// register this class with the local library, if any.
+        if(DomHelper.getAttributeAsBoolean(widgetElement,"register",false) && this.context!=null && this.context.getLocalLibrary()!=null) {
+        	this.context.getLocalLibrary().addDefinition(def);
+        }
+        
+    	this.context = null;
+    	return def;
+    }
+
+    public void service(ServiceManager serviceManager) throws ServiceException {
+        this.serviceManager = serviceManager;
+        this.widgetDefinitionBuilderSelector = (ServiceSelector) serviceManager.lookup(WidgetDefinitionBuilder.class.getName() + "Selector");
+        this.datatypeManager = (DatatypeManager) serviceManager.lookup(DatatypeManager.ROLE);
+        this.expressionManager = (ExpressionManager) serviceManager.lookup(ExpressionManager.ROLE);
+        this.widgetValidatorBuilderSelector = (ServiceSelector) serviceManager.lookup(WidgetValidatorBuilder.ROLE + "Selector");
+        this.widgetListenerBuilderSelector = (ServiceSelector) serviceManager.lookup(WidgetListenerBuilder.ROLE + "Selector");
+    }
+    
+    protected void setupDefinition(Element widgetElement, AbstractWidgetDefinition definition) throws Exception {
+    	
+    	// location
+    	definition.setLocation(DomHelper.getLocationObject(widgetElement));
+    	
+    	
+    	if(this.context.getSuperDefinition()!=null) 
+    		definition.initializeFrom(this.context.getSuperDefinition());
+    	
+        setCommonProperties(widgetElement, definition);
+        setValidators(widgetElement, definition);
+        setCreateListeners(widgetElement, definition);
+    }
+
+    private void setCommonProperties(Element widgetElement, AbstractWidgetDefinition widgetDefinition) throws Exception {
+        
+        // id
+        if (widgetDefinition instanceof FormDefinition) {
+            // FormDefinition is the *only* kind of widget that has an optional id
+            widgetDefinition.setId(DomHelper.getAttribute(widgetElement, "id", ""));   
+        } else {
+            String id = DomHelper.getAttribute(widgetElement, "id");
+            if (id.length() < 1) {
+                throw new Exception("Missing id attribute on element '" + widgetElement.getTagName() + "' at " +
+                                    DomHelper.getLocation(widgetElement));
+            }
+            if (id.indexOf('/') != -1 || id.indexOf('.') != -1) {
+                throw new Exception("A widget name cannot contain '.' or '/' as this conflicts with widget paths, at " +
+                        DomHelper.getLocation(widgetElement));
+            }
+            widgetDefinition.setId(id);
+        }
+
+        // state
+        String stateValue = DomHelper.getAttribute(widgetElement, "state", null);
+        if (stateValue != null) {
+            WidgetState state = WidgetState.stateForName(stateValue);
+            if (state == null) {
+                throw new Exception ("Unknow value '" + stateValue +"' for state attribute at " +
+                        DomHelper.getLocation(widgetElement));
+            }
+            widgetDefinition.setState(state);
+        }
+
+        // attributes
+        Element attrContainer = DomHelper.getChildElement(widgetElement, FormsConstants.DEFINITION_NS, "attributes", false);
+        if (attrContainer != null) {
+            // There's a <fd:attributes> element. Get its <fd:attribute> children
+            Element[] attrs = DomHelper.getChildElements(attrContainer, FormsConstants.DEFINITION_NS, "attribute");
+            if (attrs != null && attrs.length > 0) {
+                // We actually do have some
+                Map attrMap = new HashMap();
+                for (int i = 0; i < attrs.length; i++) {
+                    attrMap.put(DomHelper.getAttribute(attrs[i], "name"), DomHelper.getAttribute(attrs[i], "value"));
+                }
+                widgetDefinition.setAttributes(attrMap);
+            }
+        }
+    }
+
+    protected WidgetDefinition buildAnotherWidgetDefinition(Element widgetDefinition) throws Exception {
+        String widgetName = widgetDefinition.getLocalName();
+        WidgetDefinitionBuilder builder = null;
+        try {
+            builder = (WidgetDefinitionBuilder)widgetDefinitionBuilderSelector.select(widgetName);
+        } catch (ServiceException e) {
+            throw new CascadingException("Unknown kind of widget '" + widgetName + "' at " +
+                                         DomHelper.getLocation(widgetDefinition), e);
+        }
+        
+        
+        return builder.buildWidgetDefinition(widgetDefinition, this.context);
+    }
+
+    protected List buildEventListeners(Element widgetElement, String elementName, Class listenerClass) throws Exception {
+        List result = null;
+        Element listenersElement = DomHelper.getChildElement(widgetElement, FormsConstants.DEFINITION_NS, elementName);
+        if (listenersElement != null) {
+            NodeList list = listenersElement.getChildNodes();
+            for (int i = 0; i < list.getLength(); i++) {
+                if (list.item(i).getNodeType() == Node.ELEMENT_NODE) {
+                    Element listenerElement = (Element)list.item(i);
+                    WidgetListenerBuilder listenerBuilder = null;
+                    try {
+                        listenerBuilder = (WidgetListenerBuilder)widgetListenerBuilderSelector.select(listenerElement.getLocalName());
+                    } catch (ServiceException e) {
+                        throw new CascadingException("Unknown kind of eventlistener '" + listenerElement.getLocalName()
+                                + "' at " + DomHelper.getLocation(listenerElement), e);
+                    }
+                    WidgetListener listener = listenerBuilder.buildListener(listenerElement, listenerClass);
+                    widgetListenerBuilderSelector.release(listenerBuilder);
+                    if (result == null) result = new ArrayList();
+                    result.add(listener);
+                }
+            }
+        }
+
+        return result == null ? Collections.EMPTY_LIST : result;
+    }
+
+    protected void setDisplayData(Element widgetElement, AbstractWidgetDefinition widgetDefinition) throws Exception {
+        final String[] names = {"label", "help", "hint"};
+        Map displayData = new HashMap(names.length);
+        for (int i = 0; i < names.length; i++) {
+            XMLizable data = null;
+            Element dataElement = DomHelper.getChildElement(widgetElement, FormsConstants.DEFINITION_NS, names[i]);
+            if (dataElement != null) {
+                data = DomHelper.compileElementContent(dataElement);
+            }
+
+            // NOTE: We put also null values in the may in order to test their existence
+            //       (see AbstractWidgetDefinition.generateDisplayData)
+            displayData.put(names[i], data);
+        }
+
+        widgetDefinition.setDisplayData(displayData);
+    }
+
+    private void setValidators(Element widgetElement, AbstractWidgetDefinition widgetDefinition) throws Exception {
+        Element validatorElement = DomHelper.getChildElement(widgetElement, FormsConstants.DEFINITION_NS, "validation");
+        if (validatorElement != null) {
+            NodeList list = validatorElement.getChildNodes();
+            for (int i = 0; i < list.getLength(); i++) {
+                if (list.item(i).getNodeType() == Node.ELEMENT_NODE) {
+                    Element element = (Element)list.item(i);
+                    String name = element.getLocalName();
+                    WidgetValidatorBuilder builder;
+                    try {
+                        builder = (WidgetValidatorBuilder)this.widgetValidatorBuilderSelector.select(name);
+                    } catch(ServiceException e) {
+                        throw new CascadingException("Unknow kind of validator '" + name + "' at " +
+                                                     DomHelper.getLocation(element), e);
+                    }
+
+                    widgetDefinition.addValidator(builder.build(element, widgetDefinition));
+                    widgetValidatorBuilderSelector.release(builder);
+                }
+            }
+        }
+    }
+
+    private void setCreateListeners(Element widgetElement, AbstractWidgetDefinition widgetDefinition) throws Exception {
+        Iterator iter = buildEventListeners(widgetElement, "on-create", CreateListener.class).iterator();
+        while (iter.hasNext()) {
+            widgetDefinition.addCreateListener((CreateListener)iter.next());
+        }
+    }
+
+    public void dispose() {
+        this.serviceManager.release(this.widgetDefinitionBuilderSelector);
+        this.widgetDefinitionBuilderSelector = null;
+        this.serviceManager.release(this.datatypeManager);
+        this.datatypeManager = null;
+        this.serviceManager.release(this.expressionManager);
+        this.expressionManager = null;
+        this.serviceManager.release(this.widgetValidatorBuilderSelector);
+        this.widgetValidatorBuilderSelector = null;
+        this.serviceManager = null;
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/Action.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/Action.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/Action.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/Action.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,145 @@
+/*
+ * 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.formmodel;
+
+import org.apache.cocoon.environment.Request;
+import org.apache.cocoon.forms.FormContext;
+import org.apache.cocoon.forms.event.*;
+
+/**
+ * An Action widget. An Action widget can cause an {@link ActionEvent} to be triggered
+ * on the server side, which will be handled by either the event handlers defined in the
+ * form definition, and/or by the {@link org.apache.cocoon.forms.event.FormHandler FormHandler}
+ * registered with the form, if any. An Action widget can e.g. be rendered as a button,
+ * or as a hidden field which gets its value set by javascript. The Action widget will generate its associated
+ * ActionEvent when a requestparameter is present with as name the id of this Action widget, and as
+ * value a non-empty value.
+ *
+ * @version $Id: Action.java 231335 2005-08-10 21:40:35Z vgritsenko $
+ */
+public class Action extends AbstractWidget implements ActionListenerEnabled {
+
+    private final ActionDefinition definition;
+    /** Additional listeners to those defined as part of the widget definition (if any). */
+    private ActionListener listener;
+
+
+    public Action(ActionDefinition definition) {
+        super(definition);
+        this.definition = definition;
+    }
+
+    public WidgetDefinition getDefinition() {
+        return this.definition;
+    }
+
+    public void readFromRequest(final FormContext formContext) {
+        if (!getCombinedState().isAcceptingInputs()) {
+            return;
+        }
+
+        Form form = getForm();
+
+        // Set the submit widget if we can determine it from the request
+        String fullId = getRequestParameterName();
+        Request request = formContext.getRequest();
+
+        String value = request.getParameter(fullId);
+        if (value != null) {
+            form.setSubmitWidget(this);
+
+        } else {
+            // Special workaround an IE bug for <input type="image" name="foo"> :
+            // in that case, IE only sends "foo.x" and "foo.y" and not "foo" whereas
+            // standards-compliant browsers such as Mozilla do send the "foo" parameter.
+            //
+            // Note that since actions are terminal widgets, there's no chance of conflict
+            // with a child "x" or "y" widget.
+            value = request.getParameter(fullId + ".x");
+            if ((value != null) && value.length() > 0) {
+                form.setSubmitWidget(this);
+            }
+        }
+
+        if (form.getSubmitWidget() == this) {
+            form.addWidgetEvent(new ActionEvent(this, definition.getActionCommand()));
+            handleActivate();
+        }
+    }
+
+    /**
+     * Handle the fact that this action was activated. The default here is to end the
+     * current form processing and redisplay the form, which means that actual behaviour
+     * should be implemented in event listeners.
+     */
+    protected void handleActivate() {
+        getForm().endProcessing(true);
+    }
+
+    /**
+     * Always return <code>true</code> (an action has no validation)
+     *
+     * <br>TODO is there a use case for actions having validators?
+     */
+    public boolean validate() {
+        return true;
+    }
+
+    /**
+     * @see org.apache.cocoon.forms.formmodel.Widget#isValid()
+     */
+    public boolean isValid() {
+        return true;
+    }
+
+    private static final String ACTION_EL = "action";
+
+    /**
+     * @return "action"
+     */
+    public String getXMLElementName() {
+        return ACTION_EL;
+    }
+
+    /**
+     * Adds a ActionListener to this widget instance. Listeners defined
+     * on the widget instance will be executed in addtion to any listeners
+     * that might have been defined in the widget definition.
+     */
+    public void addActionListener(ActionListener listener) {
+        this.listener = WidgetEventMulticaster.add(this.listener, listener);
+    }
+
+    public void removeActionListener(ActionListener listener) {
+        this.listener = WidgetEventMulticaster.remove(this.listener, listener);
+    }
+
+    private void fireActionEvent(ActionEvent event) {
+        if (this.listener != null) {
+            this.listener.actionPerformed(event);
+        }
+    }
+
+    public void broadcastEvent(WidgetEvent event) {
+        if (event instanceof ActionEvent) {
+            this.definition.fireActionEvent((ActionEvent)event);
+            fireActionEvent((ActionEvent)event);
+        } else {
+            // Other kinds of events
+            super.broadcastEvent(event);
+        }
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/ActionDefinition.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/ActionDefinition.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/ActionDefinition.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/ActionDefinition.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,74 @@
+/*
+ * 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.formmodel;
+
+import org.apache.cocoon.forms.event.ActionEvent;
+import org.apache.cocoon.forms.event.ActionListener;
+import org.apache.cocoon.forms.event.WidgetEventMulticaster;
+
+/**
+ * The {@link WidgetDefinition} part of a Action widget, see {@link Action} for more information.
+ * 
+ * @version $Id: ActionDefinition.java 289538 2005-09-16 13:46:22Z sylvain $
+ */
+public class ActionDefinition extends AbstractWidgetDefinition {
+    private String actionCommand;
+    private ActionListener listener;
+
+    public void setActionCommand(String actionCommand) {
+        this.actionCommand = actionCommand;
+    }
+    
+    /**
+     * initialize this definition with the other, sort of like a copy constructor
+     */
+    public void initializeFrom(WidgetDefinition definition) throws Exception {
+    	super.initializeFrom(definition);
+    	
+    	if(definition instanceof ActionDefinition) {
+    		ActionDefinition other = (ActionDefinition)definition;
+    		
+    		this.actionCommand = other.actionCommand;
+    		this.listener = other.listener;
+    		
+    	} else {
+    		throw new Exception("Definition to inherit from is not of the right type! (at "+getLocation()+")");
+    	}
+    }
+
+    public String getActionCommand() {
+        return actionCommand;
+    }
+
+    public Widget createInstance() {
+        return new Action(this);
+    }
+
+    public void addActionListener(ActionListener listener) {
+        checkMutable();
+        this.listener = WidgetEventMulticaster.add(this.listener, listener);
+    }
+    
+    public void fireActionEvent(ActionEvent event) {
+        if (this.listener != null) {
+            this.listener.actionPerformed(event);
+        }
+    }
+
+    public boolean hasActionListeners() {
+        return this.listener != null;
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/ActionDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/ActionDefinitionBuilder.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/ActionDefinitionBuilder.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/ActionDefinitionBuilder.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,63 @@
+/*
+ * 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.formmodel;
+
+import java.util.Iterator;
+
+import org.apache.cocoon.forms.event.ActionListener;
+import org.apache.cocoon.forms.util.DomHelper;
+import org.apache.cocoon.util.Deprecation;
+import org.w3c.dom.Element;
+
+/**
+ * Builds {@link ActionDefinition}s.
+ * 
+ * @version $Id: ActionDefinitionBuilder.java 219043 2005-07-14 14:44:06Z cziegeler $
+ */
+public class ActionDefinitionBuilder extends AbstractWidgetDefinitionBuilder {
+
+    public WidgetDefinition buildWidgetDefinition(Element widgetElement) throws Exception {
+        ActionDefinition definition = new ActionDefinition();
+        setupDefinition(widgetElement, definition);
+        definition.makeImmutable();
+        return definition;
+    }
+    
+    protected void setupDefinition(Element widgetElement, ActionDefinition definition) throws Exception {
+        super.setupDefinition(widgetElement, definition);
+
+        setDisplayData(widgetElement, definition);
+
+        // Get the "command" optional attribute
+        String actionCommand = DomHelper.getAttribute(widgetElement, "command", null);
+        
+        // If unspecified, check the deprecated "action-command" deprecated attribute
+        if (actionCommand == null) {
+            actionCommand = DomHelper.getAttribute(widgetElement, "action-command", null);
+            if (actionCommand != null) {
+                Deprecation.logger.info("The 'action-command' attribute is deprecated and replaced by 'command', at " +
+                    DomHelper.getLocation(widgetElement));
+            }
+        }
+        
+        definition.setActionCommand(actionCommand);
+
+        Iterator iter = buildEventListeners(widgetElement, "on-action", ActionListener.class).iterator();
+        while (iter.hasNext()) {
+            definition.addActionListener((ActionListener)iter.next());
+        }
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/AggregateField.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/AggregateField.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/AggregateField.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/AggregateField.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,247 @@
+/*
+ * 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.formmodel;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cocoon.forms.FormsConstants;
+import org.apache.cocoon.forms.FormContext;
+import org.apache.cocoon.forms.formmodel.AggregateFieldDefinition.SplitMapping;
+import org.apache.cocoon.forms.util.I18nMessage;
+import org.apache.cocoon.forms.validation.ValidationError;
+import org.apache.excalibur.xml.sax.XMLizable;
+import org.apache.oro.text.regex.MatchResult;
+import org.apache.oro.text.regex.PatternMatcher;
+import org.apache.oro.text.regex.Perl5Matcher;
+import org.outerj.expression.ExpressionException;
+
+/**
+ * An aggregated field allows to represent one value as multiple input fields, or several values
+ * as one field. Hence this widget is a field and a container widget simultaneously.
+ *
+ * <p>Upon submit, it first attempts to read own value from the request, and splits over nested
+ * field widgets using a regular expression. If split fails, this will simply give a validation error.
+ * If own value was not submitted, it attempts to read values for nested field widgets, and combines
+ * theirs values using combine expression.
+ *
+ * <p>To validate this widget, both the validation rules of the nested widgets are
+ * checked, and those of the aggregated field themselves. The validation rules of the aggregated
+ * field can perform checks on the string as entered by the user (e.g. check its total length).
+ *
+ * <p>This field and nested fields can be of any supported type, as long as combine expression
+ * gives result of the correct type, and split regular expression can split string representation
+ * into parts which can be converted to the values of nested fields.
+ *
+ * @version $Id: AggregateField.java 326838 2005-10-20 06:26:53Z sylvain $
+ */
+public class AggregateField extends Field implements ContainerWidget {
+
+    private static final String AGGREGATEFIELD_EL = "aggregatefield";
+
+    /**
+     * List of nested fields
+     */
+    private List fields = new ArrayList();
+
+    /**
+     * Map of nested fields
+     */
+    private Map fieldsById = new HashMap();
+
+
+    public AggregateField(AggregateFieldDefinition definition) {
+        super(definition);
+    }
+
+    public final AggregateFieldDefinition getAggregateFieldDefinition() {
+        return (AggregateFieldDefinition)getDefinition();
+    }
+
+    public void initialize() {
+        this.selectionList = getAggregateFieldDefinition().getSelectionList();
+    }
+
+    public void addChild(Widget widget) {
+    	if (!(widget instanceof Field)) {
+            throw new IllegalArgumentException("AggregateField can only contain fields.");
+        }
+        addField((Field)widget);
+    }
+
+    protected void addField(Field field) {
+        field.setParent(this);
+        fields.add(field);
+        fieldsById.put(field.getId(), field);
+    }
+
+
+    public boolean hasChild(String id) {
+        return this.fieldsById.containsKey(id);
+    }
+
+    public Iterator getChildren() {
+        return fields.iterator();
+    }
+
+    public void readFromRequest(FormContext formContext) {
+        if (!getCombinedState().isAcceptingInputs()) {
+            return;
+        }
+
+        String newEnteredValue = formContext.getRequest().getParameter(getRequestParameterName());
+        if (newEnteredValue != null) {
+            // There is one aggregated entered value. Read it and split it.
+            super.readFromRequest(formContext);
+            if (this.valueState == VALUE_UNPARSED) {
+                setFieldsValues(enteredValue);
+            }
+        } else {
+            // Check if there are multiple splitted values. Read them and aggregate them.
+            for (Iterator i = fields.iterator(); i.hasNext();) {
+                Field field = (Field)i.next();
+                field.readFromRequest(formContext);
+                if (field.valueState == VALUE_UNPARSED) {
+                    this.valueState = VALUE_UNPARSED;
+                }
+            }
+            if (this.valueState == VALUE_UNPARSED) {
+                combineFields();
+            }
+        }
+    }
+
+    public void setValue(Object newValue) {
+        super.setValue(newValue);
+        if (this.valueState == VALUE_PARSED) {
+            setFieldsValues(enteredValue);
+        }
+    }
+
+    /**
+     * Returns false if all fields have no value.
+     */
+    private boolean fieldsHaveValues() {
+        for (Iterator i = fields.iterator(); i.hasNext();) {
+            Field field = (Field)i.next();
+            if (field.getValue() != null) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Splits passed value and sets values of all nested fields.
+     * If split fails, resets all fields.
+     */
+    private void setFieldsValues(String value) {
+        if (value == null) {
+            resetFieldsValues();
+        } else {
+            PatternMatcher matcher = new Perl5Matcher();
+            if (matcher.matches(value, getAggregateFieldDefinition().getSplitPattern())) {
+                MatchResult matchResult = matcher.getMatch();
+                Iterator iterator = getAggregateFieldDefinition().getSplitMappingsIterator();
+                while (iterator.hasNext()) {
+                    SplitMapping splitMapping = (SplitMapping)iterator.next();
+                    String result = matchResult.group(splitMapping.getGroup());
+
+                    // Fields can have a non-string datatype, going to the readFromRequest
+                    Field field = (Field)fieldsById.get(splitMapping.getFieldId());
+                    field.readFromRequest(result);
+                }
+            } else {
+                resetFieldsValues();
+            }
+        }
+    }
+
+    public void combineFields() {
+        try {
+            Object value = getAggregateFieldDefinition().getCombineExpression().evaluate(new ExpressionContextImpl(this, true));
+            super.setValue(value);
+        } catch (CannotYetResolveWarning e) {
+            super.setValue(null);
+        } catch (ExpressionException e) {
+            super.setValue(null);
+        } catch (ClassCastException e) {
+            super.setValue(null);
+        }
+    }
+
+    /**
+     * Sets values of all nested fields to null
+     */
+    private void resetFieldsValues() {
+        for (Iterator i = fields.iterator(); i.hasNext();) {
+            Field field = (Field)i.next();
+            field.setValue(null);
+        }
+    }
+
+    public boolean validate() {
+        if (!getCombinedState().isValidatingValues()) {
+            this.wasValid = true;
+            return true;
+        }
+
+        if (enteredValue != null && !fieldsHaveValues()) {
+            XMLizable failMessage = getAggregateFieldDefinition().getSplitFailMessage();
+            if (failMessage != null) {
+                validationError = new ValidationError(failMessage);
+            } else {
+                validationError = new ValidationError(new I18nMessage("aggregatedfield.split-failed",
+                                                                      new String[] { getAggregateFieldDefinition().getSplitRegexp() },
+                                                                      FormsConstants.I18N_CATALOGUE));
+            }
+            valueState = VALUE_DISPLAY_VALIDATION;
+            this.wasValid = false;
+            return false;
+        }
+
+        // Validate ALL my child fields
+        boolean valid = true;
+        for (Iterator i = fields.iterator(); i.hasNext();) {
+            Field field = (Field)i.next();
+            if (!field.validate()) {
+                validationError = field.getValidationError();
+                valid = false;
+            }
+        }
+        if (!valid) {
+            valueState = VALUE_DISPLAY_VALIDATION;
+            this.wasValid = false;
+            return false;
+        }
+
+        return super.validate();
+    }
+
+    /**
+     * @return "aggregatefield"
+     */
+    public String getXMLElementName() {
+        return AGGREGATEFIELD_EL;
+    }
+
+    public Widget getChild(String id) {
+        return (Widget)fieldsById.get(id);
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/AggregateFieldDefinition.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/AggregateFieldDefinition.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/AggregateFieldDefinition.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/AggregateFieldDefinition.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,217 @@
+/*
+ * 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.formmodel;
+
+import org.apache.excalibur.xml.sax.XMLizable;
+import org.apache.oro.text.regex.Pattern;
+
+import org.outerj.expression.Expression;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * The {@link WidgetDefinition} part of a AggregateField widget, see {@link AggregateField} for more information.
+ *
+ * @version $Id: AggregateFieldDefinition.java 289538 2005-09-16 13:46:22Z sylvain $
+ */
+public class AggregateFieldDefinition extends FieldDefinition {
+
+    /**
+     * Defines expression which combines values of nested fields into this value
+     */
+    private Expression combineExpr;
+
+    /**
+     * Regular expression which splits this value on the values of the nested fields.
+     * It is compiled into the {@link #splitPattern}.
+     */
+    private String splitRegexp;
+
+    /**
+     * Compiled pattern out of the {@link #splitRegexp} regular expression.
+     */
+    private Pattern splitPattern;
+
+    /**
+     * Message to be displayed when the {@link #setSplitPattern(Pattern, String) splitPattern}
+     * does not match what the user entered. Optional.
+     */
+    protected XMLizable splitFailMessage;
+
+    /**
+     * List containing instances of {@link SplitMapping}, i.e. the mapping between
+     * a group (paren) from the regular expression and corresponding field id.
+     */
+    private List splitMappings = new ArrayList();
+    
+    /**
+     * Set containing widgets mapped to groups to find out if a specific widget has been mapped already
+     */
+    private Set mappedFields = new HashSet();
+
+    /**
+     *
+     */
+    private WidgetDefinitionList container = new WidgetDefinitionList(this);
+
+    /**
+     * initialize this definition with the other, sort of like a copy constructor
+     */
+    public void initializeFrom(WidgetDefinition definition) throws Exception {
+    	super.initializeFrom(definition);
+    	
+    	if(definition instanceof AggregateFieldDefinition) {
+    		AggregateFieldDefinition other = (AggregateFieldDefinition)definition;
+    		
+    		this.combineExpr = other.combineExpr;
+    		this.splitRegexp = other.splitRegexp;
+    		this.splitPattern = other.splitPattern;
+    		this.splitFailMessage = other.splitFailMessage;
+    		
+    		Iterator defs = other.container.getWidgetDefinitions().iterator();
+    		while(defs.hasNext()) {
+    			container.addWidgetDefinition((WidgetDefinition)defs.next());
+    		}
+    		
+    		Collections.copy(this.splitMappings,other.splitMappings);
+    		
+    		Iterator fields = other.mappedFields.iterator();
+    		while(fields.hasNext()) {
+    			this.mappedFields.add(fields.next());
+    		}
+    		
+    	} else {
+    		throw new Exception("Definition to inherit from is not of the right type! (at "+getLocation()+")");
+    	}
+    }
+
+    public void addWidgetDefinition(WidgetDefinition widgetDefinition) throws DuplicateIdException {
+        checkMutable();
+        container.addWidgetDefinition(widgetDefinition);
+    }
+    
+    /**
+     * checks completeness of this definition
+     */
+    public void checkCompleteness() throws IncompletenessException {
+    	super.checkCompleteness();
+    	
+    	if(this.container.size()==0)
+    		throw new IncompletenessException("AggregateField doesn't have any child widgets!",this);
+    	
+    	if(this.combineExpr==null)
+    		throw new IncompletenessException("AggregateField requires a combine expression!",this);
+    	
+    	if(this.splitPattern==null)
+    		throw new IncompletenessException("AggregateField requires a split regular expression!",this);
+    	
+    	if(this.splitMappings.size()==0)
+    		throw new IncompletenessException("AggregateField requires at least one group to field mapping!",this);
+    	
+    	// now check children's completeness
+    	List defs = container.getWidgetDefinitions();
+    	Iterator it = defs.iterator();
+    	while(it.hasNext()) {
+    		((WidgetDefinition)it.next()).checkCompleteness();
+    	}
+    }
+
+    public boolean hasWidget(String id) {
+        return container.hasWidget(id);
+    }
+
+    protected void setCombineExpression(Expression expression) {
+        checkMutable();
+        combineExpr = expression;
+    }
+
+    public Expression getCombineExpression() {
+        return combineExpr;
+    }
+
+    protected void setSplitPattern(Pattern pattern, String regexp) {
+        checkMutable();
+        this.splitPattern = pattern;
+        this.splitRegexp = regexp;
+    }
+
+    public Pattern getSplitPattern() {
+        return splitPattern;
+    }
+
+    public String getSplitRegexp() {
+        return splitRegexp;
+    }
+
+    public XMLizable getSplitFailMessage() {
+        return splitFailMessage;
+    }
+
+    protected void setSplitFailMessage(XMLizable splitFailMessage) {
+        checkMutable();
+        this.splitFailMessage = splitFailMessage;
+    }
+
+    protected void addSplitMapping(int group, String fieldId) {
+        checkMutable();
+        
+        if(mappedFields.contains(fieldId))
+        	throw new RuntimeException("Field '"+fieldId+"' is already mapped to another group!");
+        
+        mappedFields.add(fieldId);
+        
+        splitMappings.add(new SplitMapping(group, fieldId));
+    }
+
+    public Iterator getSplitMappingsIterator() {
+        return splitMappings.iterator();
+    }
+
+    public Widget createInstance() {
+        AggregateField aggregateField = new AggregateField(this);
+
+        Iterator fieldDefinitionIt = container.getWidgetDefinitions().iterator();
+        while (fieldDefinitionIt.hasNext()) {
+            FieldDefinition fieldDefinition = (FieldDefinition)fieldDefinitionIt.next();
+            aggregateField.addField((Field)fieldDefinition.createInstance());
+        }
+
+        return aggregateField;
+    }
+
+    public static class SplitMapping {
+        private int group;
+        private String fieldId;
+
+        public SplitMapping(int group, String fieldId) {
+            this.group = group;
+            this.fieldId = fieldId;
+        }
+
+        public int getGroup() {
+            return group;
+        }
+
+        public String getFieldId() {
+            return fieldId;
+        }
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/AggregateFieldDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/AggregateFieldDefinitionBuilder.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/AggregateFieldDefinitionBuilder.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/AggregateFieldDefinitionBuilder.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,114 @@
+/*
+ * 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.formmodel;
+
+import org.apache.cocoon.forms.FormsConstants;
+import org.apache.cocoon.forms.util.DomHelper;
+import org.apache.excalibur.xml.sax.XMLizable;
+import org.apache.oro.text.regex.MalformedPatternException;
+import org.apache.oro.text.regex.Pattern;
+import org.apache.oro.text.regex.Perl5Compiler;
+import org.outerj.expression.Expression;
+import org.w3c.dom.Element;
+
+/**
+ * Builds {@link AggregateFieldDefinition}s.
+ *
+ * @version $Id: AggregateFieldDefinitionBuilder.java 326838 2005-10-20 06:26:53Z sylvain $
+ */
+public class AggregateFieldDefinitionBuilder extends FieldDefinitionBuilder {
+
+    public WidgetDefinition buildWidgetDefinition(Element widgetElement) throws Exception {
+        AggregateFieldDefinition definition = new AggregateFieldDefinition();
+        setupDefinition(widgetElement, definition);
+        definition.makeImmutable();
+        return definition;
+    }
+    
+    protected void setupDefinition(Element widgetElement, AggregateFieldDefinition definition) throws Exception {
+        
+        // parse the field definition
+        super.setupDefinition(widgetElement, definition);
+
+        // make children fields
+        Element widgetsElement = DomHelper.getChildElement(widgetElement, FormsConstants.DEFINITION_NS, "widgets", true);
+        Element[] fieldElements = DomHelper.getChildElements(widgetsElement, FormsConstants.DEFINITION_NS, "field");
+        for (int i = 0; i < fieldElements.length; i++) {
+            FieldDefinition fieldDefinition = (FieldDefinition)buildAnotherWidgetDefinition(fieldElements[i]);
+            definition.addWidgetDefinition(fieldDefinition);
+        }
+
+        // compile splitpattern
+        Element splitElement = DomHelper.getChildElement(widgetElement, FormsConstants.DEFINITION_NS, "split", true);
+        if(splitElement!=null) {
+	        String patternString = DomHelper.getAttribute(splitElement, "pattern");
+	        Perl5Compiler compiler = new Perl5Compiler();
+	        Pattern pattern = null;
+	        try {
+	            pattern = compiler.compile(patternString, Perl5Compiler.READ_ONLY_MASK);
+	        } catch (MalformedPatternException e) {
+	            throw new Exception("Invalid regular expression at " + DomHelper.getLocation(splitElement) + ": " + e.getMessage());
+	        }
+	        definition.setSplitPattern(pattern, patternString);
+        }
+
+        // read split mappings
+        Element[] mapElements = DomHelper.getChildElements(splitElement, FormsConstants.DEFINITION_NS, "map");
+        for (int i = 0; i < mapElements.length; i++) {
+            int group = DomHelper.getAttributeAsInteger(mapElements[i], "group");
+            String field = DomHelper.getAttribute(mapElements[i], "field");
+            // check that this field exists
+            if (!definition.hasWidget(field)) {
+                throw new Exception("Unknown widget id \"" + field + "\", at " +
+                                    DomHelper.getLocation(mapElements[i]));
+            }
+            
+            try {
+            	definition.addSplitMapping(group, field);
+            	System.out.println("Aggregate: addSplitMapping("+group+","+field+")");
+            } catch(RuntimeException e) {
+            	throw new Exception("Two groups are mapped to the same widget id \"" + field + "\", at " +
+                        DomHelper.getLocation(mapElements[i]));
+            }
+        }
+
+        // read split fail message (if any)
+        Element failMessageElement = DomHelper.getChildElement(splitElement, FormsConstants.DEFINITION_NS, "failmessage");
+        if (failMessageElement != null) {
+            XMLizable failMessage = DomHelper.compileElementContent(failMessageElement);
+            definition.setSplitFailMessage(failMessage);
+        }
+
+        // compile combine expression
+        Element combineElement = DomHelper.getChildElement(widgetElement, FormsConstants.DEFINITION_NS, "combine", true);
+        if(combineElement!=null) {
+        	String combineExprString = DomHelper.getAttribute(combineElement, "expression");
+            Expression combineExpr = null;
+            try {
+                combineExpr = expressionManager.parse(combineExprString);
+            } catch (Exception e) {
+                throw new Exception("Problem with combine expression defined at " +
+                                    DomHelper.getLocation(combineElement) + ": " + e.getMessage());
+            }
+            Class clazz = definition.getDatatype().getTypeClass();
+            if (combineExpr.getResultType() != null && !clazz.isAssignableFrom(combineExpr.getResultType())) {
+                throw new Exception("The result of the combine expression should be " + clazz.getName() + ", at " +
+                                    DomHelper.getLocation(combineElement));
+            }
+            definition.setCombineExpression(combineExpr);
+        }
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/BooleanField.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/BooleanField.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/BooleanField.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/BooleanField.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,198 @@
+/*
+ * 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.formmodel;
+
+import java.util.Locale;
+
+import org.apache.cocoon.forms.FormsConstants;
+import org.apache.cocoon.forms.FormContext;
+import org.apache.cocoon.forms.event.*;
+import org.apache.cocoon.xml.AttributesImpl;
+import org.apache.cocoon.xml.XMLUtils;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.apache.cocoon.forms.validation.ValidationErrorAware;
+import org.apache.cocoon.forms.validation.ValidationError;
+import org.apache.commons.lang.BooleanUtils;
+
+/**
+ * A widget to select a boolean value. Usually rendered as a checkbox.
+ *
+ * <p>You may wonder why we don't use a {@link Field} widget with an associated
+ * Boolean Datatype instead. The reason is that many of the features of the Field
+ * widget are overkill for a Boolean: validation is unnecessary (if the field is
+ * not true it is false), the selectionlist associated with a Datatype also
+ * has no purpose here (there would always be only 2 choices: true or false),
+ * and the manner in which the request parameter of this widget is interpreted
+ * is different (missing or empty request parameter means 'false', rather than null value).
+ *
+ * @version $Id: BooleanField.java 326930 2005-10-20 16:03:19Z sylvain $
+ */
+public class BooleanField extends AbstractWidget
+                          implements ValidationErrorAware, ValueChangedListenerEnabled {
+
+    private static final String BOOLEAN_FIELD_EL = "booleanfield";
+    private static final String VALUE_EL = "value";
+    private static final String VALIDATION_MSG_EL = "validation-message";
+
+    // FIXME(SW) : should the initial value be false or null ? This would allow
+    // event listeners to be triggered at bind time.
+    private Boolean value = Boolean.FALSE;
+    private final BooleanFieldDefinition definition;
+    /** Additional listeners to those defined as part of the widget definition (if any). */
+    private ValueChangedListener listener;
+    protected ValidationError validationError;
+
+
+    public BooleanField(BooleanFieldDefinition definition) {
+        super(definition);
+        this.definition = definition;
+        this.listener = definition.getValueChangedListener();
+    }
+
+    public WidgetDefinition getDefinition() {
+        return this.definition;
+    }
+
+    public void initialize() {
+        Boolean value = this.definition.getInitialValue();
+        if (value != null) {
+            setValue(value);
+        }
+        super.initialize();
+    }
+
+    public void readFromRequest(FormContext formContext) {
+        if (!getCombinedState().isAcceptingInputs()) {
+            return;
+        }
+
+        validationError = null;
+        Object oldValue = value;
+        String param = formContext.getRequest().getParameter(getRequestParameterName());
+
+        value = BooleanUtils.toBooleanObject(definition.getTrueParamValue().equals(param));
+
+        if (!value.equals(oldValue)) {
+            getForm().addWidgetEvent(new ValueChangedEvent(this, oldValue, value));
+        }
+    }
+
+    /**
+     * Returns the validation error, if any. There will always be a validation error in case the
+     * {@link #validate()} method returned false.
+     */
+    public ValidationError getValidationError() {
+        return validationError;
+    }
+
+    /**
+     * Set a validation error on this field. This allows fields to be externally marked as invalid by
+     * application logic.
+     *
+     * @param error the validation error
+     */
+    public void setValidationError(ValidationError error) {
+        this.validationError = error;
+        getForm().addWidgetUpdate(this);
+    }
+
+    /**
+     * @return "booleanfield"
+     */
+    public String getXMLElementName() {
+        return BOOLEAN_FIELD_EL;
+    }
+
+    protected AttributesImpl getXMLElementAttributes() {
+        AttributesImpl attrs = super.getXMLElementAttributes();
+        // Add the parameter value for true
+        attrs.addCDATAAttribute("true-value", definition.getTrueParamValue());
+        return attrs;
+    }
+
+    public void generateItemSaxFragment(ContentHandler contentHandler, Locale locale) throws SAXException {
+        // value element
+        contentHandler.startElement(FormsConstants.INSTANCE_NS, VALUE_EL, FormsConstants.INSTANCE_PREFIX_COLON + VALUE_EL, XMLUtils.EMPTY_ATTRIBUTES);
+
+        String stringValue = BooleanUtils.toBoolean(value) ? definition.getTrueParamValue() : "false";
+
+        contentHandler.characters(stringValue.toCharArray(), 0, stringValue.length());
+        contentHandler.endElement(FormsConstants.INSTANCE_NS, VALUE_EL, FormsConstants.INSTANCE_PREFIX_COLON + VALUE_EL);
+        // validation message element: only present if the value is not valid
+        if (validationError != null) {
+            contentHandler.startElement(FormsConstants.INSTANCE_NS, VALIDATION_MSG_EL, FormsConstants.INSTANCE_PREFIX_COLON + VALIDATION_MSG_EL, XMLUtils.EMPTY_ATTRIBUTES);
+            validationError.generateSaxFragment(contentHandler);
+            contentHandler.endElement(FormsConstants.INSTANCE_NS, VALIDATION_MSG_EL, FormsConstants.INSTANCE_PREFIX_COLON + VALIDATION_MSG_EL);
+        }
+    }
+
+    public Object getValue() {
+        return value;
+    }
+
+    /**
+     * Sets value of the field. If value is null, it is considered to be false
+     * (see class comment).
+     */
+    public void setValue(Object object) {
+        if (object == null) {
+            object = Boolean.FALSE;
+        }
+
+        if (!(object instanceof Boolean)) {
+            throw new RuntimeException("Cannot set value of boolean field \"" + getRequestParameterName() + "\" to a non-Boolean value.");
+        }
+
+        Object oldValue = value;
+        value = (Boolean)object;
+        if (!value.equals(oldValue)) {
+            Form form = getForm();
+            if (hasValueChangedListeners()) {
+                form.addWidgetEvent(new ValueChangedEvent(this, oldValue, value));
+            }
+            form.addWidgetUpdate(this);
+        }
+    }
+
+    /**
+     * Adds a ValueChangedListener to this widget instance. Listeners defined
+     * on the widget instance will be executed in addtion to any listeners
+     * that might have been defined in the widget definition.
+     */
+    public void addValueChangedListener(ValueChangedListener listener) {
+        this.listener = WidgetEventMulticaster.add(this.listener, listener);
+    }
+
+    public void removeValueChangedListener(ValueChangedListener listener) {
+        this.listener = WidgetEventMulticaster.remove(this.listener, listener);
+    }
+    
+    public boolean hasValueChangedListeners() {
+        return this.listener != null || this.getForm().hasFormHandler();
+    }
+
+    public void broadcastEvent(WidgetEvent event) {
+        if (event instanceof ValueChangedEvent) {
+            if (this.listener != null) {
+                this.listener.valueChanged((ValueChangedEvent)event);
+            }
+        } else {
+            // Other kinds of events
+            super.broadcastEvent(event);
+        }
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/BooleanFieldDefinition.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/BooleanFieldDefinition.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/BooleanFieldDefinition.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/BooleanFieldDefinition.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,101 @@
+/*
+ * 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.formmodel;
+
+import org.apache.cocoon.forms.event.ValueChangedEvent;
+import org.apache.cocoon.forms.event.ValueChangedListener;
+import org.apache.cocoon.forms.event.WidgetEventMulticaster;
+
+/**
+ * The {@link WidgetDefinition} part of a BooleanField widget, see {@link BooleanField} for more information.
+ * 
+ * @version $Id: BooleanFieldDefinition.java 326930 2005-10-20 16:03:19Z sylvain $
+ */
+public class BooleanFieldDefinition extends AbstractWidgetDefinition {
+    private ValueChangedListener listener;
+    
+    private Boolean initialValue;
+    
+    private String trueParamValue = "true";
+
+    public Widget createInstance() {
+        return new BooleanField(this);
+    }
+    
+    /**
+     * initialize this definition with the other, sort of like a copy constructor
+     */
+    public void initializeFrom(WidgetDefinition definition) throws Exception {
+    	super.initializeFrom(definition);
+    	
+    	if(definition instanceof BooleanFieldDefinition) {
+    		BooleanFieldDefinition other = (BooleanFieldDefinition)definition;
+    		
+    		this.listener = other.listener;
+    		this.initialValue = other.initialValue;
+    		this.trueParamValue = other.trueParamValue;
+    		
+    	} else {
+    		throw new Exception("Definition to inherit from is not of the right type! (at "+getLocation()+")");
+    	}
+    }
+    
+    public void setInitialValue(Boolean value) {
+        checkMutable();
+        this.initialValue = value;
+    }
+    
+    public Boolean getInitialValue() {
+        return this.initialValue;
+    }
+    
+    public void setTrueParamValue(String value) {
+        checkMutable();
+        this.trueParamValue = value;
+    }
+    
+    /**
+     * Get the parameter value that indicates a true value. Default
+     * is "<code>true</code>".
+     */
+    public String getTrueParamValue() {
+        return this.trueParamValue;
+    }
+    
+    public void addValueChangedListener(ValueChangedListener listener) {
+        checkMutable();
+        this.listener = WidgetEventMulticaster.add(this.listener, listener);
+    }
+    
+    public ValueChangedListener getValueChangedListener() {
+        return this.listener;
+    }
+    
+    public void fireValueChangedEvent(ValueChangedEvent event) {
+        if (this.listener != null) {
+            this.listener.valueChanged(event);
+        }
+    }
+
+    public boolean hasValueChangedListeners() {
+        return listener != null;
+    }
+        
+    public void setRequired(boolean required) {
+        checkMutable();
+        throw new UnsupportedOperationException("The property 'required' is not available on widgets of type booleanfield.");
+    }    
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/BooleanFieldDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/BooleanFieldDefinitionBuilder.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/BooleanFieldDefinitionBuilder.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/BooleanFieldDefinitionBuilder.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,58 @@
+/*
+ * 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.formmodel;
+
+import java.util.Iterator;
+
+import org.apache.cocoon.forms.FormsConstants;
+import org.apache.cocoon.forms.event.ValueChangedListener;
+import org.apache.cocoon.forms.util.DomHelper;
+import org.w3c.dom.Element;
+
+/**
+ * Builds {@link BooleanFieldDefinition}s.
+ * 
+ * @version $Id: BooleanFieldDefinitionBuilder.java 326838 2005-10-20 06:26:53Z sylvain $
+ */
+public final class BooleanFieldDefinitionBuilder extends AbstractWidgetDefinitionBuilder {
+    public WidgetDefinition buildWidgetDefinition(Element widgetElement) throws Exception {
+        
+        BooleanFieldDefinition definition = new BooleanFieldDefinition();
+        
+        setupDefinition(widgetElement, definition);
+        setDisplayData(widgetElement, definition);
+        Iterator iter = buildEventListeners(widgetElement, "on-value-changed", ValueChangedListener.class).iterator();
+        while (iter.hasNext()) {
+            definition.addValueChangedListener((ValueChangedListener)iter.next());
+        }
+
+        // Initial value
+        Element initialValueElement = DomHelper.getChildElement(widgetElement, FormsConstants.DEFINITION_NS, "initial-value", false);
+        if (initialValueElement != null) {
+            Boolean initialValue = Boolean.valueOf(DomHelper.getElementText(initialValueElement));
+            definition.setInitialValue(initialValue);
+        }
+        
+        // Parameter value for true
+        Element trueParamElement = DomHelper.getChildElement(widgetElement, FormsConstants.DEFINITION_NS, "true-param-value", false);
+        if (trueParamElement != null) {
+            definition.setTrueParamValue(DomHelper.getElementText(trueParamElement));
+        }
+
+        definition.makeImmutable();
+        return definition;
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/ButtonDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/ButtonDefinitionBuilder.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/ButtonDefinitionBuilder.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/ButtonDefinitionBuilder.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,31 @@
+/*
+ * 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.formmodel;
+
+import org.w3c.dom.Element;
+import org.apache.cocoon.forms.util.DomHelper;
+
+/**
+ * The ButtonDefinitionBuilder has been replaced by {@link ActionDefinitionBuilder}. This implementation
+ * is only left here to give a warning to users.
+ * 
+ * @version $Id: ButtonDefinitionBuilder.java 289538 2005-09-16 13:46:22Z sylvain $
+ */
+public class ButtonDefinitionBuilder extends AbstractWidgetDefinitionBuilder {
+    public WidgetDefinition buildWidgetDefinition(Element widgetElement) throws Exception {
+        throw new Exception("The button widget has been renamed to action. Please update your form definition files. Found at " + DomHelper.getLocation(widgetElement));
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/CannotYetResolveWarning.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/CannotYetResolveWarning.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/CannotYetResolveWarning.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/CannotYetResolveWarning.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,29 @@
+/*
+ * 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.formmodel;
+
+/**
+ * This exception is thrown by {@link ExpressionContextImpl} when it asked for
+ * the value of a required field, when that required field does not yet have
+ * a value.
+ * 
+ * @version $Id: CannotYetResolveWarning.java 56582 2004-11-04 10:16:22Z sylvain $
+ */
+public class CannotYetResolveWarning extends  RuntimeException {
+    public String getMessage() {
+        return "An expression variable could not yet be resolved.";
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/CaptchaDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/CaptchaDefinitionBuilder.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/CaptchaDefinitionBuilder.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/CaptchaDefinitionBuilder.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,57 @@
+/*
+ * 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.formmodel;
+
+import org.apache.avalon.framework.context.Context;
+import org.apache.avalon.framework.context.ContextException;
+import org.apache.avalon.framework.context.Contextualizable;
+import org.apache.avalon.framework.thread.ThreadSafe;
+import org.apache.cocoon.forms.util.DomHelper;
+import org.w3c.dom.Element;
+
+/**
+ * Builds {@link CaptchaFieldDefinition}s.
+ *
+ * @see http://www.captcha.net/
+ * @version $Id: CaptchaDefinitionBuilder.java 171293 2005-05-22 08:55:42Z sylvain $
+ */
+public class CaptchaDefinitionBuilder extends AbstractDatatypeWidgetDefinitionBuilder implements Contextualizable, ThreadSafe {
+    
+    private Context avalonContext;
+    
+    public void contextualize(Context context) throws ContextException {
+        this.avalonContext = context;
+    }
+
+    public WidgetDefinition buildWidgetDefinition(Element widgetElement) throws Exception {
+        FieldDefinition definition = new CaptchaFieldDefinition(avalonContext);
+        setupDefinition(widgetElement, definition);
+        definition.makeImmutable();
+        return definition;
+    }
+
+    protected void setupDefinition(Element widgetElement, FieldDefinition definition) throws Exception {
+        super.setupDefinition(widgetElement, definition);
+        
+        // parse "@required"
+        boolean required = DomHelper.getAttributeAsBoolean(widgetElement, "required", false);
+        definition.setRequired(required);
+        
+        // parse "@length"
+        int length = DomHelper.getAttributeAsInteger(widgetElement, "length", 7);
+        ((CaptchaFieldDefinition) definition).setLength(length);
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/CaptchaField.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/CaptchaField.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/CaptchaField.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/CaptchaField.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,119 @@
+/*
+ * 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.formmodel;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.avalon.framework.CascadingRuntimeException;
+import org.apache.avalon.framework.context.Context;
+import org.apache.cocoon.components.ContextHelper;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Session;
+import org.apache.cocoon.forms.FormsConstants;
+import org.apache.cocoon.xml.AttributesImpl;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+
+/**
+ * A {@link Field} for CAPTCHA validation. Upon generation, a secret random string is stored
+ * in a session attribute having a randomly generated name, for use by a
+ * {@link org.apache.cocoon.forms.validation.impl.CaptchaValidator}.
+ * <br>
+ * Usage sample:
+ * <pre>
+    &lt;fd:captcha id="f1" required="true">
+      &lt;fd:label>Copy the number shown into the input field&lt;/fd:label>
+      &lt;fd:datatype base="string"/>
+      &lt;fd:validation>
+        &lt;fd:captcha/>
+      &lt;/fd:validation>
+    &lt;/fd:captcha>
+ * </pre>
+ *
+ * @see <a href="http://www.captcha.net/">captcha.net</a>
+ * @version CVS $Id: CaptchaField.java 326838 2005-10-20 06:26:53Z sylvain $
+ */
+public class CaptchaField extends Field {
+
+    public static final String SESSION_ATTR_PREFIX = "captcha-";
+
+    private static final String IMAGE_EL = "captcha-image";
+    private static final String SECRET_CHARS = "abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ123456789";
+    private static final int SESSION_ATTR_NAME_LENGTH = 6;
+
+    private Context avalonContext;
+    private int length;
+
+    /**
+     * Random number generator used to create session attribute name.
+     */
+    protected static SecureRandom random;
+
+    static {
+        try {
+            random = SecureRandom.getInstance("SHA1PRNG");
+        } catch(java.security.NoSuchAlgorithmException nsae) {
+            // Maybe we are on IBM's SDK
+            try {
+                random = SecureRandom.getInstance("IBMSecureRandom");
+            } catch (NoSuchAlgorithmException e) {
+                throw new CascadingRuntimeException("No random number generator available", e);
+            }
+        }
+        random.setSeed(System.currentTimeMillis());
+    }
+
+    public CaptchaField(CaptchaFieldDefinition fieldDefinition, Context avalonContext) {
+        super(fieldDefinition);
+        this.avalonContext = avalonContext;
+        this.length = fieldDefinition.getLength();
+    }
+
+    private String generateSecret() {
+        StringBuffer secret = new StringBuffer(length);
+        for (int n = 0 ; n < length ; n++) {
+            int randomnumber = random.nextInt(SECRET_CHARS.length());
+            secret.append(SECRET_CHARS.charAt(randomnumber));
+        }
+        return secret.toString();
+    }
+
+    public void generateItemSaxFragment(ContentHandler contentHandler, Locale locale) throws SAXException {
+        super.generateItemSaxFragment(contentHandler, locale);
+        byte[] bytes = new byte[SESSION_ATTR_NAME_LENGTH];
+        char[] result = new char[bytes.length * 2];
+        random.nextBytes(bytes);
+        for (int i = 0; i < SESSION_ATTR_NAME_LENGTH; i++) {
+            byte ch = bytes[i];
+            result[2 * i] = Character.forDigit(Math.abs(ch >> 4), 16);
+            result[2 * i + 1] = Character.forDigit(Math.abs(ch & 0x0f), 16);
+        }
+        String id = new String(result);
+        Map objectModel = ContextHelper.getObjectModel(this.avalonContext);
+        Session session = ObjectModelHelper.getRequest(objectModel).getSession(true);
+        String secret = generateSecret();
+        session.setAttribute(SESSION_ATTR_PREFIX + id, secret);
+        this.setAttribute("secret", secret);
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "id", "id", "PCDATA", id);
+        contentHandler.startElement(FormsConstants.INSTANCE_NS, IMAGE_EL, FormsConstants.INSTANCE_PREFIX_COLON + IMAGE_EL, attrs);
+        contentHandler.endElement(FormsConstants.INSTANCE_NS, IMAGE_EL, FormsConstants.INSTANCE_PREFIX_COLON + IMAGE_EL);
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/CaptchaFieldDefinition.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/CaptchaFieldDefinition.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/CaptchaFieldDefinition.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/CaptchaFieldDefinition.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,65 @@
+/*
+ * 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.formmodel;
+
+import org.apache.avalon.framework.context.Context;
+
+/**
+ * A {@link FieldDefinition} for {@link CaptchaField}s.
+ * 
+ * @see http://www.captcha.net/
+ * @version CVS $Id: CaptchaFieldDefinition.java 289538 2005-09-16 13:46:22Z sylvain $
+ */
+public class CaptchaFieldDefinition extends FieldDefinition {
+    
+    private Context avalonContext;
+    private int length;
+
+    public CaptchaFieldDefinition(Context avalonContext) {
+        this.avalonContext = avalonContext;
+    }
+    
+    /**
+     * initialize this definition with the other, sort of like a copy constructor
+     */
+    public void initializeFrom(WidgetDefinition definition) throws Exception {
+    	super.initializeFrom(definition);
+    	
+    	if(definition instanceof CaptchaFieldDefinition) {
+    		CaptchaFieldDefinition other = (CaptchaFieldDefinition)definition;
+    		
+    		this.length = other.length;
+    		
+    	} else {
+    		throw new Exception("Definition to inherit from is not of the right type! (at "+getLocation()+")");
+    	}
+    }
+
+    public Widget createInstance() {
+        CaptchaField field = new CaptchaField(this, avalonContext);
+        return field;
+    }
+
+    public int getLength() {
+        return length;
+    }
+
+    public void setLength(int length) {
+        checkMutable();
+        this.length = length;
+    }
+
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/ClassDefinition.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/ClassDefinition.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/ClassDefinition.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/ClassDefinition.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,28 @@
+/*
+ * 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.formmodel;
+
+/**
+ * A {@link WidgetDefinition} which holds a collection of {@link Widget}s
+ * and which can be instantiated with a {@link NewDefinition}.
+ *
+ * @version $Id: ClassDefinition.java 56582 2004-11-04 10:16:22Z sylvain $
+ */
+public class ClassDefinition extends AbstractContainerDefinition {
+    public Widget createInstance() {
+        return null;
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/ClassDefinitionBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/ClassDefinitionBuilder.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/ClassDefinitionBuilder.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-forms-block/impl/src/main/java/org/apache/cocoon/forms/formmodel/ClassDefinitionBuilder.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,39 @@
+/*
+ * 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.formmodel;
+
+import org.w3c.dom.Element;
+
+/**
+ * Builds {ClassDefinition}s.
+ *
+ * @version $Id: ClassDefinitionBuilder.java 289538 2005-09-16 13:46:22Z sylvain $
+ */
+public final class ClassDefinitionBuilder extends AbstractContainerDefinitionBuilder {
+
+    public WidgetDefinition buildWidgetDefinition(Element element) throws Exception {
+        ClassDefinition definition = new ClassDefinition();
+        
+        super.setupDefinition(element, definition);
+        setDisplayData(element, definition);
+
+        setupContainer(element,"widgets",definition);
+
+        definition.makeImmutable();
+        
+        return definition;
+    }
+}

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



Mime
View raw message