001    /*
002     *  Copyright 2001-2005 Stephen Colebourne
003     *
004     *  Licensed under the Apache License, Version 2.0 (the "License");
005     *  you may not use this file except in compliance with the License.
006     *  You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     *  Unless required by applicable law or agreed to in writing, software
011     *  distributed under the License is distributed on an "AS IS" BASIS,
012     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     *  See the License for the specific language governing permissions and
014     *  limitations under the License.
015     */
016    package org.joda.time.format;
017    
018    import java.util.Locale;
019    import java.util.ResourceBundle;
020    import java.util.concurrent.ConcurrentHashMap;
021    import java.util.concurrent.ConcurrentMap;
022    
023    /**
024     * Factory that creates instances of PeriodFormatter.
025     * <p>
026     * Period formatting is performed by the {@link PeriodFormatter} class.
027     * Three classes provide factory methods to create formatters, and this is one.
028     * The others are {@link ISOPeriodFormat} and {@link PeriodFormatterBuilder}.
029     * <p>
030     * PeriodFormat is thread-safe and immutable, and the formatters it returns
031     * are as well.
032     *
033     * @author Brian S O'Neill
034     * @since 1.0
035     * @see ISOPeriodFormat
036     * @see PeriodFormatterBuilder
037     */
038    public class PeriodFormat {
039    
040        /**
041         * The resource bundle name.
042         */
043        private static final String BUNDLE_NAME = "org.joda.time.format.messages";
044        /**
045         * The created formatters.
046         */
047        private static final ConcurrentMap<Locale, PeriodFormatter> FORMATTERS = new ConcurrentHashMap<Locale, PeriodFormatter>();
048    
049        /**
050         * Constructor.
051         *
052         * @since 1.1 (previously private)
053         */
054        protected PeriodFormat() {
055            super();
056        }
057    
058        //-----------------------------------------------------------------------
059        /**
060         * Gets the default formatter that outputs words in English.
061         * <p>
062         * This calls {@link #wordBased(Locale)} using a locale of {@code ENGLISH}.
063         * 
064         * @return the formatter, not null
065         */
066        public static PeriodFormatter getDefault() {
067            return wordBased(Locale.ENGLISH);
068        }
069    
070        /**
071         * Returns a word based formatter for the JDK default locale.
072         * <p>
073         * This calls {@link #wordBased(Locale)} using the {@link Locale#getDefault() default locale}.
074         * 
075         * @return the formatter, not null
076         * @since 2.0
077         */
078        public static PeriodFormatter wordBased() {
079            return wordBased(Locale.getDefault());
080        }
081    
082        /**
083         * Returns a word based formatter for the specified locale.
084         * <p>
085         * The words are configured in a resource bundle text file -
086         * {@code org.joda.time.format.messages}.
087         * This can be added to via the normal classpath resource bundle mechanisms.
088         * <p>
089         * Available languages are English, Danish, Dutch, French, German, Japanese, Portuguese, and Spanish.
090         * 
091         * @return the formatter, not null
092         * @since 2.0
093         */
094        public static PeriodFormatter wordBased(Locale locale) {
095            PeriodFormatter pf = FORMATTERS.get(locale);
096            if (pf == null) {
097                ResourceBundle b = ResourceBundle.getBundle(BUNDLE_NAME, locale);
098                String[] variants = {
099                        b.getString("PeriodFormat.space"), b.getString("PeriodFormat.comma"),
100                        b.getString("PeriodFormat.commandand"), b.getString("PeriodFormat.commaspaceand")};
101                pf = new PeriodFormatterBuilder()
102                    .appendYears()
103                    .appendSuffix(b.getString("PeriodFormat.year"), b.getString("PeriodFormat.years"))
104                    .appendSeparator(b.getString("PeriodFormat.commaspace"), b.getString("PeriodFormat.spaceandspace"), variants)
105                    .appendMonths()
106                    .appendSuffix(b.getString("PeriodFormat.month"), b.getString("PeriodFormat.months"))
107                    .appendSeparator(b.getString("PeriodFormat.commaspace"), b.getString("PeriodFormat.spaceandspace"), variants)
108                    .appendWeeks()
109                    .appendSuffix(b.getString("PeriodFormat.week"), b.getString("PeriodFormat.weeks"))
110                    .appendSeparator(b.getString("PeriodFormat.commaspace"), b.getString("PeriodFormat.spaceandspace"), variants)
111                    .appendDays()
112                    .appendSuffix(b.getString("PeriodFormat.day"), b.getString("PeriodFormat.days"))
113                    .appendSeparator(b.getString("PeriodFormat.commaspace"), b.getString("PeriodFormat.spaceandspace"), variants)
114                    .appendHours()
115                    .appendSuffix(b.getString("PeriodFormat.hour"), b.getString("PeriodFormat.hours"))
116                    .appendSeparator(b.getString("PeriodFormat.commaspace"), b.getString("PeriodFormat.spaceandspace"), variants)
117                    .appendMinutes()
118                    .appendSuffix(b.getString("PeriodFormat.minute"), b.getString("PeriodFormat.minutes"))
119                    .appendSeparator(b.getString("PeriodFormat.commaspace"), b.getString("PeriodFormat.spaceandspace"), variants)
120                    .appendSeconds()
121                    .appendSuffix(b.getString("PeriodFormat.second"), b.getString("PeriodFormat.seconds"))
122                    .appendSeparator(b.getString("PeriodFormat.commaspace"), b.getString("PeriodFormat.spaceandspace"), variants)
123                    .appendMillis()
124                    .appendSuffix(b.getString("PeriodFormat.millisecond"), b.getString("PeriodFormat.milliseconds"))
125                    .toFormatter();
126                FORMATTERS.putIfAbsent(locale, pf);
127            }
128            return pf;
129        }
130    
131    }