View Javadoc

1   /**
2    * Copyright 2005-2012 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.util;
17  
18  import org.junit.Test;
19  import org.kuali.rice.core.api.util.RiceKeyConstants;
20  import org.springframework.util.AutoPopulatingList;
21  
22  import java.util.Arrays;
23  import java.util.HashSet;
24  import java.util.Iterator;
25  import java.util.Map;
26  import java.util.Set;
27  
28  import static org.junit.Assert.*;
29  
30  /**
31   * This class tests the ErrorMap methods.
32   */
33  public class MessageMapTest {
34  
35      /**
36       * ErrorMap should only allow String keys and values.
37       */
38      @Test public void testPut() {
39          MessageMap testMap = new MessageMap();
40  
41          // should be ok putting strings
42          try {
43              testMap.putError("accountNbr", RiceKeyConstants.ERROR_INACTIVE);
44          }
45          catch (RuntimeException e) {
46              fail("ErrorMap threw exception adding string pair");
47          }
48      }
49  
50      /**
51       * Test all errors are getting added and counted correctly.
52       */
53      @Test public void testErrorCount() {
54      	MessageMap testMap = new MessageMap();
55  
56          testMap.putError("accountNbr", RiceKeyConstants.ERROR_INACTIVE);
57          assertTrue(testMap.getErrorCount() == 1);
58  
59          testMap.putError("accountNbr", RiceKeyConstants.ERROR_INVALID_FORMAT);
60          assertTrue(testMap.getErrorCount() == 2);
61  
62          testMap.putError("chartCode", RiceKeyConstants.ERROR_INVALID_FORMAT);
63          testMap.putError("projectCode", RiceKeyConstants.ERROR_INVALID_FORMAT);
64          testMap.putError("objectCode", RiceKeyConstants.ERROR_INVALID_FORMAT);
65          assertTrue(testMap.getErrorCount() == 5);
66  
67          testMap.removeAllErrorMessagesForProperty("accountNbr");
68          assertTrue(testMap.getErrorCount() == 3);
69      }
70  
71      /**
72       * Test messages are getting accumulated correctly for a property.
73       */
74      @Test public void testFieldMessages() {
75      	MessageMap testMap = new MessageMap();
76  
77          testMap.putError("accountNbr", RiceKeyConstants.ERROR_INACTIVE);
78          testMap.putError("accountNbr", RiceKeyConstants.ERROR_INVALID_FORMAT);
79          testMap.putError("accountNbr", RiceKeyConstants.ERROR_PHONE_NUMBER);
80          assertEquals(3, testMap.countFieldMessages("accountNbr"));
81          assertTrue(testMap.fieldHasMessage("accountNbr", RiceKeyConstants.ERROR_INACTIVE));
82          assertTrue(testMap.fieldHasMessage("accountNbr", RiceKeyConstants.ERROR_INVALID_FORMAT));
83          assertTrue(testMap.fieldHasMessage("accountNbr", RiceKeyConstants.ERROR_PHONE_NUMBER));
84      }
85  
86      /**
87       * Test the error path is being prepended.
88       */
89      @Test public void testErrorPath() {
90      	MessageMap testMap = new MessageMap();
91  
92          assertTrue(testMap.getKeyPath("accountNbr", true).equals("accountNbr"));
93          testMap.addToErrorPath("document");
94          assertTrue(testMap.getKeyPath("accountNbr", true).equals("document.accountNbr"));
95          assertTrue(testMap.getKeyPath("accountNbr", false).equals("accountNbr"));
96          testMap.removeFromErrorPath("document");
97          assertTrue(testMap.getKeyPath("accountNbr", true).equals("accountNbr"));
98          assertTrue(testMap.getKeyPath("accountNbr", false).equals("accountNbr"));
99          testMap.addToErrorPath("document");
100         testMap.addToErrorPath("newAccountingLine");
101         assertTrue(testMap.getKeyPath("accountNbr", true).equals("document.newAccountingLine.accountNbr"));
102         assertTrue(testMap.getKeyPath("accountNbr", false).equals("accountNbr"));
103 
104         testMap.putError("accountNbr", RiceKeyConstants.ERROR_INACTIVE);
105         assertEquals(1, testMap.countFieldMessages("document.newAccountingLine.accountNbr"));
106         assertTrue(testMap.fieldHasMessage("document.newAccountingLine.accountNbr", RiceKeyConstants.ERROR_INACTIVE));
107 
108         // global key should not be prepended with key path
109         assertTrue(testMap.getKeyPath(KRADConstants.GLOBAL_ERRORS, true).equals(KRADConstants.GLOBAL_ERRORS));
110 
111         assertTrue(testMap.getKeyPath("projectCode.code", true).equals("document.newAccountingLine.projectCode.code"));
112         testMap.removeFromErrorPath("newAccountingLine");
113         assertTrue(testMap.getKeyPath("accountNbr", true).equals("document.accountNbr"));
114         testMap.removeFromErrorPath("document");
115         assertTrue(testMap.getKeyPath("accountNbr", true).equals("accountNbr"));
116     }
117 
118     /**
119      * Test that properties added with errors are being kept.
120      */
121     @Test public void testPropertiesWithErrors() {
122     	MessageMap testMap = new MessageMap();
123 
124         testMap.putError("accountNbr", RiceKeyConstants.ERROR_INACTIVE);
125         testMap.putError("projectCode", RiceKeyConstants.ERROR_INACTIVE);
126         testMap.putError("chartCode", RiceKeyConstants.ERROR_INACTIVE);
127         testMap.putError("objectCode", RiceKeyConstants.ERROR_INACTIVE);
128         testMap.putError("subAccountNbr", RiceKeyConstants.ERROR_INACTIVE);
129 
130         assertTrue(testMap.getPropertiesWithErrors().contains("accountNbr"));
131         assertTrue(testMap.getPropertiesWithErrors().contains("projectCode"));
132         assertTrue(testMap.getPropertiesWithErrors().contains("chartCode"));
133         assertTrue(testMap.getPropertiesWithErrors().contains("objectCode"));
134         assertTrue(testMap.getPropertiesWithErrors().contains("subAccountNbr"));
135     }
136 
137     /**
138      * Test message parameters are being correctly added and associated with an error message.
139      */
140     @Test public void testMessageParameters() {
141     	MessageMap testMap = new MessageMap();
142 
143         testMap.putError("accountNbr", RiceKeyConstants.ERROR_INACTIVE, "Account Number");
144         testMap.putError("accountNbr", RiceKeyConstants.ERROR_REQUIRED, "Account Number");
145         // check duplicate message doesn't get added
146         testMap.putError("accountNbr", RiceKeyConstants.ERROR_INACTIVE, "Account Number");
147         testMap.putError("chartCode", RiceKeyConstants.ERROR_REQUIRED, "Chart Code");
148 
149         assertEquals(3, testMap.getErrorCount());
150 
151         AutoPopulatingList errorMessages = testMap.getMessages("accountNbr");
152         assertEquals(2, errorMessages.size());
153         checkMessageParemeters(errorMessages, 0, RiceKeyConstants.ERROR_INACTIVE, new String[] { "Account Number" });
154         checkMessageParemeters(errorMessages, 1, RiceKeyConstants.ERROR_REQUIRED, new String[] { "Account Number" });
155 
156         errorMessages = testMap.getMessages("chartCode");
157         assertEquals(1, errorMessages.size());
158         checkMessageParemeters(errorMessages, 0, RiceKeyConstants.ERROR_REQUIRED, new String[] { "Chart Code" });
159     }
160 
161     private void checkMessageParemeters(AutoPopulatingList errorMessages, int messageIndex, String expectedKeyConstant, String[] expectedParameters) {
162         ErrorMessage message1 = (ErrorMessage) errorMessages.get(messageIndex);
163         assertEquals(expectedKeyConstant, message1.getErrorKey());
164         assertTrue(Arrays.equals(message1.getMessageParameters(), expectedParameters));
165     }
166 
167     /**
168      * Verify that using the same error message multiple times correctly stores different parameters each time. (Reproduces bug
169      * KULNRVSYS-943).
170      */
171     @Test public void testMessageCollisions() {
172         final String PROPERTY_NAME = "document.sourceAccounting*,document.targetAccounting*,newSourceLine*,newTargetLine*";
173         MessageMap testMap = new MessageMap();
174 
175         testMap.putError(PROPERTY_NAME, "error.inactive", "Chart Code");
176         testMap.putError(PROPERTY_NAME, "error.document.subAccountClosed", "Sub-Account Number");
177         testMap.putError(PROPERTY_NAME, "error.inactive", "Object Code");
178         testMap.putError(PROPERTY_NAME, "error.inactive", "SubObject Code");
179         testMap.putError(PROPERTY_NAME, "error.inactive", "Project Code");
180 
181         assertEquals(5, testMap.getErrorCount());
182 
183         // retrieve error messages for the one known key
184         Object thing = testMap.getErrorMessagesForProperty(PROPERTY_NAME);
185 
186         Set usedParams = new HashSet();
187         for (Iterator i = testMap.getAllPropertiesAndErrors().iterator(); i.hasNext();) {
188             Map.Entry entry = (Map.Entry) i.next();
189 
190             String propertyKey = (String) entry.getKey();
191             AutoPopulatingList messageList = (AutoPopulatingList) entry.getValue();
192             for (Iterator j = messageList.iterator(); j.hasNext();) {
193                 ErrorMessage message = (ErrorMessage) j.next();
194 
195                 String[] params = message.getMessageParameters();
196                 if (usedParams.contains(params)) {
197                     fail("usedParams contains duplicate parameters object '" + params + "'");
198                 }
199                 usedParams.add(params);
200             }
201         }
202     }
203 
204     private final static String MIXED_LIST_PATTERN = "document.sourceAccounting*,document.targetAccounting*,foo,bar,newSourceLine*,newTargetLine*";
205 
206     @Test public void testContainsKeyMatchingPattern_mixedList_empty() {
207         assertEquals(false, new MessageMap().containsKeyMatchingPattern(MIXED_LIST_PATTERN));
208     }
209 
210     @Test public void testContainsKeyMatchingPattern_mixedList_simpleNoMatch() {
211     	MessageMap testMap = new MessageMap();
212         testMap.putError("xxx", "error.inactive", "Chart Code");
213         testMap.putError("yyy", "error.inactive", "Chart Code");
214         assertEquals(false, testMap.containsKeyMatchingPattern(MIXED_LIST_PATTERN));
215     }
216 
217     @Test public void testContainsKeyMatchingPattern_mixedList_simpleMatch() {
218     	MessageMap testMap = new MessageMap();
219         testMap.putError("xxx", "error.inactive", "Chart Code");
220         testMap.putError("foo", "error.inactive", "Chart Code");
221         testMap.putError("yyy", "error.inactive", "Chart Code");
222         assertEquals(true, testMap.containsKeyMatchingPattern(MIXED_LIST_PATTERN));
223     }
224 
225     @Test public void testContainsKeyMatchingPattern_mixedList_wildcardMatch() {
226     	MessageMap testMap = new MessageMap();
227         testMap.putError("xxx", "error.inactive", "Chart Code");
228         testMap.putError("document.targetAccountingLine.something", "error.inactive", "Chart Code");
229         testMap.putError("yyy", "error.inactive", "Chart Code");
230         assertEquals(true, testMap.containsKeyMatchingPattern(MIXED_LIST_PATTERN));
231     }
232 
233 
234     @Test public void testReplace_testEquals() {
235         final MessageMap constantMap = buildReplaceErrorMap();
236         MessageMap replaceMap = buildReplaceErrorMap();
237 
238         assertEquals(replaceMap, replaceMap);
239         assertEquals(replaceMap, constantMap);
240         assertEquals(constantMap, replaceMap);
241 
242         replaceMap.putError("somethingElse", RiceKeyConstants.ERROR_INACTIVE, "Account Number");
243 
244         assertFalse(replaceMap.equals(constantMap));
245     }
246 
247 
248     @Test public void testReplace_noMatchingProperty() {
249         final MessageMap constantMap = buildReplaceErrorMap();
250         MessageMap replaceMap = buildReplaceErrorMap();
251 
252         assertTrue(replaceMap.equals(constantMap));
253         assertFalse(replaceMap.containsMessageKey("fooKey"));
254 
255         boolean replaced = replaceMap.replaceError("fooName", "fooKey", "fooReplaceKey");
256         assertFalse(replaced);
257 
258         assertTrue(replaceMap.equals(constantMap));
259         assertFalse(replaceMap.containsMessageKey("fooKey"));
260     }
261 
262     @Test public void testReplace_matchingProperty_noMatchingKey() {
263         final MessageMap constantMap = buildReplaceErrorMap();
264         MessageMap replaceMap = buildReplaceErrorMap();
265 
266         assertTrue(replaceMap.equals(constantMap));
267         assertFalse(replaceMap.containsMessageKey("fooKey"));
268 
269         boolean replaced = replaceMap.replaceError("accountNbr", "fooKey", "fooReplaceKey");
270         assertFalse(replaced);
271 
272         assertTrue(replaceMap.equals(constantMap));
273         assertFalse(replaceMap.containsMessageKey("fooKey"));
274     }
275 
276 
277     @Test public void testReplace_matchingProperty_matchingKey_noParams() {
278         final MessageMap constantMap = buildReplaceErrorMap();
279         MessageMap replaceMap = buildReplaceErrorMap();
280 
281         assertTrue(replaceMap.equals(constantMap));
282         assertTrue(replaceMap.containsMessageKey(RiceKeyConstants.ERROR_INACTIVE));
283         assertFalse(replaceMap.containsMessageKey(RiceKeyConstants.ERROR_NOT_AMONG));
284 
285         AutoPopulatingList preMessages = replaceMap.getMessages("accountNbr");
286         assertEquals(2, preMessages.size());
287 
288         boolean replaced = replaceMap.replaceError("accountNbr", RiceKeyConstants.ERROR_INACTIVE, RiceKeyConstants.ERROR_NOT_AMONG);
289         assertTrue(replaced);
290 
291         assertFalse(replaceMap.equals(constantMap));
292         assertFalse(replaceMap.containsMessageKey(RiceKeyConstants.ERROR_INACTIVE));
293         assertTrue(replaceMap.containsMessageKey(RiceKeyConstants.ERROR_NOT_AMONG));
294 
295         AutoPopulatingList postMessages = replaceMap.getMessages("accountNbr");
296         assertEquals(2, postMessages.size());
297 
298         int replacedCount = 0;
299         for (Iterator i = postMessages.iterator(); i.hasNext();) {
300             ErrorMessage em = (ErrorMessage) i.next();
301             if (em.getErrorKey().equals(RiceKeyConstants.ERROR_NOT_AMONG)) {
302                 String[] params = em.getMessageParameters();
303                 assertEquals(0, params.length);
304 
305                 ++replacedCount;
306             }
307         }
308         assertEquals(1, replacedCount);
309     }
310 
311     @Test public void testReplace_matchingProperty_matchingKey_withParams() {
312         final MessageMap constantMap = buildReplaceErrorMap();
313         MessageMap replaceMap = buildReplaceErrorMap();
314 
315         assertTrue(replaceMap.equals(constantMap));
316         assertTrue(replaceMap.containsMessageKey(RiceKeyConstants.ERROR_INACTIVE));
317         assertFalse(replaceMap.containsMessageKey(RiceKeyConstants.ERROR_NOT_AMONG));
318 
319         AutoPopulatingList preMessages = replaceMap.getMessages("accountNbr");
320         assertEquals(2, preMessages.size());
321 
322         boolean replaced = replaceMap.replaceError("accountNbr", RiceKeyConstants.ERROR_INACTIVE, RiceKeyConstants.ERROR_NOT_AMONG, "zero", "one");
323         assertTrue(replaced);
324 
325         assertFalse(replaceMap.equals(constantMap));
326         assertFalse(replaceMap.containsMessageKey(RiceKeyConstants.ERROR_INACTIVE));
327         assertTrue(replaceMap.containsMessageKey(RiceKeyConstants.ERROR_NOT_AMONG));
328 
329         AutoPopulatingList postMessages = replaceMap.getMessages("accountNbr");
330         assertEquals(2, postMessages.size());
331 
332         int replacedCount = 0;
333         for (Iterator i = postMessages.iterator(); i.hasNext();) {
334             ErrorMessage em = (ErrorMessage) i.next();
335             if (em.getErrorKey().equals(RiceKeyConstants.ERROR_NOT_AMONG)) {
336                 String[] params = em.getMessageParameters();
337                 assertEquals(2, params.length);
338                 assertEquals("zero", params[0]);
339                 assertEquals("one", params[1]);
340 
341                 ++replacedCount;
342             }
343         }
344         assertEquals(1, replacedCount);
345     }
346 
347 
348     private MessageMap buildReplaceErrorMap() {
349     	MessageMap testMap = new MessageMap();
350 
351         testMap.putError("accountNbr", RiceKeyConstants.ERROR_INACTIVE, "Account Number");
352         testMap.putError("accountNbr", RiceKeyConstants.ERROR_REQUIRED, "Account Number");
353         testMap.putError("chartCode", RiceKeyConstants.ERROR_REQUIRED, "Chart Code");
354 
355         return testMap;
356     }
357 }