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 96af230e7abcd5107dbb468a578d69892473c1b3 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Tue Dec 12 19:20:57 2023 +0100 Parse Unit of Measurement in "http://www.opengis.net/def/uom/UCUM/0/" URL. --- .../apache/sis/metadata/internal/NameMeaning.java | 2 +- .../main/org/apache/sis/measure/UnitFormat.java | 46 +++-- .../org/apache/sis/util/internal/Constants.java | 5 + .../apache/sis/util/internal/DefinitionURI.java | 81 ++++----- .../org/apache/sis/measure/UnitFormatTest.java | 117 ++++++------- .../sis/util/internal/DefinitionURITest.java | 190 +++++++++++---------- 6 files changed, 238 insertions(+), 203 deletions(-) diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/NameMeaning.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/NameMeaning.java index c3e04cc161..81f2fd8c91 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/NameMeaning.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/NameMeaning.java @@ -114,7 +114,7 @@ public final class NameMeaning extends Static { entry(Constants.OGC), // Open Geospatial Consortium entry("OGC-WFS"), // OGC Web Feature Service entry("SI"), // Système International d'Unités - entry("UCUM"), // Unified Code for Units of Measure + entry(Constants.UCUM), // Unified Code for Units of Measure entry("UNSD"), // United Nations Statistics Division entry("USNO")); // United States Naval Observatory diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitFormat.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitFormat.java index fa6b3fcbf6..e30444db26 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitFormat.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitFormat.java @@ -61,6 +61,10 @@ import org.apache.sis.util.logging.Logging; * and whitespaces around path separators), then {@code "####"} is parsed as an integer and forwarded to the * {@link Units#valueOfEPSG(int)} method. * + * <p>If a character sequence starts with {@code "http://www.opengis.net/def/uom/UCUM/0/####"} (ignoring case + * and whitespaces around path separators), then {@code "####"} is parsed as a symbol as if the URL before it + * was absent.</p> + * * <h2>Note on netCDF unit symbols</h2> * In netCDF files, values of "unit" attribute are concatenations of an angular unit with an axis direction, * as in {@code "degrees_east"} or {@code "degrees_north"}. This class ignores those suffixes and unconditionally @@ -71,7 +75,7 @@ import org.apache.sis.util.logging.Logging; * each thread should have its own {@code UnitFormat} instance. * * @author Martin Desruisseaux (Geomatys) - * @version 1.4 + * @version 1.5 * * @see Units#valueOf(String) * @@ -84,10 +88,13 @@ public class UnitFormat extends Format implements javax.measure.format.UnitForma private static final long serialVersionUID = -3064428584419360693L; /** - * Whether the parsing of authority codes such as {@code "EPSG:9001"} is allowed. + * The authorities to accept, or {@code null} for disabling authority parsing. + * Codes may be URLs such as {@code "http://www.opengis.net/def/uom/UCUM/0/d"} + * or URNs such as {@code "EPSG:9001"}. The order of authority names matter, + * because the index is used for identifying the authority. */ @Configuration - private static final boolean PARSE_AUTHORITY_CODES = true; + private static final String[] AUTHORITIES = {Constants.EPSG, Constants.UCUM}; /** * The unit name for degrees (not necessarily angular), to be handled in a special way. @@ -1113,19 +1120,30 @@ appPow: if (unit == null) { */ int end = symbols.length(); int start = CharSequences.skipLeadingWhitespaces(symbols, position.getIndex(), end); - if (PARSE_AUTHORITY_CODES) { - final String code = DefinitionURI.codeOf("uom", Constants.EPSG, symbols); - if (code != null) { + if (AUTHORITIES != null) { + final Map.Entry<Integer, String> entry = DefinitionURI.codeOf("uom", AUTHORITIES, symbols); + if (entry != null) { + Unit<?> unit = null; NumberFormatException failure = null; - try { - final Unit<?> unit = Units.valueOfEPSG(Integer.parseInt(code)); - if (unit != null) { - position.setIndex(end); - finish(position); - return unit; + final String code = entry.getValue(); + switch (entry.getKey()) { + case 0: { // EPSG + try { + unit = Units.valueOfEPSG(Integer.parseInt(code)); + } catch (NumberFormatException e) { + failure = e; + } + break; } - } catch (NumberFormatException e) { - failure = e; + case 1: { // UCUM + unit = parse(code); + break; + } + } + if (unit != null) { + position.setIndex(end); + finish(position); + return unit; } throw (MeasurementParseException) new MeasurementParseException( Errors.format(Errors.Keys.UnknownUnit_1, diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/Constants.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/Constants.java index 058a91b3a4..ccc708b113 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/Constants.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/Constants.java @@ -59,6 +59,11 @@ public final class Constants extends Static { */ public static final String GEOTIFF = "GeoTIFF"; + /** + * The {@value} code space. + */ + public static final String UCUM = "UCUM"; + /** * The {@value} code space. */ diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/DefinitionURI.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/DefinitionURI.java index 7e8a483d7f..8ec72c4001 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/DefinitionURI.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/DefinitionURI.java @@ -18,12 +18,12 @@ package org.apache.sis.util.internal; import java.util.Map; import java.util.TreeMap; +import static java.util.AbstractMap.SimpleEntry; import static java.util.logging.Logger.getLogger; import org.apache.sis.util.CharSequences; import org.apache.sis.util.logging.Logging; import org.apache.sis.system.Loggers; import static org.apache.sis.util.CharSequences.*; -import static org.apache.sis.util.ArgumentChecks.ensureNonNull; /** @@ -264,7 +264,7 @@ public final class DefinitionURI { } /** - * Attempts to parse the given URI, which may either a URN or URL. + * Attempts to parse the given URI, which may be either a URN or URL. * If this method does not recognize the given URI, then it returns {@code null}. * If the given URI is incomplete, then the {@link #code} value will be {@code null}. * @@ -272,7 +272,6 @@ public final class DefinitionURI { * @return the parse result, or {@code null} if the given URI is not recognized. */ public static DefinitionURI parse(final String uri) { - ensureNonNull("uri", uri); return parse(uri, false, -1, uri.length()); } @@ -506,52 +505,56 @@ public final class DefinitionURI { * <li>The GML form (e.g. {@code "http://www.opengis.net/gml/srs/epsg.xml#4326"}).</li> * </ul> * - * @param type the expected object type (e.g. {@code "crs"}) in lower cases. See class javadoc for a list of types. - * @param authority the expected authority, typically {@code "EPSG"}. See class javadoc for a list of authorities. - * @param uri the URI to parse. - * @return the code part of the given URI, or {@code null} if the codespace does not match the given type - * and authority, the code is empty, or the code is followed by parameters. + * @param type the expected object type (e.g. {@code "crs"}) in lower cases. See class javadoc for a list of types. + * @param authorities the expected authorities, typically {@code "EPSG"}. See class javadoc for a list of authorities. + * @param uri the URI to parse. + * @return the code part of the given URI together with the authority index, or {@code null} if the codespace + * does not match any given type and authority, the code is empty, or the code is followed by parameters. */ - public static String codeOf(final String type, final String authority, final CharSequence uri) { - ensureNonNull("type", type); - ensureNonNull("authority", authority); + public static Map.Entry<Integer,String> codeOf(final String type, final String[] authorities, final CharSequence uri) { final int length = uri.length(); int s = indexOf(uri, SEPARATOR, 0, length); if (s >= 0) { - int from = skipLeadingWhitespaces(uri, 0, s); // Start of authority part. - if (skipTrailingWhitespaces(uri, from, s) - from == authority.length() - && CharSequences.regionMatches(uri, from, authority, true)) - { - from = skipLeadingWhitespaces(uri, s+1, length); // Start of code part. - if (from >= length) { - return null; - } - /* - * The substring is expected to contains zero or one more separator character. - * If present, then the separator character and everything before it are ignored. - * The ignored part should be the version number, but this is not verified. - */ - s = indexOf(uri, SEPARATOR, from, length); - if (s >= 0) { - from = skipLeadingWhitespaces(uri, s+1, length); - if (from >= length || indexOf(uri, SEPARATOR, from, length) >= 0) { - /* - * If the remaining substring contains more ':' characters, then it means that - * the code has parameters, e.g. "urn:ogc:def:crs:OGC:1.3:AUTO42003:1:-100:45". - */ + int from = skipLeadingWhitespaces(uri, 0, s); // Start of authority part. + final int span = skipTrailingWhitespaces(uri, from, s) - from; + for (int i=0; i < authorities.length; i++) { + final String authority = authorities[i]; + if (span == authority.length() && CharSequences.regionMatches(uri, from, authority, true)) { + from = skipLeadingWhitespaces(uri, s+1, length); // Start of code part. + if (from >= length) { return null; } + /* + * The substring is expected to contains zero or one more separator character. + * If present, then the separator character and everything before it are ignored. + * The ignored part should be the version number, but this is not verified. + */ + s = indexOf(uri, SEPARATOR, from, length); + if (s >= 0) { + from = skipLeadingWhitespaces(uri, s+1, length); + if (from >= length || indexOf(uri, SEPARATOR, from, length) >= 0) { + /* + * If the remaining substring contains more ':' characters, then it means that + * the code has parameters, e.g. "urn:ogc:def:crs:OGC:1.3:AUTO42003:1:-100:45". + */ + return null; + } + } + final String code = uri.subSequence(from, skipTrailingWhitespaces(uri, from, length)).toString(); + return new SimpleEntry<>(i, code); } - return uri.subSequence(from, skipTrailingWhitespaces(uri, from, length)).toString(); } final DefinitionURI def = parse(uri.toString()); - if (def != null && def.parameters == null) { - if (type.equalsIgnoreCase(def.type) && authority.equalsIgnoreCase(def.authority)) { - String code = def.code; - if (code == null) { - code = def.version; // May happen with for example "EPSG:4326" instead of "EPSG::4326". + if (def != null && def.parameters == null && type.equalsIgnoreCase(def.type)) { + for (int i=0; i < authorities.length; i++) { + final String authority = authorities[i]; + if (authority.equalsIgnoreCase(def.authority)) { + String code = def.code; + if (code == null) { + code = def.version; // May happen with for example "EPSG:4326" instead of "EPSG::4326". + } + return new SimpleEntry<>(i, code); } - return code; } } } diff --git a/endorsed/src/org.apache.sis.util/test/org/apache/sis/measure/UnitFormatTest.java b/endorsed/src/org.apache.sis.util/test/org/apache/sis/measure/UnitFormatTest.java index 7a2553b530..9badced427 100644 --- a/endorsed/src/org.apache.sis.util/test/org/apache/sis/measure/UnitFormatTest.java +++ b/endorsed/src/org.apache.sis.util/test/org/apache/sis/measure/UnitFormatTest.java @@ -29,7 +29,7 @@ import org.apache.sis.util.Characters; // Test dependencies import org.junit.Test; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.*; import org.apache.sis.test.DependsOn; import org.apache.sis.test.DependsOnMethod; import org.apache.sis.test.TestCase; @@ -136,7 +136,7 @@ public final class UnitFormatTest extends TestCase { verify(declared, "DECIBEL", "", "dB", "decibel", Units.DECIBEL); verify(declared, "GAL", "L∕T²", "Gal", "gal", Units.GAL); verify(declared, "METRES_PER_SECOND_SQUARED", "L∕T²", "m∕s²", "metres per second squared", Units.METRES_PER_SECOND_SQUARED); - assertTrue("Missing units in test:" + declared, declared.isEmpty()); + assertTrue(declared.isEmpty(), () -> "Missing units in test:" + declared); } /** @@ -150,19 +150,19 @@ public final class UnitFormatTest extends TestCase { * @param unit the unit to verify. */ private static void verify(final Set<String> declared, final String field, final String dimension, final String symbol, final String name, final Unit<?> unit) { - assertEquals(field, dimension, String.valueOf(unit.getDimension())); - assertEquals(field, symbol, UnitFormat.INSTANCE.format(unit)); + assertEquals(dimension, String.valueOf(unit.getDimension()), field); + assertEquals(symbol, UnitFormat.INSTANCE.format(unit), field); if (name != null) { - assertEquals(field, name, UnitFormat.getBundle(Locale.UK).getString(symbol)); + assertEquals(name, UnitFormat.getBundle(Locale.UK).getString(symbol), field); for (int i=0; i<name.length();) { final int c = name.codePointAt(i); - assertTrue(name, AbstractUnit.isSymbolChar(c) || Character.isWhitespace(c)); + assertTrue(AbstractUnit.isSymbolChar(c) || Character.isWhitespace(c), name); i += Character.charCount(c); } } for (int i=0; i<symbol.length();) { final int c = symbol.codePointAt(i); - assertTrue(symbol, AbstractUnit.isSymbolChar(c) || Characters.isSuperScript(c) || c == '∕'); + assertTrue(AbstractUnit.isSymbolChar(c) || Characters.isSuperScript(c) || c == '∕', symbol); i += Character.charCount(c); } declared.remove(field); @@ -196,23 +196,15 @@ public final class UnitFormatTest extends TestCase { assertEquals("mètre", f.format(Units.METRE)); assertEquals("sFoo", f.format(Units.SECOND)); assertSame(Units.METRE, f.parse("mètre")); - try { - f.parse("mFoo"); - fail("“mFoo” should not be assigned to unit anymore."); - } catch (MeasurementParseException e) { - final String message = e.getMessage(); - assertTrue(message, message.contains("mFoo")); - } - /* - * Verify that we cannot specify invalid unit label. - */ - try { - f.label(Units.METRE, "m¹"); - fail("Should not accept labels ending with a digit."); - } catch (IllegalArgumentException e) { - final String message = e.getMessage(); - assertTrue(message, message.contains("m¹")); - } + + String message; + // “mFoo” should not be assigned to unit anymore. + message = assertThrows(MeasurementParseException.class, () -> f.parse("mFoo")).getMessage(); + assertTrue(message.contains("mFoo"), message); + + // Should not accept labels ending with a digit. + message = assertThrows(IllegalArgumentException.class, () -> f.label(Units.METRE, "m¹")).getMessage(); + assertTrue(message.contains("m¹"), message); } /** @@ -396,23 +388,18 @@ public final class UnitFormatTest extends TestCase { assertSame(Units.CELSIUS, f.parse("deg C")); assertSame(Units.WATT, f.parse("watt")); assertSame(Units.UNITY, f.parse("unity")); - try { - f.parse("degree foo"); - fail("Should not accept unknown unit."); - } catch (MeasurementParseException e) { - final String message = e.getMessage(); - assertTrue(message, message.contains("degree")); - assertTrue(message, message.contains("foo")); - } - // Tests with localisation. - try { - f.parse("mètre cube"); - fail("Should not accept localized unit unless requested."); - } catch (MeasurementParseException e) { - final String message = e.getMessage(); - assertTrue(message, message.contains("mètre")); - assertTrue(message, message.contains("cube")); - } + + String message; + // Should not accept unknown unit. + message = assertThrows(MeasurementParseException.class, () -> f.parse("degree foo")).getMessage(); + assertTrue(message.contains("degree"), message); + assertTrue(message.contains("foo"), message); + + // Should not accept localized unit unless requested. + message = assertThrows(MeasurementParseException.class, () -> f.parse("mètre cube")).getMessage(); + assertTrue(message.contains("mètre"), message); + assertTrue(message.contains("cube"), message); + f.setLocale(Locale.FRANCE); assertSame(Units.CUBIC_METRE, f.parse("mètre cube")); } @@ -439,6 +426,16 @@ public final class UnitFormatTest extends TestCase { assertSame(Units.METRES_PER_SECOND, f.parse("urn:ogc:def:uom:EPSG::1026")); } + /** + * Tests parsing a unit defined by a URL. + */ + @Test + public void testParseURL() { + final UnitFormat f = new UnitFormat(Locale.UK); + assertSame(Units.METRE, f.parse("http://www.opengis.net/def/uom/EPSG/0/9001")); + assertSame(Units.DAY, f.parse("http://www.opengis.net/def/uom/UCUM/0/d")); + } + /** * Tests parsing of symbols without arithmetic operations other than exponent. */ @@ -480,21 +477,19 @@ public final class UnitFormatTest extends TestCase { * When the unit contain an exponent, the conversion factor shall be raised * to that exponent too. */ - assertEquals("km²", 1E+6, Units.toStandardUnit(f.parse("km²")), STRICT); - assertEquals("kJ²", 1E+6, Units.toStandardUnit(f.parse("kJ²")), STRICT); + assertEquals(1E+6, Units.toStandardUnit(f.parse("km²")), "km²"); + assertEquals(1E+6, Units.toStandardUnit(f.parse("kJ²")), "kJ²"); /* * Verify that prefix are not accepted for conventional units. It would either be illegal prefix duplication * (for example we should not accept "kkm" as if it was "k" + "km") or confusing (for example "a" stands for * the tropical year, "ha" could be understood as 100 tropical years but is actually used for hectare). */ assertSame(Units.TROPICAL_YEAR, f.parse("a")); - try { - f.parse("ka"); - fail("Should not accept prefix in ConventionalUnit."); - } catch (MeasurementParseException e) { - final String message = e.getMessage(); - assertTrue(message, message.contains("ka")); - } + + String message; + // Should not accept prefix in ConventionalUnit. + message = assertThrows(MeasurementParseException.class, () -> f.parse("ka")).getMessage(); + assertTrue(message.contains("ka"), message); } /** @@ -522,14 +517,12 @@ public final class UnitFormatTest extends TestCase { final UnitFormat f = new UnitFormat(Locale.UK); assertSame(Units.METRES_PER_SECOND, f.parse("m s**-1")); assertEqualsIgnoreSymbol(Units.KILOGRAM.divide(Units.SQUARE_METRE), f.parse("kg m**-2")); - try { - f.parse("degree minute"); - fail("Should not accept unknown sentence even if each individual word is known."); - } catch (MeasurementParseException e) { - final String message = e.getMessage(); - assertTrue(message, message.contains("degree")); - assertTrue(message, message.contains("minute")); - } + + // Should not accept unknown sentence even if each individual word is known. + String message; + message = assertThrows(MeasurementParseException.class, () -> f.parse("degree minute")).getMessage(); + assertTrue(message.contains("degree"), message); + assertTrue(message.contains("minute"), message); } /** @@ -619,8 +612,8 @@ public final class UnitFormatTest extends TestCase { final UnitFormat f = new UnitFormat(Locale.UK); final ParsePosition pos = new ParsePosition(4); assertSame(Units.CENTIMETRE, f.parse("ABC cm foo", pos)); - assertEquals("ParsePosition.getIndex()", 6, pos.getIndex()); - assertEquals("ParsePosition.getErrorIndex()", -1, pos.getErrorIndex()); + assertEquals( 6, pos.getIndex(), "ParsePosition.getIndex()"); + assertEquals(-1, pos.getErrorIndex(), "ParsePosition.getErrorIndex()"); /* * Adding "cm DEF" as a unit label should allow UnitFormat to recognize those characters. * We associate a random unit to that label, just for testing purpose. @@ -628,8 +621,8 @@ public final class UnitFormatTest extends TestCase { pos.setIndex(4); f.label(Units.HECTARE, "cm foo"); assertEqualsIgnoreSymbol(Units.HECTARE, f.parse("ABC cm foo", pos)); - assertEquals("ParsePosition.getIndex()", 10, pos.getIndex()); - assertEquals("ParsePosition.getErrorIndex()", -1, pos.getErrorIndex()); + assertEquals(10, pos.getIndex(), "ParsePosition.getIndex()"); + assertEquals(-1, pos.getErrorIndex(), "ParsePosition.getErrorIndex()"); } /** diff --git a/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/internal/DefinitionURITest.java b/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/internal/DefinitionURITest.java index c8b4cf2652..f361f385d8 100644 --- a/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/internal/DefinitionURITest.java +++ b/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/internal/DefinitionURITest.java @@ -16,9 +16,11 @@ */ package org.apache.sis.util.internal; +import java.util.Map; + // Test dependencies import org.junit.Test; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.*; import org.apache.sis.test.DependsOnMethod; import org.apache.sis.test.TestCase; @@ -53,15 +55,15 @@ public final class DefinitionURITest extends TestCase { @Test public void testParse() { final DefinitionURI parsed = DefinitionURI.parse(" urn:ogc:def: crs : EPSG: 8.2 :4326 "); - assertNotNull("DefinitionURI", parsed); - assertEquals ("isHTTP", false, parsed.isHTTP); - assertEquals ("isGML", false, parsed.isGML); - assertEquals ("type", "crs", parsed.type); - assertEquals ("authority", "EPSG", parsed.authority); - assertEquals ("version", "8.2", parsed.version); - assertEquals ("code", "4326", parsed.code); - assertNull ("parameters", parsed.parameters); - assertEquals ("toString()", "urn:ogc:def:crs:EPSG:8.2:4326", parsed.toString()); + assertNotNull(parsed, "DefinitionURI"); + assertEquals (false, parsed.isHTTP, "isHTTP"); + assertEquals (false, parsed.isGML, "isGML"); + assertEquals ("crs", parsed.type, "type"); + assertEquals ("EPSG", parsed.authority, "authority"); + assertEquals ("8.2", parsed.version, "version"); + assertEquals ("4326", parsed.code, "code"); + assertNull ( parsed.parameters, "parameters"); + assertEquals ("urn:ogc:def:crs:EPSG:8.2:4326", parsed.toString(), "toString()"); } /** @@ -71,15 +73,15 @@ public final class DefinitionURITest extends TestCase { @Test public void testParseWithoutVersion() { final DefinitionURI parsed = DefinitionURI.parse("URN :X-OGC: Def:crs:EPSG::4326"); - assertNotNull("DefinitionURI", parsed); - assertEquals ("isHTTP", false, parsed.isHTTP); - assertEquals ("isGML", false, parsed.isGML); - assertEquals ("type", "crs", parsed.type); - assertEquals ("authority", "EPSG", parsed.authority); - assertNull ("version", parsed.version); - assertEquals ("code", "4326", parsed.code); - assertNull ("parameters", parsed.parameters); - assertEquals ("toString()", "urn:ogc:def:crs:EPSG::4326", parsed.toString()); + assertNotNull(parsed, "DefinitionURI"); + assertEquals (false, parsed.isHTTP, "isHTTP"); + assertEquals (false, parsed.isGML, "isGML"); + assertEquals ("crs", parsed.type, "type"); + assertEquals ("EPSG", parsed.authority, "authority"); + assertNull ( parsed.version, "version"); + assertEquals ("4326", parsed.code, "code"); + assertNull ( parsed.parameters, "parameters"); + assertEquals ("urn:ogc:def:crs:EPSG::4326", parsed.toString(), "toString()"); } /** @@ -90,16 +92,16 @@ public final class DefinitionURITest extends TestCase { @DependsOnMethod("testParse") public void testParseWithParameters() { final DefinitionURI parsed = DefinitionURI.parse("urn:ogc:def:crs:OGC:1.3:AUTO42003:1:-100:45"); - assertNotNull("DefinitionURI", parsed); - assertEquals ("isHTTP", false, parsed.isHTTP); - assertEquals ("isGML", false, parsed.isGML); - assertEquals ("type", "crs", parsed.type); - assertEquals ("authority", "OGC", parsed.authority); - assertEquals ("version", "1.3", parsed.version); - assertEquals ("code", "AUTO42003", parsed.code); - assertNotNull("parameters", parsed.parameters); - assertArrayEquals("parameters", new String[] {"1", "-100", "45"}, parsed.parameters); - assertEquals("toString()", "urn:ogc:def:crs:OGC:1.3:AUTO42003:1:-100:45", parsed.toString()); + assertNotNull(parsed, "DefinitionURI"); + assertEquals (false, parsed.isHTTP, "isHTTP"); + assertEquals (false, parsed.isGML, "isGML"); + assertEquals ("crs", parsed.type, "type"); + assertEquals ("OGC", parsed.authority, "authority"); + assertEquals ("1.3", parsed.version, "version"); + assertEquals ("AUTO42003", parsed.code, "code"); + assertNotNull( parsed.parameters, "parameters"); + assertArrayEquals(new String[] {"1", "-100", "45"}, parsed.parameters, "parameters"); + assertEquals("urn:ogc:def:crs:OGC:1.3:AUTO42003:1:-100:45", parsed.toString(), "toString()"); } /** @@ -109,15 +111,15 @@ public final class DefinitionURITest extends TestCase { @DependsOnMethod("testParse") public void testParseHTTP() { final DefinitionURI parsed = DefinitionURI.parse("http://www.opengis.net/def/crs/epsg/0/4326"); - assertNotNull("DefinitionURI", parsed); - assertEquals ("isHTTP", true, parsed.isHTTP); - assertEquals ("isGML", false, parsed.isGML); - assertEquals ("type", "crs", parsed.type); - assertEquals ("authority", "epsg", parsed.authority); - assertNull ("version", parsed.version); - assertEquals ("code", "4326", parsed.code); - assertNull ("parameters", parsed.parameters); - assertEquals ("toString()", "http://www.opengis.net/def/crs/epsg/0/4326", parsed.toString()); + assertNotNull(parsed, "DefinitionURI"); + assertEquals (true, parsed.isHTTP, "isHTTP"); + assertEquals (false, parsed.isGML, "isGML"); + assertEquals ("crs", parsed.type, "type"); + assertEquals ("epsg", parsed.authority, "authority"); + assertNull ( parsed.version, "version"); + assertEquals ("4326", parsed.code, "code"); + assertNull ( parsed.parameters, "parameters"); + assertEquals ("http://www.opengis.net/def/crs/epsg/0/4326", parsed.toString(), "toString()"); } /** @@ -127,22 +129,22 @@ public final class DefinitionURITest extends TestCase { @DependsOnMethod("testParse") public void testParseGML() { final DefinitionURI parsed = DefinitionURI.parse("http://www.opengis.net/gml/srs/epsg.xml#4326"); - assertNotNull("DefinitionURI", parsed); - assertEquals ("isHTTP", true, parsed.isHTTP); - assertEquals ("isGML", true, parsed.isGML); - assertEquals ("type", "crs", parsed.type); - assertEquals ("authority", "epsg", parsed.authority); - assertNull ("version", parsed.version); - assertEquals ("code", "4326", parsed.code); - assertNull ("parameters", parsed.parameters); - assertEquals ("toString()", "http://www.opengis.net/gml/srs/epsg.xml#4326", parsed.toString()); + assertNotNull(parsed, "DefinitionURI"); + assertEquals (true, parsed.isHTTP, "isHTTP"); + assertEquals (true, parsed.isGML, "isGML"); + assertEquals ("crs", parsed.type, "type"); + assertEquals ("epsg", parsed.authority, "authority"); + assertNull ( parsed.version, "version"); + assertEquals ("4326", parsed.code, "code"); + assertNull ( parsed.parameters, "parameters"); + assertEquals ("http://www.opengis.net/gml/srs/epsg.xml#4326", parsed.toString(), "toString()"); final DefinitionURI withoutExtension = DefinitionURI.parse("http://www.opengis.net/gml/srs/epsg#4326"); - assertNotNull("Should parse even if the .xml extension is missig.", withoutExtension); + assertNotNull(withoutExtension, "Should parse even if the .xml extension is missig."); assertEquals(parsed.toString(), withoutExtension.toString()); - assertNull("Should not parse if no '#' character.", - DefinitionURI.parse("http://www.opengis.net/gml/srs/epsg?4326")); + assertNull(DefinitionURI.parse("http://www.opengis.net/gml/srs/epsg?4326"), + "Should not parse if no '#' character."); } /** @@ -153,8 +155,8 @@ public final class DefinitionURITest extends TestCase { @DependsOnMethod("testParse") public void testCompoundURN() { DefinitionURI parsed = DefinitionURI.parse("urn:ogc:def:crs, crs :EPSG:9.1:27700, crs:EPSG: 9.1 :5701"); - assertNotNull("components", parsed.components); - assertEquals("components.length", 2, parsed.components.length); + assertNotNull(parsed.components, "components"); + assertEquals(2, parsed.components.length, "components.length"); assertEquals("urn:ogc:def:crs:EPSG:9.1:27700", parsed.components[0].toString()); assertEquals("urn:ogc:def:crs:EPSG:9.1:5701", parsed.components[1].toString()); assertEquals("urn:ogc:def:crs,crs:EPSG:9.1:27700,crs:EPSG:9.1:5701", parsed.toString()); @@ -165,10 +167,10 @@ public final class DefinitionURITest extends TestCase { * - the "ogc:crs" parts should not be accepted because "def" is missing between "ogc" and "crs". */ parsed = DefinitionURI.parse("urn:ogc:def:crs,urn:ogc:def:crs:EPSG:9.1:27700,ogc:crs:EPSG:9.1:5701,def:crs:OGC::AnsiDate"); - assertNotNull("components", parsed.components); - assertEquals("components.length", 3, parsed.components.length); + assertNotNull(parsed.components, "components"); + assertEquals(3, parsed.components.length, "components.length"); assertEquals("urn:ogc:def:crs:EPSG:9.1:27700", parsed.components[0].toString()); - assertNull ("urn:ogc:def:crs:EPSG:9.1:5701", parsed.components[1]); + assertNull (parsed.components[1], "urn:ogc:def:crs:EPSG:9.1:5701"); assertEquals("urn:ogc:def:crs:OGC::AnsiDate", parsed.components[2].toString()); } @@ -181,8 +183,8 @@ public final class DefinitionURITest extends TestCase { DefinitionURI parsed = DefinitionURI.parse("http://www.opengis.net/def/crs-compound?" + "1=http://www.opengis.net/def/crs/EPSG/9.1/27700&" + "2=http://www.opengis.net/def/crs/EPSG/9.1/5701"); - assertEquals("type", "crs-compound", parsed.type); - assertEquals("components.length", 2, parsed.components.length); + assertEquals("crs-compound", parsed.type, "type"); + assertEquals(2, parsed.components.length, "components.length"); assertEquals("http://www.opengis.net/def/crs/EPSG/9.1/27700", parsed.components[0].toString()); assertEquals("http://www.opengis.net/def/crs/EPSG/9.1/5701", parsed.components[1].toString()); assertEquals("http://www.opengis.net/def/crs-compound?" @@ -191,60 +193,74 @@ public final class DefinitionURITest extends TestCase { } /** - * Tests {@link DefinitionURI#codeOf(String, String, String)} + * Convenience method invoking {@link DefinitionURI#codeOf(String, String[], CharSequence)} + * with a single authority. + */ + private static String codeOf(final String type, final String authority, final CharSequence uri) { + Map.Entry<Integer,String> entry = DefinitionURI.codeOf(type, new String[] {authority}, uri); + if (entry == null) { + return null; + } + assertEquals(0, entry.getKey()); + return entry.getValue(); + } + + /** + * Tests {@link DefinitionURI#codeOf(String, String[], CharSequence)} * with URI like {@code "EPSG:4326"}. */ @Test public void testCodeOfEPSG() { - assertNull ( DefinitionURI.codeOf("crs", "EPSG", "4326")); - assertEquals("4326", DefinitionURI.codeOf("crs", "EPSG", "EPSG:4326")); - assertEquals("4326", DefinitionURI.codeOf("crs", "EPSG", "EPSG::4326")); - assertNull ( DefinitionURI.codeOf("crs", "EPSG", "EPSG:::4326")); - assertEquals("4326", DefinitionURI.codeOf("crs", "EPSG", "EPSG:8.2:4326")); - assertEquals("4326", DefinitionURI.codeOf("crs", "EPSG", " epsg : 4326 ")); - assertEquals("4326", DefinitionURI.codeOf("crs", "EPSG", " epsg :: 4326 ")); - assertEquals("4326", DefinitionURI.codeOf("crs", "EPSG", " epsg : : 4326 ")); + assertNull ( codeOf("crs", "EPSG", "4326")); + assertEquals("4326", codeOf("crs", "EPSG", "EPSG:4326")); + assertEquals("4326", codeOf("crs", "EPSG", "EPSG::4326")); + assertNull ( codeOf("crs", "EPSG", "EPSG:::4326")); + assertEquals("4326", codeOf("crs", "EPSG", "EPSG:8.2:4326")); + assertEquals("4326", codeOf("crs", "EPSG", " epsg : 4326 ")); + assertEquals("4326", codeOf("crs", "EPSG", " epsg :: 4326 ")); + assertEquals("4326", codeOf("crs", "EPSG", " epsg : : 4326 ")); } /** - * Tests {@link DefinitionURI#codeOf(String, String, String)} + * Tests {@link DefinitionURI#codeOf(String, String[], CharSequence)} * with URN like {@code "urn:ogc:def:crs:EPSG::4326"}. */ @Test public void testCodeOfURN() { - assertEquals("4326", DefinitionURI.codeOf("crs", "EPSG", "urn:ogc:def:crs:EPSG:4326")); - assertEquals("4326", DefinitionURI.codeOf("crs", "EPSG", "urn:ogc:def:crs:EPSG::4326")); - assertEquals("4326", DefinitionURI.codeOf("crs", "EPSG", "urn:ogc:def:crs:EPSG:8.2:4326")); - assertEquals("4326", DefinitionURI.codeOf("crs", "EPSG", "urn:x-ogc:def:crs:EPSG::4326")); - assertNull ( DefinitionURI.codeOf("crs", "EPSG", "urn:n-ogc:def:crs:EPSG::4326")); - assertEquals("4326", DefinitionURI.codeOf("crs", "EPSG", " urn : ogc : def : crs : epsg : : 4326")); - assertNull ( DefinitionURI.codeOf("crs", "EPSG", "urn:ogc:def:uom:EPSG::9102")); - assertEquals("9102", DefinitionURI.codeOf("uom", "EPSG", "urn:ogc:def:uom:EPSG::9102")); - assertNull ( DefinitionURI.codeOf("crs", "EPSG", "urn:ogc:def:crs:OGC:1.3:CRS84")); - assertEquals("CRS84", DefinitionURI.codeOf("crs", "OGC", "urn:ogc:def:crs:OGC:1.3:CRS84")); - assertNull ( DefinitionURI.codeOf("crs", "OGC", "urn:ogc:def:crs:OGC:1.3:AUTO42003:1:-100:45")); + assertEquals("4326", codeOf("crs", "EPSG", "urn:ogc:def:crs:EPSG:4326")); + assertEquals("4326", codeOf("crs", "EPSG", "urn:ogc:def:crs:EPSG::4326")); + assertEquals("4326", codeOf("crs", "EPSG", "urn:ogc:def:crs:EPSG:8.2:4326")); + assertEquals("4326", codeOf("crs", "EPSG", "urn:x-ogc:def:crs:EPSG::4326")); + assertNull ( codeOf("crs", "EPSG", "urn:n-ogc:def:crs:EPSG::4326")); + assertEquals("4326", codeOf("crs", "EPSG", " urn : ogc : def : crs : epsg : : 4326")); + assertNull ( codeOf("crs", "EPSG", "urn:ogc:def:uom:EPSG::9102")); + assertEquals("9102", codeOf("uom", "EPSG", "urn:ogc:def:uom:EPSG::9102")); + assertNull ( codeOf("crs", "EPSG", "urn:ogc:def:crs:OGC:1.3:CRS84")); + assertEquals("CRS84", codeOf("crs", "OGC", "urn:ogc:def:crs:OGC:1.3:CRS84")); + assertNull ( codeOf("crs", "OGC", "urn:ogc:def:crs:OGC:1.3:AUTO42003:1:-100:45")); } /** - * Tests {@link DefinitionURI#codeOf(String, String, String)} + * Tests {@link DefinitionURI#codeOf(String, String[], CharSequence)} * with URL like {@code "http://www.opengis.net/def/crs/EPSG/0/4326"}. */ @Test public void testCodeOfDefinitionServer() { - assertEquals("4326", DefinitionURI.codeOf("crs", "EPSG", "http://www.opengis.net/def/crs/EPSG/0/4326")); - assertEquals("9102", DefinitionURI.codeOf("uom", "EPSG", "http://www.opengis.net/def/uom/EPSG/0/9102")); + assertEquals("4326", codeOf("crs", "EPSG", "http://www.opengis.net/def/crs/EPSG/0/4326")); + assertEquals("9102", codeOf("uom", "EPSG", "http://www.opengis.net/def/uom/EPSG/0/9102")); + assertEquals("d", codeOf("uom", "UCUM", "http://www.opengis.net/def/uom/UCUM/0/d")); } /** - * Tests {@link DefinitionURI#codeOf(String, String, String)} + * Tests {@link DefinitionURI#codeOf(String, String[], CharSequence)} * with URL like {@code "http://www.opengis.net/gml/srs/epsg.xml#4326"}. */ @Test public void testCodeOfGML() { - assertEquals("4326", DefinitionURI.codeOf("crs", "EPSG", "http://www.opengis.net/gml/srs/epsg.xml#4326")); - assertNull ( DefinitionURI.codeOf("crs", "OGC", "http://www.opengis.net/gml/srs/epsg.xml#4326")); - assertNull ( DefinitionURI.codeOf("uom", "EPSG", "http://www.opengis.net/gml/srs/epsg.xml#4326")); - assertNull ( DefinitionURI.codeOf("uom", "EPSG", "http://www.isotc211.org/2005/resources/uom/gmxUom.xml#xpointer(//*[@gml:id='m'])")); - assertNull ( DefinitionURI.codeOf("uom", "EPSG", "http://schemas.opengis.net/iso/19139/20070417/resources/uom/gmxUom.xml#xpointer(//*[@gml:id='m'])")); + assertEquals("4326", codeOf("crs", "EPSG", "http://www.opengis.net/gml/srs/epsg.xml#4326")); + assertNull ( codeOf("crs", "OGC", "http://www.opengis.net/gml/srs/epsg.xml#4326")); + assertNull ( codeOf("uom", "EPSG", "http://www.opengis.net/gml/srs/epsg.xml#4326")); + assertNull ( codeOf("uom", "EPSG", "http://www.isotc211.org/2005/resources/uom/gmxUom.xml#xpointer(//*[@gml:id='m'])")); + assertNull ( codeOf("uom", "EPSG", "http://schemas.opengis.net/iso/19139/20070417/resources/uom/gmxUom.xml#xpointer(//*[@gml:id='m'])")); } }