| /* |
| * 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.iso; |
| |
| import java.util.Locale; |
| import java.util.Formatter; |
| import java.util.Formattable; |
| import java.util.FormattableFlags; |
| import org.opengis.util.InternationalString; |
| import org.apache.sis.internal.util.Strings; |
| import org.apache.sis.util.CharSequences; |
| |
| |
| /** |
| * Base class for character strings that has been internationalized into several locales. |
| * The {@link InternationalString} interface is used instead of the {@link String} class |
| * whenever an attribute needs to be internationalization capable. |
| * |
| * <p>The default value (as returned by {@link #toString()} and other {@link CharSequence} methods) |
| * is the string in the current {@linkplain Locale#getDefault() system-wide default locale}. |
| * The {@linkplain Comparable natural ordering} is defined by the value returned by {@link #toString()}.</p> |
| * |
| * <div class="section">Substituting a free text by a code list</div> |
| * The ISO standard allows to substitute some character strings in the <cite>"free text"</cite> domain |
| * by a {@link org.opengis.util.CodeList} value. This can be done with: |
| * |
| * <ul> |
| * <li>{@link Types#getCodeTitle(CodeList)} for getting the {@link InternationalString} |
| * instance to store in a metadata property.</li> |
| * <li>{@link Types#forCodeTitle(CharSequence)} for retrieving the {@link org.opengis.util.CodeList} |
| * previously stored as an {@code InternationalString}.</li> |
| * </ul> |
| * |
| * @author Martin Desruisseaux (IRD, Geomatys) |
| * @version 0.3 |
| * @since 0.3 |
| * @module |
| */ |
| public abstract class AbstractInternationalString implements InternationalString, Formattable { |
| /** |
| * The string in the {@linkplain Locale#getDefault() system default} locale, or {@code null} |
| * if this string has not yet been determined. This is the default string returned by |
| * {@link #toString()} and others methods from the {@link CharSequence} interface. |
| * |
| * <div class="section">Thread safety</div> |
| * For thread safety this field shall either be read and written in a synchronized block, |
| * or be fixed at construction time and never changed after than point. All other usages |
| * are prohibited. |
| * |
| * <div class="section">Serialization</div> |
| * This field is not serialized because serialization is often used for data transmission |
| * between a server and a client, and the client may not use the same locale than the server. |
| * We want the locale to be examined again on the client side. |
| */ |
| transient String defaultValue; |
| |
| /** |
| * Constructs an international string. |
| */ |
| protected AbstractInternationalString() { |
| } |
| |
| /** |
| * Returns the length of the string in the {@linkplain Locale#getDefault() default locale}. |
| * This is the length of the string returned by {@link #toString()}. |
| * |
| * @return length of the string in the default locale. |
| */ |
| @Override |
| public int length() { |
| return CharSequences.length(toString()); |
| } |
| |
| /** |
| * Returns the character of the string in the {@linkplain Locale#getDefault() default locale} |
| * at the specified index. This is a character of the string returned by {@link #toString()}. |
| * |
| * @param index the index of the character. |
| * @return the character at the specified index. |
| * @throws IndexOutOfBoundsException if the specified index is out of bounds. |
| */ |
| @Override |
| public char charAt(final int index) throws IndexOutOfBoundsException { |
| return toString().charAt(index); |
| } |
| |
| /** |
| * Returns a subsequence of the string in the {@linkplain Locale#getDefault() default locale}. |
| * The subsequence is a {@link String} object starting with the character value at the specified |
| * index and ending with the character value at index {@code end - 1}. |
| * |
| * @param start the start index, inclusive. |
| * @param end the end index, exclusive. |
| * @return the specified subsequence. |
| * @throws IndexOutOfBoundsException if {@code start} or {@code end} is out of range. |
| */ |
| @Override |
| public CharSequence subSequence(final int start, final int end) { |
| return toString().substring(start, end); |
| } |
| |
| /** |
| * Returns this string in the given locale. If no string is available in the given locale, |
| * then some fallback locale is used. The fallback locale is implementation-dependent, and |
| * is not necessarily the same than the default locale used by the {@link #toString()} method. |
| * |
| * <div class="section">Handling of <code>Locale.ROOT</code> argument value</div> |
| * {@link Locale#ROOT} can be given to this method for requesting a "unlocalized" string, |
| * typically some programmatic values like enumerations or identifiers. While identifiers |
| * often look like English words, {@code Locale.ROOT} is not considered synonymous to |
| * {@link Locale#ENGLISH} because the values may differ in the way numbers and dates are |
| * formatted (e.g. using the ISO 8601 standard for dates instead than English conventions). |
| * |
| * <div class="section">Handling of <code>null</code> argument value</div> |
| * The {@code Locale.ROOT} constant is new in Java 6. Some other libraries designed for Java 5 |
| * use the {@code null} value for "unlocalized" strings. Apache SIS accepts {@code null} value |
| * for inter-operability with those libraries. However the behavior is implementation dependent: |
| * some subclasses will take {@code null} as a synonymous of the system default locale, while |
| * other subclasses will take {@code null} as a synonymous of the root locale. In order to |
| * ensure determinist behavior, client code are encouraged to specify only non-null values. |
| * |
| * @param locale the desired locale for the string to be returned. |
| * @return the string in the given locale if available, or in an |
| * implementation-dependent fallback locale otherwise. |
| * |
| * @see Locale#getDefault() |
| * @see Locale#ROOT |
| */ |
| @Override |
| public abstract String toString(Locale locale); |
| |
| /** |
| * Returns this string in the default locale. Invoking this method is equivalent to invoking |
| * <code>{@linkplain #toString(Locale) toString}({@linkplain Locale#getDefault()})</code>. |
| * |
| * <p>All methods from {@link CharSequence} operate on this string. |
| * This string is also used as the criterion for {@linkplain Comparable natural ordering}.</p> |
| * |
| * @return the string in the default locale. |
| */ |
| @Override |
| public synchronized String toString() { |
| String text = defaultValue; |
| if (text == null) { |
| text = toString(Locale.getDefault()); |
| if (text == null) { |
| return ""; |
| } |
| defaultValue = text; |
| } |
| return text; |
| } |
| |
| /** |
| * Formats this international string using the given formatter. |
| * This method appends the string obtained by: |
| * |
| * <blockquote><code> |
| * {@linkplain #toString(Locale) toString}(formatter.{@linkplain Formatter#locale()}) |
| * </code></blockquote> |
| * |
| * @param formatter the formatter to use for formatting this string. |
| * @param flags a bitmask of {@link FormattableFlags} values. |
| * @param width the minimum number of characters, or -1 if none. |
| * @param precision the maximum number of characters (before expanding to the {@code width}), |
| * or -1 for no restriction. |
| */ |
| @Override |
| public void formatTo(final Formatter formatter, final int flags, final int width, final int precision) { |
| Strings.formatTo(formatter, flags, width, precision, toString(formatter.locale())); |
| } |
| |
| /** |
| * Compares this string with the specified object for order. This method compares |
| * the string in the {@linkplain Locale#getDefault() default locale}, as returned |
| * by {@link #toString()}. |
| * |
| * @param object the string to compare with this string. |
| * @return a negative number if this string is before the given string, |
| * a positive number if after, or 0 if equals. |
| */ |
| @Override |
| public int compareTo(final InternationalString object) { |
| return toString().compareTo(object.toString()); |
| } |
| } |