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 */
016package org.joda.time.format;
017
018import java.util.Locale;
019import java.util.ResourceBundle;
020import java.util.concurrent.ConcurrentHashMap;
021import 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 */
038public 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}