sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1775376 - in /sis/branches/JDK8: core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ core/sis-utility/src/main/java/org/apache/sis/util/resources/ storage/sis-storage/src/main/java/org/apache/sis/internal/stora...
Date Wed, 21 Dec 2016 08:22:54 GMT
Author: desruisseaux
Date: Wed Dec 21 08:22:53 2016
New Revision: 1775376

URL: http://svn.apache.org/viewvc?rev=1775376&view=rev
Log:
Consolidation of GPXReader. Include better error messages with line and column numbers if available.

Added:
    sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/MetadataTypes.java
      - copied, changed from r1775375, sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/JAXB.java
Removed:
    sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/JAXB.java
Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/DatumShiftGridLoader.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
    sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/IOUtilities.java
    sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java
    sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java
    sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXReader.java
    sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamReader.java
    sis/branches/JDK8/storage/sis-xmlstore/src/main/resources/META-INF/services/org.apache.sis.internal.jaxb.TypeRegistration

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/DatumShiftGridLoader.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/DatumShiftGridLoader.java?rev=1775376&r1=1775375&r2=1775376&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/DatumShiftGridLoader.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/DatumShiftGridLoader.java [UTF-8] Wed Dec 21 08:22:53 2016
@@ -84,9 +84,9 @@ class DatumShiftGridLoader {
     /**
      * Creates a new loader for the given channel and an existing buffer.
      *
-     * @param  channel Where to read data from.
-     * @param  buffer  The buffer to use.
-     * @param  file    Path to the longitude or latitude difference file. Used only for error reporting.
+     * @param  channel  where to read data from.
+     * @param  buffer   the buffer to use.
+     * @param  file     path to the longitude or latitude difference file. Used only for error reporting.
      */
     DatumShiftGridLoader(final ReadableByteChannel channel, final ByteBuffer buffer, final Path file) throws IOException {
         this.file    = file;
@@ -101,9 +101,9 @@ class DatumShiftGridLoader {
      * It is caller's responsibility to ensure that the given number of bytes is
      * not greater than the {@linkplain ByteBuffer#capacity() buffer capacity}.
      *
-     * @param  n The minimal number of bytes needed in the {@linkplain #buffer}.
-     * @throws EOFException If the channel has reached the end of stream.
-     * @throws IOException If an other kind of error occurred while reading.
+     * @param  n  the minimal number of bytes needed in the {@linkplain #buffer}.
+     * @throws EOFException if the channel has reached the end of stream.
+     * @throws IOException if an other kind of error occurred while reading.
      */
     final void ensureBufferContains(int n) throws IOException {
         assert n >= 0 && n <= buffer.capacity() : n;
@@ -141,9 +141,9 @@ class DatumShiftGridLoader {
     /**
      * Logs a message about a grid which is about to be loaded.
      *
-     * @param caller The provider to logs as the source class.
-     *               The source method will be set to {@code "createMathTransform"}.
-     * @param file   The grid file, as a {@link String} or a {@link Path}.
+     * @param  caller  the provider to logs as the source class.
+     *                 the source method will be set to {@code "createMathTransform"}.
+     * @param  file    the grid file, as a {@link String} or a {@link Path}.
      */
     static void log(final Class<?> caller, final Object file) {
         final LogRecord record = Resources.forLocale(null).getLogRecord(Level.FINE, Resources.Keys.LoadingDatumShiftFile_1, file);
@@ -154,9 +154,9 @@ class DatumShiftGridLoader {
     /**
      * Creates the exception to thrown when the provider failed to load the grid file.
      *
-     * @param format   The format name (e.g. "NTv2" or "NADCON").
-     * @param file     The grid file that the subclass tried to load.
-     * @param cause    The cause of the failure to load the grid file.
+     * @param  format  the format name (e.g. "NTv2" or "NADCON").
+     * @param  file    the grid file that the subclass tried to load.
+     * @param  cause   the cause of the failure to load the grid file.
      */
     static FactoryException canNotLoad(final String format, final Path file, final Exception cause) {
         final String message = Errors.format(Errors.Keys.CanNotParseFile_2, format, file);

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java?rev=1775376&r1=1775375&r2=1775376&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java [UTF-8] Wed Dec 21 08:22:53 2016
@@ -158,7 +158,7 @@ public class FranceGeocentricInterpolati
         PARAMETERS = builder
                 .addIdentifier("9655")
                 .addName("France geocentric interpolation")
-                .createGroup(Molodensky.DIMENSION,       // Not an EPSG parameter.
+                .createGroup(Molodensky.DIMENSION,              // Not an EPSG parameter.
                              Molodensky.SRC_SEMI_MAJOR,
                              Molodensky.SRC_SEMI_MINOR,
                              Molodensky.TGT_SEMI_MAJOR,
@@ -200,7 +200,7 @@ public class FranceGeocentricInterpolati
      * {@code "gr3df97a.txt"} grid, but in fact the Apache SIS implementation should be flexible enough for use
      * with other area.
      *
-     * @param file The grid file.
+     * @param  file  the grid file.
      * @return {@code true} if the given file looks like a fie from the French mapping agency.
      */
     public static boolean isRecognized(final Path file) {
@@ -233,14 +233,14 @@ public class FranceGeocentricInterpolati
      * Creates the source or the target ellipsoid. This is a temporary ellipsoid
      * used only at {@link InterpolatedGeocentricTransform} time, then discarded.
      *
-     * @param values     The parameter group from which to get the axis lengths.
-     * @param semiMajor  The descriptor for locating the semi-major axis parameter.
-     * @param semiMinor  The descriptor for locating the semi-minor axis parameter.
-     * @param candidate  An ellipsoid to return if the axis lengths match the lengths found in the parameters,
-     *                   or {@code null} if none. The intend is to use the pre-defined "GRS 1980" ellipsoid if
-     *                   we can, because that ellipsoid is defined by inverse flattening factor instead than by
-     *                   semi-minor axis length.
-     * @return A temporary ellipsoid encapsulating the axis lengths found in the parameters.
+     * @param  values     the parameter group from which to get the axis lengths.
+     * @param  semiMajor  the descriptor for locating the semi-major axis parameter.
+     * @param  semiMinor  the descriptor for locating the semi-minor axis parameter.
+     * @param  candidate  an ellipsoid to return if the axis lengths match the lengths found in the parameters,
+     *                    or {@code null} if none. The intend is to use the pre-defined "GRS 1980" ellipsoid if
+     *                    we can, because that ellipsoid is defined by inverse flattening factor instead than by
+     *                    semi-minor axis length.
+     * @return a temporary ellipsoid encapsulating the axis lengths found in the parameters.
      */
     private static Ellipsoid createEllipsoid(final Parameters values,
                                              final ParameterDescriptor<Double> semiMajor,
@@ -264,9 +264,9 @@ public class FranceGeocentricInterpolati
      * (which is the direction that use the interpolation grid directly without iteration),
      * then inverts the transform.
      *
-     * @param  factory The factory to use if this constructor needs to create other math transforms.
-     * @param  values The group of parameter values.
-     * @return The created math transform.
+     * @param  factory  the factory to use if this constructor needs to create other math transforms.
+     * @param  values   the group of parameter values.
+     * @return the created math transform.
      * @throws ParameterNotFoundException if a required parameter was not found.
      * @throws FactoryException if an error occurred while loading the grid.
      */
@@ -317,9 +317,9 @@ public class FranceGeocentricInterpolati
      * Returns the grid of the given name. This method returns the cached instance if it still exists,
      * or load the grid otherwise.
      *
-     * @param  file      Name of the datum shift grid file to load.
-     * @param  averages  An "average" value for the offset in each dimension, or {@code null} if unknown.
-     * @param  scale     The factor by which to multiply each compressed value before to add to the average value.
+     * @param  file      name of the datum shift grid file to load.
+     * @param  averages  an "average" value for the offset in each dimension, or {@code null} if unknown.
+     * @param  scale     the factor by which to multiply each compressed value before to add to the average value.
      */
     @SuppressWarnings("null")
     static DatumShiftGridFile<Angle,Length> getOrLoad(final Path file, final double[] averages, final double scale)
@@ -352,8 +352,8 @@ public class FranceGeocentricInterpolati
     /**
      * Unconditionally loads the grid for the given file without in-memory compression.
      *
-     * @param  in Reader of the RGF93 datum shift file.
-     * @param  file Path to the file being read, used only for error reporting.
+     * @param  in    reader of the RGF93 datum shift file.
+     * @param  file  path to the file being read, used only for error reporting.
      * @throws IOException if an I/O error occurred.
      * @throws NumberFormatException if a number can not be parsed.
      * @throws NoSuchElementException if a data line is missing a value.
@@ -460,11 +460,11 @@ public class FranceGeocentricInterpolati
         final float[] tZ = grid.offsets[2];
         do {
             final StringTokenizer t = new StringTokenizer(line.trim());
-            t.nextToken();                                                // Ignored
-            final double x = Double.parseDouble(t.nextToken());           // Longitude in degrees
-            final double y = Double.parseDouble(t.nextToken());           // Latitude in degrees
-            final int    i = Math.toIntExact(Math.round((x - x0) / Δx));  // Column index
-            final int    j = Math.toIntExact(Math.round((y - y0) / Δy));  // Row index
+            t.nextToken();                                                      // Ignored
+            final double x = Double.parseDouble(t.nextToken());                 // Longitude in degrees
+            final double y = Double.parseDouble(t.nextToken());                 // Latitude in degrees
+            final int    i = Math.toIntExact(Math.round((x - x0) / Δx));        // Column index
+            final int    j = Math.toIntExact(Math.round((y - y0) / Δy));        // Row index
             if (i < 0 || i >= nx) {
                 throw new FactoryException(Errors.format(Errors.Keys.ValueOutOfRange_4, "x", x, x0, xf));
             }
@@ -475,12 +475,12 @@ public class FranceGeocentricInterpolati
             if (!Double.isNaN(tX[p]) || !Double.isNaN(tY[p]) || !Double.isNaN(tZ[p])) {
                 throw new FactoryException(Errors.format(Errors.Keys.ValueAlreadyDefined_1, x + ", " + y));
             }
-            tX[p] = -parseFloat(t.nextToken());  // See javadoc for the reason why we reverse the sign.
+            tX[p] = -parseFloat(t.nextToken());     // See javadoc for the reason why we reverse the sign.
             tY[p] = -parseFloat(t.nextToken());
             tZ[p] = -parseFloat(t.nextToken());
             final double accuracy = ACCURACY[Math.min(ACCURACY.length-1,
                     Math.max(0, Integer.parseInt(t.nextToken()) - 1))];
-            if (!(accuracy >= grid.accuracy)) {   // Use '!' for replacing the initial NaN.
+            if (!(accuracy >= grid.accuracy)) {     // Use '!' for replacing the initial NaN.
                 grid.accuracy = accuracy;
             }
         } while ((line = in.readLine()) != null);

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1775376&r1=1775375&r2=1775376&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] Wed Dec 21 08:22:53 2016
@@ -116,6 +116,16 @@ public final class Errors extends Indexe
         public static final short CanNotParseFile_2 = 9;
 
         /**
+         * Can not parse line {2} of “{1}” as part of a file in the {0} format.
+         */
+        public static final short CanNotParseFile_3 = 168;
+
+        /**
+         * Can not parse line {2} (after column {3}) of “{1}” as part of a file in the {0} format.
+         */
+        public static final short CanNotParseFile_4 = 169;
+
+        /**
          * Can not read property “{1}” in file “{0}”.
          */
         public static final short CanNotReadPropertyInFile_2 = 10;

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1775376&r1=1775375&r2=1775376&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] Wed Dec 21 08:22:53 2016
@@ -34,6 +34,8 @@ CanNotConvertValue_2              = Can
 CanNotCompute_1                   = Can not compute \u201c{0}\u201d.
 CanNotOpen_1                      = Can not open \u201c{0}\u201d.
 CanNotParseFile_2                 = Can not parse \u201c{1}\u201d as a file in the {0} format.
+CanNotParseFile_3                 = Can not parse line {2} of \u201c{1}\u201d as part of a file in the {0} format.
+CanNotParseFile_4                 = Can not parse line {2} (after column {3}) of \u201c{1}\u201d as part of a file in the {0} format.
 CanNotRead_1                      = Can not read \u201c{0}\u201d.
 CanNotReadPropertyInFile_2        = Can not read property \u201c{1}\u201d in file \u201c{0}\u201d.
 CanNotRepresentInFormat_2         = Can not represent \u201c{1}\u201d in a strictly standard-compliant {0} format.

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1775376&r1=1775375&r2=1775376&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] Wed Dec 21 08:22:53 2016
@@ -31,6 +31,8 @@ CanNotConvertValue_2              = La v
 CanNotCompute_1                   = Ne peut pas calculer \u00ab\u202f{0}\u202f\u00bb.
 CanNotOpen_1                      = Ne peut pas ouvrir \u00ab\u202f{0}\u202f\u00bb.
 CanNotParseFile_2                 = Ne peut pas lire \u00ab\u202f{1}\u202f\u00bb comme un fichier au format {0}.
+CanNotParseFile_3                 = Ne peut pas lire la ligne {2} de \u00ab\u202f{1}\u202f\u00bb comme une partie d\u2019un fichier au format {0}.
+CanNotParseFile_4                 = Ne peut pas lire la ligne {2} (apr\u00e8s la colonne {3}) de \u00ab\u202f{1}\u202f\u00bb comme une partie d\u2019un fichier au format {0}.
 CanNotRead_1                      = Ne peut pas lire \u00ab\u202f{0}\u202f\u00bb.
 CanNotReadPropertyInFile_2        = Ne peut pas lire la propri\u00e9t\u00e9 \u00ab\u202f{1}\u202f\u00bb dans le fichier \u00ab\u202f{0}\u202f\u00bb.
 CanNotRepresentInFormat_2         = Ne peut pas repr\u00e9senter \u00ab\u202f{1}\u202f\u00bb dans un format {0} strictement conforme.

Modified: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/IOUtilities.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/IOUtilities.java?rev=1775376&r1=1775375&r2=1775376&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/IOUtilities.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/IOUtilities.java [UTF-8] Wed Dec 21 08:22:53 2016
@@ -26,6 +26,8 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.InputStream;
 import java.io.IOException;
+import java.io.LineNumberReader;
+import java.io.Reader;
 import java.net.URI;
 import java.net.URL;
 import java.net.URLDecoder;
@@ -61,7 +63,7 @@ import org.apache.sis.internal.system.Mo
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Johann Sorel (Geomatys)
  * @since   0.3
- * @version 0.4
+ * @version 0.8
  * @module
  */
 public final class IOUtilities extends Static {
@@ -553,4 +555,53 @@ public final class IOUtilities extends S
     private static void recoverableException(final Exception warning) {
         Logging.recoverableException(Logging.getLogger(Modules.STORAGE), IOUtilities.class, "open", warning);
     }
+
+    /**
+     * Returns an error message a file that can not be parsed because of an error at the given location.
+     *
+     * @param  errors    the resource bundle to use for creating the message.
+     * @param  format    abbreviation of the file format (e.g. "CSV", "GML", "WKT", <i>etc</i>).
+     * @param  filename  name of the file being parsed.
+     * @param  line      1-based line number where the error occurred, or 0 if unknown.
+     * @param  column    1-based column number where the error occurred, or 0 if unknown.
+     * @return a localized error message for a file that can not be parsed.
+     *
+     * @since 0.8
+     */
+    @SuppressWarnings("fallthrough")
+    public static String canNotParseFile(final Errors errors, final String format,
+            final String filename, final int line, final int column)
+    {
+        final Object[] params = new Object[(line == 0) ? 2 : (column == 0) ? 3 : 4];
+        switch (params.length) {
+            default: // Fallthrough everywhere
+            case 4:  params[3] = column;
+            case 3:  params[2] = line;
+            case 2:  params[1] = filename;
+            case 1:  params[0] = format;
+            case 0:  break;
+        }
+        return errors.getString((line   == 0) ? Errors.Keys.CanNotParseFile_2 :
+                                (column == 0) ? Errors.Keys.CanNotParseFile_3 :
+                                                Errors.Keys.CanNotParseFile_4, params);
+    }
+
+    /**
+     * Returns an error message a file that can not be parsed because of an error at the current line.
+     * This method uses the {@link LineNumberReader#getLineNumber()} value if the given {@code input}
+     * is an instance of {@link LineNumberReader}.
+     *
+     * @param  errors    the resource bundle to use for creating the message.
+     * @param  format    abbreviation of the file format (e.g. "CSV", "GML", "WKT", <i>etc</i>).
+     * @param  filename  name of the file being parsed.
+     * @param  input     the reader, preferably as an instance of {@link LineNumberReader}.
+     * @return a localized error message for a file that can not be parsed.
+     *
+     * @since 0.8
+     */
+    @SuppressWarnings("fallthrough")
+    public static String canNotParseFile(final Errors errors, final String format, final String filename, final Reader input) {
+        return canNotParseFile(errors, format, filename,
+                (input instanceof LineNumberReader) ? ((LineNumberReader) input).getLineNumber() : 0, 0);
+    }
 }

Modified: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java?rev=1775376&r1=1775375&r2=1775376&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java [UTF-8] Wed Dec 21 08:22:53 2016
@@ -44,12 +44,14 @@ import org.apache.sis.referencing.CRS;
 import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.internal.referencing.GeodeticObjectBuilder;
 import org.apache.sis.internal.storage.MetadataBuilder;
+import org.apache.sis.internal.storage.IOUtilities;
 import org.apache.sis.geometry.GeneralEnvelope;
 import org.apache.sis.metadata.iso.DefaultMetadata;
 import org.apache.sis.metadata.sql.MetadataStoreException;
 import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.DataStoreContentException;
+import org.apache.sis.storage.DataStoreReferencingException;
 import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.setup.OptionKey;
 import org.apache.sis.util.ArraysExt;
@@ -57,7 +59,6 @@ import org.apache.sis.util.CharSequences
 import org.apache.sis.util.ObjectConverter;
 import org.apache.sis.util.ObjectConverters;
 import org.apache.sis.util.resources.Errors;
-import org.apache.sis.util.resources.IndexedResourceBundle;
 import org.apache.sis.util.collection.BackingStoreException;
 import org.apache.sis.measure.Units;
 
@@ -238,8 +239,12 @@ public final class Store extends DataSto
                 source.mark(1024);
             }
             source.reset();
-        } catch (IOException | FactoryException | IllegalArgumentException | DateTimeException e) {
-            throw new DataStoreException(errors().getString(Errors.Keys.CanNotParseFile_2, "CSV", filename), e);
+        } catch (IOException e) {
+            throw new DataStoreException(canNotParseFile(), e);
+        } catch (FactoryException e) {
+            throw new DataStoreReferencingException(canNotParseFile(), e);
+        } catch (IllegalArgumentException | DateTimeException e) {
+            throw new DataStoreContentException(canNotParseFile(), e);
         }
         this.encoding    = connector.getOption(OptionKey.ENCODING);
         this.envelope    = envelope;
@@ -497,7 +502,7 @@ public final class Store extends DataSto
             try {
                 builder.addExtent(envelope);
             } catch (TransformException e) {
-                throw new DataStoreContentException(errors().getString(Errors.Keys.CanNotParseFile_2, "CSV", filename), e);
+                throw new DataStoreReferencingException(canNotParseFile(), e);
             } catch (UnsupportedOperationException e) {
                 // Failed to set the temporal components if the sis-temporal module was
                 // not on the classpath, but the other dimensions still have been set.
@@ -642,7 +647,7 @@ public final class Store extends DataSto
             try {
                 return read(action, false);
             } catch (IOException | IllegalArgumentException | DateTimeException e) {
-                throw new BackingStoreException(canNotParse(), e);
+                throw new BackingStoreException(canNotParseFile(), e);
             }
         }
 
@@ -654,18 +659,11 @@ public final class Store extends DataSto
             try {
                 read(action, true);
             } catch (IOException | IllegalArgumentException | DateTimeException e) {
-                throw new BackingStoreException(canNotParse(), e);
+                throw new BackingStoreException(canNotParseFile(), e);
             }
         }
 
         /**
-         * Returns the error message for a file that can not be parsed.
-         */
-        private String canNotParse() {
-            return errors().getString(Errors.Keys.CanNotParseFile_2, "CSV", filename);
-        }
-
-        /**
          * Current implementation can not split this iterator.
          */
         @Override
@@ -765,9 +763,17 @@ public final class Store extends DataSto
     }
 
     /**
+     * Returns the error message for a file that can not be parsed.
+     * The error message will contain the line number if available.
+     */
+    final String canNotParseFile() {
+        return IOUtilities.canNotParseFile(errors(), "CSV", filename, source);
+    }
+
+    /**
      * Returns the resources to use for producing error messages.
      */
-    private IndexedResourceBundle errors() {
+    private Errors errors() {
         return Errors.getResources(getLocale());
     }
 

Modified: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java?rev=1775376&r1=1775375&r2=1775376&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java [UTF-8] Wed Dec 21 08:22:53 2016
@@ -34,6 +34,7 @@ import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.DataStoreContentException;
+import org.apache.sis.internal.storage.IOUtilities;
 import org.apache.sis.metadata.iso.DefaultMetadata;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.CharSequences;
@@ -136,12 +137,22 @@ final class Store extends DataStore {
                     listeners.warning(record);
                 }
             } while (pos.getIndex() < wkt.length());
-        } catch (IOException | ParseException e) {
-            throw new DataStoreException(Errors.format(Errors.Keys.CanNotParseFile_2, "WKT", name), e);
+        } catch (ParseException e) {
+            throw new DataStoreContentException(canNotParseFile(in), e);
+        } catch (IOException e) {
+            throw new DataStoreException(canNotParseFile(in), e);
         }
     }
 
     /**
+     * Returns the error message for a file that can not be parsed.
+     * The error message will contain the line number if available.
+     */
+    private String canNotParseFile(final Reader in) {
+        return IOUtilities.canNotParseFile(Errors.getResources(getLocale()), "WKT", name, in);
+    }
+
+    /**
      * Returns the metadata associated to the parsed objects, or {@code null} if none.
      * The current implementation retains only instances of {@link ReferenceSystem}
      * and ignore other cases.

Modified: sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXReader.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXReader.java?rev=1775376&r1=1775375&r2=1775376&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXReader.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXReader.java [UTF-8] Wed Dec 21 08:22:53 2016
@@ -64,6 +64,8 @@ import org.opengis.feature.Feature;
 public class GPXReader extends StaxStreamReader {
     /**
      * The {@link org.opengis.feature.FeatureType} for routes, tracks, way points, <i>etc</i>.
+     * Currently always {@link Types#DEFAULT}, but we use a field for keeping {@code GPXReader}
+     * ready to handle profiles or extensions.
      */
     private final Types types;
 
@@ -120,10 +122,21 @@ public class GPXReader extends StaxStrea
     }
 
     /**
+     * Returns {@code true} if the current element can be considered as in the GPX namespace.
+     * Strictly speaking we should require the namespace URI to be exactly {@link #namespace},
+     * but this method is a little bit more lenient.
+     */
+    private boolean isGPX(final XMLStreamReader reader) {
+        final String ns = reader.getNamespaceURI();
+        return Objects.equals(namespace, ns) || isGPX(ns);
+    }
+
+    /**
      * Returns {@code true} if the current position of the given reader is the closing {@code </gpx>} tag.
-     * The reader event should be {@link #END_DOCUMENT} before to invoke this method.
+     * The reader event should be {@link #END_ELEMENT} before to invoke this method.
      */
     private boolean isEndGPX(final XMLStreamReader reader) {
+        assert reader.isEndElement();
         return Tags.GPX.equals(reader.getLocalName()) && Objects.equals(namespace, reader.getNamespaceURI());
     }
 
@@ -161,8 +174,9 @@ public class GPXReader extends StaxStrea
         Version version = null;
         if (ver != null) {
             version = new Version(ver);
-            final int c = version.compareTo(GPXStore.V1_0, 2);
-            if (c < 0 || version.compareTo(GPXStore.V1_1, 2) > 0) {
+            if (version.compareTo(GPXStore.V1_0, 2) < 0 ||
+                version.compareTo(GPXStore.V1_1, 2) > 0)
+            {
                 throw new DataStoreContentException(errors().getString(
                         Errors.Keys.UnsupportedFormatVersion_2, owner.getFormatName(), version));
             }
@@ -188,8 +202,9 @@ parse:  while (reader.hasNext()) {
                     /*
                      * GPX 1.0 and 1.1 metadata should not be mixed. However the following code will work even
                      * if GPX 1.0 metadata like <name> or <author> appear after the GPX 1.1 <metadata> element.
+                     * If both kind of metadata are specified, the latest value overwrites the values before it.
                      */
-                    if (isGPX(reader.getNamespaceURI())) {
+                    if (isGPX(reader)) {
                         final String name = reader.getLocalName();
                         if (readMetadata) {
                             switch (name) {
@@ -228,9 +243,8 @@ parse:  while (reader.hasNext()) {
                 }
                 case END_ELEMENT: {
                     /*
-                     * Reminder: END_ELEMENT events are already handled by XMLStreamReader.getElementText(),
-                     * Unmarshaller.unmarshal(XMLStreamReader, …) and our parseBound(…) methods. There is only
-                     * the enclosing <gpx> tag to check.
+                     * Reminder: END_ELEMENT events are skipped by getElementText(), getElementAsFoo()
+                     * and unmarshal(…) methods. There is only the enclosing <gpx> tag to check here.
                      */
                     if (isEndGPX(reader)) {
                         break parse;
@@ -245,6 +259,9 @@ parse:  while (reader.hasNext()) {
     /**
      * Returns the {@link #metadata} field, creating it if needed.
      * This is a convenience method for GPX 1.0 metadata parsing.
+     * This is not for returning the metadata result after parsing.
+     *
+     * @see #getMetadata()
      */
     private Metadata metadata() {
         if (metadata == null) {
@@ -283,6 +300,8 @@ parse:  while (reader.hasNext()) {
 
     /**
      * Adds the given element to the given list if non null, or do nothing otherwise.
+     * This is a convenience method for storing {@code <link>} elements in way points,
+     * routes or tracks (not in metadata).
      *
      * @param  links    the list where to add the element, or {@code null} if not yet created.
      * @param  element  the element to add, or {@code null} if none.
@@ -291,7 +310,7 @@ parse:  while (reader.hasNext()) {
     private static List<Link> addIfNonNull(List<Link> links, final Link element) {
         if (element != null) {
             if (links == null) {
-                links = new ArrayList<>(3);
+                links = new ArrayList<>(3);         // Small capacity since there is usually only one link.
             }
             links.add(element);
         }
@@ -326,7 +345,7 @@ parse:  while (reader.hasNext()) {
         try {
             return parse(action, false);
         } catch (Exception e) {                 // Many possible exceptions including unchecked ones.
-            throw new BackingStoreException(canNotReadFile(), e);
+            throw new BackingStoreException(canNotParseFile(), e);
         }
     }
 
@@ -343,7 +362,7 @@ parse:  while (reader.hasNext()) {
         try {
             parse(action, true);
         } catch (Exception e) {                 // Many possible exceptions including unchecked ones.
-            throw new BackingStoreException(canNotReadFile(), e);
+            throw new BackingStoreException(canNotParseFile(), e);
         }
     }
 
@@ -363,9 +382,7 @@ parse:  while (reader.hasNext()) {
      * @throws EOFException if the file seems to be truncated.
      */
     @SuppressWarnings("fallthrough")
-    private boolean parse(final Consumer<? super Feature> action, final boolean all)
-            throws DataStoreException, XMLStreamException, JAXBException, URISyntaxException, EOFException
-    {
+    private boolean parse(final Consumer<? super Feature> action, final boolean all) throws Exception {
         final XMLStreamReader reader = getReader();
         for (int type = reader.getEventType(); ; type = reader.next()) {
             /*
@@ -375,7 +392,7 @@ parse:  while (reader.hasNext()) {
             switch (type) {
                 case START_ELEMENT: {
                     final Feature f;
-                    switch (isGPX(reader.getNamespaceURI()) ? reader.getLocalName() : "") {
+                    switch (isGPX(reader) ? reader.getLocalName() : "") {
                         case Tags.WAY_POINT: f = parseWayPoint(reader, ++wayPointId); break;
                         case Tags.ROUTES:    f = parseRoute   (reader, ++routeId);    break;
                         case Tags.TRACKS:    f = parseTrack   (reader, ++trackId);    break;
@@ -396,20 +413,21 @@ parse:  while (reader.hasNext()) {
     /**
      * Parses a {@code <wpt>}, {@code <rtept>} or {@code <trkpt>} element.
      * The STAX reader {@linkplain XMLStreamReader#getEventType() current event} must be a {@link #START_ELEMENT}.
+     *
+     * @throws Exception see the list of exceptions documented in {@link #parse(Consumer, boolean)}.
      */
-    private Feature parseWayPoint(final XMLStreamReader reader, final int index)
-            throws DataStoreException, XMLStreamException, JAXBException, URISyntaxException, EOFException
-    {
+    private Feature parseWayPoint(final XMLStreamReader reader, final int index) throws Exception {
+        assert reader.isStartElement();
         /*
-         * Way points might be located in different tag elements: <wpt>, <rtept> and <trkpt>.
-         * We have to keep the current tag name in order to know when we reached the end.
+         * Way points might be located in different elements: <wpt>, <rtept> and <trkpt>.
+         * We have to keep the current tag name in order to know when we reach the end.
          * We are lenient about namespace since we do not allow nested way points.
          */
         final String tagName = reader.getLocalName();
         final String lat = reader.getAttributeValue(null, Attributes.LATITUDE);
         final String lon = reader.getAttributeValue(null, Attributes.LONGITUDE);
         if (lat == null || lon == null) {
-            throw new XMLStreamException(errors().getString(Errors.Keys.MandatoryAttribute_2,
+            throw new DataStoreContentException(errors().getString(Errors.Keys.MandatoryAttribute_2,
                     (lat == null) ? Attributes.LATITUDE : Attributes.LONGITUDE, tagName));
         }
         final Feature feature = types.wayPoint.newInstance();
@@ -425,7 +443,7 @@ parse:  while (reader.hasNext()) {
                 case START_ELEMENT: {
                     final Object value;
                     final String name = reader.getLocalName();
-                    switch (isGPX(reader.getNamespaceURI()) ? name : "") {
+                    switch (isGPX(reader) ? name : "") {
                         case Tags.NAME:             // Fallthrough to getElementText()
                         case Tags.COMMENT:          // ︙
                         case Tags.DESCRIPTION:      // ︙
@@ -456,7 +474,7 @@ parse:  while (reader.hasNext()) {
                     break;
                 }
                 case END_ELEMENT: {
-                    if (tagName.equals(reader.getLocalName()) && isGPX(reader.getNamespaceURI())) {
+                    if (tagName.equals(reader.getLocalName()) && isGPX(reader)) {
                         if (links != null) feature.setPropertyValue(Tags.LINK, links);
                         return feature;
                     }
@@ -472,10 +490,11 @@ parse:  while (reader.hasNext()) {
     /**
      * Parses a {@code <rte>} element. The STAX reader {@linkplain XMLStreamReader#getEventType() current event}
      * must be a {@link #START_ELEMENT} and the name of that start element must be {@link Tags#ROUTES}.
+     *
+     * @throws Exception see the list of exceptions documented in {@link #parse(Consumer, boolean)}.
      */
-    private Feature parseRoute(final XMLStreamReader reader, final int index)
-            throws DataStoreException, XMLStreamException, JAXBException, URISyntaxException, EOFException
-    {
+    private Feature parseRoute(final XMLStreamReader reader, final int index) throws Exception {
+        assert reader.isStartElement() && Tags.ROUTES.equals(reader.getLocalName());
         final Feature feature = types.route.newInstance();
         feature.setPropertyValue("@identifier", index);
         List<Feature> wayPoints = null;
@@ -489,7 +508,7 @@ parse:  while (reader.hasNext()) {
                 case START_ELEMENT: {
                     final Object value;
                     final String name = reader.getLocalName();
-                    switch (isGPX(reader.getNamespaceURI()) ? name : "") {
+                    switch (isGPX(reader) ? name : "") {
                         default: continue;
                         case Tags.NAME:        // Fallthrough to getElementText()
                         case Tags.COMMENT:     // ︙
@@ -510,7 +529,7 @@ parse:  while (reader.hasNext()) {
                     break;
                 }
                 case END_ELEMENT: {
-                    if (Tags.ROUTES.equals(reader.getLocalName()) && isGPX(reader.getNamespaceURI())) {
+                    if (Tags.ROUTES.equals(reader.getLocalName()) && isGPX(reader)) {
                         if (wayPoints != null) feature.setPropertyValue(Tags.ROUTE_POINTS, wayPoints);
                         if (links     != null) feature.setPropertyValue(Tags.LINK, links);
                         return feature;
@@ -527,10 +546,11 @@ parse:  while (reader.hasNext()) {
     /**
      * Parses a {@code <trkseg>} element. The STAX reader {@linkplain XMLStreamReader#getEventType() current event}
      * must be a {@link #START_ELEMENT} and the name of that start element must be {@link Tags#TRACK_SEGMENTS}.
+     *
+     * @throws Exception see the list of exceptions documented in {@link #parse(Consumer, boolean)}.
      */
-    private Feature parseTrackSegment(final XMLStreamReader reader, final int index)
-            throws DataStoreException, XMLStreamException, JAXBException, URISyntaxException, EOFException
-    {
+    private Feature parseTrackSegment(final XMLStreamReader reader, final int index) throws Exception {
+        assert reader.isStartElement() && Tags.TRACK_SEGMENTS.equals(reader.getLocalName());
         final Feature feature = types.trackSegment.newInstance();
         feature.setPropertyValue("@identifier", index);
         List<Feature> wayPoints = null;
@@ -542,7 +562,7 @@ parse:  while (reader.hasNext()) {
             switch (reader.next()) {
                 case START_ELEMENT: {
                     final String name = reader.getLocalName();
-                    switch (isGPX(reader.getNamespaceURI()) ? name : "") {
+                    switch (isGPX(reader) ? name : "") {
                         default: continue;
                         case Tags.TRACK_POINTS: {
                             if (wayPoints == null) wayPoints = new ArrayList<>(8);
@@ -553,7 +573,7 @@ parse:  while (reader.hasNext()) {
                     }
                 }
                 case END_ELEMENT: {
-                    if (Tags.TRACK_SEGMENTS.equals(reader.getLocalName()) && isGPX(reader.getNamespaceURI())) {
+                    if (Tags.TRACK_SEGMENTS.equals(reader.getLocalName()) && isGPX(reader)) {
                         if (wayPoints != null) feature.setPropertyValue(Tags.TRACK_POINTS, wayPoints);
                         return feature;
                     }
@@ -569,10 +589,11 @@ parse:  while (reader.hasNext()) {
     /**
      * Parses a {@code <trk>} element. The STAX reader {@linkplain XMLStreamReader#getEventType() current event}
      * must be a {@link #START_ELEMENT} and the name of that start element must be {@link Tags#TRACKS}.
+     *
+     * @throws Exception see the list of exceptions documented in {@link #parse(Consumer, boolean)}.
      */
-    private Feature parseTrack(final XMLStreamReader reader, final int index)
-            throws DataStoreException, XMLStreamException, JAXBException, URISyntaxException, EOFException
-    {
+    private Feature parseTrack(final XMLStreamReader reader, final int index) throws Exception {
+        assert reader.isStartElement() && Tags.TRACKS.equals(reader.getLocalName());
         final Feature feature = types.track.newInstance();
         feature.setPropertyValue("@identifier", index);
         List<Feature> segments = null;
@@ -586,7 +607,7 @@ parse:  while (reader.hasNext()) {
                 case START_ELEMENT: {
                     final Object value;
                     final String name = reader.getLocalName();
-                    switch (isGPX(reader.getNamespaceURI()) ? name : "") {
+                    switch (isGPX(reader) ? name : "") {
                         default: continue;
                         case Tags.NAME:         // Fallthrough to getElementText()
                         case Tags.COMMENT:      // ︙
@@ -607,7 +628,7 @@ parse:  while (reader.hasNext()) {
                     break;
                 }
                 case END_ELEMENT: {
-                    if (Tags.TRACKS.equalsIgnoreCase(reader.getLocalName()) && isGPX(reader.getNamespaceURI())) {
+                    if (Tags.TRACKS.equals(reader.getLocalName()) && isGPX(reader)) {
                         if (segments != null) feature.setPropertyValue(Tags.TRACK_SEGMENTS, segments);
                         if (links    != null) feature.setPropertyValue(Tags.LINK, links);
                         return feature;

Copied: sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/MetadataTypes.java (from r1775375, sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/JAXB.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/MetadataTypes.java?p2=sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/MetadataTypes.java&p1=sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/JAXB.java&r1=1775375&r2=1775376&rev=1775376&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/JAXB.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/MetadataTypes.java [UTF-8] Wed Dec 21 08:22:53 2016
@@ -29,7 +29,7 @@ import org.apache.sis.internal.jaxb.Type
  * @version 0.8
  * @module
  */
-public final class JAXB extends TypeRegistration {
+public final class MetadataTypes extends TypeRegistration {
     /**
      * Adds to the given collection the metadata types that should be given to the initial JAXB context.
      */

Modified: sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamReader.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamReader.java?rev=1775376&r1=1775375&r2=1775376&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamReader.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamReader.java [UTF-8] Wed Dec 21 08:22:53 2016
@@ -28,6 +28,7 @@ import java.io.IOException;
 import java.io.EOFException;
 import java.net.URISyntaxException;
 import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
 import javax.xml.stream.XMLEventReader;
 import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLStreamConstants;
@@ -45,6 +46,7 @@ import org.apache.sis.xml.XML;
 import org.apache.sis.internal.jaxb.Context;
 import org.apache.sis.internal.util.Numerics;
 import org.apache.sis.internal.util.StandardDateFormat;
+import org.apache.sis.internal.storage.IOUtilities;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.storage.DataStoreContentException;
@@ -224,7 +226,9 @@ public abstract class StaxStreamReader e
      * Returns the XML stream reader if it is not closed.
      *
      * @return the XML stream reader (never null).
-     * @throws XMLStreamException if this XML reader has been closed.
+     * @throws XMLStreamException if this XML reader has been closed. Note that a closed reader does not mean that
+     *         the whole {@link StaxDataStore} has been closed since the same datastore may produce many iterators,
+     *         which is why the exception type is not {@link org.apache.sis.storage.DataStoreContentException}.
      */
     protected final XMLStreamReader getReader() throws XMLStreamException {
         if (reader != null) {
@@ -485,11 +489,21 @@ public abstract class StaxStreamReader e
     /**
      * Returns an error message for {@link BackingStoreException}.
      * This a convenience method for {@link #tryAdvance(Consumer)} implementations.
+     * The error message will contain the current line and column number if available.
      *
      * @return a localized error message for a file that can not be parsed.
      */
-    protected final String canNotReadFile() {
-        return errors().getString(Errors.Keys.CanNotParseFile_2, owner.getFormatName(), inputName);
+    protected final String canNotParseFile() {
+        final int line, column;
+        if (reader != null) {
+            final Location location = reader.getLocation();
+            line   = location.getLineNumber()   + 1;
+            column = location.getColumnNumber() + 1;
+        } else {
+            line   = 0;
+            column = 0;
+        }
+        return IOUtilities.canNotParseFile(errors(), owner.getFormatName(), inputName, line, column);
     }
 
     /**

Modified: sis/branches/JDK8/storage/sis-xmlstore/src/main/resources/META-INF/services/org.apache.sis.internal.jaxb.TypeRegistration
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/main/resources/META-INF/services/org.apache.sis.internal.jaxb.TypeRegistration?rev=1775376&r1=1775375&r2=1775376&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-xmlstore/src/main/resources/META-INF/services/org.apache.sis.internal.jaxb.TypeRegistration [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-xmlstore/src/main/resources/META-INF/services/org.apache.sis.internal.jaxb.TypeRegistration [UTF-8] Wed Dec 21 08:22:53 2016
@@ -1 +1 @@
-org.apache.sis.internal.gpx.JAXB
+org.apache.sis.internal.gpx.MetadataTypes



Mime
View raw message