001/*
002 *    GeoAPI - Java interfaces for OGC/ISO standards
003 *    Copyright © 2023-2024 Open Geospatial Consortium, Inc.
004 *    http://www.geoapi.org
005 *
006 *    Licensed under the Apache License, Version 2.0 (the "License");
007 *    you may not use this file except in compliance with the License.
008 *    You may obtain a copy of the License at
009 *
010 *        http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *    Unless required by applicable law or agreed to in writing, software
013 *    distributed under the License is distributed on an "AS IS" BASIS,
014 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 *    See the License for the specific language governing permissions and
016 *    limitations under the License.
017 */
018package org.opengis.annotation;
019
020import java.io.IOException;
021import java.io.InputStream;
022import java.util.Locale;
023import java.util.Properties;
024import java.util.ResourceBundle;
025
026
027/**
028 * Localized resources for elements from OGC/ISO standards.
029 * This class provides {@link ResourceBundle} or {@link Properties} objects
030 * in which keys can have the following patterns:
031 *
032 * <ul>
033 *   <li>{@code <class>}</li>
034 *   <li>{@code <class>.<member>}</li>
035 * </ul>
036 *
037 * where {@code <class>} and {@code <member>} are the UML identifiers as specified in the OGC/ISO standards.
038 * Those identifiers for GeoAPI interfaces and methods are given by {@link UML#identifier()}.
039 *
040 * <h2>Example</h2>
041 * The {@code "CI_RoleCode.principalInvestigator"} key is associated to the following values:
042 *
043 * <ul>
044 *   <li>{@link Locale#ENGLISH}<ul>
045 *     <li><b>{@code CodeList}:</b> <q>Principal investigator</q></li>
046 *     <li><b>{@code Description}:</b> <q>Key party responsible for gathering information and conducting research.</q></li>
047 *   </ul></li>
048 *   <li>{@link Locale#FRENCH}<ul>
049 *     <li><b>{@code CodeList}:</b> <q>Maître d’œuvre principal</q></li>
050 *     <li><b>{@code Description}:</b> <q>Acteur qui a assuré la réalisation de la ressource,
051 *         éventuellement en faisant appel à des co-traitants ou des sous-traitants.</q></li>
052 *   </ul></li>
053 * </ul>
054 *
055 * @author  Martin Desruisseaux (Geomatys)
056 * @version 3.1
057 * @since   3.1
058 */
059public final class ResourceBundles {
060    /**
061     * Do not allow instantiation of this class.
062     */
063    private ResourceBundles() {
064    }
065
066    /**
067     * Returns the localized resources of the specified base name.
068     *
069     * @param  basename  the base name of the resource bundle.
070     * @param  locale    the locale for which a resource bundle is desired, or {@code null} for the default locale.
071     * @return localized texts for the specified or default locale.
072     */
073    private static ResourceBundle resources(final String basename, final Locale locale) {
074        return (locale == null)
075                ? ResourceBundle.getBundle(basename)
076                : ResourceBundle.getBundle(basename, locale);
077    }
078
079    /**
080     * Returns the localized resources for the code list labels.
081     * Keys are {@code <class>} or {@code <class>.<member>} strings where {@code <class>}
082     * and {@code <member>} are UML identifiers as specified in the OGC/ISO standards.
083     * Values are human-readable texts in the specified locale if available, or in English as a fallback.
084     *
085     * <h4>Example</h4>
086     * {@code codeLists.getString("CI_RoleCode.principalInvestigator")} returns
087     * <q>Principal investigator</q> if the specified locale is {@link Locale#ENGLISH}, or
088     * <q>Maître d’œuvre principal</q> if the specified locale is {@link Locale#FRENCH}.
089     *
090     * @param  locale    the locale for which a resource bundle is desired, or {@code null} for the default locale.
091     * @return localized texts for the specified or default locale.
092     */
093    public static ResourceBundle codeLists(final Locale locale) {
094        return resources("org.opengis.metadata.CodeLists", locale);
095    }
096
097    /**
098     * Returns the localized resources for the property descriptions.
099     * Keys are {@code <class>} or {@code <class>.<member>} strings where {@code <class>}
100     * and {@code <member>} are UML identifiers as specified in the OGC/ISO standards.
101     * Values are human-readable texts in the specified locale if available, or in English as a fallback.
102     *
103     * <h4>Example</h4>
104     * {@code descriptions.getString("CI_RoleCode.principalInvestigator")} returns
105     * <q>Key party responsible for gathering information and conducting research.</q>
106     * if the specified locale is {@link Locale#ENGLISH}, or
107     * <q>Acteur qui a assuré la réalisation de la ressource, éventuellement en faisant appel
108     * à des co-traitants ou des sous-traitants.</q> if the specified locale is {@link Locale#FRENCH}.
109     *
110     * @param  locale  the locale for which a resource bundle is desired, or {@code null} for the default locale.
111     * @return localized texts for the specified or default locale.
112     */
113    public static ResourceBundle descriptions(final Locale locale) {
114        return resources("org.opengis.metadata.Descriptions", locale);
115    }
116
117    /**
118     * Returns the mapping from UML identifiers to Java classes.
119     * The returned map is the converse of {@link UML#identifier()}.
120     *
121     * <h4>Examples</h4>
122     * {@code classIndex.getString("CRS")} returns
123     * {@code "org.opengis.referencing.crs.CoordinateReferenceSystem"}.
124     *
125     * <h4>Performance note</h4>
126     * This method loads the resources in a new {@code Properties} instance every time
127     * that this method is invoked, because {@code Properties} is a mutable object.
128     * Callers should invoke this method only once and cache the map.
129     *
130     * @return mapping from UML identifiers to Java classes in a new {@code Properties} instance.
131     * @throws IOException if the properties cannot be loaded.
132     *
133     * @see UML#identifier()
134     */
135    public static Properties classIndex() throws IOException {
136        final Properties classIndex = new Properties(INDEX_CAPACITY);
137        try (InputStream in = UML.class.getResourceAsStream("class-index.properties")) {
138            classIndex.load(in);
139        }
140        return classIndex;
141    }
142
143    /**
144     * Number of lines in the {@code "class-index.properties"} file.
145     */
146    static final int INDEX_CAPACITY = 257;
147}