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.lang.text;
18  
19  import java.text.DateFormat;
20  import java.text.FieldPosition;
21  import java.text.Format;
22  import java.text.MessageFormat;
23  import java.text.NumberFormat;
24  import java.text.ParsePosition;
25  import java.util.Calendar;
26  import java.util.HashMap;
27  import java.util.Locale;
28  import java.util.Map;
29  
30  import org.apache.commons.lang.SystemUtils;
31  
32  import junit.framework.Test;
33  import junit.framework.TestCase;
34  import junit.framework.TestSuite;
35  
36  /**
37   * Test case for {@link ExtendedMessageFormat}.
38   *
39   * @since 2.4
40   * @version $Id: ExtendedMessageFormatTest.java 634874 2008-03-08 00:30:04Z mbenson $
41   */
42  public class ExtendedMessageFormatTest extends TestCase {
43  
44      private Locale[] testLocales = new Locale[] {null, //default locale
45                                                   Locale.US,
46                                                   Locale.UK,
47                                                   Locale.FRANCE,
48                                                   Locale.GERMANY};
49  
50      private Map registry = new HashMap();
51  
52      /**
53       * Return a new test suite containing this test case.
54       * 
55       * @return a new test suite containing this test case
56       */
57      public static Test suite() {
58          TestSuite suite = new TestSuite(ExtendedMessageFormatTest.class);
59          suite.setName("ExtendedMessageFormat Tests");
60          return suite;
61      }
62  
63      /**
64       * Create a new test case.
65       *
66       * @param name The name of the test
67       */
68      public ExtendedMessageFormatTest(String name) {
69          super(name);
70      }
71  
72      protected void setUp() throws Exception {
73          super.setUp();
74          registry.put("lower", new LowerCaseFormatFactory());
75          registry.put("upper", new UpperCaseFormatFactory());
76      }
77  
78      protected void tearDown() throws Exception {
79          super.tearDown();
80      }
81  
82      /**
83       * Test extended formats.
84       */
85      public void testExtendedFormats() {
86          String pattern = "Lower: {0,lower} Upper: {1,upper}";
87          ExtendedMessageFormat emf = new ExtendedMessageFormat(pattern, registry);
88          assertPatternsEqual("TOPATTERN", pattern, emf.toPattern());
89          assertEquals("Lower: foo Upper: BAR", emf.format(new Object[] {"foo", "bar"}));
90          assertEquals("Lower: foo Upper: BAR", emf.format(new Object[] {"Foo", "Bar"}));
91          assertEquals("Lower: foo Upper: BAR", emf.format(new Object[] {"FOO", "BAR"}));
92          assertEquals("Lower: foo Upper: BAR", emf.format(new Object[] {"FOO", "bar"}));
93          assertEquals("Lower: foo Upper: BAR", emf.format(new Object[] {"foo", "BAR"}));
94      }
95  
96      /**
97       * Test extended and built in formats.
98       */
99      public void testExtendedAndBuiltInFormats() {
100         Calendar cal = Calendar.getInstance();
101         cal.set(2007, Calendar.JANUARY, 23, 18, 33, 05);
102         Object[] args = new Object[] {"John Doe", cal.getTime(), new Double("12345.67")};
103         String pattern = "Name: {0,upper} DOB: {1,date,short} Salary: {2,number,currency}";
104 
105         for (int i = 0; i < testLocales.length; i++) {
106             DateFormat df = null;
107             NumberFormat nf = null;
108             ExtendedMessageFormat emf = null;
109             if (testLocales[i] == null) {
110                 df = DateFormat.getDateInstance(DateFormat.SHORT);
111                 nf = NumberFormat.getCurrencyInstance();
112                 emf = new ExtendedMessageFormat(pattern, registry);
113             } else {
114                 df = DateFormat.getDateInstance(DateFormat.SHORT, testLocales[i]);
115                 nf = NumberFormat.getCurrencyInstance(testLocales[i]);
116                 emf = new ExtendedMessageFormat(pattern, testLocales[i], registry);
117             }
118             StringBuffer expected = new StringBuffer();
119             expected.append("Name: ");
120             expected.append(args[0].toString().toUpperCase());
121             expected.append(" DOB: ");
122             expected.append(df.format(args[1]));
123             expected.append(" Salary: ");
124             expected.append(nf.format(args[2]));
125             assertPatternsEqual(null, pattern, emf.toPattern());
126             assertEquals("" + testLocales[i], expected.toString(), emf.format(args));
127         }
128     }
129 
130 //    /**
131 //     * Test extended formats with choice format.
132 //     *
133 //     * N.B. FAILING - currently sub-formats not supported
134 //     */
135 //    public void testExtendedWithChoiceFormat() {
136 //        String pattern = "Choice: {0,choice,1.0#{1,lower}|2.0#{1,upper}}";
137 //        ExtendedMessageFormat emf = new ExtendedMessageFormat(pattern, registry);
138 //        assertPatterns(null, pattern, emf.toPattern());
139 //        try {
140 //            assertEquals("one", emf.format(new Object[] {new Integer(1), "ONE"}));
141 //            assertEquals("TWO", emf.format(new Object[] {new Integer(2), "two"}));
142 //        } catch (IllegalArgumentException e) {
143 //            // currently sub-formats not supported
144 //        }
145 //    }
146 
147 //    /**
148 //     * Test mixed extended and built-in formats with choice format.
149 //     *
150 //     * N.B. FAILING - currently sub-formats not supported
151 //     */
152 //    public void testExtendedAndBuiltInWithChoiceFormat() {
153 //        String pattern = "Choice: {0,choice,1.0#{0} {1,lower} {2,number}|2.0#{0} {1,upper} {2,number,currency}}";
154 //        Object[] lowArgs  = new Object[] {new Integer(1), "Low",  new Double("1234.56")};
155 //        Object[] highArgs = new Object[] {new Integer(2), "High", new Double("9876.54")};
156 
157 //        for (int i = 0; i < testLocales.length; i++) {
158 //            NumberFormat nf = null;
159 //            NumberFormat cf = null;
160 //            ExtendedMessageFormat emf = null;
161 //            if (testLocales[i] == null) {
162 //                nf = NumberFormat.getNumberInstance();
163 //                cf = NumberFormat.getCurrencyInstance();
164 //                emf = new ExtendedMessageFormat(pattern, registry);
165 //            } else {
166 //                nf = NumberFormat.getNumberInstance(testLocales[i]);
167 //                cf = NumberFormat.getCurrencyInstance(testLocales[i]);
168 //                emf = new ExtendedMessageFormat(pattern, testLocales[i], registry);
169 //            }
170 //            assertPatterns(null, pattern, emf.toPattern());
171 //            try {
172 //                String lowExpected = lowArgs[0] + " low "    + nf.format(lowArgs[2]);
173 //                String highExpected = highArgs[0] + " HIGH "  + cf.format(highArgs[2]);
174 //                assertEquals(lowExpected,  emf.format(lowArgs));
175 //                assertEquals(highExpected, emf.format(highArgs));
176 //            } catch (IllegalArgumentException e) {
177 //                // currently sub-formats not supported
178 //            }
179 //        }
180 //    }
181 
182     /**
183      * Test the built in choice format.
184      */
185     public void testBuiltInChoiceFormat() {
186         Object[] values = new Number[] {new Integer(1), new Double("2.2"), new Double("1234.5")};
187         String choicePattern = null; 
188 
189         choicePattern = "{0,choice,1#One|2#Two|3#Many {0,number}}";
190         for (int i = 0; i < values.length; i++) {
191             checkBuiltInFormat(values[i] + ": " + choicePattern, new Object[] {values[i]});
192         }
193 
194         choicePattern = "{0,choice,1#''One''|2#\"Two\"|3#''{Many}'' {0,number}}";
195         for (int i = 0; i < values.length; i++) {
196             checkBuiltInFormat(values[i] + ": " + choicePattern, new Object[] {values[i]});
197         }
198     }
199 
200     /**
201      * Test the built in date/time formats
202      */
203     public void testBuiltInDateTimeFormat() {
204         Calendar cal = Calendar.getInstance();
205         cal.set(2007, Calendar.JANUARY, 23, 18, 33, 05);
206         Object[] args = new Object[] {cal.getTime()};
207 
208         checkBuiltInFormat("1: {0,date,short}",    args);
209         checkBuiltInFormat("2: {0,date,medium}",   args);
210         checkBuiltInFormat("3: {0,date,long}",     args);
211         checkBuiltInFormat("4: {0,date,full}",     args);
212         checkBuiltInFormat("5: {0,date,d MMM yy}", args);
213         checkBuiltInFormat("6: {0,time,short}",    args);
214         checkBuiltInFormat("7: {0,time,medium}",   args);
215         checkBuiltInFormat("8: {0,time,long}",     args);
216         checkBuiltInFormat("9: {0,time,full}",     args);
217         checkBuiltInFormat("10: {0,time,HH:mm}",   args);
218     }
219 
220     /**
221      * Test the built in number formats.
222      */
223     public void testBuiltInNumberFormat() {
224         Object[] args = new Object[] {new Double("6543.21")};
225         checkBuiltInFormat("1: {0,number}",            args);
226         checkBuiltInFormat("2: {0,number,integer}",    args);
227         checkBuiltInFormat("3: {0,number,currency}",   args);
228         checkBuiltInFormat("4: {0,number,percent}",    args);
229         checkBuiltInFormat("5: {0,number,00000.000}",  args);
230     }
231 
232     /**
233      * Create ExtendedMessageFormats for the specified pattern and the set of locales
234      * and check the formated output matches the expected result for the parameters.
235      */
236     private void checkBuiltInFormat(String pattern, Object[] args) {
237         for (int i = 0; i < testLocales.length; i++) {
238             checkBuiltInFormat(pattern, args, testLocales[i]);
239         }
240     }
241 
242     /**
243      * Create an ExtendedMessageFormat for the specified pattern and locale and check the
244      * formated output matches the expected result for the parameters.
245      */
246     private void checkBuiltInFormat(String pattern, Object[] args, Locale locale) {
247         StringBuffer buffer = new StringBuffer();
248         buffer.append("Pattern=[");
249         buffer.append(pattern);
250         buffer.append("], locale=[");
251         buffer.append(locale);
252         buffer.append("]");
253         MessageFormat mf = new MessageFormat(pattern);
254         if (locale != null) {
255             mf.setLocale(locale);
256             mf.applyPattern(pattern);
257         }
258         // System.out.println(buffer + ", result=[" + mf.format(args) +"]");
259         ExtendedMessageFormat emf = null;
260         if (locale == null) {
261             emf = new ExtendedMessageFormat(pattern);
262         } else {
263             emf = new ExtendedMessageFormat(pattern, locale);
264         }
265         assertEquals("format "    + buffer.toString(), mf.format(args), emf.format(args));
266         assertPatternsEqual("toPattern " + buffer.toString(), mf.toPattern(),  emf.toPattern());
267     }
268 
269     //can't trust what MessageFormat does with toPattern() pre 1.4:
270     private void assertPatternsEqual(String message, String expected, String actual) {
271         if (SystemUtils.isJavaVersionAtLeast(1.4f)) {
272             assertEquals(message, expected, actual);
273         }
274     }
275 
276     // ------------------------ Test Formats ------------------------
277 
278     /**
279      * {@link Format} implementation which converts to upper case.
280      */
281     private static class LowerCaseFormat extends Format {
282         public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
283             return toAppendTo.append(((String)obj).toLowerCase());
284         }
285         public Object parseObject(String source, ParsePosition pos) {throw new UnsupportedOperationException();}
286     }
287 
288     /**
289      * {@link Format} implementation which converts to lower case.
290      */
291     private static class UpperCaseFormat extends Format {
292         public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
293             return toAppendTo.append(((String)obj).toUpperCase());
294         }
295         public Object parseObject(String source, ParsePosition pos) {throw new UnsupportedOperationException();}
296     }
297 
298 
299     // ------------------------ Test Format Factories ---------------
300     /**
301      * {@link FormatFactory} implementation for lower case format.
302      */
303     private static class LowerCaseFormatFactory implements FormatFactory {
304         private static final Format LOWER_INSTANCE = new LowerCaseFormat();
305         public Format getFormat(String name, String arguments, Locale locale) {
306             return LOWER_INSTANCE;
307         }
308     }
309     /**
310      * {@link FormatFactory} implementation for upper case format.
311      */
312     private static class UpperCaseFormatFactory implements FormatFactory {
313         private static final Format UPPER_INSTANCE = new UpperCaseFormat();
314         public Format getFormat(String name, String arguments, Locale locale) {
315             return UPPER_INSTANCE;
316         }
317     }
318 }