com.facebook.buck.i18n.NumberFormatter.java Source code

Java tutorial

Introduction

Here is the source code for com.facebook.buck.i18n.NumberFormatter.java

Source

/*
 * Copyright 2015-present Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

package com.facebook.buck.i18n;

import com.google.common.base.Function;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

import java.text.FieldPosition;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.Locale;

import javax.annotation.concurrent.ThreadSafe;

/**
 * Thread-safe and i18n-safe wrapper for {@link NumberFormat} (which is not thread-safe).
 */
@ThreadSafe
public class NumberFormatter {
    // Instead of a ThreadLocal<NumberFormat> (which leaks memory),
    // we'll use a LoadingCache of <thread+locale: numberformat> pairs
    // which evicts itself as necessary.
    private final LoadingCache<NumberFormatterCacheKey, NumberFormat> numberFormatCache;

    /**
     * Given a function which creates {@link NumberFormat} objects for a {@link Locale},
     * returns a wrapper providing thread-safe access to the formatter for that locale.
     */
    public NumberFormatter(final Function<Locale, NumberFormat> numberFormatCreator) {
        numberFormatCache = CacheBuilder.newBuilder().maximumSize(1000)
                .build(new CacheLoader<NumberFormatterCacheKey, NumberFormat>() {
                    @Override
                    public NumberFormat load(NumberFormatterCacheKey key) {
                        return numberFormatCreator.apply(key.getLocale());
                    }
                });
    }

    private NumberFormat getFormatter(Locale locale) {
        return numberFormatCache.getUnchecked(NumberFormatterCacheKey.of(Thread.currentThread().getId(), locale));
    }

    /**
     * @see NumberFormat#format(double)
     */
    public String format(Locale locale, double number) {
        return getFormatter(locale).format(number);
    }

    /**
     * @see NumberFormat#format(double, StringBuffer, FieldPosition)
     */
    public StringBuffer format(Locale locale, double number, StringBuffer toAppendTo, FieldPosition pos) {
        return getFormatter(locale).format(number, toAppendTo, pos);
    }

    /**
     * @see NumberFormat#format(long)
     */
    public String format(Locale locale, long number) {
        return getFormatter(locale).format(number);
    }

    /**
     * @see NumberFormat#format(Object)
     */
    public String format(Locale locale, Object object) {
        return getFormatter(locale).format(object);
    }

    /**
     * @see NumberFormat#format(Object, StringBuffer, FieldPosition)
     */
    public StringBuffer format(Locale locale, Object object, StringBuffer toAppendTo, FieldPosition pos) {
        return getFormatter(locale).format(object, toAppendTo, pos);
    }

    /**
     * @see NumberFormat#parse(String)
     */
    public Number parse(Locale locale, String source) throws ParseException {
        return getFormatter(locale).parse(source);
    }

    /**
     * @see NumberFormat#parse(String, ParsePosition)
     */
    public Number parse(Locale locale, String source, ParsePosition pos) {
        return getFormatter(locale).parse(source, pos);
    }

    /**
     * @see NumberFormat#parseObject(String, ParsePosition)
     */
    public Object parseObject(Locale locale, String source, ParsePosition pos) {
        return getFormatter(locale).parseObject(source, pos);
    }
}