This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
commit 847ab7ed972ce1cc0a1f765d4583fa19aa04dcc7 Author: Martin Desruisseaux <[email protected]> AuthorDate: Fri Nov 6 11:09:59 2020 +0100 Clarify which locale is used in error messages. --- .../main/java/org/apache/sis/io/wkt/Element.java | 34 ++++++++++---------- .../main/java/org/apache/sis/io/wkt/Formatter.java | 36 +++++++++++++++++----- .../main/java/org/apache/sis/io/wkt/WKTFormat.java | 33 +++++++++++++++----- .../java/org/apache/sis/io/wkt/WKTFormatTest.java | 3 +- .../java/org/apache/sis/math/StatisticsFormat.java | 3 +- .../sis/util/collection/TreeTableFormat.java | 4 +-- 6 files changed, 76 insertions(+), 37 deletions(-) diff --git a/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Element.java b/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Element.java index a1e66d1..137203e 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Element.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Element.java @@ -111,7 +111,7 @@ final class Element implements Serializable { * The locale to be used for formatting an error message if the parsing fails, or {@code null} for * the system default. This is <strong>not</strong> the locale for parting number or date values. */ - private final Locale locale; + private final Locale errorLocale; /** * Constructs a root element. @@ -120,10 +120,10 @@ final class Element implements Serializable { * @param singleton the only child for this root. */ Element(final String name, final Element singleton) { - keyword = name; - offset = singleton.offset; - locale = singleton.locale; - children = new LinkedList<>(); // Needs to be a modifiable collection. + keyword = name; + offset = singleton.offset; + errorLocale = singleton.errorLocale; + children = new LinkedList<>(); // Needs to be a modifiable collection. children.add(singleton); isEnumeration = false; } @@ -135,7 +135,7 @@ final class Element implements Serializable { offset = toCopy.offset; keyword = toCopy.keyword; isEnumeration = toCopy.isEnumeration; - locale = toCopy.locale; + errorLocale = toCopy.errorLocale; children = new LinkedList<>(toCopy.children); // Needs to be a modifiable collection. final ListIterator<Object> it = children.listIterator(); while (it.hasNext()) { @@ -175,7 +175,7 @@ final class Element implements Serializable { * Find the first keyword in the specified string. If a keyword is found, then * the position is set to the index of the first character after the keyword. */ - locale = parser.errorLocale; + errorLocale = parser.errorLocale; offset = position.getIndex(); final int length = text.length(); int lower = skipLeadingWhitespaces(text, offset, length); @@ -238,7 +238,7 @@ final class Element implements Serializable { if (fragment == null) { position.setIndex(offset); position.setErrorIndex(lower); - throw new UnparsableObjectException(locale, Errors.Keys.NoSuchValue_1, new Object[] {id}, lower); + throw new UnparsableObjectException(errorLocale, Errors.Keys.NoSuchValue_1, new Object[] {id}, lower); } if (!fragment.isEnumeration) { fragment = new Element(fragment); @@ -388,8 +388,8 @@ final class Element implements Serializable { * @return the exception to be thrown. */ final ParseException parseFailed(final Exception cause) { - return new UnparsableObjectException(locale, Errors.Keys.ErrorIn_2, - new String[] {keyword, Exceptions.getLocalizedMessage(cause, locale)}, offset).initCause(cause); + return new UnparsableObjectException(errorLocale, Errors.Keys.ErrorIn_2, + new String[] {keyword, Exceptions.getLocalizedMessage(cause, errorLocale)}, offset).initCause(cause); } /** @@ -415,7 +415,7 @@ final class Element implements Serializable { arguments = new CharSequence[] {keyword, CharSequences.token(text, errorIndex)}; } position.setIndex(offset); - return new UnparsableObjectException(locale, errorKey, arguments, errorIndex); + return new UnparsableObjectException(errorLocale, errorKey, arguments, errorIndex); } /** @@ -429,7 +429,7 @@ final class Element implements Serializable { position.setIndex(offset); position.setErrorIndex(errorIndex); final StringBuilder buffer = new StringBuilder(2).appendCodePoint(c); - return new UnparsableObjectException(locale, Errors.Keys.MissingCharacterInElement_2, + return new UnparsableObjectException(errorLocale, Errors.Keys.MissingCharacterInElement_2, new CharSequence[] {keyword, buffer}, errorIndex); } @@ -443,7 +443,7 @@ final class Element implements Serializable { if (keyword != null) { error += keyword.length(); } - return new UnparsableObjectException(locale, Errors.Keys.MissingComponentInElement_2, + return new UnparsableObjectException(errorLocale, Errors.Keys.MissingComponentInElement_2, new String[] {keyword, key}, error); } @@ -472,7 +472,7 @@ final class Element implements Serializable { res = Errors.Keys.MissingComponentInElement_2; args = new String[] {keyword, expected}; } - return new UnparsableObjectException(locale, res, args, offset); + return new UnparsableObjectException(errorLocale, res, args, offset); } /** @@ -496,7 +496,7 @@ final class Element implements Serializable { key = Errors.Keys.IllegalCoordinateSystem_1; value = cs.getName().getCode(); } - return new UnparsableObjectException(locale, key, new String[] {value}, offset); + return new UnparsableObjectException(errorLocale, key, new String[] {value}, offset); } @@ -577,7 +577,7 @@ final class Element implements Serializable { iterator.remove(); final Number number = (Number) object; if (number instanceof Float || number instanceof Double) { - throw new UnparsableObjectException(locale, Errors.Keys.UnparsableStringForClass_2, + throw new UnparsableObjectException(errorLocale, Errors.Keys.UnparsableStringForClass_2, new Object[] {Integer.class, number}, offset); } return number.intValue(); @@ -764,7 +764,7 @@ final class Element implements Serializable { if (value instanceof Element) { CollectionsExt.addToMultiValuesMap(ignoredElements, ((Element) value).keyword, keyword); } else { - throw new UnparsableObjectException(locale, Errors.Keys.UnexpectedValueInElement_2, + throw new UnparsableObjectException(errorLocale, Errors.Keys.UnexpectedValueInElement_2, new Object[] {keyword, value}, offset + keyword.length()); } } diff --git a/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Formatter.java b/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Formatter.java index 5f28fbd..11a1d0c 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Formatter.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Formatter.java @@ -105,7 +105,7 @@ import org.apache.sis.math.Vector; * </ul> * * @author Martin Desruisseaux (IRD, Geomatys) - * @version 1.0 + * @version 1.1 * * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html">WKT 2 specification</a> * @see <a href="http://www.geoapi.org/3.0/javadoc/org/opengis/referencing/doc-files/WKT.html">Legacy WKT 1</a> @@ -141,6 +141,8 @@ public class Formatter implements Localized { /** * The locale for the localization of international strings. * This is not the same than {@link Symbols#getLocale()}. + * + * @see #errorLocale */ private final Locale locale; @@ -345,6 +347,13 @@ public class Formatter implements Localized { private Warnings warnings; /** + * The locale for error messages (not for formatting). + * + * @see #locale + */ + private final Locale errorLocale; + + /** * Creates a new formatter instance with the default configuration. */ public Formatter() { @@ -364,6 +373,7 @@ public class Formatter implements Localized { ArgumentChecks.ensureNonNull("symbols", symbols); ArgumentChecks.ensureBetween("indentation", WKTFormat.SINGLE_LINE, Byte.MAX_VALUE, indentation); this.locale = Locale.getDefault(Locale.Category.DISPLAY); + this.errorLocale = locale; this.convention = convention; this.authority = convention.getNameAuthority(); this.symbols = symbols.immutable(); @@ -383,11 +393,19 @@ public class Formatter implements Localized { /** * Constructor for private use by {@link WKTFormat} only. This allows to use the number format * created by {@link WKTFormat#createFormat(Class)}, which may be overridden by the user. + * + * @param locale the locale for the localization of international strings. + * @param errorLocale the locale for error messages (not for parsing), or {@code null} for the system default. + * @param symbols the symbols to use for this formatter. + * @param numberFormat the object to use for formatting numbers. + * @param dateFormat the object to use for formatting dates. + * @param unitFormat the object to use for formatting unit symbols. */ - Formatter(final Locale locale, final Symbols symbols, final NumberFormat numberFormat, - final DateFormat dateFormat, final UnitFormat unitFormat) + Formatter(final Locale locale, final Locale errorLocale, final Symbols symbols, + final NumberFormat numberFormat, final DateFormat dateFormat, final UnitFormat unitFormat) { this.locale = locale; + this.errorLocale = errorLocale; this.convention = Convention.DEFAULT; this.authority = Convention.DEFAULT.getNameAuthority(); this.symbols = symbols; @@ -662,12 +680,14 @@ public class Formatter implements Localized { final int stackDepth = enclosingElements.size(); for (int i=stackDepth; --i >= 0;) { if (enclosingElements.get(i) == object) { - throw new IllegalStateException(Errors.getResources(locale).getString(Errors.Keys.CircularReference)); + throw new IllegalStateException(Errors.getResources(errorLocale) + .getString(Errors.Keys.CircularReference)); } } enclosingElements.add(object); if (hasContextualUnit < 0) { // Test if leftmost bit is set to 1. - throw new IllegalStateException(Errors.getResources(locale).getString(Errors.Keys.TreeDepthExceedsMaximum)); + throw new IllegalStateException(Errors.getResources(errorLocale) + .getString(Errors.Keys.TreeDepthExceedsMaximum)); } hasContextualUnit <<= 1; /* @@ -1741,7 +1761,7 @@ public class Formatter implements Localized { */ private Warnings warnings() { if (warnings == null) { - warnings = new Warnings(locale, false, Collections.emptyMap()); + warnings = new Warnings(errorLocale, false, Collections.emptyMap()); } return warnings; } @@ -1825,7 +1845,7 @@ public class Formatter implements Localized { if (colors != null) { buffer.append(X364.BACKGROUND_RED.sequence()).append(X364.BOLD.sequence()).append(' '); } - Vocabulary.getResources(locale).appendLabel(Vocabulary.Keys.Warnings, buffer); + Vocabulary.getResources(errorLocale).appendLabel(Vocabulary.Keys.Warnings, buffer); if (colors != null) { buffer.append(' ').append(X364.RESET.sequence()).append(X364.FOREGROUND_RED.sequence()); } @@ -1833,7 +1853,7 @@ public class Formatter implements Localized { final int n = warnings.getNumMessages(); final Set<String> done = new HashSet<>(); for (int i=0; i<n; i++) { - String message = Exceptions.getLocalizedMessage(warnings.getException(i), locale); + String message = Exceptions.getLocalizedMessage(warnings.getException(i), errorLocale); if (message == null) { message = warnings.getMessage(i); } diff --git a/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/WKTFormat.java b/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/WKTFormat.java index 9c53c96..f9ab3e9 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/WKTFormat.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/WKTFormat.java @@ -333,6 +333,19 @@ public class WKTFormat extends CompoundFormat<Object> { } /** + * Returns the locale to use for error messages. Other {@link CompoundFormat} classes use the system default. + * But this class uses a compromise: not exactly the locale used for {@link InternationalString} because that + * locale is often fixed to English, and not exactly the system default neither because this "error locale" + * is also used for warnings. The compromise implemented in this method may change in any future version. + * + * @see #errors() + */ + private Locale getErrorLocale() { + final Locale locale = getLocale(Locale.Category.DISPLAY); + return (locale != null && locale != Locale.ROOT) ? locale : Locale.getDefault(Locale.Category.DISPLAY); + } + + /** * Returns the symbols used for parsing and formatting WKT. This method returns an unmodifiable instance. * Modifications, if desired, should be applied on a {@linkplain Symbols#clone() clone} of the returned object. * @@ -634,8 +647,7 @@ public class WKTFormat extends CompoundFormat<Object> { type != MathTransformFactory.class && type != CoordinateOperationFactory.class) { - throw new IllegalArgumentException(Errors.getResources(getLocale()) - .getString(Errors.Keys.IllegalArgumentValue_2, "type", type)); + throw new IllegalArgumentException(errors().getString(Errors.Keys.IllegalArgumentValue_2, "type", type)); } } @@ -751,7 +763,7 @@ public class WKTFormat extends CompoundFormat<Object> { final Element element = parseFragment(wkt, pos); final int index = CharSequences.skipLeadingWhitespaces(wkt, pos.getIndex(), wkt.length()); if (index < wkt.length()) { - throw new UnparsableObjectException(getLocale(), Errors.Keys.UnexpectedCharactersAfter_2, + throw new UnparsableObjectException(getErrorLocale(), Errors.Keys.UnexpectedCharactersAfter_2, new Object[] {name + " = " + element.keyword + "[…]", CharSequences.token(wkt, index)}, index); } // `fragments` map has been created by `parser(true)`. @@ -760,7 +772,7 @@ public class WKTFormat extends CompoundFormat<Object> { } error = Errors.Keys.ElementAlreadyPresent_1; } - throw new IllegalArgumentException(Errors.getResources(getLocale()).getString(error, name)); + throw new IllegalArgumentException(errors().getString(error, name)); } /** @@ -817,7 +829,7 @@ public class WKTFormat extends CompoundFormat<Object> { (UnitFormat) getFormat(Unit.class), convention, (transliterator != null) ? transliterator : Transliterator.DEFAULT, - getLocale(), + getErrorLocale(), factories()); } return parser; @@ -879,7 +891,7 @@ public class WKTFormat extends CompoundFormat<Object> { */ Formatter formatter = this.formatter; if (formatter == null) { - formatter = new Formatter(getLocale(), symbols, + formatter = new Formatter(getLocale(), getErrorLocale(), symbols, (NumberFormat) getFormat(Number.class), (DateFormat) getFormat(Date.class), (UnitFormat) getFormat(Unit.class)); @@ -905,7 +917,7 @@ public class WKTFormat extends CompoundFormat<Object> { warnings.setRoot(object); } if (!valid) { - throw new ClassCastException(Errors.getResources(getLocale()).getString( + throw new ClassCastException(errors().getString( Errors.Keys.IllegalArgumentClass_2, "object", object.getClass())); } if (buffer != toAppendTo) { @@ -956,6 +968,13 @@ public class WKTFormat extends CompoundFormat<Object> { } /** + * Convenience methods for resources for error message in the locale given by {@link #getLocale()}. + */ + private Errors errors() { + return Errors.getResources(getErrorLocale()); + } + + /** * Returns a clone of this format. The clone has the same configuration (including any added * {@linkplain #addFragment fragments}), except the {@linkplain #getWarnings() warnings}. * diff --git a/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/WKTFormatTest.java b/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/WKTFormatTest.java index 8af1cff..e81ed67 100644 --- a/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/WKTFormatTest.java +++ b/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/WKTFormatTest.java @@ -16,6 +16,7 @@ */ package org.apache.sis.io.wkt; +import java.util.Locale; import java.util.Collections; import java.text.ParseException; import org.opengis.referencing.crs.VerticalCRS; @@ -381,7 +382,7 @@ public final strictfp class WKTFormatTest extends TestCase { public void testWarnings() throws ParseException { DefaultPrimeMeridian pm = new DefaultPrimeMeridian(Collections.singletonMap( DefaultPrimeMeridian.NAME_KEY, "Invalid “$name” here"), -10, Units.DEGREE); - format = new WKTFormat(null, null); + format = new WKTFormat(Locale.US, null); final String wkt = format.format(pm); final Warnings warnings = format.getWarnings(); assertNotNull("warnings", warnings); diff --git a/core/sis-utility/src/main/java/org/apache/sis/math/StatisticsFormat.java b/core/sis-utility/src/main/java/org/apache/sis/math/StatisticsFormat.java index 99f2bfe..e785fc4 100644 --- a/core/sis-utility/src/main/java/org/apache/sis/math/StatisticsFormat.java +++ b/core/sis-utility/src/main/java/org/apache/sis/math/StatisticsFormat.java @@ -226,8 +226,7 @@ public class StatisticsFormat extends TabularFormat<Statistics> { */ @Override public Statistics parse(CharSequence text, ParsePosition pos) throws ParseException { - throw new ParseException(Errors.getResources(getLocale()) - .getString(Errors.Keys.UnsupportedOperation_1, "parse"), pos.getIndex()); + throw new ParseException(Errors.format(Errors.Keys.UnsupportedOperation_1, "parse"), pos.getIndex()); } /** diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java b/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java index c00e883..d06e8af 100644 --- a/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java +++ b/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java @@ -340,9 +340,9 @@ public class TreeTableFormat extends TabularFormat<TreeTable> { } /** - * Returns the locale to use for code lists, international strings and exception messages. + * Returns the locale to use for code lists, international strings and localized messages of exceptions. */ - final Locale getDisplayLocale() { + private Locale getDisplayLocale() { return getLocale(Locale.Category.DISPLAY); }
