Return-Path:
X-Original-To: apmail-sis-commits-archive@www.apache.org
Delivered-To: apmail-sis-commits-archive@www.apache.org
Received: from mail.apache.org (hermes.apache.org [140.211.11.3])
by minotaur.apache.org (Postfix) with SMTP id B1DF010497
for ;
Thu, 30 Jan 2014 12:37:40 +0000 (UTC)
Received: (qmail 25964 invoked by uid 500); 30 Jan 2014 12:37:40 -0000
Delivered-To: apmail-sis-commits-archive@sis.apache.org
Received: (qmail 25942 invoked by uid 500); 30 Jan 2014 12:37:38 -0000
Mailing-List: contact commits-help@sis.apache.org; run by ezmlm
Precedence: bulk
List-Help:
List-Unsubscribe:
List-Post:
List-Id:
Reply-To: sis-dev@sis.apache.org
Delivered-To: mailing list commits@sis.apache.org
Received: (qmail 25933 invoked by uid 99); 30 Jan 2014 12:37:38 -0000
Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136)
by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 30 Jan 2014 12:37:38 +0000
X-ASF-Spam-Status: No, hits=-2000.0 required=5.0
tests=ALL_TRUSTED
X-Spam-Check-By: apache.org
Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4)
by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 30 Jan 2014 12:37:33 +0000
Received: from eris.apache.org (localhost [127.0.0.1])
by eris.apache.org (Postfix) with ESMTP id 368BB2388868;
Thu, 30 Jan 2014 12:37:13 +0000 (UTC)
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Subject: svn commit: r1562800 [1/3] - in /sis/trunk: ./
core/sis-referencing/src/main/java/org/apache/sis/geometry/
core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/
core/sis-referencing/src/main/java/org/apache/sis/io/wkt/ core/sis-refere...
Date: Thu, 30 Jan 2014 12:37:11 -0000
To: commits@sis.apache.org
From: desruisseaux@apache.org
X-Mailer: svnmailer-1.0.9
Message-Id: <20140130123713.368BB2388868@eris.apache.org>
X-Virus-Checked: Checked by ClamAV on apache.org
Author: desruisseaux
Date: Thu Jan 30 12:37:10 2014
New Revision: 1562800
URL: http://svn.apache.org/r1562800
Log:
Merge from the JDK6 branch.
Added:
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Legacy.java
- copied unchanged from r1562799, sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Legacy.java
Removed:
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Legacy.java
Modified:
sis/trunk/ (props changed)
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/ArrayEnvelope.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/Envelopes.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralEnvelope.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/SubEnvelope.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/AxisDirections.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/VerticalDatumTypes.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Colors.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Convention.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/FormattableObject.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Formatter.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Symbols.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/UnformattableObjectException.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/WKTFormat.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/package-info.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/CommonCRS.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractCRS.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultGeocentricCRS.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AxesConvention.java
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/CoordinateSystems.java
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralDirectPositionTest.java
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralEnvelopeTest.java
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/AxisDirectionsTest.java
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/ConventionTest.java
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/FormatterTest.java
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/SymbolsTest.java
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/Assert.java
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/CRSTest.java
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/HardCodedCRS.java
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/HardCodedCRSTest.java
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/DefaultCoordinateSystemAxisTest.java
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/HardCodedAxes.java
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultEllipsoidTest.java
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultGeodeticDatumTest.java
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultPrimeMeridianTest.java
sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultVerticalDatumTest.java
sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/ComparisonMode.java
sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties
sis/trunk/pom.xml
Propchange: sis/trunk/
------------------------------------------------------------------------------
Merged /sis/branches/JDK7:r1560379-1562797
Merged /sis/branches/JDK6:r1560381-1562799
Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java?rev=1562800&r1=1562799&r2=1562800&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java [UTF-8] Thu Jan 30 12:37:10 2014
@@ -526,6 +526,7 @@ public abstract class AbstractEnvelope i
* @return A representation of this envelope as an array of non-empty envelope.
*
* @see Envelope2D#toRectangles()
+ * @see GeneralEnvelope#simplify()
*
* @since 0.4
*/
@@ -1035,11 +1036,11 @@ public abstract class AbstractEnvelope i
* where n is the {@linkplain #getDimension() number of dimensions}.
* The number of dimension is written only if different than 2.
*
- * Example:
- *
- * {@preformat wkt
- * BOX(-90 -180, 90 180)
- * BOX3D(-90 -180 0, 90 180 1)
+ * {@example
+ *
+ * BOX(-90 -180, 90 180)
+ * BOX3D(-90 -180 0, 90 180 1)
+ *
* }
*
* {@note The BOX
element is not part of the standard Well Known Text
@@ -1182,7 +1183,10 @@ public abstract class AbstractEnvelope i
* @param dimension The dimension to set.
* @param lower The limit in the direction of decreasing ordinate values.
* @param upper The limit in the direction of increasing ordinate values.
+ * @throws UnmodifiableGeometryException If this envelope is not modifiable.
* @throws IndexOutOfBoundsException If the given index is out of bounds.
+ * @throws IllegalArgumentException If {@code lower > upper}, this envelope has a CRS
+ * and the axis range meaning at the given dimension is not "wraparound".
*/
void setRange(final int dimension, final double lower, final double upper)
throws IndexOutOfBoundsException
Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/ArrayEnvelope.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/ArrayEnvelope.java?rev=1562800&r1=1562799&r2=1562800&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/ArrayEnvelope.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/ArrayEnvelope.java [UTF-8] Thu Jan 30 12:37:10 2014
@@ -27,8 +27,10 @@ import org.opengis.geometry.Envelope;
import org.opengis.geometry.DirectPosition;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.metadata.extent.GeographicBoundingBox;
+import org.opengis.referencing.cs.RangeMeaning;
import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.referencing.CommonCRS;
import org.apache.sis.util.ArraysExt;
import org.apache.sis.util.CharSequences;
@@ -115,6 +117,7 @@ class ArrayEnvelope extends AbstractEnve
ordinates[i ] = lowerCorner.getOrdinate(i);
ordinates[i + dimension] = upperCorner.getOrdinate(i);
}
+ verifyRanges(crs, ordinates);
}
/**
@@ -171,6 +174,7 @@ class ArrayEnvelope extends AbstractEnve
ordinates[i] = lowerCorner.getOrdinate(i);
ordinates[i+dimension] = upperCorner.getOrdinate(i);
}
+ verifyRanges(crs, ordinates);
}
/**
@@ -196,6 +200,7 @@ class ArrayEnvelope extends AbstractEnve
}
}
crs = CommonCRS.defaultGeographic();
+ verifyRanges(crs, ordinates);
}
/**
@@ -316,6 +321,59 @@ scanNumber: while ((i += Character.charC
}
/**
+ * Verifies the validity of the range of ordinates values in the given array.
+ * If the given CRS is null, then this method conservatively does nothing.
+ * Otherwise this method performs the following verifications:
+ *
+ *
+ * - {@code lower > upper} is allowed only for axes having {@link RangeMeaning#WRAPAROUND}.
+ *
+ *
+ * This method does not verify if the ordinate values are between the axis minimum and
+ * maximum values. This is because out-of-range values exist in practice but do not impact the working
+ * of {@code add(…)}, {@code intersect(…)}, {@code contains(…)} and similar methods. This in contrast
+ * with the checks listed above, where failure to meet those conditions will cause the methods to
+ * behave in an unexpected way.
+ *
+ * {@section Implementation consistency}
+ * The checks performed by this method shall be consistent with the checks performed by the following methods:
+ *
+ * - {@link GeneralEnvelope#setCoordinateReferenceSystem(CoordinateReferenceSystem)}
+ * - {@link GeneralEnvelope#setRange(int, double, double)}
+ * - {@link SubEnvelope#setRange(int, double, double)}
+ *
+ *
+ * @param crs The coordinate reference system, or {@code null}.
+ * @param ordinates The array of ordinate values to verify.
+ */
+ static void verifyRanges(final CoordinateReferenceSystem crs, final double[] ordinates) {
+ if (crs != null) {
+ final int dimension = ordinates.length >>> 1;
+ for (int i=0; i upper && !isWrapAround(crs, i)) {
+ throw new IllegalArgumentException(illegalRange(crs, i, lower, upper));
+ }
+ }
+ }
+ }
+
+ /**
+ * Creates an error message for an illegal ordinates range at the given dimension.
+ * This is used for formatting the exception message.
+ */
+ static String illegalRange(final CoordinateReferenceSystem crs,
+ final int dimension, final double lower, final double upper)
+ {
+ Object name = IdentifiedObjects.getName(getAxis(crs, dimension), null);
+ if (name == null) {
+ name = dimension; // Paranoiac fallback (name should never be null).
+ }
+ return Errors.format(Errors.Keys.IllegalOrdinateRange_3, lower, upper, name);
+ }
+
+ /**
* Returns the index of the first valid ordinate value of the lower corner in the {@link #ordinates} array.
* This is always 0, unless this envelope is a {@link SubEnvelope}.
*
Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/Envelopes.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/Envelopes.java?rev=1562800&r1=1562799&r2=1562800&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/Envelopes.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/Envelopes.java [UTF-8] Thu Jan 30 12:37:10 2014
@@ -93,7 +93,7 @@ public final class Envelopes extends Sta
ensureNonNull("wkt", wkt);
try {
return new GeneralEnvelope(wkt);
- } catch (RuntimeException e) {
+ } catch (IllegalArgumentException e) {
throw new FactoryException(Errors.format(
Errors.Keys.UnparsableStringForClass_2, Envelope.class), e);
}
Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralEnvelope.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralEnvelope.java?rev=1562800&r1=1562799&r2=1562800&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralEnvelope.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralEnvelope.java [UTF-8] Thu Jan 30 12:37:10 2014
@@ -90,6 +90,24 @@ import static org.apache.sis.math.MathFu
*
*
*
+ * {@section Envelope validation}
+ * If and only if this envelope is associated to a non-null CRS, then constructors and setter methods
+ * in this class perform the following checks:
+ *
+ *
+ * - The number of CRS dimensions must be equals to
this.{@linkplain #getDimension()}
.
+ * - For each dimension i,
+ *
{@linkplain #getLower(int) getLower}(i) > {@linkplain #getUpper(int) getUpper}(i)
is allowed
+ * only if the {@linkplain org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis#getRangeMeaning() coordinate
+ * system axis range meaning} is {@code WRAPAROUND}.
+ *
+ *
+ * Note that this class does not require the ordinate values to be between the axis minimum and
+ * maximum values. This flexibility exists because out-of-range values happen in practice, while they do
+ * not hurt the working of {@code add(…)}, {@code intersect(…)}, {@code contains(…)} and similar methods.
+ * This in contrast with the {@code lower > upper} case, which cause the above-cited methods to behave in
+ * an unexpected way if the axis does not have wraparound range meaning.
+ *
* @author Martin Desruisseaux (IRD, Geomatys)
* @author Johann Sorel (Geomatys)
* @since 0.3 (derived from geotk-2.4)
@@ -218,14 +236,14 @@ public class GeneralEnvelope extends Arr
* check that every points in a {@code LINESTRING} have the same dimension. However this
* constructor ensures that the parenthesis are balanced, in order to catch some malformed WKT.
*
- * The following examples can be parsed by this constructor in addition of the usual
- * {@code BOX} element. This constructor creates the bounding box of those geometries:
+ * {@example The following texts can be parsed by this constructor in addition of the usual
+ * BOX
element. This constructor creates the bounding box of those geometries:
*
*
- * - {@code POINT(6 10)}
- * - {@code MULTIPOLYGON(((1 1, 5 1, 1 5, 1 1),(2 2, 3 2, 3 3, 2 2)))}
- * - {@code GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(3 8,7 10))}
- *
+ * POINT(6 10)
+ * MULTIPOLYGON(((1 1, 5 1, 1 5, 1 1),(2 2, 3 2, 3 3, 2 2)))
+ * GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(3 8,7 10))
+ * }
*
* @param wkt The {@code BOX}, {@code POLYGON} or other kind of element to parse.
* @throws IllegalArgumentException If the given string can not be parsed.
@@ -258,21 +276,42 @@ public class GeneralEnvelope extends Arr
/**
* Sets the coordinate reference system in which the coordinate are given.
- * This method does not reproject the envelope, and do not
- * check if the envelope is contained in the new domain of validity.
+ * This method does not reproject the envelope, and does
+ * not check if the envelope is contained in the new domain of validity.
*
* If the envelope coordinates need to be transformed to the new CRS, consider
* using {@link Envelopes#transform(Envelope, CoordinateReferenceSystem)} instead.
*
* @param crs The new coordinate reference system, or {@code null}.
- * @throws MismatchedDimensionException if the specified CRS doesn't have the expected
- * number of dimensions.
+ * @throws MismatchedDimensionException if the specified CRS doesn't have the expected number of dimensions.
+ * @throws IllegalStateException if a range of ordinate values in this envelope is compatible with the given CRS.
+ * See Envelope validation in class javadoc for more details.
*/
public void setCoordinateReferenceSystem(final CoordinateReferenceSystem crs)
throws MismatchedDimensionException
{
ensureDimensionMatches("crs", getDimension(), crs);
- this.crs = crs;
+ /*
+ * The check performed here shall be identical to ArrayEnvelope.verifyRanges(crs, ordinates)
+ * except that it may verify only a subset of the ordinate array and throws a different kind
+ * of exception in caseo of failure.
+ */
+ if (crs != null) {
+ final int beginIndex = beginIndex();
+ final int endIndex = endIndex();
+ final int d = ordinates.length >>> 1;
+ for (int i=beginIndex; i upper) {
+ final int j = i - beginIndex;
+ if (!isWrapAround(crs, j)) {
+ throw new IllegalStateException(illegalRange(crs, j, lower, upper));
+ }
+ }
+ }
+ }
+ this.crs = crs; // Set only on success.
}
/**
@@ -282,6 +321,8 @@ public class GeneralEnvelope extends Arr
* @param lower The limit in the direction of decreasing ordinate values.
* @param upper The limit in the direction of increasing ordinate values.
* @throws IndexOutOfBoundsException If the given index is out of bounds.
+ * @throws IllegalArgumentException If {@code lower > upper} and the axis range meaning at the given dimension
+ * is not "wraparound". See Envelope validation in class javadoc for more details.
*/
@Override // Must also be overridden in SubEnvelope
public void setRange(final int dimension, final double lower, final double upper)
@@ -289,6 +330,13 @@ public class GeneralEnvelope extends Arr
{
final int d = ordinates.length >>> 1;
ensureValidIndex(d, dimension);
+ /*
+ * The check performed here shall be identical to ArrayEnvelope.verifyRanges(crs, ordinates),
+ * except that there is no loop.
+ */
+ if (lower > upper && crs != null && !isWrapAround(crs, dimension)) {
+ throw new IllegalArgumentException(illegalRange(crs, dimension, lower, upper));
+ }
ordinates[dimension + d] = upper;
ordinates[dimension] = lower;
}
@@ -299,14 +347,16 @@ public class GeneralEnvelope extends Arr
* this {@linkplain #getDimension() envelope dimension}, and minimum shall not be greater
* than maximum.
*
- * Example:
+ * {@example
* (xmin, ymin, zmin,
* xmax, ymax, zmax)
+ * }
*
* @param corners Ordinates of the new lower corner followed by the new upper corner.
*/
public void setEnvelope(final double... corners) {
verifyArrayLength(ordinates.length >>> 1, corners);
+ verifyRanges(crs, corners);
System.arraycopy(corners, 0, ordinates, 0, ordinates.length);
}
@@ -876,6 +926,8 @@ public class GeneralEnvelope extends Arr
* or {@code false} if no change has been done.
* @throws IllegalStateException If a upper ordinate value is less than a lower ordinate
* value on an axis which does not have the {@code WRAPAROUND} range meaning.
+ *
+ * @see #toSimpleEnvelopes()
*/
public boolean simplify() throws IllegalStateException {
boolean changed = false;
Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/SubEnvelope.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/SubEnvelope.java?rev=1562800&r1=1562799&r2=1562800&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/SubEnvelope.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/geometry/SubEnvelope.java [UTF-8] Thu Jan 30 12:37:10 2014
@@ -126,6 +126,13 @@ final class SubEnvelope extends GeneralE
throws IndexOutOfBoundsException
{
ensureValidIndex(endIndex, dimension);
+ /*
+ * The check performed here shall be identical to the super-class method, which is itself
+ * identical to ArrayEnvelope.verifyRanges(crs, ordinates) except that there is no loop.
+ */
+ if (lower > upper && crs != null && !isWrapAround(crs, dimension)) {
+ throw new IllegalArgumentException(illegalRange(crs, dimension, lower, upper));
+ }
dimension += beginIndex;
ordinates[dimension + (ordinates.length >>> 1)] = upper;
ordinates[dimension] = lower;
@@ -138,6 +145,7 @@ final class SubEnvelope extends GeneralE
public void setEnvelope(final double... corners) {
final int dimension = getDimension();
verifyArrayLength(dimension, corners);
+ verifyRanges(crs, corners);
final int d = ordinates.length >>> 1;
System.arraycopy(corners, 0, ordinates, beginIndex, dimension);
System.arraycopy(corners, dimension, ordinates, beginIndex + d, dimension);
Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/AxisDirections.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/AxisDirections.java?rev=1562800&r1=1562799&r2=1562800&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/AxisDirections.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/AxisDirections.java [UTF-8] Thu Jan 30 12:37:10 2014
@@ -334,17 +334,16 @@ public final class AxisDirections extend
* @param direction The direction of the axis to search.
* @return The dimension of the axis using the given direction or its opposite, or -1 if none.
*/
- public static int indexOf(final CoordinateSystem cs, final AxisDirection direction) {
+ public static int indexOfColinear(final CoordinateSystem cs, final AxisDirection direction) {
int fallback = -1;
if (cs != null) {
- final AxisDirection opposite = opposite(direction);
final int dimension = cs.getDimension();
for (int i=0; iCoordinate Transformation Services
- * (OGC 01-009), which also defined the
+ * OGC 01-009
+ * (Coordinate Transformation Services), which also defined the version 1 of
* Well
- * Known Text (WKT) format. This method is used for WKT parsing.
+ * Known Text format (WKT 1). This method is used for WKT 1 parsing.
*
* @param code The legacy vertical datum code.
* @return The vertical datum type, or {@code null} if the code is unrecognized.
Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Colors.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Colors.java?rev=1562800&r1=1562799&r2=1562800&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Colors.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Colors.java [UTF-8] Thu Jan 30 12:37:10 2014
@@ -50,13 +50,15 @@ public class Colors implements Serializa
private static final long serialVersionUID = 256160285861027191L;
/**
- * The immutable default set of colors.
+ * A map of colors for outputs to the {@link java.io.Console}.
+ * Those colors give better results on a black background.
+ * This map is immutable.
*
- * @see Symbols#DEFAULT
+ * @see FormattableObject#print()
*/
- public static final Colors DEFAULT = new Immutable();
+ public static final Colors CONSOLE = new Immutable();
static {
- final EnumMap map = DEFAULT.map;
+ final EnumMap map = CONSOLE.map;
map.put(ElementKind.NUMBER, X364.FOREGROUND_YELLOW);
map.put(ElementKind.INTEGER, X364.FOREGROUND_YELLOW);
map.put(ElementKind.UNIT, X364.FOREGROUND_YELLOW);
@@ -134,7 +136,7 @@ public class Colors implements Serializa
}
/**
- * An immutable subclass of {@link Colors} for the {@link Colors#DEFAULT} constant
+ * An immutable subclass of {@link Colors} for the {@link Colors#CONSOLE} constant
* or for the object to be used by {@link WKTFormat}.
*/
private static final class Immutable extends Colors {
@@ -174,10 +176,10 @@ public class Colors implements Serializa
}
/**
- * Replaces the deserialized instance by {@link #DEFAULT} one if possible.
+ * Replaces the deserialized instance by {@link #CONSOLE} one if possible.
*/
Object readResolve() throws ObjectStreamException {
- return super.map.equals(DEFAULT.map) ? DEFAULT : this;
+ return super.map.equals(CONSOLE.map) ? CONSOLE : this;
}
}
}
Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Convention.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Convention.java?rev=1562800&r1=1562799&r2=1562800&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Convention.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Convention.java [UTF-8] Thu Jan 30 12:37:10 2014
@@ -20,11 +20,7 @@ import javax.measure.unit.Unit;
import javax.measure.quantity.Angle;
import javax.measure.quantity.Quantity;
import org.opengis.metadata.citation.Citation;
-import org.opengis.referencing.cs.CartesianCS;
-import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.crs.GeocentricCRS;
-import org.opengis.referencing.operation.OperationMethod;
-import org.opengis.referencing.operation.CoordinateOperation;
import org.apache.sis.util.Debug;
import org.apache.sis.metadata.iso.citation.Citations;
@@ -33,21 +29,26 @@ import static javax.measure.unit.NonSI.D
/**
* The convention to use for WKT formatting.
- * This enumeration attempts to address some of the variability documented in the Frank Warmerdam's
- * OGC WKT Coordinate System Issues page.
- * The various conventions enumerated in this class differ mostly in:
+ * This enumeration specifies whether to use the Well Known Text format defined by ISO 19162
+ * (also known as “WKT 2”), or whether to use the format previously defined in OGC 01-009 (referenced as “WKT 1”).
+ *
+ * {@section WKT 1 variants}
+ * The WKT 2 format should be parsed and formatted consistently by all softwares.
+ * But the WKT 1 format has been interpreted differently by various implementors.
+ * Apache SIS can adapt itself to different WKT variants, sometime automatically. But some aspects can not be guessed.
+ * One noticeable source of confusion is the unit of measurement of {@code PRIMEM[…]} and {@code PARAMETER[…]} elements:
*
*
- * - Parameter names - for example a parameter named "Longitude of natural origin"
- * according {@linkplain #EPSG} may be named "{@code central_meridian}" according {@linkplain #OGC}
- * and "{@code NatOriginLong}" according {@linkplain #GEOTIFF GeoTIFF}.
- * - WKT syntax - for example {@linkplain #ORACLE Oracle} does not enclose Bursa-Wolf parameters in a
- * {@code TOWGS84[…]} element.
- * - Unit of measurement - for example the unit of the Prime Meridian shall be the angular unit of the
- * enclosing Geographic CRS according the {@linkplain #OGC} standard, but is restricted to decimal degrees by
- * {@linkplain #ESRI}.
+ * - The unit of the Prime Meridian shall be the angular unit of the enclosing Geographic CRS
+ * according the OGC 01-009 (Coordinate transformation services) specification.
+ * - An older specification — Simple Features — was unclear on this matter and has been
+ * interpreted by many softwares as fixing the unit to decimal degrees.
*
*
+ * Despite the first interpretation being specified by both OGC 01-009 and ISO 19162 standards, the second
+ * interpretation appears to be in wide use for WKT 1. Apache SIS uses the standard interpretation by default,
+ * but the {@link #WKT1_COMMON_UNITS} enumeration allows parsing and formatting using the older interpretation.
+ *
* @author Martin Desruisseaux (Geomatys)
* @since 0.4 (derived from geotk-3.20)
* @version 0.4
@@ -58,219 +59,139 @@ import static javax.measure.unit.NonSI.D
*/
public enum Convention {
/**
- * The Open Geospatial consortium convention.
+ * The ISO 19162 format, also known as “WKT 2”.
* This is the default convention for all WKT formatting in the Apache SIS library.
- * Some worthy aspects to note:
- *
- *
- * - For {@link GeocentricCRS}, this convention uses the legacy set of Cartesian axes.
- * Those axes were defined in OGC 01-009 as Other, Easting and Northing
- * in metres, where the "Other" axis is toward prime meridian.
- *
- *
- * @see Citations#OGC
- * @see #toConformCS(CoordinateSystem)
- */
- OGC(Citations.OGC, null, false),
-
- /**
- * The European Petroleum Survey Group convention.
- * This convention uses the most descriptive parameter and projection names.
- * Some worthy aspects to note:
*
- *
- * - For {@link GeocentricCRS}, this convention uses the new set of Cartesian axes.
- * Those axes are defined in ISO 19111 as Geocentric X, Geocentric Y
- * and Geocentric Z in metres.
- *
+ * Unless otherwise specified by {@link WKTFormat#setNameAuthority(Citation)}, when using
+ * this convention SIS will favor {@linkplain Citations#EPSG EPSG} definitions of projection
+ * and parameter names.
+ */
+ WKT2(Citations.EPSG, false, false),
+
+ /**
+ * The OGC 01-009 format, also known as “WKT 1”.
+ * A definition for this format is shown in Extended Backus Naur Form (EBNF)
+ * on GeoAPI.
+ *
+ * Unless otherwise specified by {@link WKTFormat#setNameAuthority(Citation)}, when using
+ * this convention SIS will favor {@linkplain Citations#OGC OGC} definitions of projection
+ * and parameter names.
+ *
+ * {@section Differences compared to WKT 2}
+ * WKT 1 and WKT 2 differ in their keywords and syntax, but also in more subtle ways regarding parameter
+ * and code list values. For {@link GeocentricCRS}, WKT 1 uses a legacy set of Cartesian axes which were
+ * defined in OGC 01-009. Those axes use the Other, Easting and Northing
+ * {@linkplain org.opengis.referencing.cs.AxisDirection axis directions} instead than the geocentric ones,
+ * as shown in the following table:
*
- * @see Citations#EPSG
- * @see #toConformCS(CoordinateSystem)
+ *
+ * ISO 19111 | OGC 01-009 | Description |
+ * Geocentric X | Other | Toward prime meridian |
+ * Geocentric Y | Easting | Toward 90°E longitude |
+ * Geocentric Z | Northing | Toward north pole |
+ *
*/
- EPSG(Citations.EPSG, null, false) {
- @Override
- public CoordinateSystem toConformCS(CoordinateSystem cs) {
- if (cs instanceof CartesianCS) {
- cs = Legacy.replace((CartesianCS) cs, false);
- }
- return cs;
- }
- },
+ WKT1(Citations.OGC, true, false),
/**
- * The ESRI convention.
- * This convention is similar to the {@link #OGC} convention except in the following aspects:
+ * The Simple Feature format, also known as “WKT 1”.
+ * Simple Feature is anterior to OGC 01-009 and defines the same format,
+ * but was unclear about the unit of measurement for prime meridians and projection parameters.
+ * Consequently many implementations interpreted those angular units as fixed to degrees instead
+ * than being context-dependent.
*
+ * This convention is identical to {@link #WKT1} except for the following aspects:
*
* - The angular units of {@code PRIMEM} and {@code PARAMETER} elements are always degrees,
* no matter the units of the enclosing {@code GEOGCS} element.
- * - The {@code AXIS} elements are ignored at parsing time.
* - Unit names use American spelling instead than the international ones
* (e.g. "meter" instead than "metre").
- * - At parsing time, the {@code AXIS} elements are ignored.
*
- *
- * @see Citations#ESRI
*/
- ESRI(Citations.ESRI, DEGREE_ANGLE, true),
+ WKT1_COMMON_UNITS(Citations.OGC, true, true),
/**
- * The Oracle convention.
- * This convention is similar to the {@link #OGC} convention except in the following aspects:
- *
- *
- * - The Bursa-Wolf parameters are inserted straight into the {@code DATUM} element,
- * without enclosing them in a {@code TOWGS84} element.
- * - The {@code PROJECTION} names are {@linkplain CoordinateOperation Coordinate Operation}
- * names instead than {@linkplain OperationMethod Operation Method} names.
- * - Unit names use American spelling instead than the international ones
- * (e.g. "meter" instead than "metre").
- *
+ * A special convention for formatting objects as stored internally by Apache SIS.
+ * In the majority of cases, the result will be identical to the one we would get using the {@link #WKT2} convention.
+ * However in the particular case of map projections, the result may be quite different because of the way
+ * SIS separates the linear from the non-linear parameters.
*
- * @see Citations#ORACLE
+ * This convention is used only for debugging purpose.
*/
- ORACLE(Citations.ORACLE, null, true),
+ @Debug
+ INTERNAL(Citations.OGC, false, false);
/**
- * The NetCDF convention.
- * This convention is similar to the {@link #OGC} convention except in the following aspects:
- *
- *
- * - Parameter and projection names.
- *
+ * The default conventions.
*
- * @see Citations#NETCDF
+ * @todo Make final after we completed the migration from Geotk.
*/
- NETCDF(Citations.NETCDF, null, false),
+ static Convention DEFAULT = WKT2;
/**
- * The GeoTIFF convention.
- * This convention is similar to the {@link #OGC} convention except in the following aspects:
- *
- *
- * - Parameter and projection names.
- *
- *
- * @see Citations#GEOTIFF
+ * {@code true} for using WKT 1 syntax, or {@code false} for using WKT 2 syntax.
*/
- GEOTIFF(Citations.GEOTIFF, null, false),
+ final boolean isWKT1;
/**
- * The Proj.4 convention.
- * This convention is similar to the {@link #OGC} convention except in the following aspects:
- *
+ * {@code true} for a frequently-used convention about units instead than the standard one.
*
- * - Very short parameter and projection names.
- * - The angular units of {@code PRIMEM} and {@code PARAMETER} elements are always degrees,
- * no matter the units of the enclosing {@code GEOGCS} element.
+ * - If {@code true}, forces {@code PRIMEM} and {@code PARAMETER} angular units to degrees
+ * instead than inferring the unit from the context. The standard value is {@code false},
+ * which means that the angular units are inferred from the context as required by the
+ * WKT 1 specification.
+ * - If {@code true}, uses US unit names instead of the international names.
+ * For example Americans said {@code "meter"} instead of {@code "metre"}.
*
*
- * @see Citations#PROJ4
- */
- PROJ4(Citations.PROJ4, DEGREE_ANGLE, false),
-
- /**
- * A special convention for formatting objects as stored internally by Apache SIS.
- * In the majority of cases, the result will be identical to the one we would get using the {@link #OGC} convention.
- * However in the particular case of map projections, the result may be quite different because of the way
- * SIS separates the linear from the non-linear parameters.
- *
- * This convention is used only for debugging purpose.
- */
- @Debug
- INTERNAL(Citations.OGC, null, false) {
- /**
- * Declares publicly that this convention is defined by Apache SIS, despite the
- * package-private {@link #authority} field being set to OGC for {@link Formatter} needs.
- */
- @Override
- public Citation getAuthority() {
- return Citations.SIS;
- }
-
- @Override
- public CoordinateSystem toConformCS(final CoordinateSystem cs) {
- return cs; // Prevent any modification on the internal CS.
- }
- };
-
- /**
- * If non-null, forces {@code PRIMEM} and {@code PARAMETER} angular units to this field
- * value instead than inferring it from the context. The standard value is {@code null},
- * which means that the angular units are inferred from the context as required by the
- * WKT specification.
- *
* @see #getForcedUnit(Class)
*/
- final Unit forcedAngularUnit;
+ final boolean commonUnits;
/**
- * {@code true} if the convention uses US unit names instead of the international names.
- * For example Americans said [@code "meter"} instead of {@code "metre"}.
+ * The organization, standard or project to look for when fetching Map Projection parameter names.
+ * Should be one of the authorities known to {@link org.apache.sis.referencing.operation.provider}.
*/
- final boolean unitUS;
-
- /**
- * The organization, standard or project to use for fetching Map Projection parameter names.
- * Shall be one of the authorities known to {@link org.apache.sis.referencing.operation.provider}.
- */
- final Citation authority;
+ private final Citation authority;
/**
* Creates a new enumeration value.
*/
- private Convention(final Citation authority, final Unit angularUnit, final boolean unitUS) {
- this.authority = authority;
- this.forcedAngularUnit = angularUnit;
- this.unitUS = unitUS;
+ private Convention(final Citation authority, final boolean isWKT1, final boolean commonUnits) {
+ this.authority = authority;
+ this.isWKT1 = isWKT1;
+ this.commonUnits = commonUnits;
}
/**
- * Returns the convention for the organization, standard or project specified by the given citation.
+ * Returns {@code true} if this convention is one of the WKT 1 variants.
*
- * @param authority The organization, standard or project for which to get the convention, or {@code null}.
- * @param defaultConvention The default convention to return if none where found for the given citation.
- * @return The convention, or {@code null} if no matching convention were found and the
- * {@code defaultConvention} argument is {@code null}.
- */
- public static Convention forCitation(final Citation authority, final Convention defaultConvention) {
- if (authority != null) {
- for (final Convention candidate : values()) {
- if (Citations.identifierMatches(candidate.getAuthority(), authority)) {
- return candidate;
- }
- }
- }
- return defaultConvention;
+ * @return {@code true} if this convention is one of the WKT 1 variants.
+ */
+ public boolean isWKT1() {
+ return isWKT1;
}
/**
- * Returns the convention for the organization, standard or project specified by the given identifier.
+ * Returns the default authority to look for when fetching Map Projection parameter names.
+ * The value returned by this method can be overwritten by {@link WKTFormat#setNameAuthority(Citation)}.
*
- * @param authority The organization, standard or project for which to get the convention, or {@code null}.
- * @param defaultConvention The default convention to return if none where found for the given identifier.
- * @return The convention, or {@code null} if no matching convention were found and the
- * {@code defaultConvention} argument is {@code null}.
- */
- public static Convention forIdentifier(final String authority, final Convention defaultConvention) {
- if (authority != null) {
- for (final Convention candidate : values()) {
- if (Citations.identifierMatches(candidate.getAuthority(), authority)) {
- return candidate;
- }
- }
- }
- return defaultConvention;
- }
-
- /**
- * Returns the citation for the organization, standard of project that defines this convention.
+ * {@example The following table shows the names given by various organizations or projects for the same projection:
+ *
+ *
+ * Authority | Projection name |
+ * EPSG | Mercator (variant A) |
+ * OGC | Mercator_1SP |
+ * GEOTIFF | CT_Mercator |
+ *
}
*
- * @return The organization, standard or project that defines this convention.
+ * @return The organization, standard or project to look for when fetching Map Projection parameter names.
*
- * @see WKTFormat#getAuthority()
+ * @see WKTFormat#getNameAuthority()
+ * @see Citations#EPSG
+ * @see Citations#OGC
*/
- public Citation getAuthority() {
+ public Citation getNameAuthority() {
return authority;
}
@@ -287,35 +208,11 @@ public enum Convention {
*/
@SuppressWarnings("unchecked")
public Unit getForcedUnit(final Class quantity) {
- if (quantity == Angle.class) {
- return (Unit) forcedAngularUnit;
+ if (commonUnits) {
+ if (quantity == Angle.class) {
+ return (Unit) DEGREE_ANGLE;
+ }
}
return null;
}
-
- /**
- * Makes the given coordinate system conform to this convention. This method is used mostly
- * for converting between the legacy (OGC 01-009) {@link GeocentricCRS} axis directions,
- * and the new (ISO 19111) directions. Those directions are:
- *
- *
- * ISO 19111 | OGC 01-009 |
- * Geocentric X | Other |
- * Geocentric Y | Easting |
- * Geocentric Z | Northing |
- *
- *
- * @param cs The coordinate system.
- * @return A coordinate system equivalent to the given one but with conform axis names,
- * or the given {@code cs} if no change apply to the given coordinate system.
- *
- * @see #OGC
- * @see #EPSG
- */
- public CoordinateSystem toConformCS(CoordinateSystem cs) {
- if (cs instanceof CartesianCS) {
- cs = Legacy.replace((CartesianCS) cs, true);
- }
- return cs;
- }
}
Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/FormattableObject.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/FormattableObject.java?rev=1562800&r1=1562799&r2=1562800&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/FormattableObject.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/FormattableObject.java [UTF-8] Thu Jan 30 12:37:10 2014
@@ -36,15 +36,14 @@ import org.apache.sis.internal.util.X364
* representation of this object:
*
*
- * - {@link #toWKT()} returns a strictly compliant WKT or throw an exception.
- * - {@link #toString()} is like {@code toWKT()} with some rules relaxed in order
- * to never throw exception.
+ * - {@link #toWKT()} returns a strictly compliant WKT or throws {@link UnformattableObjectException}
+ * if this object contains elements not defined by the ISO 19162 standard.
+ * - {@link #toString()} returns a WKT with some rules relaxed in order to never throw exception,
+ * using non-standard representation if necessary. In some cases {@code toString()} may also use
+ * an alternative text representation for better readability, for example a matrix instead of
+ * a list of {@code PARAMETER["elt_…", …]} elements for linear transforms.
*
*
- * The {@code toWKT()} method may throw {@link UnformattableObjectException} if an object
- * contains elements not defined by the official standard, while {@code toString()} can
- * fallback on a non-standard representation.
- *
* {@section Syntax coloring}
* A convenience {@link #print()} method is provided, which is roughly equivalent to
* {@code System.out.println(this)} except that syntax coloring is automatically applied
@@ -90,25 +89,23 @@ public class FormattableObject {
* @see org.opengis.referencing.IdentifiedObject#toWKT()
*/
public String toWKT() throws UnformattableObjectException {
- return formatWKT(Convention.OGC, WKTFormat.DEFAULT_INDENTATION, false, true);
+ return formatWKT(Convention.DEFAULT, WKTFormat.DEFAULT_INDENTATION, false, true);
}
/**
- * Returns a Well Known Text (WKT) using the default convention, symbols and indentation.
+ * Returns a Well Known Text (WKT) or an alternative text representation for this object.
* If this object can not be represented in a standard way, then this method fallbacks on a non-standard
* representation.
*
- * @return The Well Known Text (WKT) or a pseudo-WKT representation of this object.
+ * @return The Well Known Text (WKT) or an alternative representation of this object.
*/
@Override
public String toString() {
- return formatWKT(Convention.OGC, WKTFormat.DEFAULT_INDENTATION, false, false);
+ return formatWKT(Convention.DEFAULT, WKTFormat.DEFAULT_INDENTATION, false, false);
}
/**
* Returns a Well Known Text (WKT) for this object using the specified convention.
- * The convention is usually {@link Convention#OGC OGC}, but other common conventions are
- * {@link Convention#GEOTIFF GEOTIFF} and {@link Convention#EPSG EPSG}.
* The {@link Convention#INTERNAL INTERNAL} convention is a special value for debugging map projections.
*
* @param convention The WKT convention to use.
@@ -126,12 +123,14 @@ public class FormattableObject {
* the console supports the ANSI escape codes (a.k.a. X3.64), then a syntax coloring will be applied.
*
* This is a convenience method for debugging purpose and for console applications.
+ *
+ * @see Colors#CONSOLE
*/
@Debug
public void print() {
final Console console = System.console();
final PrintWriter out = (console != null) ? console.writer() : null;
- final String wkt = formatWKT(Convention.OGC, WKTFormat.DEFAULT_INDENTATION,
+ final String wkt = formatWKT(Convention.DEFAULT, WKTFormat.DEFAULT_INDENTATION,
(out != null) && X364.isAnsiSupported(), false);
if (out != null) {
out.println(wkt);
@@ -144,7 +143,7 @@ public class FormattableObject {
* Returns a WKT for this object using the specified convention.
* If {@code strict} is true, then an exception is thrown if the WKT is not standard-compliant.
*
- * @param convention The convention for choosing WKT entities names.
+ * @param convention The convention for choosing WKT element names.
* @param indentation The indentation to apply, or {@link WKTFormat#SINGLE_LINE}.
* @param colorize {@code true} for applying syntax coloring, or {@code false} otherwise.
* @param strict {@code true} if an exception shall be thrown for unformattable objects,
@@ -160,7 +159,7 @@ public class FormattableObject {
formatter = new Formatter();
}
formatter.indentation = indentation;
- formatter.colors = colorize ? Colors.DEFAULT : null;
+ formatter.colors = colorize ? Colors.CONSOLE : null;
formatter.setConvention(convention, null);
final String wkt;
try {
@@ -192,7 +191,7 @@ public class FormattableObject {
* Formats the inner part of this Well Known Text (WKT) element into the given formatter.
* This method is automatically invoked by {@link WKTFormat} when a formattable element is found.
*
- * Element keyword and authority code shall not be formatted here.
+ *
Keywords and authority codes shall not be formatted here.
* For example if this formattable element is for a {@code GEOGCS} element,
* then this method shall write the content starting at the insertion point shows below:
*
Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Formatter.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Formatter.java?rev=1562800&r1=1562799&r2=1562800&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Formatter.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Formatter.java [UTF-8] Thu Jan 30 12:37:10 2014
@@ -127,8 +127,8 @@ public class Formatter {
/**
* The preferred authority for objects or parameter names.
*
- * @see WKTFormat#getAuthority(Citation)
- * @see WKTFormat#setAuthority(Citation)
+ * @see WKTFormat#getNameAuthority()
+ * @see WKTFormat#setNameAuthority(Citation)
*/
private Citation authority;
@@ -191,7 +191,7 @@ public class Formatter {
private boolean requestNewLine;
/**
- * {@code true} if the last formatted element was invalid WKT and shall be highlighted with syntatic coloration.
+ * {@code true} if the last formatted element was invalid WKT and shall be highlighted with syntactic coloration.
* This field has no effect if {@link #colors} is null. This field is reset to {@code false} after the invalid
* part has been processed by {@link #append(FormattableObject)}, in order to highlight only the first erroneous
* element without clearing the {@link #invalidElement} value.
@@ -218,7 +218,7 @@ public class Formatter {
* Creates a new formatter instance with the default symbols, no syntax coloring and the default indentation.
*/
public Formatter() {
- this(Convention.OGC, Symbols.DEFAULT, null, WKTFormat.DEFAULT_INDENTATION);
+ this(Convention.DEFAULT, Symbols.DEFAULT, null, WKTFormat.DEFAULT_INDENTATION);
}
/**
@@ -250,7 +250,7 @@ public class Formatter {
* This constructor helps to share some objects with {@link Parser}.
*/
Formatter(final Symbols symbols, final NumberFormat numberFormat) {
- this.convention = Convention.OGC;
+ this.convention = Convention.DEFAULT;
this.symbols = symbols;
this.indentation = WKTFormat.DEFAULT_INDENTATION;
this.numberFormat = numberFormat; // No clone needed.
@@ -259,8 +259,7 @@ public class Formatter {
}
/**
- * Returns the convention to use for formatting the WKT. The default convention is {@link Convention#OGC OGC}.
- * A different convention will usually result in different parameter names, but may also change the WKT syntax.
+ * Returns the convention to use for formatting the WKT. The default is {@link Convention#WKT2}.
*
* @return The convention (never {@code null}).
*
@@ -278,30 +277,26 @@ public class Formatter {
* @param authority The authority, or {@code null} for inferring it from the convention.
*/
final void setConvention(Convention convention, final Citation authority) {
- if (convention == null) {
- convention = Convention.forCitation(authority, Convention.OGC);
- }
this.convention = convention;
- this.authority = (authority != null) ? authority : convention.authority; // NOT convention.getAuthority()
+ this.authority = (authority != null) ? authority : convention.getNameAuthority();
}
/**
* Returns the preferred name for the specified object.
- * If the specified object contains a name from the preferred authority
- * (usually {@linkplain org.apache.sis.metadata.iso.citation.Citations#OGC Open Geospatial}),
- * then this name is returned. Otherwise, the first name found is returned.
+ * If the specified object contains a name from the preferred authority, then this name is returned.
+ * Otherwise, the first name found is returned.
*
- * The preferred authority can be set by the {@link WKTFormat#setAuthority(Citation)} method.
+ *
The preferred authority can be set by the {@link WKTFormat#setNameAuthority(Citation)} method.
* This is not necessarily the authority of the given {@linkplain IdentifiedObject#getName() object name}.
*
* {@example The EPSG name of the EPSG:6326
datum is "World Geodetic System 1984".
- * However if the preferred authority is OGC (which is the case by default), then this method usually
- * returns "WGS84" (the exact string to be returned depends on the object aliases).}
+ * However if the preferred authority is OGC, then this method usually returns "WGS84"
+ * (the exact string to be returned depends on the object aliases).}
*
* @param object The object to look for a preferred name.
* @return The preferred name, or {@code null} if the given object has no name.
*
- * @see WKTFormat#getAuthority()
+ * @see WKTFormat#getNameAuthority()
* @see IdentifiedObjects#getName(IdentifiedObject, Citation)
*/
public String getName(final IdentifiedObject object) {
@@ -314,9 +309,8 @@ public class Formatter {
/**
* Returns the preferred identifier for the specified object.
- * If the specified object contains an identifier from the preferred authority
- * (usually {@linkplain org.apache.sis.metadata.iso.citation.Citations#OGC Open Geospatial}),
- * then this identifier is returned. Otherwise, the first identifier is returned.
+ * If the specified object contains an identifier from the preferred authority, then this identifier is returned.
+ * Otherwise, the first identifier is returned.
* If the specified object contains no identifier, then this method returns {@code null}.
*
* @param info The object to look for a preferred identifier, or {@code null} if none.
@@ -548,8 +542,8 @@ public class Formatter {
final int numCol = matrix.getNumCol();
final int openingBracket = symbols.getOpeningBracket(0);
final int closingBracket = symbols.getClosingBracket(0);
- final int openQuote = symbols.getOpenQuote();
- final int closeQuote = symbols.getCloseQuote();
+ final int openQuote = symbols.getOpeningQuote(0);
+ final int closeQuote = symbols.getClosingQuote(0);
final String separator = symbols.getSeparator();
final StringBuffer buffer = this.buffer;
boolean columns = false;
@@ -601,7 +595,7 @@ public class Formatter {
if (contextUnit!=null && unit.isCompatible(contextUnit)) {
unit = contextUnit;
} else {
- contextUnit = convention.forcedAngularUnit;
+ contextUnit = convention.getForcedUnit(Angle.class);
if (contextUnit == null) {
contextUnit = angularUnit;
}
@@ -710,7 +704,8 @@ public class Formatter {
* Appends the given string as a quoted text.
*/
private void quote(final String text) {
- buffer.appendCodePoint(symbols.getOpenQuote()).append(text).appendCodePoint(symbols.getCloseQuote());
+ buffer.appendCodePoint(symbols.getOpeningQuote(0)).append(text)
+ .appendCodePoint(symbols.getClosingQuote(0));
}
/**
@@ -775,15 +770,15 @@ public class Formatter {
appendSeparator(requestNewLine);
buffer.append("UNIT").appendCodePoint(symbols.getOpeningBracket(0));
setColor(ElementKind.UNIT);
- buffer.appendCodePoint(symbols.getOpenQuote());
+ buffer.appendCodePoint(symbols.getOpeningQuote(0));
if (NonSI.DEGREE_ANGLE.equals(unit)) {
buffer.append("degree");
} else if (SI.METRE.equals(unit)) {
- buffer.append(convention.unitUS ? "meter" : "metre");
+ buffer.append(convention.commonUnits ? "meter" : "metre");
} else {
unitFormat.format(unit, buffer, dummy);
}
- buffer.appendCodePoint(symbols.getCloseQuote());
+ buffer.appendCodePoint(symbols.getClosingQuote(0));
resetColor();
append(Units.toStandardUnit(unit));
buffer.appendCodePoint(symbols.getClosingBracket(0));
@@ -829,10 +824,9 @@ public class Formatter {
}
/**
- * Returns {@code true} if the WKT written by this formatter is not strictly compliant to the
- * WKT
- * specification. This method returns {@code true} if {@link #setInvalidWKT(IdentifiedObject)}
- * has been invoked at least once. The action to take regarding invalid WKT is caller-dependent.
+ * Returns {@code true} if the WKT written by this formatter is not strictly compliant to the WKT specification.
+ * This method returns {@code true} if {@link #setInvalidWKT(IdentifiedObject)} has been invoked at least once.
+ * The action to take regarding invalid WKT is caller-dependent.
* For example {@link FormattableObject#toString()} will accepts loose WKT formatting and ignore
* this flag, while {@link FormattableObject#toWKT()} requires strict WKT formatting and will
* thrown an exception if this flag is set.
Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Symbols.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Symbols.java?rev=1562800&r1=1562799&r2=1562800&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Symbols.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Symbols.java [UTF-8] Thu Jan 30 12:37:10 2014
@@ -34,15 +34,16 @@ import static org.apache.sis.util.Argume
* An English locale for {@linkplain java.text.DecimalFormatSymbols decimal format symbols}.
* Square brackets, as in {@code DATUM["WGS84"]}. An alternative allowed by the WKT
* specification is curly brackets as in {@code DATUM("WGS84")}.
- * English quotation mark ({@code '"'}).
+ * English quotation mark ({@code '"'}). SIS also accepts {@code “…”} quotation marks
+ * for more readable {@link String} constants in Java code.
* Coma separator followed by a space ({@code ", "}).
*
*
- * {@note Relationship between Symbols
locale and WKTFormat
locale
- * The WKTFormat
Locale
property specifies the language to use when
- * formatting InternationalString
instances. This can be set to any value.
- * On the contrary, the Locale
property of this Symbols
class controls
- * the decimal format symbols and is very rarely set to an other locale than an English one.}
+ * {@section Relationship between Symbols
locale and WKTFormat
locale}
+ * The {@link WKTFormat#getLocale()} property specifies the language to use when formatting
+ * {@link org.opengis.util.InternationalString} instances. This can be set to any value.
+ * On the contrary, the {@code Locale} property of this {@code Symbols} class controls
+ * the decimal format symbols and is very rarely set to an other locale than an English one.
*
* @author Martin Desruisseaux (IRD)
* @since 0.4 (derived from geotk-2.1)
@@ -62,19 +63,19 @@ public class Symbols implements Localize
* A set of symbols with values between square brackets, like {@code DATUM["WGS84"]}.
* This is the most frequently used WKT format.
*/
- public static final Symbols SQUARE_BRACKETS = new Immutable('[', ']', '(', ')');
+ public static final Symbols SQUARE_BRACKETS = new Immutable(
+ new int[] {'[', ']', '(', ')'}, new int[] {'"', '"', '“', '”'});
/**
* A set of symbols with values between parentheses, like {@code DATUM("WGS84")}.
* This is a less frequently used but legal WKT format.
*/
- public static final Symbols CURLY_BRACKETS = new Immutable('(', ')', '[', ']');
+ public static final Symbols CURLY_BRACKETS = new Immutable(
+ new int[] {'(', ')', '[', ']'}, SQUARE_BRACKETS.quotes);
/**
* The default set of symbols, as documented in the class javadoc.
* This is currently set to {@link #SQUARE_BRACKETS}.
- *
- * @see Colors#DEFAULT
*/
public static final Symbols DEFAULT = SQUARE_BRACKETS;
@@ -100,16 +101,23 @@ public class Symbols implements Localize
private int[] brackets;
/**
- * The character (as Unicode code point) used for opening ({@code openSequence})
- * or closing ({@code closeSequence}) an array or enumeration.
+ * List of characters (as Unicode code point) used for opening or closing a quoted text.
+ * The array shall comply to the following restrictions:
+ *
+ *
+ * - The characters at index 0 and 1 are the preferred opening and closing quotes respectively.
+ * - For each even index i, {@code quotes[i+1]} is the closing quote matching {@code quotes[i]}.
+ *
+ *
+ * Both opening and closing quotes are usually {@code '"'}.
*/
- private int openSequence, closeSequence;
+ private int[] quotes;
/**
- * The character (as Unicode code point) used for opening ({@code openQuote}) or
- * closing ({@code closeQuote}) a quoted text. This is usually {@code '"'}.
+ * The character (as Unicode code point) used for opening ({@code openSequence})
+ * or closing ({@code closeSequence}) an array or enumeration.
*/
- private int openQuote, closeQuote;
+ private int openSequence, closeSequence;
/**
* The string used as a separator in a list of values. This is usually {@code ", "},
@@ -132,10 +140,9 @@ public class Symbols implements Localize
public Symbols(final Symbols symbols) {
locale = symbols.locale;
brackets = symbols.brackets;
+ quotes = symbols.quotes;
openSequence = symbols.openSequence;
closeSequence = symbols.closeSequence;
- openQuote = symbols.openQuote;
- closeQuote = symbols.closeQuote;
separator = symbols.separator;
}
@@ -143,13 +150,12 @@ public class Symbols implements Localize
* Constructor reserved to {@link #SQUARE_BRACKETS} and {@link #CURLY_BRACKETS} constants.
* The given array is stored by reference - it is not cloned.
*/
- private Symbols(final int[] brackets) {
+ private Symbols(final int[] brackets, final int[] quotes) {
this.locale = Locale.US;
this.brackets = brackets;
+ this.quotes = quotes;
this.openSequence = '{';
this.closeSequence = '}';
- this.openQuote = '"';
- this.closeQuote = '"';
this.separator = ", ";
}
@@ -164,10 +170,10 @@ public class Symbols implements Localize
/**
* Constructor reserved to {@link Symbols#SQUARE_BRACKETS} and {@link Symbols#CURLY_BRACKETS} constants.
- * The given array is stored by reference - it is not cloned.
+ * The given arrays are stored by reference - they are not cloned.
*/
- Immutable(final int... brackets) {
- super(brackets);
+ Immutable(final int[] brackets, final int[] quotes) {
+ super(brackets, quotes);
}
/**
@@ -246,12 +252,15 @@ public class Symbols implements Localize
/**
* Returns the number of paired brackets. For example if the WKT parser accepts both the
- * {@code [ ]} and {@code ( )} paired brackets, then this method returns 2.
+ * {@code […]} and {@code (…)} bracket pairs, then this method returns 2.
*
* @return The number of bracket pairs.
+ *
+ * @see #getOpeningBracket(int)
+ * @see #getClosingBracket(int)
*/
- public final int getNumPairedBracket() {
- return brackets.length / 2;
+ public final int getNumPairedBrackets() {
+ return brackets.length >>> 1;
}
/**
@@ -259,12 +268,12 @@ public class Symbols implements Localize
* Index 0 stands for the default bracket used at formatting time.
* All other index are for optional brackets accepted at parsing time.
*
- * @param index Index of the opening bracket to get, from 0 to {@link #getNumPairedBracket()} exclusive.
+ * @param index Index of the opening bracket to get, from 0 to {@link #getNumPairedBrackets()} exclusive.
* @return The opening bracket at the given index, as a Unicode code point.
* @throws IndexOutOfBoundsException if the given index is out of bounds.
*/
public final int getOpeningBracket(final int index) {
- return brackets[index*2];
+ return brackets[index << 1];
}
/**
@@ -272,47 +281,116 @@ public class Symbols implements Localize
* Index 0 stands for the default bracket used at formatting time.
* All other index are for optional brackets accepted at parsing time.
*
- * @param index Index of the closing bracket to get, from 0 to {@link #getNumPairedBracket()} exclusive.
+ * @param index Index of the closing bracket to get, from 0 to {@link #getNumPairedBrackets()} exclusive.
* @return The closing bracket at the given index, as a Unicode code point.
* @throws IndexOutOfBoundsException if the given index is out of bounds.
*/
public final int getClosingBracket(final int index) {
- return brackets[index*2 + 1];
+ return brackets[(index << 1) | 1];
}
/**
- * Sets the opening and closing brackets to the given characters.
- * The given arrays shall comply to the following constraints:
+ * Sets the opening and closing brackets to the given pairs.
+ * Each string shall contain exactly two code points (usually two characters).
+ * The first code point is taken as the opening bracket, and the second code point as the closing bracket.
*
- *
- * - The two arrays shall be non-empty and have the same length.
- * - The characters at index 0 are the preferred opening and closing brackets.
- * - For each index i, {@code closingBrackets[i]} is the closing bracket
- * matching {@code openingBrackets[i]}.
- *
+ * {@example The following code will instruct the WKT formatter to use the (…)
pair of brackets
+ * at formatting time, but still accept the more common […]
pair of brackets at parsing
+ * time:
+ *
+ * setPairedBrackets("()", "[]");
}
*
- * @param openingBrackets The opening brackets, as a Unicode code point.
- * @param closingBrackets The closing brackets matching the opening ones.
+ * @param preferred The preferred pair of opening and closing quotes, used at formatting time.
+ * @param alternatives Alternative pairs of opening and closing quotes accepted at parsing time.
*/
- public void setBrackets(final int[] openingBrackets, final int[] closingBrackets) {
+ public void setPairedBrackets(final String preferred, final String... alternatives) {
checkWritePermission();
- ensureNonNull("openingBrackets", openingBrackets);
- ensureNonNull("closingBrackets", closingBrackets);
- final int length = openingBrackets.length;
- if (closingBrackets.length != length) {
- throw new IllegalArgumentException(Errors.format(Errors.Keys.MismatchedArrayLengths));
- }
- if (length == 0) {
- throw new IllegalArgumentException(Errors.format(Errors.Keys.EmptyArgument_1, "openingBrackets"));
- }
- final int[] brackets = new int[length * 2];
- for (int i=0,j=0; i>> 1;
+ }
+
+ /**
+ * Returns the opening quote character at the given index.
+ * Index 0 stands for the default quote used at formatting time, which is usually {@code '"'}.
+ * All other index are for optional quotes accepted at parsing time.
+ *
+ * @param index Index of the opening quote to get, from 0 to {@link #getNumPairedQuotes()} exclusive.
+ * @return The opening quote at the given index, as a Unicode code point.
+ * @throws IndexOutOfBoundsException if the given index is out of bounds.
+ */
+ public final int getOpeningQuote(final int index) {
+ return quotes[index << 1];
+ }
+
+ /**
+ * Returns the closing quote character at the given index.
+ * Index 0 stands for the default quote used at formatting time, which is usually {@code '"'}.
+ * All other index are for optional quotes accepted at parsing time.
+ *
+ * @param index Index of the closing quote to get, from 0 to {@link #getNumPairedQuotes()} exclusive.
+ * @return The closing quote at the given index, as a Unicode code point.
+ * @throws IndexOutOfBoundsException if the given index is out of bounds.
+ */
+ public final int getClosingQuote(final int index) {
+ return quotes[(index << 1) | 1];
+ }
+
+ /**
+ * Sets the opening and closing quotes to the given pairs.
+ * Each string shall contain exactly two code points (usually two characters).
+ * The first code point is taken as the opening quote, and the second code point as the closing quote.
+ *
+ * {@example The following code will instruct the WKT formatter to use the prettier “…”
+ * quotation marks at formatting time (especially useful for String
constants
+ * in Java code), but still accept the standard "…"
quotation marks at parsing
+ * time:
+ *
+ * setPairedQuotes("“”", "\"\"");
}
+ *
+ * @param preferred The preferred pair of opening and closing quotes, used at formatting time.
+ * @param alternatives Alternative pairs of opening and closing quotes accepted at parsing time.
+ */
+ public void setPairedQuotes(final String preferred, final String... alternatives) {
+ checkWritePermission();
+ quotes = toCodePoints(preferred, alternatives);
+ }
+
+ /**
+ * Packs the given pairs of bracket or quotes in a single array of code points.
+ * This method also verifies arguments validity.
+ */
+ private static int[] toCodePoints(final String preferred, final String[] alternatives) {
+ ensureNonNull("preferred", preferred);
+ final int n = (alternatives != null) ? alternatives.length : 0;
+ final int[] array = new int[(n+1) * 2];
+ String name = "preferred";
+ String pair = preferred;
+ int i=0, j=0;
+ while (true) {
+ if (pair.codePointCount(0, pair.length()) != 2) {
+ throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentValue_2, name, pair));
+ }
+ final int c = pair.codePointAt(0);
+ ensureValidUnicodeCodePoint(name, array[j++] = c);
+ ensureValidUnicodeCodePoint(name, array[j++] = pair.codePointAt(Character.charCount(c)));
+ if (i >= n) {
+ break;
+ }
+ ensureNonNullElement(name = "alternatives", i, pair = alternatives[i++]);
}
- this.brackets = brackets; // Store only on success.
+ return array;
}
/**
@@ -350,38 +428,6 @@ public class Symbols implements Localize
}
/**
- * Returns the character used for opening a quoted text. This is usually {@code '"'}.
- *
- * @return The character used for opening a quoted text, as a Unicode code point.
- */
- public final int getOpenQuote() {
- return openQuote;
- }
-
- /**
- * Returns the character used for closing a quoted text. This is usually {@code '"'}.
- *
- * @return The character used for closing a quoted text, as a Unicode code point.
- */
- public final int getCloseQuote() {
- return closeQuote;
- }
-
- /**
- * Sets the characters used for opening and closing a quoted text.
- *
- * @param openQuote The character for opening a quoted text, as a Unicode code point.
- * @param closeQuote The character for closing a quoted text, as a Unicode code point.
- */
- public void setQuotes(final int openQuote, final int closeQuote) {
- checkWritePermission();
- ensureValidUnicodeCodePoint("openQuote", openQuote);
- ensureValidUnicodeCodePoint("closeQuote", closeQuote);
- this.openQuote = openQuote;
- this.closeQuote = closeQuote;
- }
-
- /**
* Returns the string used as a separator in a list of values. This is usually {@code ", "},
* but may be different if a non-English locale is used for formatting numbers.
*
@@ -428,8 +474,8 @@ public class Symbols implements Localize
*
*
* - The search is case-insensitive.
- * - Characters between the {@linkplain #getOpenQuote() open quote} and the
- * {@linkplain #getCloseQuote() close quote} are ignored.
+ * - Characters between {@linkplain #getOpeningQuote(int) opening quotes} and
+ * {@linkplain #getClosingQuote(int) closing quotes} are ignored.
* - The element found in the given WKT can not be preceded by other
* {@linkplain Character#isUnicodeIdentifierPart(int) Unicode identifier characters}.
* - The element found in the given WKT must be followed, ignoring space, by an
@@ -457,12 +503,12 @@ public class Symbols implements Localize
* Invoking this method is equivalent to invoking
*
{@linkplain #containsElement(CharSequence, String) containsElement}(wkt, "AXIS")
.
*
- * The check for axis elements is of particular interest because the axis order is a frequent cause
+ * {@section Use case}
+ * The check for axis elements is of particular interest because the axis order is a frequent cause
* of confusion when processing geographic data. Some applications just ignore any declared axis order
* in favor of their own hard-coded (longitude, latitude) axis order.
* Consequently, the presence of {@code AXIS[…]} elements in a WKT is an indication that the encoded
* object may not be understood as intended by some external softwares.
- * See for example {@link Convention#ESRI}.
*
* @param wkt The WKT to inspect.
* @return {@code true} if the given WKT contains at least one instance of the {@code AXIS[…]} element.
@@ -480,12 +526,22 @@ public class Symbols implements Localize
* @param offset The index to start the search from.
*/
private boolean containsElement(final CharSequence wkt, final String element, int offset) {
+ final int[] quotes = this.quotes;
final int length = wkt.length();
boolean isQuoting = false;
+ int closeQuote = 0;
while (offset < length) {
int c = Character.codePointAt(wkt, offset);
- if (c == (isQuoting ? closeQuote : openQuote)) {
- isQuoting = !isQuoting;
+ if (closeQuote != 0) {
+ if (c == closeQuote) {
+ isQuoting = false;
+ }
+ } else for (int i=0; i