You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by iv...@apache.org on 2007/06/28 20:59:09 UTC

svn commit: r551658 - in /incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket: Component.java markup/html/form/Form.java

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 {@link Component#RENDER} action is
+	 * allowed on this component
+	 * 
+	 * @return ture if {@link 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
 	 * {@link 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);
+		}
+
 	}
 }