View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.beanutils.converters;
18  
19  import java.lang.reflect.Array;
20  import java.util.ArrayList;
21  import java.util.Locale;
22  
23  import junit.framework.TestCase;
24  import junit.framework.TestSuite;
25  
26  /**
27   * Test Case for the ArrayConverter class.
28   *
29   * @version $Id$
30   */
31  public class ArrayConverterTestCase extends TestCase {
32  
33      /**
34       * Construct a new Array Converter test case.
35       * @param name Test Name
36       */
37      public ArrayConverterTestCase(final String name) {
38          super(name);
39      }
40  
41      // ------------------------------------------------------------------------
42  
43      /**
44       * Create Test Suite
45       * @return test suite
46       */
47      public static TestSuite suite() {
48          return new TestSuite(ArrayConverterTestCase.class);
49      }
50  
51      /** Set Up */
52      @Override
53      public void setUp() throws Exception {
54      }
55  
56      /** Tear Down */
57      @Override
58      public void tearDown() throws Exception {
59      }
60  
61  
62      // ------------------------------------------------------------------------
63  
64      /**
65       * Test Converting using the IntegerConverter as the component Converter
66       */
67      public void testComponentIntegerConverter() {
68  
69          final IntegerConverter intConverter = new IntegerConverter(new Integer(0));
70          intConverter.setPattern("#,###");
71          intConverter.setLocale(Locale.US);
72          final ArrayConverter arrayConverter = new ArrayConverter(int[].class, intConverter, 0);
73          arrayConverter.setAllowedChars(new char[] {',', '-'});
74          arrayConverter.setDelimiter(';');
75  
76          // Expected results
77          final int[]     intArray     = new int[] {1111, 2222, 3333, 4444};
78          final String    stringA      = "1,111; 2,222; 3,333; 4,444";
79          final String    stringB      = intArray[0]+ ";" + intArray[1] + ";" + intArray[2] + ";" +intArray[3];
80          final String[]  strArray     = new String[] {""+intArray[0], ""+intArray[1], ""+intArray[2], ""+intArray[3]};
81          final long[]    longArray    = new long[] {intArray[0], intArray[1], intArray[2], intArray[3]};
82          final Long[]    LONGArray    = new Long[]    {new Long(intArray[0]),    new Long(intArray[1]),    new Long(intArray[2]),    new Long(intArray[3])};
83          final Integer[] IntegerArray = new Integer[] {new Integer(intArray[0]), new Integer(intArray[1]), new Integer(intArray[2]), new Integer(intArray[3])};
84          final ArrayList<String> strList = new ArrayList<String>();
85          final ArrayList<Long> longList = new ArrayList<Long>();
86          for (int i = 0; i < strArray.length; i++) {
87              strList.add(strArray[i]);
88              longList.add(LONGArray[i]);
89          }
90  
91  
92          String msg = null;
93  
94          // String --> int[]
95          try {
96              msg = "String --> int[]";
97              checkArray(msg, intArray, arrayConverter.convert(int[].class, stringA));
98          } catch (final Exception e) {
99              fail(msg + " failed " + e);
100         }
101 
102         // String --> int[] (with braces)
103         try {
104             msg = "String --> Integer[] (with braces)";
105             checkArray(msg, IntegerArray, arrayConverter.convert(Integer[].class, "{" + stringA + "}"));
106         } catch (final Exception e) {
107             fail(msg + " failed " + e);
108         }
109 
110         // String[] --> int[]
111         try {
112             msg = "String[] --> int[]";
113             checkArray(msg, intArray, arrayConverter.convert(int[].class, strArray));
114         } catch (final Exception e) {
115             fail(msg + " failed " + e);
116         }
117 
118         // String[] --> Integer[]
119         try {
120             msg = "String[] --> Integer[]";
121             checkArray(msg, IntegerArray, arrayConverter.convert(Integer[].class, strArray));
122         } catch (final Exception e) {
123             fail(msg + " failed " + e);
124         }
125 
126         // long[] --> int[]
127         try {
128             msg = "long[] --> int[]";
129             checkArray(msg, intArray, arrayConverter.convert(int[].class, longArray));
130         } catch (final Exception e) {
131             fail(msg + " failed " + e);
132         }
133 
134         // Long --> int[]
135         try {
136             msg = "Long --> int[]";
137             checkArray(msg, new int[] {LONGArray[0].intValue()}, arrayConverter.convert(int[].class, LONGArray[0]));
138         } catch (final Exception e) {
139             fail(msg + " failed " + e);
140         }
141 
142         // LONG[] --> int[]
143         try {
144             msg = "LONG[] --> int[]";
145             checkArray(msg, intArray, arrayConverter.convert(int[].class, LONGArray));
146         } catch (final Exception e) {
147             fail(msg + " failed " + e);
148         }
149 
150         // Long --> String
151         try {
152             msg = "Long --> String";
153             assertEquals(msg, LONGArray[0] + "", arrayConverter.convert(String.class, LONGArray[0]));
154         } catch (final Exception e) {
155             fail(msg + " failed " + e);
156         }
157 
158         // LONG[] --> String (first)
159         try {
160             msg = "LONG[] --> String (first)";
161             assertEquals(msg, LONGArray[0] + "", arrayConverter.convert(String.class, LONGArray));
162         } catch (final Exception e) {
163             fail(msg + " failed " + e);
164         }
165 
166         // LONG[] --> String (all)
167         try {
168             msg = "LONG[] --> String (all)";
169             arrayConverter.setOnlyFirstToString(false);
170             assertEquals(msg, stringB, arrayConverter.convert(String.class, LONGArray));
171         } catch (final Exception e) {
172             fail(msg + " failed " + e);
173         }
174 
175         // Collection of Long --> String
176         try {
177             msg = "Collection of Long --> String";
178             assertEquals(msg, stringB, arrayConverter.convert(String.class, longList));
179         } catch (final Exception e) {
180             fail(msg + " failed " + e);
181         }
182 
183         // LONG[] --> String[]
184         try {
185             msg = "long[] --> String[]";
186             checkArray(msg, strArray, arrayConverter.convert(String[].class, LONGArray));
187         } catch (final Exception e) {
188             fail(msg + " failed " + e);
189         }
190 
191         // Collection of String --> Integer[]
192         try {
193             msg = "Collection of String --> Integer[]";
194             checkArray(msg, IntegerArray, arrayConverter.convert(Integer[].class, strList));
195         } catch (final Exception e) {
196             fail(msg + " failed " + e);
197         }
198 
199         // Collection of Long --> int[]
200         try {
201             msg = "Collection of Long --> int[]";
202             checkArray(msg, intArray, arrayConverter.convert(int[].class, longList));
203         } catch (final Exception e) {
204             fail(msg + " failed " + e);
205         }
206     }
207 
208     /**
209      * Test Converting a String[] to integer array (with leading/trailing whitespace)
210      */
211     public void testStringArrayToNumber() {
212 
213         // Configure Converter
214         final IntegerConverter intConverter = new IntegerConverter();
215         final ArrayConverter arrayConverter = new ArrayConverter(int[].class, intConverter);
216 
217         // Test Data
218         final String[] array = new String[] {"10", "  11", "12  ", "  13  "};
219         final ArrayList<String> list = new ArrayList<String>();
220         for (String element : array) {
221             list.add(element);
222         }
223 
224         // Expected results
225         String msg = null;
226         final int[]     expectedInt     = new int[] {10, 11, 12, 13};
227         final Integer[] expectedInteger = new Integer[] {new Integer(expectedInt[0]), new Integer(expectedInt[1]), new Integer(expectedInt[2]), new Integer(expectedInt[3])};
228 
229         // Test String[] --> int[]
230         try {
231             msg = "String[] --> int[]";
232             checkArray(msg, expectedInt, arrayConverter.convert(int[].class, array));
233         } catch (final Exception e) {
234             fail(msg + " failed " + e);
235         }
236 
237         // Test String[] --> Integer[]
238         try {
239             msg = "String[] --> Integer[]";
240             checkArray(msg, expectedInteger, arrayConverter.convert(Integer[].class, array));
241         } catch (final Exception e) {
242             fail(msg + " failed " + e);
243         }
244 
245         // Test List --> int[]
246         try {
247             msg = "List --> int[]";
248             checkArray(msg, expectedInt, arrayConverter.convert(int[].class, list));
249         } catch (final Exception e) {
250             fail(msg + " failed " + e);
251         }
252 
253         // Test List --> Integer[]
254         try {
255             msg = "List --> Integer[]";
256             checkArray(msg, expectedInteger, arrayConverter.convert(Integer[].class, list));
257         } catch (final Exception e) {
258             fail(msg + " failed " + e);
259         }
260    }
261 
262     /**
263      * Test the Matrix!!!! (parses a String into a 2 dimensional integer array or matrix)
264      */
265     public void testTheMatrix() {
266 
267         // Test Date - create the Matrix!!
268         // Following String uses two delimiter:
269         //     - comma (",") to separate individual numbers
270         //     - semi-colon (";") to separate lists of numbers
271         final String matrixString = "11,12,13 ; 21,22,23 ; 31,32,33 ; 41,42,43";
272         final int[][] expected = new int[][] {new int[] {11, 12, 13},
273                                         new int[] {21, 22, 23},
274                                         new int[] {31, 32, 33},
275                                         new int[] {41, 42, 43}};
276 
277         // Construct an Integer Converter
278         final IntegerConverter integerConverter = new IntegerConverter();
279 
280         // Construct an array Converter for an integer array (i.e. int[]) using
281         // an IntegerConverter as the element converter.
282         // N.B. Uses the default comma (i.e. ",") as the delimiter between individual numbers
283         final ArrayConverter arrayConverter = new ArrayConverter(int[].class, integerConverter);
284 
285         // Construct a "Matrix" Converter which converts arrays of integer arrays using
286         // the first (int[]) Converter as the element Converter.
287         // N.B. Uses a semi-colon (i.e. ";") as the delimiter to separate the different sets of numbers.
288         //      Also the delimiter for the above array Converter needs to be added to this
289         //      array Converter's "allowed characters"
290         final ArrayConverter matrixConverter = new ArrayConverter(int[][].class, arrayConverter);
291         matrixConverter.setDelimiter(';');
292         matrixConverter.setAllowedChars(new char[] {','});
293 
294         try {
295             // Do the Conversion
296             final Object result = matrixConverter.convert(int[][].class, matrixString);
297 
298             // Check it actually worked OK
299             assertEquals("Check int[][].class", int[][].class, result.getClass());
300             final int[][] matrix = (int[][])result;
301             assertEquals("Check int[][] length", expected.length, matrix.length);
302             for (int i = 0; i < expected.length; i++) {
303                 assertEquals("Check int[" + i + "] length", expected[i].length, matrix[i].length);
304                 for (int j = 0; j < expected[i].length; j++) {
305                     final String label = "Matrix int[" + i + "," + j + "] element";
306                     assertEquals(label, expected[i][j], matrix[i][j]);
307                     // System.out.println(label + " = " + matrix[i][j]);
308                 }
309             }
310         } catch (final Exception e) {
311             fail("Matrix Conversion threw " + e);
312         }
313     }
314 
315     /**
316      * Test Converting using the IntegerConverter as the component Converter
317      */
318     public void testInvalidWithDefault() {
319         final int[]  zeroArray  = new int[0];
320         final int[]  oneArray   = new int[1];
321         final IntegerConverter intConverter = new IntegerConverter();
322 
323         assertEquals("Null Default", null,   new ArrayConverter(int[].class, intConverter, -1).convert(int[].class, null));
324         checkArray("Zero Length",  zeroArray, new ArrayConverter(int[].class, intConverter, 0).convert(int[].class, null));
325         checkArray("One Length",   oneArray,  new ArrayConverter(Integer[].class, intConverter, 1).convert(int[].class, null));
326     }
327 
328     /**
329      * Test Empty String
330      */
331     public void testEmptyString() {
332         final int[]  zeroArray  = new int[0];
333         final IntegerConverter intConverter = new IntegerConverter();
334 
335         checkArray("Empty String",  zeroArray, new ArrayConverter(int[].class, intConverter, -1).convert(int[].class, ""));
336         assertEquals("Default String",  null, new ArrayConverter(int[].class, intConverter).convert(String.class, null));
337     }
338 
339     /**
340      * Test Errors creating the converter
341      */
342     public void testErrors() {
343         try {
344             new ArrayConverter(null, new DateConverter());
345             fail("Default Type missing - expected IllegalArgumentException");
346         } catch (final IllegalArgumentException e) {
347             // expected result
348         }
349         try {
350             new ArrayConverter(Boolean.class, new DateConverter());
351             fail("Default Type not an array - expected IllegalArgumentException");
352         } catch (final IllegalArgumentException e) {
353             // expected result
354         }
355         try {
356             new ArrayConverter(int[].class, null);
357             fail("Component Converter missing - expected IllegalArgumentException");
358         } catch (final IllegalArgumentException e) {
359             // expected result
360         }
361     }
362 
363     /**
364      * Test for BEANUTILS-302 - throwing a NPE when underscore used
365      */
366     public void testUnderscore_BEANUTILS_302() {
367         final String value = "first_value,second_value";
368         final ArrayConverter converter = new ArrayConverter(String[].class, new StringConverter());
369 
370         // test underscore not allowed (the default)
371         String[] result = converter.convert(String[].class, value);
372         assertNotNull("result.null", result);
373         assertEquals("result.length", 4, result.length);
374         assertEquals("result[0]", "first", result[0]);
375         assertEquals("result[1]", "value", result[1]);
376         assertEquals("result[2]", "second", result[2]);
377         assertEquals("result[3]", "value", result[3]);
378 
379         // configure the converter to allow underscore
380         converter.setAllowedChars(new char[] {'.', '-', '_'});
381 
382         // test underscore allowed
383         result = converter.convert(String[].class, value);
384         assertNotNull("result.null", result);
385         assertEquals("result.length", 2, result.length);
386         assertEquals("result[0]", "first_value", result[0]);
387         assertEquals("result[1]", "second_value", result[1]);
388     }
389 
390     /**
391      * Check that two arrays are the same.
392      * @param msg Test prefix msg
393      * @param expected Expected Array value
394      * @param result Result array value
395      */
396     private void checkArray(final String msg, final Object expected, final Object result) {
397         assertNotNull(msg + " Expected Null", expected);
398         assertNotNull(msg + " Result   Null", result);
399         assertTrue(msg + " Result   not array", result.getClass().isArray());
400         assertTrue(msg + " Expected not array", expected.getClass().isArray());
401         final int resultLth = Array.getLength(result);
402         assertEquals(msg + " Size", Array.getLength(expected), resultLth);
403         assertEquals(msg + " Type", expected.getClass(), result.getClass());
404         for (int i = 0; i < resultLth; i++) {
405             final Object expectElement = Array.get(expected, i);
406             final Object resultElement = Array.get(result, i);
407             assertEquals(msg + " Element " + i, expectElement, resultElement);
408         }
409     }
410 }