Author: andyhot
Date: Fri Mar 16 22:21:13 2007
New Revision: 519241
URL: http://svn.apache.org/viewvc?view=rev&rev=519241
Log:
TAPESTRY-410:Match-differ validator (server and client side)
Added:
tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/form/validator/Identity.java
tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/form/validator/TestIdentity.java
Modified:
tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.form.validator.xml
Modified:
tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.form.validator.xml
URL:
http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.form.validator.xml?view=diff&rev=519241&r1=519240&r2=519241
==============================================================================
---
tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.form.validator.xml
(original)
+++
tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.form.validator.xml
Fri Mar 16 22:21:13 2007
@@ -49,7 +49,9 @@
<validator name="min" class="Min"/>
<validator name="minDate" class="MinDate"/>
<validator name="minLength" class="MinLength"/>
- <validator name="pattern" class="Pattern"/>
+ <validator name="pattern" class="Pattern"/>
+ <validator name="match" configurable="true" class="Identity"/>
+ <validator name="differ" configurable="true" class="Identity"/>
</contribution>
<service-point id="ValidatorFactory">
Added:
tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/form/validator/Identity.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/form/validator/Identity.java?view=auto&rev=519241
==============================================================================
---
tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/form/validator/Identity.java
(added)
+++
tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/form/validator/Identity.java
Fri Mar 16 22:21:13 2007
@@ -0,0 +1,157 @@
+// Copyright 2007 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.tapestry.form.validator;
+
+import org.apache.tapestry.IMarkupWriter;
+import org.apache.tapestry.IRequestCycle;
+import org.apache.tapestry.form.FormComponentContributorContext;
+import org.apache.tapestry.form.IFormComponent;
+import org.apache.tapestry.form.ValidationMessages;
+import org.apache.tapestry.json.JSONLiteral;
+import org.apache.tapestry.json.JSONObject;
+import org.apache.tapestry.valid.ValidationConstants;
+import org.apache.tapestry.valid.ValidatorException;
+import org.apache.tapestry.valid.ValidationConstraint;
+
+/**
+ * Validates that the input value is the same as the value of another field.
+ * This validator can also work in 'differ' mode.
+ * <p/>
+ * Apply this validator to the second field in question and define the name
+ * of the component against which to compare the current value.
+ *
+ * @since 4.1.2
+ */
+public class Identity extends BaseValidator {
+ private String _fieldName;
+ private int _matchType;
+ private String _identityMessage;
+
+ private static final int DIFFER = 0;
+ private static final int MATCH = 1;
+
+
+ public Identity() {
+ super();
+ }
+
+
+ public Identity(String initializer) {
+ super(initializer);
+ }
+
+ public String toString(IFormComponent field, Object value) {
+ if (value == null)
+ return null;
+
+ return value.toString();
+ }
+
+ public void validate(IFormComponent field, ValidationMessages messages,
Object object)
+ throws ValidatorException {
+ IFormComponent referent = (IFormComponent)
field.getContainer().getComponent(_fieldName);
+ Object referentValue = referent.getBinding("value").getObject();
+
+ //TODO: if component is null treat _fieldName as an ognl expression
+ boolean notEq = notEqual(referentValue, object);
+
+ if (_matchType == MATCH ? notEq : !notEq)
+ throw new ValidatorException(buildIdentityMessage(messages, field,
referent),
+ ValidationConstraint.CONSISTENCY);
+ }
+
+ public void renderContribution(IMarkupWriter writer, IRequestCycle cycle,
+ FormComponentContributorContext context, IFormComponent field)
+ {
+ if(field.isDisabled())
+ return;
+
+ IFormComponent referent = (IFormComponent)
field.getContainer().getComponent(_fieldName);
+
+ JSONObject profile = context.getProfile();
+
+ if (!profile.has(ValidationConstants.CONSTRAINTS)) {
+ profile.put(ValidationConstants.CONSTRAINTS, new JSONObject());
+ }
+ JSONObject cons =
profile.getJSONObject(ValidationConstants.CONSTRAINTS);
+
+ String func = (_matchType == MATCH) ?
+ "tapestry.form.validation.isEqual" :
+ "tapestry.form.validation.isNotEqual";
+
+ accumulateProperty(cons, field.getClientId(),
+ new JSONLiteral("[" + func + ",\""
+ + referent.getClientId() + "\"]"));
+
+ accumulateProfileProperty(field, profile,
+ ValidationConstants.CONSTRAINTS, buildIdentityMessage(context,
field, referent));
+ }
+
+ public String getMatch() {
+ return _fieldName;
+ }
+
+ public void setMatch(String field) {
+ _fieldName = field;
+ _matchType = MATCH;
+
+ }
+
+ public String getDiffer() {
+ return _fieldName;
+ }
+
+ public void setDiffer(String field) {
+ _fieldName = field;
+ _matchType = DIFFER;
+ }
+
+
+ /** @since 3.0 */
+ public String getIdentityMessage() {
+ return _identityMessage;
+ }
+
+ /**
+ * Overrides the <code>field-too-short</code> bundle key. Parameter {0} is
the minimum length.
+ * Parameter {1} is the display name of the field.
+ *
+ * @since 3.0
+ */
+
+ public void setIdentityMessage(String string) {
+ _identityMessage = string;
+ }
+
+ /** @since 3.0 */
+
+ protected String buildIdentityMessage(ValidationMessages messages,
IFormComponent field, IFormComponent referent) {
+ Object[] parameters = new Object[]{
+ field.getDisplayName(), new Integer(_matchType),
referent.getDisplayName()
+ };
+ return messages.formatValidationMessage(_identityMessage,
+ "invalid-field-equality", parameters);
+
+ }
+
+ private boolean notEqual(Object o1, Object o2) {
+ if (o1 == null && o2 == null)
+ return false;
+ if (o1 == null || o2 == null)
+ return true;
+ return !o1.equals(o2);
+ }
+
+}
\ No newline at end of file
Added:
tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/form/validator/TestIdentity.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/form/validator/TestIdentity.java?view=auto&rev=519241
==============================================================================
---
tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/form/validator/TestIdentity.java
(added)
+++
tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/form/validator/TestIdentity.java
Fri Mar 16 22:21:13 2007
@@ -0,0 +1,167 @@
+// Copyright 2007 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.tapestry.form.validator;
+
+import java.util.Locale;
+import org.apache.tapestry.IBinding;
+import org.apache.tapestry.IComponent;
+import org.apache.tapestry.form.ValidationMessagesImpl;
+import org.easymock.EasyMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.aryEq;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.isNull;
+import static org.easymock.EasyMock.checkOrder;
+
+import org.apache.tapestry.IMarkupWriter;
+import org.apache.tapestry.IRequestCycle;
+import org.apache.tapestry.form.FormComponentContributorContext;
+import org.apache.tapestry.form.IFormComponent;
+import org.apache.tapestry.form.ValidationMessages;
+import org.apache.tapestry.json.JSONObject;
+import org.apache.tapestry.valid.ValidationConstraint;
+import org.apache.tapestry.valid.ValidationStrings;
+import org.apache.tapestry.valid.ValidatorException;
+import org.testng.annotations.Test;
+
+/**
+ * Tests for [EMAIL PROTECTED] org.apache.tapestry.form.validator.Identity}.
+ *
+ * @since 4.1.2
+ */
[EMAIL PROTECTED]
+public class TestIdentity extends BaseValidatorTestCase
+{
+ public void testOK() throws Exception
+ {
+ IFormComponent field = newField();
+ IFormComponent otherField = newField();
+
+ trainGetContainerAndComponent(field, "newPass", otherField);
+ trainGetValueBinding(otherField, "pass");
+
+ ValidationMessages messages = newMessages();
+
+ replay();
+
+ new Identity("match=newPass").validate(field, messages, "pass");
+
+ verify();
+ }
+
+ public void testFail()
+ {
+ IFormComponent field = newField();
+ IFormComponent otherField = newField();
+
+ trainGetContainerAndComponent(field, "newPass", otherField);
+ trainGetValueBinding(otherField, "pass");
+ expect(field.getDisplayName()).andReturn("Password-1");
+ expect(otherField.getDisplayName()).andReturn("Password-2");
+
+ ValidationMessages messages = newMessages();
+ trainIdentityMessages(messages, "Password-1", "Password-2", 1,
"err1");
+
+ replay();
+
+ try
+ {
+ new Identity("match=newPass").validate(field, messages,
"passOTHER");
+ }
+ catch (ValidatorException ex)
+ {
+ assertEquals(ex.getMessage(), "err1");
+ assertEquals(ex.getConstraint(), ValidationConstraint.CONSISTENCY);
+ }
+ }
+
+ public void testFailCustomMessage()
+ {
+ IFormComponent field = newField();
+ IFormComponent otherField = newField();
+
+ trainGetContainerAndComponent(field, "newPass", otherField);
+ trainGetValueBinding(otherField, "pass");
+ expect(field.getDisplayName()).andReturn("Password-1");
+ expect(otherField.getDisplayName()).andReturn("Password-2");
+
+ ValidationMessages messages = newMessages();
+ trainIdentityMessages(messages, "Password-1", "Password-2", 0,
"error");
+
+ replay();
+
+ try
+ {
+ new Identity("differ=newPass,message=Should
differ!").validate(field, messages, "pass");
+ }
+ catch (ValidatorException ex)
+ {
+ assertEquals(ex.getMessage(), "error");
+ assertEquals(ex.getConstraint(), ValidationConstraint.CONSISTENCY);
+ }
+ }
+
+ public void test_Render_Contribution()
+ {
+ JSONObject json = new JSONObject();
+
+ IFormComponent field = newField(/*);//*/"Password", "pass1");
+ expect(field.isDisabled()).andReturn(false);
+
+ IFormComponent otherField = newField(/*);//*/"Verify Password",
"pass2");
+ trainGetContainerAndComponent(field, "other", otherField);
+
+ FormComponentContributorContext context =
newMock(FormComponentContributorContext.class);
+ expect(context.getProfile()).andReturn(json);
+
+ trainIdentityMessages(context, "Password", "Verify Password", 1,
"Fields must match");
+
+ IMarkupWriter writer = newWriter();
+ IRequestCycle cycle = newCycle();
+
+ replay();
+
+ new Identity("match=other").renderContribution(writer, cycle, context,
field);
+
+ verify();
+
+
assertEquals("{\"constraints\":{\"pass1\":[[tapestry.form.validation.isEqual,\"pass2\"]]},"
+ + "\"pass1\":{\"constraints\":[\"Fields must match\"]}}",
+ json.toString());
+ }
+
+ public void testNotRequired()
+ {
+ assertEquals(false, new Identity().isRequired());
+ }
+
+ private void trainGetContainerAndComponent(IFormComponent field, String
name, IFormComponent other) {
+ IComponent container = newComponent();
+ expect(field.getContainer()).andReturn(container);
+ expect(container.getComponent(name)).andReturn(other);
+ }
+
+ private void trainGetValueBinding(IFormComponent field, String value) {
+ IBinding ret = newBinding(value);
+ expect(field.getBinding("value")).andReturn(ret);
+ }
+
+ private void trainIdentityMessages(ValidationMessages messages, String
name1, String name2, int match, String result)
+ {
+ trainFormatMessage(messages, null, "invalid-field-equality",
+ new Object[]{ name1, new Integer(match), name2 },
+ result);
+ }
+}