Author: desruisseaux
Date: Sun Apr 10 20:29:17 2016
New Revision: 1738462
URL: http://svn.apache.org/viewvc?rev=1738462&view=rev
Log:
WKTParser should emit a warning when a CS[...] element contains a UNIT[...]
element which is inconsistent with the coordinate system axis units.
Modified:
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/AxisDirections.java
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/AbstractParser.java
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
Modified:
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/AxisDirections.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/AxisDirections.java?rev=1738462&r1=1738461&r2=1738462&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/AxisDirections.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/AxisDirections.java
[UTF-8] Sun Apr 10 20:29:17 2016
@@ -417,7 +417,7 @@ public final class AxisDirections extend
*
* @param cs The coordinate system from which to get the angular unit, or
{@code null}.
* @param unit The default unit to return if no angular unit is found.
- * @return The angular unit, of {@code null} if no angular unit was found.
+ * @return The angular unit, of {@code unit} if no angular unit was found.
*
* @since 0.6
*
Modified:
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/AbstractParser.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/AbstractParser.java?rev=1738462&r1=1738461&r2=1738462&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/AbstractParser.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/AbstractParser.java
[UTF-8] Sun Apr 10 20:29:17 2016
@@ -354,11 +354,23 @@ abstract class AbstractParser implements
* @param ex The non-fatal exception that occurred while parsing the
element, or {@code null}.
*/
final void warning(final Element parent, final Element element, final
InternationalString message, final Exception ex) {
+ warning(parent, (element != null) ? element.keyword : null, message,
ex);
+ }
+
+ /**
+ * Reports a non-fatal warning that occurred while parsing a WKT.
+ *
+ * @param parent The parent element, or {@code null} if unknown.
+ * @param element The name of the element that we can not parse, or {@code
null} if unknown.
+ * @param message The message. Can be {@code null} only if {@code ex} is
non-null.
+ * @param ex The non-fatal exception that occurred while parsing the
element, or {@code null}.
+ */
+ final void warning(final Element parent, final String element, final
InternationalString message, final Exception ex) {
if (warnings == null) {
warnings = new Warnings(errorLocale, true, ignoredElements);
}
warnings.add(message, ex, (parent != null && element != null)
- ? new String[] {parent.keyword, element.keyword} : null);
+ ? new String[] {parent.keyword, element} : null);
}
/**
Modified:
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java?rev=1738462&r1=1738461&r2=1738462&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java
[UTF-8] Sun Apr 10 20:29:17 2016
@@ -300,7 +300,7 @@ final class GeodeticObjectParser extends
else ex.addSuppressed(e);
}
if (verticalElements != null) {
- warning(null, null,
Errors.formatInternational(Errors.Keys.CanNotAssignUnitToDimension_2,
+ warning(null, (String) null,
Errors.formatInternational(Errors.Keys.CanNotAssignUnitToDimension_2,
WKTKeywords.VerticalExtent,
verticalElements.unit), ex);
}
}
@@ -956,7 +956,7 @@ final class GeodeticObjectParser extends
return csFactory.createParametricCS(csProperties, axes[0]);
}
default: {
- warning(parent, null,
Errors.formatInternational(Errors.Keys.UnknownType_1, type), null);
+ warning(parent, WKTKeywords.CS,
Errors.formatInternational(Errors.Keys.UnknownType_1, type), null);
return referencing.createAbstractCS(csProperties, axes);
}
}
@@ -1690,8 +1690,8 @@ final class GeodeticObjectParser extends
return null;
}
final boolean isWKT1;
- Unit<?> csUnit;
- Unit<Angle> angularUnit;
+ Unit<?> csUnit;
+ final Unit<Angle> angularUnit;
switch (element.getKeywordIndex()) {
default: {
/*
@@ -1788,7 +1788,7 @@ final class GeodeticObjectParser extends
return crsFactory.createDerivedCRS(properties, baseCRS,
fromBase, cs);
}
/*
- * The specifiation in §8.2.2 (ii) said:
+ * The specification in §8.2.2 (ii) said:
*
* "(snip) the prime meridian’s <irm longitude> value shall be
given in the
* same angular units as those for the horizontal axes of the
geographic CRS."
@@ -1798,8 +1798,12 @@ final class GeodeticObjectParser extends
* So we re-fetch the angular unit. Normally, we will get the same
value (unless
* the previous value was null).
*/
- angularUnit = AxisDirections.getAngularUnit(cs, angularUnit);
- final PrimeMeridian meridian = parsePrimeMeridian(OPTIONAL,
element, isWKT1, angularUnit);
+ final Unit<Angle> longitudeUnit =
AxisDirections.getAngularUnit(cs, angularUnit);
+ if (angularUnit != null && !angularUnit.equals(longitudeUnit)) {
+ warning(element, WKTKeywords.AngleUnit,
Errors.formatInternational(
+ Errors.Keys.InconsistentUnitsForCS_1, angularUnit),
null);
+ }
+ final PrimeMeridian meridian = parsePrimeMeridian(OPTIONAL,
element, isWKT1, longitudeUnit);
final GeodeticDatum datum = parseDatum(MANDATORY, element,
meridian);
final Map<String,?> properties = parseMetadataAndClose(element,
name, datum);
if (cs instanceof EllipsoidalCS) { // By far the most frequent
case.
@@ -1834,6 +1838,7 @@ final class GeodeticObjectParser extends
* @return The {@code "VerticalCRS"} element as a {@link VerticalCRS}
object.
* @throws ParseException if the {@code "VerticalCRS"} element can not be
parsed.
*/
+ @SuppressWarnings("null")
private SingleCRS parseVerticalCRS(final int mode, final Element parent,
final boolean isBaseCRS)
throws ParseException
{
Modified:
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java?rev=1738462&r1=1738461&r2=1738462&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
[UTF-8] Sun Apr 10 20:29:17 2016
@@ -89,14 +89,14 @@ public final strictfp class GeodeticObje
}
/**
- * Parses the given text.
+ * Parses the given text. It is caller's responsibility to verify if some
warnings have been emitted.
*
* @param type The expected object type.
* @param text The WKT string to parse.
* @return The parsed object.
* @throws ParseException if an error occurred during the parsing.
*/
- private <T> T parse(final Class<T> type, final String text) throws
ParseException {
+ private <T> T parseIgnoreWarnings(final Class<T> type, final String text)
throws ParseException {
if (parser == null) {
newParser(Convention.DEFAULT);
}
@@ -104,13 +104,26 @@ public final strictfp class GeodeticObje
final Object obj = parser.parseObject(text, position);
assertEquals("errorIndex", -1, position.getErrorIndex());
assertEquals("index", text.length(), position.getIndex());
- assertNull("warnings", parser.getAndClearWarnings(obj));
- assertTrue("ignoredElements", parser.ignoredElements.isEmpty());
assertInstanceOf("GeodeticObjectParser.parseObject", type, obj);
return type.cast(obj);
}
/**
+ * Parses the given text and ensure that no warnings have been emitted.
+ *
+ * @param type The expected object type.
+ * @param text The WKT string to parse.
+ * @return The parsed object.
+ * @throws ParseException if an error occurred during the parsing.
+ */
+ private <T> T parse(final Class<T> type, final String text) throws
ParseException {
+ final T obj = parseIgnoreWarnings(type, text);
+ assertNull("warnings", parser.getAndClearWarnings(obj));
+ assertTrue("ignoredElements", parser.ignoredElements.isEmpty());
+ return obj;
+ }
+
+ /**
* Asserts that the name and (optionally) the EPSG identifier of the given
object are equal to the given strings.
* As a special case if the given EPSG code is 0, then this method
verifies that the given object has no identifier.
*
@@ -436,6 +449,48 @@ public final strictfp class GeodeticObje
}
/**
+ * Tests parsing of a CRS with a prime meridian having implicit unit in
grads but axes having explicit unit
+ * in degrees. The specification in §8.2.2 (ii) said:
+ *
+ * "(snip) the prime meridian’s {@literal <irm longitude>} value shall
be given in
+ * the same angular units as those for the horizontal axes of the
geographic CRS."
+ *
+ * Consequently we expect the prime meridian to be in decimal degrees even
if the WKT used in this test has
+ * an {@code Unit[“grade”, 0.015707963267948967]} element, because this WK
also declare the axis as being in
+ * degrees. Since this can be confusing, we expect the parser to emit a
warning.
+ *
+ * @throws ParseException if the parsing failed.
+ */
+ @Test
+ @DependsOnMethod("testGeographicWithParisMeridian")
+ public void testMismatchedAngularUnits() throws ParseException {
+ String wkt = "GeodeticCRS[“NTF (Paris)”,\n" +
+ " Datum[“Nouvelle Triangulation Française (Paris)”,\n" +
+ " Ellipsoid[“Clarke 1880 (IGN)”, 6378249.2,
293.4660212936269]],\n" +
+ " PrimeMeridian[“Paris”, 2.33722917],\n" +
// In units of the longitude axis.
+ " CS[ellipsoidal, 2],\n" +
+ " Axis[“Latitude (φ)”, NORTH, Unit[“degree”,
0.017453292519943295]],\n" +
+ " Axis[“Longitude (λ)”, EAST, Unit[“degree”,
0.017453292519943295]],\n" +
+ " Unit[“grade”, 0.015707963267948967]\n," +
// Inconsistent with axis units.
+ " Id[“EPSG”, 4807]]";
+
+ GeographicCRS crs = parseIgnoreWarnings(GeographicCRS.class, wkt);
+ final Warnings warnings = parser.getAndClearWarnings(crs);
+ assertTrue("ignoredElements", parser.ignoredElements.isEmpty());
+ assertNotNull("warnings", warnings);
+ assertEquals("warnings.numMessages", 1, warnings.getNumMessages());
+
+ assertNameAndIdentifierEqual("NTF (Paris)", 4807, crs);
+ PrimeMeridian pm = crs.getDatum().getPrimeMeridian();
+ assertEquals("angularUnit", NonSI.DEGREE_ANGLE, pm.getAngularUnit());
+ assertEquals("greenwichLongitude", 2.33722917,
pm.getGreenwichLongitude(), STRICT);
+ EllipsoidalCS cs = crs.getCoordinateSystem();
+ assertEquals("dimension", 2, cs.getDimension());
+ assertAxisEquals(AxisNames.GEODETIC_LATITUDE, "φ",
AxisDirection.NORTH, -90, +90, NonSI.DEGREE_ANGLE, RangeMeaning.EXACT,
cs.getAxis(0));
+ assertAxisEquals(AxisNames.GEODETIC_LONGITUDE, "λ",
AxisDirection.EAST, -180, +180, NonSI.DEGREE_ANGLE, RangeMeaning.WRAPAROUND,
cs.getAxis(1));
+ }
+
+ /**
* Implementation of {@link #testGeographicCRS()} and {@link
#testWithAxisSwapping()}.
* This test expects no {@code AUTHORITY} element on any component.
*
@@ -1039,17 +1094,14 @@ public final strictfp class GeodeticObje
@Test
@DependsOnMethod("testGeographicWithImplicitAxes")
public void testWarnings() throws ParseException {
- newParser(Convention.DEFAULT);
- final ParsePosition position = new ParsePosition(0);
- final GeographicCRS crs = (GeographicCRS) parser.parseObject(
+ final GeographicCRS crs = parseIgnoreWarnings(GeographicCRS.class,
"GEOGCS[“WGS 84”,\n" +
" DATUM[“World Geodetic System 1984”,\n" +
" SPHEROID[“WGS84”, 6378137.0, 298.257223563, Ext1[“foo”],
Ext2[“bla”]]],\n" +
" PRIMEM[“Greenwich”, 0.0, Intruder[“unknown”]],\n" +
- " UNIT[“degree”, 0.017453292519943295], Intruder[“foo”]]",
position);
+ " UNIT[“degree”, 0.017453292519943295], Intruder[“foo”]]");
verifyGeographicCRS(0, crs);
- assertEquals("errorIndex", -1, position.getErrorIndex());
final Warnings warnings = parser.getAndClearWarnings(crs);
assertNotNull("warnings", warnings);
Modified:
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1738462&r1=1738461&r2=1738462&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
[UTF-8] Sun Apr 10 20:29:17 2016
@@ -519,6 +519,11 @@ public final class Errors extends Indexe
public static final short InconsistentTableColumns = 48;
/**
+ * Unit of measurement “{0}” is inconsistent with coordinate system
axes.
+ */
+ public static final short InconsistentUnitsForCS_1 = 222;
+
+ /**
* Index {0} is out of bounds.
*/
public static final short IndexOutOfBounds_1 = 49;
Modified:
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1738462&r1=1738461&r2=1738462&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
[ISO-8859-1] (original)
+++
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
[ISO-8859-1] Sun Apr 10 20:29:17 2016
@@ -113,6 +113,7 @@ IncompatibleUnits_2 = Unit
InconsistentAttribute_2 = Value \u201c{1}\u201d of attribute
\u2018{0}\u2019 is inconsistent with other attributes.
InconsistentNamespace_2 = Expected \u201c{0}\u201d namespace for
\u201c{1}\u201d.
InconsistentTableColumns = Inconsistent table columns.
+InconsistentUnitsForCS_1 = Unit of measurement \u201c{0}\u201d is
inconsistent with coordinate system axes.
IdentifierAlreadyBound_1 = Identifier \u201c{0}\u201d is already
associated to another object.
IndexOutOfBounds_1 = Index {0} is out of bounds.
IndicesOutOfBounds_2 = Indices ({0}, {1}) are out of bounds.
Modified:
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1738462&r1=1738461&r2=1738462&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
[ISO-8859-1] (original)
+++
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
[ISO-8859-1] Sun Apr 10 20:29:17 2016
@@ -110,6 +110,7 @@ IncompatibleUnits_2 = Les
InconsistentAttribute_2 = La valeur \u00ab\u202f{1}\u202f\u00bb de
l\u2019attribut \u2018{0}\u2019 n\u2019est pas coh\u00e9rente avec celles des
autres attributs.
InconsistentNamespace_2 = L\u2019espace de nom \u201c{0}\u201d
\u00e9tait attendu pour \u201c{1}\u201d.
InconsistentTableColumns = Les colonnes des tables ne sont pas
coh\u00e9rentes.
+InconsistentUnitsForCS_1 = L\u2019unit\u00e9 de mesure
\u00ab\u202f{0}\u202f\u00bb n\u2019est pas coh\u00e9rente avec les axes du
syst\u00e8me de coordonn\u00e9es.
IdentifierAlreadyBound_1 = L\u2019identifiant
\u00ab\u202f{0}\u202f\u00bb est d\u00e9j\u00e0 associ\u00e9 \u00e0 un autre
objet.
IndexOutOfBounds_1 = L\u2019index {0} est en dehors des limites
permises.
IndicesOutOfBounds_2 = Les index ({0}, {1}) sont en dehors des
limites permises.