/*
 * 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.sling.i18n.impl;

import static org.apache.sling.i18n.impl.JcrResourceBundle.PROP_BASENAME;
import static org.apache.sling.i18n.impl.JcrResourceBundle.PROP_LANGUAGE;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Semaphore;
import java.util.regex.Pattern;

import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.resource.observation.ExternalResourceChangeListener;
import org.apache.sling.api.resource.observation.ResourceChange;
import org.apache.sling.api.resource.observation.ResourceChangeListener;
import org.apache.sling.commons.scheduler.ScheduleOptions;
import org.apache.sling.commons.scheduler.Scheduler;
import org.apache.sling.i18n.ResourceBundleProvider;
import org.apache.sling.serviceusermapping.ServiceUserMapped;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The <code>JcrResourceBundleProvider</code> implements the
 * <code>ResourceBundleProvider</code> interface creating
 * <code>ResourceBundle</code> instances from resources stored in the
 * repository.
 */
@Component(service = {ResourceBundleProvider.class, ResourceChangeListener.class},
    property = {
            Constants.SERVICE_DESCRIPTION + "=Apache Sling I18n Resource Bundle Provider",
            Constants.SERVICE_VENDOR + "=The Apache Software Foundation",
            ResourceChangeListener.PATHS + "=/",
            ResourceChangeListener.CHANGES + "=ADDED",
            ResourceChangeListener.CHANGES + "=REMOVED",
            ResourceChangeListener.CHANGES + "=CHANGED"
    })
@Designate(ocd = JcrResourceBundleProvider.Config.class)
public class JcrResourceBundleProvider implements ResourceBundleProvider, ResourceChangeListener, ExternalResourceChangeListener {

    /**
     * A regular expression pattern matching all custom country codes.
     * @see <a href="https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#User-assigned_code_elements">User-assigned code elements</a>
     */
    private static final Pattern USER_ASSIGNED_COUNTRY_CODES_PATTERN = Pattern.compile("aa|q[m-z]|x[a-z]|zz");

    @ObjectClassDefinition(name ="Apache Sling I18N Resource Bundle Provider",
            description ="ResourceBundleProvider service which loads the messages from the repository.")
    public @interface Config {

        @AttributeDefinition(name = "Default Locale",
            description = "The default locale to assume if none can be "+
                 "resolved otherwise. This value must be in the form acceptable to the "+
                 "java.util.Locale class.")
        String locale_default() default "en";

        @AttributeDefinition(name = "Preload Bundles",
                description = "Whether or not to eagerly load the resource bundles "+
                    "on bundle start or a cache invalidation.")
        boolean preload_bundles() default false;

        @AttributeDefinition(name = "Invalidation Delay",
                description = "In case of dictionary change events the cached "+
                        "resource bundle becomes invalid after the given delay (in ms). ")
        long invalidation_delay() default 5000;
    }

    @Reference
    private Scheduler scheduler;

    /** job names of scheduled jobs for reloading individual bundles */
    private final Collection<String> scheduledJobNames = Collections.synchronizedList(new ArrayList<String>()) ;

    /** default log */
    private final Logger log = LoggerFactory.getLogger(getClass());

    @Reference
    private ResourceResolverFactory resourceResolverFactory;

    @Reference
    private ServiceUserMapped serviceUserMapped;

    /**
     * The default Locale as configured with the <i>locale.default</i>
     * configuration property. This defaults to <code>Locale.ENGLISH</code> if
     * the configuration property is not set.
     */
    private volatile Locale defaultLocale = Locale.ENGLISH;

    /**
     * Map of cached resource bundles indexed by a key combined of the base name
     * and <code>Locale</code> used to load and identify the <code>ResourceBundle</code>.
     */
    private final ConcurrentHashMap<Key, JcrResourceBundle> resourceBundleCache = new ConcurrentHashMap<>();

    private final ConcurrentHashMap<Key, Semaphore> loadingGuards = new ConcurrentHashMap<>();

    /**
     * paths from which JCR resource bundles have been loaded
     */
    private final Set<String> languageRootPaths = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());

    /**
     * Return root resource bundle as created on-demand by
     * {@link #getRootResourceBundle()}.
     */
    private volatile ResourceBundle rootResourceBundle;

    private volatile BundleContext bundleContext;

    /**
     * Each ResourceBundle is registered as a service. Each registration is stored in this map with the locale & base name used as a key.
     */
    private final Map<Key, ServiceRegistration<ResourceBundle>> bundleServiceRegistrations = new HashMap<>();

    private boolean preloadBundles;

    private long invalidationDelay;

    private ResourceResolver createResourceResolver() throws LoginException {
        return resourceResolverFactory.getServiceResourceResolver(null);
    }

    // ---------- ResourceBundleProvider ---------------------------------------

    /**
     * Returns the configured default <code>Locale</code> which is used as a
     * fallback for {@link #getResourceBundle(Locale)} and also as the basis for
     * any messages requested from resource bundles.
     */
    @Override
    public Locale getDefaultLocale() {
        return defaultLocale;
    }

    /**
     * Returns the <code>ResourceBundle</code> for the given
     * <code>locale</code>.
     *
     * @param locale The <code>Locale</code> for which to return the resource
     *            bundle. If this is <code>null</code> the configured
     *            {@link #getDefaultLocale() default locale} is assumed.
     * @return The <code>ResourceBundle</code> for the given locale.
     * @throws MissingResourceException If the <code>ResourceResolver</code>
     *             is not available to access the resources.
     */
    @Override
    public ResourceBundle getResourceBundle(final Locale locale) {
        return getResourceBundle(null, locale);
    }

    @Override
    public ResourceBundle getResourceBundle(final String baseName, Locale locale) {
        return getResourceBundleInternal(null, baseName, locale);
    }

    // ---------- ResourceChangeListener ------------------------------------------------

    private static final class ChangeStatus {
        public ResourceResolver resourceResolver;
        public boolean reloadAll = false;
        public final Set<JcrResourceBundle> reloadBundles = new HashSet<>();
    }

    @Override
    public void onChange(final List<ResourceChange> changes) {
        final ChangeStatus status = new ChangeStatus();
        try {
            for (final ResourceChange change : changes) {
                this.onChange(status, change);
                // if we need to reload all, we can skip all other events
                if ( status.reloadAll ) {
                    break;
                }
            }
            if ( status.reloadAll ) {
                this.scheduleReloadBundles(true);
            } else {
                for(final JcrResourceBundle bundle : status.reloadBundles ) {
                    this.scheduleReloadBundle(bundle);
                }
            }
        } catch ( final LoginException le) {
            log.error("Unable to get service resource resolver.", le);
        } finally {
            if ( status.resourceResolver != null ) {
                status.resourceResolver.close();
            }
        }
    }

    private void onChange(final ChangeStatus status, final ResourceChange change)
    throws LoginException {
        log.debug("onChange: Detecting change {} for path '{}'", change.getType(), change.getPath());

        // if this change was on languageRootPath level this might change basename and locale as well, therefore
        // invalidate everything
        if (languageRootPaths.contains(change.getPath())) {
            log.debug(
                    "onChange: Detected change of cached language root '{}', removing all cached ResourceBundles",
                    change.getPath());
            status.reloadAll = true;
        } else {
            for (final String root : languageRootPaths) {
                if (change.getPath().startsWith(root)) {
                    // figure out which JcrResourceBundles from the cached ones is affected
                    for (JcrResourceBundle bundle : resourceBundleCache.values()) {
                        if (bundle.getLanguageRootPaths().contains(root)) {
                            // reload it
                            log.debug("onChange: Resource changes below '{}', reloading ResourceBundle '{}'",
                                    root, bundle);
                            status.reloadBundles.add(bundle);
                        }
                    }
                }
            }

            // may be a completely new dictionary
            if ( status.resourceResolver == null ) {
                status.resourceResolver = createResourceResolver() ;
            }
            if (isDictionaryResource(status.resourceResolver, change)) {
                status.reloadAll = true;
            }
        }
    }


    private boolean isDictionaryResource(final ResourceResolver resolver, final ResourceChange change) {
        // language node changes happen quite frequently (https://issues.apache.org/jira/browse/SLING-2881)
        // therefore only consider changes either for sling:MessageEntry's
        // or for JSON dictionaries
        // get valuemap
        final Resource resource = resolver.getResource(change.getPath());
        if (resource == null) {
            log.trace("Could not get resource for '{}' for event {}", change.getPath(), change.getType());
            return false;
        }
        if ( resource.getResourceType() == null ) {
            return false;
        }
        if (resource.isResourceType(JcrResourceBundle.RT_MESSAGE_ENTRY)) {
            log.debug("Found new dictionary entry: New {} resource in '{}' detected", JcrResourceBundle.RT_MESSAGE_ENTRY, change.getPath());
            return true;
        }
        final ValueMap valueMap = resource.getValueMap();
        // FIXME: derivatives from mix:Message are not detected
        if (hasMixin(valueMap, JcrResourceBundle.MIXIN_MESSAGE)) {
            log.debug("Found new dictionary entry: New {} resource in '{}' detected", JcrResourceBundle.MIXIN_MESSAGE, change.getPath());
            return true;
        }
        if (change.getPath().endsWith(".json")) {
            // check for mixin
            if (hasMixin(valueMap, JcrResourceBundle.MIXIN_LANGUAGE)) {
                log.debug("Found new dictionary: New {} resource in '{}' detected", JcrResourceBundle.MIXIN_LANGUAGE, change.getPath());
                return true;
            }
        }
        return false;
    }

    private boolean hasMixin(ValueMap valueMap, String mixin) {
        final String[] mixins = valueMap.get(JcrResourceBundle.PROP_MIXINS, String[].class);
        if ( mixins != null ) {
            for(final String m : mixins) {
                if (mixin.equals(m) ) {
                    return true;
                }
            }
        }
        return false;
    }

    private void scheduleReloadBundles(final boolean withDelay) {
        // cancel all reload individual bundle jobs!
        synchronized(scheduledJobNames) {
            for (String scheduledJobName : scheduledJobNames) {
                scheduler.unschedule(scheduledJobName);
            }
        }
        scheduledJobNames.clear();
        // defer this job
        final ScheduleOptions options;
        if (withDelay) {
            options = scheduler.AT(new Date(System.currentTimeMillis() + invalidationDelay));
        } else {
            options = scheduler.NOW();
        }
        options.name("ResourceBundleProvider: reload all resource bundles");
        scheduler.schedule(new Runnable() {
            @Override
            public void run() {
                log.info("Reloading all resource bundles");
                clearCache();
                preloadBundles();
            }
        }, options);
    }

    private void scheduleReloadBundle(final JcrResourceBundle bundle) {
        final Key key = new Key(bundle.getBaseName(), bundle.getLocale());

        // defer this job
        ScheduleOptions options = scheduler.AT(new Date(System.currentTimeMillis() + invalidationDelay));
        final String jobName = "ResourceBundleProvider: reload bundle with key " + key.toString();
        scheduledJobNames.add(jobName);
        options.name(jobName);
        scheduler.schedule(new Runnable() {
            @Override
            public void run() {
                reloadBundle(key);
                scheduledJobNames.remove(jobName);
            }
        }, options);
    }

    void reloadBundle(final Key key) {
        log.info("Reloading resource bundle for {}", key);
        if (!this.preloadBundles) {
            // remove bundle from cache
            resourceBundleCache.remove(key);
            // unregister bundle
            unregisterResourceBundle(key);
        }

        Collection<JcrResourceBundle> dependentBundles = new ArrayList<>();
        // this bundle might be a parent of a cached bundle -> invalidate those dependent bundles as well
        for (JcrResourceBundle bundle : resourceBundleCache.values()) {
            if (bundle.getParent() instanceof JcrResourceBundle) {
                JcrResourceBundle parentBundle = (JcrResourceBundle) bundle.getParent();
                Key parentKey = new Key(parentBundle.getBaseName(), parentBundle.getLocale());
                if (parentKey.equals(key)) {
                    log.debug("Also invalidate dependent bundle {} which has bundle {} as parent", bundle, parentBundle);
                    dependentBundles.add(bundle);
                }
            }
        }
        for (JcrResourceBundle dependentBundle : dependentBundles) {
            reloadBundle(new Key(dependentBundle.getBaseName(), dependentBundle.getLocale()));
        }

        if (preloadBundles) {
            // reload the bundle from the repository (will also fill cache and register as a service)
            getResourceBundleInternal(null, key.baseName, key.locale, true);
        }
    }

    // ---------- SCR Integration ----------------------------------------------

    /**
     * Activates and configures this component with the repository access
     * details and the default locale to use
     * @throws LoginException
     */
    @Activate
    protected void activate(final BundleContext context, final Config config) throws LoginException {
        final String localeString = config.locale_default();
        this.defaultLocale = toLocale(localeString);
        this.preloadBundles = config.preload_bundles();

        this.bundleContext = context;
        this.invalidationDelay = config.invalidation_delay();
        if (this.resourceResolverFactory != null) { // this is only null during test execution!
            scheduleReloadBundles(false);
        }

    }

    @Deactivate
    protected void deactivate() {
        clearCache();
        this.bundleContext = null;
    }

    // ---------- internal -----------------------------------------------------

    /**
     * Internal implementation of the {@link #getResourceBundle(Locale)} method
     * employing the cache of resource bundles. Creates the bundle if not
     * already cached.
     *
     * @throws MissingResourceException If the resource bundles needs to be
     *             created and the <code>ResourceResolver</code> is not
     *             available to access the resources.
     */
    private ResourceBundle getResourceBundleInternal(ResourceResolver optionalResolver, String baseName, Locale locale) {
        return getResourceBundleInternal(optionalResolver, baseName, locale, false);
    }

    private ResourceBundle getResourceBundleInternal(ResourceResolver optionalResolver, final String baseName, Locale locale, final boolean overwriteCache) {
        if (locale == null) {
            locale = defaultLocale;
        }

        final Key key = new Key(baseName, locale);
        JcrResourceBundle resourceBundle = !overwriteCache ? resourceBundleCache.get(key) : null;
        if (resourceBundle != null) {
            log.debug("getResourceBundleInternal({}): got cache hit on first try", key);
        } else {
            if (loadingGuards.get(key) == null) {
                loadingGuards.putIfAbsent(key, new Semaphore(1));
            }
            final Semaphore loadingGuard = loadingGuards.get(key);
            try {
                loadingGuard.acquire();
                resourceBundle = !overwriteCache ? resourceBundleCache.get(key) : null;
                if (resourceBundle != null) {
                    log.debug("getResourceBundleInternal({}): got cache hit on second try", key);
                } else {
                    log.debug("getResourceBundleInternal({}): reading from Repository", key);
                    ResourceResolver localResolver = null;
                    try  {
                        if ( optionalResolver == null ) {
                            localResolver = createResourceResolver();
                            optionalResolver = localResolver;
                        }

                        resourceBundle = createResourceBundle(optionalResolver, key.baseName, key.locale);
                        // put the newly created ResourceBundle to the cache. If it replaces an existing entry unregister the existing
                        // service registration first before re-registering the new ResourceBundle.
                        if (resourceBundleCache.put(key, resourceBundle) != null) {
                            unregisterResourceBundle(key);
                        }
                        registerResourceBundle(key, resourceBundle);

                    } catch ( final LoginException le) {
                        throw (MissingResourceException)new MissingResourceException("Unable to create service resource resolver",
                                baseName,
                                locale.toString()).initCause(le);
                    } finally {
                        if ( localResolver != null ) {
                            localResolver.close();
                        }
                    }
                }
            } catch (InterruptedException e) {
                Thread.interrupted();
            } finally {
                loadingGuard.release();
            }
        }
        log.trace("getResourceBundleInternal({}) ==> {}", key, resourceBundle);
        return resourceBundle;
    }

    private void unregisterResourceBundle(Key key) {
        ServiceRegistration<ResourceBundle> serviceRegistration = null;
        synchronized (this) {
            serviceRegistration = bundleServiceRegistrations.remove(key);
        }
        if (serviceRegistration != null) {
            serviceRegistration.unregister();
        } else {
            log.warn("Could not find resource bundle service for {}", key);
        }
    }

    private void registerResourceBundle(Key key, JcrResourceBundle resourceBundle) {
        Dictionary<String, Object> serviceProps = new Hashtable<>();
        if (key.baseName != null) {
            serviceProps.put("baseName", key.baseName);
        }
        serviceProps.put("locale", key.locale.toString());
        ServiceRegistration<ResourceBundle> serviceReg = bundleContext.registerService(ResourceBundle.class,
                resourceBundle, serviceProps);
        synchronized (this) {
            bundleServiceRegistrations.put(key, serviceReg);
        }

        // register language root paths
        final Set<String> languageRoots = resourceBundle.getLanguageRootPaths();
        this.languageRootPaths.addAll(languageRoots);

        log.debug("registerResourceBundle({}, ...): added service registration and language roots {}", key, languageRoots);
        log.info("Currently loaded dictionaries across all locales: {}", languageRootPaths);
    }

    /**
     * Creates the resource bundle for the give locale.
     *
     * @throws MissingResourceException If the <code>ResourceResolver</code>
     *             is not available to access the resources.
     */
    private JcrResourceBundle createResourceBundle(final ResourceResolver resolver, final String baseName, final Locale locale) {
        final JcrResourceBundle bundle = new JcrResourceBundle(locale, baseName, resolver);

        // set parent resource bundle
        Locale parentLocale = getParentLocale(locale);
        if (parentLocale != null) {
            bundle.setParent(getResourceBundleInternal(resolver, baseName, parentLocale));
        } else {
            bundle.setParent(getRootResourceBundle());
        }

        return bundle;
    }

    /**
     * Returns the parent locale of the given locale. The parent locale is the
     * locale of a locale is defined as follows:
     * <ol>
     * <li>If the locale has an variant, the parent locale is the locale with
     * the same language and country without the variant.</li>
     * <li>If the locale has no variant but a country, the parent locale is the
     * locale with the same language but neither country nor variant.</li>
     * <li>If the locale has no country and not variant and whose language is
     * different from the language of the the configured default locale, the
     * parent locale is the configured default locale.</li>
     * <li>Otherwise there is no parent locale and <code>null</code> is
     * returned.</li>
     * </ol>
     */
    private Locale getParentLocale(Locale locale) {
        if (locale.getVariant().length() != 0) {
            return new Locale(locale.getLanguage(), locale.getCountry());
        } else if (locale.getCountry().length() != 0) {
            return new Locale(locale.getLanguage());
        } else if (!locale.getLanguage().equals(defaultLocale.getLanguage())) {
            return defaultLocale;
        }

        // no more parents
        return null;
    }

    /**
     * Returns a ResourceBundle which is used as the root resource bundle, that
     * is the ultimate parent:
     * <ul>
     * <li><code>getLocale()</code> returns Locale("", "", "")</li>
     * <li><code>handleGetObject(String key)</code> returns the <code>key</code></li>
     * <li><code>getKeys()</code> returns an empty enumeration.
     * </ul>
     *
     * @return The root resource bundle
     */
    private ResourceBundle getRootResourceBundle() {
        if (rootResourceBundle == null) {
            rootResourceBundle = new RootResourceBundle();
        }
        return rootResourceBundle;
    }

    private void clearCache() {
        resourceBundleCache.clear();
        languageRootPaths.clear();

        final List<ServiceRegistration<ResourceBundle>> regs;
        synchronized (this) {
            regs = new ArrayList<>(bundleServiceRegistrations.values());
            bundleServiceRegistrations.clear();
        }
        for (final ServiceRegistration<ResourceBundle> serviceReg : regs) {
            serviceReg.unregister();
        }
    }

    private void preloadBundles() {
        if (preloadBundles) {
            try ( final ResourceResolver resolver = createResourceResolver() ) {
                final Iterator<Map<String, Object>> bundles = resolver.queryResources(
                    JcrResourceBundle.QUERY_LANGUAGE_ROOTS, "xpath");
                final Set<Key> usedKeys = new HashSet<>();
                while (bundles.hasNext()) {
                    final Map<String,Object> bundle = bundles.next();
                    if (bundle.containsKey(PROP_LANGUAGE)) {
                        final Locale locale = toLocale(bundle.get(PROP_LANGUAGE).toString());
                        String baseName = null;
                        if (bundle.containsKey(PROP_BASENAME)) {
                            baseName = bundle.get(PROP_BASENAME).toString();
                        }
                        final Key key = new Key(baseName, locale);
                        if (usedKeys.add(key)) {
                            getResourceBundleInternal(resolver, baseName, locale);
                        }
                    }
                }
            } catch ( final LoginException le) {
                log.error("Unable to create service user resource resolver.", le);
            }
        }
    }

    /**
     * Converts the given <code>localeString</code> to a valid
     * <code>java.util.Locale</code>. It must either be in the format specified by
     * {@link Locale#toString()} or in <a href="https://tools.ietf.org/html/bcp47">BCP 47 format</a>
     * If the locale string is <code>null</code> or empty, the platform default locale is assumed. If
     * the localeString matches any locale available per default on the
     * platform, that platform locale is returned. Otherwise the localeString is
     * parsed and the language and country parts are compared against the
     * languages and countries provided by the platform. Any unsupported
     * language or country is replaced by the platform default language and
     * country.
     * @param localeString the locale as string
     * @return the {@link Locale} being generated from the {@code localeString}
     */
    static Locale toLocale(String localeString) {
        if (localeString == null || localeString.length() == 0) {
            return Locale.getDefault();
        }
        // support BCP 47 compliant strings as well (using a different separator "-" instead of "_")
        localeString = localeString.replaceAll("-", "_");

        // check language and country
        final String[] parts = localeString.split("_");
        if (parts.length == 0) {
            return Locale.getDefault();
        }

        // at least language is available
        String lang = parts[0];
        boolean isValidLanguageCode = false;
        String[] langs = Locale.getISOLanguages();
        for (int i = 0; i < langs.length; i++) {
            if (langs[i].equalsIgnoreCase(lang)) {
                isValidLanguageCode = true;
                break;
            }
        }
        if (!isValidLanguageCode) {
            lang = Locale.getDefault().getLanguage();
        }

        // only language
        if (parts.length == 1) {
            return new Locale(lang);
        }

        // country is also available
        String country = parts[1];
        boolean isValidCountryCode = false;
        // allow user-assigned codes (https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#User-assigned_code_elements)
        if (USER_ASSIGNED_COUNTRY_CODES_PATTERN.matcher(country.toLowerCase()).matches()) {
            isValidCountryCode = true;
        } else {
            String[] countries = Locale.getISOCountries();
            for (int i = 0; i < countries.length; i++) {
                if (countries[i].equalsIgnoreCase(country)) {
                    isValidCountryCode = true; // signal ok
                    break;
                }
            }
        }
        if (!isValidCountryCode) {
            country = Locale.getDefault().getCountry();
        }

        // language and country
        if (parts.length == 2) {
            return new Locale(lang, country);
        }

        // language, country and variant
        return new Locale(lang, country, parts[2]);
    }

    //---------- internal class

    /**
     * The <code>Key</code> class encapsulates the base name and Locale in a
     * single object that can be used as the key in a <code>HashMap</code>.
     */
    protected static final class Key {

        final String baseName;

        final Locale locale;

        // precomputed hash code, because this will always be used due to
        // this instance being used as a key in a HashMap.
        private final int hashCode;

        Key(final String baseName, final Locale locale) {

            int hc = 0;
            if (baseName != null) {
                hc += 17 * baseName.hashCode();
            }
            if (locale != null) {
                hc += 13 * locale.hashCode();
            }

            this.baseName = baseName;
            this.locale = locale;
            this.hashCode = hc;
        }

        @Override
        public int hashCode() {
            return hashCode;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == this) {
                return true;
            } else if (obj instanceof Key) {
                Key other = (Key) obj;
                return equals(this.baseName, other.baseName)
                    && equals(this.locale, other.locale);
            }

            return false;
        }

        private static boolean equals(Object o1, Object o2) {
            if (o1 == null) {
                if (o2 != null) {
                    return false;
                }
            } else if (!o1.equals(o2)) {
                return false;
            }
            return true;
        }

        @Override
        public String toString() {
            return "Key(" + baseName + ", " + locale + ")";
        }
    }
}
