Author: desruisseaux
Date: Wed Feb 1 19:15:46 2017
New Revision: 1781298
URL: http://svn.apache.org/viewvc?rev=1781298&view=rev
Log:
Initial port of CoordinateFormat class.
Added:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/CoordinateFormat.java
(with props)
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/CoordinateFormatTest.java
(with props)
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/DirectPosition1D.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/DirectPosition2D.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralDirectPosition.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/package-info.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/XPaths.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/io/CompoundFormat.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/AngleFormat.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Latitude.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/LinearConverter.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Longitude.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitFormat.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/package-info.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java?rev=1781298&r1=1781297&r2=1781298&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/AbstractEnvelope.java
[UTF-8] Wed Feb 1 19:15:46 2017
@@ -1121,7 +1121,7 @@ public abstract class AbstractEnvelope i
* @return this envelope as a {@code BOX} or {@code BOX3D} (most typical
dimensions) element.
*
* @see GeneralEnvelope#GeneralEnvelope(CharSequence)
- * @see org.apache.sis.measure.CoordinateFormat
+ * @see CoordinateFormat
* @see org.apache.sis.io.wkt
*/
static String toString(final Envelope envelope, final boolean
isSimplePrecision) {
Added:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/CoordinateFormat.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/CoordinateFormat.java?rev=1781298&view=auto
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/CoordinateFormat.java
(added)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/CoordinateFormat.java
[UTF-8] Wed Feb 1 19:15:46 2017
@@ -0,0 +1,716 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.geometry;
+
+import java.text.Format;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.text.NumberFormat;
+import java.text.DecimalFormat;
+import java.text.FieldPosition;
+import java.text.ParsePosition;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+import java.io.IOException;
+import javax.measure.Unit;
+import javax.measure.UnitConverter;
+import javax.measure.quantity.Time;
+import javax.measure.IncommensurableException;
+import org.opengis.geometry.DirectPosition;
+import org.opengis.referencing.cs.AxisDirection;
+import org.opengis.referencing.cs.CoordinateSystem;
+import org.opengis.referencing.cs.CoordinateSystemAxis;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.crs.TemporalCRS;
+import org.apache.sis.internal.util.LocalizedParseException;
+import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.CharSequences;
+import org.apache.sis.util.Characters;
+import org.apache.sis.measure.Angle;
+import org.apache.sis.measure.AngleFormat;
+import org.apache.sis.measure.Latitude;
+import org.apache.sis.measure.Longitude;
+import org.apache.sis.measure.Units;
+import org.apache.sis.referencing.CRS;
+import org.apache.sis.io.CompoundFormat;
+
+// Branch-dependent imports
+import java.io.UncheckedIOException;
+
+
+/**
+ * Formats spatiotemporal coordinates using number, angle and date formats
inferred from the coordinate system.
+ * The format for each ordinate is inferred from the
+ * {@linkplain
org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis#getUnit() coordinate
system units}
+ * using the following rules:
+ *
+ * <ul>
+ * <li>Ordinate values in angular units are formated as angles using {@link
AngleFormat}.</li>
+ * <li>Ordinate values in temporal units are formated as dates using {@link
DateFormat}.</li>
+ * <li>Other values are formatted as numbers using {@link NumberFormat}
followed by the unit symbol
+ * formatted by {@link org.apache.sis.measure.UnitFormat}.</li>
+ * </ul>
+ *
+ * The format can be controlled by invoking the {@link #applyPattern(Class,
String)} public method,
+ * or by overriding the {@link #createFormat(Class)} protected method.
+ *
+ * <p>This format does <strong>not</strong> transform the given coordinates in
a unique CRS.
+ * If the coordinates need to be formatted in a specific CRS, then the caller
should
+ * {@linkplain
org.apache.sis.referencing.operation.transform.AbstractMathTransform#transform(DirectPosition,
DirectPosition)
+ * transform the position} before to format it.</p>
+ *
+ * @author Martin Desruisseaux (MPO, IRD, Geomatys)
+ * @since 0.8
+ * @version 0.8
+ * @module
+ *
+ * @see AngleFormat
+ * @see org.apache.sis.measure.UnitFormat
+ * @see GeneralDirectPosition
+ */
+public class CoordinateFormat extends CompoundFormat<DirectPosition> {
+ /**
+ * Serial number for cross-version compatibility.
+ */
+ private static final long serialVersionUID = 8324486673169133932L;
+
+ /**
+ * The separator between each coordinate values to be formatted.
+ * The default value is a space.
+ */
+ private String separator;
+
+ /**
+ * The coordinate reference system to assume if no CRS is attached to the
position to format.
+ * May be {@code null}.
+ */
+ private CoordinateReferenceSystem defaultCRS;
+
+ /**
+ * The coordinate reference system of the last {@link DirectPosition} that
we formatted.
+ * This is used for determining if we need to recompute all other
transient fields in this class.
+ */
+ private transient CoordinateReferenceSystem lastCRS;
+
+ /**
+ * Constants for the {@link #types} array.
+ */
+ private static final byte LONGITUDE=1, LATITUDE=2, ANGLE=3, DATE=4, TIME=5;
+
+ /**
+ * The type for each value in the {@code formats} array, or {@code null}
if not yet computed.
+ * Types are: 0=number, 1=longitude, 2=latitude, 3=other angle, 4=date,
5=elapsed time.
+ */
+ private transient byte[] types;
+
+ /**
+ * The formats to use for formatting, or {@code null} if not yet computed.
+ * This array length should be equal to the {@link #lastCRS} dimension.
+ */
+ private transient Format[] formats;
+
+ /**
+ * The units for each dimension to be formatted as number.
+ * We do not store this information for dimensions to be formatted as
angle or date.
+ */
+ private transient Unit<?>[] units;
+
+ /**
+ * Conversions from arbitrary units to the unit used by formatter, or
{@code null} if none.
+ * For example in the case of dates, this is the conversions from temporal
axis units to milliseconds.
+ */
+ private transient UnitConverter[] toFormatUnit;
+
+ /**
+ * Units symbols. Used only for ordinate to be formatted as ordinary
numbers.
+ * Non-null only if at least one ordinate is to be formatted that way.
+ */
+ private transient String[] unitSymbols;
+
+ /**
+ * Flags the ordinate values that need to be inverted before to be
formatted.
+ * This is needed for example if the axis is oriented toward past instead
than future,
+ * or toward west instead than east.
+ *
+ * @see #negate(int)
+ */
+ private transient int negate;
+
+ /**
+ * The time epochs. Non-null only if the at least on ordinate is to be
formatted as a date.
+ */
+ private transient long[] epochs;
+
+ /**
+ * Dummy field position.
+ */
+ private transient FieldPosition dummy;
+
+ /**
+ * Temporary buffer to use if the {@code toAppendTo} argument given to
{@link #format(DirectPosition, Appendable)}
+ * is not an instance of {@code StringBuffer}.
+ */
+ private transient StringBuffer buffer;
+
+ /**
+ * Constructs a new coordinate format with default locale and timezone.
+ */
+ public CoordinateFormat() {
+ this(Locale.getDefault(Locale.Category.FORMAT), TimeZone.getDefault());
+ }
+
+ /**
+ * Constructs a new coordinate format for the specified locale and
timezone.
+ *
+ * @param locale the locale for the new {@code Format}, or {@code
null} for {@code Locale.ROOT}.
+ * @param timezone the timezone, or {@code null} for UTC.
+ */
+ public CoordinateFormat(final Locale locale, final TimeZone timezone) {
+ super(locale, timezone);
+ separator = " ";
+ }
+
+ /**
+ * Returns the separator between each coordinate (number, angle or date).
+ * The default value is a single space.
+ *
+ * @return the current coordinate separator.
+ */
+ public String getSeparator() {
+ return separator;
+ }
+
+ /**
+ * Sets the separator between each coordinate.
+ * The default value is a single space.
+ *
+ * @param separator the new coordinate separator.
+ */
+ public void setSeparator(final String separator) {
+ ArgumentChecks.ensureNonNull("separator", separator);
+ this.separator = separator;
+ }
+
+ /**
+ * Returns the coordinate reference system to use if no CRS is explicitely
associated to a given {@code DirectPosition}.
+ *
+ * @return the default coordinate reference system, or {@code null} if
none.
+ */
+ public CoordinateReferenceSystem getDefaultCRS() {
+ return defaultCRS;
+ }
+
+ /**
+ * Sets the coordinate reference system to use if no CRS is explicitely
associated to a given {@code DirectPosition}.
+ * This CRS is only a default; positions given in another CRS are
<strong>not</strong> automatically transformed to
+ * that CRS before formatting.
+ *
+ * @param crs the default coordinate reference system, or {@code null}
if none.
+ */
+ public void setDefaultCRS(final CoordinateReferenceSystem crs) {
+ defaultCRS = crs;
+ }
+
+ /**
+ * Computes the value of transient fields from the given CRS.
+ */
+ private void initialize(final CoordinateReferenceSystem crs) {
+ types = null;
+ formats = null;
+ units = null;
+ toFormatUnit = null;
+ unitSymbols = null;
+ epochs = null;
+ negate = 0;
+ lastCRS = crs;
+ if (crs == null) {
+ return;
+ }
+ /*
+ * If no CRS were specified, we will format everything as numbers.
Working with null CRS
+ * is sometime useful because null CRS are allowed in DirectPosition
according ISO 19107.
+ * Otherwise (if a CRS is given), infer the format subclasses from the
axes.
+ */
+ final CoordinateSystem cs = crs.getCoordinateSystem();
+ final int dimension = cs.getDimension();
+ final byte[] types = new byte [dimension];
+ final Format[] formats = new Format[dimension];
+ for (int i=0; i<dimension; i++) {
+ final CoordinateSystemAxis axis = cs.getAxis(i);
+ final Unit<?> unit = axis.getUnit();
+ /*
+ * Formatter for angular units. Target unit is DEGREE_ANGLE.
+ * Type is LONGITUDE, LATITUDE or ANGLE depending on axis
direction.
+ */
+ if (Units.isAngular(unit)) {
+ byte type = ANGLE;
+ final AxisDirection dir = axis.getDirection();
+ if (AxisDirection.NORTH.equals(dir)) {type = LATITUDE;}
+ else if (AxisDirection.EAST .equals(dir)) {type = LONGITUDE;}
+ else if (AxisDirection.SOUTH.equals(dir)) {type = LATITUDE;
negate(i);}
+ else if (AxisDirection.WEST .equals(dir)) {type = LONGITUDE;
negate(i);}
+ types [i] = type;
+ formats[i] = getFormat(Angle.class);
+ setConverter(dimension, i,
unit.asType(javax.measure.quantity.Angle.class).getConverterTo(Units.DEGREE));
+ continue;
+ }
+ /*
+ * Formatter for temporal units. Target unit is MILLISECONDS.
+ * Type is DATE.
+ */
+ if (Units.isTemporal(unit)) {
+ final CoordinateReferenceSystem t = CRS.getComponentAt(crs, i,
i+1);
+ if (t instanceof TemporalCRS) {
+ if (epochs == null) {
+ epochs = new long[dimension];
+ }
+ types [i] = DATE;
+ formats[i] = getFormat(Date.class);
+ epochs [i] = ((TemporalCRS)
t).getDatum().getOrigin().getTime();
+ setConverter(dimension, i,
unit.asType(Time.class).getConverterTo(Units.MILLISECOND));
+ if (AxisDirection.PAST.equals(axis.getDirection())) {
+ negate(i);
+ }
+ continue;
+ }
+ types[i] = TIME;
+ // Fallthrough: formatted as number.
+ }
+ /*
+ * Formatter for all other units. Do NOT set types[i] since it may
have been set
+ * to a non-zero value by previous case. If not, the default value
(zero) is the
+ * one we want.
+ */
+ formats[i] = getFormat(Number.class);
+ if (unit != null) {
+ if (units == null) {
+ units = new Unit<?>[dimension];
+ }
+ units[i] = unit;
+ final String symbol = getFormat(Unit.class).format(unit);
+ if (!symbol.isEmpty()) {
+ if (unitSymbols == null) {
+ unitSymbols = new String[dimension];
+ }
+ unitSymbols[i] = symbol;
+ }
+ }
+ }
+ this.types = types; // Assign only on success.
+ this.formats = formats;
+ }
+
+ /**
+ * Sets the unit converter at the given index.
+ */
+ private void setConverter(final int dimension, final int i, final
UnitConverter c) {
+ if (!c.isIdentity()) {
+ if (toFormatUnit == null) {
+ toFormatUnit = new UnitConverter[dimension];
+ }
+ toFormatUnit[i] = c;
+ }
+ }
+
+ /**
+ * Remembers that ordinate values at the given dimension will need to have
their sign reverted.
+ */
+ private void negate(final int dimension) {
+ if (dimension >= Integer.SIZE) {
+ throw new
ArithmeticException(Errors.format(Errors.Keys.ExcessiveNumberOfDimensions_1,
dimension));
+ }
+ negate |= (1 << dimension);
+ }
+
+ /**
+ * Returns {@code true} if the value at the given dimension needs to have
its sign reversed.
+ */
+ private boolean isNegative(final int dimension) {
+ return (dimension < Integer.SIZE) && (negate & (1 << dimension)) != 0;
+ }
+
+ /**
+ * Returns the pattern for number, angle or date fields. The given {@code
valueType} should be
+ * {@code Number.class}, {@code Angle.class}, {@code Date.class} or a
sub-type of the above.
+ * This method may return {@code null} if the underlying format can not
provide a pattern.
+ *
+ * <table class="sis">
+ * <caption>Pattern availability for type of value</caption>
+ * <tr><th>Value type</th> <th>Base format class</th> <th>Format
with pattern</th></tr>
+ * <tr><td>{@link Number}</td> <td>{@link NumberFormat}</td> <td>{@link
DecimalFormat}</td></tr>
+ * <tr><td>{@link Angle}</td> <td>{@link AngleFormat}</td> <td>{@link
AngleFormat}</td></tr>
+ * <tr><td>{@link Date}</td> <td>{@link DateFormat}</td> <td>{@link
SimpleDateFormat}</td></tr>
+ * </table>
+ *
+ * @param valueType the base type of ordinate values to parse and format:
+ * {@code Number.class}, {@code Angle.class} or {@code
Date.class}.
+ * @return the pattern for fields of the given type, or {@code null} if
not applicable.
+ *
+ * @see #getFormat(Class)
+ */
+ public String getPattern(final Class<?> valueType) {
+ final Format format = getFormat(valueType);
+ if (format instanceof AngleFormat) {
+ return ((AngleFormat) format).toPattern();
+ } else if (format instanceof DecimalFormat) {
+ return ((DecimalFormat) format).toPattern();
+ } else if (format instanceof SimpleDateFormat) {
+ return ((SimpleDateFormat) format).toPattern();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the pattern for number, angle or date fields.
+ * The pattern syntax depends on the {@code valueType} argument:
+ *
+ * <ul>
+ * <li>If {@code valueType} is {@code Number.class}, then the pattern
syntax shall be as described in the
+ * {@link DecimalFormat} class. This pattern may be used for any
ordinate to be formatted as plain number,
+ * for example in {@linkplain
org.apache.sis.referencing.cs.DefaultCartesianCS Cartesian coordinate
system}.</li>
+ * <li>If {@code valueType} is {@code Angle.class}, then the pattern
syntax shall be as described in the
+ * {@link AngleFormat} class. This pattern may be used for any
ordinate to be formatted as latitude or longitude,
+ * for example in {@linkplain
org.apache.sis.referencing.cs.DefaultEllipsoidalCS ellipsoidal coordinate
system}.</li>
+ * <li>If {@code valueType} is {@code Date.class}, then the pattern
syntax shall be as described in the
+ * {@link SimpleDateFormat} class. This pattern may be used for any
ordinate to be formatted as date and time,
+ * for example in {@linkplain
org.apache.sis.referencing.cs.DefaultTimeCS time coordinate system}.</li>
+ * </ul>
+ *
+ * @param valueType the base type of ordinate values to parse and format:
+ * {@code Number.class}, {@code Angle.class} or {@code
Date.class}.
+ * @param pattern the pattern as specified in {@link DecimalFormat},
{@link AngleFormat}
+ * or {@link SimpleDateFormat} javadoc.
+ * @return {@code true} if the pattern has been applied, or {@code false}
if {@code valueType} does not
+ * specify a known type or if the format associated to that type
does not support patterns.
+ * @throws IllegalArgumentException if the given pattern is invalid.
+ */
+ public boolean applyPattern(final Class<?> valueType, final String
pattern) {
+ ArgumentChecks.ensureNonNull("pattern", pattern);
+ final Format format = getFormat(valueType);
+ if (format instanceof DecimalFormat) {
+ ((DecimalFormat) format).applyPattern(pattern);
+ } else if (format instanceof SimpleDateFormat) {
+ ((SimpleDateFormat) format).applyPattern(pattern);
+ } else if (format instanceof AngleFormat) {
+ ((AngleFormat) format).applyPattern(pattern);
+ } else {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns the base type of values parsed and formatted by this {@code
Format} instance.
+ *
+ * @return {@code DirectPosition.class}.
+ */
+ @Override
+ public final Class<DirectPosition> getValueType() {
+ return DirectPosition.class;
+ }
+
+ /**
+ * Formats the given coordinate.
+ *
+ * @param position the coordinate to format.
+ * @return the formatted position.
+ */
+ public String format(final DirectPosition position) {
+ if (buffer == null) {
+ buffer = new StringBuffer();
+ }
+ buffer.setLength(0);
+ try {
+ format(position, buffer);
+ } catch (IOException e) {
+ /*
+ * Should never happen when writing into a StringBuffer, unless
the user override the
+ * format(…) method. We do not rethrow an AssertionError because
of this possibility.
+ */
+ throw new UncheckedIOException(e);
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Formats the given coordinate and appends the resulting text to the
given stream or buffer.
+ *
+ * @param position the coordinate to format.
+ * @param toAppendTo where the text is to be appended.
+ * @throws IOException if an error occurred while writing to the given
appendable.
+ */
+ @Override
+ @SuppressWarnings("UnnecessaryBoxing")
+ public void format(final DirectPosition position, final Appendable
toAppendTo) throws IOException {
+ ArgumentChecks.ensureNonNull("position", position);
+ ArgumentChecks.ensureNonNull("toAppendTo", toAppendTo);
+ CoordinateReferenceSystem crs =
position.getCoordinateReferenceSystem();
+ if (crs == null) {
+ crs = defaultCRS; // May still be null.
+ }
+ if (crs != lastCRS) {
+ initialize(crs);
+ }
+ /*
+ * Standard java.text.Format API can only write into a StringBuffer.
If the given Appendable is not a
+ * StringBuffer, then we will need to format in a temporary buffer
before to copy to the Appendable.
+ */
+ final StringBuffer destination;
+ if (toAppendTo instanceof StringBuffer) {
+ destination = (StringBuffer) toAppendTo;
+ } else {
+ if (buffer == null) {
+ buffer = new StringBuffer();
+ }
+ destination = buffer;
+ destination.setLength(0);
+ }
+ if (dummy == null) {
+ dummy = new FieldPosition(0);
+ }
+ /*
+ * The format to use for each ordinate has been computed by
'initialize'. The format array length
+ * should match the number of dimensions in the given position if the
DirectPosition is consistent
+ * with its CRS, but we will nevertheless verify has a paranoiac
check. If there is no CRS, or if
+ * the DirectPosition dimension is (illegally) greater than the CRS
dimension, then we will format
+ * the ordinate as a number.
+ */
+ final int dimension = position.getDimension();
+ for (int i=0; i < dimension; i++) {
+ double value = position.getOrdinate(i);
+ final Object object;
+ final Format f;
+ if (formats != null && i < formats.length) {
+ f = formats[i];
+ if (isNegative(i)) {
+ value = -value;
+ }
+ if (toFormatUnit != null) {
+ final UnitConverter c = toFormatUnit[i];
+ if (c != null) {
+ value = c.convert(value);
+ }
+ }
+ switch (types[i]) {
+ default: object = Double.valueOf(value); break;
+ case LONGITUDE: object = new Longitude (value); break;
+ case LATITUDE: object = new Latitude (value); break;
+ case ANGLE: object = new Angle (value); break;
+ case DATE: object = new Date(Math.round(value) +
epochs[i]); break;
+ }
+ } else {
+ object = value;
+ f = getFormat(Number.class);
+ }
+ /*
+ * At this point we got the value to format together with the
Format instance to use.
+ */
+ if (i != 0) {
+ toAppendTo.append(separator);
+ }
+ if (f.format(object, destination, dummy) != toAppendTo) {
+ toAppendTo.append(destination);
+ destination.setLength(0);
+ }
+ if (unitSymbols != null && i < unitSymbols.length) {
+ final String symbol = unitSymbols[i];
+ if (symbol != null) {
+
toAppendTo.append(Characters.NO_BREAK_SPACE).append(symbol);
+ }
+ }
+ }
+ }
+
+ /**
+ * Parses a coordinate from the given character sequence.
+ * This method presumes that the coordinate reference system is the
{@linkplain #getDefaultCRS() default CRS}.
+ * The parsing begins at the index given by the {@code pos} argument. If
parsing succeeds, then:
+ *
+ * <ul>
+ * <li>The {@code pos} {@linkplain ParsePosition#getIndex() index}
+ * is updated to the index after the last ordinate value.</li>
+ * <li>The parsed coordinate is returned.</li>
+ * </ul>
+ *
+ * If parsing fails, then:
+ *
+ * <ul>
+ * <li>The {@code pos} index is left unchanged</li>
+ * <li>The {@code pos} {@linkplain ParsePosition#getErrorIndex() error
index}
+ * is set to the beginning of the unparsable ordinate value.</li>
+ * </ul>
+ *
+ * @param text the character sequence for the coordinate to parse.
+ * @param pos the index where to start the parsing.
+ * @return the parsed coordinate.
+ * @throws ParseException if an error occurred while parsing the
coordinate.
+ */
+ @Override
+ public DirectPosition parse(final CharSequence text, final ParsePosition
pos) throws ParseException {
+ ArgumentChecks.ensureNonNull("text", text);
+ ArgumentChecks.ensureNonNull("pos", pos);
+ /*
+ * The NumberFormat, DateFormat and AngleFormat work only on String
values, not on CharSequence.
+ * If the given text is not a String, we will convert an arbitrarily
small section of the given
+ * text. Note that this will require to adjust the ParsePosition
indices.
+ */
+ final int offset;
+ final String asString;
+ final ParsePosition subPos;
+ if (text instanceof String) {
+ offset = 0;
+ subPos = pos;
+ asString = (String) text;
+ } else {
+ offset = pos.getIndex();
+ subPos = new ParsePosition(0);
+ asString = text.subSequence(offset, Math.min(offset + 256,
text.length())).toString();
+ }
+ /*
+ * The Format instances to be used for each ordinate values is
determined by the default CRS.
+ * If no such CRS has been specified, then we will parse everything as
plain numbers.
+ */
+ if (lastCRS != defaultCRS) {
+ initialize(defaultCRS);
+ }
+ double[] ordinates = new double[formats.length]; // TODO: null
if no CRS has been specified.
+ for (int i=0; i < ordinates.length; i++) {
+ final Object object = formats[i].parseObject(asString, subPos);
+ if (object == null) {
+ /*
+ * If we failed to parse, build an error message with the type
that was expected for that ordinate.
+ * If the given CharSequence was not a String, we may need to
update the error index since we tried
+ * to parse only a substring.
+ */
+ Class<?> type = Number.class;
+ if (types != null) {
+ switch (types[i]) {
+ case LONGITUDE: type = Longitude.class; break;
+ case LATITUDE: type = Latitude.class; break;
+ case ANGLE: type = Angle.class; break;
+ case DATE: type = Date.class; break;
+ }
+ }
+ pos.setIndex(offset);
+ if (subPos != pos) {
+ pos.setErrorIndex(offset + subPos.getErrorIndex());
+ }
+ throw new LocalizedParseException(getLocale(), type, text,
pos);
+ }
+ double value;
+ if (object instanceof Angle) {
+ value = ((Angle) object).degrees();
+ } else if (object instanceof Date) {
+ value = ((Date) object).getTime() - epochs[i];
+ } else {
+ value = ((Number) object).doubleValue();
+ }
+ /*
+ * The conversions and sign reversal applied below shall be in
exact reverse order than
+ * in the 'format(…)' method. However we have one additional step
compared to format(…):
+ * the unit written after the ordinate value may not be the same
than the unit declared
+ * in the CRS axis, so we have to parse the unit and convert the
value before to apply
+ * the reverse of 'format(…)' steps.
+ */
+ if (units != null) {
+ final Unit<?> target = units[i];
+ if (target != null) {
+ final int base = subPos.getIndex();
+ int index = base;
+ /*
+ * Skip whitespaces using Character.isSpaceChar(…), not
Character.isWhitespace(…),
+ * because we need to skip also the non-breaking space
(Characters.NO_BREAK_SPACE).
+ * If we can not parse the unit after those spaces, we
will revert to the original
+ * position (absence of unit will not be considered an
error).
+ */
+ while (index < asString.length()) {
+ final int c = asString.codePointAt(index);
+ if (Character.isSpaceChar(c)) {
+ index += Character.charCount(c);
+ continue;
+ }
+ subPos.setIndex(index);
+ final Object unit =
getFormat(Unit.class).parseObject(asString, subPos);
+ if (unit == null) {
+ subPos.setIndex(base);
+ subPos.setErrorIndex(-1);
+ } else try {
+ value = ((Unit<?>)
unit).getConverterToAny(target).convert(value);
+ } catch (IncommensurableException e) {
+ index += offset;
+ pos.setIndex(offset);
+ pos.setErrorIndex(index);
+ throw (ParseException) new
ParseException(e.getMessage(), index).initCause(e);
+ }
+ break;
+ }
+ }
+ }
+ if (toFormatUnit != null) {
+ final UnitConverter c = toFormatUnit[i];
+ if (c != null) {
+ value = c.inverse().convert(value);
+ }
+ }
+ if (isNegative(i)) {
+ value = -value;
+ }
+ ordinates[i] = value;
+ /*
+ * We require the separator to be present before to continue.
+ */
+ final int index = offset + subPos.getIndex();
+ if (!CharSequences.regionMatches(text, index, separator)) {
+ if (i+1 == ordinates.length) {
+ break;
+ }
+ pos.setIndex(offset);
+ pos.setErrorIndex(index);
+ throw new LocalizedParseException(getLocale(),
Errors.Keys.UnexpectedCharactersAfter_2,
+ new CharSequence[] {text.subSequence(offset, index),
CharSequences.token(text, index)}, index);
+ }
+ subPos.setIndex(index + separator.length() - offset);
+ }
+ final GeneralDirectPosition position = new
GeneralDirectPosition(ordinates);
+ position.setCoordinateReferenceSystem(defaultCRS);
+ return position;
+ }
+
+ /**
+ * Returns a clone of this format.
+ *
+ * @return a clone of this format.
+ */
+ @Override
+ public CoordinateFormat clone() {
+ final CoordinateFormat clone = (CoordinateFormat) super.clone();
+ clone.dummy = null;
+ clone.buffer = null;
+ Format[] cf = clone.formats;
+ if (cf != null) {
+ clone.formats = cf = cf.clone();
+ for (int i=0; i < cf.length; i++) {
+ cf[i] = (Format) cf[i].clone();
+ }
+ }
+ return clone;
+ }
+}
Propchange:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/CoordinateFormat.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/CoordinateFormat.java
------------------------------------------------------------------------------
svn:mime-type = text/plain;charset=UTF-8
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/DirectPosition1D.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/DirectPosition1D.java?rev=1781298&r1=1781297&r2=1781298&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/DirectPosition1D.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/DirectPosition1D.java
[UTF-8] Wed Feb 1 19:15:46 2017
@@ -42,6 +42,7 @@ import static org.apache.sis.util.Argume
*
* @see DirectPosition2D
* @see GeneralDirectPosition
+ * @see CoordinateFormat
*/
public class DirectPosition1D extends AbstractDirectPosition implements
Serializable, Cloneable {
/**
@@ -99,7 +100,7 @@ public class DirectPosition1D extends Ab
* @throws MismatchedDimensionException if the given point is not
one-dimensional.
*
* @see #toString()
- * @see org.apache.sis.measure.CoordinateFormat
+ * @see CoordinateFormat
*/
public DirectPosition1D(final CharSequence wkt) throws
IllegalArgumentException {
final double[] ordinates = parse(wkt);
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/DirectPosition2D.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/DirectPosition2D.java?rev=1781298&r1=1781297&r2=1781298&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/DirectPosition2D.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/DirectPosition2D.java
[UTF-8] Wed Feb 1 19:15:46 2017
@@ -66,6 +66,7 @@ import static org.apache.sis.util.Argume
* @see DirectPosition1D
* @see GeneralDirectPosition
* @see Point2D
+ * @see CoordinateFormat
*/
public class DirectPosition2D extends Point2D.Double implements
DirectPosition, Cloneable {
/**
@@ -156,7 +157,7 @@ public class DirectPosition2D extends Po
* @throws MismatchedDimensionException if the given point is not
two-dimensional.
*
* @see #toString()
- * @see org.apache.sis.measure.CoordinateFormat
+ * @see CoordinateFormat
*/
public DirectPosition2D(final CharSequence wkt) throws
IllegalArgumentException {
final double[] ordinates = AbstractDirectPosition.parse(wkt);
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralDirectPosition.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralDirectPosition.java?rev=1781298&r1=1781297&r2=1781298&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralDirectPosition.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralDirectPosition.java
[UTF-8] Wed Feb 1 19:15:46 2017
@@ -57,6 +57,7 @@ import static org.apache.sis.util.Argume
*
* @see DirectPosition1D
* @see DirectPosition2D
+ * @see CoordinateFormat
*/
public class GeneralDirectPosition extends AbstractDirectPosition implements
Serializable, Cloneable {
/**
@@ -108,10 +109,16 @@ public class GeneralDirectPosition exten
* Consequently, callers shall not recycle the same array for creating
many instances.
*
* <div class="note"><b>Implementation note:</b>
- * The array is not cloned because this is usually not needed, especially
in the context of variable
+ * the array is not cloned because this is usually not needed, especially
in the context of variable
* argument lengths since the array is often created implicitly.
Furthermore the {@link #ordinates}
* field is public, so cloning the array would not protect the state of
this object anyway.</div>
*
+ * <p><b>Caution:</b> if only one number is specified, make sure that the
number type is {@code double},
+ * {@code float} or {@code long} otherwise the {@link
#GeneralDirectPosition(int)} constructor would be
+ * invoked with a very different meaning. For example for creating a
one-dimensional coordinate initialized
+ * to the ordinate value 100, use <code>new
GeneralDirectPosition(100<u>.0</u>)</code>, <strong>not</strong>
+ * {@code new GeneralDirectPosition(100)}, because the later would
actually create a position with 100 dimensions.</p>
+ *
* @param ordinates the ordinate values. This array is
<strong>not</strong> cloned.
*/
public GeneralDirectPosition(final double... ordinates) {
@@ -145,7 +152,7 @@ public class GeneralDirectPosition exten
* @throws IllegalArgumentException if the given string can not be parsed.
*
* @see #toString()
- * @see org.apache.sis.measure.CoordinateFormat
+ * @see CoordinateFormat
*/
public GeneralDirectPosition(final CharSequence wkt) throws
IllegalArgumentException {
if ((ordinates = parse(wkt)) == null) {
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/package-info.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/package-info.java?rev=1781298&r1=1781297&r2=1781298&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/package-info.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/geometry/package-info.java
[UTF-8] Wed Feb 1 19:15:46 2017
@@ -81,7 +81,7 @@
* than an inclusion area.</li>
* </ul>
*
- * @author Martin Desruisseaux (IRD, Geomatys)
+ * @author Martin Desruisseaux (IRD, Geomatys)
* @since 0.3
* @version 0.8
* @module
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java?rev=1781298&r1=1781297&r2=1781298&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
[UTF-8] Wed Feb 1 19:15:46 2017
@@ -960,9 +960,11 @@ check: while (lower != 0 || upper != di
crs = components.get(i);
dimension = crs.getCoordinateSystem().getDimension();
if (lower < dimension) {
- // The requested dimensions may intersect the
dimension of this CRS.
- // The outer loop will perform the verification, and
eventually go
- // down again in the tree of sub-components.
+ /*
+ * The requested dimensions may intersect the
dimension of this CRS.
+ * The outer loop will perform the verification, and
eventually go
+ * down again in the tree of sub-components.
+ */
continue check;
}
lower -= dimension;
Added:
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/CoordinateFormatTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/CoordinateFormatTest.java?rev=1781298&view=auto
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/CoordinateFormatTest.java
(added)
+++
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/CoordinateFormatTest.java
[UTF-8] Wed Feb 1 19:15:46 2017
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.geometry;
+
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+import java.text.ParsePosition;
+import java.text.ParseException;
+import org.apache.sis.measure.Angle;
+import org.apache.sis.referencing.crs.HardCodedCRS;
+import org.apache.sis.test.mock.VerticalCRSMock;
+import org.apache.sis.test.TestCase;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+import org.opengis.geometry.DirectPosition;
+
+
+/**
+ * Tests the {@link CoordinateFormat} class.
+ *
+ * @author Martin Desruisseaux (IRD, Geomatys)
+ * @since 0.8
+ * @version 0.8
+ * @module
+ *
+ * @see org.apache.sis.measure.CoordinateFormatTest
+ */
+public final strictfp class CoordinateFormatTest extends TestCase {
+ /**
+ * Tests formatting a coordinate in unknown CRS.
+ * The ordinate values are expected to be formatted as ordinary numbers.
+ */
+ @Test
+ public void testFormatUnknownCRS() {
+ final CoordinateFormat format = new CoordinateFormat(null, null);
+ GeneralDirectPosition position = new GeneralDirectPosition(23.78,
-12.74, 127.9, 3.25);
+ assertEquals("23.78 -12.74 127.9 3.25", format.format(position));
+ /*
+ * Try another point having a different number of position
+ * for verifying that no cached values are causing problem.
+ */
+ position = new GeneralDirectPosition(4.64, 10.25, -3.12);
+ assertEquals("4.64 10.25 -3.12", format.format(position));
+ /*
+ * Try again with a different separator.
+ */
+ format.setSeparator("; ");
+ assertEquals("4.64; 10.25; -3.12", format.format(position));
+ }
+
+ /**
+ * Tests formatting a single vertical coordinate.
+ */
+ @Test
+ public void testFormatVertical() {
+ final CoordinateFormat format = new CoordinateFormat(Locale.US, null);
+ format.setDefaultCRS(VerticalCRSMock.HEIGHT);
+ DirectPosition1D position = new DirectPosition1D(100);
+ assertEquals("100 m", format.format(position));
+
+ position.setCoordinateReferenceSystem(VerticalCRSMock.HEIGHT_ft);
+ assertEquals("100 ft", format.format(position));
+
+ position.setCoordinateReferenceSystem(VerticalCRSMock.DEPTH);
+ assertEquals("100 m", format.format(position));
+ }
+
+ /**
+ * Tests formatting a 4-dimensional geographic coordinate.
+ */
+ @Test
+ public void testFormatGeographic4D() {
+ /*
+ * For a 4-dimensional coordinate with a temporal CRS.
+ * Use a fixed timezone and date pattern for portability.
+ * Epoch is November 17, 1858 at 00:00 UTC.
+ */
+ final CoordinateFormat format = new CoordinateFormat(Locale.FRANCE,
TimeZone.getTimeZone("GMT+01:00"));
+ final String anglePattern = "DD°MM.m′";
+ final String datePattern = "dd-MM-yyyy HH:mm";
+ format.applyPattern(Angle.class, anglePattern);
+ format.applyPattern(Date.class, datePattern);
+ assertEquals("getPattern(Angle)", anglePattern,
format.getPattern(Angle.class));
+ assertEquals("getPattern(Date)", datePattern, format.getPattern(Date
.class));
+ final GeneralDirectPosition position = new
GeneralDirectPosition(23.78, -12.74, 127.9, 54000.25);
+ position.setCoordinateReferenceSystem(HardCodedCRS.GEOID_4D);
+ assertEquals("23°46,8′E 12°44,4′S 127,9 m 22-09-2006 07:00",
format.format(position));
+ /*
+ * Try a null CRS. Should format everything as numbers.
+ */
+ position.setCoordinateReferenceSystem(null);
+ assertEquals("getPattern(Angle)", anglePattern,
format.getPattern(Angle.class));
+ assertEquals("getPattern(Date)", datePattern, format.getPattern(Date
.class));
+ assertEquals("23,78 -12,74 127,9 54 000,25",
format.format(position));
+ /*
+ * Try again with the original CRS, but different separator.
+ */
+ format.setSeparator("; ");
+ position.setCoordinateReferenceSystem(HardCodedCRS.GEOID_4D);
+ assertEquals("getPattern(Angle)", anglePattern,
format.getPattern(Angle.class));
+ assertEquals("getPattern(Date)", datePattern, format.getPattern(Date
.class));
+ assertEquals("23°46,8′E; 12°44,4′S; 127,9 m; 22-09-2006 07:00",
format.format(position));
+ }
+
+ /**
+ * Tests parsing a 4-dimensional geographic coordinate.
+ * This method is the converse of {@link #testFormatGeographic4D()}.
+ *
+ * @throws ParseException if the parsing failed.
+ */
+// @Test
+ public void testParseGeographic4D() throws ParseException {
+ final CoordinateFormat format = new CoordinateFormat(Locale.FRANCE,
TimeZone.getTimeZone("GMT+01:00"));
+ final String anglePattern = "DD°MM.m′";
+ final String datePattern = "dd-MM-yyyy HH:mm";
+ final ParsePosition index = new ParsePosition(0);
+ format.applyPattern(Angle.class, anglePattern);
+ format.applyPattern(Date.class, datePattern);
+ format.setDefaultCRS(HardCodedCRS.GEOID_4D);
+ final DirectPosition pos = format.parse("23°46,8′E 12°44,4′S 127,9 m
22-09-2006 07:00", index);
+ assertArrayEquals(new double[] {23.78, -12.74, 127.90, 54000.25},
pos.getCoordinate(), 0.005);
+ }
+}
Propchange:
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/CoordinateFormatTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/CoordinateFormatTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain;charset=UTF-8
Modified:
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java?rev=1781298&r1=1781297&r2=1781298&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
[UTF-8] Wed Feb 1 19:15:46 2017
@@ -239,6 +239,7 @@ import org.junit.BeforeClass;
org.apache.sis.geometry.Shapes2DTest.class, // Simpler
than EnvelopesTest.
org.apache.sis.geometry.EnvelopesTest.class,
org.apache.sis.internal.referencing.ServicesForMetadataTest.class,
+ org.apache.sis.geometry.CoordinateFormatTest.class,
org.apache.sis.distance.LatLonPointRadiusTest.class, // Pending
refactoring in a geometry package.
Modified:
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/XPaths.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/XPaths.java?rev=1781298&r1=1781297&r2=1781298&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/XPaths.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/XPaths.java
[UTF-8] Wed Feb 1 19:15:46 2017
@@ -71,7 +71,7 @@ scan: while (offset < length) {
case '(': parenthesis++; break;
case ')': parenthesis--; break;
default: {
- if (Character.isWhitespace(c)) break; // Not
supposed to be valid, but be lenient.
+ if (Character.isSpaceChar(c)) break; // Not
supposed to be valid, but be lenient.
if (parenthesis != 0) break;
break scan; //
Non-valid character outside parenthesis.
}
Modified:
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/io/CompoundFormat.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/io/CompoundFormat.java?rev=1781298&r1=1781297&r2=1781298&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/io/CompoundFormat.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/io/CompoundFormat.java
[UTF-8] Wed Feb 1 19:15:46 2017
@@ -24,9 +24,9 @@ import java.util.Date;
import java.io.IOException;
import java.text.Format;
import java.text.DateFormat;
+import java.text.NumberFormat;
import java.text.FieldPosition;
import java.text.ParsePosition;
-import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import javax.measure.Unit;
@@ -40,11 +40,13 @@ import org.apache.sis.measure.UnitFormat
import org.apache.sis.util.Localized;
import org.apache.sis.util.ArraysExt;
import org.apache.sis.util.ArgumentChecks;
-import org.apache.sis.util.collection.BackingStoreException;
import org.apache.sis.internal.util.LocalizedParseException;
import static org.apache.sis.internal.util.StandardDateFormat.UTC;
+// Branch-dependent imports
+import java.io.UncheckedIOException;
+
/**
* Base class of {@link Format} implementations which delegate part of their
work to other
@@ -73,7 +75,7 @@ import static org.apache.sis.internal.ut
* throws a {@code ParseException} on error. This allows both substring
parsing and more accurate exception message
* in case of error.</div>
*
- * @param <T> The base type of objects parsed and formatted by this class.
+ * @param <T> the base type of objects parsed and formatted by this class.
*
* @author Martin Desruisseaux (Geomatys)
* @since 0.3
@@ -171,7 +173,7 @@ public abstract class CompoundFormat<T>
* @return the timezone used for this format, or UTC for unlocalized
format.
*/
public TimeZone getTimeZone() {
- return timezone != null ? (TimeZone) timezone.clone() :
TimeZone.getTimeZone(UTC);
+ return (timezone != null) ? (TimeZone) timezone.clone() :
TimeZone.getTimeZone(UTC);
}
/**
@@ -214,13 +216,14 @@ public abstract class CompoundFormat<T>
* </ul>
*
* <div class="note"><b>Example:</b>
- * If parsing of the {@code "30.0 40,0"} coordinate fails on the coma in
the last number, then the {@code pos}
+ * if parsing of the {@code "30.0 40,0"} coordinate fails on the coma in
the last number, then the {@code pos}
* error index will be set to 5 (the beginning of the {@code "40.0"}
character sequence) while the
* {@link ParseException} error offset will be set to 2 (the coma position
relative the beginning
* of the {@code "40.0"} character sequence).</div>
*
* This error offset policy is a consequence of the compound nature of
{@code CompoundFormat},
- * since the exception may have been produced by a call to {@link
Format#parseObject(String)}.
+ * since the exception may have been produced by a call to {@link
Format#parseObject(String)}
+ * on one of the {@linkplain #getFormat(Class) sub-formats} used by this
{@code CompoundFormat}.
*
* @param text the character sequence for the object to parse.
* @param pos the position where to start the parsing.
@@ -331,16 +334,16 @@ public abstract class CompoundFormat<T>
@Override
public StringBuffer format(final Object object, final StringBuffer
toAppendTo, final FieldPosition pos) {
final Class<? extends T> valueType = getValueType();
- ArgumentChecks.ensureCanCast("tree", valueType, object);
+ ArgumentChecks.ensureCanCast("object", valueType, object);
try {
format(valueType.cast(object), toAppendTo);
} catch (IOException e) {
/*
* Should never happen when writing into a StringBuffer, unless
the user
- * override the format(Object, Appendable) method. We do not
rethrown an
+ * override the format(Object, Appendable) method. We do not
rethrow an
* AssertionError because of this possibility.
*/
- throw new BackingStoreException(e);
+ throw new UncheckedIOException(e);
}
return toAppendTo;
}
Modified:
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/AngleFormat.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/AngleFormat.java?rev=1781298&r1=1781297&r2=1781298&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/AngleFormat.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/AngleFormat.java
[UTF-8] Wed Feb 1 19:15:46 2017
@@ -126,6 +126,7 @@ import static org.apache.sis.math.Decima
* @see Angle
* @see Latitude
* @see Longitude
+ * @see org.apache.sis.geometry.CoordinateFormat
*/
public class AngleFormat extends Format implements Localized {
/**
Modified:
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Latitude.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Latitude.java?rev=1781298&r1=1781297&r2=1781298&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Latitude.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Latitude.java
[UTF-8] Wed Feb 1 19:15:46 2017
@@ -52,6 +52,7 @@ package org.apache.sis.measure;
*
* @see Longitude
* @see AngleFormat
+ * @see org.apache.sis.geometry.CoordinateFormat
*/
public final class Latitude extends Angle {
/**
Modified:
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/LinearConverter.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/LinearConverter.java?rev=1781298&r1=1781297&r2=1781298&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/LinearConverter.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/LinearConverter.java
[UTF-8] Wed Feb 1 19:15:46 2017
@@ -105,6 +105,11 @@ final class LinearConverter extends Abst
private transient volatile BigDecimal scale10, offset10;
/**
+ * The inverse of this unit converter. Computed when first needed.
+ */
+ private transient volatile LinearConverter inverse;
+
+ /**
* Creates a new linear converter for the given scale and offset.
* The complete formula applied is {@code y = (x*scale + offset) /
divisor}.
*/
@@ -253,7 +258,11 @@ final class LinearConverter extends Abst
*/
@Override
public synchronized UnitConverter inverse() {
- return isIdentity() ? this : new LinearConverter(divisor, -offset,
scale);
+ if (inverse == null) {
+ inverse = isIdentity() ? this : new LinearConverter(divisor,
-offset, scale);
+ inverse.inverse = this;
+ }
+ return inverse;
}
/**
Modified:
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Longitude.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Longitude.java?rev=1781298&r1=1781297&r2=1781298&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Longitude.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Longitude.java
[UTF-8] Wed Feb 1 19:15:46 2017
@@ -37,6 +37,7 @@ package org.apache.sis.measure;
*
* @see Latitude
* @see AngleFormat
+ * @see org.apache.sis.geometry.CoordinateFormat
*/
public final class Longitude extends Angle {
/**
Modified:
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitFormat.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitFormat.java?rev=1781298&r1=1781297&r2=1781298&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitFormat.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitFormat.java
[UTF-8] Wed Feb 1 19:15:46 2017
@@ -383,8 +383,8 @@ public class UnitFormat extends Format i
*
* <div class="section">Restriction on character set</div>
* Current implementation accepts only {@linkplain Character#isLetter(int)
letters},
- * {@linkplain Characters#isSubScript(int) subscripts}, {@linkplain
Character#isWhitespace(int) whitespaces}
- * and the degree sign (°),
+ * {@linkplain Characters#isSubScript(int) subscripts}, {@linkplain
Character#isSpaceChar(int) spaces}
+ * (including non-breaking spaces but <strong>not</strong> CR/LF
characters) and the degree sign (°),
* but the set of legal characters may be expanded in future Apache SIS
versions.
* However the following restrictions are likely to remain:
*
@@ -405,7 +405,7 @@ public class UnitFormat extends Format i
ArgumentChecks.ensureNonEmpty("label", label);
for (int i=0; i < label.length();) {
final int c = label.codePointAt(i);
- if (!AbstractUnit.isSymbolChar(c) && !Character.isWhitespace(c)) {
+ if (!AbstractUnit.isSymbolChar(c) && !Character.isSpaceChar(c)) {
throw new
IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentValue_2,
"label", label));
}
i += Character.charCount(c);
@@ -906,7 +906,7 @@ scan: for (int n; i < end; i += n) {
}
continue;
}
- if (Character.isWhitespace(c) || Character.isDigit(c) ||
Characters.isSuperScript(c)) {
+ if (Character.isSpaceChar(c) || Character.isDigit(c) ||
Characters.isSuperScript(c)) {
continue;
}
break scan;
Modified:
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/package-info.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/package-info.java?rev=1781298&r1=1781297&r2=1781298&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/package-info.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/package-info.java
[UTF-8] Wed Feb 1 19:15:46 2017
@@ -56,7 +56,6 @@
* ({@link org.apache.sis.measure.ValueRange})</li>
* <li>Formatters
* ({@link org.apache.sis.measure.AngleFormat},
- * {@link org.apache.sis.measure.CoordinateFormat},
* {@link org.apache.sis.measure.RangeFormat})</li>
* </ul>
*
Modified:
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java?rev=1781298&r1=1781297&r2=1781298&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java
[UTF-8] Wed Feb 1 19:15:46 2017
@@ -414,8 +414,10 @@ public class TreeTableFormat extends Tab
parseValue(node, columns[ci], formats[ci],
text.subSequence(indexOfValue, endOfValue).toString());
}
if (!found) break;
- // The end of this column will be the beginning of the
next column,
- // after skipping the last character of the column
separator.
+ /*
+ * The end of this column will be the beginning of the
next column,
+ * after skipping the last character of the column
separator.
+ */
indexOfValue = matcher.end();
}
} catch (ParseException e) {