Author: desruisseaux
Date: Fri Sep 16 20:52:47 2016
New Revision: 1761084

URL: http://svn.apache.org/viewvc?rev=1761084&view=rev
Log:
Begin implementation of Moving Features encoding in NetCDF files.

Added:
    
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/DiscreteSampling.java
   (with props)
    
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/FeaturesInfo.java
   (with props)
    
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/FeaturesWrapper.java
   (with props)
    
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/LogAdapter.java
   (with props)
Modified:
    
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/impl/ChannelDecoder.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/storage/netcdf/MetadataReader.java
    
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java
    
sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/DecoderTest.java
    
sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/TestCase.java
    
sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/NetcdfStoreTest.java

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=1761084&r1=1761083&r2=1761084&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] Fri Sep 16 20:52:47 2016
@@ -30,9 +30,12 @@ import java.util.Objects;
 /**
  * The API used internally by Apache SIS for fetching variables and attribute 
values from a NetCDF file.
  *
+ * <p>This {@code Decoder} class and subclasses are <strong>not</strong> 
thread-safe.
+ * Synchronizations are caller's responsibility.</p>
+ *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.8
  * @module
  */
 public abstract class Decoder implements Closeable {
@@ -62,9 +65,8 @@ public abstract class Decoder implements
      * The {@code null} group name stands for the global attributes.
      *
      * @param  groupNames  the name of the group where to search, in 
preference order.
-     * @throws IOException if an I/O operation was necessary but failed.
      */
-    public abstract void setSearchPath(final String... groupNames) throws 
IOException;
+    public abstract void setSearchPath(final String... groupNames);
 
     /**
      * Returns the path which is currently set. The array returned by this 
method may be only
@@ -72,9 +74,8 @@ public abstract class Decoder implements
      * groups which have been found in the NetCDF file are returned by this 
method.
      *
      * @return the current search path.
-     * @throws IOException if an I/O operation was necessary but failed.
      */
-    public abstract String[] getSearchPath() throws IOException;
+    public abstract String[] getSearchPath();
 
     /**
      * Returns the value for the attribute of the given name, or {@code null} 
if none.
@@ -83,18 +84,16 @@ public abstract class Decoder implements
      *
      * @param  name  the name of the attribute to search, or {@code null}.
      * @return the attribute value, or {@code null} if none or empty or if the 
given name was null.
-     * @throws IOException if an I/O operation was necessary but failed.
      */
-    public abstract String stringValue(final String name) throws IOException;
+    public abstract String stringValue(final String name);
 
     /**
      * Returns the value of the attribute of the given name as a number, or 
{@code null} if none.
      *
      * @param  name  the name of the attribute to search, or {@code null}.
      * @return the attribute value, or {@code null} if none or unparsable or 
if the given name was null.
-     * @throws IOException if an I/O operation was necessary but failed.
      */
-    public abstract Number numericValue(final String name) throws IOException;
+    public abstract Number numericValue(final String name);
 
     /**
      * Convenience method for {@link #numericValue(String)} implementation.
@@ -122,22 +121,20 @@ public abstract class Decoder implements
      *
      * @param  name  the name of the attribute to search, or {@code null}.
      * @return the attribute value, or {@code null} if none or unparsable or 
if the given name was null.
-     * @throws IOException if an I/O operation was necessary but failed.
      */
-    public abstract Date dateValue(final String name) throws IOException;
+    public abstract Date dateValue(final String name);
 
     /**
      * Returns the value of the attribute of the given name as a unit of 
measurement, or {@code null} if none.
      *
      * @param  name  the name of the attribute to search, or {@code null}.
      * @return the attribute value, or {@code null} if none or unparsable or 
if the given name was null.
-     * @throws IOException if an I/O operation was necessary but failed.
      *
      * @todo Current Units.valueOf(String) implementation ignore direction in 
"degrees_east" or "degrees_west".
      *       We may need to take that in account (with "degrees_west" to 
"degrees_east" converter that reverse
      *       the sign).
      */
-    public final Unit<?> unitValue(final String name) throws IOException {
+    public final Unit<?> unitValue(final String name) {
         final String unit = stringValue(name);
         if (unit != null) try {
             return Units.valueOf(unit);
@@ -154,19 +151,20 @@ public abstract class Decoder implements
      * @param  symbol  the temporal unit name or symbol, followed by the epoch.
      * @param  values  the values to convert. May contains {@code null} 
elements.
      * @return the converted values. May contains {@code null} elements.
-     * @throws IOException if an I/O operation was necessary but failed.
      */
-    public abstract Date[] numberToDate(final String symbol, final Number... 
values) throws IOException;
+    public abstract Date[] numberToDate(final String symbol, final Number... 
values);
 
     /**
      * Returns the value of the {@code "_Id"} global attribute. The UCAR 
library defines a
      * {@link ucar.nc2.NetcdfFile#getId()} method for that purpose, which we 
will use when
      * possible in case that {@code getId()} method is defined in an other way.
      *
+     * <p>This method is used by {@link 
org.apache.sis.storage.netcdf.MetadataReader} in last resort
+     * when no value were found for the attributes defined by the CF standard 
or by THREDDS.</p>
+     *
      * @return the global dataset identifier, or {@code null} if none.
-     * @throws IOException if an I/O operation was necessary but failed.
      */
-    public String getId() throws IOException {
+    public String getId() {
         return stringValue("_Id");
     }
 
@@ -175,10 +173,12 @@ public abstract class Decoder implements
      * {@link ucar.nc2.NetcdfFile#getTitle()} method for that purpose, which 
we will use when
      * possible in case that {@code getTitle()} method is defined in an other 
way.
      *
+     * <p>This method is used by {@link 
org.apache.sis.storage.netcdf.MetadataReader} in last resort
+     * when no value were found for the attributes defined by the CF standard 
or by THREDDS.</p>
+     *
      * @return the dataset title, or {@code null} if none.
-     * @throws IOException if an I/O operation was necessary but failed.
      */
-    public String getTitle() throws IOException {
+    public String getTitle() {
         return stringValue("_Title");
     }
 
@@ -187,9 +187,18 @@ public abstract class Decoder implements
      * This method may return a direct reference to an internal array - do not 
modify.
      *
      * @return all variables, or an empty array if none.
+     */
+    public abstract Variable[] getVariables();
+
+    /**
+     * If the file contains features encoded as discrete sampling (for example 
profiles or trajectories),
+     * returns objects for handling them.
+     * This method may return a direct reference to an internal array - do not 
modify.
+     *
+     * @return a handler for the features, or an empty array if none.
      * @throws IOException if an I/O operation was necessary but failed.
      */
-    public abstract Variable[] getVariables() throws IOException;
+    public abstract DiscreteSampling[] getDiscreteSampling() throws 
IOException;
 
     /**
      * 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/DiscreteSampling.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/DiscreteSampling.java?rev=1761084&view=auto
==============================================================================
--- 
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/DiscreteSampling.java
 (added)
+++ 
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/DiscreteSampling.java
 [UTF-8] Fri Sep 16 20:52:47 2016
@@ -0,0 +1,37 @@
+/*
+ * 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;
+
+
+/**
+ * Returns the features encoded in the NetCDF files when they are encoded as 
discrete sampling.
+ * The NetCDF attributes shall be conform to the "Discrete Sampling 
Geometries" chapter of
+ * <a href="http://cfconventions.org/";>CF conventions</a>. Some examples are 
trajectories
+ * and profiles.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.8
+ * @version 0.8
+ * @module
+ */
+public abstract class DiscreteSampling {
+    /**
+     * Creates a new discrete sampling parser.
+     */
+    protected DiscreteSampling() {
+    }
+}

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

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

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=1761084&r1=1761083&r2=1761084&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] Fri Sep 16 20:52:47 2016
@@ -37,6 +37,7 @@ import org.apache.sis.internal.netcdf.Da
 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.DiscreteSampling;
 import org.apache.sis.internal.storage.ChannelDataInput;
 import org.apache.sis.internal.util.CollectionsExt;
 import org.apache.sis.internal.util.StandardDateFormat;
@@ -48,6 +49,7 @@ import org.apache.sis.util.resources.Voc
 import org.apache.sis.util.logging.WarningListeners;
 import org.apache.sis.util.Debug;
 import org.apache.sis.measure.Units;
+import ucar.nc2.constants.CF;
 
 // Branch-dependent imports
 import java.time.DateTimeException;
@@ -167,7 +169,7 @@ public final class ChannelDecoder extend
      *
      * @see #getVariables()
      */
-    private final VariableInfo[] variables;
+    final VariableInfo[] variables;
 
     /**
      * The attributes found in the NetCDF file.
@@ -545,11 +547,9 @@ public final class ChannelDecoder extend
      * <p>Current implementation does nothing, since the NetCDF binary files 
that {@code ChannelDecoder}
      * can read do not have groups anyway. Future SIS implementations may 
honor the given group names if
      * groups support is added.</p>
-     *
-     * @throws IOException {@inheritDoc}
      */
     @Override
-    public void setSearchPath(final String... groupNames) throws IOException {
+    public void setSearchPath(final String... groupNames) {
     }
 
     /**
@@ -558,10 +558,9 @@ public final class ChannelDecoder extend
      * groups which have been found in the NetCDF file are returned by this 
method.
      *
      * @return {@inheritDoc}
-     * @throws IOException {@inheritDoc}
      */
     @Override
-    public String[] getSearchPath() throws IOException {
+    public String[] getSearchPath() {
         return new String[1];
     }
 
@@ -589,10 +588,9 @@ public final class ChannelDecoder extend
      *
      * @param  name  the name of the attribute to search, or {@code null}.
      * @return the attribute value, or {@code null} if none or empty or if the 
given name was null.
-     * @throws IOException {@inheritDoc}
      */
     @Override
-    public String stringValue(final String name) throws IOException {
+    public String stringValue(final String name) {
         final Object value = findAttribute(name);
         return (value != null) ? value.toString() : null;
     }
@@ -602,10 +600,9 @@ public final class ChannelDecoder extend
      * If there is more than one numeric value, only the first one is returned.
      *
      * @return {@inheritDoc}
-     * @throws IOException {@inheritDoc}
      */
     @Override
-    public Number numericValue(final String name) throws IOException {
+    public Number numericValue(final String name) {
         final Object value = findAttribute(name);
         if (value instanceof String) {
             return parseNumber((String) value);
@@ -619,10 +616,9 @@ public final class ChannelDecoder extend
      * If there is more than one numeric value, only the first one is returned.
      *
      * @return {@inheritDoc}
-     * @throws IOException {@inheritDoc}
      */
     @Override
-    public Date dateValue(final String name) throws IOException {
+    public Date dateValue(final String name) {
         final Object value = findAttribute(name);
         if (value instanceof CharSequence) try {
             return 
StandardDateFormat.toDate(StandardDateFormat.FORMAT.parse((CharSequence) 
value));
@@ -638,10 +634,9 @@ public final class ChannelDecoder extend
      *
      * @param  values  the values to convert. May contain {@code null} 
elements.
      * @return the converted values. May contain {@code null} elements.
-     * @throws IOException {@inheritDoc}
      */
     @Override
-    public Date[] numberToDate(final String symbol, final Number... values) 
throws IOException {
+    public Date[] numberToDate(final String symbol, final Number... values) {
         final Date[] dates = new Date[values.length];
         final String[] parts = TIME_UNIT_PATTERN.split(symbol);
         if (parts.length == 2) try {
@@ -664,24 +659,35 @@ public final class ChannelDecoder extend
      * This method returns a direct reference to an internal array - do not 
modify.
      *
      * @return {@inheritDoc}
-     * @throws IOException {@inheritDoc}
      */
     @Override
     @SuppressWarnings("ReturnOfCollectionOrArrayField")
-    public Variable[] getVariables() throws IOException {
+    public Variable[] getVariables() {
         return variables;
     }
 
     /**
+     * If this decoder can handle the file content as features, returns 
handlers for them.
+     *
+     * @return {@inheritDoc}
+     */
+    @Override
+    public DiscreteSampling[] getDiscreteSampling() {
+        if ("trajectory".equalsIgnoreCase(stringValue(CF.FEATURE_TYPE))) {
+            return FeaturesInfo.create(this);
+        }
+        return new FeaturesInfo[0];
+    }
+
+    /**
      * Returns all grid geometries found in the NetCDF file.
      * This method returns a direct reference to an internal array - do not 
modify.
      *
      * @return {@inheritDoc}
-     * @throws IOException {@inheritDoc}
      */
     @Override
     @SuppressWarnings("ReturnOfCollectionOrArrayField")
-    public GridGeometry[] getGridGeometries() throws IOException {
+    public GridGeometry[] getGridGeometries() {
         if (gridGeometries == null) {
             /*
              * First, find all variables which are used as coordinate system 
axis. The keys are the

Added: 
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=1761084&view=auto
==============================================================================
--- 
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/FeaturesInfo.java
 (added)
+++ 
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/FeaturesInfo.java
 [UTF-8] Fri Sep 16 20:52:47 2016
@@ -0,0 +1,56 @@
+/*
+ * 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.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.sis.internal.netcdf.DiscreteSampling;
+import ucar.nc2.constants.CF;
+
+
+/**
+ * Implementations of the discrete sampling features decoder. This 
implementation shall be able to decode at least the
+ * NetCDF files encoded as specified in the OGC 16-114 (OGC Moving Features 
Encoding Extension: NetCDF) specification.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.8
+ * @version 0.8
+ * @module
+ */
+final class FeaturesInfo extends DiscreteSampling {
+    /**
+     * Creates a new discrete sampling parser for features identified by the 
given variable.
+     */
+    private FeaturesInfo(final ChannelDecoder decoder, final VariableInfo 
identifiers) {
+        // TODO
+    }
+
+    /**
+     * Creates new discrete sampling parsers.
+     */
+    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));
+                }
+            }
+        }
+        return features.toArray(new FeaturesInfo[features.size()]);
+    }
+}

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

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

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=1761084&r1=1761083&r2=1761084&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] Fri Sep 16 20:52:47 2016
@@ -19,6 +19,7 @@ package org.apache.sis.internal.netcdf.u
 import java.util.Date;
 import java.util.List;
 import java.util.EnumSet;
+import java.util.Formatter;
 import java.io.IOException;
 import ucar.nc2.Group;
 import ucar.nc2.Dimension;
@@ -32,12 +33,17 @@ import ucar.nc2.units.DateUnit;
 import ucar.nc2.time.Calendar;
 import ucar.nc2.time.CalendarDate;
 import ucar.nc2.time.CalendarDateFormatter;
+import ucar.nc2.ft.FeatureDataset;
+import ucar.nc2.ft.FeatureDatasetPoint;
+import ucar.nc2.ft.FeatureDatasetFactoryManager;
+import ucar.nc2.ft.FeatureCollection;
 import org.apache.sis.util.Debug;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.logging.WarningListeners;
 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.DiscreteSampling;
 
 
 /**
@@ -45,7 +51,7 @@ import org.apache.sis.internal.netcdf.Gr
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.8
  * @module
  */
 public final class DecoderWrapper extends Decoder implements CancelTask {
@@ -76,6 +82,11 @@ public final class DecoderWrapper extend
     private transient Variable[] variables;
 
     /**
+     * The discrete sampling features, or {@code null} if none.
+     */
+    private transient FeatureDataset features;
+
+    /**
      * The grid geometries, computed when first needed.
      *
      * @see #getGridGeometries()
@@ -102,6 +113,7 @@ public final class DecoderWrapper extend
      * @param  filename   the name of the NetCDF file from which to read data.
      * @throws IOException if an error occurred while opening the NetCDF file.
      */
+    @SuppressWarnings("ThisEscapedInObjectConstruction")
     public DecoderWrapper(final WarningListeners<?> listeners, final String 
filename) throws IOException {
         super(listeners);
         file = NetcdfDataset.openDataset(filename, false, this);
@@ -310,6 +322,30 @@ public final class DecoderWrapper 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.
+     */
+    @Override
+    @SuppressWarnings("null")
+    public DiscreteSampling[] getDiscreteSampling() throws IOException {
+        if (features == null && file instanceof NetcdfDataset) {
+            features = FeatureDatasetFactoryManager.wrap(null, (NetcdfDataset) 
file, this,
+                    new Formatter(new LogAdapter(listeners), 
listeners.getLocale()));
+        }
+        List<FeatureCollection> fc = null;
+        if (features instanceof FeatureDatasetPoint) {
+            fc = ((FeatureDatasetPoint) 
features).getPointFeatureCollectionList();
+        }
+        final FeaturesWrapper[] wrappers = new FeaturesWrapper[(fc != null) ? 
fc.size() : 0];
+        for (int i=0; i<wrappers.length; i++) {
+            wrappers[i] = new FeaturesWrapper(fc.get(i));
+        }
+        return wrappers;
+    }
+
+    /**
      * Returns all grid geometries (related to coordinate systems) found in 
the NetCDF file.
      * This method returns a direct reference to an internal array - do not 
modify.
      *
@@ -375,6 +411,10 @@ public final class DecoderWrapper extend
      */
     @Override
     public void close() throws IOException {
+        if (features != null) {
+            features.close();
+            features = null;
+        }
         file.close();
     }
 

Added: 
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/FeaturesWrapper.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/FeaturesWrapper.java?rev=1761084&view=auto
==============================================================================
--- 
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/FeaturesWrapper.java
 (added)
+++ 
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/FeaturesWrapper.java
 [UTF-8] Fri Sep 16 20:52:47 2016
@@ -0,0 +1,45 @@
+/*
+ * 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.ucar;
+
+import org.apache.sis.internal.netcdf.DiscreteSampling;
+import ucar.nc2.ft.FeatureCollection;
+
+
+/**
+ * A wrapper around the UCAR {@code ucar.nc2.ft} package.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.8
+ * @version 0.8
+ * @module
+ */
+final class FeaturesWrapper extends DiscreteSampling {
+    /**
+     * The feature dataset provided by the UCAR library.
+     */
+    private final FeatureCollection features;
+
+    /**
+     * Creates a new discrete sampling parser.
+     */
+    FeaturesWrapper(final FeatureCollection features) {
+        this.features = features;
+    }
+
+    // TODO
+}

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

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

Added: 
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/LogAdapter.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/LogAdapter.java?rev=1761084&view=auto
==============================================================================
--- 
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/LogAdapter.java
 (added)
+++ 
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/LogAdapter.java
 [UTF-8] Fri Sep 16 20:52:47 2016
@@ -0,0 +1,123 @@
+/*
+ * 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.ucar;
+
+import org.apache.sis.util.CharSequences;
+import org.apache.sis.util.logging.WarningListeners;
+
+
+/**
+ * Forwards NetCDF logging to the Apache SIS warning listeners.
+ * NetCDF sends message to a user-specified {@link java.util.Formatter} with 
one message per line.
+ * This class intercepts the characters and send them to the {@link 
WarningListeners} every time
+ * that a complete line has been received.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.8
+ * @version 0.8
+ * @module
+ */
+final class LogAdapter implements Appendable {
+    /**
+     * Temporary buffer where to append the NetCDF logging messages.
+     */
+    private final StringBuilder buffer = new StringBuilder();
+
+    /**
+     * Where to sends the warning messages.
+     */
+    private final WarningListeners<?> listeners;
+
+    /**
+     * Creates a new adapter which will send lines to the given listeners.
+     */
+    LogAdapter(final WarningListeners<?> listeners) {
+        this.listeners = listeners;
+    }
+
+    /**
+     * Appends the given message and forwards to the listeners after we 
completed a line.
+     */
+    @Override
+    public Appendable append(final CharSequence message) {
+        if (message.length() != 0) {
+            final CharSequence[] sp = CharSequences.splitOnEOL(message);
+            int count = sp.length;
+            /*
+             * If the last line does not ends with a EOL character, we will 
not send it to the listeners.
+             * Instead we will copy it to the buffer for concatenation with 
the next characters appended.
+             */
+            final char c = message.charAt(message.length() - 1);
+            if (c != '\r' && c != '\n') {
+                count--;
+            }
+            /*
+             * Send complete lines to the warning listeners.
+             */
+            for (int i=0; i<count; i++) {
+                final CharSequence line = sp[i];
+                if (buffer.length() != 0) {
+                    warning(buffer.append(line));
+                    buffer.setLength(0);
+                } else {
+                    warning(line);
+                }
+            }
+            /*
+             * If the last line has not been sent to the warning listeners, 
copy in the buffer
+             * for next iteration.
+             */
+            if (count != sp.length) {
+                buffer.append(sp[count]);
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Appends the given message and forwards to the listeners after we 
completed a line.
+     */
+    @Override
+    public Appendable append(CharSequence message, int start, int end) {
+        if (message == null) message = "null";              // For compliance 
with Appendable specification.
+        return append(message.subSequence(start, end));
+    }
+
+    /**
+     * Appends the given character and forwards to the listeners after we 
completed a line.
+     */
+    @Override
+    public Appendable append(char c) {
+        if (c != '\r' && c != '\n') {
+            buffer.append(c);
+        } else if (buffer.length() != 0) {
+            warning(buffer);
+            buffer.setLength(0);
+        }
+        return this;
+    }
+
+    /**
+     * Sends the given message to the listeners if the message is non-white.
+     */
+    private void warning(CharSequence message) {
+        message = CharSequences.trimWhitespaces(message);
+        if (message.length() != 0) {
+            listeners.warning(message.toString(), null);
+        }
+    }
+}

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

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

Modified: 
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java?rev=1761084&r1=1761083&r2=1761084&view=diff
==============================================================================
--- 
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
 [UTF-8] Fri Sep 16 20:52:47 2016
@@ -453,7 +453,7 @@ final class MetadataReader {
                 if (resource == null) resource = createOnlineResource(url);
                 contact = createContact(address, resource);
             }
-            if (individualName != null || organisationName != null || contact 
!= null) { // Do not test role.
+            if (individualName != null || organisationName != null || contact 
!= null) {        // Do not test role.
                 AbstractParty party = null;
                 if (individualName   != null) party = new 
DefaultIndividual(individualName, null, null);
                 if (organisationName != null) party = new 
DefaultOrganisation(organisationName, null, (Individual) party, null);
@@ -475,9 +475,9 @@ final class MetadataReader {
     private Citation createCitation(final Identifier identifier) throws 
IOException {
         String title = stringValue(TITLE);
         if (title == null) {
-            title = stringValue("full_name"); // THREDDS attribute documented 
in TITLE javadoc.
+            title = stringValue("full_name");   // THREDDS attribute 
documented in TITLE javadoc.
             if (title == null) {
-                title = stringValue("name"); // THREDDS attribute documented 
in TITLE javadoc.
+                title = stringValue("name");    // THREDDS attribute 
documented in TITLE javadoc.
                 if (title == null) {
                     title = decoder.getTitle();
                 }

Modified: 
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java?rev=1761084&r1=1761083&r2=1761084&view=diff
==============================================================================
--- 
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java
 [UTF-8] Fri Sep 16 20:52:47 2016
@@ -28,6 +28,9 @@ import org.apache.sis.storage.DataStoreC
 import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.internal.netcdf.Decoder;
 import org.apache.sis.metadata.ModifiableMetadata;
+import org.apache.sis.util.CharSequences;
+import org.apache.sis.util.Version;
+import ucar.nc2.constants.CDM;
 
 
 /**
@@ -97,6 +100,25 @@ public class NetcdfStore extends DataSto
     }
 
     /**
+     * Returns the version number of the Climate and Forecast (CF) conventions 
used in the NetCDF file.
+     * The use of CF convention is mandated by the OGC 11-165r2 standard
+     * (<cite>CF-netCDF3 Data Model Extension standard</cite>).
+     *
+     * @return CF-convention version, or {@code null} if no information about 
CF convention has been found.
+     * @throws DataStoreException if an error occurred while reading the data.
+     *
+     * @since 0.8
+     */
+    public synchronized Version getConventionVersion() throws 
DataStoreException {
+        for (final CharSequence value : 
CharSequences.split(decoder.stringValue(CDM.CONVENTIONS), ',')) {
+            if (CharSequences.regionMatches(value, 0, "CF-", true)) {
+                return new Version(value.subSequence(3, 
value.length()).toString());
+            }
+        }
+        return null;
+    }
+
+    /**
      * Closes this NetCDF store and releases any underlying resources.
      *
      * @throws DataStoreException if an error occurred while closing the 
NetCDF file.

Modified: 
sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/DecoderTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/DecoderTest.java?rev=1761084&r1=1761083&r2=1761084&view=diff
==============================================================================
--- 
sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/DecoderTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/DecoderTest.java
 [UTF-8] Fri Sep 16 20:52:47 2016
@@ -34,7 +34,7 @@ import static org.apache.sis.storage.net
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.8
  * @module
  */
 public strictfp class DecoderTest extends TestCase {
@@ -112,4 +112,22 @@ public strictfp class DecoderTest extend
             date("1993-04-10 00:00:00")
         }, decoder.numberToDate("days since 1970-01-01T00:00:00Z", 8.75, 
-2.75, 8500));
     }
+
+    /**
+     * Tests {@link Decoder#getTitle()} and {@link Decoder#getId()}.
+     *
+     * @throws IOException if an I/O error occurred while opening the file.
+     * @throws DataStoreException if a logical error occurred.
+     */
+    @Test
+    public void testGetTitleAndID() throws IOException, DataStoreException {
+        final Decoder decoder = selectDataset(NCEP);
+        /*
+         * Actually we really want a null value, even if the NCEP file 
contains 'title' and 'id' attributes,
+         * because the decoder methods are supposed to check only for the 
"_Title" and "_Id" attributes as a
+         * last resort fallback when MetadataReader failed to find the title 
and identifier by itself.
+         */
+        assertNull("title", decoder.getTitle());
+        assertNull("id",    decoder.getId());
+    }
 }

Modified: 
sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/TestCase.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/TestCase.java?rev=1761084&r1=1761083&r2=1761084&view=diff
==============================================================================
--- 
sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/TestCase.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/TestCase.java
 [UTF-8] Fri Sep 16 20:52:47 2016
@@ -124,7 +124,7 @@ public abstract strictfp class TestCase
      * @throws DataStoreException if a logical error occurred.
      */
     protected final Decoder selectDataset(final String name) throws 
IOException, DataStoreException {
-        synchronized (DECODERS) { // Paranoiac safety, but should not be used 
in multi-threads environment.
+        synchronized (DECODERS) {               // Paranoiac safety, but 
should not be used in multi-threads environment.
             decoder = DECODERS.get(name);
             if (decoder == null) {
                 decoder = createDecoder(name);
@@ -132,7 +132,7 @@ public abstract strictfp class TestCase
                 assertNull(DECODERS.put(name, decoder));
             }
             decoder.setSearchPath(GLOBAL);
-            return decoder; // Reminder: Decoder instances are not thread-safe.
+            return decoder;                     // Reminder: Decoder instances 
are not thread-safe.
         }
     }
 
@@ -145,7 +145,7 @@ public abstract strictfp class TestCase
     @AfterClass
     public static void closeAllDecoders() throws IOException {
         Throwable failure = null;
-        synchronized (DECODERS) { // Paranoiac safety.
+        synchronized (DECODERS) {               // Paranoiac safety.
             final Iterator<Decoder> it = DECODERS.values().iterator();
             while (it.hasNext()) {
                 final Decoder decoder = it.next();

Modified: 
sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/NetcdfStoreTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/NetcdfStoreTest.java?rev=1761084&r1=1761083&r2=1761084&view=diff
==============================================================================
--- 
sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/NetcdfStoreTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/NetcdfStoreTest.java
 [UTF-8] Fri Sep 16 20:52:47 2016
@@ -21,6 +21,7 @@ import org.opengis.wrapper.netcdf.IOTest
 import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.test.DependsOn;
+import org.apache.sis.util.Version;
 import org.junit.Test;
 
 import static org.opengis.test.Assert.*;
@@ -31,7 +32,7 @@ import static org.opengis.test.Assert.*;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.8
  * @module
  */
 @DependsOn({
@@ -63,4 +64,19 @@ public final strictfp class NetcdfStoreT
         }
         MetadataReaderTest.compareToExpected(metadata);
     }
+
+    /**
+     * Tests {@link Decoder#getConventionVersion()}.
+     *
+     * @throws DataStoreException if an error occurred while reading the 
NetCDF file.
+     */
+    @Test
+    public void testGetConventionVersion() throws DataStoreException {
+        final Version version;
+        try (NetcdfStore store = create(LANDSAT)) {
+            version = store.getConventionVersion();
+        }
+        assertEquals("major", 1, version.getMajor());
+        assertEquals("minor", 0, version.getMinor());
+    }
 }



Reply via email to