1 /*
2  * Copyright (c) 2007-present, Stephen Colebourne & Michael Nascimento Santos
3  *
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  *  * Redistributions of source code must retain the above copyright notice,
10  *    this list of conditions and the following disclaimer.
11  *
12  *  * Redistributions in binary form must reproduce the above copyright notice,
13  *    this list of conditions and the following disclaimer in the documentation
14  *    and/or other materials provided with the distribution.
15  *
16  *  * Neither the name of JSR-310 nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 package org.threeten.bp.format;
33 
34 import java.text.DateFormat;
35 import java.text.SimpleDateFormat;
36 import java.util.Locale;
37 import java.util.concurrent.ConcurrentHashMap;
38 import java.util.concurrent.ConcurrentMap;
39 
40 import org.threeten.bp.chrono.Chronology;
41 
42 /**
43  * The Service Provider Implementation to obtain date-time formatters for a style.
44  * <p>
45  * This implementation is based on extraction of data from a {@link SimpleDateFormat}.
46  *
47  * <h3>Specification for implementors</h3>
48  * This class is immutable and thread-safe.
49  */
50 final class SimpleDateTimeFormatStyleProvider extends DateTimeFormatStyleProvider {
51     // TODO: Better implementation based on CLDR
52 
53     /** Cache of formatters. */
54     private static final ConcurrentMap<String, Object> FORMATTER_CACHE =
55                         new ConcurrentHashMap<String, Object>(16, 0.75f, 2);
56 
57     @Override
getAvailableLocales()58     public Locale[] getAvailableLocales() {
59         return DateFormat.getAvailableLocales();
60     }
61 
62     @Override
getFormatter( FormatStyle dateStyle, FormatStyle timeStyle, Chronology chrono, Locale locale)63     public DateTimeFormatter getFormatter(
64             FormatStyle dateStyle, FormatStyle timeStyle, Chronology chrono, Locale locale) {
65         if (dateStyle == null && timeStyle == null) {
66             throw new IllegalArgumentException("Date and Time style must not both be null");
67         }
68         String key = chrono.getId() + '|' + locale.toString() + '|' + dateStyle + timeStyle;
69         Object cached = FORMATTER_CACHE.get(key);
70         if (cached != null) {
71             if (cached.equals("")) {
72                 throw new IllegalArgumentException("Unable to convert DateFormat to DateTimeFormatter");
73             }
74             return (DateTimeFormatter) cached;
75         }
76         DateFormat dateFormat;
77         if (dateStyle != null) {
78             if (timeStyle != null) {
79                 dateFormat = DateFormat.getDateTimeInstance(convertStyle(dateStyle), convertStyle(timeStyle), locale);
80             } else {
81                 dateFormat = DateFormat.getDateInstance(convertStyle(dateStyle), locale);
82             }
83         } else {
84             dateFormat = DateFormat.getTimeInstance(convertStyle(timeStyle), locale);
85         }
86         if (dateFormat instanceof SimpleDateFormat) {
87             String pattern = ((SimpleDateFormat) dateFormat).toPattern();
88             DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(locale);
89             FORMATTER_CACHE.putIfAbsent(key, formatter);
90             return formatter;
91         }
92         FORMATTER_CACHE.putIfAbsent(key, "");
93         throw new IllegalArgumentException("Unable to convert DateFormat to DateTimeFormatter");
94     }
95 
96     /**
97      * Converts the enum style to the old format style.
98      * @param style  the enum style, not null
99      * @return the int style
100      */
convertStyle(FormatStyle style)101     private int convertStyle(FormatStyle style) {
102         return style.ordinal();  // indices happen to align
103     }
104 
105 }
106