Author: desruisseaux Date: Wed Nov 7 17:00:36 2012 New Revision: 1406720 URL: http://svn.apache.org/viewvc?rev=1406720&view=rev Log: Tried to make LocalizedParseException public API less convolved (even if it is internal API).
Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/LocalizedParseException.java sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/AngleFormat.java sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/internal/util/LocalizedParseExceptionTest.java Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/LocalizedParseException.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/LocalizedParseException.java?rev=1406720&r1=1406719&r2=1406720&view=diff ============================================================================== --- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/LocalizedParseException.java (original) +++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/LocalizedParseException.java Wed Nov 7 17:00:36 2012 @@ -19,26 +19,23 @@ package org.apache.sis.internal.util; import java.util.Locale; import java.text.ParsePosition; import java.text.ParseException; -import org.apache.sis.util.Arrays; -import org.apache.sis.util.CharSequences; import org.apache.sis.util.Workaround; +import org.apache.sis.util.CharSequences; import org.apache.sis.util.resources.Errors; /** * A {@link ParseException} in which {@link #getLocalizedMessage()} returns the message in the - * parser locale. - * - * {@section Special cases} - * This class has special cases for the following classes: + * parser locale. This exception contains the error message in two languages: * * <ul> - * <li>{@link org.apache.sis.util.tree.TreeTable.Node}, for {@code TreeTableFormat} needs.</li> + * <li>{@link ParseException#getMessage()} returns the message in the default locale.</li> + * <li>{@link ParseException#getLocalizedMessage()} returns the message in the locale given + * in argument to the constructor.</li> * </ul> * - * Those special cases are checked in the {@link #specialCase(Object)} method and may change - * without notice in any future SIS version. Ideally we should use package-private classes, - * but this is not always practical. + * This locale given to the constructor is usually the {@link java.text.Format} locale, + * which is presumed to be the end-user locale. * * @author Martin Desruisseaux (Geomatys) * @since 0.3 @@ -57,45 +54,78 @@ public final class LocalizedParseExcepti private final Locale locale; /** - * The arguments for the localization message, as an array of length 1, 2 or 3. - * - * <ul> - * <li>The type of objects to be parsed, as a {@link Class}. - * Omitted if the error is "unexpected end of string".</li> - * <li>The text to be parsed, as a {@link String}.</li> - * <li>The characters that couldn't be parsed. Omitted if empty.</li> - * </ul> + * The resources key as one of the {@link Errors.Keys} constant. + */ + private final int key; + + /** + * The arguments for the localization message. */ private final Object[] arguments; /** - * Constructs a ParseException with the specified detail message and offset. + * Constructs a {@code ParseException} with a message formatted from the given resource key + * and message arguments. This is the most generic constructor. * * @param locale The locale for {@link #getLocalizedMessage()}. + * @param key The resource key as one of the {@link Errors.Keys} constant. * @param arguments The value of {@link #arguments(String, ParsePosition)}. * @param errorOffset The position where the error is found while parsing. */ - public LocalizedParseException(final Locale locale, final Object[] arguments, final int errorOffset) { - super(message(null, arguments), errorOffset); + public LocalizedParseException(final Locale locale, final int key, final Object[] arguments, final int errorOffset) { + super(Errors.format(key, arguments), errorOffset); this.locale = locale; this.arguments = arguments; + this.key = key; } /** - * If the given class is one of the hard-coded special cases, returns the key of the - * error message to use for that case. Otherwise returns -1. The list of special cases - * is an undocumented feature for SIS internal usage only, and may change in any future - * version. + * Constructs a {@code ParseException} with a message formatted from the given resource key + * and unparseable string. This convenience constructor fetches the word starting at the error + * index, and uses that word as the single argument associated to the resource key. * - * @param type The {@link Class} of the object for which to format an error message. - * @return The resource keys for the given class, or -1 if the given type is not a special case. + * @param locale The locale for {@link #getLocalizedMessage()}. + * @param key The resource key as one of the {@link Errors.Keys} constant. + * @param text The full text that {@code Format} failed to parse. + * @param errorOffset The position where the error is found while parsing. */ - private static int specialCase(final Object type) { - if (type == org.apache.sis.util.collection.TreeTable.Node.class) { - return Errors.Keys.NodeHasNoParent_1; - } - // More special cases may be added here in any future version. - return -1; + public LocalizedParseException(final Locale locale, final int key, final CharSequence text, final int errorOffset) { + this(locale, key, new Object[] {CharSequences.token(text, errorOffset)}, errorOffset); + } + + /** + * Creates a {@link ParseException} with a localized message built from the given parsing + * information. This convenience constructor creates a message of the kind "<cite>Can not + * parse string "text" as an object of type 'type'</cite>". + * + * @param locale The locale for {@link ParseException#getLocalizedMessage()}. + * @param type The type of objects parsed by the {@link java.text.Format}. + * @param text The full text that {@code Format} failed to parse. + * @param pos Index of the {@linkplain ParsePosition#getIndex() first parsed character}, + * together with the {@linkplain ParsePosition#getErrorIndex() error index}. + */ + public LocalizedParseException(final Locale locale, final Class<?> type, final CharSequence text, final ParsePosition pos) { + this(locale, type, text, pos.getIndex(), pos.getErrorIndex()); + } + + /** + * Workaround for RFE #4093999 + * ("Relax constraint on placement of this()/super() call in constructors"). + */ + @Workaround(library="JDK", version="1.7") + private LocalizedParseException(final Locale locale, final Class<?> type, + final CharSequence text, final int offset, final int errorOffset) + { + this(locale, arguments(type, text, offset, Math.max(offset, errorOffset)), errorOffset); + } + + /** + * Workaround for RFE #4093999 + * ("Relax constraint on placement of this()/super() call in constructors"). + */ + @Workaround(library="JDK", version="1.7") + private LocalizedParseException(final Locale locale, final Object[] arguments, final int errorOffset) { + this(locale, key(arguments), arguments, errorOffset); } /** @@ -109,16 +139,12 @@ public final class LocalizedParseExcepti * @return The {@code arguments} value to give to the constructor. */ @Workaround(library="JDK", version="1.7") - public static Object[] arguments(final Class<?> type, CharSequence text, final int offset, final int errorOffset) { + private static Object[] arguments(final Class<?> type, CharSequence text, final int offset, final int errorOffset) { if (errorOffset >= text.length()) { return new Object[] {text}; } - final CharSequence erroneous = CharSequences.token(text, errorOffset); - switch (specialCase(type)) { - case Errors.Keys.NodeHasNoParent_1: return new Object[] {type, erroneous}; - // More special cases may be added here in any future version. - } text = text.subSequence(offset, text.length()); + final CharSequence erroneous = CharSequences.token(text, errorOffset); if (erroneous.length() == 0) { return new Object[] {type, text}; } @@ -126,21 +152,19 @@ public final class LocalizedParseExcepti } /** - * Formats the error message using the given locale and arguments. + * Workaround for RFE #4093999 + * ("Relax constraint on placement of this()/super() call in constructors"). */ - private static String message(final Locale locale, Object[] arguments) { - int key = specialCase(arguments[0]); - if (key >= 0) { - arguments = Arrays.remove(arguments, 0, 1); - } else { - switch (arguments.length) { - case 1: key = Errors.Keys.UnexpectedEndOfString_1; break; - case 2: key = Errors.Keys.UnparsableStringForClass_2; break; - case 3: key = Errors.Keys.UnparsableStringForClass_3; break; - default: throw new AssertionError(); - } + @Workaround(library="JDK", version="1.7") + private static int key(final Object[] arguments) { + final int key; + switch (arguments.length) { + case 1: key = Errors.Keys.UnexpectedEndOfString_1; break; + case 2: key = Errors.Keys.UnparsableStringForClass_2; break; + case 3: key = Errors.Keys.UnparsableStringForClass_3; break; + default: throw new AssertionError(); } - return Errors.getResources(locale).getString(key, arguments); + return key; } /** @@ -156,7 +180,7 @@ public final class LocalizedParseExcepti */ @Override public String getLocalizedMessage() { - return message(locale, arguments); + return Errors.getResources(locale).getString(key, arguments); } /** @@ -164,6 +188,6 @@ public final class LocalizedParseExcepti */ @Override public String getLocalizedMessage(final Locale locale) { - return message(locale, arguments); + return Errors.getResources(locale).getString(key, arguments); } } Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/AngleFormat.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/AngleFormat.java?rev=1406720&r1=1406719&r2=1406720&view=diff ============================================================================== --- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/AngleFormat.java (original) +++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/AngleFormat.java Wed Nov 7 17:00:36 2012 @@ -1537,9 +1537,7 @@ BigBoss: switch (skipSuffix(source, p final Angle angle = parse(source, pos, true); final int offset = pos.getIndex(); if (skipSpaces(source, offset) != source.length()) { - final int errorOffset = Math.max(offset, pos.getErrorIndex()); - throw new LocalizedParseException(locale, LocalizedParseException.arguments( - Angle.class, source, offset, errorOffset), errorOffset); + throw new LocalizedParseException(locale, Angle.class, source, pos); } return angle; } Modified: sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/internal/util/LocalizedParseExceptionTest.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/internal/util/LocalizedParseExceptionTest.java?rev=1406720&r1=1406719&r2=1406720&view=diff ============================================================================== --- sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/internal/util/LocalizedParseExceptionTest.java (original) +++ sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/internal/util/LocalizedParseExceptionTest.java Wed Nov 7 17:00:36 2012 @@ -20,10 +20,10 @@ import java.util.Locale; import java.text.ParseException; import java.text.ParsePosition; import org.apache.sis.measure.Angle; -import org.apache.sis.util.collection.TreeTable; +import org.apache.sis.util.resources.Errors; +import org.apache.sis.util.Exceptions; import org.apache.sis.test.DependsOn; import org.apache.sis.test.TestCase; -import org.apache.sis.util.Exceptions; import org.junit.Test; import static org.junit.Assert.*; @@ -32,9 +32,6 @@ import static org.junit.Assert.*; /** * Tests the {@link LocalizedParseException} class. * - * <p><b>Note:</b> this test case contains a method which was previously part of public API, - * but has been removed because considered too convolved.</p> - * * @author Martin Desruisseaux (Geomatys) * @since 0.3 (derived from geotk-3.04) * @version 0.3 @@ -43,44 +40,15 @@ import static org.junit.Assert.*; @DependsOn(org.apache.sis.util.resources.IndexedResourceBundleTest.class) public final strictfp class LocalizedParseExceptionTest extends TestCase { /** - * Creates a {@link ParseException} with a localized message built from the given parsing - * information. The exception returned by this method contains the error message in two - * languages: - * - * <ul> - * <li>{@link ParseException#getMessage()} returns the message in the default locale.</li> - * <li>{@link ParseException#getLocalizedMessage()} returns the message in the locale given - * in argument to this method.</li> - * </ul> - * - * This locale given to this method is usually the {@link java.text.Format} locale, - * which is presumed to be the end-user locale. - * - * @param locale The locale for {@link ParseException#getLocalizedMessage()}. - * @param type The type of objects parsed by the {@link java.text.Format}. - * @param text The text that {@code Format} failed to parse. - * @param pos Index of the {@linkplain ParsePosition#getIndex() first parsed character}, - * together with the {@linkplain ParsePosition#getErrorIndex() error index}. - * @return The localized exception. - */ - public static ParseException createParseException(final Locale locale, final Class<?> type, - final CharSequence text, final ParsePosition pos) - { - final int offset = pos.getIndex(); - final int errorOffset = Math.max(offset, pos.getErrorIndex()); - return new LocalizedParseException(locale, - LocalizedParseException.arguments(type, text, offset, errorOffset), errorOffset); - } - - /** - * Tests the {@link LocalizedParseException} constructor. This method also tests - * {@link Exceptions#getLocalizedMessage(Throwable, Locale)} as a side-effect. + * Tests the {@link LocalizedParseException} constructor using the default string. + * This method also tests {@link Exceptions#getLocalizedMessage(Throwable, Locale)} + * as a side-effect. */ @Test - public void testCreateParseException() { + public void testAutomaticMessage() { final ParsePosition pos = new ParsePosition(0); pos.setErrorIndex(5); - final ParseException e = createParseException( + final ParseException e = new LocalizedParseException( Locale.CANADA, Angle.class, "Some text to parse", pos); String message = e.getLocalizedMessage(); assertTrue(message, message.contains("Some text to parse")); @@ -95,15 +63,13 @@ public final strictfp class LocalizedPar } /** - * Tests the undocumented special case, for SIS internal usage only. - * Such special cases many change in any future version without notice. + * Tests the {@link LocalizedParseException} constructor using a given resource key + * and the text that we failed to parse. */ @Test - public void testSpecialCase() { - final ParsePosition pos = new ParsePosition(0); - pos.setErrorIndex(5); - final ParseException e = createParseException( - Locale.CANADA, TreeTable.Node.class, "Some text to parse", pos); + public void testResourceKeyForText() { + final ParseException e = new LocalizedParseException( + Locale.CANADA, Errors.Keys.NodeHasNoParent_1, "Some text to parse", 5); String message = e.getLocalizedMessage(); assertTrue(message, message.contains("Node âtextâ has no parent.")); }