Commits

Anonymous committed ecd5a2d

o added tests for validation annotations

git-svn-id: http://svn.opensymphony.com/svn/xwork/trunk@617e221344d-f017-0410-9bd5-d282ab1896d7

  • Participants
  • Parent commits 51fc11b

Comments (0)

Files changed (16)

tiger/src/test/com/opensymphony/xwork/TestBean.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork;
+
+import com.opensymphony.xwork.validator.annotations.IntRangeFieldValidator;
+import com.opensymphony.xwork.validator.annotations.Validations;
+import com.opensymphony.xwork.validator.annotations.RequiredStringValidator;
+
+import java.util.Date;
+
+
+/**
+ * TestBean
+ * @author Jason Carreira
+ * Created Aug 4, 2003 12:39:53 AM
+ */
+public class TestBean {
+    //~ Instance fields ////////////////////////////////////////////////////////
+
+    private Date birth;
+    private String name;
+    private int count;
+
+    //~ Constructors ///////////////////////////////////////////////////////////
+
+    public TestBean() {
+    }
+
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public void setBirth(Date birth) {
+        this.birth = birth;
+    }
+
+    public Date getBirth() {
+        return birth;
+    }
+
+    /*
+    <field name="count">
+        <field-validator type="int" short-circuit="true">
+            <param name="min">1</param>
+            <param name="max">100</param>
+            <message key="invalid.count">Invalid Count!</message>
+        </field-validator>
+        <field-validator type="int">
+            <param name="min">20</param>
+            <param name="max">80</param>
+            <message key="invalid.count.bad">Smaller Invalid Count: ${count}</message>
+        </field-validator>
+    </field>
+    */
+    @Validations(
+            intRangeFields = {
+                @IntRangeFieldValidator(shortCircuit = true, min = "1", max="100", key="invalid.count", message = "Invalid Count!"),
+                @IntRangeFieldValidator(shortCircuit = true, min = "20", max="28", key="invalid.count.bad", message = "Smaller Invalid Count: ${count}")
+            }
+
+    )
+    public void setCount(int count) {
+        this.count = count;
+    }
+
+    public int getCount() {
+        return count;
+    }
+
+    /*
+    <field name="name">
+        <field-validator type="requiredstring">
+            <message>You must enter a name.</message>
+        </field-validator>
+    </field>
+    */
+    @RequiredStringValidator(message = "You must enter a name.")
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+}

tiger/src/test/com/opensymphony/xwork/TestBean.properties

+invalid.count=Count must be between ${min} and ${max}, current value is ${count}.

tiger/src/test/com/opensymphony/xwork/util/Bar.java

+/*
+ * Copyright (c) 2005 Your Corporation. All Rights Reserved.
+ */
+package com.opensymphony.xwork.util;
+
+import com.opensymphony.xwork.ActionSupport;
+
+
+/**
+ * @author <a href="mailto:plightbo@cisco.com">Pat Lightbody</a>
+ * @author $Author$
+ * @version $Revision$
+ */
+public class Bar extends ActionSupport {
+
+    Long id;
+    String title;
+    int somethingElse;
+
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getId() {
+        return this.id;
+    }
+
+    public void setSomethingElse(int somethingElse) {
+        this.somethingElse = somethingElse;
+    }
+
+    public int getSomethingElse() {
+        return somethingElse;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public String toString() {
+        return getTitle() + ":" + getSomethingElse();
+    }
+}

tiger/src/test/com/opensymphony/xwork/util/Foo.java

+/*
+ * Copyright (c) 2005 Your Corporation. All Rights Reserved.
+ */
+package com.opensymphony.xwork.util;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * @author <a href="mailto:plightbo@cisco.com">Pat Lightbody</a>
+ * @author $Author$
+ * @version $Revision$
+ */
+public class Foo {
+
+    Bar bar;
+    Date birthday;
+    Foo child;
+    List cats;
+    List moreCats;
+    List strings;
+    Set barSet;
+    Map catMap;
+    Map anotherCatMap;
+    String title;
+    long[] points;
+    Foo[] relatives;
+    boolean useful;
+    int number;
+    long aLong;
+
+
+    public void setALong(long aLong) {
+        this.aLong = aLong;
+    }
+
+    public long getALong() {
+        return aLong;
+    }
+
+    public void setBar(Bar bar) {
+        this.bar = bar;
+    }
+
+    public Bar getBar() {
+        return bar;
+    }
+
+    public void setBirthday(Date birthday) {
+        this.birthday = birthday;
+    }
+
+    public Date getBirthday() {
+        return birthday;
+    }
+
+    public void setCatMap(Map catMap) {
+        this.catMap = catMap;
+    }
+
+    public Map getCatMap() {
+        return catMap;
+    }
+
+    public void setCats(List cats) {
+        this.cats = cats;
+    }
+
+    public List getCats() {
+        return cats;
+    }
+
+    public void setChild(Foo child) {
+        this.child = child;
+    }
+
+    public Foo getChild() {
+        return child;
+    }
+
+    public void setNumber(int number) {
+        this.number = number;
+    }
+
+    public int getNumber() {
+        return number;
+    }
+
+    /**
+     * @return Returns the anotherCatMap.
+     */
+    public Map getAnotherCatMap() {
+        return anotherCatMap;
+    }
+
+    /**
+     * @param anotherCatMap The anotherCatMap to set.
+     */
+    public void setAnotherCatMap(Map anotherCatMap) {
+        this.anotherCatMap = anotherCatMap;
+    }
+
+    /**
+     * @return Returns the moreCats.
+     */
+    public List getMoreCats() {
+        return moreCats;
+    }
+
+    /**
+     * @param moreCats The moreCats to set.
+     */
+    public void setMoreCats(List moreCats) {
+        this.moreCats = moreCats;
+    }
+
+    /**
+     * @return Returns the catSet.
+     */
+    public Set getBarSet() {
+        return barSet;
+    }
+
+    /**
+     * @param catSet The catSet to set.
+     */
+    public void setBarSet(Set catSet) {
+        this.barSet = catSet;
+    }
+
+    public void setPoints(long[] points) {
+        this.points = points;
+    }
+
+    public long[] getPoints() {
+        return points;
+    }
+
+    public void setRelatives(Foo[] relatives) {
+        this.relatives = relatives;
+    }
+
+    public Foo[] getRelatives() {
+        return relatives;
+    }
+
+    public void setStrings(List strings) {
+        this.strings = strings;
+    }
+
+    public List getStrings() {
+        return strings;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setUseful(boolean useful) {
+        this.useful = useful;
+    }
+
+    public boolean isUseful() {
+        return useful;
+    }
+}

tiger/src/test/com/opensymphony/xwork/validator/AnnotationActionValidatorManagerTest.java

+/*
+ * Copyright (c) 2005 Your Corporation. All Rights Reserved.
+ */
+package com.opensymphony.xwork.validator;
+
+import com.opensymphony.xwork.TestBean;
+import com.opensymphony.xwork.XWorkTestCase;
+import com.opensymphony.xwork.validator.validators.*;
+
+import java.util.List;
+
+
+/**
+ * AnnotationActionValidatorManagerTest
+ *
+ * @author Rainer Hermanns
+ * @author Jason Carreira
+ * @author tm_jee ( tm_jee (at) yahoo.co.uk )
+ *         Created Jun 9, 2003 11:03:01 AM
+ */
+public class AnnotationActionValidatorManagerTest extends XWorkTestCase {
+
+    protected final String alias = "validationAlias";
+
+
+    public void testBuildValidatorKey() {
+        String validatorKey = AnnotationActionValidatorManager.buildValidatorKey(SimpleAnnotationAction.class, alias);
+        assertEquals(SimpleAnnotationAction.class.getName() + "/" + alias, validatorKey);
+    }
+
+    public void testBuildsValidatorsForAlias() {
+        List validatorList = AnnotationActionValidatorManager.getValidators(SimpleAnnotationAction.class, alias);
+
+        // 16 in the class level + 0 in the alias
+        // TODO: add alias tests
+        assertEquals(16, validatorList.size());
+    }
+
+    public void testDefaultMessageInterpolation() {
+        // get validators
+        List validatorList = AnnotationActionValidatorManager.getValidators(TestBean.class, "beanMessageBundle");
+        assertEquals(3, validatorList.size());
+
+        try {
+            TestBean bean = new TestBean();
+            bean.setName("foo");
+            bean.setCount(99);
+
+            ValidatorContext context = new GenericValidatorContext(bean);
+            AnnotationActionValidatorManager.validate(bean, "beanMessageBundle", context);
+            assertTrue(context.hasErrors());
+            assertTrue(context.hasFieldErrors());
+
+            List l = (List) context.getFieldErrors().get("count");
+            assertNotNull(l);
+            assertEquals(1, l.size());
+            assertEquals("Smaller Invalid Count: 99", l.get(0));
+        } catch (ValidationException ex) {
+            ex.printStackTrace();
+            fail("Validation error: " + ex.getMessage());
+        }
+    }
+
+    public void testGetValidatorsForInterface() {
+        List validatorList = AnnotationActionValidatorManager.getValidators(AnnotationDataAware2.class, alias);
+
+        // 1 in interface hierarchy, 2 from parent interface (1 default + 1 context)
+        assertEquals(3, validatorList.size());
+
+        final FieldValidator dataValidator1 = (FieldValidator) validatorList.get(0);
+        assertEquals("data", dataValidator1.getFieldName());
+        assertTrue(dataValidator1 instanceof RequiredFieldValidator);
+
+        final FieldValidator dataValidator2 = (FieldValidator) validatorList.get(1);
+        assertEquals("data", dataValidator2.getFieldName());
+        assertTrue(dataValidator2 instanceof RequiredStringValidator);
+
+        final FieldValidator blingValidator = (FieldValidator) validatorList.get(2);
+        assertEquals("bling", blingValidator.getFieldName());
+        assertTrue(blingValidator instanceof RequiredStringValidator);
+    }
+
+    public void testGetValidatorsFromInterface() {
+        List validatorList = AnnotationActionValidatorManager.getValidators(SimpleAnnotationAction3.class, alias);
+
+        // 16 in the class hierarchy + 1 in the interface + 1 in interface alias
+        assertEquals(18, validatorList.size());
+
+        final FieldValidator v = (FieldValidator) validatorList.get(0);
+        assertEquals("bar", v.getFieldName());
+        assertTrue(v instanceof RequiredFieldValidator);
+
+        final FieldValidator v1 = (FieldValidator) validatorList.get(1);
+        assertEquals("bar", v1.getFieldName());
+        assertTrue(v1 instanceof IntRangeFieldValidator);
+
+        final FieldValidator v2 = (FieldValidator) validatorList.get(2);
+        assertEquals("baz", v2.getFieldName());
+        assertTrue(v2 instanceof IntRangeFieldValidator);
+
+        final FieldValidator v3 = (FieldValidator) validatorList.get(3);
+        assertEquals("date", v3.getFieldName());
+        assertTrue(v3 instanceof DateRangeFieldValidator);
+
+        // action-level validator comes first
+        final Validator v4 = (Validator) validatorList.get(4);
+        assertTrue(v4 instanceof ExpressionValidator);
+
+        // action-level validator comes first
+        final Validator v5 = (Validator) validatorList.get(5);
+        assertTrue(v5 instanceof ExpressionValidator);
+
+        // action-level validator comes first
+        final Validator v6 = (Validator) validatorList.get(6);
+        assertTrue(v6 instanceof ExpressionValidator);
+
+        // action-level validator comes first
+        final Validator v7 = (Validator) validatorList.get(7);
+        assertTrue(v7 instanceof ExpressionValidator);
+
+        // action-level validator comes first
+        final Validator v8 = (Validator) validatorList.get(8);
+        assertTrue(v8 instanceof ExpressionValidator);
+
+        final FieldValidator v9 = (FieldValidator) validatorList.get(9);
+        assertEquals("cute", v9.getFieldName());
+        assertTrue(v9 instanceof DateRangeFieldValidator);
+
+        final FieldValidator v10 = (FieldValidator) validatorList.get(10);
+        assertEquals("cute", v10.getFieldName());
+        assertTrue(v10 instanceof EmailValidator);
+
+        final FieldValidator v11 = (FieldValidator) validatorList.get(11);
+        assertEquals("cute", v11.getFieldName());
+        assertTrue(v11 instanceof IntRangeFieldValidator);
+
+        final FieldValidator v12 = (FieldValidator) validatorList.get(12);
+        assertEquals("cute", v12.getFieldName());
+        assertTrue(v12 instanceof RequiredFieldValidator);
+
+        final FieldValidator v13 = (FieldValidator) validatorList.get(13);
+        assertEquals("cute", v13.getFieldName());
+        assertTrue(v13 instanceof RequiredStringValidator);
+
+        final FieldValidator v14 = (FieldValidator) validatorList.get(14);
+        assertEquals("cute", v14.getFieldName());
+        assertTrue(v14 instanceof StringLengthFieldValidator);
+
+        final FieldValidator v15 = (FieldValidator) validatorList.get(15);
+        assertEquals("cute", v15.getFieldName());
+        assertTrue(v15 instanceof URLValidator);
+
+
+        final FieldValidator v16 = (FieldValidator) validatorList.get(16);
+        assertEquals("data", v16.getFieldName());
+        assertTrue(v16 instanceof RequiredFieldValidator);
+
+        final FieldValidator v17 = (FieldValidator) validatorList.get(17);
+        assertEquals("data", v17.getFieldName());
+        assertTrue(v17 instanceof RequiredStringValidator);
+
+
+
+    }
+
+    public void testMessageInterpolation() {
+        // get validators
+        List validatorList = AnnotationActionValidatorManager.getValidators(TestBean.class, "beanMessageBundle");
+        assertEquals(3, validatorList.size());
+
+        try {
+            TestBean bean = new TestBean();
+            bean.setName("foo");
+            bean.setCount(150);
+
+            ValidatorContext context = new GenericValidatorContext(bean);
+            AnnotationActionValidatorManager.validate(bean, "beanMessageBundle", context);
+            assertTrue(context.hasErrors());
+            assertTrue(context.hasFieldErrors());
+
+            List l = (List) context.getFieldErrors().get("count");
+            assertNotNull(l);
+            assertEquals(1, l.size());
+            assertEquals("Count must be between 1 and 100, current value is 150.", l.get(0));
+        } catch (ValidationException ex) {
+            ex.printStackTrace();
+            fail("Validation error: " + ex.getMessage());
+        }
+    }
+
+    public void testSameAliasWithDifferentClass() {
+        List validatorList = AnnotationActionValidatorManager.getValidators(SimpleAnnotationAction.class, alias);
+        List validatorList2 = AnnotationActionValidatorManager.getValidators(SimpleAnnotationAction2.class, alias);
+        assertFalse(validatorList.size() == validatorList2.size());
+    }
+
+    public void testSkipUserMarkerActionLevelShortCircuit() {
+        // get validators
+        List validatorList = AnnotationActionValidatorManager.getValidators(AnnotationUser.class, null);
+        assertEquals(10, validatorList.size());
+
+        try {
+            AnnotationUser user = new AnnotationUser();
+            user.setName("Mark");
+            user.setEmail("bad_email");
+            user.setEmail2("bad_email");
+
+            ValidatorContext context = new GenericValidatorContext(user);
+            AnnotationActionValidatorManager.validate(user, null, context);
+            assertTrue(context.hasFieldErrors());
+
+            // check field errors
+            List l = (List) context.getFieldErrors().get("email");
+            assertNotNull(l);
+            assertEquals(1, l.size());
+            assertEquals("Not a valid e-mail.", l.get(0));
+            l = (List) context.getFieldErrors().get("email2");
+            assertNotNull(l);
+            assertEquals(2, l.size());
+            assertEquals("Not a valid e-mail2.", l.get(0));
+            assertEquals("Email2 not from the right company.", l.get(1));
+
+            // check action errors
+            assertTrue(context.hasActionErrors());
+            l = (List) context.getActionErrors();
+            assertNotNull(l);
+            assertEquals(2, l.size()); // both expression test failed see AnnotationUser-validation.xml
+            assertEquals("Email does not start with mark", l.get(0));
+        } catch (ValidationException ex) {
+            ex.printStackTrace();
+            fail("Validation error: " + ex.getMessage());
+        }
+    }
+
+    public void testSkipAllActionLevelShortCircuit2() {
+        // get validators
+        List validatorList = AnnotationActionValidatorManager.getValidators(AnnotationUser.class, null);
+        assertEquals(10, validatorList.size());
+
+        try {
+            AnnotationUser user = new AnnotationUser();
+            user.setName("Mark");
+            // * mark both email to starts with mark to get pass the action-level validator,
+            // so we could concentrate on testing the field-level validators (AnnotationUser-validation.xml)
+            // * make both email the same to pass the action-level validator at 
+            // AnnotationUserMarker-validation.xml
+            user.setEmail("mark_bad_email_for_field_val@foo.com");
+            user.setEmail2("mark_bad_email_for_field_val@foo.com");
+
+            ValidatorContext context = new GenericValidatorContext(user);
+            AnnotationActionValidatorManager.validate(user, null, context);
+            assertTrue(context.hasFieldErrors());
+
+            // check field errors
+            // we have an error in this field level, email does not ends with mycompany.com
+            List l = (List) context.getFieldErrors().get("email");
+            assertNotNull(l);
+            assertEquals(1, l.size()); // because email-field-val is short-circuit
+            assertEquals("Email not from the right company.", l.get(0));
+
+            
+            // check action errors
+            l = (List) context.getActionErrors();
+            assertFalse(context.hasActionErrors());
+            assertEquals(0, l.size());
+            
+            
+        } catch (ValidationException ex) {
+            ex.printStackTrace();
+            fail("Validation error: " + ex.getMessage());
+        }
+    }
+
+    
+    public void testActionLevelShortCircuit() throws Exception {
+    	
+    	List validatorList = AnnotationActionValidatorManager.getValidators(AnnotationUser.class, null);
+        assertEquals(10, validatorList.size());
+        
+        AnnotationUser user = new AnnotationUser();
+        // all fields will trigger error, but sc of action-level, cause it to not appear
+        user.setName(null);		
+
+        user.setEmail("rainerh(at)example.com");
+        user.setEmail("rainer_h(at)example.com");
+
+
+        ValidatorContext context = new GenericValidatorContext(user);
+        AnnotationActionValidatorManager.validate(user, null, context);
+    	
+    	// check field level errors
+        // shouldn't have any because action error prevents validation of anything else
+        List l = (List) context.getFieldErrors().get("email2");
+        assertNull(l);
+    	
+    	
+        // check action errors
+        assertTrue(context.hasActionErrors());
+        l = (List) context.getActionErrors();
+        assertNotNull(l);
+        // we only get one, because AnnotationUserMarker-validation.xml action-level validator
+        // already sc it   :-)
+        assertEquals(1, l.size()); 
+        assertEquals("Email not the same as email2", l.get(0));
+    }
+    
+    
+    public void testShortCircuitNoErrors() {
+        // get validators
+        List validatorList = AnnotationActionValidatorManager.getValidators(AnnotationUser.class, null);
+        assertEquals(10, validatorList.size());
+
+        try {
+            AnnotationUser user = new AnnotationUser();
+            user.setName("Mark");
+            user.setEmail("mark@mycompany.com");
+            user.setEmail2("mark@mycompany.com");
+
+            ValidatorContext context = new GenericValidatorContext(user);
+            AnnotationActionValidatorManager.validate(user, null, context);
+            assertFalse(context.hasErrors());
+        } catch (ValidationException ex) {
+            ex.printStackTrace();
+            fail("Validation error: " + ex.getMessage());
+        }
+    }
+}

tiger/src/test/com/opensymphony/xwork/validator/AnnotationDataAware.java

+/*
+ * Copyright (c) 2005 Your Corporation. All Rights Reserved.
+ */
+package com.opensymphony.xwork.validator;
+
+import com.opensymphony.xwork.util.Bar;
+import com.opensymphony.xwork.validator.annotations.RequiredFieldValidator;
+import com.opensymphony.xwork.validator.annotations.Validation;
+import com.opensymphony.xwork.validator.annotations.RequiredStringValidator;
+
+
+/**
+ * Implemented by SimpleAction3 and TestBean2 to test class hierarchy traversal.
+ *
+ * @author Mark Woon
+ */
+@Validation()
+public interface AnnotationDataAware {
+
+    void setBarObj(Bar b);
+
+    Bar getBarObj();
+
+    @RequiredFieldValidator(message = "You must enter a value for data.")
+    @RequiredStringValidator(message = "You must enter a value for data.")
+    void setData(String data);
+
+    String getData();
+}

tiger/src/test/com/opensymphony/xwork/validator/AnnotationDataAware2.java

+/*
+ * Copyright (c) 2005 Your Corporation. All Rights Reserved.
+ */
+package com.opensymphony.xwork.validator;
+
+import com.opensymphony.xwork.validator.annotations.RequiredStringValidator;
+
+
+/**
+ * Used to test hierarchy traversal for interfaces.
+ *
+ * @author Mark Woon
+ */
+public interface AnnotationDataAware2 extends AnnotationDataAware {
+
+    @RequiredStringValidator(message = "You must enter a value for data.")
+    public void setBling(String bling);
+
+    public String getBling();
+}

tiger/src/test/com/opensymphony/xwork/validator/AnnotationUser.java

+/*
+ * Copyright (c) 2005 Your Corporation. All Rights Reserved.
+ */
+package com.opensymphony.xwork.validator;
+
+import com.opensymphony.xwork.validator.annotations.*;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Test bean.
+ *
+ * @author Mark Woon
+ */
+/*
+<validator type="expression">
+    <param name="expression">email.startsWith('mark')</param>
+    <message>Email does not start with mark</message>
+</validator>
+<validator type="expression">
+    <param name="expression">email2.startsWith('mark')</param>
+    <message>Email2 does not start with mark</message>
+</validator>
+*/
+@Validation(
+        validations = @Validations(
+                expressions = {
+                    @ExpressionValidator(expression = "email.startsWith('mark')", message = "Email does not start with mark"),
+                    @ExpressionValidator(expression = "email2.startsWith('mark')", message = "Email2 does not start with mark")
+                }
+        )
+)
+public class AnnotationUser implements AnnotationUserMarker {
+
+    private Collection collection;
+    private List list;
+    private Map map;
+    private String email;
+    private String email2;
+    private String name;
+
+
+    public void setCollection(Collection collection) {
+        this.collection = collection;
+    }
+
+    public Collection getCollection() {
+        return collection;
+    }
+
+    /*
+    <field name="email">
+        <field-validator type="email" short-circuit="true">
+            <message>Not a valid e-mail.</message>
+        </field-validator>
+        <field-validator type="fieldexpression">
+            <param name="expression">email.endsWith('mycompany.com')</param>
+            <message>Email not from the right company.</message>
+        </field-validator>
+    </field>
+    */
+    @EmailValidator(shortCircuit = true, message = "Not a valid e-mail.")
+    @FieldExpressionValidator(expression = "email.endsWith('mycompany.com')", message = "Email not from the right company.")
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    /*
+    <field name="email2">
+        <field-validator type="email">
+            <message>Not a valid e-mail2.</message>
+        </field-validator>
+        <field-validator type="fieldexpression">
+            <param name="expression">email.endsWith('mycompany.com')</param>
+            <message>Email2 not from the right company.</message>
+        </field-validator>
+    </field>
+    */
+    @EmailValidator(message = "Not a valid e-mail2.")
+    @FieldExpressionValidator(expression = "email2.endsWith('mycompany.com')", message = "Email2 not from the right company.")
+    public void setEmail2(String email) {
+        email2 = email;
+    }
+
+    public String getEmail2() {
+        return email2;
+    }
+
+    public void setList(List l) {
+        list = l;
+    }
+
+    public List getList() {
+        return list;
+    }
+
+    public void setMap(Map m) {
+        map = m;
+    }
+
+    public Map getMap() {
+        return map;
+    }
+
+    /*
+    <field name="name">
+        <field-validator type="required">
+            <message key="name.key">You must enter a value for name.</message>
+        </field-validator>
+    </field>
+    */
+    @RequiredFieldValidator(key = "name.key", message = "You must enter a value for name.")
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+}

tiger/src/test/com/opensymphony/xwork/validator/AnnotationUserMarker.java

+/*
+ * Copyright (c) 2005 Your Corporation. All Rights Reserved.
+ */
+package com.opensymphony.xwork.validator;
+
+import com.opensymphony.xwork.validator.annotations.*;
+
+/**
+ * Marker interface to help test hierarchy traversal.
+ *
+ * @author Mark Woon
+ */
+/*
+    <field name="email">
+        <field-validator type="required" short-circuit="true">
+            <message>You must enter a value for email.</message>
+        </field-validator>
+    </field>
+    <field name="email2">
+        <field-validator type="required" short-circuit="true">
+            <message>You must enter a value for email2.</message>
+        </field-validator>
+    </field>
+    <validator type="expression" short-circuit="true">
+        <param name="expression">email.equals(email2)</param>
+        <message>Email not the same as email2</message>
+    </validator>
+*/
+@Validation(
+        validations = @Validations(
+                requiredFields = {
+                    @RequiredFieldValidator(fieldName = "email", shortCircuit = true, message = "You must enter a value for email."),
+                    @RequiredFieldValidator(fieldName = "email2", shortCircuit = true, message = "You must enter a value for email2.")
+                },
+                expressions = {
+                        @ExpressionValidator(shortCircuit = true, expression = "email.equals(email2)", message = "Email not the same as email2" )
+                }
+        )
+)
+public interface AnnotationUserMarker {
+}

tiger/src/test/com/opensymphony/xwork/validator/GenericValidatorContext.java

+/*
+ * Copyright (c) 2005 Your Corporation. All Rights Reserved.
+ */
+package com.opensymphony.xwork.validator;
+
+import java.util.*;
+
+
+/**
+ * Dummy validator context to use to capture error messages.
+ *
+ * @author Mark Woon
+ * @author Matthew Payne
+ */
+public class GenericValidatorContext extends DelegatingValidatorContext {
+
+    private Collection actionErrors;
+    private Collection actionMessages;
+    private Map fieldErrors;
+
+
+    public GenericValidatorContext(Object object) {
+        super(object);
+    }
+
+
+    public synchronized void setActionErrors(Collection errorMessages) {
+        this.actionErrors = errorMessages;
+    }
+
+    public synchronized Collection getActionErrors() {
+        return new ArrayList(internalGetActionErrors());
+    }
+
+    public synchronized void setActionMessages(Collection messages) {
+        this.actionMessages = messages;
+    }
+
+    public synchronized Collection getActionMessages() {
+        return new ArrayList(internalGetActionMessages());
+    }
+
+    public synchronized void setFieldErrors(Map errorMap) {
+        this.fieldErrors = errorMap;
+    }
+
+    /**
+     * Get the field specific errors.
+     *
+     * @return an unmodifiable Map with errors mapped from fieldname (String) to Collection of String error messages
+     */
+    public synchronized Map getFieldErrors() {
+        return new HashMap(internalGetFieldErrors());
+    }
+
+    public synchronized void addActionError(String anErrorMessage) {
+        internalGetActionErrors().add(anErrorMessage);
+    }
+
+    /**
+     * Add an Action level message to this Action
+     */
+    public void addActionMessage(String aMessage) {
+        internalGetActionMessages().add(aMessage);
+    }
+
+    public synchronized void addFieldError(String fieldName, String errorMessage) {
+        final Map errors = internalGetFieldErrors();
+        List thisFieldErrors = (List) errors.get(fieldName);
+
+        if (thisFieldErrors == null) {
+            thisFieldErrors = new ArrayList();
+            errors.put(fieldName, thisFieldErrors);
+        }
+
+        thisFieldErrors.add(errorMessage);
+    }
+
+    public synchronized boolean hasActionErrors() {
+        return (actionErrors != null) && !actionErrors.isEmpty();
+    }
+
+    /**
+     * Note that this does not have the same meaning as in WW 1.x
+     *
+     * @return (hasActionErrors() || hasFieldErrors())
+     */
+    public synchronized boolean hasErrors() {
+        return (hasActionErrors() || hasFieldErrors());
+    }
+
+    public synchronized boolean hasFieldErrors() {
+        return (fieldErrors != null) && !fieldErrors.isEmpty();
+    }
+
+    private Collection internalGetActionErrors() {
+        if (actionErrors == null) {
+            actionErrors = new ArrayList();
+        }
+
+        return actionErrors;
+    }
+
+    private Collection internalGetActionMessages() {
+        if (actionMessages == null) {
+            actionMessages = new ArrayList();
+        }
+
+        return actionMessages;
+    }
+
+    private Map internalGetFieldErrors() {
+        if (fieldErrors == null) {
+            fieldErrors = new HashMap();
+        }
+
+        return fieldErrors;
+    }
+}

tiger/src/test/com/opensymphony/xwork/validator/SimpleAnnotationAction.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork.validator;
+
+import com.opensymphony.xwork.validator.annotations.*;
+import com.opensymphony.xwork.ActionSupport;
+import com.opensymphony.xwork.TestBean;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Properties;
+
+
+/**
+ * Simple Test Action for annotaton processing.
+ *
+ * @author $author$
+ * @version $Revision$
+ */
+@Validation()
+public class SimpleAnnotationAction extends ActionSupport {
+    //~ Static fields/initializers /////////////////////////////////////////////
+
+    public static final String COMMAND_RETURN_CODE = "com.opensymphony.xwork.validator.SimpleAnnotationAction.CommandInvoked";
+
+    //~ Instance fields ////////////////////////////////////////////////////////
+
+    private ArrayList someList = new ArrayList();
+    private Date date = new Date();
+    private Properties settings = new Properties();
+    private String blah;
+    private String name;
+    private TestBean bean = new TestBean();
+    private boolean throwException;
+    private int bar;
+    private int baz;
+    private int foo;
+    
+    private String aliasSource;
+    private String aliasDest;
+    
+    
+
+    //~ Constructors ///////////////////////////////////////////////////////////
+
+    public SimpleAnnotationAction() {
+    }
+
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    /*
+        <field name="bar">
+            <field-validator type="required">
+                <message>You must enter a value for bar.</message>
+            </field-validator>
+            <field-validator type="int">
+                <param name="min">6</param>
+                <param name="max">10</param>
+                <message>bar must be between ${min} and ${max}, current value is ${bar}.</message>
+            </field-validator>
+        </field>
+    */
+    @RequiredFieldValidator(type = ValidatorType.FIELD, message = "You must enter a value for bar.")
+    @IntRangeFieldValidator(type = ValidatorType.FIELD, min = "6", max = "10", message = "bar must be between ${min} and ${max}, current value is ${bar}.")
+    public void setBar(int bar) {
+        this.bar = bar;
+    }
+
+    public int getBar() {
+        return bar;
+    }
+
+    /*
+        <field name="baz">
+            <field-validator type="int">
+                <param name="min">0</param>
+                <message key="baz.range">Could not find baz.range!</message>
+            </field-validator>
+        </field>
+    */
+    @IntRangeFieldValidator(min = "0", key = "baz.range", message = "Could not find baz.range!")
+    public void setBaz(int baz) {
+        this.baz = baz;
+    }
+
+    public int getBaz() {
+        return baz;
+    }
+
+    public void setBean(TestBean bean) {
+        this.bean = bean;
+    }
+
+    public TestBean getBean() {
+        return bean;
+    }
+
+    public void setBlah(String blah) {
+        this.blah = blah;
+    }
+
+    public String getBlah() {
+        return blah;
+    }
+
+    public Boolean getBool(String b) {
+        return new Boolean(b);
+    }
+
+    public boolean[] getBools() {
+        boolean[] b = new boolean[] {true, false, false, true};
+
+        return b;
+    }
+
+    /*
+        <field name="date">
+            <field-validator type="date">
+                <param name="min">12/22/2002</param>
+                <param name="max">12/25/2002</param>
+                <message>The date must be between 12-22-2002 and 12-25-2002.</message>
+            </field-validator>
+        </field>
+    */
+    @DateRangeFieldValidator(min = "12/22/2002", max = "12/25/2002", message = "The date must be between 12-22-2002 and 12-25-2002.")
+    public void setDate(Date date) {
+        this.date = date;
+    }
+
+    public Date getDate() {
+        return date;
+    }
+
+    public void setFoo(int foo) {
+        this.foo = foo;
+    }
+
+    public int getFoo() {
+        return foo;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setSettings(Properties settings) {
+        this.settings = settings;
+    }
+
+    public Properties getSettings() {
+        return settings;
+    }
+
+
+    public String getAliasDest() {
+        return aliasDest;
+    }
+
+    public void setAliasDest(String aliasDest) {
+        this.aliasDest = aliasDest;
+    }
+
+    public String getAliasSource() {
+        return aliasSource;
+    }
+
+    public void setAliasSource(String aliasSource) {
+        this.aliasSource = aliasSource;
+    }
+
+    
+    public void setSomeList(ArrayList someList) {
+        this.someList = someList;
+    }
+
+    public ArrayList getSomeList() {
+        return someList;
+    }
+
+    public void setThrowException(boolean throwException) {
+        this.throwException = throwException;
+    }
+
+    public String commandMethod() throws Exception {
+        return COMMAND_RETURN_CODE;
+    }
+
+    public String exceptionMethod() throws Exception {
+        if (throwException) {
+            throw new Exception("We're supposed to throw this");
+        }
+
+        return "OK";
+    }
+
+    @Validations(
+            requiredFields =
+                    {@RequiredFieldValidator(type = ValidatorType.SIMPLE, fieldName = "customfield", message = "You must enter a value for field.")},
+            requiredStrings =
+                    {@RequiredStringValidator(type = ValidatorType.SIMPLE, fieldName = "stringisrequired", message = "You must enter a value for string.")},
+            emails =
+                    { @EmailValidator(type = ValidatorType.SIMPLE, fieldName = "emailaddress", message = "You must enter a value for email.")},
+            urls =
+                    { @UrlValidator(type = ValidatorType.SIMPLE, fieldName = "hreflocation", message = "You must enter a value for email.")},
+            stringLengthFields =
+                    {@StringLengthFieldValidator(type = ValidatorType.SIMPLE, trim = true, minLength="10" , maxLength = "12", fieldName = "needstringlength", message = "You must enter a stringlength.")},
+            intRangeFields =
+                    { @IntRangeFieldValidator(type = ValidatorType.SIMPLE, fieldName = "intfield", min = "6", max = "10", message = "bar must be between ${min} and ${max}, current value is ${bar}.")},
+            dateRangeFields =
+                    {@DateRangeFieldValidator(type = ValidatorType.SIMPLE, fieldName = "datefield", min = "-1", max = "99", message = "bar must be between ${min} and ${max}, current value is ${bar}.")},
+            expressions = {
+                @ExpressionValidator(expression = "foo &gt; 1", message = "Foo must be greater than Bar 1. Foo = ${foo}, Bar = ${bar}."),
+                @ExpressionValidator(expression = "foo &gt; 2", message = "Foo must be greater than Bar 2. Foo = ${foo}, Bar = ${bar}."),
+                @ExpressionValidator(expression = "foo &gt; 3", message = "Foo must be greater than Bar 3. Foo = ${foo}, Bar = ${bar}."),
+                @ExpressionValidator(expression = "foo &gt; 4", message = "Foo must be greater than Bar 4. Foo = ${foo}, Bar = ${bar}."),
+                @ExpressionValidator(expression = "foo &gt; 5", message = "Foo must be greater than Bar 5. Foo = ${foo}, Bar = ${bar}.")
+    }
+    )
+    public String execute() throws Exception {
+        if (foo == bar) {
+            return ERROR;
+        }
+
+        baz = foo + bar;
+
+        name = "HelloWorld";
+        settings.put("foo", "bar");
+        settings.put("black", "white");
+
+        someList.add("jack");
+        someList.add("bill");
+        someList.add("kerry");
+
+        return SUCCESS;
+    }
+}

tiger/src/test/com/opensymphony/xwork/validator/SimpleAnnotationAction.properties

+foo.range=Foo Range Message
+baz.range=${getText(fieldName)} must be greater than ${min}
+baz=Baz Field

tiger/src/test/com/opensymphony/xwork/validator/SimpleAnnotationAction2.java

+/*
+ * Copyright (c) 2005 Your Corporation. All Rights Reserved.
+ */
+package com.opensymphony.xwork.validator;
+
+import com.opensymphony.xwork.validator.annotations.RequiredFieldValidator;
+import com.opensymphony.xwork.validator.annotations.IntRangeFieldValidator;
+
+/**
+ * SimpleAction2
+ *
+ * @author Jason Carreira
+ *         Created Jun 14, 2003 9:51:12 PM
+ */
+public class SimpleAnnotationAction2 extends SimpleAnnotationAction {
+
+    private int count;
+
+    /*
+    <field name="count">
+        <field-validator type="required">
+            <message>You must enter a value for count.</message>
+        </field-validator>
+        <field-validator type="int">
+            <param name="min">0</param>
+            <param name="max">5</param>
+            <message>count must be between ${min} and ${max}, current value is ${count}.</message>
+        </field-validator>
+    </field>
+    */
+
+    @RequiredFieldValidator(message = "You must enter a value for count.")
+    @IntRangeFieldValidator(min = "0", max = "5", message = "count must be between ${min} and ${max}, current value is ${count}.")
+    public void setCount(int count) {
+        this.count = count;
+    }
+
+    public int getCount() {
+        return count;
+    }
+}

tiger/src/test/com/opensymphony/xwork/validator/SimpleAnnotationAction3.java

+/*
+ * Copyright (c) 2005 Your Corporation. All Rights Reserved.
+ */
+package com.opensymphony.xwork.validator;
+
+import com.opensymphony.xwork.util.Bar;
+
+
+/**
+ * Extend SimpleAction to test class hierarchy traversal.
+ *
+ * @author Mark Woon
+ */
+public class SimpleAnnotationAction3 extends SimpleAnnotationAction implements AnnotationDataAware {
+
+    private Bar bar;
+    private String data;
+
+
+    public void setBarObj(Bar b) {
+        bar = b;
+    }
+
+    public Bar getBarObj() {
+        return bar;
+    }
+
+    public void setData(String data) {
+        this.data = data;
+    }
+
+    public String getData() {
+        return data;
+    }
+}

tiger/src/test/com/opensymphony/xwork/validator/SimpleAnnotationAction_de.properties

+foo.range=I don''t know German

tiger/src/test/com/opensymphony/xwork/validator/SimpleAnnotationAction_en.properties

Empty file added.