View Javadoc

1   /**
2    * Copyright 2005-2011 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.service.impl;
17  
18  import org.junit.Assert;
19  import org.junit.Before;
20  import org.junit.Test;
21  import org.kuali.test.KRADTestCase;
22  import org.kuali.rice.core.api.util.RiceKeyConstants;
23  import org.kuali.rice.krad.datadictionary.DataDictionary;
24  import org.kuali.rice.krad.datadictionary.DataObjectEntry;
25  import org.kuali.rice.krad.datadictionary.state.StateMapping;
26  import org.kuali.rice.krad.datadictionary.state.StateMappingBase;
27  import org.kuali.rice.krad.datadictionary.validation.Address;
28  import org.kuali.rice.krad.datadictionary.validation.Company;
29  import org.kuali.rice.krad.datadictionary.validation.Employee;
30  import org.kuali.rice.krad.datadictionary.validation.ErrorLevel;
31  import org.kuali.rice.krad.datadictionary.validation.Person;
32  import org.kuali.rice.krad.datadictionary.validation.constraint.BaseConstraint;
33  import org.kuali.rice.krad.datadictionary.validation.constraint.Constraint;
34  import org.kuali.rice.krad.datadictionary.validation.constraint.ValidCharactersConstraint;
35  import org.kuali.rice.krad.datadictionary.validation.constraint.provider.CollectionDefinitionConstraintProvider;
36  import org.kuali.rice.krad.datadictionary.validation.processor.MustOccurConstraintProcessor;
37  import org.kuali.rice.krad.datadictionary.validation.result.ConstraintValidationResult;
38  import org.kuali.rice.krad.datadictionary.validation.result.DictionaryValidationResult;
39  import org.kuali.rice.krad.service.DataDictionaryService;
40  import org.kuali.rice.krad.uif.util.ConstraintStateUtils;
41  import org.springframework.context.support.ClassPathXmlApplicationContext;
42  
43  import java.io.IOException;
44  import java.util.ArrayList;
45  import java.util.Arrays;
46  import java.util.Date;
47  import java.util.Iterator;
48  import java.util.List;
49  
50  /**
51   * DictionaryValidationServiceImplTest tests {@link DictionaryValidationServiceImpl} using the data dictionary
52   * configurations in
53   * org/kuali/rice/krad/test/datadictionary/validation
54   *
55   * @author Kuali Rice Team (rice.collab@kuali.org)
56   */
57  public class DictionaryValidationServiceImplTest extends KRADTestCase {
58  
59      ClassPathXmlApplicationContext context;
60      private DictionaryValidationServiceImpl service;
61      DataDictionary dataDictionary = new DataDictionary();
62  
63      protected DataObjectEntry addressEntry;
64  
65      private Address validLondonAddress = new Address("8129 Maiden Lane", "", "London", "", "SE1 0P3", "UK", null);
66      private Address validUSAddress = new Address("893 Presidential Ave", "Suite 800", "Washington", "DC", "12031",
67              "USA", null);
68      private Address invalidUSAddress = new Address("893 Presidential Ave", "Suite 800", "Washington", "",
69              "92342-123456", "USA", null);
70      private Address noZipNoCityUSAddress = new Address("893 Presidential Ave", "Suite 800", null, "DC", null, "USA",
71              null);
72      private Address validNonDCUSAddress = new Address("89 11th Street", "Suite 800", "Seattle", "WA", "", "USA", null);
73      private Address invalidDCUSAddress = new Address("89 Presidential Ave", "Suite 800", "Washington", "DC", "12031",
74              "USA", null);
75      private Address invalidHKAddress = new Address("182 Lin Pai Road", "", "Hong Kong", "N.T.", "", "CN", null);
76  
77      @Before
78      public void setUp() throws Exception {
79          super.setUp();
80  
81          context = new ClassPathXmlApplicationContext("classpath:DictionaryValidationServiceSpringBeans.xml");
82  
83          service = (DictionaryValidationServiceImpl) context.getBean("dictionaryValidationService");
84  
85          dataDictionary.addConfigFileLocation("KR-NS",
86                  "classpath:org/kuali/rice/krad/bo/datadictionary/DataDictionaryBaseTypes.xml");
87          dataDictionary.addConfigFileLocation("KR-NS",
88                  "classpath:org/kuali/rice/kns/bo/datadictionary/DataDictionaryBaseTypes.xml");
89          dataDictionary.addConfigFileLocation("KR-NS",
90                  "classpath:org/kuali/rice/krad/test/datadictionary/validation/Company.xml");
91          dataDictionary.addConfigFileLocation("KR-NS",
92                  "classpath:org/kuali/rice/krad/test/datadictionary/validation/Address.xml");
93          dataDictionary.addConfigFileLocation("KR-NS",
94                  "classpath:org/kuali/rice/krad/test/datadictionary/validation/Employee.xml");
95          dataDictionary.addConfigFileLocation("KR-NS","classpath:org/kuali/rice/krad/test/datadictionary/validation/Person.xml");
96  
97          dataDictionary.parseDataDictionaryConfigurationFiles(false);
98  
99          addressEntry = dataDictionary.getDataObjectEntry("org.kuali.rice.krad.datadictionary.validation.Address");
100     }
101 
102     @Test
103     /**
104      * tests that a valid non US address will not generate warnings or errors
105      *
106      * @see DictionaryValidationServiceImpl#validate(Object, String, String, boolean)
107      * @see org.kuali.rice.krad.datadictionary.validation.constraint.MustOccurConstraint
108      */
109     public void testValidNonUSAddress() {
110         DictionaryValidationResult dictionaryValidationResult = service.validate(validLondonAddress,
111                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
112 
113         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
114         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
115     }
116 
117     @Test
118     /**
119      * tests that a valid US address will not generate warnings or errors
120      *
121      * @see DictionaryValidationServiceImpl#validate(Object, String, String, boolean)
122      * @see org.kuali.rice.krad.datadictionary.validation.constraint.MustOccurConstraint
123      */
124     public void testValidUSAddress() {
125         DictionaryValidationResult dictionaryValidationResult = service.validate(validUSAddress,
126                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
127 
128         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
129         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
130     }
131 
132     @Test
133     /**
134      * tests that an invalid US address will generate the expected errors
135      *
136      * @see DictionaryValidationServiceImpl#validate(Object, String, String, boolean)
137      * @see org.kuali.rice.krad.datadictionary.validation.constraint.MustOccurConstraint
138      */
139     public void testInvalidUSAddress() {
140         DictionaryValidationResult dictionaryValidationResult = service.validate(invalidUSAddress,
141                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
142 
143         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
144         Assert.assertEquals(2, dictionaryValidationResult.getNumberOfErrors());
145 
146         Assert.assertTrue(hasError(dictionaryValidationResult, "country", RiceKeyConstants.ERROR_REQUIRES_FIELD));
147         Assert.assertTrue(hasError(dictionaryValidationResult, "postalCode", RiceKeyConstants.ERROR_OUT_OF_RANGE));
148     }
149 
150     @Test
151     /**
152      * tests that a valid US address will not generate warnings or errors
153      *
154      * @see DictionaryValidationServiceImpl#validate(Object, String, String, boolean)
155      * @see org.kuali.rice.krad.datadictionary.validation.constraint.MustOccurConstraint
156      */
157     public void testValidNonDCAddress() {
158         DictionaryValidationResult dictionaryValidationResult = service.validate(validNonDCUSAddress,
159                 "org.kuali.rice.krad.datadictionary.validation.Address", addressEntry, true);
160 
161         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
162         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
163     }
164 
165     @Test
166     /**
167      * tests that an invalid DC address will generate the expected errors
168      *
169      * <p>the attribute street1 has a ValidCharacters constraint that is activated when the state attribute has the value 'DC'</p>
170      *
171      * @see DictionaryValidationServiceImpl#validate(Object, String, String, boolean)
172      * @see org.kuali.rice.krad.datadictionary.validation.constraint.WhenConstraint
173      * @see DictionaryValidationResult
174      */
175     public void testInvalidDCAddress() {
176         DictionaryValidationResult dictionaryValidationResult = service.validate(invalidDCUSAddress,
177                 "org.kuali.rice.krad.datadictionary.validation.Address", addressEntry, true);
178 
179         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
180         Assert.assertEquals(1, dictionaryValidationResult.getNumberOfErrors());
181 
182         Assert.assertTrue(hasError(dictionaryValidationResult, "street1", RiceKeyConstants.ERROR_INVALID_FORMAT));
183     }
184 
185     @Test
186     /**
187      * test that the error produced for an invalid US address has the expected attributes
188      *
189      * <p>Address has a must occur constraint where either the postal code must be entered or _both_ the city and state</p>
190      *
191      * @see DictionaryValidationServiceImpl#validate(Object, String, String, boolean)
192      * @see ConstraintValidationResult
193      * @see org.kuali.rice.krad.datadictionary.validation.constraint.MustOccurConstraint
194      */
195     public void testNoStateNoZipUSAddress() {
196         DictionaryValidationResult dictionaryValidationResult = service.validate(noZipNoCityUSAddress,
197                 "org.kuali.rice.krad.datadictionary.validation.Address", addressEntry, true);
198 
199         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
200         Assert.assertEquals(1, dictionaryValidationResult.getNumberOfErrors());
201 
202         if (dictionaryValidationResult.getNumberOfErrors() > 0) {
203             for (Iterator<ConstraintValidationResult> iterator = dictionaryValidationResult.iterator();
204                  iterator.hasNext(); ) {
205                 ConstraintValidationResult constraintValidationResult = iterator.next();
206                 if (constraintValidationResult.getStatus().getLevel() >= ErrorLevel.WARN.getLevel()) {
207                     // The top level error should be an occurs error
208                     Assert.assertEquals(ErrorLevel.ERROR, constraintValidationResult.getStatus());
209                     Assert.assertEquals("error.occurs", constraintValidationResult.getErrorKey());
210                     // It should have two children
211                     List<ConstraintValidationResult> children = constraintValidationResult.getChildren();
212                     Assert.assertNotNull(children);
213                     Assert.assertEquals(2, children.size());
214                     // The first child should have it's own child
215                     ConstraintValidationResult child1 = children.get(0);
216                     ConstraintValidationResult child2 = children.get(1);
217 
218                     Assert.assertEquals("error.requiresField", child1.getErrorKey());
219                     Assert.assertArrayEquals(new String[]{"postalCode"}, child1.getErrorParameters());
220 
221                     List<ConstraintValidationResult> grandchildren = child2.getChildren();
222                     Assert.assertNotNull(grandchildren);
223                     Assert.assertEquals(2, grandchildren.size());
224                     ConstraintValidationResult grandchild1 = grandchildren.get(0);
225                     Assert.assertEquals(ErrorLevel.ERROR, grandchild1.getStatus());
226                     Assert.assertEquals("error.requiresField", grandchild1.getErrorKey());
227                     Assert.assertArrayEquals(new String[]{"city"}, grandchild1.getErrorParameters());
228                     ConstraintValidationResult grandchild2 = grandchildren.get(1);
229                     Assert.assertEquals(ErrorLevel.OK, grandchild2.getStatus());
230                     Assert.assertEquals(new MustOccurConstraintProcessor().getName(), grandchild2.getConstraintName());
231                 }
232             }
233         }
234     }
235 
236     @Test
237     /**
238      * tests that an error is generated when an address where the country attribute is 'CN' has not value for street2
239      *
240      * @see DictionaryValidationServiceImpl#validate(Object, String, String, boolean)
241      * @see org.kuali.rice.krad.datadictionary.validation.constraint.WhenConstraint
242      * @see org.kuali.rice.krad.datadictionary.validation.constraint.SimpleConstraint
243      */
244     public void testSimpleCaseConstraints() throws IOException {
245         DictionaryValidationResult dictionaryValidationResult = service.validate(invalidHKAddress,
246                 "org.kuali.rice.krad.datadictionary.validation.Address", addressEntry, true);
247 
248         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
249         Assert.assertEquals(1, dictionaryValidationResult.getNumberOfErrors());
250 
251         Assert.assertTrue(hasError(dictionaryValidationResult, "street2", RiceKeyConstants.ERROR_REQUIRED));
252     }
253 
254     @Test
255     /**
256      * tests that nested attributes are validated as expected
257      *
258      * @see DictionaryValidationServiceImpl#validate(Object, String, String, boolean)
259      * @see DictionaryValidationResult
260      */
261     public void testRequiredNestedAttribute() throws IOException {
262         DataDictionaryService dataDictionaryService = new DataDictionaryServiceImpl(dataDictionary);
263         service.setDataDictionaryService(dataDictionaryService);
264 
265         //Get object entries from dictionary
266         DataObjectEntry addressEntry = dataDictionary.getDataObjectEntry(
267                 "org.kuali.rice.krad.datadictionary.validation.Address");
268         DataObjectEntry companyEntry = dataDictionary.getDataObjectEntry(
269                 "org.kuali.rice.krad.datadictionary.validation.Company");
270 
271         //Validate object entries
272         addressEntry.completeValidation();
273         companyEntry.completeValidation();
274 
275         Company acmeCompany = new Company();
276 
277         //Validate empty Company object
278         DictionaryValidationResult dictionaryValidationResult;
279         dictionaryValidationResult = service.validate(acmeCompany,
280                 "org.kuali.rice.krad.datadictionary.validation.Company", companyEntry, true);
281 
282         //Main address is required this should result in error
283         Assert.assertEquals(1, dictionaryValidationResult.getNumberOfErrors());
284         Assert.assertTrue(hasError(dictionaryValidationResult, "mainAddress", RiceKeyConstants.ERROR_REQUIRED));
285 
286         //Adding an invalid mainAddress for company
287         Address acmeMainAddress = new Address();
288         acmeCompany.setMainAddress(acmeMainAddress);
289 
290         dictionaryValidationResult = service.validate(acmeCompany,
291                 "org.kuali.rice.krad.datadictionary.validation.Company", companyEntry, true);
292 
293         //This should result in missing country error
294         Assert.assertEquals(2, dictionaryValidationResult.getNumberOfErrors());
295         Assert.assertTrue(hasError(dictionaryValidationResult, "mainAddress.country", RiceKeyConstants.ERROR_REQUIRED));
296         Assert.assertTrue(hasError(dictionaryValidationResult, "mainAddress", RiceKeyConstants.ERROR_OCCURS));
297 
298         //Set items to valid address
299         acmeMainAddress.setCountry("US");
300         acmeMainAddress.setPostalCode("11111");
301 
302         dictionaryValidationResult = service.validate(acmeCompany,
303                 "org.kuali.rice.krad.datadictionary.validation.Company", companyEntry, true);
304 
305         //This should result in no error
306         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
307 
308         //Test Nested Attribute Within Nested Attribute, and nested property override
309         Employee companyContact = new Employee();
310         acmeCompany.setMainContact(companyContact);
311         Person mainContactPerson = new Person();
312         companyContact.setEmployeeDetails(mainContactPerson);
313         companyContact.setEmployeeId("companyContact");
314 
315         dictionaryValidationResult = service.validate(acmeCompany,
316                 "org.kuali.rice.krad.datadictionary.validation.Company", companyEntry, true);
317 
318         Assert.assertEquals(1, dictionaryValidationResult.getNumberOfErrors());
319         Assert.assertTrue(hasError(dictionaryValidationResult, "mainContact.employeeDetails.gender",
320                 RiceKeyConstants.ERROR_REQUIRED));
321     }
322 
323     @Test
324     /**
325      * tests the collection definition as defined in org/kuali/rice/krad/test/datadictionary/validation/Company.xml
326      *
327      * @see org.kuali.rice.krad.datadictionary.CollectionDefinition
328      * @see DictionaryValidationServiceImpl#validate(Object, String, String, boolean)
329      */
330     public void testCollectionConstraints() throws IOException {
331         DataDictionaryService dataDictionaryService = new DataDictionaryServiceImpl(dataDictionary);
332         service.setDataDictionaryService(dataDictionaryService);
333 
334         DataObjectEntry companyEntry = dataDictionary.getDataObjectEntry(
335                 "org.kuali.rice.krad.datadictionary.validation.Company");
336 
337         //Add collection constraint provider so constraints on collections get processed
338         service.getConstraintProviders().add(new CollectionDefinitionConstraintProvider());
339 
340         Company acmeCompany = new Company();
341         Address acmeMainAddress = new Address();
342         acmeMainAddress.setCountry("US");
343         acmeMainAddress.setPostalCode("11111");
344         acmeCompany.setMainAddress(acmeMainAddress);
345 
346         DictionaryValidationResult dictionaryValidationResult = service.validate(acmeCompany,
347                 "org.kuali.rice.krad.datadictionary.validation.Company", companyEntry, true);
348 
349         //Company requires at least two employees
350         Assert.assertEquals(2, dictionaryValidationResult.getNumberOfErrors());
351         Assert.assertTrue(hasError(dictionaryValidationResult, "employees", RiceKeyConstants.ERROR_QUANTITY_RANGE));
352         Assert.assertTrue(hasError(dictionaryValidationResult, "slogans", RiceKeyConstants.ERROR_MIN_OCCURS));
353 
354         //Add required employes and revalidate
355         Employee employee1 = new Employee();
356         Person person = new Person();
357         person.setBirthDate(new Date());
358         person.setGender("M");
359         employee1.setEmployeeDetails(person);
360         employee1.setEmployeeId("123456789");
361 
362         List<Employee> employees = new ArrayList<Employee>();
363         employees.add(employee1);
364         acmeCompany.setEmployees(employees);
365 
366         List<String> slogans = new ArrayList<String>();
367         slogans.add("Slogan One");
368         acmeCompany.setSlogans(slogans);
369 
370         dictionaryValidationResult = service.validate(acmeCompany,
371                 "org.kuali.rice.krad.datadictionary.validation.Company", companyEntry, true);
372         Assert.assertEquals(2, dictionaryValidationResult.getNumberOfErrors());
373         Assert.assertTrue(hasError(dictionaryValidationResult, "employees", RiceKeyConstants.ERROR_QUANTITY_RANGE));
374         Assert.assertTrue(hasError(dictionaryValidationResult, "slogans", RiceKeyConstants.ERROR_MIN_OCCURS));
375 
376         //Add two invalid employees, this should result in size constraint, and invalid employee errors
377         employees.add(new Employee());
378         employees.add(new Employee());
379         slogans.add("Slogan Two");
380 
381         dictionaryValidationResult = service.validate(acmeCompany,
382                 "org.kuali.rice.krad.datadictionary.validation.Company", companyEntry, true);
383         Assert.assertEquals(5, dictionaryValidationResult.getNumberOfErrors());
384 
385         Assert.assertTrue(hasError(dictionaryValidationResult, "employees[1].employeeId",
386                 RiceKeyConstants.ERROR_REQUIRED));
387         Assert.assertTrue(hasError(dictionaryValidationResult, "employees[1].employeeDetails",
388                 RiceKeyConstants.ERROR_REQUIRED));
389         Assert.assertTrue(hasError(dictionaryValidationResult, "employees[2].employeeId",
390                 RiceKeyConstants.ERROR_REQUIRED));
391         Assert.assertTrue(hasError(dictionaryValidationResult, "employees[2].employeeDetails",
392                 RiceKeyConstants.ERROR_REQUIRED));
393 
394     }
395 
396     /**
397      * General test for state based using case constraints and valid characters constraints.
398      *
399      * @throws IOException
400      */
401     @Test
402     public void testStateValidation() throws IOException {
403         Address testAddress = new Address("893 Presidential Ave", "Suite 800", "Washington", "DC", "12031", "USA",
404                 null);
405 
406         testAddress.setValidationState("state1");
407         DictionaryValidationResult dictionaryValidationResult = service.validate(testAddress,
408                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
409         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
410         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
411 
412         testAddress.setValidationState("state1");
413         testAddress.setStreet2("@");
414         dictionaryValidationResult = service.validate(testAddress,
415                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
416         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
417         Assert.assertEquals(1, dictionaryValidationResult.getNumberOfErrors());
418         testAddress.setValidationState("state5");
419         dictionaryValidationResult = service.validate(testAddress,
420                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
421         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
422         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
423 
424         testAddress.setValidationState("state2");
425         testAddress.setCountry("CN");
426         testAddress.setStreet2("Apt 122");
427         dictionaryValidationResult = service.validate(testAddress,
428                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
429         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
430         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
431         testAddress.setValidationState("state5");
432         dictionaryValidationResult = service.validate(testAddress,
433                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
434         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
435         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
436 
437         testAddress.setValidationState("state1");
438         testAddress.setStreet2("");
439         dictionaryValidationResult = service.validate(testAddress,
440                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
441         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
442         Assert.assertEquals(1, dictionaryValidationResult.getNumberOfErrors());
443         testAddress.setValidationState("state5");
444         dictionaryValidationResult = service.validate(testAddress,
445                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
446         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
447         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
448 
449         testAddress.setValidationState("state2");
450         testAddress.setCountry("USA");
451         testAddress.setStreet2("");
452         dictionaryValidationResult = service.validate(testAddress,
453                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
454         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
455         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
456         testAddress.setValidationState("state5");
457         dictionaryValidationResult = service.validate(testAddress,
458                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
459         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
460         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
461 
462     }
463 
464     /**
465      * Tests for state based validation using a MustOccurs constraint.
466      *
467      * @throws IOException
468      */
469     @Test
470     public void testStateValidationForMustOccurs() throws IOException {
471         Address testAddress = new Address("893 Presidential Ave", "Suite 800", "Washington", "DC", "12031", "Country",
472                 null);
473 
474         //Correct address
475         testAddress.setValidationState("state1");
476         DictionaryValidationResult dictionaryValidationResult = service.validate(testAddress,
477                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
478         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
479 
480         testAddress.setValidationState("state2");
481         dictionaryValidationResult = service.validate(testAddress,
482                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
483         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
484 
485         //no error state1, 1 error state2 because mustOccurs applies
486         testAddress.setPostalCode("");
487         testAddress.setState("");
488         testAddress.setValidationState("state1");
489         dictionaryValidationResult = service.validate(testAddress,
490                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
491         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
492 
493         testAddress.setValidationState("state2");
494         dictionaryValidationResult = service.validate(testAddress,
495                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
496         Assert.assertEquals(1, dictionaryValidationResult.getNumberOfErrors());
497 
498         //Valid for both states
499         testAddress.setPostalCode("");
500         testAddress.setState("CA");
501         testAddress.setValidationState("state1");
502         dictionaryValidationResult = service.validate(testAddress,
503                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
504         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
505 
506         testAddress.setValidationState("state2");
507         dictionaryValidationResult = service.validate(testAddress,
508                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
509         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
510 
511         //Valid for both states
512         testAddress.setPostalCode("23456");
513         testAddress.setState("");
514         testAddress.setValidationState("state1");
515         dictionaryValidationResult = service.validate(testAddress,
516                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
517         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
518 
519         testAddress.setValidationState("state2");
520         dictionaryValidationResult = service.validate(testAddress,
521                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
522         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
523 
524     }
525 
526     /**
527      * Testing of stateConstraintOverrides for multiple different cases
528      *
529      * @throws IOException
530      */
531     @Test
532     public void testStateValidationConstraintOverrides() throws IOException {
533         Address testAddress = new Address("893 Presidential Ave", "Suite 800", "Washington", "DC", "12031", "USA",
534                 null);
535 
536         //alphaNumeric
537         testAddress.setStreet2("123AAAAA123");
538         testAddress.setValidationState("state2");
539         DictionaryValidationResult dictionaryValidationResult = service.validate(testAddress,
540                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
541         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
542         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
543 
544         testAddress.setValidationState("state3");
545         dictionaryValidationResult = service.validate(testAddress,
546                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
547         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
548         Assert.assertEquals(1, dictionaryValidationResult.getNumberOfErrors());
549 
550         testAddress.setValidationState("state4");
551         dictionaryValidationResult = service.validate(testAddress,
552                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
553         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
554         Assert.assertEquals(1, dictionaryValidationResult.getNumberOfErrors());
555 
556         //Numeric
557         testAddress.setStreet2("1111");
558         testAddress.setValidationState("state2");
559         dictionaryValidationResult = service.validate(testAddress,
560                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
561         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
562         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
563         testAddress.setValidationState("state3");
564         dictionaryValidationResult = service.validate(testAddress,
565                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
566         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
567         Assert.assertEquals(1, dictionaryValidationResult.getNumberOfErrors());
568         testAddress.setValidationState("state4");
569         dictionaryValidationResult = service.validate(testAddress,
570                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
571         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
572         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
573 
574         //Alpha
575         testAddress.setStreet2("BBBB");
576         testAddress.setValidationState("state2");
577         dictionaryValidationResult = service.validate(testAddress,
578                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
579         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
580         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
581         testAddress.setValidationState("state3");
582         dictionaryValidationResult = service.validate(testAddress,
583                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
584         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
585         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
586         testAddress.setValidationState("state4");
587         dictionaryValidationResult = service.validate(testAddress,
588                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
589         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
590         Assert.assertEquals(1, dictionaryValidationResult.getNumberOfErrors());
591 
592         //no constraint applies in state5
593         testAddress.setStreet2("$%@");
594         testAddress.setValidationState("state5");
595         dictionaryValidationResult = service.validate(testAddress,
596                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
597         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfWarnings());
598         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
599 
600     }
601 
602     /**
603      * Testing state based validation state ranges, "ie state2>state4" and using prerequisite constraints
604      *
605      * @throws IOException
606      */
607     @Test
608     public void testStateRangeValidationForPrerequisite() throws IOException {
609         Address testAddress = new Address("893 Presidential Ave", "Suite 800", "Washington", "DC", "12031", "USA",
610                 null);
611 
612         testAddress.setValidationState("state1");
613         DictionaryValidationResult dictionaryValidationResult = service.validate(testAddress,
614                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
615         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
616 
617         testAddress.setValidationState("state2");
618         dictionaryValidationResult = service.validate(testAddress,
619                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
620         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
621 
622         //state2-state4 should get errors with no country
623         testAddress.setCity("City");
624         testAddress.setCountry("");
625         testAddress.setValidationState("state1");
626         dictionaryValidationResult = service.validate(testAddress,
627                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
628         Assert.assertEquals(1, dictionaryValidationResult.getNumberOfErrors());
629         testAddress.setValidationState("state2");
630         dictionaryValidationResult = service.validate(testAddress,
631                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
632         Assert.assertEquals(2, dictionaryValidationResult.getNumberOfErrors());
633         testAddress.setValidationState("state3");
634         dictionaryValidationResult = service.validate(testAddress,
635                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
636         Assert.assertEquals(3, dictionaryValidationResult.getNumberOfErrors());
637         testAddress.setValidationState("state4");
638         dictionaryValidationResult = service.validate(testAddress,
639                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
640         Assert.assertEquals(3, dictionaryValidationResult.getNumberOfErrors());
641         testAddress.setValidationState("state5");
642         dictionaryValidationResult = service.validate(testAddress,
643                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
644         Assert.assertEquals(1, dictionaryValidationResult.getNumberOfErrors());
645 
646         //should be no errors at any state with both blank
647         testAddress.setCity("");
648         testAddress.setCountry("");
649         testAddress.setValidationState("state1");
650         dictionaryValidationResult = service.validate(testAddress,
651                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
652         Assert.assertEquals(1, dictionaryValidationResult.getNumberOfErrors());
653         testAddress.setValidationState("state2");
654         dictionaryValidationResult = service.validate(testAddress,
655                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
656         Assert.assertEquals(1, dictionaryValidationResult.getNumberOfErrors());
657         testAddress.setValidationState("state3");
658         dictionaryValidationResult = service.validate(testAddress,
659                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
660         Assert.assertEquals(2, dictionaryValidationResult.getNumberOfErrors());
661         testAddress.setValidationState("state4");
662         dictionaryValidationResult = service.validate(testAddress,
663                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
664         Assert.assertEquals(2, dictionaryValidationResult.getNumberOfErrors());
665         testAddress.setValidationState("state5");
666         dictionaryValidationResult = service.validate(testAddress,
667                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
668         Assert.assertEquals(1, dictionaryValidationResult.getNumberOfErrors());
669 
670     }
671 
672     @Test
673     public void testStateValidationSimpleConstraintWithOverrides(){
674         Address testAddress = new Address("893 Presidential Ave", "Suite 800", "Washington", "DC", "12031", "USA",
675                         null);
676 
677         testAddress.setValidationState("state1");
678         DictionaryValidationResult dictionaryValidationResult = service.validate(testAddress,
679                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
680         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
681 
682         //36 length should apply at state1
683         testAddress.setState("1234567890123456789012345678901234567");
684         dictionaryValidationResult = service.validate(testAddress,
685                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
686         Assert.assertEquals(1, dictionaryValidationResult.getNumberOfErrors());
687         
688         //correct format for state at state5
689         testAddress.setValidationState("state5");
690         testAddress.setState("DC");
691         dictionaryValidationResult = service.validate(testAddress,
692                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
693         Assert.assertEquals(0, dictionaryValidationResult.getNumberOfErrors());
694         
695         //state is required at state5 should have error
696         testAddress.setState("");
697         dictionaryValidationResult = service.validate(testAddress,
698                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
699         Assert.assertEquals(2, dictionaryValidationResult.getNumberOfErrors());
700 
701         //too long
702         testAddress.setState("fff");
703         dictionaryValidationResult = service.validate(testAddress,
704                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
705         Assert.assertEquals(1, dictionaryValidationResult.getNumberOfErrors());
706 
707         //too short
708         testAddress.setState("f");
709         dictionaryValidationResult = service.validate(testAddress,
710                 "org.kuali.rice.kns.datadictionary.validation.MockAddress", addressEntry, true);
711         Assert.assertEquals(1, dictionaryValidationResult.getNumberOfErrors());
712     }
713 
714     /**
715      * checks whether a {@link DictionaryValidationResult} contains errors for a named attribute
716      *
717      * @param dvr - the dictionary validation result
718      * @param attributeName - the attribute whose validation errors are being checked
719      * @param errorKey - a constant that retrieves an informational message to display to the user
720      * @return true if an error with the error key has been found for the attribute, false otherwise
721      */
722     protected boolean hasError(DictionaryValidationResult dvr, String attributeName, String errorKey) {
723         Iterator<ConstraintValidationResult> dvrIterator = dvr.iterator();
724 
725         boolean containsError = false;
726         while (dvrIterator.hasNext() && !containsError) {
727             ConstraintValidationResult cvr = dvrIterator.next();
728             if (attributeName.contains("[")) {
729                 containsError = attributeName.equals(cvr.getAttributePath())
730                         && errorKey.equals(cvr.getErrorKey())
731                         && ErrorLevel.ERROR == cvr.getStatus();
732             } else {
733                 containsError = attributeName.equals(cvr.getAttributeName())
734                         && errorKey.equals(cvr.getErrorKey())
735                         && ErrorLevel.ERROR == cvr.getStatus();
736             }
737         }
738 
739         return containsError;
740     }
741 
742 }