001/*
002 * Copyright 2002-2018 the original author or authors.
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 *      https://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
017package org.springframework.core.io.support;
018
019import java.util.Locale;
020
021import org.springframework.core.io.DefaultResourceLoader;
022import org.springframework.core.io.Resource;
023import org.springframework.core.io.ResourceLoader;
024import org.springframework.lang.Nullable;
025import org.springframework.util.Assert;
026
027/**
028 * Helper class for loading a localized resource,
029 * specified through name, extension and current locale.
030 *
031 * @author Juergen Hoeller
032 * @since 1.2.5
033 */
034public class LocalizedResourceHelper {
035
036        /** The default separator to use in-between file name parts: an underscore. */
037        public static final String DEFAULT_SEPARATOR = "_";
038
039
040        private final ResourceLoader resourceLoader;
041
042        private String separator = DEFAULT_SEPARATOR;
043
044
045        /**
046         * Create a new LocalizedResourceHelper with a DefaultResourceLoader.
047         * @see org.springframework.core.io.DefaultResourceLoader
048         */
049        public LocalizedResourceHelper() {
050                this.resourceLoader = new DefaultResourceLoader();
051        }
052
053        /**
054         * Create a new LocalizedResourceHelper with the given ResourceLoader.
055         * @param resourceLoader the ResourceLoader to use
056         */
057        public LocalizedResourceHelper(ResourceLoader resourceLoader) {
058                Assert.notNull(resourceLoader, "ResourceLoader must not be null");
059                this.resourceLoader = resourceLoader;
060        }
061
062        /**
063         * Set the separator to use in-between file name parts.
064         * Default is an underscore ("_").
065         */
066        public void setSeparator(@Nullable String separator) {
067                this.separator = (separator != null ? separator : DEFAULT_SEPARATOR);
068        }
069
070
071        /**
072         * Find the most specific localized resource for the given name,
073         * extension and locale:
074         * <p>The file will be searched with locations in the following order,
075         * similar to {@code java.util.ResourceBundle}'s search order:
076         * <ul>
077         * <li>[name]_[language]_[country]_[variant][extension]
078         * <li>[name]_[language]_[country][extension]
079         * <li>[name]_[language][extension]
080         * <li>[name][extension]
081         * </ul>
082         * <p>If none of the specific files can be found, a resource
083         * descriptor for the default location will be returned.
084         * @param name the name of the file, without localization part nor extension
085         * @param extension the file extension (e.g. ".xls")
086         * @param locale the current locale (may be {@code null})
087         * @return the most specific localized resource found
088         * @see java.util.ResourceBundle
089         */
090        public Resource findLocalizedResource(String name, String extension, @Nullable Locale locale) {
091                Assert.notNull(name, "Name must not be null");
092                Assert.notNull(extension, "Extension must not be null");
093
094                Resource resource = null;
095
096                if (locale != null) {
097                        String lang = locale.getLanguage();
098                        String country = locale.getCountry();
099                        String variant = locale.getVariant();
100
101                        // Check for file with language, country and variant localization.
102                        if (variant.length() > 0) {
103                                String location =
104                                                name + this.separator + lang + this.separator + country + this.separator + variant + extension;
105                                resource = this.resourceLoader.getResource(location);
106                        }
107
108                        // Check for file with language and country localization.
109                        if ((resource == null || !resource.exists()) && country.length() > 0) {
110                                String location = name + this.separator + lang + this.separator + country + extension;
111                                resource = this.resourceLoader.getResource(location);
112                        }
113
114                        // Check for document with language localization.
115                        if ((resource == null || !resource.exists()) && lang.length() > 0) {
116                                String location = name + this.separator + lang + extension;
117                                resource = this.resourceLoader.getResource(location);
118                        }
119                }
120
121                // Check for document without localization.
122                if (resource == null || !resource.exists()) {
123                        String location = name + extension;
124                        resource = this.resourceLoader.getResource(location);
125                }
126
127                return resource;
128        }
129
130}