You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by an...@apache.org on 2007/03/17 06:21:14 UTC

svn commit: r519241 - in /tapestry/tapestry4/trunk/tapestry-framework/src: descriptor/META-INF/tapestry.form.validator.xml java/org/apache/tapestry/form/validator/Identity.java test/org/apache/tapestry/form/validator/TestIdentity.java

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 {@link org.apache.tapestry.form.validator.Identity}.
+ * 
+ * @since 4.1.2
+ */
+@Test
+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);
+    }    
+}



Re: svn commit: r519241 - in /tapestry/tapestry4/trunk/tapestry-framework/src: descriptor/META-INF/tapestry.form.validator.xml java/org/apache/tapestry/form/validator/Identity.java test/org/apache/tapestry/form/validator/TestIdentity.java

Posted by Andreas Andreou <an...@di.uoa.gr>.
:)
I think i spent too much time thinking about splitting those 2 cases and
using 'confirm'
myself... but i just went for the simpler implementation...

BTW, can't TAPESTRY-772 be implemented using 'dependancies' from
http://tapestry.apache.org/tapestry4.1/javascript/form.html ?
Or, do you have other plans for this?


On 3/17/07, Jesse Kuhnert <jk...@gmail.com> wrote:
>
> Oops nevermind...Hadn't read your previous comments about lack of
> support for differ.
>
>
>
>
> --
> Jesse Kuhnert
> Tapestry/Dojo team member/developer
>
> Open source based consulting work centered around
> dojo/tapestry/tacos/hivemind. http://blog.opencomponentry.com
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: dev-help@tapestry.apache.org
>
>


-- 
Andreas Andreou - andyhot@apache.org - http://andyhot.di.uoa.gr
Tapestry / Tacos developer
Open Source / JEE Consulting

Re: svn commit: r519241 - in /tapestry/tapestry4/trunk/tapestry-framework/src: descriptor/META-INF/tapestry.form.validator.xml java/org/apache/tapestry/form/validator/Identity.java test/org/apache/tapestry/form/validator/TestIdentity.java

Posted by Jesse Kuhnert <jk...@gmail.com>.
Oops nevermind...Hadn't read your previous comments about lack of
support for differ.

On 3/17/07, Jesse Kuhnert <jk...@gmail.com> wrote:
> Looks good!
>
> The only thing I noticed was that I think the client side isEqual is
> already handle-able via the "confirm" validation type (look towards
> bottom of page):
>
> http://tapestry.apache.org/tapestry4.1/javascript/form.html
>
> On 3/17/07, andyhot@apache.org <an...@apache.org> wrote:
> > 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 {@link org.apache.tapestry.form.validator.Identity}.
> > + *
> > + * @since 4.1.2
> > + */
> > +@Test
> > +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);
> > +    }
> > +}
> >
> >
> >
>
>
> --
> Jesse Kuhnert
> Tapestry/Dojo team member/developer
>
> Open source based consulting work centered around
> dojo/tapestry/tacos/hivemind. http://blog.opencomponentry.com
>


-- 
Jesse Kuhnert
Tapestry/Dojo team member/developer

Open source based consulting work centered around
dojo/tapestry/tacos/hivemind. http://blog.opencomponentry.com

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org


Re: svn commit: r519241 - in /tapestry/tapestry4/trunk/tapestry-framework/src: descriptor/META-INF/tapestry.form.validator.xml java/org/apache/tapestry/form/validator/Identity.java test/org/apache/tapestry/form/validator/TestIdentity.java

Posted by Jesse Kuhnert <jk...@gmail.com>.
Looks good!

The only thing I noticed was that I think the client side isEqual is
already handle-able via the "confirm" validation type (look towards
bottom of page):

http://tapestry.apache.org/tapestry4.1/javascript/form.html

On 3/17/07, andyhot@apache.org <an...@apache.org> wrote:
> 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 {@link org.apache.tapestry.form.validator.Identity}.
> + *
> + * @since 4.1.2
> + */
> +@Test
> +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);
> +    }
> +}
>
>
>


-- 
Jesse Kuhnert
Tapestry/Dojo team member/developer

Open source based consulting work centered around
dojo/tapestry/tacos/hivemind. http://blog.opencomponentry.com

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org