/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.sis.util.resources;

import java.net.URL;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Map;
import java.util.Enumeration;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.NoSuchElementException;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.lang.reflect.Modifier;
import javax.measure.Unit;
import org.opengis.util.CodeList;
import org.opengis.util.InternationalString;
import org.apache.sis.util.Debug;
import org.apache.sis.util.Classes;
import org.apache.sis.util.Localized;
import org.apache.sis.util.Utilities;
import org.apache.sis.util.Exceptions;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.logging.Logging;
import org.apache.sis.internal.system.Loggers;
import org.apache.sis.internal.util.AutoMessageFormat;
import org.apache.sis.internal.util.MetadataServices;
import org.apache.sis.internal.util.Strings;
import org.apache.sis.measure.RangeFormat;
import org.apache.sis.measure.Range;


/**
 * {@link ResourceBundle} implementation accepting integers instead of strings for resource keys.
 * Using integers allow implementations to avoid adding large string constants into their
 * {@code .class} files and runtime images. Developers still have meaningful labels in their
 * code (e.g. {@code MismatchedDimension}) through a set of constants defined in {@code Keys}
 * inner classes, with the side-effect of compile-time safety. Because integer constants are
 * inlined right into class files at compile time, the declarative classes is not loaded at run time.
 *
 * <p>Localized resources are fetched by calls to {@link #getString(short)}.
 * Arguments can optionally be provided by calls to {@link #getString(short, Object) getString(short, Object, ...)}.
 * If arguments are present, then the string will be formatted using {@link MessageFormat},
 * completed by some special cases handled by this class. Roughly speaking:</p>
 *
 * <ul>
 *   <li>{@link Number}, {@link java.util.Date}, {@link CodeList} and {@link InternationalString} instances
 *       are localized using the current {@code ResourceBundle} locale.</li>
 *   <li>Long {@link CharSequence} instances are shortened by {@link CharSequences#shortSentence(CharSequence, int)}.</li>
 *   <li>{@link Class} and {@link Throwable} instances are summarized.</li>
 * </ul>
 *
 * <div class="section">Thread safety</div>
 * The same {@code IndexedResourceBundle} instance can be safely used by many threads without synchronization
 * on the part of the caller. Subclasses should make sure that any overridden methods remain safe to call from
 * multiple threads.
 *
 * @author  Martin Desruisseaux (IRD, Geomatys)
 * @version 1.0
 * @since   0.3
 * @module
 */
public class IndexedResourceBundle extends ResourceBundle implements Localized {
    /**
     * Key used in properties map for localizing some aspects of the operation being executed.
     * The {@code getResources(Map<?,?>)} methods defined in some sub-classes will look for this property.
     *
     * @see org.apache.sis.referencing.AbstractIdentifiedObject#LOCALE_KEY
     */
    public static final String LOCALE_KEY = "locale";

    /**
     * Maximum string length for text inserted into another text. This parameter is used by {@link #toArray(Object)}.
     * Resource strings are never cut to this length. However, text replacing {@code "{0}"} in a string like
     * {@code "Parameter name is {0}"} will be cut to this length.
     */
    private static final int MAX_STRING_LENGTH = 200;

    /**
     * First valid key index.
     * We start at 1 rather than 0 in order to keep value 0 available for meaning "no localized message".
     *
     * @since 0.8
     */
    static final int FIRST = 1;

    /**
     * The path of the binary file containing resources, or {@code null} if there is no resources
     * or if the resources have already been loaded. The resources may be a file or an entry in a
     * JAR file.
     */
    private URL resources;

    /**
     * The array of resources. Keys are an array index plus {@value #FIRST}. For example the value for key "14" is
     * {@code values[13]}. This array will be loaded only when first needed. We should not load it at construction
     * time, because some {@code ResourceBundle} objects will never ask for values.  This is particularly the case
     * for parent resources of {@code Resources_fr_CA}, {@code Resources_en}, {@code Resources_de}, etc. which will
     * only be used if a key has not been found in the child resources.
     *
     * @see #ensureLoaded(String)
     */
    @SuppressWarnings("VolatileArrayField")     // Okay because we set this field only after the array has been fully constructed.
    private volatile String[] values;

    /**
     * The object to use for formatting messages. This object
     * will be constructed only when first needed.
     */
    private transient AutoMessageFormat format;

    /**
     * The key of the last resource requested. If the same resource is requested multiple times,
     * knowing its key allows us to avoid invoking the costly {@link MessageFormat#applyPattern}
     * method.
     */
    private transient short lastKey;

    /**
     * Constructs a new resource bundle loading data from the given UTF file.
     *
     * @param  resources  the path of the binary file containing resources, or {@code null} if
     *         there is no resources. The resources may be a file or an entry in a JAR file.
     */
    protected IndexedResourceBundle(final URL resources) {
        this.resources = resources;
    }

    /**
     * Returns a resource bundle of the specified class.
     *
     * @param  <T>      the resource bundle class.
     * @param  base     the resource bundle class.
     * @param  locale   the locale, or {@code null} for the default locale.
     * @return resources in the given locale.
     * @throws MissingResourceException if resources can't be found.
     *
     * @see Vocabulary#getResources(Locale)
     * @see Errors#getResources(Locale)
     */
    protected static <T extends IndexedResourceBundle> T getBundle(Class<T> base, Locale locale)
            throws MissingResourceException
    {
        if (locale == null) {
            locale = Locale.getDefault();
        }
        // No caching; we rely on the one implemented in ResourceBundle.
        return base.cast(getBundle(base.getName(), locale, base.getClassLoader(), Loader.INSTANCE));
    }

    /**
     * Returns a handler for the constants declared in the inner {@code Keys} class.
     * Subclasses should override this method for efficiency, but this is not mandatory.
     *
     * @return a handler for the constants declared in the inner {@code Keys} class.
     */
    protected KeyConstants getKeyConstants() {
        Class<?> keysClass = KeyConstants.class;
        for (final Class<?> inner : getClass().getClasses()) {
            if ("Keys".equals(inner.getSimpleName())) {
                keysClass = inner;
                break;
            }
        }
        return new KeyConstants(keysClass);
    }

    /**
     * Returns an enumeration of the keys.
     *
     * @return all keys in this resource bundle.
     */
    @Override
    public final Enumeration<String> getKeys() {
        return new KeyEnum(getKeyConstants().getKeyNames());
    }

    /**
     * The keys as an enumeration. This enumeration needs to skip null values, which
     * may occur if the resource bundle is incomplete for that particular locale.
     */
    private static final class KeyEnum implements Enumeration<String> {
        /** The keys to return.          */ private final String[] keys;
        /** Index of next key to return. */ private int next;

        /** Creates a new enum for the given array of keys. */
        KeyEnum(final String[] keys) {
            this.keys = keys;
        }

        /** Returns {@code true} if there is at least one more non-null key. */
        @Override public boolean hasMoreElements() {
            while (next < keys.length) {
                if (keys[next] != null) {
                    return true;
                }
                next++;
            }
            return false;
        }

        /** Returns the next key. */
        @Override public String nextElement() {
            while (next < keys.length) {
                final String key = keys[next++];
                if (key != null) {
                    return key;
                }
            }
            throw new NoSuchElementException();
        }
    }

    /**
     * Lists resources to the specified stream. If a resource has more than one line, only
     * the first line will be written. This method is used mostly for debugging purposes.
     *
     * @param  out  the destination stream.
     * @throws IOException if an output operation failed.
     */
    @Debug
    public final void list(final Appendable out) throws IOException {
        int keyLength = 0;
        final String[] keys = getKeyConstants().getKeyNames();
        for (final String key : keys) {
            if (key != null) {
                keyLength = Math.max(keyLength, key.length());
            }
        }
        final String lineSeparator = System.lineSeparator();
        final String[] values = ensureLoaded(null);
        for (int i=0; i < values.length; i++) {
            final String key   = keys  [i];
            final String value = values[i];
            if (key != null && value != null) {
                int indexCR = value.indexOf('\r'); if (indexCR < 0) indexCR = value.length();
                int indexLF = value.indexOf('\n'); if (indexLF < 0) indexLF = value.length();
                final String number = String.valueOf(i);
                out.append(CharSequences.spaces(5 - number.length()))
                   .append(number)
                   .append(": ")
                   .append(key)
                   .append(CharSequences.spaces(keyLength - key.length()))
                   .append(" = ")
                   .append(value, 0, Math.min(indexCR, indexLF))
                   .append(lineSeparator);
            }
        }
    }

    /**
     * Ensures that resource values are loaded. If they are not, loads them immediately.
     *
     * @param  key  key for the requested resource, or {@code null} if all resources
     *         are requested. This key is used mostly for constructing messages.
     * @return the resources.
     * @throws MissingResourceException if this method failed to load resources.
     */
    private String[] ensureLoaded(final String key) throws MissingResourceException {
        String[] values = this.values;
        if (values == null) synchronized (this) {
            values = this.values;
            if (values == null) {
                /*
                 * If there is no explicit resources for this instance, inherit the resources
                 * from the parent. Note that this IndexedResourceBundle instance may still
                 * differ from its parent in the way dates and numbers are formatted.
                 */
                if (resources == null) {
                    /*
                     * If we get a NullPointerException or ClassCastException here,
                     * it would be a bug in the way we create the chain of parents.
                     */
                    values = ((IndexedResourceBundle) parent).ensureLoaded(key);
                } else {
                    /*
                     * Prepares a log record.  We will wait for successful loading before
                     * posting this record.  If loading fails, the record will be changed
                     * into an error record. Note that the message must be logged outside
                     * the synchronized block, otherwise there is dead locks!
                     */
                    final Locale    locale     = getLocale();                         // Sometime null with IBM's JDK.
                    final String    baseName   = getClass().getCanonicalName();
                    final String    methodName = (key != null) ? "getObject" : "getKeys";
                    final LogRecord record     = new LogRecord(Level.FINER, "Loaded resources for {0} from bundle \"{1}\".");
                    record.setLoggerName(Loggers.LOCALIZATION);
                    /*
                     * Loads resources from the UTF file.
                     */
                    try (DataInputStream input = new DataInputStream(new BufferedInputStream(resources.openStream()))) {
                        values = new String[input.readInt()];
                        for (int i=0; i<values.length; i++) {
                            values[i] = input.readUTF();
                            if (values[i].isEmpty()) {
                                values[i] = null;
                            }
                        }
                    } catch (IOException exception) {
                        record.setLevel  (Level.WARNING);
                        record.setMessage(exception.getMessage());              // For administrator, use system locale.
                        record.setThrown (exception);
                        Logging.log(IndexedResourceBundle.class, methodName, record);
                        throw (MissingResourceException) new MissingResourceException(
                                Exceptions.getLocalizedMessage(exception, locale),   // For users, use requested locale.
                                baseName, key).initCause(exception);
                    }
                    /*
                     * Now, logs the message. This message is provided only in English.
                     * Note that Locale.getDisplayName() may return different string on
                     * different Java implementation, but it doesn't matter here since
                     * we use the result only for logging purpose.
                     */
                    String language = null;
                    if (locale != null) {
                        language = locale.getDisplayName(Locale.US);
                    }
                    if (language == null || language.isEmpty()) {
                        language = "<root>";
                    }
                    record.setParameters(new String[] {language, baseName});
                    Logging.log(IndexedResourceBundle.class, methodName, record);
                    resources = null;                                           // Not needed anymore, let GC do its job.
                }
                this.values = values;
            }
        }
        return values;
    }

    /**
     * Gets an object for the given key from this resource bundle.
     * Returns null if this resource bundle does not contain an
     * object for the given key.
     *
     * @param  key  the key for the desired object
     * @throws NullPointerException if {@code key} is {@code null}
     * @return the object for the given key, or null
     */
    @Override
    protected final Object handleGetObject(final String key) {
        /*
         * Note: Synchronization is performed by 'ensureLoaded'
         */
        final String[] values = ensureLoaded(key);
        int keyID;
        try {
            keyID = Short.parseShort(key);
        } catch (NumberFormatException exception) {
            /*
             * Maybe the full key name has been specified instead. We do that for localized
             * LogRecords, for easier debugging if the message has not been properly formatted.
             */
            try {
                keyID = getKeyConstants().getKeyValue(key);
            } catch (ReflectiveOperationException e) {
                e.addSuppressed(exception);
                Logging.recoverableException(Logging.getLogger(Loggers.LOCALIZATION), getClass(), "handleGetObject", e);
                return null;                // This is okay as of 'handleGetObject' contract.
            }
        }
        keyID -= FIRST;
        return (keyID >= 0 && keyID < values.length) ? values[keyID] : null;
    }

    /**
     * Returns {@code arguments} as an array, and convert some types that are not recognized
     * by {@link MessageFormat}. If {@code arguments} is already an array, then that array or
     * a copy of that array will be returned. If {@code arguments} is not an array, it will be
     * placed in an array of length 1.
     *
     * <p>All the array elements will be checked for {@link CharSequence}, {@link InternationalString},
     * {@link CodeList}, {@link Throwable} or {@link Class} instances.
     * All {@code InternationalString} instances will be localized according this resource bundle locale.
     * Any characters sequences of length greater than {@link #MAX_STRING_LENGTH} will be shortened using
     * the {@link CharSequences#shortSentence(CharSequence, int)} method.</p>
     *
     * <div class="note"><b>Note:</b>
     * If more cases are added, remember to update class and package javadoc.</div>
     *
     * @param  arguments  the object to check.
     * @return {@code arguments} as an array, eventually with some elements replaced.
     */
    final Object[] toArray(final Object arguments) {
        Object[] array;
        if (arguments instanceof Object[]) {
            array = (Object[]) arguments;
        } else {
            array = new Object[] {arguments};
        }
        for (int i=0; i<array.length; i++) {
            final Object element = array[i];
            if (element == null) continue;
            Object replacement = element;
            if (element instanceof CharSequence) {
                CharSequence text = (CharSequence) element;
                if (text instanceof InternationalString) {
                    text = ((InternationalString) element).toString(getLocale());
                }
                replacement = CharSequences.shortSentence(text, MAX_STRING_LENGTH);
            } else if (element instanceof Throwable) {
                String message = Exceptions.getLocalizedMessage((Throwable) element, getLocale());
                if (message == null) {
                    message = Classes.getShortClassName(element);
                }
                replacement = message;
            } else if (element instanceof Class<?>) {
                replacement = Classes.getShortName(getPublicType((Class<?>) element));
            } else if (element instanceof CodeList<?>) {
                replacement = MetadataServices.getInstance().getCodeTitle((CodeList<?>) element, getLocale());
            } else if (element instanceof Range<?>) {
                final Range<?> range = (Range<?>) element;
                replacement = new RangeFormat(getLocale(), range.getElementType()).format(range);
            } else if (element instanceof Unit<?>) {
                String s = element.toString();
                if (s.isEmpty()) s = "1";
                replacement = s;
            } else if (element.getClass().isArray()) {
                replacement = Utilities.deepToString(element);
            }
            /*
             * No need to check for Numbers or Dates instances, since they are
             * properly formatted in the ResourceBundle locale by MessageFormat.
             */
            if (replacement != element) {
                if (array == arguments) {
                    array = array.clone();                  // Protect the user-provided array from change.
                }
                array[i] = replacement;
            }
        }
        return array;
    }

    /**
     * If the given class is not public, returns the first public interface or the first public super-class.
     * This is for avoiding confusing the user with private class in message like "Value can not be instance
     * of XYZ".
     */
    private static Class<?> getPublicType(Class<?> c) {
        while (!Modifier.isPublic(c.getModifiers())) {
            for (final Class<?> type : c.getInterfaces()) {
                if (Modifier.isPublic(type.getModifiers()) && !type.getName().startsWith("java")) {
                    return type;
                }
            }
            c = c.getSuperclass();
        }
        return c;
    }

    /**
     * Writes the localized string identified by the given key followed by a colon.
     * The way to write the colon depends on the language.
     *
     * @param  key         the key for the desired string.
     * @param  toAppendTo  where to write the localized string followed by a colon.
     * @throws IOException if an error occurred while writing to the given destination.
     *
     * @since 0.8
     */
    public final void appendLabel(final short key, final Appendable toAppendTo) throws IOException {
        toAppendTo.append(getString(key));
        if (Locale.FRENCH.getLanguage().equals(getLocale().getLanguage())) {
            toAppendTo.append("\u00A0:");
        } else {
            toAppendTo.append(':');
        }
    }

    /**
     * Gets a string for the given key and appends "…" to it.
     * This method is typically used for creating menu items.
     *
     * @param  key  the key for the desired string.
     * @return the string for the given key.
     * @throws MissingResourceException if no object for the given key can be found.
     */
    public final String getMenuLabel(final short key) throws MissingResourceException {
        return getString(key) + '…';
    }

    /**
     * Gets a string for the given key from this resource bundle or one of its parents.
     *
     * @param  key  the key for the desired string.
     * @return the string for the given key.
     * @throws MissingResourceException if no object for the given key can be found.
     */
    public final String getString(final short key) throws MissingResourceException {
        return getString(String.valueOf(key));
    }

    /**
     * Gets a string for the given key and formats it with the specified argument. The message is
     * formatted using {@link MessageFormat}. Calling this method is approximately equivalent to
     * calling:
     *
     * {@preformat java
     *     String pattern = getString(key);
     *     Format f = new MessageFormat(pattern);
     *     return f.format(arg0);
     * }
     *
     * If {@code arg0} is not already an array, it will be placed into an array of length 1. Using
     * {@link MessageFormat}, all occurrences of "{0}", "{1}", "{2}" in the resource string will be
     * replaced by {@code arg0[0]}, {@code arg0[1]}, {@code arg0[2]}, etc.
     *
     * @param  key   the key for the desired string.
     * @param  arg0  a single object or an array of objects to be formatted and substituted.
     * @return the string for the given key.
     * @throws MissingResourceException if no object for the given key can be found.
     *
     * @see #getString(String)
     * @see #getString(short,Object,Object)
     * @see #getString(short,Object,Object,Object)
     * @see MessageFormat
     */
    public final String getString(final short key, final Object arg0) throws MissingResourceException {
        final String pattern = getString(key);
        final Object[] arguments = toArray(arg0);
        synchronized (this) {
            if (format == null) {
                /*
                 * Constructs a new MessageFormat for formatting the arguments.
                 */
                format  = new AutoMessageFormat(pattern, getLocale());
                lastKey = key;
            } else if (key != lastKey) {
                /*
                 * Method MessageFormat.applyPattern(…) is costly! We will avoid
                 * calling it again if the format already has the right pattern.
                 */
                format.applyPattern(pattern);
                lastKey = key;
            }
            try {
                format.configure(arguments);
                return format.format(arguments);
            } catch (RuntimeException e) {
                /*
                 * Safety against badly implemented toString() method
                 * in libraries that we do not control.
                 */
                return "[Unformattable message: " + e + ']';
            }
        }
    }

    /**
     * Gets a string for the given key and replaces all occurrences of "{0}",
     * "{1}", with values of {@code arg0}, {@code arg1}, etc.
     *
     * @param  key   the key for the desired string.
     * @param  arg0  value to substitute for "{0}".
     * @param  arg1  value to substitute for "{1}".
     * @return the formatted string for the given key.
     * @throws MissingResourceException if no object for the given key can be found.
     */
    public final String getString(final short  key,
                                  final Object arg0,
                                  final Object arg1) throws MissingResourceException
    {
        return getString(key, new Object[] {arg0, arg1});
    }

    /**
     * Gets a string for the given key and replaces all occurrences of "{0}",
     * "{1}", with values of {@code arg0}, {@code arg1}, etc.
     *
     * @param  key   the key for the desired string.
     * @param  arg0  value to substitute for "{0}".
     * @param  arg1  value to substitute for "{1}".
     * @param  arg2  value to substitute for "{2}".
     * @return the formatted string for the given key.
     * @throws MissingResourceException if no object for the given key can be found.
     */
    public final String getString(final short  key,
                                  final Object arg0,
                                  final Object arg1,
                                  final Object arg2) throws MissingResourceException
    {
        return getString(key, new Object[] {arg0, arg1, arg2});
    }

    /**
     * Gets a string for the given key and replaces all occurrences of "{0}",
     * "{1}", with values of {@code arg0}, {@code arg1}, etc.
     *
     * @param  key   the key for the desired string.
     * @param  arg0  value to substitute for "{0}".
     * @param  arg1  value to substitute for "{1}".
     * @param  arg2  value to substitute for "{2}".
     * @param  arg3  value to substitute for "{3}".
     * @return the formatted string for the given key.
     * @throws MissingResourceException if no object for the given key can be found.
     */
    public final String getString(final short  key,
                                  final Object arg0,
                                  final Object arg1,
                                  final Object arg2,
                                  final Object arg3) throws MissingResourceException
    {
        return getString(key, new Object[] {arg0, arg1, arg2, arg3});
    }

    /**
     * Gets a string for the given key and replaces all occurrences of "{0}",
     * "{1}", with values of {@code arg0}, {@code arg1}, etc.
     *
     * @param  key   the key for the desired string.
     * @param  arg0  value to substitute for "{0}".
     * @param  arg1  value to substitute for "{1}".
     * @param  arg2  value to substitute for "{2}".
     * @param  arg3  value to substitute for "{3}".
     * @param  arg4  value to substitute for "{4}".
     * @return the formatted string for the given key.
     * @throws MissingResourceException if no object for the given key can be found.
     */
    public final String getString(final short  key,
                                  final Object arg0,
                                  final Object arg1,
                                  final Object arg2,
                                  final Object arg3,
                                  final Object arg4) throws MissingResourceException
    {
        return getString(key, new Object[] {arg0, arg1, arg2, arg3, arg4});
    }

    /**
     * Gets a localized log record.
     *
     * @param  level  the log record level.
     * @param  key    the resource key.
     * @return the log record.
     */
    public final LogRecord getLogRecord(final Level level, final short key) {
        final LogRecord record = new LogRecord(level, getKeyConstants().getKeyName(key));
        record.setResourceBundleName(getClass().getName());
        record.setResourceBundle(this);
        return record;
    }

    /**
     * Gets a localized log record.
     *
     * @param  level  the log record level.
     * @param  key    the resource key.
     * @param  arg0   the parameter for the log message, which may be an array.
     * @return the log record.
     */
    public final LogRecord getLogRecord(final Level level, final short key,
                                        final Object arg0)
    {
        final LogRecord record = getLogRecord(level, key);
        record.setParameters(toArray(arg0));
        return record;
    }

    /**
     * Gets a localized log record.
     *
     * @param  level  the log record level.
     * @param  key    the resource key.
     * @param  arg0   the first parameter.
     * @param  arg1   the second parameter.
     * @return the log record.
     */
    public final LogRecord getLogRecord(final Level level, final short key,
                                        final Object arg0,
                                        final Object arg1)
    {
        return getLogRecord(level, key, new Object[] {arg0, arg1});
    }

    /**
     * Gets a localized log record.
     *
     * @param  level  the log record level.
     * @param  key    the resource key.
     * @param  arg0   the first parameter.
     * @param  arg1   the second parameter.
     * @param  arg2   the third parameter.
     * @return the log record.
     */
    public final LogRecord getLogRecord(final Level level, final short key,
                                        final Object arg0,
                                        final Object arg1,
                                        final Object arg2)
    {
        return getLogRecord(level, key, new Object[] {arg0, arg1, arg2});
    }

    /**
     * Gets a localized log record.
     *
     * @param  level  the log record level.
     * @param  key    the resource key.
     * @param  arg0   the first parameter.
     * @param  arg1   the second parameter.
     * @param  arg2   the third parameter.
     * @param  arg3   the fourth parameter.
     * @return the log record.
     */
    public final LogRecord getLogRecord(final Level level, final short key,
                                        final Object arg0,
                                        final Object arg1,
                                        final Object arg2,
                                        final Object arg3)
    {
        return getLogRecord(level, key, new Object[] {arg0, arg1, arg2, arg3});
    }

    /**
     * Returns the locale specified in the given map, or {@code null} if none.
     * Value of unexpected type are ignored.
     *
     * @param  properties  the map of properties, or {@code null} if none.
     * @return the locale found in the given map, or {@code null} if none.
     *
     * @since 0.8
     */
    protected static Locale getLocale(final Map<?,?> properties) {
        if (properties != null) {
            final Object candidate = properties.get(LOCALE_KEY);
            if (candidate instanceof Locale) {
                return (Locale) candidate;
            }
        }
        return null;
    }

    /**
     * Returns a string representation of this object.
     * This method is for debugging purposes only.
     *
     * @return a string representation of this resources bundle.
     */
    @Override
    public synchronized String toString() {
        return Strings.bracket(getClass(), getLocale());
    }
}
