sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1803070 [16/20] - in /sis/branches/JDK9: ./ application/sis-console/src/main/java/org/apache/sis/console/ core/sis-build-helper/ core/sis-build-helper/src/main/java/org/apache/sis/internal/book/ core/sis-build-helper/src/main/java/org/apac...
Date Wed, 26 Jul 2017 16:14:14 GMT
Modified: sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/package-info.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/package-info.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/package-info.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -23,7 +23,7 @@
  *   <li><a href="http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf">TIFF specification</a>: baseline</li>
  *   <li><a href="http://partners.adobe.com/public/developer/en/tiff/TIFFphotoshop.pdf">TIFF Tecnical Notes</a>: add new compressions</li>
  *   <li><a href="http://www.awaresystems.be/imaging/tiff/tifftags.html">TIFF Tag Reference</a></li>
- *   <li><a href="http://www.remotesensing.org/geotiff/spec/contents.html">GeoTIFF specification</a></li>
+ *   <li><a href="http://download.osgeo.org/geotiff/spec/geotiff.rtf">GeoTIFF specification</a></li>
  * </ul>
  *
  * @author  Rémi Maréchal (Geomatys)

Modified: sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -16,8 +16,10 @@
  */
 package org.apache.sis.internal.netcdf;
 
+import java.io.IOException;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.storage.netcdf.AttributeNames;
+import org.apache.sis.storage.DataStoreException;
 
 
 /**
@@ -27,7 +29,7 @@ import org.apache.sis.storage.netcdf.Att
  * {@link ucar.nc2.dataset.CoordinateAxis1D} or {@link ucar.nc2.dataset.CoordinateAxis2D} respectively.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.3
+ * @version 0.8
  *
  * @see GridGeometry#getAxes()
  *
@@ -41,14 +43,13 @@ public final class Axis {
     public final AttributeNames.Dimension attributeNames;
 
     /**
-     * The indices of the grid dimension associated to this axis. Values in this array are sorted with more
-     * "significant" (defined below) dimensions first - this is not necessarily increasing order.
-     *
-     * <div class="section">Elements order</div>
-     * The length of this array is often 1. But if more than one grid dimension is associated to this axis
-     * (i.e. if the wrapped NetCDF axis is an instance of {@link ucar.nc2.dataset.CoordinateAxis2D}), then
-     * the first index is what seems the most significant grid dimension (i.e. the dimension which seems
-     * to be varying fastest along this axis).
+     * The indices of the grid dimension associated to this axis. The length of this array is often 1.
+     * But if more than one grid dimension is associated to this axis (i.e. if the wrapped NetCDF axis
+     * is an instance of {@link ucar.nc2.dataset.CoordinateAxis2D}),  then the first value is the grid
+     * dimension which seems most closely oriented toward this axis direction. We do that for allowing
+     * {@code MetadataReader.addSpatialRepresentationInfo(…)} method to get the most appropriate value
+     * for ISO 19115 {@code metadata/spatialRepresentationInfo/axisDimensionProperties/dimensionSize}
+     * metadata property.
      */
     public final int[] sourceDimensions;
 
@@ -61,16 +62,20 @@ public final class Axis {
 
     /**
      * Constructs a new axis associated to an arbitrary number of grid dimension.
-     * In the particular case where the number of dimensions is equals to 2, this
-     * constructor will detects by itself which grid dimension varies fastest.
+     * In the particular case where the number of dimensions is equals to 2, this constructor will detect
+     * by itself which grid dimension varies fastest and reorder in-place the elements in the given arrays
+     * (those array are modified, not cloned).
      *
-     * @param owner             provides callback for the conversion from grid coordinates to geodetic coordinates.
-     * @param attributeNames    the attributes to use for fetching dimension information, or {@code null} if unknown.
-     * @param sourceDimensions  the index of the grid dimension associated to this axis.
-     * @param sourceSizes       the number of cell elements along that axis.
+     * @param  owner             provides callback for the conversion from grid coordinates to geodetic coordinates.
+     * @param  axis              an implementation-dependent object representing the two-dimensional axis, or {@code null} if none.
+     * @param  attributeNames    the attributes to use for fetching dimension information, or {@code null} if unknown.
+     * @param  sourceDimensions  the index of the grid dimension associated to this axis.
+     * @param  sourceSizes       the number of cell elements along that axis.
+     * @throws IOException if an I/O operation was necessary but failed.
+     * @throws DataStoreException if a logical error occurred.
      */
-    public Axis(final GridGeometry owner, final AttributeNames.Dimension attributeNames,
-            final int[] sourceDimensions, final int[] sourceSizes)
+    public Axis(final GridGeometry owner, final Object axis, final AttributeNames.Dimension attributeNames,
+            final int[] sourceDimensions, final int[] sourceSizes) throws IOException, DataStoreException
     {
         this.attributeNames   = attributeNames;
         this.sourceDimensions = sourceDimensions;
@@ -80,9 +85,11 @@ public final class Axis {
             final int up1  = sourceSizes[1];
             final int mid0 = up0 / 2;
             final int mid1 = up1 / 2;
-            final double d1 = (owner.coordinateForCurrentAxis(0, mid1) - owner.coordinateForCurrentAxis(up0-1, mid1)) / up0;
-            final double d2 = (owner.coordinateForCurrentAxis(mid0, 0) - owner.coordinateForCurrentAxis(mid0, up1-1)) / up1;
-            if (Math.abs(d2) > Math.abs(d1)) {
+            final double inc0 = (owner.coordinateForAxis(axis,     0, mid1) -
+                                 owner.coordinateForAxis(axis, up0-1, mid1)) / up0;
+            final double inc1 = (owner.coordinateForAxis(axis, mid0,     0) -
+                                 owner.coordinateForAxis(axis, mid0, up1-1)) / up1;
+            if (Math.abs(inc1) > Math.abs(inc0)) {
                 sourceSizes[0] = up1;
                 sourceSizes[1] = up0;
                 ArraysExt.swap(sourceDimensions, 0, 1);

Modified: sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -18,11 +18,13 @@ package org.apache.sis.internal.netcdf;
 
 import java.util.Date;
 import java.util.Objects;
+import java.util.Collection;
 import java.io.Closeable;
 import java.io.IOException;
 import javax.measure.Unit;
 import javax.measure.format.ParserException;
 import org.apache.sis.measure.Units;
+import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.util.logging.WarningListeners;
 
@@ -42,7 +44,7 @@ public abstract class Decoder implements
     /**
      * Where to send the warnings.
      */
-    public final WarningListeners<?> listeners;
+    public final WarningListeners<DataStore> listeners;
 
     /**
      * Sets to {@code true} for canceling a reading process.
@@ -55,7 +57,7 @@ public abstract class Decoder implements
      *
      * @param  listeners  where to send the warnings.
      */
-    protected Decoder(final WarningListeners<?> listeners) {
+    protected Decoder(final WarningListeners<DataStore> listeners) {
         Objects.requireNonNull(listeners);
         this.listeners = listeners;
     }
@@ -85,6 +87,13 @@ public abstract class Decoder implements
     public abstract String[] getSearchPath();
 
     /**
+     * Returns the names of all global attributes found in the file.
+     *
+     * @return names of all global attributes in the file.
+     */
+    public abstract Collection<String> getAttributeNames();
+
+    /**
      * Returns the value for the attribute of the given name, or {@code null} if none.
      * This method searches in the groups specified by the last call to {@link #setSearchPath(String[])}.
      * Null values and empty strings are ignored.
@@ -216,6 +225,7 @@ public abstract class Decoder implements
      *
      * @return all grid geometries, or an empty array if none.
      * @throws IOException if an I/O operation was necessary but failed.
+     * @throws DataStoreException if a logical error occurred.
      */
-    public abstract GridGeometry[] getGridGeometries() throws IOException;
+    public abstract GridGeometry[] getGridGeometries() throws IOException, DataStoreException;
 }

Modified: sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/DiscreteSampling.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/DiscreteSampling.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/DiscreteSampling.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/DiscreteSampling.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -16,6 +16,10 @@
  */
 package org.apache.sis.internal.netcdf;
 
+// Branch-dependent imports
+import java.util.stream.Stream;
+import org.opengis.feature.Feature;
+
 
 /**
  * Returns the features encoded in the NetCDF files when they are encoded as discrete sampling.
@@ -34,4 +38,11 @@ public abstract class DiscreteSampling {
      */
     protected DiscreteSampling() {
     }
+
+    /**
+     * Returns the stream of features.
+     *
+     * @return the stream of features.
+     */
+    public abstract Stream<Feature> features();
 }

Modified: sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/GridGeometry.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/GridGeometry.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/GridGeometry.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/GridGeometry.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -16,12 +16,15 @@
  */
 package org.apache.sis.internal.netcdf;
 
+import java.io.IOException;
+import org.apache.sis.storage.DataStoreException;
+
 
 /**
  * Information about the grid geometry and the conversion from grid coordinates to geodetic coordinates.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.3
+ * @version 0.8
  * @since   0.3
  * @module
  */
@@ -33,38 +36,47 @@ public abstract class GridGeometry {
     }
 
     /**
-     * Returns the number of dimensions in the grid.
-     * This is the number of dimensions of source coordinates in the <cite>"grid to CRS"</cite> transform.
+     * Returns the number of dimensions of source coordinates in the <cite>"grid to CRS"</cite> conversion.
+     * This is the number of dimensions of the <em>grid</em>.
      *
      * @return number of grid dimensions.
      */
     public abstract int getSourceDimensions();
 
     /**
-     * Returns the number of dimensions in the coordinate reference system.
-     * This is the number of dimensions of target coordinates in the <cite>"grid to CRS"</cite> transform.
-     * It should also be equal to the size of the list returned by {@link #getAxes()}.
+     * Returns the number of dimensions of target coordinates in the <cite>"grid to CRS"</cite> conversion.
+     * This is the number of dimensions of the <em>coordinate reference system</em>.
+     * It should be equal to the size of the array returned by {@link #getAxes()},
+     * but caller should be robust to inconsistencies.
      *
      * @return number of CRS dimensions.
      */
     public abstract int getTargetDimensions();
 
     /**
-     * Returns the axes of the coordinate reference system. The size of this list is expected equals to the
-     * value returned by {@link #getTargetDimensions()}, however the caller should be robust to inconsistencies.
+     * Returns the axes of the coordinate reference system. The size of this array is expected equals to the
+     * value returned by {@link #getTargetDimensions()}, but the caller should be robust to inconsistencies.
+     *
+     * <p>This method is used mostly for producing ISO 19115 metadata. It is typically invoked only once.</p>
      *
      * @return the CRS axes, in NetCDF order (reverse of "natural" order).
+     * @throws IOException if an I/O operation was necessary but failed.
+     * @throws DataStoreException if a logical error occurred.
      */
-    public abstract Axis[] getAxes();
+    public abstract Axis[] getAxes() throws IOException, DataStoreException;
 
     /**
-     * Returns the coordinate for the given grid coordinate of an axis in the process of being constructed.
-     * This is a callback method for {@link #getAxes()}. In the NetCDF UCAR API, this method maps directly
-     * to {@link ucar.nc2.dataset.CoordinateAxis2D#getCoordValue(int, int)}.
+     * Returns a coordinate for the given two-dimensional grid coordinate axis. This is (indirectly) a callback
+     * method for {@link #getAxes()}. The (<var>i</var>, <var>j</var>) indices are grid indices <em>before</em>
+     * they get reordered by the {@link Axis} constructor. In the NetCDF UCAR API, this method maps directly to
+     * {@link ucar.nc2.dataset.CoordinateAxis2D#getCoordValue(int, int)}.
      *
-     * @param  j  the fastest varying (right-most) index.
-     * @param  i  the slowest varying (left-most) index.
+     * @param  axis  an implementation-dependent object representing the two-dimensional axis, or {@code null} if none.
+     * @param  j     the fastest varying (right-most) index.
+     * @param  i     the slowest varying (left-most) index.
      * @return the coordinate at the given index, or {@link Double#NaN} if it can not be computed.
+     * @throws IOException if an I/O operation was necessary but failed.
+     * @throws DataStoreException if a logical error occurred.
      */
-    protected abstract double coordinateForCurrentAxis(final int j, final int i);
+    protected abstract double coordinateForAxis(Object axis, int j, int i) throws IOException, DataStoreException;
 }

Modified: sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.internal.netcdf;
 
+import java.util.Collection;
 import java.io.IOException;
 import java.awt.image.DataBuffer;
 import org.apache.sis.math.Vector;
@@ -154,6 +155,13 @@ public abstract class Variable extends N
     public abstract int[] getGridEnvelope();
 
     /**
+     * Returns the names of all attributes associated to this variable.
+     *
+     * @return names of all attributes associated to this variable.
+     */
+    public abstract Collection<String> getAttributeNames();
+
+    /**
      * Returns the sequence of values for the given attribute, or an empty array if none.
      * The elements will be of class {@link String} if {@code numeric} is {@code false},
      * or {@link Number} if {@code numeric} is {@code true}.
@@ -166,6 +174,28 @@ public abstract class Variable extends N
 
     /**
      * Reads all the data for this variable and returns them as an array of a Java primitive type.
+     * Multi-dimensional variables are flattened as a one-dimensional array (wrapped in a vector).
+     * Example:
+     *
+     * {@preformat text
+     *   DIMENSIONS:
+     *     time: 3
+     *     lat : 2
+     *     lon : 4
+     *
+     *   VARIABLES:
+     *     temperature (time,lat,lon)
+     *
+     *   DATA INDICES:
+     *     (0,0,0) (0,0,1) (0,0,2) (0,0,3)
+     *     (0,1,0) (0,1,1) (0,1,2) (0,1,3)
+     *     (1,0,0) (1,0,1) (1,0,2) (1,0,3)
+     *     (1,1,0) (1,1,1) (1,1,2) (1,1,3)
+     *     (2,0,0) (2,0,1) (2,0,2) (2,0,3)
+     *     (2,1,0) (2,1,1) (2,1,2) (2,1,3)
+     * }
+     *
+     * This method may cache the returned vector, at implementation choice.
      *
      * @return the data as an array of a Java primitive type.
      * @throws IOException if an error occurred while reading the data.
@@ -183,6 +213,9 @@ public abstract class Variable extends N
      *       to {@code Integer.toUnsignedLong(getGridEnvelope()[i])} exclusive.</li>
      * </ul>
      *
+     * If the variable has more than one dimension, then the data are packed in a one-dimensional vector
+     * in the same way than {@link #read()}.
+     *
      * @param  areaLower    index of the first value to read along each dimension.
      * @param  areaUpper    index after the last value to read along each dimension.
      * @param  subsampling  sub-sampling along each dimension. 1 means no sub-sampling.

Modified: sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -18,6 +18,8 @@ package org.apache.sis.internal.netcdf.i
 
 import java.util.Set;
 import java.util.Map;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.AbstractMap;
 import java.util.LinkedHashSet;
 import java.util.LinkedHashMap;
@@ -45,6 +47,7 @@ import org.apache.sis.internal.netcdf.Re
 import org.apache.sis.internal.storage.io.ChannelDataInput;
 import org.apache.sis.internal.util.CollectionsExt;
 import org.apache.sis.internal.util.StandardDateFormat;
+import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.DataStoreContentException;
 import org.apache.sis.util.iso.DefaultNameSpace;
@@ -222,7 +225,7 @@ public final class ChannelDecoder extend
      * @throws IOException if an error occurred while reading the channel.
      * @throws DataStoreException if the content of the given channel is not a NetCDF file.
      */
-    public ChannelDecoder(final WarningListeners<?> listeners, final ChannelDataInput input)
+    public ChannelDecoder(final WarningListeners<DataStore> listeners, final ChannelDataInput input)
             throws IOException, DataStoreException
     {
         super(listeners);
@@ -648,6 +651,8 @@ public final class ChannelDecoder extend
      *
      * @param  name  the name of the attribute to search, or {@code null}.
      * @return the attribute value, or {@code null} if none.
+     *
+     * @see #getAttributeNames()
      */
     private Object findAttribute(final String name) {
         Object value = attributeMap.get(name);
@@ -662,6 +667,16 @@ public final class ChannelDecoder extend
     }
 
     /**
+     * Returns the names of all global attributes found in the file.
+     *
+     * @return names of all global attributes in the file.
+     */
+    @Override
+    public Collection<String> getAttributeNames() {
+        return Collections.unmodifiableSet(attributeMap.keySet());
+    }
+
+    /**
      * Returns the value for the attribute of the given name, or {@code null} if none.
      *
      * @param  name  the name of the attribute to search, or {@code null}.
@@ -772,7 +787,8 @@ public final class ChannelDecoder extend
             /*
              * First, find all variables which are used as coordinate system axis. The keys in the map are
              * the grid dimensions which are the domain of the variable (i.e. the sources of the conversion
-             * from grid coordinates to CRS coordinates).
+             * from grid coordinates to CRS coordinates). For each key there is usually only one value, but
+             * we try to make this code robust to unusual NetCDF files.
              */
             final Map<Dimension, List<VariableInfo>> dimToAxes = new IdentityHashMap<>();
             for (final VariableInfo variable : variables) {
@@ -803,7 +819,7 @@ nextVar:    for (final VariableInfo vari
                      * This is a "all or nothing" operation.
                      */
                     for (final Dimension dimension : variable.dimensions) {
-                        final List<VariableInfo> axis = dimToAxes.get(dimension);
+                        final List<VariableInfo> axis = dimToAxes.get(dimension);       // Should have only 1 element.
                         if (axis == null) {
                             axes.clear();
                             continue nextVar;

Modified: sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/FeaturesInfo.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/FeaturesInfo.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/FeaturesInfo.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/FeaturesInfo.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -16,16 +16,35 @@
  */
 package org.apache.sis.internal.netcdf.impl;
 
-import java.util.ArrayList;
+import java.util.Map;
 import java.util.List;
+import java.util.Collection;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.io.IOException;
 import org.apache.sis.math.Vector;
 import org.apache.sis.internal.netcdf.DataType;
 import org.apache.sis.internal.netcdf.DiscreteSampling;
 import org.apache.sis.internal.netcdf.Resources;
+import org.apache.sis.internal.feature.Geometries;
+import org.apache.sis.internal.feature.MovingFeature;
 import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.feature.DefaultFeatureType;
+import org.apache.sis.feature.DefaultAttributeType;
+import org.apache.sis.util.collection.BackingStoreException;
 import ucar.nc2.constants.CF;
 
+// Branch-dependent imports
+import java.util.Spliterator;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import java.util.function.Consumer;
+import org.opengis.feature.Feature;
+import org.opengis.feature.FeatureType;
+import org.opengis.feature.PropertyType;
+import org.opengis.feature.AttributeType;
+
 
 /**
  * Implementations of the discrete sampling features decoder. This implementation shall be able to decode at least the
@@ -44,18 +63,85 @@ final class FeaturesInfo extends Discret
 
     /**
      * The moving feature identifiers ("mfIdRef").
+     * The amount of identifiers shall be the same than the length of the {@link #counts} vector.
      */
     private final VariableInfo identifiers;
 
     /**
+     * The variable that contains time.
+     */
+    private final VariableInfo time;
+
+    /**
+     * The variable that contains <var>x</var> and <var>y</var> ordinate values (typically longitudes and latitudes).
+     * All variables in this array shall have the same length, and that length shall be the same than {@link #time}.
+     */
+    private final VariableInfo[] coordinates;
+
+    /**
+     * Any custom properties.
+     */
+    private final VariableInfo[] properties;
+
+    /**
+     * The type of all features to be read by this {@code FeaturesInfo}.
+     */
+    private final FeatureType type;
+
+    private final Geometries<?> factory = Geometries.implementation(null);          // TODO: shall be given by the store.
+
+    /**
      * Creates a new discrete sampling parser for features identified by the given variable.
      *
      * @param  counts       the count of instances per feature.
      * @param  identifiers  the feature identifiers.
      */
-    private FeaturesInfo(final Vector counts, final VariableInfo identifiers) {
+    @SuppressWarnings("rawtypes")                               // Because of generic array creation.
+    private FeaturesInfo(final Vector counts, final VariableInfo identifiers, final VariableInfo time,
+            final Collection<VariableInfo> coordinates, final Collection<VariableInfo> properties)
+    {
         this.counts      = counts;
         this.identifiers = identifiers;
+        this.coordinates = coordinates.toArray(new VariableInfo[coordinates.size()]);
+        this.properties  = properties .toArray(new VariableInfo[properties .size()]);
+        this.time        = time;
+        /*
+         * Creates a description of the features to be read.
+         */
+        final Map<String,Object> info = new HashMap<>(4);
+        final PropertyType[] pt = new PropertyType[this.properties.length + 2];
+        AttributeType[] characteristics = null;
+        for (int i=0; i<pt.length; i++) {
+            final VariableInfo variable;
+            final Class<?> valueClass;
+            int minOccurs = 1;
+            int maxOccurs = 1;
+            switch (i) {
+                case 0: {
+                    variable        = identifiers;
+                    valueClass      = Integer.class;
+                    break;
+                }
+                case 1: {
+                    variable        = null;
+                    valueClass      = factory.polylineClass;
+                    characteristics = new AttributeType[] {MovingFeature.TIME};
+                    break;
+                }
+                default: {
+                    variable        = this.properties[i-2];
+                    valueClass      = Number.class;           // TODO: use more accurate value class.
+                    minOccurs       = 0;
+                    maxOccurs       = Integer.MAX_VALUE;
+                    break;
+                }
+            }
+            info.put(DefaultAttributeType.NAME_KEY, (variable != null) ? variable.getName() : "trajectory");
+            // TODO: add description.
+            pt[i] = new DefaultAttributeType<>(info, valueClass, minOccurs, maxOccurs, null, characteristics);
+        }
+        info.put(DefaultAttributeType.NAME_KEY, "Feature");     // TODO: find a better name.
+        type = new DefaultFeatureType(info, false, null, pt);
     }
 
     /**
@@ -148,12 +234,154 @@ search: for (final VariableInfo counts :
                         }
                     }
                     /*
-                     * At this point, all information has been verified as valid.
+                     * At this point, all information have been verified as valid. Now search all variables having
+                     * the expected sample dimension. Those variable contains the actual data. For example if the
+                     * sample dimension name is "points", then we may have:
+                     *
+                     *     double longitude(points);
+                     *         longitude:axis = "X";
+                     *         longitude:standard_name = "longitude";
+                     *         longitude:units = "degrees_east";
+                     *     double latitude(points);
+                     *         latitude:axis = "Y";
+                     *         latitude:standard_name = "latitude";
+                     *         latitude:units = "degrees_north";
+                     *     double time(points);
+                     *         time:axis = "T";
+                     *         time:standard_name = "time";
+                     *         time:units = "minutes since 2014-11-29 00:00:00";
+                     *     short myCustomProperty(points);
                      */
-                    features.add(new FeaturesInfo(counts.read().compress(0), identifiers));
+                    final Map<String,VariableInfo> coordinates = new LinkedHashMap<>();
+                    final List<VariableInfo> properties  = new ArrayList<>();
+                    for (final VariableInfo data : decoder.variables) {
+                        if (data.dimensions.length == 1 && data.dimensions[0] == sampleDimension) {
+                            final Object axisType = data.getAttributeValue(CF.AXIS);
+                            if (axisType == null) {
+                                properties.add(data);
+                            } else if (coordinates.put(axisType.toString(), data) != null) {
+                                continue search;    // Two axes of the same type: abort.
+                            }
+                        }
+                    }
+                    final VariableInfo time = coordinates.remove("T");
+                    if (time != null) {
+                        features.add(new FeaturesInfo(counts.read().compress(0), identifiers, time, coordinates.values(), properties));
+                    }
                 }
             }
         }
         return features.toArray(new FeaturesInfo[features.size()]);
     }
+
+    /**
+     * Returns the stream of features.
+     */
+    @Override
+    public Stream<Feature> features() {
+        return StreamSupport.stream(new Iter(), false);
+    }
+
+    /**
+     * Implementation of the iterator returned by {@link #features()}.
+     */
+    private final class Iter implements Spliterator<Feature> {
+        /**
+         * Index of the next feature to read.
+         */
+        private int index;
+
+        /**
+         * Position in the data vectors of the next feature to read.
+         * This is the sum of the length of data in all previous features.
+         */
+        private int position;
+
+        /**
+         * Creates a new iterator.
+         */
+        Iter() {
+        }
+
+        /**
+         * Executes the given action only on the next feature, if any.
+         *
+         * @todo current reading process implies lot of seeks, which is inefficient.
+         */
+        @Override
+        public boolean tryAdvance(final Consumer<? super Feature> action) {
+            final int   length = counts.intValue(index);
+            final int[] lower  = {position};
+            final int[] upper  = {position + length};
+            final int[] step   = {1};
+            final Vector   id, t;
+            final Vector[] coords = new Vector[coordinates.length];
+            final Vector[] props  = new Vector[properties.length];
+            try {
+                id = identifiers.read();                    // Efficiency should be okay because of cached value.
+                t = time.read(lower, upper, step);
+                for (int i=0; i<coordinates.length; i++) {
+                    coords[i] = coordinates[i].read(lower, upper, step);
+                }
+                for (int i=0; i<properties.length; i++) {
+                    props[i] = properties[i].read(lower, upper, step);
+                }
+            } catch (IOException | DataStoreException e) {
+                throw new BackingStoreException(canNotReadFile(), e);
+            }
+            final Feature feature = type.newInstance();
+            feature.setPropertyValue(identifiers.getName(), id.intValue(index));
+            for (int i=0; i<properties.length; i++) {
+                feature.setPropertyValue(properties[i].getName(), props[i]);
+                // TODO: set time characteristic.
+            }
+            // TODO: temporary hack - to be replaced by support in Vector.
+            final int dimension = coordinates.length;
+            final double[] tmp = new double[length * dimension];
+            for (int i=0; i<tmp.length; i++) {
+                tmp[i] = coords[i % dimension].doubleValue(i / dimension);
+            }
+            feature.setPropertyValue("trajectory", factory.createPolyline(dimension, Vector.create(tmp, false)));
+            action.accept(feature);
+            position = Math.addExact(position, length);
+            return ++index < counts.size();
+        }
+
+        /**
+         * Current implementation can not split this iterator.
+         */
+        @Override
+        public Spliterator<Feature> trySplit() {
+            return null;
+        }
+
+        /**
+         * Returns the number of features.
+         */
+        @Override
+        public long estimateSize() {
+            return counts.size();
+        }
+
+        /**
+         * Returns the characteristics of the iteration over feature instances.
+         * The iteration is assumed {@link #ORDERED} in the declaration order in the NetCDF file.
+         * The iteration is {@link #NONNULL} (i.e. {@link #tryAdvance(Consumer)} is not allowed
+         * to return null value) and {@link #IMMUTABLE} (i.e. we do not support modification of
+         * the NetCDF file while an iteration is in progress).
+         *
+         * @return characteristics of iteration over the features in the NetCDF file.
+         */
+        @Override
+        public int characteristics() {
+            return ORDERED | NONNULL | IMMUTABLE | SIZED;
+        }
+    }
+
+    /**
+     * Returns the error message for a file that can not be read.
+     */
+    final String canNotReadFile() {
+        return null;    // TODO
+    }
 }

Modified: sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/GridGeometryInfo.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/GridGeometryInfo.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/GridGeometryInfo.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/GridGeometryInfo.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -16,10 +16,15 @@
  */
 package org.apache.sis.internal.netcdf.impl;
 
+import java.io.IOException;
+import java.util.TreeMap;
+import java.util.SortedMap;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.internal.netcdf.Axis;
 import org.apache.sis.internal.netcdf.GridGeometry;
 import org.apache.sis.storage.netcdf.AttributeNames;
+import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.util.resources.Errors;
 
 
 /**
@@ -29,7 +34,7 @@ import org.apache.sis.storage.netcdf.Att
  * (domain) and output (range) of the function that convert grid indices to geodetic coordinates.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.3
+ * @version 0.8
  * @since   0.3
  * @module
  */
@@ -82,6 +87,8 @@ final class GridGeometryInfo extends Gri
     /**
      * Returns the number of dimensions of target coordinates in the <cite>"grid to CRS"</cite> conversion.
      * This is the number of dimensions of the <em>coordinate reference system</em>.
+     * It should be equal to the size of the array returned by {@link #getAxes()},
+     * but caller should be robust to inconsistencies.
      */
     @Override
     public int getTargetDimensions() {
@@ -90,16 +97,46 @@ final class GridGeometryInfo extends Gri
 
     /**
      * Returns all axes of the NetCDF coordinate system, together with the grid dimension to which the axis
-     * is associated. See {@code org.apache.sis.internal.netcdf.ucar.GridGeometryWrapper.getAxes()} for more
-     * information on the algorithm applied here, and relationship with the UCAR library.
+     * is associated. See {@code org.apache.sis.internal.netcdf.ucar.GridGeometryWrapper.getAxes()} for a
+     * closer look on the relationship between this algorithm and the UCAR library.
+     *
+     * <p>In this method, the words "domain" and "range" are used in the NetCDF sense: they are the input
+     * (domain) and output (range) of the function that convert grid indices to geodetic coordinates.</p>
+     *
+     * <p>The domain of all axes is often the same than the domain of the variable, but not necessarily.
+     * In particular, the relationship is not straightforward when the coordinate system contains
+     * "two-dimensional axes" (in {@link ucar.nc2.dataset.CoordinateAxis2D} sense).</p>
+     *
+     * @return the CRS axes, in NetCDF order (reverse of "natural" order).
+     * @throws IOException if an I/O operation was necessary but failed.
+     * @throws DataStoreException if a logical error occurred.
      */
     @Override
-    public Axis[] getAxes() {
-        int targetDim = range.length;
-        final Axis[] axes = new Axis[targetDim];
-        while (--targetDim >= 0) {
-            final VariableInfo axis = range[targetDim];
-            final Dimension[] axisDomain = axis.dimensions;
+    public Axis[] getAxes() throws IOException, DataStoreException {
+        /*
+         * Process the variables in the order the appear in the sequence of bytes that make the NetCDF files.
+         * This is often the same order than the indices, but not necessarily. The intend is to reduce the
+         * amount of disk seek operations.
+         */
+        final SortedMap<VariableInfo,Integer> variables = new TreeMap<>();
+        for (int i=0; i<range.length; i++) {
+            final VariableInfo v = range[i];
+            if (variables.put(v, i) != null) {
+                throw new DataStoreException(Errors.format(Errors.Keys.DuplicatedElement_1, v.getName()));
+            }
+        }
+        /*
+         * In this method, 'sourceDim' and 'targetDim' are relative to "grid to CRS" conversion.
+         * So 'sourceDim' is the grid (domain) dimension and 'targetDim' is the CRS (range) dimension.
+         */
+        final Axis[] axes = new Axis[range.length];
+        for (final SortedMap.Entry<VariableInfo,Integer> entry : variables.entrySet()) {
+            final int targetDim = entry.getValue();
+            final VariableInfo axis = entry.getKey();
+            /*
+             * The AttributeNames are for ISO 19115 metadata. They are not used for locating grid cells
+             * on Earth, but we nevertheless get them now for making MetadataReader work easier.
+             */
             AttributeNames.Dimension attributeNames = null;
             final String type = axis.getAxisType();
             if (type != null) {
@@ -110,11 +147,17 @@ final class GridGeometryInfo extends Gri
                     }
                 }
             }
+            /*
+             * Get the grid dimensions (part of the "domain" in UCAR terminology) used for computing
+             * the ordinate values along the current axis. There is exactly 1 such grid dimension in
+             * straightforward NetCDF files. However some more complex files may have 2 dimensions.
+             */
             int i = 0;
+            final Dimension[] axisDomain = axis.dimensions;
             final int[] indices = new int[axisDomain.length];
             final int[] sizes   = new int[axisDomain.length];
             for (final Dimension dimension : axisDomain) {
-                for (int sourceDim=domain.length; --sourceDim>=0;) {
+                for (int sourceDim = domain.length; --sourceDim >= 0;) {
                     if (domain[sourceDim] == dimension) {
                         indices[i] = sourceDim;
                         sizes[i++] = dimension.length;
@@ -122,15 +165,21 @@ final class GridGeometryInfo extends Gri
                     }
                 }
             }
-            axes[targetDim] = new Axis(this, attributeNames,
-                    ArraysExt.resize(indices, i),
-                    ArraysExt.resize(sizes, i));
+            axes[targetDim] = new Axis(this, axis, attributeNames,
+                                       ArraysExt.resize(indices, i),
+                                       ArraysExt.resize(sizes, i));
         }
         return axes;
     }
 
+    /**
+     * Returns a coordinate for the given two-dimensional grid coordinate axis.
+     * This is (indirectly) a callback method for {@link #getAxes()}.
+     */
     @Override
-    protected double coordinateForCurrentAxis(final int j, final int i) {
-        throw new UnsupportedOperationException();
+    protected double coordinateForAxis(final Object axis, final int j, final int i) throws IOException, DataStoreException {
+        final VariableInfo v = ((VariableInfo) axis);
+        final int n = v.dimensions[0].length;
+        return v.read().doubleValue(j + n*i);
     }
 }

Modified: sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/VariableInfo.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/VariableInfo.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/VariableInfo.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/VariableInfo.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -17,6 +17,8 @@
 package org.apache.sis.internal.netcdf.impl;
 
 import java.util.Map;
+import java.util.Collection;
+import java.util.Collections;
 import java.io.IOException;
 import java.lang.reflect.Array;
 import ucar.nc2.constants.CF;
@@ -37,6 +39,8 @@ import org.apache.sis.math.Vector;
 
 /**
  * Description of a variable found in a NetCDF file.
+ * The natural ordering of {@code VariableInfo} is the order in which the variables appear in the stream of bytes
+ * that make the NetCDF file. Reading variables in natural order reduces the amount of channel seek operations.
  *
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
@@ -44,7 +48,7 @@ import org.apache.sis.math.Vector;
  * @since   0.3
  * @module
  */
-final class VariableInfo extends Variable {
+final class VariableInfo extends Variable implements Comparable<VariableInfo> {
     /**
      * The array to be returned by {@link #numberValues(Object)} when the given value is null.
      */
@@ -119,6 +123,13 @@ final class VariableInfo extends Variabl
     private final boolean isCoordinateSystemAxis;
 
     /**
+     * The values of the whole variable, or {@code null} if not yet read. This vector should be assigned only
+     * for relatively small variables, or for variables that are critical to the use of other variables
+     * (for example the values in coordinate system axes).
+     */
+    private transient Vector values;
+
+    /**
      * Creates a new variable.
      *
      * @param  input       the channel together with a buffer for reading the variable data.
@@ -262,6 +273,16 @@ final class VariableInfo extends Variabl
     }
 
     /**
+     * Returns the names of all attributes associated to this variable.
+     *
+     * @return names of all attributes associated to this variable.
+     */
+    @Override
+    public Collection<String> getAttributeNames() {
+        return Collections.unmodifiableSet(attributes.keySet());
+    }
+
+    /**
      * Returns the value of the given attribute, or {@code null} if none.
      * This method should be invoked only for hard-coded names that mix lower-case and upper-case letters.
      *
@@ -353,31 +374,39 @@ final class VariableInfo extends Variabl
 
     /**
      * Reads all the data for this variable and returns them as an array of a Java primitive type.
+     * Multi-dimensional variables are flattened as a one-dimensional array (wrapped in a vector).
+     * The vector is cached and returned as-is in all future invocation of this method.
      */
     @Override
+    @SuppressWarnings("ReturnOfCollectionOrArrayField")
     public Vector read() throws IOException, DataStoreException {
-        if (reader == null) {
-            throw new DataStoreContentException(unknownType());
-        }
-        long length = 1;
-        for (final Dimension dimension : dimensions) {
-            length *= dimension.length;
-        }
-        if (length > Integer.MAX_VALUE) {
-            throw new DataStoreContentException(Errors.format(Errors.Keys.ExcessiveListSize_2, name, length));
-        }
-        final int dimension = dimensions.length;
-        final long[] size  = new long[dimension];
-        final int [] sub   = new int [dimension];
-        for (int i=0; i<dimension; i++) {
-            sub [i] = 1;
-            size[i] = dimensions[(dimension - 1) - i].length();
+        if (values == null) {
+            if (reader == null) {
+                throw new DataStoreContentException(unknownType());
+            }
+            long length = 1;
+            for (final Dimension dimension : dimensions) {
+                length *= dimension.length();
+            }
+            if (length > Integer.MAX_VALUE) {
+                throw new DataStoreContentException(Errors.format(Errors.Keys.ExcessiveListSize_2, name, length));
+            }
+            final int dimension = dimensions.length;
+            final long[] size  = new long[dimension];
+            final int [] sub   = new int [dimension];
+            for (int i=0; i<dimension; i++) {
+                sub [i] = 1;
+                size[i] = dimensions[(dimension - 1) - i].length();
+            }
+            values = Vector.create(reader.read(new Region(size, new long[dimension], size, sub)), dataType.isUnsigned)
+                    .compress(0);
         }
-        return Vector.create(reader.read(new Region(size, new long[dimension], size, sub)), dataType.isUnsigned);
+        return values;
     }
 
     /**
      * Reads a sub-sampled sub-area of the variable.
+     * Multi-dimensional variables are flattened as a one-dimensional array (wrapped in a vector).
      *
      * @param  areaLower    index of the first value to read along each dimension, as unsigned integers.
      * @param  areaUpper    index after the last value to read along each dimension, as unsigned integers.
@@ -429,4 +458,15 @@ final class VariableInfo extends Variabl
     private String unknownType() {
         return Errors.format(Errors.Keys.UnknownType_1, "NetCDF:" + dataType);
     }
+
+    /**
+     * Returns -1 if this variable is located before the other variable in the streal of bytes that make
+     * the NetCDF file, or +1 if it is located after.
+     */
+    @Override
+    public int compareTo(final VariableInfo other) {
+        int c = Long.compare(reader.origin, other.reader.origin);
+        if (c == 0) c = name.compareTo(other.name);                 // Should not happen, but we are paranoiac.
+        return c;
+    }
 }

Modified: sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -20,6 +20,7 @@ import java.util.Date;
 import java.util.List;
 import java.util.EnumSet;
 import java.util.Formatter;
+import java.util.Collection;
 import java.io.IOException;
 import ucar.nc2.Group;
 import ucar.nc2.Attribute;
@@ -43,6 +44,7 @@ import org.apache.sis.internal.netcdf.De
 import org.apache.sis.internal.netcdf.Variable;
 import org.apache.sis.internal.netcdf.GridGeometry;
 import org.apache.sis.internal.netcdf.DiscreteSampling;
+import org.apache.sis.storage.DataStore;
 
 
 /**
@@ -100,7 +102,7 @@ public final class DecoderWrapper extend
      * @param listeners  where to send the warnings.
      * @param file       the NetCDF file from which to read data.
      */
-    public DecoderWrapper(final WarningListeners<?> listeners, final NetcdfFile file) {
+    public DecoderWrapper(final WarningListeners<DataStore> listeners, final NetcdfFile file) {
         super(listeners);
         this.file = file;
     }
@@ -113,7 +115,7 @@ public final class DecoderWrapper extend
      * @throws IOException if an error occurred while opening the NetCDF file.
      */
     @SuppressWarnings("ThisEscapedInObjectConstruction")
-    public DecoderWrapper(final WarningListeners<?> listeners, final String filename) throws IOException {
+    public DecoderWrapper(final WarningListeners<DataStore> listeners, final String filename) throws IOException {
         super(listeners);
         file = NetcdfDataset.openDataset(filename, false, this);
     }
@@ -169,6 +171,16 @@ public final class DecoderWrapper extend
     }
 
     /**
+     * Returns the names of all global attributes found in the file.
+     *
+     * @return names of all global attributes in the file.
+     */
+    @Override
+    public Collection<String> getAttributeNames() {
+        return VariableWrapper.toNames(file.getGlobalAttributes());
+    }
+
+    /**
      * Returns the NetCDF attribute of the given name in the given group, or {@code null} if none.
      * This method is invoked for every global and group attributes to be read by this class (but
      * not {@linkplain ucar.nc2.VariableSimpleIF variable} attributes), thus providing a single point

Modified: sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/FeaturesWrapper.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/FeaturesWrapper.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/FeaturesWrapper.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/FeaturesWrapper.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -19,6 +19,10 @@ package org.apache.sis.internal.netcdf.u
 import org.apache.sis.internal.netcdf.DiscreteSampling;
 import ucar.nc2.ft.FeatureCollection;
 
+// Branch-dependent imports
+import java.util.stream.Stream;
+import org.opengis.feature.Feature;
+
 
 /**
  * A wrapper around the UCAR {@code ucar.nc2.ft} package.
@@ -41,5 +45,12 @@ final class FeaturesWrapper extends Disc
         this.features = features;
     }
 
-    // TODO
+
+    /**
+     * Returns the stream of features.
+     */
+    @Override
+    public Stream<Feature> features() {
+        throw new UnsupportedOperationException();      // TODO
+    }
 }

Modified: sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridGeometryWrapper.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridGeometryWrapper.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridGeometryWrapper.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridGeometryWrapper.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.internal.netcdf.ucar;
 
+import java.io.IOException;
 import java.util.List;
 import ucar.nc2.Dimension;
 import ucar.nc2.constants.AxisType;
@@ -25,6 +26,7 @@ import ucar.nc2.dataset.CoordinateSystem
 import org.apache.sis.internal.netcdf.Axis;
 import org.apache.sis.internal.netcdf.GridGeometry;
 import org.apache.sis.storage.netcdf.AttributeNames;
+import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.util.ArraysExt;
 
 
@@ -35,7 +37,7 @@ import org.apache.sis.util.ArraysExt;
  * of the grid geometry information.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.3
+ * @version 0.8
  * @since   0.3
  * @module
  */
@@ -46,11 +48,6 @@ final class GridGeometryWrapper extends
     private final CoordinateSystem netcdfCS;
 
     /**
-     * A temporary variable for {@link #coordinateForCurrentAxis(int, int)}.
-     */
-    private transient CoordinateAxis2D axis2D;
-
-    /**
      * Creates a new grid geometry for the given NetCDF coordinate system.
      *
      * @param  cs  the NetCDF coordinate system, or {@code null} if none.
@@ -60,7 +57,8 @@ final class GridGeometryWrapper extends
     }
 
     /**
-     * Returns the number of dimensions in the grid.
+     * Returns the number of dimensions of source coordinates in the <cite>"grid to CRS"</cite> conversion.
+     * This is the number of dimensions of the <em>grid</em>.
      */
     @Override
     public int getSourceDimensions() {
@@ -68,7 +66,10 @@ final class GridGeometryWrapper extends
     }
 
     /**
-     * Returns the number of dimensions in the coordinate reference system.
+     * Returns the number of dimensions of target coordinates in the <cite>"grid to CRS"</cite> conversion.
+     * This is the number of dimensions of the <em>coordinate reference system</em>.
+     * It should be equal to the size of the array returned by {@link #getAxes()},
+     * but caller should be robust to inconsistencies.
      */
     @Override
     public int getTargetDimensions() {
@@ -86,20 +87,27 @@ final class GridGeometryWrapper extends
      * is often the same than the domain of the variable, but not necessarily.
      * In particular, the relationship is not straightforward when the coordinate system contains instances
      * of {@link CoordinateAxis2D}.</p>
+     *
+     * @return the CRS axes, in NetCDF order (reverse of "natural" order).
+     * @throws IOException if an I/O operation was necessary but failed.
+     * @throws DataStoreException if a logical error occurred.
      */
     @Override
-    public Axis[] getAxes() {
+    public Axis[] getAxes() throws IOException, DataStoreException {
         final List<Dimension> domain = netcdfCS.getDomain();
         final List<CoordinateAxis> range = netcdfCS.getCoordinateAxes();
-        int targetDim = range.size();
-        final Axis[] axes = new Axis[targetDim];
         /*
-         * NetCDF files declare axes in reverse order, so we iterate in the 'netcdfAxes'
-         * list in reverse order for adding to the 'axes' list in "natural" order.
+         * In this method, 'sourceDim' and 'targetDim' are relative to "grid to CRS" conversion.
+         * So 'sourceDim' is the grid (domain) dimension and 'targetDim' is the CRS (range) dimension.
          */
+        int targetDim = range.size();
+        final Axis[] axes = new Axis[targetDim];
         while (--targetDim >= 0) {
-            final CoordinateAxis  axis = range.get(targetDim);
-            final List<Dimension> axisDomain = axis.getDimensions();
+            final CoordinateAxis axis = range.get(targetDim);
+            /*
+             * The AttributeNames are for ISO 19115 metadata. They are not used for locating grid cells
+             * on Earth, but we nevertheless get them now for making MetadataReader work easier.
+             */
             AttributeNames.Dimension attributeNames = null;
             final AxisType type = axis.getAxisType();
             if (type != null) switch (type) {
@@ -116,6 +124,7 @@ final class GridGeometryWrapper extends
              * straightforward NetCDF files. However some more complex files may have 2 dimensions.
              */
             int i = 0;
+            final List<Dimension> axisDomain = axis.getDimensions();
             final int[] indices = new int[axisDomain.size()];
             final int[] sizes   = new int[indices.length];
             for (final Dimension dimension : axisDomain) {
@@ -127,24 +136,22 @@ final class GridGeometryWrapper extends
                 /*
                  * If the axis dimension has not been found in the coordinate system (sourceDim < 0),
                  * then there is maybe a problem with the NetCDF file. However for the purpose of this
-                 * package, we can proceed as if the dimension does not exist.
+                 * package, we can proceed as if the dimension does not exist ('i' not incremented).
                  */
             }
-            axis2D = (axis instanceof CoordinateAxis2D) ? (CoordinateAxis2D) axis : null;
-            axes[targetDim] = new Axis(this, attributeNames,
-                    ArraysExt.resize(indices, i),
-                    ArraysExt.resize(sizes, i));
+            axes[targetDim] = new Axis(this, axis, attributeNames,
+                                       ArraysExt.resize(indices, i),
+                                       ArraysExt.resize(sizes, i));
         }
-        axis2D = null;
         return axes;
     }
 
     /**
-     * Returns the coordinate for the given grid coordinate of an axis in the process of being constructed.
-     * This is a callback method for {@link #getAxes()}.
+     * Returns a coordinate for the given two-dimensional grid coordinate axis.
+     * This is (indirectly) a callback method for {@link #getAxes()}.
      */
     @Override
-    protected double coordinateForCurrentAxis(final int j, final int i) {
-        return (axis2D != null) ? axis2D.getCoordValue(j, i) : Double.NaN;
+    protected double coordinateForAxis(final Object axis, final int j, final int i) {
+        return (axis instanceof CoordinateAxis2D) ? ((CoordinateAxis2D) axis).getCoordValue(j, i) : Double.NaN;
     }
 }

Modified: sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/LogAdapter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/LogAdapter.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/LogAdapter.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/LogAdapter.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.internal.netcdf.ucar;
 
+import org.apache.sis.storage.DataStore;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.logging.WarningListeners;
 
@@ -40,12 +41,12 @@ final class LogAdapter implements Append
     /**
      * Where to sends the warning messages.
      */
-    private final WarningListeners<?> listeners;
+    private final WarningListeners<DataStore> listeners;
 
     /**
      * Creates a new adapter which will send lines to the given listeners.
      */
-    LogAdapter(final WarningListeners<?> listeners) {
+    LogAdapter(final WarningListeners<DataStore> listeners) {
         this.listeners = listeners;
     }
 

Modified: sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -18,6 +18,7 @@ package org.apache.sis.internal.netcdf.u
 
 import java.util.List;
 import java.io.IOException;
+import java.util.Collection;
 import ucar.ma2.Array;
 import ucar.ma2.Section;
 import ucar.ma2.InvalidRangeException;
@@ -27,6 +28,7 @@ import ucar.nc2.VariableIF;
 import org.apache.sis.math.Vector;
 import org.apache.sis.internal.netcdf.DataType;
 import org.apache.sis.internal.netcdf.Variable;
+import org.apache.sis.internal.util.UnmodifiableArrayList;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.DataStoreContentException;
 
@@ -130,6 +132,16 @@ final class VariableWrapper extends Vari
     }
 
     /**
+     * Returns the names of all attributes associated to this variable.
+     *
+     * @return names of all attributes associated to this variable.
+     */
+    @Override
+    public Collection<String> getAttributeNames() {
+        return toNames(variable.getAttributes());
+    }
+
+    /**
      * Returns the sequence of values for the given attribute, or an empty array if none.
      * The elements will be of class {@link String} if {@code numeric} is {@code false},
      * or {@link Number} if {@code numeric} is {@code true}.
@@ -164,11 +176,24 @@ final class VariableWrapper extends Vari
     }
 
     /**
+     * Returns the names of all attributes in the given list.
+     */
+    static List<String> toNames(final List<Attribute> attributes) {
+        final String[] names = new String[attributes.size()];
+        for (int i=0; i<names.length; i++) {
+            names[i] = attributes.get(i).getShortName();
+        }
+        return UnmodifiableArrayList.wrap(names);
+    }
+
+    /**
      * Reads all the data for this variable and returns them as an array of a Java primitive type.
+     * Multi-dimensional variables are flattened as a one-dimensional array (wrapped in a vector).
+     * This method may cache the returned vector, at UCAR library choice.
      */
     @Override
     public Vector read() throws IOException {
-        final Array array = variable.read();
+        final Array array = variable.read();                // May be cached by the UCAR library.
         return Vector.create(array.get1DJavaArray(array.getElementType()), variable.isUnsigned());
     }
 

Modified: sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/AttributeNames.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/AttributeNames.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/AttributeNames.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/AttributeNames.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -58,7 +58,7 @@ import org.opengis.metadata.extent.Geogr
  * <blockquote><table class="compact" summary="List of all NetCDF attributes.">
  * <tr valign="top"><td style="width: 25%">
  * {@value     #ACCESS_CONSTRAINT}<br>
- * {@value     #ACKNOWLEDGMENT}<br>
+ * {@value     #ACKNOWLEDGEMENT}<br>
  * {@value     #COMMENT}<br>
  * {@linkplain #CONTRIBUTOR "contributor_email"}<br>
  * {@linkplain #CONTRIBUTOR "contributor_name"}<br>
@@ -123,9 +123,9 @@ import org.opengis.metadata.extent.Geogr
  *
  * <p><b>References:</b></p>
  * <ul>
- *   <li><a href="https://geo-ide.noaa.gov/wiki/index.php?title=NetCDF_Attribute_Convention_for_Dataset_Discovery">NetCDF
+ *   <li><a href="http://wiki.esipfed.org/index.php/Category:Attribute_Conventions_Dataset_Discovery">NetCDF
  *       Attribute Convention for Dataset Discovery</a> wiki</li>
- *   <li><a href="http://ngdc.noaa.gov/metadata/published/xsl/nciso2.0/UnidataDD2MI.xsl">UnidataDD2MI.xsl</a> file</li>
+ *   <li><a href="https://github.com/Unidata/threddsIso/blob/master/src/main/resources/xsl/nciso/UnidataDD2MI.xsl">UnidataDD2MI.xsl</a> file</li>
  * </ul>
  *
  * @author  Martin Desruisseaux (Geomatys)
@@ -145,7 +145,7 @@ public class AttributeNames {
      * {@link Citation#getTitle() title}</li></ul>
      *
      * @see NetcdfFile#getTitle()
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#title_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#title">ESIP reference</a>
      */
     public static final String TITLE = ACDD.title;
 
@@ -157,7 +157,7 @@ public class AttributeNames {
      * {@link Metadata#getIdentificationInfo() identificationInfo} /
      * {@link DataIdentification#getAbstract() abstract}</li></ul>
      *
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#summary_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#summary">ESIP reference</a>
      */
     public static final String SUMMARY = ACDD.summary;
 
@@ -174,9 +174,8 @@ public class AttributeNames {
      * {@link Citation#getIdentifiers() identifier} /
      * {@link Identifier#getCode() code}</li></ul>
      *
-     * @see MetadataReader#getFileIdentifier()
      * @see NetcdfFile#getId()
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#id_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#id">ESIP reference</a>
      */
     public static final String IDENTIFIER = ACDD.id;
 
@@ -194,8 +193,7 @@ public class AttributeNames {
      * {@link Identifier#getAuthority() authority}</li></ul>
      *
      * @see #IDENTIFIER
-     * @see MetadataReader#getFileIdentifier()
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#id_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#naming_authority">ESIP reference</a>
      */
     public static final String NAMING_AUTHORITY = ACDD.naming_authority;
 
@@ -211,7 +209,7 @@ public class AttributeNames {
      *
      * @see #STANDARD_NAME_VOCABULARY
      * @see #KEYWORDS
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#standard_name_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#standard_name">ESIP reference</a>
      */
     public static final String STANDARD_NAME = CF.STANDARD_NAME;
 
@@ -227,7 +225,7 @@ public class AttributeNames {
      *
      * @see #STANDARD_NAME
      * @see #VOCABULARY
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#standard_name_vocabulary_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#standard_name_vocabulary">ESIP reference</a>
      */
     public static final String STANDARD_NAME_VOCABULARY = ACDD.standard_name_vocabulary;
 
@@ -242,7 +240,7 @@ public class AttributeNames {
      *
      * @see #VOCABULARY
      * @see #STANDARD_NAME
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#keywords_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#keywords">ESIP reference</a>
      */
     public static final String KEYWORDS = ACDD.keywords;
 
@@ -258,7 +256,7 @@ public class AttributeNames {
      *
      * @see #KEYWORDS
      * @see #STANDARD_NAME_VOCABULARY
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#keywords_vocabulary_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#keywords_vocabulary">ESIP reference</a>
      */
     public static final String VOCABULARY = ACDD.keywords_vocabulary;
 
@@ -291,7 +289,7 @@ public class AttributeNames {
      * {@link DataIdentification#getSpatialRepresentationTypes() spatialRepresentationType}</li></ul>
      *
      * @see SpatialRepresentationType
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#cdm_data_type_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#cdm_data_type">ESIP reference</a>
      */
     public static final String DATA_TYPE = ACDD.cdm_data_type;
 
@@ -304,7 +302,7 @@ public class AttributeNames {
      * {@link DataQuality#getLineage() lineage} /
      * {@link Lineage#getStatement() statement}</li></ul>
      *
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#history_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#history">ESIP reference</a>
      */
     public static final String HISTORY = ACDD.history;
 
@@ -316,7 +314,7 @@ public class AttributeNames {
      * {@link Metadata#getIdentificationInfo() identificationInfo} /
      * {@link DataIdentification#getSupplementalInformation() supplementalInformation}</li></ul>
      *
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#comment_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#comment">ESIP reference</a>
      */
     public static final String COMMENT = ACDD.comment;
 
@@ -340,7 +338,7 @@ public class AttributeNames {
      * {@link Citation#getDates() date} /
      * {@link CitationDate#getDate() date} with {@link DateType#CREATION}</li></ul>
      *
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#date_created_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#date_created">ESIP reference</a>
      */
     public static final String DATE_CREATED = ACDD.date_created;
 
@@ -354,7 +352,7 @@ public class AttributeNames {
      * {@link Citation#getDates() date} /
      * {@link CitationDate#getDate() date} with {@link DateType#REVISION}</li></ul>
      *
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#date_modified_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#date_modified">ESIP reference</a>
      */
     public static final String DATE_MODIFIED = ACDD.date_modified;
 
@@ -368,7 +366,7 @@ public class AttributeNames {
      * {@link Citation#getDates() date} /
      * {@link CitationDate#getDate() date} with {@link DateType#PUBLICATION}</li></ul>
      *
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#date_issued_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#date_issued">ESIP reference</a>
      */
     public static final String DATE_ISSUED = "date_issued";
 
@@ -524,7 +522,7 @@ public class AttributeNames {
      *
      * @see #CONTRIBUTOR
      * @see #PUBLISHER
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#creator_name_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#creator_name">ESIP reference</a>
      */
     public static final Responsible CREATOR = new Responsible(ACDD.creator_name,
             "institution", ACDD.creator_url, ACDD.creator_email, null, Role.ORIGINATOR);
@@ -538,7 +536,7 @@ public class AttributeNames {
      *
      * @see #CREATOR
      * @see #PUBLISHER
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#contributor_name_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#contributor_name">ESIP reference</a>
      */
     public static final Responsible CONTRIBUTOR = new Responsible("contributor_name",
             null, "contributor_url", "contributor_email", "contributor_role", null);
@@ -557,7 +555,7 @@ public class AttributeNames {
      *
      * @see #CREATOR
      * @see #CONTRIBUTOR
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#publisher_name_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#publisher_name">ESIP reference</a>
      */
     public static final Responsible PUBLISHER = new Responsible(ACDD.publisher_name,
             null, ACDD.publisher_url, ACDD.publisher_email, null, Role.PUBLISHER);
@@ -571,7 +569,7 @@ public class AttributeNames {
      * {@link DataIdentification#getDescriptiveKeywords() descriptiveKeywords} /
      * {@link Keywords#getKeywords() keyword} with the {@code "project"} {@link KeywordType}</li></ul>
      *
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#project_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#project">ESIP reference</a>
      */
     public static final String PROJECT = "project";
 
@@ -603,7 +601,7 @@ public class AttributeNames {
      * {@link Metadata#getContentInfo() contentInfo} /
      * {@link ImageDescription#getProcessingLevelCode() processingLevelCode}</li></ul>
      *
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#processing_level_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#processing_level">ESIP reference</a>
      */
     public static final String PROCESSING_LEVEL = ACDD.processing_level;
 
@@ -615,7 +613,14 @@ public class AttributeNames {
      * {@link Metadata#getIdentificationInfo() identificationInfo} /
      * {@link DataIdentification#getCredits() credit}</li></ul>
      *
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#acknowledgement_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#acknowledgement">ESIP reference</a>
+     *
+     * @since 0.8
+     */
+    public static final String ACKNOWLEDGEMENT = ACDD.acknowledgement;
+
+    /**
+     * @deprecated Renamed {@link #ACKNOWLEDGEMENT}.
      */
     public static final String ACKNOWLEDGMENT = "acknowledgment";
 
@@ -628,7 +633,7 @@ public class AttributeNames {
      * {@link DataIdentification#getResourceConstraints() resourceConstraints} /
      * {@link LegalConstraints#getUseLimitations() useLimitation}</li></ul>
      *
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#license_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#license">ESIP reference</a>
      */
     public static final String LICENSE = ACDD.license;
 
@@ -832,7 +837,7 @@ public class AttributeNames {
      * @see #LONGITUDE
      * @see #VERTICAL
      * @see #TIME
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#geospatial_lat_min_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#geospatial_lat_min">ESIP reference</a>
      */
     public static final Dimension LATITUDE = new Dimension(DimensionNameType.ROW,
             ACDD.LAT_MIN, ACDD.LAT_MAX, null, ACDD.LAT_RESOLUTION, ACDD.LAT_UNITS, null);
@@ -856,7 +861,7 @@ public class AttributeNames {
      * @see #LATITUDE
      * @see #VERTICAL
      * @see #TIME
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#geospatial_lon_min_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#geospatial_lon_min">ESIP reference</a>
      */
     public static final Dimension LONGITUDE = new Dimension(DimensionNameType.COLUMN,
             ACDD.LON_MIN, ACDD.LON_MAX, null, ACDD.LON_RESOLUTION, ACDD.LON_UNITS, null);
@@ -880,7 +885,7 @@ public class AttributeNames {
      * @see #LATITUDE
      * @see #LONGITUDE
      * @see #TIME
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#geospatial_vertical_min_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#geospatial_vertical_min">ESIP reference</a>
      */
     public static final Dimension VERTICAL = new Dimension(DimensionNameType.VERTICAL,
             ACDD.VERT_MIN, ACDD.VERT_MAX, null, ACDD.VERT_RESOLUTION, ACDD.VERT_UNITS, ACDD.VERT_IS_POSITIVE);
@@ -902,7 +907,7 @@ public class AttributeNames {
      * @see #LATITUDE
      * @see #LONGITUDE
      * @see #VERTICAL
-     * @see <a href="http://www.unidata.ucar.edu/software/netcdf-java/formats/DataDiscoveryAttConvention.html#time_coverage_start_Attribute">UCAR reference</a>
+     * @see <a href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#time_coverage_start">ESIP reference</a>
      */
     public static final Dimension TIME = new Dimension(DimensionNameType.TIME,
             ACDD.TIME_START, ACDD.TIME_END, ACDD.TIME_DURATION, ACDD.TIME_RESOLUTION, "time_coverage_units", null);



Mime
View raw message