sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1482413 - in /sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis: internal/netcdf/ internal/netcdf/ucar/ storage/netcdf/
Date Tue, 14 May 2013 15:59:36 GMT
Author: desruisseaux
Date: Tue May 14 15:59:36 2013
New Revision: 1482413

URL: http://svn.apache.org/r1482413
Log:
Better separation of concerns: moved some code out of "internal.ucar" in order
to leave only UCAR-specific code (as much as possible) in "internal.ucar".

Added:
    sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java   (with props)
    sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/GridGeometry.java   (with props)
    sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridGeometryWrapper.java
      - copied, changed from r1482262, sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/CRSBuilder.java
Removed:
    sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/CRSBuilder.java
Modified:
    sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java
    sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java
    sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/package-info.java
    sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java
    sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/AttributeNames.java
    sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java

Added: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java?rev=1482413&view=auto
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java (added)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java [UTF-8] Tue May 14 15:59:36 2013
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.netcdf;
+
+import org.apache.sis.util.ArraysExt;
+import org.apache.sis.storage.netcdf.AttributeNames;
+
+
+/**
+ * Information about a coordinate system axes. In NetCDF files, all axes can be related to 1 or more dimensions
+ * of the grid domain. Those grid domain dimensions are specified by the {@link #sourceDimensions} array.
+ * Whether the array length is 1 or 2 depends on whether the wrapped NetCDF axis is an instance of
+ * {@link ucar.nc2.dataset.CoordinateAxis1D} or {@link ucar.nc2.dataset.CoordinateAxis2D} respectively.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3
+ * @version 0.3
+ * @module
+ *
+ * @see GridGeometry#getAxes()
+ */
+public final class Axis {
+    /**
+     * The attributes to use for fetching dimension (in ISO-19115 sense) information, or {@code null} if unknown.
+     */
+    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.
+     *
+     * {@section Elements order}
+     * 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).
+     */
+    public final int[] sourceDimensions;
+
+    /**
+     * The number of cell elements along the source grid dimensions. The length of this array shall be
+     * equals to the {@link #sourceDimensions} length. For each element, {@code sourceSizes[i]} shall
+     * be equals to the number of grid cells in the grid dimension at index {@code sourceDimensions[i]}.
+     */
+    public final int[] sourceSizes;
+
+    /**
+     * Constructs a new axis associated to no grid dimension.
+     * Actually this should never happen, but we try to be safe.
+     *
+     * @param attributeNames The attributes to use for fetching dimension information, or {@code null} if unknown.
+     */
+    public Axis(final AttributeNames.Dimension attributeNames) {
+        this.attributeNames   = attributeNames;
+        this.sourceDimensions = ArraysExt.EMPTY_INT;
+        this.sourceSizes      = ArraysExt.EMPTY_INT;
+    }
+
+    /**
+     * Constructs a new axis associated to a single grid dimension.
+     *
+     * @param attributeNames The attributes to use for fetching dimension information, or {@code null} if unknown.
+     * @param sourceDim      The index of the grid dimension associated to this axis.
+     * @param sourceSize     The number of cell elements along that axis.
+     */
+    public Axis(final AttributeNames.Dimension attributeNames, final int sourceDim, final int sourceSize) {
+        this.attributeNames   = attributeNames;
+        this.sourceDimensions = new int[] {sourceDim};
+        this.sourceSizes      = new int[] {sourceSize};
+    }
+
+    /**
+     * Constructs a new axis associated to exactly two grid dimensions.
+     * This constructor will detects by itself which grid dimension varies fastest.
+     *
+     * @param attributeNames The attributes to use for fetching dimension information, or {@code null} if unknown.
+     * @param sourceDim1     The index of a first grid dimension associated to this axis.
+     * @param sourceSize1    The number of cell elements along the first grid dimension.
+     * @param sourceDim2     The index of a second grid dimension associated to this axis.
+     * @param sourceSize2    The number of cell elements along the second grid dimension.
+     * @param toTarget       The conversion from grid coordinates to geodetic coordinates.
+     */
+    public Axis(final AttributeNames.Dimension attributeNames,
+                final int sourceDim1, final int sourceSize1,
+                final int sourceDim2, final int sourceSize2,
+                final GridGeometry toTarget)
+    {
+        this.attributeNames = attributeNames;
+        final int mid1 = sourceSize1 / 2;
+        final int mid2 = sourceSize2 / 2;
+        final double d1 = (toTarget.coordinateForCurrentAxis(0, mid2) - toTarget.coordinateForCurrentAxis(sourceSize1-1, mid2)) / sourceSize1;
+        final double d2 = (toTarget.coordinateForCurrentAxis(mid1, 0) - toTarget.coordinateForCurrentAxis(mid1, sourceSize2-1)) / sourceSize2;
+        if (Math.abs(d2) > Math.abs(d1)) {
+            sourceDimensions  = new int[] {sourceDim2,  sourceDim1};
+            sourceSizes       = new int[] {sourceSize2, sourceSize1};
+        } else {
+            sourceDimensions = new int[] {sourceDim1,  sourceDim2};
+            sourceSizes      = new int[] {sourceSize1, sourceSize2};
+        }
+    }
+
+    /**
+     * Constructs a new axis associated to an arbitrary number of grid dimension.
+     * Current implementation does not try to identify the "main" dimension
+     * (we may try to improve that in a future SIS version).
+     *
+     * @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.
+     */
+    public Axis(final AttributeNames.Dimension attributeNames, final int[] sourceDimensions, final int[] sourceSizes) {
+        this.attributeNames   = attributeNames;
+        this.sourceDimensions = sourceDimensions;
+        this.sourceSizes      = sourceSizes;
+    }
+}

Propchange: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java?rev=1482413&r1=1482412&r2=1482413&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java [UTF-8] Tue May 14 15:59:36 2013
@@ -21,7 +21,6 @@ import java.util.List;
 import java.io.IOException;
 import javax.measure.unit.Unit;
 import org.apache.sis.measure.Units;
-import org.apache.sis.metadata.iso.DefaultMetadata;
 
 
 /**
@@ -155,10 +154,10 @@ public abstract class Decoder extends Wa
     public abstract List<Variable> getVariables() throws IOException;
 
     /**
-     * Adds the spatial information inferred from the the NetCDF {@code CoordinateSystem} objects.
+     * Returns all grid geometries (related to coordinate systems) found in the NetCDF file.
      *
-     * @param  metadata Where to add the spatial information.
+     * @return All grid geometries, or an empty list if none.
      * @throws IOException If an I/O operation was necessary but failed.
      */
-    public abstract void addSpatialRepresentationInfo(DefaultMetadata metadata) throws IOException;
+    public abstract List<GridGeometry> getGridGeometries() throws IOException;
 }

Added: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/GridGeometry.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/GridGeometry.java?rev=1482413&view=auto
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/GridGeometry.java (added)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/GridGeometry.java [UTF-8] Tue May 14 15:59:36 2013
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.netcdf;
+
+import java.util.List;
+
+
+/**
+ * Information about the grid geometry and the conversion from grid coordinates to geodetic coordinates.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3
+ * @version 0.3
+ * @module
+ */
+public abstract class GridGeometry extends WarningProducer {
+    /**
+     * Constructs a new conversion information.
+     *
+     * @param parent Where to send the warnings, or {@code null} if none.
+     */
+    protected GridGeometry(final WarningProducer parent) {
+        super(parent);
+    }
+
+    /**
+     * 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.
+     *
+     * @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()}.
+     *
+     * @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.
+     *
+     * @return The CRS axes.
+     */
+    public abstract List<Axis> getAxes();
+
+    /**
+     * 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)}.
+     *
+     * @param  j The fastest varying (right-most) index.
+     * @param  i The slowest varying (left-most) index.
+     * @return The coordinate at the given index.
+     */
+    protected abstract double coordinateForCurrentAxis(final int j, final int i);
+}

Propchange: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/GridGeometry.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/GridGeometry.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java?rev=1482413&r1=1482412&r2=1482413&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java [UTF-8] Tue May 14 15:59:36 2013
@@ -56,6 +56,7 @@ public abstract class Variable {
     /**
      * Returns the name of the variable data type as the name of the primitive type
      * followed by the span of each dimension (in unit of grid cells) between brackets.
+     * Example: {@code "short[180][360]"}.
      *
      * @return The name of the variable data type.
      */

Modified: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/package-info.java?rev=1482413&r1=1482412&r2=1482413&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/package-info.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/package-info.java [UTF-8] Tue May 14 15:59:36 2013
@@ -27,6 +27,16 @@
  * its raw format, while the UCAR high level API provides the values converted by the offset and scale
  * factors.</p>
  *
+ * <p>A side effect of this isolation layer is also to adapt NetCDF vocabulary to Apache SIS one.
+ * For example what NetCDF calls "<cite>coordinate system</cite>" is actually a mix of what OGC/ISO
+ * specifications call "<cite>coordinate system</cite>", "<cite>coordinate reference system</cite>"
+ * and "<cite>grid geometry</cite>". The NetCDF coordinate system "<cite>range</cite>" is closer to
+ * ISO 19123 "<cite>domain</cite>", the NetCDF coordinate system "<cite>domain</cite>" is closer to
+ * ISO 19123 "<cite>grid envelope</cite>" and the ISO 19123 "<cite>range</cite>" is rather related
+ * to the NetCDF variable minimum and maximum values. Trying to use OGC/ISO and NetCDF objects in
+ * the same code appears to be <strong>very</strong> confusing. This isolation layer allows our code
+ * use a more consistent vocabulary (compared to the rest of Apache SIS).</p>
+ *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.3
  * @version 0.3

Modified: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java?rev=1482413&r1=1482412&r2=1482413&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java [UTF-8] Tue May 14 15:59:36 2013
@@ -19,35 +19,25 @@ package org.apache.sis.internal.netcdf.u
 import java.util.Date;
 import java.util.List;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.EnumSet;
-import java.util.Map;
 import java.io.IOException;
 import ucar.nc2.Group;
 import ucar.nc2.Attribute;
 import ucar.nc2.VariableIF;
 import ucar.nc2.NetcdfFile;
 import ucar.nc2.dataset.NetcdfDataset;
-import ucar.nc2.dataset.CoordinateAxis;
 import ucar.nc2.dataset.CoordinateSystem;
-import ucar.nc2.constants.AxisType;
 import ucar.nc2.units.DateUnit;
 import ucar.nc2.time.Calendar;
 import ucar.nc2.time.CalendarDate;
 import ucar.nc2.time.CalendarDateFormatter;
-
-import org.opengis.metadata.spatial.CellGeometry;
-import org.opengis.metadata.spatial.GridSpatialRepresentation;
-
 import org.apache.sis.util.ArraysExt;
-import org.apache.sis.metadata.iso.DefaultMetadata;
-import org.apache.sis.metadata.iso.spatial.DefaultDimension;
-import org.apache.sis.metadata.iso.spatial.DefaultGridSpatialRepresentation;
 import org.apache.sis.internal.netcdf.Decoder;
 import org.apache.sis.internal.netcdf.Variable;
+import org.apache.sis.internal.netcdf.GridGeometry;
 import org.apache.sis.internal.netcdf.WarningProducer;
 
-import static org.apache.sis.storage.netcdf.AttributeNames.*;
-
 
 /**
  * Provides NetCDF decoding services based on the NetCDF library.
@@ -278,12 +268,13 @@ public final class DecoderWrapper extend
 
     /**
      * Returns all variables found in the NetCDF file.
-     *
-     * @return All variables, or an empty list if none.
      */
     @Override
     public List<Variable> getVariables() {
         final List<? extends VariableIF> all = file.getVariables();
+        if (all == null) {
+            return Collections.emptyList();
+        }
         final List<Variable> variables = new ArrayList<>(all.size());
         for (final VariableIF variable : all) {
             variables.add(new VariableWrapper(variable, all));
@@ -292,71 +283,25 @@ public final class DecoderWrapper extend
     }
 
     /**
-     * Adds the spatial information inferred from the the NetCDF {@link CoordinateSystem} objects.
+     * Returns all grid geometries (related to coordinate systems) found in the NetCDF file.
      */
     @Override
-    public void addSpatialRepresentationInfo(final DefaultMetadata metadata) throws IOException {
+    public List<GridGeometry> getGridGeometries() throws IOException {
         if (file instanceof NetcdfDataset) {
             final NetcdfDataset ds = (NetcdfDataset) file;
             final EnumSet<NetcdfDataset.Enhance> mode = EnumSet.copyOf(ds.getEnhanceMode());
             if (mode.add(NetcdfDataset.Enhance.CoordSystems)) {
                 ds.enhance(mode);
             }
-            for (final CoordinateSystem cs : ds.getCoordinateSystems()) {
-                if (cs.getRankDomain() >= Variable.MIN_DIMENSION && cs.getRankRange() >= Variable.MIN_DIMENSION) {
-                    metadata.getSpatialRepresentationInfo().add(createSpatialRepresentationInfo(cs));
+            final List<CoordinateSystem> systems = ds.getCoordinateSystems();
+            if (systems != null) {
+                final List<GridGeometry> geometries = new ArrayList<>(systems.size());
+                for (final CoordinateSystem cs : systems) {
+                    geometries.add(new GridGeometryWrapper(this, cs));
                 }
+                return geometries;
             }
         }
-    }
-
-    /**
-     * Creates a {@code <gmd:spatialRepresentationInfo>} element from the given NetCDF coordinate system.
-     *
-     * @param  cs The NetCDF coordinate system.
-     * @return The grid spatial representation info.
-     * @throws IOException If an I/O operation was necessary but failed.
-     */
-    @SuppressWarnings("fallthrough")
-    private GridSpatialRepresentation createSpatialRepresentationInfo(final CoordinateSystem cs) throws IOException {
-        final DefaultGridSpatialRepresentation grid = new DefaultGridSpatialRepresentation();
-        grid.setNumberOfDimensions(cs.getRankDomain());
-        final CRSBuilder builder = new CRSBuilder(this, cs);
-        for (final Map.Entry<ucar.nc2.Dimension, CoordinateAxis> entry : builder.getAxesDomain().entrySet()) {
-            final CoordinateAxis axis = entry.getValue();
-            final int i = axis.getDimensions().indexOf(entry.getKey());
-            Dimension rsat = null;
-            Double resolution = null;
-            final AxisType at = axis.getAxisType();
-            if (at != null) {
-                boolean valid = false;
-                switch (at) {
-                    case Lon:      valid = true; // fallthrough
-                    case GeoX:     rsat  = LONGITUDE; break;
-                    case Lat:      valid = true; // fallthrough
-                    case GeoY:     rsat  = LATITUDE; break;
-                    case Height:   valid = true; // fallthrough
-                    case GeoZ:
-                    case Pressure: rsat  = VERTICAL; break;
-                    case Time:     valid = true; // fallthrough
-                    case RunTime:  rsat  = TIME; break;
-                }
-                if (valid) {
-                    final Number res = numericValue(rsat.RESOLUTION);
-                    if (res != null) {
-                        resolution = (res instanceof Double) ? (Double) res : res.doubleValue();
-                    }
-                }
-            }
-            final DefaultDimension dimension = new DefaultDimension();
-            if (rsat != null) {
-                dimension.setDimensionName(rsat.DEFAULT_NAME_TYPE);
-                dimension.setResolution(resolution);
-            }
-            dimension.setDimensionSize(axis.getShape(i));
-            grid.getAxisDimensionProperties().add(dimension);
-        }
-        grid.setCellGeometry(CellGeometry.AREA);
-        return grid;
+        return Collections.emptyList();
     }
 }

Copied: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridGeometryWrapper.java (from r1482262, sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/CRSBuilder.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridGeometryWrapper.java?p2=sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridGeometryWrapper.java&p1=sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/CRSBuilder.java&r1=1482262&r2=1482413&rev=1482413&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/CRSBuilder.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridGeometryWrapper.java [UTF-8] Tue May 14 15:59:36 2013
@@ -16,47 +16,41 @@
  */
 package org.apache.sis.internal.netcdf.ucar;
 
+import java.util.List;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-
 import ucar.nc2.Dimension;
+import ucar.nc2.constants.AxisType;
 import ucar.nc2.dataset.CoordinateAxis;
-import ucar.nc2.dataset.CoordinateAxis1D;
 import ucar.nc2.dataset.CoordinateAxis2D;
 import ucar.nc2.dataset.CoordinateSystem;
-
-import org.apache.sis.util.resources.Errors;
+import org.apache.sis.internal.netcdf.Axis;
+import org.apache.sis.internal.netcdf.GridGeometry;
 import org.apache.sis.internal.netcdf.WarningProducer;
-
-import static org.apache.sis.util.collection.Containers.isNullOrEmpty;
-import static org.apache.sis.util.collection.Containers.hashMapCapacity;
+import org.apache.sis.storage.netcdf.AttributeNames;
 
 
 /**
- * Information about NetCDF coordinate system.
+ * Information about NetCDF coordinate system, which include information about grid geometries.
+ * In OGC/ISO specifications, the coordinate system and the grid geometries are distinct entities.
+ * However the UCAR model takes a different point of view where the coordinate system holds some
+ * of the grid geometry information.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3 (derived from geotk-3.14)
  * @version 0.3
  * @module
  */
-final class CRSBuilder extends WarningProducer {
+final class GridGeometryWrapper extends GridGeometry {
     /**
      * The NetCDF coordinate system to wrap.
      */
     private final CoordinateSystem netcdfCS;
 
     /**
-     * The coordinate axes in natural (reverse of NetCDF) order, or {@code null} for inferring
-     * it from the {@link #netcdfCS}.
+     * A temporary variable for {@link #coordinateForCurrentAxis(int, int)}.
      */
-    private List<CoordinateAxis> axes;
+    private transient CoordinateAxis2D axis2D;
 
     /**
      * Creates a new CRS builder.
@@ -64,186 +58,111 @@ final class CRSBuilder extends WarningPr
      * @param parent Where to send the warnings, or {@code null} if none.
      * @param cs The NetCDF coordinate system, or {@code null} if none.
      */
-    CRSBuilder(final WarningProducer parent, final CoordinateSystem cs) {
+    GridGeometryWrapper(final WarningProducer parent, final CoordinateSystem cs) {
         super(parent);
         netcdfCS = cs;
     }
 
     /**
-     * Ensures that the given value is defined.
+     * Returns the number of dimensions in the grid.
      */
-    private static void ensureDefined(final String name, final Object value) throws IllegalStateException {
-        if (value == null) {
-            throw new IllegalStateException(Errors.format(Errors.Keys.MissingValueForProperty_1, name));
-        }
+    @Override
+    public int getSourceDimensions() {
+        return netcdfCS.getRankDomain();
     }
 
     /**
-     * Returns the NetCDF coordinate axes in natural (reverse of NetCDF) order. The returned list is
-     * usually the NetCDF {@linkplain CoordinateSystem#getCoordinateAxes() coordinate axes} list in
-     * the reverse order.
-     *
-     * <p>By default, the returned list is modifiable. Any changes in the content of this list will
-     * be reflected in the wrappers to be {@linkplain #build() build}. This is useful if the caller
-     * wants to modify the axis order, as in the example below:</p>
-     *
-     * {@preformat java
-     *     builder.setCoordinateSystem(...);
-     *     Collection.sort(builder.getCoordinateAxes(), new CoordinateAxis.AxisComparator());
-     * }
-     *
-     * @return The NetCDF coordinate axis in natural order (reverse of NetCDF order),
-     *         or {@code null} if unknown.
-     *
-     * @see ucar.nc2.dataset.CoordinateAxis.AxisComparator
+     * Returns the number of dimensions in the coordinate reference system.
      */
-    private List<CoordinateAxis> getCoordinateAxes() {
-        if (axes == null && netcdfCS != null) {
-            Collections.reverse(axes = new ArrayList<>(netcdfCS.getCoordinateAxes()));
-        }
-        return axes;
+    @Override
+    public int getTargetDimensions() {
+        return netcdfCS.getRankRange();
     }
 
     /**
-     * Returns the dimensions of all axes, together with an axis associated to each dimension.
-     * If more than one axis use the same dimension, then the first axis has precedence.
+     * Returns all axes of the NetCDF coordinate system, together with the grid dimension to which the axis
+     * is associated.
      *
-     * <p>The domain of all axes (or the {@linkplain CoordinateSystem#getDomain() coordinate system
-     * domain}) is often the same than the {@linkplain #getDomain() 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 All axis dimensions associated to their originating axis.
-     * @throws IllegalStateException If the {@linkplain #getCoordinateAxes() coordinate axes}
-     *         are not defined.
-     *
-     * @see CoordinateAxis#getDimensions()
-     */
-    public Map<Dimension,CoordinateAxis> getAxesDomain() throws IllegalStateException {
-        final List<CoordinateAxis> axes = getCoordinateAxes();
-        ensureDefined("axes", axes);
-        final Map<Dimension,CoordinateAxis> map = new LinkedHashMap<>(hashMapCapacity(axes.size()));
-        /*
-         * Stores all dimensions in the map, together with an arbitrary axis. If there is no
-         * conflict, we are done. If there is conflicts, then the first one-dimensional axis
-         * (if any) will have precedence over all other axes for that dimension. If the conflict
-         * involves only axes having 2 or more dimensions, then we will defer their handling
-         * to a later stage.
-         */
-        Map<Dimension, Set<CoordinateAxis>> conflicts = null;
-        for (final CoordinateAxis axis : axes) {
-            final int rank = axis.getRank();
-            for (int i=rank; --i>=0;) {
-                final Dimension dimension = axis.getDimension(i);
-                final CoordinateAxis previous = map.put(dimension, axis);
-                if (previous != null) {
-                    final int pr = previous.getRank();
-                    if (pr != 1 && rank != 1) {
-                        /*
-                         * Found a conflict (two axes using the same dimension) that can not be
-                         * resolved before the loop completion. Remember this conflict in order
-                         * to process it later.
-                         */
-                        if (conflicts == null) {
-                            conflicts = new HashMap<>(4);
-                        }
-                        Set<CoordinateAxis> deferred = conflicts.get(dimension);
-                        if (deferred == null) {
-                            deferred = new LinkedHashSet<>(4);
-                            conflicts.put(dimension, deferred);
-                        }
-                        deferred.add(previous);
-                        deferred.add(axis);
-                    } else {
-                        /*
-                         * The conflict can be resolved by giving precedence to a one-dimensional
-                         * axis and discart the other.
-                         */
-                        if (pr == 1) {
-                            map.put(dimension, previous);
-                        }
-                        if (conflicts != null) {
-                            conflicts.remove(dimension);
-                        }
-                    }
-                }
+     * <p>The domain of all axes (or the {@linkplain CoordinateSystem#getDomain() coordinate system domain})
+     * is often the same than the {@linkplain #getDomain() domain of the variable}, but not necessarily.
+     * In particular, the relationship is not straightforward when the coordinate system contains instances
+     * of {@link CoordinateAxis2D}.</p>
+     */
+    @Override
+    @SuppressWarnings("fallthrough")
+    public List<Axis> getAxes() {
+        final List<Dimension> sourceDimensions = netcdfCS.getDomain();
+        final List<CoordinateAxis> netcdfAxes = netcdfCS.getCoordinateAxes();
+        final List<Axis> axes = new ArrayList<>(netcdfAxes.size());
+        for (final CoordinateAxis netcdfAxis : netcdfAxes) {
+            final List<Dimension> dimensions = netcdfAxis.getDimensions();
+            AttributeNames.Dimension attributeNames = null;
+            final AxisType type = netcdfAxis.getAxisType();
+            if (type != null) switch (type) {
+                case Lon:      attributeNames = AttributeNames.LONGITUDE; break;
+                case Lat:      attributeNames = AttributeNames.LATITUDE; break;
+                case Pressure: // Fallthrough: consider as Height
+                case Height:   attributeNames = AttributeNames.VERTICAL; break;
+                case RunTime:  // Fallthrough: consider as Time
+                case Time:     attributeNames = AttributeNames.TIME; break;
             }
-        }
-        /*
-         * At this point the map is fully build, but some values may be inaccurate if conflicts
-         * exist. In such cases, we will first checks if there is any axis that can be assigned
-         * to only one dimension, because all other dimensions are not available anymore.
-         */
-redo:   while (!isNullOrEmpty(conflicts)) {
-            for (final Map.Entry<Dimension,Set<CoordinateAxis>> entry : conflicts.entrySet()) {
-                final Dimension dimension = entry.getKey();
-otherAxis:      for (final CoordinateAxis axis : entry.getValue()) {
-                    for (int i=axis.getRank(); --i>=0;) {
-                        final Dimension candidate = axis.getDimension(i);
-                        if (candidate != dimension && conflicts.containsKey(candidate)) {
-                            // Axis can be assigned to 2 or more dimensions. Search an other one.
-                            continue otherAxis;
-                        }
+            final Axis axis;
+            switch (dimensions.size()) {
+                case 0: {
+                    // Should never happen, but defined by paranoia.
+                    axis = new Axis(attributeNames);
+                    break;
+                }
+                case 1: {
+                    // The most common case where one source axis == one target axis.
+                    final Dimension dim = dimensions.get(0);
+                    axis = new Axis(attributeNames,
+                            sourceDimensions.indexOf(dim), dim.getLength());
+                    break;
+                }
+                case 2: {
+                    // An other case managed by the UCAR API.
+                    if (netcdfAxis instanceof CoordinateAxis2D) {
+                        axis2D = (CoordinateAxis2D) netcdfAxis;
+                        final CoordinateAxis2D a2 = (CoordinateAxis2D) netcdfAxis;
+                        final Dimension dim0 = dimensions.get(0);
+                        final Dimension dim1 = dimensions.get(1);
+                        axis = new Axis(attributeNames,
+                                sourceDimensions.indexOf(dim0), dim0.getLength(),
+                                sourceDimensions.indexOf(dim1), dim1.getLength(),
+                                this);
+                        break;
                     }
-                    /*
-                     * If we reach this point, then this axis can be associated only
-                     * to the current dimension; no other dimension are available.
-                     */
-                    conflicts.remove(dimension);
-                    map.put(dimension, axis);
-                    continue redo; // Maybe some axes prior to this one can now be processed.
+                    // Fallthrough: use the generic case as a fallback.
                 }
-            }
-            /*
-             * If we reach this point, we have not been able to process any axis.
-             * Pickup what seems the "main" dimension according an arbitrary rule.
-             */
-            for (final Set<CoordinateAxis> as : conflicts.values()) {
-                for (final CoordinateAxis axis : as) {
-                    final Dimension dimension = axis.getDimension(findMainDimensionOf(axis));
-                    if (conflicts.remove(dimension) != null) {
-                        map.put(dimension, axis);
-                        for (final Set<CoordinateAxis> toClean : conflicts.values()) {
-                            toClean.remove(axis);
-                        }
-                        continue redo; // Maybe some other axes can now be processed.
+                default: {
+                    // Uncommon case.
+                    final int[] indices = new int[dimensions.size()];
+                    final int[] sizes   = new int[indices.length];
+                    for (int i=indices.length; --i>=0;) {
+                        final Dimension dimension = dimensions.get(i);
+                        indices[i] = sourceDimensions.indexOf(dimension);
+                        sizes[i] = dimension.getLength();
                     }
+                    axis = new Axis(attributeNames, indices, sizes);
+                    break;
                 }
             }
-            /*
-             * If we reach this point, there is no "main" dimension available. Such case should
-             * never happen for two-dimensional axes, but could happen for axes having three or
-             * more dimensions. Such axes do not exist in the NetCDF API at the time of writting,
-             * but if they appear in a future version there is where we should complete the code.
-             */
-            throw new UnsupportedOperationException();
         }
-        return map;
+        /*
+         * NetCDF files define the axes in reverse order.
+         * Retores them in "natural" order.
+         */
+        Collections.reverse(axes);
+        return axes;
     }
 
     /**
-     * Returns the index of what seems to be the "main" dimension of the given coordinate axis.
-     * For {@link CoordinateAxis1D}, the returned index is trivially 0 in all cases.
-     * For {@link CoordinateAxis2D}, the default implementation returns the index (0 or 1)
-     * of the dimension for which the largest increment is found.
-     *
-     * <p>This method affects the sort performed by {@link #sortAxesAccordingDomain()}.</p>
-     *
-     * @param  axis The axis for which to get the index of the "main" dimension.
-     * @return Index of the axis dimension having the largest increment.
+     * 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()}.
      */
-    private static int findMainDimensionOf(final CoordinateAxis axis) {
-        int main = 0;
-        if (axis instanceof CoordinateAxis2D) {
-            final CoordinateAxis2D a2 = (CoordinateAxis2D) axis;
-            final int    si = a2.getShape(0);
-            final int    sj = a2.getShape(1);
-            final double di = Math.abs(a2.getCoordValue(0, sj >>> 1) - a2.getCoordValue(si-1, sj >>> 1)) / si;
-            final double dj = Math.abs(a2.getCoordValue(si >>> 1, 0) - a2.getCoordValue(si >>> 1, sj-1)) / sj;
-            if (dj > di) {
-                main = 1;
-            }
-        }
-        return main;
+    @Override
+    protected double coordinateForCurrentAxis(final int j, final int i) {
+        return axis2D.getCoordValue(j, i);
     }
 }

Modified: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/AttributeNames.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/AttributeNames.java?rev=1482413&r1=1482412&r2=1482413&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/AttributeNames.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/AttributeNames.java [UTF-8] Tue May 14 15:59:36 2013
@@ -61,45 +61,70 @@ import org.opengis.metadata.extent.Geogr
  *
  * The attributes recognized by SIS are listed below:
  *
- * <p>{@value #ACCESS_CONSTRAINT}, {@value #ACKNOWLEDGMENT}, {@value #COMMENT},
- * {@linkplain #CONTRIBUTOR "contributor_email"},
- * {@linkplain #CONTRIBUTOR "contributor_name"},
- * {@linkplain #CONTRIBUTOR "contributor_role"},
- * {@linkplain #CONTRIBUTOR "contributor_url"},
- * {@linkplain #CREATOR     "creator_email"},
- * {@linkplain #CREATOR     "creator_name"},
- * {@linkplain #CREATOR     "creator_url"},
- * {@value #DATA_TYPE}, {@value #DATE_CREATED}, {@value #DATE_ISSUED}, {@value #DATE_MODIFIED},
- * {@value #FLAG_MASKS}, {@value #FLAG_MEANINGS}, {@value #FLAG_NAMES}, {@value #FLAG_VALUES},
- * {@linkplain #TITLE "full_name"},
- * {@linkplain #GEOGRAPHIC_IDENTIFIER "geographic_identifier"},
- * {@linkplain #LATITUDE  "geospatial_lat_max"},
- * {@linkplain #LATITUDE  "geospatial_lat_min"},
- * {@linkplain #LATITUDE  "geospatial_lat_resolution"},
- * {@linkplain #LATITUDE  "geospatial_lat_units"},
- * {@linkplain #LONGITUDE "geospatial_lon_max"},
- * {@linkplain #LONGITUDE "geospatial_lon_min"},
- * {@linkplain #LONGITUDE "geospatial_lon_resolution"},
- * {@linkplain #LONGITUDE "geospatial_lon_units"},
- * {@linkplain #VERTICAL  "geospatial_vertical_max"},
- * {@linkplain #VERTICAL  "geospatial_vertical_min"},
- * {@linkplain #VERTICAL  "geospatial_vertical_positive"},
- * {@linkplain #VERTICAL  "geospatial_vertical_resolution"},
- * {@linkplain #VERTICAL  "geospatial_vertical_units"},
- * {@value #HISTORY}, {@value #IDENTIFIER}, {@linkplain #CREATOR "institution"}, {@value #KEYWORDS},
- * {@value #LICENSE}, {@value #METADATA_CREATION}, {@linkplain #TITLE "name"}, {@value #NAMING_AUTHORITY},
- * {@value #PROCESSING_LEVEL}, {@value #PROJECT},
- * {@linkplain #PUBLISHER "publisher_email"},
- * {@linkplain #PUBLISHER "publisher_name"},
- * {@linkplain #PUBLISHER "publisher_url"},
- * {@value #PURPOSE}, {@value #REFERENCES}, {@value #STANDARD_NAME},
- * {@value #STANDARD_NAME_VOCABULARY}, {@value #SUMMARY},
- * {@linkplain #TIME "time_coverage_duration"},
- * {@linkplain #TIME "time_coverage_end"},
- * {@linkplain #TIME "time_coverage_resolution"},
- * {@linkplain #TIME "time_coverage_start"},
- * {@linkplain #TIME "time_coverage_units"},
- * {@value #TITLE}, {@value #TOPIC_CATEGORY} and {@value #VOCABULARY}.</p>
+ * <table class="compact"><tr valign="top" width="25%"><td>
+ * {@value     #ACCESS_CONSTRAINT}<br>
+ * {@value     #ACKNOWLEDGMENT}<br>
+ * {@value     #COMMENT}<br>
+ * {@linkplain #CONTRIBUTOR "contributor_email"}<br>
+ * {@linkplain #CONTRIBUTOR "contributor_name"}<br>
+ * {@linkplain #CONTRIBUTOR "contributor_role"}<br>
+ * {@linkplain #CONTRIBUTOR "contributor_url"}<br>
+ * {@linkplain #CREATOR     "creator_email"}<br>
+ * {@linkplain #CREATOR     "creator_name"}<br>
+ * {@linkplain #CREATOR     "creator_url"}<br>
+ * {@value     #DATA_TYPE}<br>
+ * {@value     #DATE_CREATED}<br>
+ * {@value     #DATE_ISSUED}<br>
+ * {@value     #DATE_MODIFIED}<br>
+ * {@value     #FLAG_MASKS}<br>
+ * {@value     #FLAG_MEANINGS}<br>
+ * {@value     #FLAG_NAMES}<br>
+ * {@value     #FLAG_VALUES}<br>
+ * </td><td width="25%">
+ * {@linkplain #TITLE "full_name"}<br>
+ * {@linkplain #GEOGRAPHIC_IDENTIFIER "geographic_identifier"}<br>
+ * {@linkplain #LATITUDE  "geospatial_lat_max"}<br>
+ * {@linkplain #LATITUDE  "geospatial_lat_min"}<br>
+ * {@linkplain #LATITUDE  "geospatial_lat_resolution"}<br>
+ * {@linkplain #LATITUDE  "geospatial_lat_units"}<br>
+ * {@linkplain #LONGITUDE "geospatial_lon_max"}<br>
+ * {@linkplain #LONGITUDE "geospatial_lon_min"}<br>
+ * {@linkplain #LONGITUDE "geospatial_lon_resolution"}<br>
+ * {@linkplain #LONGITUDE "geospatial_lon_units"}<br>
+ * {@linkplain #VERTICAL  "geospatial_vertical_max"}<br>
+ * {@linkplain #VERTICAL  "geospatial_vertical_min"}<br>
+ * {@linkplain #VERTICAL  "geospatial_vertical_positive"}<br>
+ * {@linkplain #VERTICAL  "geospatial_vertical_resolution"}<br>
+ * {@linkplain #VERTICAL  "geospatial_vertical_units"}<br>
+ * </td><td width="25%">
+ * {@value     #HISTORY}<br>
+ * {@value     #IDENTIFIER}<br>
+ * {@linkplain #CREATOR "institution"}<br>
+ * {@value     #KEYWORDS}<br>
+ * {@value     #VOCABULARY}<br>
+ * {@value     #LICENSE}<br>
+ * {@value     #METADATA_CREATION}<br>
+ * {@linkplain #TITLE "name"}<br>
+ * {@value     #NAMING_AUTHORITY}<br>
+ * {@value     #PROCESSING_LEVEL}<br>
+ * {@value     #PROJECT}<br>
+ * {@linkplain #PUBLISHER "publisher_email"}<br>
+ * {@linkplain #PUBLISHER "publisher_name"}<br>
+ * {@linkplain #PUBLISHER "publisher_url"}<br>
+ * {@value     #PURPOSE}<br>
+ * {@value     #REFERENCES}<br>
+ * </td><td width="25%">
+ * {@value     #STANDARD_NAME}<br>
+ * {@value     #STANDARD_NAME_VOCABULARY}<br>
+ * {@value     #SUMMARY}<br>
+ * {@linkplain #TIME "time_coverage_duration"}<br>
+ * {@linkplain #TIME "time_coverage_end"}<br>
+ * {@linkplain #TIME "time_coverage_resolution"}<br>
+ * {@linkplain #TIME "time_coverage_start"}<br>
+ * {@linkplain #TIME "time_coverage_units"}<br>
+ * {@value     #TITLE}<br>
+ * {@value     #TOPIC_CATEGORY}<br>
+ * </td></tr></table>
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3 (derived from geotk-3.20)

Modified: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java?rev=1482413&r1=1482412&r2=1482413&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java [UTF-8] Tue May 14 15:59:36 2013
@@ -48,11 +48,10 @@ import org.opengis.referencing.crs.Verti
 import org.apache.sis.util.iso.Types;
 import org.apache.sis.util.iso.DefaultNameSpace;
 import org.apache.sis.util.iso.SimpleInternationalString;
-import org.apache.sis.internal.util.DefaultFactories;
-import org.apache.sis.internal.metadata.MetadataUtilities;
 import org.apache.sis.metadata.iso.DefaultMetadata;
 import org.apache.sis.metadata.iso.DefaultIdentifier;
 import org.apache.sis.metadata.iso.extent.*;
+import org.apache.sis.metadata.iso.spatial.*;
 import org.apache.sis.metadata.iso.content.*;
 import org.apache.sis.metadata.iso.citation.*;
 import org.apache.sis.metadata.iso.distribution.*;
@@ -60,9 +59,13 @@ import org.apache.sis.metadata.iso.ident
 import org.apache.sis.metadata.iso.lineage.DefaultLineage;
 import org.apache.sis.metadata.iso.quality.DefaultDataQuality;
 import org.apache.sis.metadata.iso.constraint.DefaultLegalConstraints;
+import org.apache.sis.internal.netcdf.Axis;
 import org.apache.sis.internal.netcdf.Decoder;
 import org.apache.sis.internal.netcdf.Variable;
+import org.apache.sis.internal.netcdf.GridGeometry;
 import org.apache.sis.internal.netcdf.WarningProducer;
+import org.apache.sis.internal.util.DefaultFactories;
+import org.apache.sis.internal.metadata.MetadataUtilities;
 
 // The following dependency is used only for static final String constants.
 // Consequently the compiled class files should not have this dependency.
@@ -572,6 +575,35 @@ final class MetadataReader extends Warni
     }
 
     /**
+     * Creates a {@code <gmd:spatialRepresentationInfo>} element from the given grid geometries.
+     *
+     * @param  cs The grid geometry (related to the NetCDF coordinate system).
+     * @return The grid spatial representation info.
+     * @throws IOException If an I/O operation was necessary but failed.
+     */
+    private GridSpatialRepresentation createSpatialRepresentationInfo(final GridGeometry cs) throws IOException {
+        final DefaultGridSpatialRepresentation grid = new DefaultGridSpatialRepresentation();
+        grid.setNumberOfDimensions(cs.getTargetDimensions());
+        for (final Axis axis : cs.getAxes()) {
+            if (axis.sourceDimensions.length != 0) {
+                final DefaultDimension dimension = new DefaultDimension();
+                dimension.setDimensionSize(axis.sourceSizes[0]);
+                final AttributeNames.Dimension attributeNames = axis.attributeNames;
+                if (attributeNames != null) {
+                    dimension.setDimensionName(attributeNames.DEFAULT_NAME_TYPE);
+                    final Number value = decoder.numericValue(attributeNames.RESOLUTION);
+                    if (value != null) {
+                        dimension.setResolution((value instanceof Double) ? (Double) value : value.doubleValue());
+                    }
+                }
+                grid.getAxisDimensionProperties().add(dimension);
+            }
+        }
+        grid.setCellGeometry(CellGeometry.AREA);
+        return grid;
+    }
+
+    /**
      * Returns the extent declared in the given group, or {@code null} if none. For more consistent results,
      * the caller should restrict the {@linkplain Decoder#setSearchPath search path} to a single group before
      * invoking this method.
@@ -883,7 +915,11 @@ final class MetadataReader extends Warni
          * Add the dimension information, if any. This metadata node
          * is built from the NetCDF CoordinateSystem objects.
          */
-        decoder.addSpatialRepresentationInfo(metadata);
+        for (final GridGeometry cs : decoder.getGridGeometries()) {
+            if (cs.getSourceDimensions() >= Variable.MIN_DIMENSION && cs.getTargetDimensions() >= Variable.MIN_DIMENSION) {
+                metadata.getSpatialRepresentationInfo().add(createSpatialRepresentationInfo(cs));
+            }
+        }
         return metadata;
     }
 }



Mime
View raw message