Author: ivaynberg
Date: Thu Jun 28 11:59:08 2007
New Revision: 551658

URL: http://svn.apache.org/viewvc?view=rev&rev=551658
Log:
WICKET-709: ability to remove form validators as well as not validate 
formvalidators if they depend on components that are no longer on the page

Modified:
    
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Component.java
    
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/form/Form.java

Modified: 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Component.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Component.java?view=diff&rev=551658&r1=551657&r2=551658
==============================================================================
--- 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Component.java
 (original)
+++ 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Component.java
 Thu Jun 28 11:59:08 2007
@@ -1413,7 +1413,8 @@
                RequestCycle requestCycle = getRequestCycle();
                if (requestCycle == null)
                {
-                       // Happens often with WicketTester when one forgets to 
call createRequestCycle()
+                       // Happens often with WicketTester when one forgets to 
call
+                       // createRequestCycle()
                        throw new WicketRuntimeException("No RequestCycle is 
currently set!");
                }
                return requestCycle.getRequest();
@@ -3152,7 +3153,14 @@
                return this.getFlag(FLAG_IGNORE_ATTRIBUTE_MODIFIER);
        }
 
-       protected final boolean isRenderAllowed()
+       /**
+        * Checks the security strategy if the [EMAIL PROTECTED] 
Component#RENDER} action is
+        * allowed on this component
+        * 
+        * @return ture if [EMAIL PROTECTED] Component#RENDER} action is 
allowed, false
+        *         otherwise
+        */
+       public final boolean isRenderAllowed()
        {
                return getFlag(FLAG_IS_RENDER_ALLOWED);
        }

Modified: 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/form/Form.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/form/Form.java?view=diff&rev=551658&r1=551657&r2=551658
==============================================================================
--- 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/form/Form.java
 (original)
+++ 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/form/Form.java
 Thu Jun 28 11:59:08 2007
@@ -52,6 +52,7 @@
 import org.apache.wicket.util.upload.FileUploadBase.SizeLimitExceededException;
 import org.apache.wicket.util.value.ValueMap;
 import org.apache.wicket.validation.IValidatorAddListener;
+import org.apache.wicket.version.undo.Change;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -349,7 +350,7 @@
        {
                if (validator == null)
                {
-                       throw new IllegalArgumentException("validator argument 
cannot be null");
+                       throw new IllegalArgumentException("Argument 
`validator` cannot be null");
                }
 
                // add the validator
@@ -363,6 +364,112 @@
        }
 
        /**
+        * Removes a form validator from the form.
+        * 
+        * @param validator
+        *            validator
+        * @throws IllegalArgumentException
+        *             if validator is null
+        * @see IFormValidator
+        */
+       public void remove(IFormValidator validator)
+       {
+               if (validator == null)
+               {
+                       throw new IllegalArgumentException("Argument 
`validator` cannot be null");
+               }
+
+               IFormValidator removed = formValidators_remove(validator);
+               if (removed == null)
+               {
+                       throw new IllegalStateException(
+                                       "Tried to remove form validator that 
was not previously added. "
+                                                       + "Make sure your 
validator's equals() implementation is sufficient");
+               }
+               addStateChange(new FormValidatorRemovedChange(removed));
+       }
+
+       private final int formValidators_indexOf(IFormValidator validator)
+       {
+               if (formValidators != null)
+               {
+                       if (formValidators instanceof IFormValidator)
+                       {
+                               final IFormValidator v = 
(IFormValidator)formValidators;
+                               if (v == validator || v.equals(validator))
+                               {
+                                       return 0;
+                               }
+                       }
+                       else
+                       {
+                               final IFormValidator[] validators = 
(IFormValidator[])formValidators;
+                               for (int i = 0; i < validators.length; i++)
+                               {
+                                       final IFormValidator v = validators[i];
+                                       if (v == validator || 
v.equals(validator))
+                                       {
+                                               return i;
+                                       }
+                               }
+                       }
+               }
+               return -1;
+       }
+
+       private final IFormValidator formValidators_remove(IFormValidator 
validator)
+       {
+               int index = formValidators_indexOf(validator);
+               if (index != -1)
+               {
+                       return formValidators_remove(index);
+               }
+               return null;
+       }
+
+       private final IFormValidator formValidators_remove(int index)
+       {
+               if (formValidators instanceof IFormValidator)
+               {
+                       if (index == 0)
+                       {
+                               final IFormValidator removed = 
(IFormValidator)formValidators;
+                               formValidators = null;
+                               return removed;
+                       }
+                       else
+                       {
+                               throw new IndexOutOfBoundsException();
+                       }
+               }
+               else
+               {
+                       final IFormValidator[] validators = 
(IFormValidator[])formValidators;
+                       final IFormValidator removed = validators[index];
+                       // check if we can collapse array of 1 element into a 
single object
+                       if (validators.length == 2)
+                       {
+                               formValidators = validators[1 - index];
+                       }
+                       else
+                       {
+                               IFormValidator[] newValidators = new 
IFormValidator[validators.length - 1];
+                               int j = 0;
+                               for (int i = 0; i < validators.length; i++)
+                               {
+                                       if (i != index)
+                                       {
+                                               newValidators[j++] = 
validators[i];
+                                       }
+                               }
+                               this.formValidators = newValidators;
+                       }
+                       return removed;
+               }
+       }
+
+
+       /**
         * Clears the input from the form's nested children of type
         * [EMAIL PROTECTED] FormComponent}. This method is typically called 
when a form needs
         * to be reset.
@@ -1109,24 +1216,26 @@
        protected void appendDefaultButtonField(final MarkupStream markupStream,
                        final ComponentTag openTag)
        {
-               
+
                AppendingStringBuffer buffer = new AppendingStringBuffer();
-       
+
                // div that is not visible (but not display:none either)
-               buffer.append("<div 
style=\"width:0px;height:0px;position:absolute;left:-100px;top:-100px;overflow:hidden\"");
+               buffer
+                               .append("<div 
style=\"width:0px;height:0px;position:absolute;left:-100px;top:-100px;overflow:hidden\"");
 
                // add an empty textfield (otherwise IE doesn't work)
                buffer.append("<input type=\"text\" autocomplete=\"false\"/>");
-               
+
                // add the button
                buffer.append("<input type=\"submit\" onclick=\" var 
b=Wicket.$('");
                buffer.append(defaultButton.getMarkupId());
-               buffer.append("'); if (typeof(b.onclick) != 'undefined') {  var 
r = b.onclick.bind(this)(); if (r != false) b.click(); } else { b.click(); };  
return false;\" ");
+               buffer
+                               .append("'); if (typeof(b.onclick) != 
'undefined') {  var r = b.onclick.bind(this)(); if (r != false) b.click(); } 
else { b.click(); };  return false;\" ");
                buffer.append(" />");
-               
+
                // close div
                buffer.append("</div>");
-               
+
                getResponse().write(buffer);
        }
 
@@ -1540,6 +1649,39 @@
        }
 
        /**
+        * Checks if the specified form component visible and is attached to a 
page
+        * 
+        * @param fc
+        *            form component
+        * 
+        * @return true if the form component and all its parents are visible 
and
+        *         there component is in page's hierarchy
+        */
+       private boolean isFormComponentVisibleInPage(FormComponent fc)
+       {
+               if (fc == null)
+               {
+                       throw new IllegalArgumentException("Argument `fc` 
cannot be null");
+               }
+               Component c = fc;
+               Component last = fc;
+               while (c != null)
+               {
+                       if (c.isRenderAllowed() && c.isVisible())
+                       {
+                               last = c;
+                               c = c.getParent();
+                       }
+                       else
+                       {
+                               return false;
+                       }
+               }
+               return last == this;
+       }
+
+
+       /**
         * Validates form with the given form validator
         * 
         * @param validator
@@ -1560,11 +1702,27 @@
                        for (int j = 0; j < dependents.length; j++)
                        {
                                final FormComponent dependent = dependents[j];
+                               // check if the dependent component is valid
                                if (!dependent.isValid())
                                {
                                        validate = false;
                                        break;
                                }
+                               // check if the dependent componet is visible 
and is attached to
+                               // the page
+                               else if 
(!isFormComponentVisibleInPage(dependent))
+                               {
+                                       if (log.isWarnEnabled())
+                                       {
+                                               log
+                                                               
.warn("IFormValidator in form `"
+                                                                               
+ getPageRelativePath()
+                                                                               
+ "` depends on a component that has been removed from the page or is no longer 
visible. "
+                                                                               
+ "Offending component id `" + dependent.getId() + "`.");
+                                       }
+                                       validate = false;
+                                       break;
+                               }
                        }
                }
 
@@ -1584,5 +1742,35 @@
                {
                        validateFormValidator(formValidators_get(i));
                }
+       }
+
+       /**
+        * Change object to keep track of form validator removals
+        * 
+        * @author Igor Vaynberg (ivaynberg at apache dot org)
+        */
+       private class FormValidatorRemovedChange extends Change
+       {
+               private static final long serialVersionUID = 1L;
+
+               private final IFormValidator removed;
+
+               /**
+                * Construct.
+                * 
+                * @param removed
+                */
+               public FormValidatorRemovedChange(final IFormValidator removed)
+               {
+                       super();
+                       this.removed = removed;
+               }
+
+
+               public void undo()
+               {
+                       add(removed);
+               }
+
        }
 }


Reply via email to