sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1762217 - in /sis/branches/JDK8: core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ core/sis-utility/src/main/java/org/apache/sis/util/resources/ storage/sis-netcdf/src/main/java/org/apache/sis/internal/net...
Date Sun, 25 Sep 2016 15:32:42 GMT
Author: desruisseaux
Date: Sun Sep 25 15:32:42 2016
New Revision: 1762217

URL: http://svn.apache.org/viewvc?rev=1762217&view=rev
Log:
Minor performance improvement in NetCDF reader by more extensive use of HashMap instead than iterating over all dimensions or variables.
Wraps array of primitive type into a org.apache.math.Vector object, which also allow us to take in account the unsigned types.
More progress in implementation of moving features NetCDF encoding (not yet finished).

Added:
    sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/NamedElement.java   (with props)
Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/EqualAreaProjection.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
    sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/DataType.java
    sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java
    sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java
    sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java
    sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/Dimension.java
    sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/FeaturesInfo.java
    sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/VariableInfo.java
    sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java
    sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java
    sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/DataTypeTest.java
    sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/VariableTest.java

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/EqualAreaProjection.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/EqualAreaProjection.java?rev=1762217&r1=1762216&r2=1762217&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/EqualAreaProjection.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/EqualAreaProjection.java [UTF-8] Sun Sep 25 15:32:42 2016
@@ -192,7 +192,7 @@ abstract class EqualAreaProjection exten
 
     /**
      * Computes the latitude using equation 3-18 from Synder, followed by iterative resolution of Synder 3-16.
-     * If theory, the series expansion given by equation 3-18 (φ ≈ c₂⋅sin(2β) + c₄⋅sin(4β) + c₈⋅sin(8β)) should
+     * In theory, the series expansion given by equation 3-18 (φ ≈ c₂⋅sin(2β) + c₄⋅sin(4β) + c₈⋅sin(8β)) should
      * be used in replacement of the iterative method. However in practice the series expansion seems to not
      * have a sufficient amount of terms for achieving the centimetric precision, so we "finish" it by the
      * iterative method. The series expansion is nevertheless useful for reducing the number of iterations.

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1762217&r1=1762216&r2=1762217&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] Sun Sep 25 15:32:42 2016
@@ -246,6 +246,11 @@ public final class Errors extends Indexe
         public static final short DependencyNotFound_3 = 235;
 
         /**
+         * Dimension “{2}” declared by attribute “{1}” is not found in the “{0}” file.
+         */
+        public static final short DimensionNotFound_3 = 238;
+
+        /**
          * The “{0}” file points to a directory instead of a regular file.
          */
         public static final short DirectoryNotExpected_1 = 165;
@@ -1062,6 +1067,11 @@ public final class Errors extends Indexe
         public static final short UnexpectedDimensionForCS_1 = 212;
 
         /**
+         * Variable “{1}” in file “{0}” has a dimension “{3}” while we expected “{2}”.
+         */
+        public static final short UnexpectedDimensionForVariable_4 = 239;
+
+        /**
          * Unexpected end of file while reading “{0}”.
          */
         public static final short UnexpectedEndOfFile_1 = 109;
@@ -1261,6 +1271,11 @@ public final class Errors extends Indexe
          * Value ‘{0}’ = {3} is invalid. Expected a value in the [{1} … {2}] range.
          */
         public static final short ValueOutOfRange_4 = 133;
+
+        /**
+         * Variable “{1}” is not found in the “{0}” file.
+         */
+        public static final short VariableNotFound_2 = 240;
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1762217&r1=1762216&r2=1762217&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] Sun Sep 25 15:32:42 2016
@@ -60,6 +60,7 @@ DatabaseError_2                   = Data
 DatumOriginShallBeDate            = Origin of temporal datum shall be a date.
 DeadThread_1                      = Thread \u201c{0}\u201d is dead.
 DependencyNotFound_3              = Operation \u201c{0}\u201d requires a \u201c{1}\u201d property, but no such property has been found in \u201c{2}\u201d.
+DimensionNotFound_3               = Dimension \u201c{2}\u201d declared by attribute \u201c{1}\u201d is not found in the \u201c{0}\u201d file.
 DirectoryNotExpected_1            = The \u201c{0}\u201d file points to a directory instead of a regular file.
 DisposedInstanceOf_1              = This instance of \u2018{0}\u2019 has been disposed.
 DuplicatedElement_1               = Element \u201c{0}\u201d is duplicated.
@@ -223,6 +224,7 @@ UnexpectedChange_1                = Unex
 UnexpectedCharactersAfter_2       = The \u201c{1}\u201d characters after \u201c{0}\u201d was unexpected.
 UnexpectedCharactersAtBound_4     = Text for \u2018{0}\u2019 was expected to {1,choice,0#begin|1#end} with \u201c{2}\u201d, but found \u201c{3}\u201d.
 UnexpectedDimensionForCS_1        = Unexpected dimension for a coordinate system of type \u2018{0}\u2019.
+UnexpectedDimensionForVariable_4  = Variable \u201c{1}\u201d in file \u201c{0}\u201d has a dimension \u201c{3}\u201d while we expected \u201c{2}\u201d.
 UnexpectedEndOfFile_1             = Unexpected end of file while reading \u201c{0}\u201d.
 UnexpectedEndOfString_1           = More characters were expected at the end of \u201c{0}\u201d.
 UnexpectedFileFormat_2            = File \u201c{1}\u201d seems to be encoded in an other format than {0}.
@@ -263,3 +265,4 @@ UnsupportedVersion_1              = Vers
 ValueAlreadyDefined_1             = A value is already defined for \u201c{0}\u201d.
 ValueNotGreaterThanZero_2         = Value \u2018{0}\u2019 = {1} is invalid. Expected a number greater than 0.
 ValueOutOfRange_4                 = Value \u2018{0}\u2019 = {3} is invalid. Expected a value in the [{1} \u2026 {2}] range.
+VariableNotFound_2                = Variable \u201c{1}\u201d is not found in the \u201c{0}\u201d file.

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1762217&r1=1762216&r2=1762217&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] Sun Sep 25 15:32:42 2016
@@ -57,6 +57,7 @@ DatabaseError_2                   = Erre
 DatumOriginShallBeDate            = L\u2019origine d\u2019un r\u00e9f\u00e9rentiel temporel doit \u00eatre une date.
 DeadThread_1                      = La t\u00e2che \u00ab\u202f{0}\u202f\u00bb est morte.
 DependencyNotFound_3              = L\u2019op\u00e9ration \u00ab\u202f{0}\u202f\u00bb n\u00e9cessite une propri\u00e9t\u00e9 \u00ab\u202f{1}\u202f\u00bb, mais cette propri\u00e9t\u00e9 n\u2019a pas \u00e9t\u00e9 trouv\u00e9e dans \u00ab\u202f{2}\u202f\u00bb.
+DimensionNotFound_3               = La dimension \u00ab\u202f{2}\u202f\u00bb d\u00e9clar\u00e9e par l\u2019attribut \u00ab\u202f{1}\u202f\u00bb n\u2019a pas \u00e9t\u00e9 trouv\u00e9e dans le fichier \u00ab\u202f{0}\u202f\u00bb.
 DirectoryNotExpected_1            = Le fichier \u00ab\u202f{0}\u202f\u00bb d\u00e9signe un r\u00e9pertoire plut\u00f4t qu\u2019un fichier r\u00e9gulier.
 DisposedInstanceOf_1              = Cette instance de \u2018{0}\u2019 a \u00e9t\u00e9 dispos\u00e9e.
 DuplicatedElement_1               = L\u2019\u00e9lement \u00ab\u202f{0}\u202f\u00bb est dupliqu\u00e9.
@@ -219,6 +220,7 @@ UnexpectedChange_1                = Chan
 UnexpectedCharactersAfter_2       = Les caract\u00e8res \u00ab\u202f{1}\u202f\u00bb apr\u00e8s \u00ab\u202f{0}\u202f\u00bb sont inattendus.
 UnexpectedCharactersAtBound_4     = Le texte pour \u2018{0}\u2019 devait {1,choice,0#commencer|1#finir} par \u00ab\u202f{2}\u202f\u00bb, mais on a trouv\u00e9 \u00ab\u202f{3}\u202f\u00bb.
 UnexpectedDimensionForCS_1        = Dimension inattendue pour un syst\u00e8me de coordonn\u00e9es de type \u2018{0}\u2019.
+UnexpectedDimensionForVariable_4  = La variable \u00ab\u202f{1}\u202f\u00bb dans le fichier  \u00ab\u202f{0}\u202f\u00bb a une dimension \u00ab\u202f{3}\u202f\u00bb alors qu\u2019on attendait \u00ab\u202f{2}\u202f\u00bb.
 UnexpectedEndOfFile_1             = Fin de fichier inattendue lors de la lecture de \u00ab\u202f{0}\u202f\u00bb.
 UnexpectedEndOfString_1           = D\u2019autres caract\u00e8res \u00e9taient attendus \u00e0 la fin du texte \u00ab\u202f{0}\u202f\u00bb.
 UnexpectedNumberOfComponents_3    = Il y a {2} composantes dans \u00ab\u202f{0}\u202f\u00bb alors qu\u2019on en attendait {1}.
@@ -259,3 +261,4 @@ UnsupportedVersion_1              = La v
 ValueAlreadyDefined_1             = Une valeur est d\u00e9j\u00e0 d\u00e9finie pour \u00ab\u202f{0}\u202f\u00bb.
 ValueNotGreaterThanZero_2         = La valeur \u2018{0}\u2019 = {1} n\u2019est pas valide. On attendait un nombre positif non-nul.
 ValueOutOfRange_4                 = La valeur \u2018{0}\u2019 = {3} est invalide. Une valeur dans la plage [{1} \u2026 {2}] \u00e9tait attendue.
+VariableNotFound_2                = La variable \u00ab\u202f{1}\u202f\u00bb n\u2019a pas \u00e9t\u00e9 trouv\u00e9e dans le fichier \u00ab\u202f{0}\u202f\u00bb.

Modified: sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/DataType.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/DataType.java?rev=1762217&r1=1762216&r2=1762217&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/DataType.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/DataType.java [UTF-8] Sun Sep 25 15:32:42 2016
@@ -26,8 +26,9 @@ import org.apache.sis.util.Numbers;
  * related to the NetCDF standard as below:
  *
  * <ul>
- *   <li>The NetCDF numerical code is the {@link #ordinal()} plus 1.</li>
- *   <li>The CDL reserved word is the {@link #name()} is lower case.</li>
+ *   <li>The NetCDF numerical code is the {@link #ordinal()}.</li>
+ *   <li>The CDL reserved word is the {@link #name()} is lower case,
+ *       except for {@link #UNKNOWN} which is not a valid CDL type.</li>
  * </ul>
  *
  * The unsigned data types are not defined in NetCDF classical version. However those data types
@@ -42,74 +43,79 @@ import org.apache.sis.util.Numbers;
  */
 public enum DataType {
     /**
+     * The enumeration for unknown data type. This is not a valid NetCDF type.
+     */
+    UNKNOWN(Numbers.OTHER, false, false, (byte) 0, DataBuffer.TYPE_UNDEFINED),
+
+    /**
      * 8 bits signed integer (NetCDF type 1).
      * Can be made unsigned by assigning the “_Unsigned” attribute to a NetCDF variable.
      */
-    BYTE(Numbers.BYTE, false, (byte) 7, DataBuffer.TYPE_BYTE),
+    BYTE(Numbers.BYTE, true, false, (byte) 7, DataBuffer.TYPE_BYTE),
 
     /**
      * Character type as unsigned 8 bits (NetCDF type 2).
      * Encoding can be specified by assigning the “_Encoding” attribute to a NetCDF variable.
      */
-    CHAR(Numbers.BYTE, true, (byte) 2, DataBuffer.TYPE_UNDEFINED),        // NOT Numbers.CHARACTER
+    CHAR(Numbers.BYTE, false, true, (byte) 2, DataBuffer.TYPE_UNDEFINED),        // NOT Numbers.CHARACTER
 
     /**
      * 16 bits signed integer (NetCDF type 3).
      */
-    SHORT(Numbers.SHORT, false, (byte) 8, DataBuffer.TYPE_SHORT),
+    SHORT(Numbers.SHORT, true, false, (byte) 8, DataBuffer.TYPE_SHORT),
 
     /**
      * 32 bits signed integer (NetCDF type 4).
      * This is also called "long", but that name is deprecated.
      */
-    INT(Numbers.INTEGER, false, (byte) 9, DataBuffer.TYPE_INT),
+    INT(Numbers.INTEGER, true, false, (byte) 9, DataBuffer.TYPE_INT),
 
     /**
      * 32 bits floating point number (NetCDF type 5)
      * This is also called "real".
      */
-    FLOAT(Numbers.FLOAT, false, (byte) 5, DataBuffer.TYPE_FLOAT),
+    FLOAT(Numbers.FLOAT, false, false, (byte) 5, DataBuffer.TYPE_FLOAT),
 
     /**
      * 64 bits floating point number (NetCDF type 6).
      */
-    DOUBLE(Numbers.DOUBLE, false, (byte) 6, DataBuffer.TYPE_DOUBLE),
+    DOUBLE(Numbers.DOUBLE, false, false, (byte) 6, DataBuffer.TYPE_DOUBLE),
 
     /**
      * 8 bits unsigned integer (NetCDF type 7).
      * Not available in NetCDF classic format.
      */
-    UBYTE(Numbers.BYTE, true, (byte) 1, DataBuffer.TYPE_BYTE),
+    UBYTE(Numbers.BYTE, true, true, (byte) 1, DataBuffer.TYPE_BYTE),
 
     /**
      * 16 bits unsigned integer (NetCDF type 8).
      * Not available in NetCDF classic format.
      */
-    USHORT(Numbers.SHORT, true, (byte) 3, DataBuffer.TYPE_USHORT),
+    USHORT(Numbers.SHORT, true, true, (byte) 3, DataBuffer.TYPE_USHORT),
 
     /**
      * 43 bits unsigned integer (NetCDF type 9).
      * Not available in NetCDF classic format.
      */
-    UINT(Numbers.INTEGER, true, (byte) 4, DataBuffer.TYPE_INT),
+    UINT(Numbers.INTEGER, true, true, (byte) 4, DataBuffer.TYPE_INT),
 
     /**
      * 64 bits signed integer (NetCDF type 10).
      * Not available in NetCDF classic format.
      */
-    INT64(Numbers.LONG, false, (byte) 11, DataBuffer.TYPE_UNDEFINED),
+    INT64(Numbers.LONG, true, false, (byte) 11, DataBuffer.TYPE_UNDEFINED),
 
     /**
      * 64 bits unsigned integer (NetCDF type 11).
      * Not available in NetCDF classic format.
      */
-    UINT64(Numbers.LONG, true, (byte) 10, DataBuffer.TYPE_UNDEFINED),
+    UINT64(Numbers.LONG, true, true, (byte) 10, DataBuffer.TYPE_UNDEFINED),
 
     /**
      * Character string (NetCDF type 12).
      * Not available in NetCDF classic format.
      */
-    STRING(Numbers.OTHER, false, (byte) 12, DataBuffer.TYPE_UNDEFINED);
+    STRING(Numbers.OTHER, false, false, (byte) 12, DataBuffer.TYPE_UNDEFINED);
 
     /**
      * Mapping from the NetCDF data type to the enumeration used by our {@link Numbers} class.
@@ -117,6 +123,11 @@ public enum DataType {
     public final byte number;
 
     /**
+     * {@code true} for data type that are signed or unsigned integers.
+     */
+    public final boolean isInteger;
+
+    /**
      * {@code false} for signed data type (the default), or {@code true} for unsigned data type.
      * The OGC NetCDF standard version 1.0 does not define unsigned data types. However some data
      * providers attach an {@code "_Unsigned = true"} attribute to the variable.
@@ -140,8 +151,11 @@ public enum DataType {
     /**
      * Creates a new enumeration.
      */
-    private DataType(final byte number, final boolean isUnsigned, final byte opposite, final int rasterDataType) {
+    private DataType(final byte number, final boolean isInteger, final boolean isUnsigned,
+            final byte opposite, final int rasterDataType)
+    {
         this.number         = number;
+        this.isInteger      = isInteger;
         this.isUnsigned     = isUnsigned;
         this.opposite       = opposite;
         this.rasterDataType = rasterDataType;
@@ -165,12 +179,12 @@ public enum DataType {
     private static final DataType[] VALUES = values();
 
     /**
-     * Returns the enumeration value for the given NetCDF code, or {@code null} if the given code is unknown.
+     * Returns the enumeration value for the given NetCDF code, or {@link #UNKNOWN} if the given code is unknown.
      *
      * @param  code  the NetCDF code.
-     * @return enumeration value for the give NetCDF code, or {@code null} if the given code is unknown.
+     * @return enumeration value for the give NetCDF code.
      */
-    public static DataType valueOf(int code) {
-        return (--code >= 0 && code < VALUES.length) ? VALUES[code] : null;
+    public static DataType valueOf(final int code) {
+        return (code >= 0 && code < VALUES.length) ? VALUES[code] : UNKNOWN;
     }
 }

Modified: sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java?rev=1762217&r1=1762216&r2=1762217&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Decoder.java [UTF-8] Sun Sep 25 15:32:42 2016
@@ -21,6 +21,7 @@ import java.io.Closeable;
 import java.io.IOException;
 import javax.measure.unit.Unit;
 import org.apache.sis.measure.Units;
+import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.util.logging.WarningListeners;
 
 // Branch-dependent imports
@@ -61,6 +62,13 @@ public abstract class Decoder implements
     }
 
     /**
+     * Returns a filename for information purpose only. This is used for formatting error messages.
+     *
+     * @return a filename to report in warning or error messages.
+     */
+    public abstract String getFilename();
+
+    /**
      * Defines the groups where to search for named attributes, in preference order.
      * The {@code null} group name stands for the global attributes.
      *
@@ -197,8 +205,9 @@ public abstract class Decoder implements
      *
      * @return a handler for the features, 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 DiscreteSampling[] getDiscreteSampling() throws IOException;
+    public abstract DiscreteSampling[] getDiscreteSampling() throws IOException, DataStoreException;
 
     /**
      * Returns all grid geometries (related to coordinate systems) found in the NetCDF file.

Added: sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/NamedElement.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/NamedElement.java?rev=1762217&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/NamedElement.java (added)
+++ sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/NamedElement.java [UTF-8] Sun Sep 25 15:32:42 2016
@@ -0,0 +1,78 @@
+/*
+ * 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.AbstractList;
+import java.util.AbstractMap;
+import java.util.Locale;
+import java.util.Map;
+import org.apache.sis.internal.util.CollectionsExt;
+import org.opengis.parameter.InvalidParameterCardinalityException;
+
+
+/**
+ * Base class of NetCDF dimension, variable or attribute.
+ * All those objects share in common a {@link #getName()} method.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.8
+ * @version 0.8
+ * @module
+ */
+public abstract class NamedElement {
+    /**
+     * For subclasses constructors.
+     */
+    protected NamedElement() {
+    }
+
+    /**
+     * Returns the dimension, variable or attribute name.
+     *
+     * @return the name of this element.
+     */
+    public abstract String getName();
+
+    /**
+     * Creates a (<cite>name</cite>, <cite>element</cite>) mapping for the given array of elements.
+     * If the name of an element is not all lower cases, then this method also adds an entry for the
+     * lower cases version of that name in order to allow case-insensitive searches.
+     *
+     * <p>Code searching in the returned map shall ask for the original (non lower-case) name
+     * <strong>before</strong> to ask for the lower-cases version of that name.</p>
+     *
+     * @param  <E>           the type of elements.
+     * @param  elements      the elements to store in the map, or {@code null} if none.
+     * @param  namesLocale   the locale to use for creating the "all lower cases" names.
+     * @return a (<cite>name</cite>, <cite>element</cite>) mapping with lower cases entries where possible.
+     * @throws InvalidParameterCardinalityException if the same name is used for more than one element.
+     */
+    public static <E extends NamedElement> Map<String,E> toCaseInsensitiveNameMap(final E[] elements, final Locale namesLocale) {
+        return CollectionsExt.toCaseInsensitiveNameMap(new AbstractList<Map.Entry<String,E>>() {
+            @Override
+            public int size() {
+                return elements.length;
+            }
+
+            @Override
+            public Map.Entry<String,E> get(final int index) {
+                final E e = elements[index];
+                return new AbstractMap.SimpleImmutableEntry<>(e.getName(), e);
+            }
+        }, namesLocale);
+    }
+}

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

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

Modified: sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java?rev=1762217&r1=1762216&r2=1762217&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java [UTF-8] Sun Sep 25 15:32:42 2016
@@ -18,6 +18,7 @@ package org.apache.sis.internal.netcdf;
 
 import java.io.IOException;
 import java.awt.image.DataBuffer;
+import org.apache.sis.math.Vector;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.util.Debug;
 
@@ -31,23 +32,13 @@ import org.apache.sis.util.Debug;
  * @version 0.8
  * @module
  */
-public abstract class Variable {
+public abstract class Variable extends NamedElement {
     /**
      * Minimal number of dimension for accepting a variable as a coverage variable.
      */
     public static final int MIN_DIMENSION = 2;
 
     /**
-     * The {@value} attribute name, used by {@link #isCoordinateSystemAxis()} implementations.
-     * If this attribute is defined, then that name will be used as the variable name when
-     * determining if the variable is a coordinate system axis.
-     *
-     * <p>This constants may be removed in any future SIS version if it is added to the
-     * {@link ucar.nc2.constants._Coordinate} class.</p>
-     */
-    protected static final String _CoordinateVariableAlias = "_CoordinateVariableAlias";
-
-    /**
      * Creates a new variable.
      */
     protected Variable() {
@@ -58,6 +49,7 @@ public abstract class Variable {
      *
      * @return the name of this variable, or {@code null}.
      */
+    @Override
     public abstract String getName();
 
     /**
@@ -77,7 +69,7 @@ public abstract class Variable {
     /**
      * Returns the variable data type.
      *
-     * @return the variable data type, or {@code null} if unknown.
+     * @return the variable data type, or {@code UNKNOWN} if unknown.
      */
     public abstract DataType getDataType();
 
@@ -127,7 +119,7 @@ public abstract class Variable {
         }
         if (numVectors >= MIN_DIMENSION) {
             final DataType dataType = getDataType();
-            if (dataType != null && dataType.rasterDataType != DataBuffer.TYPE_UNDEFINED) {
+            if (dataType.rasterDataType != DataBuffer.TYPE_UNDEFINED) {
                 return !isCoordinateSystemAxis();
             }
         }
@@ -179,7 +171,7 @@ public abstract class Variable {
      * @throws IOException if an error occurred while reading the data.
      * @throws DataStoreException if a logical error occurred.
      */
-    public abstract Object read() throws IOException, DataStoreException;
+    public abstract Vector read() throws IOException, DataStoreException;
 
     /**
      * Reads a sub-sampled sub-area of the variable.
@@ -198,7 +190,7 @@ public abstract class Variable {
      * @throws IOException if an error occurred while reading the data.
      * @throws DataStoreException if a logical error occurred.
      */
-    public abstract Object read(int[] areaLower, int[] areaUpper, int[] subsampling) throws IOException, DataStoreException;
+    public abstract Vector read(int[] areaLower, int[] areaUpper, int[] subsampling) throws IOException, DataStoreException;
 
     /**
      * Returns a string representation of this variable for debugging purpose.

Modified: sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java?rev=1762217&r1=1762216&r2=1762217&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java [UTF-8] Sun Sep 25 15:32:42 2016
@@ -33,10 +33,12 @@ import java.nio.ByteBuffer;
 import java.nio.channels.ReadableByteChannel;
 import javax.measure.converter.UnitConverter;
 import javax.measure.converter.ConversionException;
+import org.opengis.parameter.InvalidParameterCardinalityException;
 import org.apache.sis.internal.netcdf.DataType;
 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.NamedElement;
 import org.apache.sis.internal.netcdf.DiscreteSampling;
 import org.apache.sis.internal.storage.ChannelDataInput;
 import org.apache.sis.internal.util.CollectionsExt;
@@ -100,7 +102,7 @@ public final class ChannelDecoder extend
      *
      * @see #findAttribute(String)
      */
-    private static final Locale NAME_LOCALE = Locale.US;
+    static final Locale NAME_LOCALE = Locale.US;
 
     /**
      * The pattern to use for separating the component of a time unit.
@@ -172,6 +174,11 @@ public final class ChannelDecoder extend
     final VariableInfo[] variables;
 
     /**
+     * Same as {@link #variables}, but as a map for faster search.
+     */
+    private final Map<String,VariableInfo> variableMap;
+
+    /**
      * The attributes found in the NetCDF file.
      *
      * @see #findAttribute(String)
@@ -214,7 +221,7 @@ public final class ChannelDecoder extend
          */
         int version = input.readInt();
         if ((version & 0xFFFFFF00) != MAGIC_NUMBER) {
-            throw new DataStoreContentException(errors().getString(Errors.Keys.UnexpectedFileFormat_2, "NetCDF", input.filename));
+            throw new DataStoreContentException(errors().getString(Errors.Keys.UnexpectedFileFormat_2, "NetCDF", getFilename()));
         }
         /*
          * Check the version number.
@@ -240,16 +247,21 @@ public final class ChannelDecoder extend
                 final int tag = (int) (tn >>> Integer.SIZE);
                 final int nelems = (int) tn;
                 ensureNonNegative(nelems, tag);
-                switch (tag) {
-                    case DIMENSION: dimensions = readDimensions(nelems); break;
-                    case VARIABLE:  variables  = readVariables (nelems, dimensions); break;
-                    case ATTRIBUTE: attributes = readAttributes(nelems); break;
-                    default:        throw malformedHeader();
+                try {
+                    switch (tag) {
+                        case DIMENSION: dimensions = readDimensions(nelems); break;
+                        case VARIABLE:  variables  = readVariables (nelems, dimensions); break;
+                        case ATTRIBUTE: attributes = readAttributes(nelems); break;
+                        default:        throw malformedHeader();
+                    }
+                } catch (InvalidParameterCardinalityException e) {
+                    throw new DataStoreContentException(e.getLocalizedMessage());
                 }
             }
         }
         attributeMap = attributes;
         this.variables = variables;
+        variableMap = NamedElement.toCaseInsensitiveNameMap(variables, NAME_LOCALE);
     }
 
     /**
@@ -275,7 +287,7 @@ public final class ChannelDecoder extend
      *
      * @return the localized error resource bundle.
      */
-    private Errors errors() {
+    final Errors errors() {
         return Errors.getResources(listeners.getLocale());
     }
 
@@ -284,7 +296,7 @@ public final class ChannelDecoder extend
      * that the file should be a NetCDF one, but we found some inconsistency or unknown tags.
      */
     private DataStoreException malformedHeader() {
-        return new DataStoreContentException(errors().getString(Errors.Keys.CanNotParseFile_2, "NetCDF", input.filename));
+        return new DataStoreContentException(errors().getString(Errors.Keys.CanNotParseFile_2, "NetCDF", getFilename()));
     }
 
     /**
@@ -293,7 +305,7 @@ public final class ChannelDecoder extend
     private void ensureNonNegative(final int nelems, final int tag) throws DataStoreException {
         if (nelems < 0) {
             throw new DataStoreContentException(errors().getString(Errors.Keys.NegativeArrayLength_1,
-                    input.filename + DefaultNameSpace.DEFAULT_SEPARATOR + tagName(tag)));
+                    getFilename() + DefaultNameSpace.DEFAULT_SEPARATOR + tagName(tag)));
         }
     }
 
@@ -353,7 +365,7 @@ public final class ChannelDecoder extend
         if (length == 0) {
             return null;
         }
-        if (length < 0 || type == null) {
+        if (length < 0) {
             throw malformedHeader();
         }
         if (length == 1) {
@@ -489,15 +501,16 @@ public final class ChannelDecoder extend
      *   <li>Offset where data begins   (use {@link #readOffset()})</li>
      * </ul>
      *
-     * @param  nelems      the number of variables to read.
-     * @param  dimensions  the dimensions previously read by {@link #readDimensions(int)}.
+     * @param  nelems         the number of variables to read.
+     * @param  allDimensions  the dimensions previously read by {@link #readDimensions(int)}.
      */
-    private VariableInfo[] readVariables(final int nelems, final Dimension[] dimensions)
+    private VariableInfo[] readVariables(final int nelems, final Dimension[] allDimensions)
             throws IOException, DataStoreException
     {
-        if (dimensions == null) {
-            throw malformedHeader();
+        if (allDimensions == null) {
+            throw malformedHeader();        // May happen if readDimensions(…) has not been invoked.
         }
+        final Map<String,Dimension> dimByNames = Dimension.toCaseInsensitiveNameMap(allDimensions, NAME_LOCALE);
         final VariableInfo[] variables = new VariableInfo[nelems];
         for (int j=0; j<nelems; j++) {
             final String name = readName();
@@ -505,7 +518,7 @@ public final class ChannelDecoder extend
             final Dimension[] varDims = new Dimension[n];
             try {
                 for (int i=0; i<n; i++) {
-                    varDims[i] = dimensions[input.readInt()];
+                    varDims[i] = allDimensions[input.readInt()];
                 }
             } catch (IndexOutOfBoundsException cause) {
                 final DataStoreException e = malformedHeader();
@@ -528,7 +541,7 @@ public final class ChannelDecoder extend
                     default:        throw malformedHeader();
                 }
             }
-            variables[j] = new VariableInfo(input, name, varDims, dimensions, attributes,
+            variables[j] = new VariableInfo(input, name, varDims, dimByNames, attributes,
                     DataType.valueOf(input.readInt()), input.readInt(), readOffset());
         }
         return variables;
@@ -541,6 +554,16 @@ public final class ChannelDecoder extend
     // --------------------------------------------------------------------------------------------
 
     /**
+     * Returns a filename for information purpose only. This is used for formatting error messages.
+     *
+     * @return a filename to report in warning or error messages.
+     */
+    @Override
+    public final String getFilename() {
+        return input.filename;
+    }
+
+    /**
      * Defines the groups where to search for named attributes, in preference order.
      * The {@code null} group name stands for the global attributes.
      *
@@ -565,6 +588,24 @@ public final class ChannelDecoder extend
     }
 
     /**
+     * Returns the NetCDF variable of the given name, or {@code null} if none.
+     *
+     * @param  name  the name of the variable to search, or {@code null}.
+     * @return the attribute value, or {@code null} if none.
+     */
+    final VariableInfo findVariable(final String name) {
+        VariableInfo v = variableMap.get(name);
+        if (v == null && name != null) {
+            final String lower = name.toLowerCase(NAME_LOCALE);
+            // Identity comparison is ok since following check is only an optimization for a common case.
+            if (lower != name) {
+                v = variableMap.get(lower);
+            }
+        }
+        return v;
+    }
+
+    /**
      * Returns the NetCDF attribute of the given name, or {@code null} if none.
      * The {@code name} argument is typically (but is not restricted too) one of
      * the constants defined in the {@link AttributeNames} class.
@@ -576,7 +617,8 @@ public final class ChannelDecoder extend
         Object value = attributeMap.get(name);
         if (value == null && name != null) {
             final String lower = name.toLowerCase(NAME_LOCALE);
-            if (lower != name) { // Identity comparison is ok since this check is only an optimization for a common case.
+            // Identity comparison is ok since following check is only an optimization for a common case.
+            if (lower != name) {
                 value = attributeMap.get(lower);
             }
         }
@@ -670,9 +712,11 @@ public final class ChannelDecoder extend
      * If this decoder can handle the file content as features, returns handlers for them.
      *
      * @return {@inheritDoc}
+     * @throws IOException if an I/O operation was necessary but failed.
+     * @throws DataStoreException if a logical error occurred.
      */
     @Override
-    public DiscreteSampling[] getDiscreteSampling() {
+    public DiscreteSampling[] getDiscreteSampling() throws IOException, DataStoreException {
         if ("trajectory".equalsIgnoreCase(stringValue(CF.FEATURE_TYPE))) {
             return FeaturesInfo.create(this);
         }
@@ -690,8 +734,8 @@ public final class ChannelDecoder extend
     public GridGeometry[] getGridGeometries() {
         if (gridGeometries == null) {
             /*
-             * First, find all variables which are used as coordinate system axis. The keys are the
-             * grid dimensions which are the domain of the variable (i.e. the sources of the conversion
+             * 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).
              */
             final Map<Dimension, List<VariableInfo>> dimToAxes = new IdentityHashMap<>();
@@ -703,7 +747,7 @@ public final class ChannelDecoder extend
                 }
             }
             /*
-             * For each variables, gets the list of all axes associated to their dimensions. The association
+             * For each variables, get the list of all axes associated to their dimensions. The association
              * is given by the above 'dimToVars' map. More than one variable may have the same dimensions,
              * and consequently the same axes, so we will remember the previously created instances in order
              * to share them.
@@ -761,7 +805,7 @@ nextVar:    for (final VariableInfo vari
     @Override
     public String toString() {
         final StringBuilder buffer = new StringBuilder();
-        buffer.append("SIS driver: “").append(input.filename).append('”');
+        buffer.append("SIS driver: “").append(getFilename()).append('”');
         if (!input.channel.isOpen()) {
             buffer.append(" (closed)");
         }

Modified: sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/Dimension.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/Dimension.java?rev=1762217&r1=1762216&r2=1762217&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/Dimension.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/Dimension.java [UTF-8] Sun Sep 25 15:32:42 2016
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.internal.netcdf.impl;
 
+import org.apache.sis.internal.netcdf.NamedElement;
 import org.apache.sis.util.Debug;
 
 
@@ -27,10 +28,10 @@ import org.apache.sis.util.Debug;
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.7
+ * @version 0.8
  * @module
  */
-final class Dimension {
+final class Dimension extends NamedElement {
     /**
      * The dimension name.
      */
@@ -53,6 +54,14 @@ final class Dimension {
     }
 
     /**
+     * Returns the name of this NetCDF dimension.
+     */
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    /**
      * Returns the number of grid cell value along this dimension.
      */
     final long length() {

Modified: sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/FeaturesInfo.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/FeaturesInfo.java?rev=1762217&r1=1762216&r2=1762217&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/FeaturesInfo.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/FeaturesInfo.java [UTF-8] Sun Sep 25 15:32:42 2016
@@ -18,7 +18,13 @@ package org.apache.sis.internal.netcdf.i
 
 import java.util.ArrayList;
 import java.util.List;
+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.storage.DataStoreException;
+import org.apache.sis.util.collection.IntegerList;
+import org.apache.sis.util.resources.Errors;
 import ucar.nc2.constants.CF;
 
 
@@ -33,21 +39,88 @@ import ucar.nc2.constants.CF;
  */
 final class FeaturesInfo extends DiscreteSampling {
     /**
+     * The number of instances for each feature.
+     */
+    private final IntegerList counts;
+
+    /**
+     * The moving feature identifiers ("mfIdRef").
+     */
+    private final VariableInfo identifiers;
+
+    /**
      * Creates a new discrete sampling parser for features identified by the given variable.
+     *
+     * @param  cpf          the count of instances per feature.
+     * @param  identifiers  the feature identifiers.
      */
-    private FeaturesInfo(final ChannelDecoder decoder, final VariableInfo identifiers) {
-        // TODO
+    private FeaturesInfo(final Vector cpf, final VariableInfo identifiers) {
+        final int n = cpf.size();
+        int max = 1;
+        for (int i=0; i<n; i++) {
+            final int v = cpf.intValue(i);
+            if (v > max) max = v;
+        }
+        counts = new IntegerList(n, max);
+        for (int i=0; i<n; i++) {
+            counts.addInt(cpf.intValue(i));
+        }
+        this.identifiers = identifiers;
+        final Object role = identifiers.getAttributeValue(CF.CF_ROLE);
+        if (role instanceof String && ((String) role).equalsIgnoreCase(CF.TRAJECTORY_ID)) {
+            // TODO
+        }
     }
 
     /**
-     * Creates new discrete sampling parsers.
+     * Creates new discrete sampling parsers from the attribute values found in the given decoder.
      */
-    static FeaturesInfo[] create(final ChannelDecoder decoder) {
-        final List<FeaturesInfo> features = new ArrayList<>();
-        for (final VariableInfo v : decoder.variables) {
-            for (final Object role : v.getAttributeValues(CF.CF_ROLE, false)) {
-                if (role instanceof String && ((String) role).equalsIgnoreCase(CF.TRAJECTORY_ID)) {
-                    features.add(new FeaturesInfo(decoder, v));
+    static FeaturesInfo[] create(final ChannelDecoder decoder) throws IOException, DataStoreException {
+        final List<FeaturesInfo> features = new ArrayList<>(3);     // Will usually contain at most one element.
+search: for (final VariableInfo counts : decoder.variables) {
+            if (counts.dimensions.length == 1 && counts.getDataType().isInteger) {
+                final Object sampleDimName = counts.getAttributeValue(CF.SAMPLE_DIMENSION);
+                if (sampleDimName instanceof String) {
+                    /*
+                     * Any one-dimensional integer variable having a "sample_dimension" attribute string value
+                     * will be taken as an indication that we have Discrete Sampling Geometries. That variable
+                     * shall be counting the number of feature instances, and another variable having the same
+                     * dimension (optionally plus a character dimension) shall give the feature identifiers.
+                     */
+                    final Dimension featureDimension = counts.dimensions[0];
+                    final VariableInfo identifiers = decoder.findVariable(featureDimension.name);
+                    if (identifiers == null) {
+                        decoder.listeners.warning(decoder.errors().getString(Errors.Keys.VariableNotFound_2,
+                                decoder.getFilename(), featureDimension.name), null);
+                        continue;
+                    }
+                    for (int i=0; i<identifiers.dimensions.length; i++) {
+                        final boolean isValid;
+                        switch (i) {
+                            case 0:  isValid = (identifiers.dimensions[0] == featureDimension); break;
+                            case 1:  isValid = (identifiers.getDataType() == DataType.CHAR); break;
+                            default: isValid = false; break;                    // Too many dimensions
+                        }
+                        if (!isValid) {
+                            decoder.listeners.warning(decoder.errors().getString(
+                                    Errors.Keys.UnexpectedDimensionForVariable_4,
+                                    decoder.getFilename(), identifiers.getName(),
+                                    featureDimension.getName(), identifiers.dimensions[i].name), null);
+                            continue search;
+                        }
+                    }
+                    /*
+                     * The "sample_dimension" attribute value shall be the name of a dimension.
+                     * Those dimensions are associated to other variables (not the count one),
+                     * but the 'findDimension' method below searches in all dimensions.
+                     */
+                    final Dimension sampleDim = counts.findDimension((String) sampleDimName);
+                    if (sampleDim == null) {
+                        decoder.listeners.warning(decoder.errors().getString(Errors.Keys.DimensionNotFound_3,
+                                decoder.getFilename(), counts.getName(), sampleDimName), null);
+                        continue;
+                    }
+                    features.add(new FeaturesInfo(counts.read(), identifiers));
                 }
             }
         }

Modified: sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/VariableInfo.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/VariableInfo.java?rev=1762217&r1=1762216&r2=1762217&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/VariableInfo.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/VariableInfo.java [UTF-8] Sun Sep 25 15:32:42 2016
@@ -32,6 +32,7 @@ import org.apache.sis.storage.DataStoreC
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.Numbers;
+import org.apache.sis.math.Vector;
 
 
 /**
@@ -72,14 +73,16 @@ final class VariableInfo extends Variabl
     private final String name;
 
     /**
-     * The dimensions of this variable.
+     * The dimensions of this variable, in order. When iterating over the values stored in this variable
+     * (a flattened one-dimensional sequence of values), index in the domain of {@code dimensions[0]}
+     * varies faster, followed by index in the domain of {@code dimensions[1]}, <i>etc.</i>
      */
     final Dimension[] dimensions;
 
     /**
      * All dimensions in the NetCDF files.
      */
-    private final Dimension[] allDimensions;
+    private final Map<String,Dimension> allDimensions;
 
     /**
      * The attributes associates to the variable, or an empty map if none.
@@ -112,6 +115,15 @@ final class VariableInfo extends Variabl
     GridGeometryInfo gridGeometry;
 
     /**
+     * {@code true} if this variable seems to be a coordinate system axis, as determined by comparing its name
+     * with the name of all dimensions in the NetCDF file. This information is computed at construction time
+     * because requested more than once.
+     *
+     * @see #isCoordinateSystemAxis()
+     */
+    private final boolean isCoordinateSystemAxis;
+
+    /**
      * Creates a new variable.
      *
      * @param  input          the channel together with a buffer for reading the variable data.
@@ -123,9 +135,14 @@ final class VariableInfo extends Variabl
      * @param  size           the variable size, used for verification purpose only.
      * @param  offset         the offset where the variable data begins in the NetCDF file.
      */
-    VariableInfo(final ChannelDataInput input, final String name,
-            final Dimension[] dimensions, final Dimension[] allDimensions, final Map<String,Object> attributes,
-            DataType dataType, final int size, final long offset) throws DataStoreException
+    VariableInfo(final ChannelDataInput      input,
+                 final String                name,
+                 final Dimension[]           dimensions,
+                 final Map<String,Dimension> allDimensions,
+                 final Map<String,Object>    attributes,
+                       DataType              dataType,
+                 final int                   size,
+                 final long                  offset) throws DataStoreException
     {
         final Object isUnsigned = attributes.get(CDM.UNSIGNED);
         if (isUnsigned != null) {
@@ -145,6 +162,23 @@ final class VariableInfo extends Variabl
         } else {
             reader = null;
         }
+        /*
+         * If the "_CoordinateAliasForDimension" attribute is defined, then its value will be used
+         * instead of the variable name when determining if the variable is a coordinate system axis.
+         * "_CoordinateVariableAlias" seems to be a legacy attribute name for the same purpose.
+         */
+        if (dimensions.length == 1) {
+            Object value = getAttributeValue(_Coordinate.AliasForDimension, "_coordinatealiasfordimension");
+            if (value == null) {
+                value = getAttributeValue("_CoordinateVariableAlias", "_coordinatevariablealias");
+                if (value == null) {
+                    value = name;
+                }
+            }
+            isCoordinateSystemAxis = dimensions[0].name.equals(value);
+        } else {
+            isCoordinateSystemAxis = false;
+        }
     }
 
     /**
@@ -163,7 +197,7 @@ final class VariableInfo extends Variabl
     @Override
     public String getDescription() {
         for (final String attributeName : DESCRIPTION_ATTRIBUTES) {
-            final Object value = attributes.get(attributeName);
+            final Object value = getAttributeValue(attributeName);
             if (value instanceof String) {
                 return (String) value;
             }
@@ -176,12 +210,12 @@ final class VariableInfo extends Variabl
      */
     @Override
     public String getUnitsString() {
-        final Object value = attributes.get(CDM.UNITS);
+        final Object value = getAttributeValue(CDM.UNITS);
         return (value instanceof String) ? (String) value : null;
     }
 
     /**
-     * Returns the type of data, or {@code null} if the data type is unknown to this method.
+     * Returns the type of data, or {@code UNKNOWN} if the data type is unknown to this method.
      * If this variable has a {@code "_Unsigned = true"} attribute, then the returned data type
      * will be a unsigned variant.
      */
@@ -196,22 +230,14 @@ final class VariableInfo extends Variabl
      */
     @Override
     public boolean isCoordinateSystemAxis() {
-        final Object value = attributes.get(_CoordinateVariableAlias);
-        final String alias = (value instanceof String) ? (String) value : name;
-        for (final Dimension dimension : allDimensions) {
-            if (alias.equals(dimension.name)) {
-                // This variable is a dimension of another variable.
-                return true;
-            }
-        }
-        return false;
+        return isCoordinateSystemAxis;
     }
 
     /**
      * Returns the value of the {@code "_CoordinateAxisType"} attribute, or {@code null} if none.
      */
     final String getAxisType() {
-        final Object value = attributes.get(_Coordinate.AxisType);
+        final Object value = getAttributeValue(_Coordinate.AxisType, "_coordinateaxistype");
         return (value instanceof String) ? (String) value : null;
     }
 
@@ -244,13 +270,61 @@ final class VariableInfo extends Variabl
     }
 
     /**
+     * Returns the dimension of the given name (eventually ignoring case), or {@code null} if none.
+     * This method searches in all dimensions found in the NetCDF file,
+     * regardless of whether the dimension is used by this variable or not.
+     * The search will ignore case only if no exact match is found for the given name.
+     *
+     * @param  dimName  the name of the dimension to search.
+     * @return dimension of the given name, or {@code null} if none.
+     */
+    final Dimension findDimension(final String dimName) {
+        Dimension dim = allDimensions.get(dimName);         // Give precedence to exact match before to ignore case.
+        if (dim == null) {
+            final String lower = dimName.toLowerCase(ChannelDecoder.NAME_LOCALE);
+            if (lower != dimName) {                         // Identity comparison is okay here.
+                dim = allDimensions.get(lower);
+            }
+        }
+        return dim;
+    }
+
+    /**
+     * 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.
+     *
+     * @param  attributeName  name of attribute to search, in the expected case.
+     * @param  lowerCase      the all lower-case variant of {@code attributeName}.
+     * @return variable attribute value of the given name, or {@code null} if none.
+     */
+    private Object getAttributeValue(final String attributeName, final String lowerCase) {
+        Object value = attributes.get(attributeName);
+        if (value == null) {
+            value = attributes.get(lowerCase);
+        }
+        return value;
+    }
+
+    /**
+     * Returns the value of the given attribute, or {@code null} if none.
+     * This method does not search the lower-case variant of the given name because the argument given to this method
+     * is usually a hard-coded value from {@link CF} or {@link CDM} conventions, which are already in lower-cases.
+     *
+     * @param  attributeName  name of attribute to search, in the expected case.
+     * @return variable attribute value of the given name, or {@code null} if none.
+     */
+    final Object getAttributeValue(final String attributeName) {
+        return attributes.get(attributeName);
+    }
+
+    /**
      * 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}.
      */
     @Override
     public Object[] getAttributeValues(final String attributeName, final boolean numeric) {
-        final Object value = attributes.get(attributeName);
+        final Object value = getAttributeValue(attributeName);
         return numeric ? numberValues(value) : stringValues(value);
     }
 
@@ -309,7 +383,7 @@ final class VariableInfo extends Variabl
      * Reads all the data for this variable and returns them as an array of a Java primitive type.
      */
     @Override
-    public Object read() throws IOException, DataStoreException {
+    public Vector read() throws IOException, DataStoreException {
         if (reader == null) {
             throw new DataStoreContentException(unknownType());
         }
@@ -327,7 +401,7 @@ final class VariableInfo extends Variabl
             sub [i] = 1;
             size[i] = dimensions[(dimension - 1) - i].length();
         }
-        return reader.read(new Region(size, new long[dimension], size, sub));
+        return Vector.create(reader.read(new Region(size, new long[dimension], size, sub)), dataType.isUnsigned);
     }
 
     /**
@@ -339,7 +413,7 @@ final class VariableInfo extends Variabl
      * @return the data as an array of a Java primitive type.
      */
     @Override
-    public Object read(int[] areaLower, int[] areaUpper, int[] subsampling) throws IOException, DataStoreException {
+    public Vector read(int[] areaLower, int[] areaUpper, int[] subsampling) throws IOException, DataStoreException {
         if (reader == null) {
             throw new DataStoreContentException(unknownType());
         }
@@ -374,7 +448,7 @@ final class VariableInfo extends Variabl
             sub  [i] = subsampling[j];
             size [i] = dimensions[j].length();
         }
-        return reader.read(new Region(size, lower, upper, sub));
+        return Vector.create(reader.read(new Region(size, lower, upper, sub)), dataType.isUnsigned);
     }
 
     /**

Modified: sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java?rev=1762217&r1=1762216&r2=1762217&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java [UTF-8] Sun Sep 25 15:32:42 2016
@@ -22,7 +22,6 @@ import java.util.EnumSet;
 import java.util.Formatter;
 import java.io.IOException;
 import ucar.nc2.Group;
-import ucar.nc2.Dimension;
 import ucar.nc2.Attribute;
 import ucar.nc2.VariableIF;
 import ucar.nc2.NetcdfFile;
@@ -120,6 +119,16 @@ public final class DecoderWrapper extend
     }
 
     /**
+     * Returns a filename for information purpose only. This is used for formatting error messages.
+     *
+     * @return a filename to report in warning or error messages.
+     */
+    @Override
+    public String getFilename() {
+        return file.getLocation();
+    }
+
+    /**
      * Defines the groups where to search for named attributes, in preference order.
      * The {@code null} group name stands for the global attributes.
      */
@@ -311,11 +320,10 @@ public final class DecoderWrapper extend
     @SuppressWarnings({"ReturnOfCollectionOrArrayField", "null"})
     public Variable[] getVariables() {
         if (variables == null) {
-            final List<Dimension> dimensions = file.getDimensions();
             final List<? extends VariableIF> all = file.getVariables();
             variables = new Variable[(all != null) ? all.size() : 0];
             for (int i=0; i<variables.length; i++) {
-                variables[i] = new VariableWrapper(all.get(i), dimensions);
+                variables[i] = new VariableWrapper(all.get(i));
             }
         }
         return variables;
@@ -425,6 +433,6 @@ public final class DecoderWrapper extend
     @Debug
     @Override
     public String toString() {
-        return "UCAR driver: “" + file.getLocation() + '”';
+        return "UCAR driver: “" + getFilename() + '”';
     }
 }

Modified: sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java?rev=1762217&r1=1762216&r2=1762217&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java [UTF-8] Sun Sep 25 15:32:42 2016
@@ -24,6 +24,7 @@ import ucar.ma2.InvalidRangeException;
 import ucar.nc2.Attribute;
 import ucar.nc2.Dimension;
 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.storage.DataStoreException;
@@ -46,16 +47,10 @@ final class VariableWrapper extends Vari
     private final VariableIF variable;
 
     /**
-     * The list of all dimensions in the NetCDF file.
-     */
-    private final List<? extends Dimension> all;
-
-    /**
      * Creates a new variable wrapping the given NetCDF interface.
      */
-    VariableWrapper(final VariableIF variable, List<? extends Dimension> all) {
+    VariableWrapper(final VariableIF variable) {
         this.variable = variable;
-        this.all = all;
     }
 
     /**
@@ -84,46 +79,31 @@ final class VariableWrapper extends Vari
 
     /**
      * Returns the variable data type.
-     * This method may return {@code null} if the datatype is unknown.
+     * This method may return {@code UNKNOWN} if the datatype is unknown.
      */
     @Override
     public DataType getDataType() {
         final DataType type;
         switch (variable.getDataType()) {
-            case STRING: type = DataType.STRING; break;
-            case CHAR:   type = DataType.CHAR;   break;
+            case STRING: return DataType.STRING;
+            case CHAR:   return DataType.CHAR;
             case BYTE:   type = DataType.BYTE;   break;
             case SHORT:  type = DataType.SHORT;  break;
             case INT:    type = DataType.INT;    break;
             case LONG:   type = DataType.INT64;  break;
-            case FLOAT:  type = DataType.FLOAT;  break;
-            case DOUBLE: type = DataType.DOUBLE; break;
-            default: return null;
+            case FLOAT:  return DataType.FLOAT;
+            case DOUBLE: return DataType.DOUBLE;
+            default:     return DataType.UNKNOWN;
         }
         return type.unsigned(variable.isUnsigned());
     }
 
     /**
-     * Returns {@code true} if this variable seems to be a coordinate system axis,
-     * determined by comparing its name with the name of all dimensions in the NetCDF file.
+     * Returns {@code true} if this variable seems to be a coordinate system axis.
      */
     @Override
     public boolean isCoordinateSystemAxis() {
-        String name = null;
-        final Attribute attribute = variable.findAttributeIgnoreCase(_CoordinateVariableAlias);
-        if (attribute != null) {
-            name = attribute.getStringValue();
-        }
-        if (name == null) {
-            name = getName();
-        }
-        for (final Dimension dimension : all) {
-            if (name.equals(dimension.getShortName())) {
-                // This variable is a dimension of another variable.
-                return true;
-            }
-        }
-        return false;
+        return variable.isCoordinateVariable();
     }
 
     /**
@@ -187,9 +167,9 @@ final class VariableWrapper extends Vari
      * Reads all the data for this variable and returns them as an array of a Java primitive type.
      */
     @Override
-    public Object read() throws IOException {
+    public Vector read() throws IOException {
         final Array array = variable.read();
-        return array.get1DJavaArray(array.getElementType());
+        return Vector.create(array.get1DJavaArray(array.getElementType()), variable.isUnsigned());
     }
 
     /**
@@ -201,7 +181,7 @@ final class VariableWrapper extends Vari
      * @return the data as an array of a Java primitive type.
      */
     @Override
-    public Object read(final int[] areaLower, final int[] areaUpper, final int[] subsampling)
+    public Vector read(final int[] areaLower, final int[] areaUpper, final int[] subsampling)
             throws IOException, DataStoreException
     {
         final int[] size = new int[areaUpper.length];
@@ -214,6 +194,6 @@ final class VariableWrapper extends Vari
         } catch (InvalidRangeException e) {
             throw new DataStoreContentException(e);
         }
-        return array.get1DJavaArray(array.getElementType());
+        return Vector.create(array.get1DJavaArray(array.getElementType()), variable.isUnsigned());
     }
 }

Modified: sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/DataTypeTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/DataTypeTest.java?rev=1762217&r1=1762216&r2=1762217&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/DataTypeTest.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/DataTypeTest.java [UTF-8] Sun Sep 25 15:32:42 2016
@@ -54,7 +54,7 @@ public final strictfp class DataTypeTest
      * Verifies the ordinal value of the given data type.
      */
     private static void verifyOrdinal(final int codeNetCDF, final DataType type) {
-        assertEquals(type.name(), codeNetCDF, type.ordinal() + 1);
+        assertEquals(type.name(), codeNetCDF, type.ordinal());
         assertSame("DataType.valueOf(int)", type, DataType.valueOf(codeNetCDF));
     }
 

Modified: sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/VariableTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/VariableTest.java?rev=1762217&r1=1762216&r2=1762217&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/VariableTest.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/VariableTest.java [UTF-8] Sun Sep 25 15:32:42 2016
@@ -17,6 +17,7 @@
 package org.apache.sis.internal.netcdf;
 
 import java.io.IOException;
+import org.apache.sis.math.Vector;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.test.DependsOn;
 import org.junit.Test;
@@ -170,12 +171,12 @@ public strictfp class VariableTest exten
     public void testRead1D() throws IOException, DataStoreException {
         final Variable variable = selectDataset(NCEP).getVariables()[25];
         assertEquals("lon", variable.getName());
-        final Object data = variable.read();
-        assertInstanceOf("lon", float[].class, data);
-        final float[] array = (float[]) data;
-        assertEquals(73, array.length);
-        for (int i=0; i<array.length; i++) {
-            assertEquals("Longitude value", -180 + 5*i, array[i], 0f);
+        final Vector data = variable.read();
+        assertEquals("lon", Float.class, data.getElementType());
+        final int length = data.size();
+        assertEquals("length", 73, length);
+        for (int i=0; i<length; i++) {
+            assertEquals("Longitude value", -180 + 5*i, data.floatValue(i), 0f);
         }
     }
 }



Mime
View raw message