click-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sa...@apache.org
Subject svn commit: r749759 - in /incubator/click/trunk/click/framework/src/org/apache/click: control/AbstractContainer.java control/FieldSet.java control/Form.java util/ContainerUtils.java
Date Tue, 03 Mar 2009 21:22:37 GMT
Author: sabob
Date: Tue Mar  3 21:22:37 2009
New Revision: 749759

URL: http://svn.apache.org/viewvc?rev=749759&view=rev
Log:
Refactored FieldSet and removed the innerclass delegate. Added  insert and remove methods
to ContainerUtils.

Modified:
    incubator/click/trunk/click/framework/src/org/apache/click/control/AbstractContainer.java
    incubator/click/trunk/click/framework/src/org/apache/click/control/FieldSet.java
    incubator/click/trunk/click/framework/src/org/apache/click/control/Form.java
    incubator/click/trunk/click/framework/src/org/apache/click/util/ContainerUtils.java

Modified: incubator/click/trunk/click/framework/src/org/apache/click/control/AbstractContainer.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/framework/src/org/apache/click/control/AbstractContainer.java?rev=749759&r1=749758&r2=749759&view=diff
==============================================================================
--- incubator/click/trunk/click/framework/src/org/apache/click/control/AbstractContainer.java
(original)
+++ incubator/click/trunk/click/framework/src/org/apache/click/control/AbstractContainer.java
Tue Mar  3 21:22:37 2009
@@ -25,10 +25,9 @@
 import java.util.Map;
 
 import org.apache.click.Control;
-import org.apache.click.Page;
 import org.apache.click.util.ClickUtils;
+import org.apache.click.util.ContainerUtils;
 import org.apache.click.util.HtmlStringBuffer;
-import org.apache.commons.lang.ClassUtils;
 
 /**
  * Provides a default implementation of the {@link Container} interface,
@@ -118,63 +117,7 @@
      * <tt>(index &lt; 0 || index &gt; getControls().size())</tt>
      */
     public Control insert(Control control, int index) {
-
-        // Pre conditions start
-        if (control == null) {
-            throw new IllegalArgumentException("Null control parameter");
-        }
-        if (control == this) {
-            throw new IllegalArgumentException("Cannot add container to itself");
-        }
-        int size = getControls().size();
-        if (index > size || index < 0) {
-            throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
-                + size);
-        }
-        if (control instanceof Field) {
-            Field field = (Field) control;
-            // Check if container already contains the field. Labels can share
-            // names though.
-            if (getControlMap().containsKey(field.getName())
-                && !(field instanceof Label)) {
-                String msg = "Container already contains field named: " + field.getName();
-                throw new IllegalArgumentException(msg);
-            }
-        } else {
-            // Check if container already contains the control
-            if (getControlMap().containsKey(control.getName())) {
-                throw new IllegalArgumentException(
-                    "Container already contains control named: " + control.getName());
-            }
-        }
-        // Pre conditions end
-
-        // Check if control already has parent
-        // If parent references *this* container, there is no need to remove it
-        Object currentParent = control.getParent();
-        if (currentParent != null && currentParent != this) {
-
-            // Remove control from parent Page or Container
-            if (currentParent instanceof Page) {
-                ((Page) currentParent).removeControl(control);
-
-            } else if (currentParent instanceof Container) {
-                ((Container) currentParent).remove(control);
-            }
-
-            // Create warning message to users that the parent has been reset
-            logParentReset(control, currentParent);
-        }
-
-        // Note: set parent first since setParent might veto further processing
-        control.setParent(this);
-        getControls().add(index, control);
-
-        String controlName = control.getName();
-        if (controlName != null) {
-            getControlMap().put(controlName, control);
-        }
-        return control;
+        return ContainerUtils.insert(this, control, index, getControlMap());
     }
 
     /**
@@ -185,29 +128,7 @@
      * @throws IllegalArgumentException if the control is null
      */
     public boolean remove(Control control) {
-        if (control == null) {
-            throw new IllegalArgumentException("Control cannot be null");
-        }
-
-        boolean contains = getControls().remove(control);
-
-        if (contains) {
-            // Only nullify if this container is parent. This check is for the
-            // case where a Control has two parents e.g. Page and Form.
-            // NOTE the current #insert logic does not allow Controls to have
-            // two parents so this check might be redundant.
-            if (control.getParent() == this) {
-                control.setParent(null);
-            }
-
-            String controlName = control.getName();
-
-            if (controlName != null) {
-                getControlMap().remove(controlName);
-            }
-        }
-
-        return contains;
+        return ContainerUtils.remove(this, control, getControlMap());
     }
 
     /**
@@ -464,62 +385,4 @@
             }
         }
     }
-
-    // -------------------------------------------------------- Private Methods
-
-    /**
-     * Log a warning that the parent of the specified control will be set to
-     * this container.
-     *
-     * @param control the control which parent is being reset
-     * @param currentParent the control current parent
-     */
-    private void logParentReset(Control control, Object currentParent) {
-        HtmlStringBuffer message = new HtmlStringBuffer();
-
-        message.append("Changed ");
-        message.append(ClassUtils.getShortClassName(control.getClass()));
-        String controlId = control.getId();
-        if (controlId != null) {
-            message.append("[");
-            message.append(controlId);
-            message.append("]");
-        } else {
-            message.append("#");
-            message.append(control.hashCode());
-        }
-        message.append(" parent from ");
-
-        if (currentParent instanceof Page) {
-            message.append(ClassUtils.getShortClassName(currentParent.getClass()));
-
-        } else if (currentParent instanceof Container) {
-            Container parentContainer = (Container) currentParent;
-
-            message.append(ClassUtils.getShortClassName(parentContainer.getClass()));
-            String parentId = parentContainer.getId();
-            if (parentId != null) {
-                message.append("[");
-                message.append(parentId);
-                message.append("]");
-            } else {
-                message.append("#");
-                message.append(parentContainer.hashCode());
-            }
-        }
-
-        message.append(" to ");
-        message.append(ClassUtils.getShortClassName(this.getClass()));
-        String id = this.getId();
-        if (id != null) {
-            message.append("[");
-            message.append(id);
-            message.append("]");
-        } else {
-            message.append("#");
-            message.append(this.hashCode());
-        }
-
-        ClickUtils.getLogService().warn(message);
-    }
 }

Modified: incubator/click/trunk/click/framework/src/org/apache/click/control/FieldSet.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/framework/src/org/apache/click/control/FieldSet.java?rev=749759&r1=749758&r2=749759&view=diff
==============================================================================
--- incubator/click/trunk/click/framework/src/org/apache/click/control/FieldSet.java (original)
+++ incubator/click/trunk/click/framework/src/org/apache/click/control/FieldSet.java Tue Mar
 3 21:22:37 2009
@@ -24,7 +24,6 @@
 import java.util.List;
 import java.util.Map;
 import org.apache.click.ActionListener;
-import org.apache.click.Context;
 import org.apache.click.Control;
 import org.apache.click.util.ClickUtils;
 import org.apache.click.util.ContainerUtils;
@@ -104,6 +103,15 @@
 
     // ----------------------------------------------------- Instance Variables
 
+    /** The list of controls. */
+    protected List controls;
+
+    /** The map of controls keyed by field name. */
+    protected Map controlMap;
+
+    /** The ordered list of fields, excluding buttons. */
+    protected final List fieldList = new ArrayList();
+
     /** The map of field width values. */
     protected Map fieldWidths;
 
@@ -124,9 +132,6 @@
      */
     protected Integer columns;
 
-    /** Internal container instance. */
-    private InnerContainerField container = new InnerContainerField();
-
     // ----------------------------------------------------------- Constructors
 
     /**
@@ -177,7 +182,7 @@
      * it will automatically be removed from that parent and inserted into the
      * fieldSet.
      *
-     * @see Container#add(org.apache.click.Control)
+     * @see Container#insert(org.apache.click.Control, int)
      *
      * @param control the control to add to the FieldSet and return
      * @param index the index at which the control is to be inserted
@@ -187,7 +192,33 @@
      * name or if the control is neither a Field nor FieldSet
      */
     public Control insert(Control control, int index) {
-        return container.insert(control, index);
+        ContainerUtils.insert(this, control, index, getControlMap());
+
+        if (control instanceof Field) {
+            Field field = (Field) control;
+
+            // Add field to fieldList for fast access
+            if (!(field instanceof Button)) {
+                getFieldList().add(field);
+            }
+
+            Form form = getForm();
+            field.setForm(form);
+
+            if (form != null && form.getDefaultFieldSize() > 0) {
+                if (field instanceof TextField) {
+                    ((TextField) field).setSize(form.getDefaultFieldSize());
+
+                } else if (field instanceof FileField) {
+                    ((FileField) field).setSize(form.getDefaultFieldSize());
+
+                } else if (field instanceof TextArea) {
+                    ((TextArea) field).setCols(form.getDefaultFieldSize());
+                }
+            }
+        }
+
+        return control;
     }
 
     /**
@@ -298,7 +329,20 @@
      * @throws IllegalArgumentException if the control is null
      */
     public boolean remove(Control control) {
-        return container.remove(control);
+        boolean removed = ContainerUtils.remove(this, control, getControlMap());
+
+        if (removed && control instanceof Field) {
+            Field field = (Field) control;
+
+            field.setForm(null);
+
+            if (!(field instanceof Button)) {
+                getFieldList().remove(field);
+            }
+        }
+        getFieldWidths().remove(control.getName());
+
+        return removed;
     }
 
     /**
@@ -336,7 +380,10 @@
      * @return the sequential list of controls held by the container
      */
     public List getControls() {
-        return container.getControls();
+        if (controls == null) {
+            controls = new ArrayList();
+        }
+        return controls;
     }
 
     /**
@@ -346,7 +393,10 @@
      * @return the named control from the container if found or null otherwise
      */
     public Control getControl(String controlName) {
-        return container.getControl(controlName);
+        if (hasControls()) {
+            return (Control) getControlMap().get(controlName);
+        }
+        return null;
     }
 
     /**
@@ -356,7 +406,7 @@
      * @return true if the container contains the specified control
      */
     public boolean contains(Control control) {
-        return container.contains(control);
+        return getControls().contains(control);
     }
 
     /**
@@ -367,7 +417,7 @@
      * @return true if the container has existing controls, false otherwise.
      */
     public boolean hasControls() {
-        return container.hasControls();
+        return (controls == null) ? false : !controls.isEmpty();
     }
 
     /**
@@ -429,7 +479,7 @@
             return readonly;
         }
     }
- 
+
     /**
      * Set the FieldSet readonly flag which in turn will set all its fields
      * to readonly.
@@ -503,15 +553,17 @@
     }
 
     /**
-     * Return the List of fields in the same order they were added to the
-     * fieldset.
+     * Return the ordered list of FieldSet fields, excluding buttons.
+     * <p/>
+     * The order of the fields is the same order they were added to the
+     * FieldSet.
      * <p/>
      * The returned list only includes fields directly added to the FieldSet.
      *
      * @return the ordered List of fieldset fields
      */
     public List getFieldList() {
-        return container.getFieldList();
+        return fieldList;
     }
 
     /**
@@ -566,9 +618,9 @@
      * and JavaScript files
      */
     public String getHtmlImports() {
-        HtmlStringBuffer buffer = new HtmlStringBuffer(512);
-
         if (hasControls()) {
+            HtmlStringBuffer buffer = new HtmlStringBuffer(512);
+
             for (int i = 0, size = getControls().size(); i < size; i++) {
                 Control control = (Control) getControls().get(i);
                 String htmlImports = control.getHtmlImports();
@@ -576,9 +628,10 @@
                     buffer.append(htmlImports);
                 }
             }
+            return buffer.toString();
         }
 
-        return buffer.toString();
+        return null;
     }
 
     /**
@@ -712,21 +765,41 @@
      * @see org.apache.click.Control#onDestroy()
      */
     public void onDestroy() {
-        container.onDestroy();
+        if (hasControls()) {
+            for (int i = 0, size = getControls().size(); i < size; i++) {
+                Control control = (Control) getControls().get(i);
+                try {
+                    control.onDestroy();
+                } catch (Throwable t) {
+                    ClickUtils.getLogService().error("onDestroy error", t);
+                }
+            }
+        }
     }
 
-    /**
-     * @see org.apache.click.Control#onInit()
-     */
+   /**
+    * @see org.apache.click.Control#onInit()
+    */
     public void onInit() {
-        container.onInit();
+        super.onInit();
+        if (hasControls()) {
+            for (int i = 0, size = getControls().size(); i < size; i++) {
+                Control control = (Control) getControls().get(i);
+                control.onInit();
+            }
+        }
     }
 
-    /**
-     * @see org.apache.click.Control#onRender()
-     */
+   /**
+    * @see org.apache.click.Control#onRender()
+    */
     public void onRender() {
-        container.onRender();
+        if (hasControls()) {
+            for (int i = 0, size = getControls().size(); i < size; i++) {
+                Control control = (Control) getControls().get(i);
+                control.onRender();
+            }
+        }
     }
 
     /**
@@ -838,7 +911,10 @@
      * @return the map of controls
      */
     protected Map getControlMap() {
-        return container.getControlMap();
+        if (controlMap == null) {
+            controlMap = new HashMap();
+        }
+        return controlMap;
     }
 
     /**
@@ -847,7 +923,17 @@
      * @return the estimated rendered control size in characters
      */
     protected int getControlSizeEst() {
-        return container.getControlSizeEst();
+        int size = 20;
+
+        if (getTag() != null && hasAttributes()) {
+            size += 20 * getAttributes().size();
+        }
+
+        if (hasControls()) {
+            size += getControls().size() * size;
+        }
+
+        return size;
     }
 
     /**
@@ -1070,212 +1156,4 @@
             return ((Field) control).isHidden();
         }
     }
-
-    // ------------------------------------------------------------ Inner Class
-
-    /**
-     * Inner class providing the container implementation for
-     * FieldSet.
-     * <p/>
-     * Note this class delegates certain methods to FieldSet, so
-     * that the Container implementation can manipulate state of the
-     * FieldSet instance.
-     */
-    private class InnerContainerField extends AbstractContainer {
-
-        // ---------------------------------------------------------- Variables
-
-        private static final long serialVersionUID = 1L;
-
-        /** The ordered list of fields, excluding buttons. */
-        protected final List fieldList = new ArrayList();
-
-        // ----------------------------------------------------- Public Methods
-
-        /**
-         * Add a Field to the FieldSet and return the added instance.
-         *
-         * @see Container#add(org.apache.click.Control)
-         *
-         * @param control the control to add to the FieldSet and return
-         * @param index the index at which the control is to be inserted
-         * @return the control that was added to the FieldSet
-         *
-         * @throws IllegalArgumentException if the control is null, the Field's name
-         * is not defined, the container already contains a control with the same
-         * name or if the Field name is not defined
-         */
-        public Control insert(Control control, int index) {
-            super.insert(control, index);
-            control.setParent(FieldSet.this);
-
-            if (control instanceof Field) {
-                Field field = (Field) control;
-
-                // Add field to fieldList for fast access
-                if (!(field instanceof Button)) {
-                    getFieldList().add(field);
-                }
-
-                Form form = getForm();
-                field.setForm(form);
-
-                if (form != null && form.getDefaultFieldSize() > 0) {
-                    if (field instanceof TextField) {
-                        ((TextField) field).setSize(form.getDefaultFieldSize());
-
-                    } else if (field instanceof FileField) {
-                        ((FileField) field).setSize(form.getDefaultFieldSize());
-
-                    } else if (field instanceof TextArea) {
-                        ((TextArea) field).setCols(form.getDefaultFieldSize());
-                    }
-                }
-            }
-
-            return control;
-        }
-
-        /**
-         * @see org.apache.click.control.Container#remove(org.apache.click.Control).
-         *
-         * @param control the control to remove from the container
-         * @return true if the control was removed from the container
-         * @throws IllegalArgumentException if the control is null
-         */
-        public boolean remove(Control control) {
-
-            boolean removed = super.remove(control);
-            if (control.getParent() == FieldSet.this) {
-                control.setParent(null);
-            }
-
-            if (removed && control instanceof Field) {
-                Field field = (Field) control;
-
-                field.setForm(null);
-
-                if (!(field instanceof Button)) {
-                    getFieldList().remove(field);
-                }
-            }
-            getFieldWidths().remove(control.getName());
-
-            return removed;
-        }
-
-        /**
-         * Return the ordered list of FieldSet fields, excluding buttons.
-         * <p/>
-         * The order of the fields is the same order they were added to the
-         * FieldSet.
-         * <p/>
-         * The returned list only includes fields directly added to the FieldSet.
-         *
-         * @return the ordered List of fieldSet fields, excluding buttons
-         */
-        public List getFieldList() {
-            return fieldList;
-        }
-
-        /**
-         * Return the FieldSet html tag.
-         *
-         * @return the FieldSet html tag
-         */
-        public String getTag() {
-            return FieldSet.this.getTag();
-        }
-
-        /**
-         * Sets the FieldSet parent.
-         *
-         * @param parent the parent of the FieldSet
-         */
-        public void setParent(Object parent) {
-            FieldSet.this.setParent(parent);
-        }
-
-        /**
-         * Sets the FieldSet name.
-         *
-         * @param name the name of the FieldSet
-         */
-        public void setName(String name) {
-            FieldSet.this.setName(name);
-        }
-
-        /**
-         * Sets the action listener of the FieldSet.
-         *
-         * @param actionListener the action listener object to invoke
-         */
-        public void setActionListener(ActionListener actionListener) {
-            FieldSet.this.setActionListener(actionListener);
-        }
-
-        /**
-         * Sets the listener of the FieldSet.
-         *
-         * @param listener the listener object with the named method to invoke
-         * @param method the name of the method to invoke
-         */
-        public void setListener(Object listener, String method) {
-            FieldSet.this.setListener(listener, method);
-        }
-
-        /**
-         * Return the parent of the FieldSet.
-         *
-         * @return the parent of the FieldSet
-         */
-        public Object getParent() {
-            return FieldSet.this.getParent();
-        }
-
-        /**
-         * Return the name of the FieldSet.
-         *
-         * @return the name of the FieldSet
-         */
-        public String getName() {
-            return FieldSet.this.getName();
-        }
-
-        /**
-         * Return the messages of the FieldSet.
-         *
-         * @return the message of the FieldSet
-         */
-        public Map getMessages() {
-            return FieldSet.this.getMessages();
-        }
-
-        /**
-         * Return the id of the FieldSet.
-         *
-         * @return the id of the FieldSet
-         */
-        public String getId() {
-            return FieldSet.this.getId();
-        }
-
-        /**
-         * Return the html imports of the FieldSet.
-         *
-         * @return the html imports of the FieldSet
-         */
-        public String getHtmlImports() {
-            return FieldSet.this.getHtmlImports();
-        }
-
-        /**
-         * Return the Context of the FieldSet.
-         *
-         * @return the Context of the FieldSet
-         */
-        public Context getContext() {
-            return FieldSet.this.getContext();
-        }
-    }
 }

Modified: incubator/click/trunk/click/framework/src/org/apache/click/control/Form.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/framework/src/org/apache/click/control/Form.java?rev=749759&r1=749758&r2=749759&view=diff
==============================================================================
--- incubator/click/trunk/click/framework/src/org/apache/click/control/Form.java (original)
+++ incubator/click/trunk/click/framework/src/org/apache/click/control/Form.java Tue Mar 
3 21:22:37 2009
@@ -648,29 +648,6 @@
     // --------------------------------------------------------- Container Impl
 
     /**
-     * Add a Control to the form and return the added instance.
-     * <p/>
-     * Controls can be retrieved from the Map {@link #getControlMap() controlMap}
-     * where the key is the Control name and value is the Control instance.
-     * <p/>
-     * All controls are available on the {@link #getControls() controls} list
-     * in the order they were added. If you are only interested in Fields,
-     * note that Buttons are available on the {@link #getButtonList() buttonList}
-     * while other fields are available on {@link #getFieldList() fieldList}.
-     *
-     * @see Container#add(org.apache.click.Control)
-     *
-     * @param control the control to add to the container and return
-     * @return the control that was added to the container
-     * @throws IllegalArgumentException if the control is null, the Control name
-     * is not defined or the container already contains a control with the same
-     * name
-     */
-    public Control add(Control control) {
-        return super.add(control);
-    }
-
-    /**
      * Add the control to the form at the specified index, and return the
      * added instance.
      * <p/>
@@ -694,7 +671,7 @@
      * hidden fields might influence the position of the Control you insert.
      * <em>This restriction might be removed in a future version of Click.</em>
      *
-     * @see org.apache.click.control.Container#insert(org.apache.click.Control, int)
+     * @see Container#insert(org.apache.click.Control, int)
      *
      * @param control the control to add to the container
      * @param index the index at which the control is to be inserted
@@ -741,6 +718,29 @@
     }
 
     /**
+     * Add a Control to the form and return the added instance.
+     * <p/>
+     * Controls can be retrieved from the Map {@link #getControlMap() controlMap}
+     * where the key is the Control name and value is the Control instance.
+     * <p/>
+     * All controls are available on the {@link #getControls() controls} list
+     * in the order they were added. If you are only interested in Fields,
+     * note that Buttons are available on the {@link #getButtonList() buttonList}
+     * while other fields are available on {@link #getFieldList() fieldList}.
+     *
+     * @see Container#add(org.apache.click.Control)
+     *
+     * @param control the control to add to the container and return
+     * @return the control that was added to the container
+     * @throws IllegalArgumentException if the control is null, the Control name
+     * is not defined or the container already contains a control with the same
+     * name
+     */
+    public Control add(Control control) {
+        return super.add(control);
+    }
+
+    /**
      * Add the field to the form, and set the fields form property.
      * <p/>
      * Fields can be retrieved from the Map {@link #getFields() fields} where

Modified: incubator/click/trunk/click/framework/src/org/apache/click/util/ContainerUtils.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/framework/src/org/apache/click/util/ContainerUtils.java?rev=749759&r1=749758&r2=749759&view=diff
==============================================================================
--- incubator/click/trunk/click/framework/src/org/apache/click/util/ContainerUtils.java (original)
+++ incubator/click/trunk/click/framework/src/org/apache/click/util/ContainerUtils.java Tue
Mar  3 21:22:37 2009
@@ -45,184 +45,6 @@
 public class ContainerUtils {
 
     /**
-     * Return the list of Buttons for the given Container, recursively including
-     * any Fields contained in child containers.
-     *
-     * @param container the container to obtain the buttons from
-     * @return the list of contained buttons
-     */
-    public static List getButtons(final Container container) {
-        if (container == null) {
-            throw new IllegalArgumentException("Null container parameter");
-        }
-
-        final List buttons = new ArrayList();
-        addButtons(container, buttons);
-        return buttons;
-    }
-
-    /**
-     * Return the list of Fields for the given Container, recursively including
-     * any Fields contained in child containers.
-     *
-     * @param container the container to obtain the fields from
-     * @return the list of contained fields
-     */
-    public static List getFields(final Container container) {
-        if (container == null) {
-            throw new IllegalArgumentException("Null container parameter");
-        }
-
-        final List fields = new ArrayList();
-        addFields(container, fields);
-        return fields;
-    }
-
-    /**
-     * Return the list of input Fields (TextField, Select, Radio, Checkbox etc).
-     * for the given Container, recursively including any Fields contained in
-     * child containers. The list of returned fields will exclude any
-     * <tt>Button</tt>, <tt>FieldSet</tt> and <tt>Label</tt>
fields.
-     *
-     * @param container the container to obtain the fields from
-     * @return the list of contained fields
-     */
-    public static List getInputFields(final Container container) {
-        if (container == null) {
-            throw new IllegalArgumentException("Null container parameter");
-        }
-
-        final List fields = new ArrayList();
-        addInputFields(container, fields);
-        return fields;
-    }
-
-    /**
-     * Return the list of Fields for the given Container, recursively including
-     * any Fields contained in child containers. The list of returned fields
-     * will exclude any <tt>Button</tt> and <tt>FieldSet</tt> fields.
-     *
-     * @param container the container to obtain the fields from
-     * @return the list of contained fields
-     */
-    public static List getFieldsAndLabels(final Container container) {
-        if (container == null) {
-            throw new IllegalArgumentException("Null container parameter");
-        }
-
-        final List fields = new ArrayList();
-        addFieldsAndLabels(container, fields);
-        return fields;
-    }
-
-    /**
-     * Return a map of all Fields for the given Container, recursively including
-     * any Fields contained in child containers.
-     * <p/>
-     * The map's key / value pair will consist of the control name and instance.
-     *
-     * @param container the container to obtain the fields from
-     * @return the map of contained fields
-     */
-    public static Map getFieldMap(final Container container) {
-        if (container == null) {
-            throw new IllegalArgumentException("Null container parameter");
-        }
-
-        final Map fields = new HashMap();
-        addFields(container, fields);
-        return fields;
-    }
-
-    /**
-     * Return the list of hidden Fields for the given Container, recursively including
-     * any Fields contained in child containers. The list of returned fields
-     * will exclude any <tt>Button</tt>, <tt>FieldSet</tt> and <tt>Label</tt>
-     * fields.
-     *
-     * @param container the container to obtain the fields from
-     * @return the list of contained fields
-     */
-    public static List getHiddenFields(final Container container) {
-        if (container == null) {
-            throw new IllegalArgumentException("Null container parameter");
-        }
-
-        final List fields = new ArrayList();
-        addHiddenFields(container, fields);
-        return fields;
-    }
-
-    /**
-     * Return a list of container fields which are not valid, not hidden and not
-     * disabled.
-     * <p/>
-     * The list of returned fields will exclude any <tt>Button</tt> fields.
-     *
-     * @param container the container to obtain the invalid fields from
-     * @return list of container fields which are not valid, not hidden and not
-     * disabled
-     */
-    public static List getErrorFields(final Container container) {
-        if (container == null) {
-            throw new IllegalArgumentException("Null container parameter");
-        }
-
-        final List fields = new ArrayList();
-        addErrorFields(container, fields);
-        return fields;
-    }
-
-    /**
-     * Find and return the specified controls parent Form or null
-     * if no Form is present.
-     *
-     * @param control the control to check for Form
-     * @return the controls parent Form or null if no parent is a Form
-     */
-    public static Form findForm(Control control) {
-        while (control.getParent() != null && !(control.getParent() instanceof Page))
{
-            control = (Control) control.getParent();
-            if (control instanceof Form) {
-                return (Form) control;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Find and return the first control with a matching name in the specified
-     * container.
-     *
-     * @param container the container that is checked for controls for matching
-     * names
-     * @param name the name of the control to find
-     * @return the control with a matching name
-     */
-    public static Control findControlByName(Container container, String name) {
-        Control control = (Control) container.getControl(name);
-
-        if (control != null) {
-            return control;
-
-        } else {
-            for (int i = 0; i < container.getControls().size(); i++) {
-                Control childControl = (Control) container.getControls().get(i);
-
-                if (childControl instanceof Container) {
-                    Container childContainer = (Container) childControl;
-                    Control found = findControlByName(childContainer, name);
-                    if (found != null) {
-                        return found;
-                    }
-                }
-
-            }
-        }
-        return null;
-    }
-
-    /**
      * Populate the given object attributes from the Containers field values.
      * <p/>
      * If a Field and object attribute matches, the object attribute is set to
@@ -472,19 +294,341 @@
     }
 
     /**
-     * Return how deep the control is in the container hierarchy.
+     * Find and return the first control with a matching name in the specified
+     * container.
      *
-     * @param control the control which depth to return
-     * @return the depth of the control in the container hierarchy
+     * @param container the container that is checked for controls for matching
+     * names
+     * @param name the name of the control to find
+     * @return the control with a matching name
      */
-    protected int getDepth(Control control) {
-        int depth = 1;
+    public static Control findControlByName(Container container, String name) {
+        Control control = (Control) container.getControl(name);
+
+        if (control != null) {
+            return control;
+
+        } else {
+            for (int i = 0; i < container.getControls().size(); i++) {
+                Control childControl = (Control) container.getControls().get(i);
+
+                if (childControl instanceof Container) {
+                    Container childContainer = (Container) childControl;
+                    Control found = findControlByName(childContainer, name);
+                    if (found != null) {
+                        return found;
+                    }
+                }
 
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Find and return the specified controls parent Form or null
+     * if no Form is present.
+     *
+     * @param control the control to check for Form
+     * @return the controls parent Form or null if no parent is a Form
+     */
+    public static Form findForm(Control control) {
         while (control.getParent() != null && !(control.getParent() instanceof Page))
{
             control = (Control) control.getParent();
-            depth++;
+            if (control instanceof Form) {
+                return (Form) control;
+            }
         }
-        return depth;
+        return null;
+    }
+
+    /**
+     * Return the list of Buttons for the given Container, recursively including
+     * any Fields contained in child containers.
+     *
+     * @param container the container to obtain the buttons from
+     * @return the list of contained buttons
+     */
+    public static List getButtons(final Container container) {
+        if (container == null) {
+            throw new IllegalArgumentException("Null container parameter");
+        }
+
+        final List buttons = new ArrayList();
+        addButtons(container, buttons);
+        return buttons;
+    }
+
+    /**
+     * Return a list of container fields which are not valid, not hidden and not
+     * disabled.
+     * <p/>
+     * The list of returned fields will exclude any <tt>Button</tt> fields.
+     *
+     * @param container the container to obtain the invalid fields from
+     * @return list of container fields which are not valid, not hidden and not
+     * disabled
+     */
+    public static List getErrorFields(final Container container) {
+        if (container == null) {
+            throw new IllegalArgumentException("Null container parameter");
+        }
+
+        final List fields = new ArrayList();
+        addErrorFields(container, fields);
+        return fields;
+    }
+
+    /**
+     * Return a map of all Fields for the given Container, recursively including
+     * any Fields contained in child containers.
+     * <p/>
+     * The map's key / value pair will consist of the control name and instance.
+     *
+     * @param container the container to obtain the fields from
+     * @return the map of contained fields
+     */
+    public static Map getFieldMap(final Container container) {
+        if (container == null) {
+            throw new IllegalArgumentException("Null container parameter");
+        }
+
+        final Map fields = new HashMap();
+        addFields(container, fields);
+        return fields;
+    }
+
+    /**
+     * Return the list of Fields for the given Container, recursively including
+     * any Fields contained in child containers.
+     *
+     * @param container the container to obtain the fields from
+     * @return the list of contained fields
+     */
+    public static List getFields(final Container container) {
+        if (container == null) {
+            throw new IllegalArgumentException("Null container parameter");
+        }
+
+        final List fields = new ArrayList();
+        addFields(container, fields);
+        return fields;
+    }
+
+    /**
+     * Return the list of Fields for the given Container, recursively including
+     * any Fields contained in child containers. The list of returned fields
+     * will exclude any <tt>Button</tt> and <tt>FieldSet</tt> fields.
+     *
+     * @param container the container to obtain the fields from
+     * @return the list of contained fields
+     */
+    public static List getFieldsAndLabels(final Container container) {
+        if (container == null) {
+            throw new IllegalArgumentException("Null container parameter");
+        }
+
+        final List fields = new ArrayList();
+        addFieldsAndLabels(container, fields);
+        return fields;
+    }
+
+    /**
+     * Return the list of hidden Fields for the given Container, recursively including
+     * any Fields contained in child containers. The list of returned fields
+     * will exclude any <tt>Button</tt>, <tt>FieldSet</tt> and <tt>Label</tt>
+     * fields.
+     *
+     * @param container the container to obtain the fields from
+     * @return the list of contained fields
+     */
+    public static List getHiddenFields(final Container container) {
+        if (container == null) {
+            throw new IllegalArgumentException("Null container parameter");
+        }
+
+        final List fields = new ArrayList();
+        addHiddenFields(container, fields);
+        return fields;
+    }
+
+    /**
+     * Return the list of input Fields (TextField, Select, Radio, Checkbox etc).
+     * for the given Container, recursively including any Fields contained in
+     * child containers. The list of returned fields will exclude any
+     * <tt>Button</tt>, <tt>FieldSet</tt> and <tt>Label</tt>
fields.
+     *
+     * @param container the container to obtain the fields from
+     * @return the list of contained fields
+     */
+    public static List getInputFields(final Container container) {
+        if (container == null) {
+            throw new IllegalArgumentException("Null container parameter");
+        }
+
+        final List fields = new ArrayList();
+        addInputFields(container, fields);
+        return fields;
+    }
+
+    /**
+     * Add the given control to the container at the specified index, and return
+     * the added instance.
+     * <p/>
+     * <b>Please note</b> if the specified control already has a parent assigned,
+     * it will automatically be removed from that parent and inserted into the
+     * container.
+     * <p/>
+     * This method is useful for developers needing to implement the
+     * {@link org.apache.click.control.Container} interface but cannot for one
+     * reason or another extend from {@link org.apache.click.control.AbstractContainer}.
+     * For example if the Container already extends from an existing <tt>Control</tt>
+     * such as a <tt>Field</tt>, it won't be possible to extend
+     * <tt>AbstractContainer</tt> as well. In such scenarios instead of
+     * reimplementing {@link org.apache.click.control.Container#insert(org.apache.click.Control,
int) insert},
+     * one can delegate to this method.
+     * <p/>
+     * For example, a custom Container that extends <tt>Field</tt> and
+     * implements <tt>Container</tt> could implement the <tt>insert</tt>
method
+     * as follows:
+     * <pre class="prettyprint">
+     * public class MyContainer extends Field implements Container {
+     *
+     *     public Control insert(Control control, int index) {
+     *         return ContainerUtils.insert(this, control, index, getControlMap());
+     *     }
+     *
+     *     ...
+     * }
+     * </pre>
+     *
+     * @param container the container to insert the given control into
+     * @param control the control to add to the container
+     * @param index the index at which the control is to be inserted
+     * @param controlMap the container's map of controls keyed on control name
+     * @return the control that was added to the container
+     *
+     * @throws IllegalArgumentException if the control is null or if the control
+     * and container is the same instance or the container already contains
+     * a control with the same name or if a Field name is not defined
+     *
+     * @throws IndexOutOfBoundsException if index is out of range
+     * <tt>(index &lt; 0 || index &gt; container.getControls().size())</tt>
+     */
+    public static Control insert(Container container, Control control, int index,
+        Map controlMap) {
+
+        // Pre conditions start
+        if (control == null) {
+            throw new IllegalArgumentException("Null control parameter");
+        }
+        if (control == container) {
+            throw new IllegalArgumentException("Cannot add container to itself");
+        }
+        int size = container.getControls().size();
+        if (index > size || index < 0) {
+            throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
+                + size);
+        }
+        // Check if container already contains the control
+        if (controlMap.containsKey(control.getName())
+            && !(control instanceof Label)) {
+
+            throw new IllegalArgumentException(
+                "Container already contains control named: " + control.getName());
+        }
+
+        // Pre conditions end
+
+        // Check if control already has parent
+        // If parent references the given container, there is no need to remove it
+        Object currentParent = control.getParent();
+        if (currentParent != null && currentParent != container) {
+
+            // Remove control from parent Page or Container
+            if (currentParent instanceof Page) {
+                ((Page) currentParent).removeControl(control);
+
+            } else if (currentParent instanceof Container) {
+                ((Container) currentParent).remove(control);
+            }
+
+            // Create warning message to users that the parent has been reset
+            logParentReset(container, control, currentParent);
+        }
+
+        // Note: set parent first since setParent might veto further processing
+        control.setParent(container);
+        container.getControls().add(index, control);
+
+        String controlName = control.getName();
+        if (controlName != null) {
+            controlMap.put(controlName, control);
+        }
+        return control;
+    }
+
+    /**
+     * Remove the given control from the container, returning <tt>true</tt> if
+     * the control was found in the container and removed, or <tt>false</tt>
if
+     * the control was not found.
+     * <p/>
+     * This method is useful for developers needing to implement the
+     * {@link org.apache.click.control.Container} interface but cannot for one
+     * reason or another extend from {@link org.apache.click.control.AbstractContainer}.
+     * For example if the Container already extends from an existing <tt>Control</tt>
+     * such as a <tt>Field</tt>, it won't be possible to extend
+     * <tt>AbstractContainer</tt> as well. In such scenarios instead of
+     * reimplementing {@link org.apache.click.control.Container#remove(org.apache.click.Control)
remove},
+     * one can delegate to this method.
+     * <p/>
+     * For example, a custom Container that extends <tt>Field</tt> and
+     * implements <tt>Container</tt> could implement the <tt>remove</tt>
method
+     * as follows:
+     * <pre class="prettyprint">
+     * public class MyContainer extends Field implements Container {
+     *
+     *     public boolean remove (Control control) {
+     *         return ContainerUtils.remove(this, control, getControlMap());
+     *     }
+     *
+     *     ...
+     * }
+     * </pre>
+     *
+     * @param container the container to remove the given control from
+     * @param control the control to remove from the container
+     * @param controlMap the container's map of controls keyed on control name
+     *
+     * @return true if the control was removed from the container
+     * @throws IllegalArgumentException if the control is null
+     */
+    public static boolean remove(Container container, Control control,
+        Map controlMap) {
+
+        if (control == null) {
+            throw new IllegalArgumentException("Control cannot be null");
+        }
+
+        boolean contains = container.getControls().remove(control);
+
+        if (contains) {
+            // Only nullify if the container is parent. This check is for the
+            // case where a Control has two parents e.g. Page and Form.
+            // NOTE the current #insert logic does not allow Controls to have
+            // two parents so this check might be redundant.
+            if (control.getParent() == container) {
+                control.setParent(null);
+            }
+
+            String controlName = control.getName();
+
+            if (controlName != null) {
+                controlMap.remove(controlName);
+            }
+        }
+
+        return contains;
     }
 
     // -------------------------------------------------------- Private Methods
@@ -1052,4 +1196,62 @@
             }
         }
     }
+
+    /**
+     * Log a warning that the parent of the given control will be set to
+     * the specified container.
+     *
+     * @param container the parent container
+     * @param control the control which parent is being reset
+     * @param currentParent the control current parent
+     */
+    private static void logParentReset(Container container, Control control,
+        Object currentParent) {
+        HtmlStringBuffer message = new HtmlStringBuffer();
+
+        message.append("Changed ");
+        message.append(ClassUtils.getShortClassName(control.getClass()));
+        String controlId = control.getId();
+        if (controlId != null) {
+            message.append("[");
+            message.append(controlId);
+            message.append("]");
+        } else {
+            message.append("#");
+            message.append(control.hashCode());
+        }
+        message.append(" parent from ");
+
+        if (currentParent instanceof Page) {
+            message.append(ClassUtils.getShortClassName(currentParent.getClass()));
+
+        } else if (currentParent instanceof Container) {
+            Container parentContainer = (Container) currentParent;
+
+            message.append(ClassUtils.getShortClassName(parentContainer.getClass()));
+            String parentId = parentContainer.getId();
+            if (parentId != null) {
+                message.append("[");
+                message.append(parentId);
+                message.append("]");
+            } else {
+                message.append("#");
+                message.append(parentContainer.hashCode());
+            }
+        }
+
+        message.append(" to ");
+        message.append(ClassUtils.getShortClassName(container.getClass()));
+        String id = container.getId();
+        if (id != null) {
+            message.append("[");
+            message.append(id);
+            message.append("]");
+        } else {
+            message.append("#");
+            message.append(container.hashCode());
+        }
+
+        ClickUtils.getLogService().warn(message);
+    }
 }



Mime
View raw message