sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1760780 [10/11] - in /sis/branches/JDK7: ./ application/sis-webapp/src/test/ core/sis-feature/src/main/java/org/apache/sis/feature/ core/sis-metadata/src/main/java/org/apache/sis/metadata/ core/sis-metadata/src/main/java/org/apache/sis/met...
Date Wed, 14 Sep 2016 21:29:51 GMT
Modified: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java?rev=1760780&r1=1760779&r2=1760780&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java [UTF-8] Wed Sep 14 21:29:50 2016
@@ -87,8 +87,8 @@ public final class DecoderWrapper extend
      * {@link NetcdfFile} instance, the {@link NetcdfDataset} subclass is necessary in order to
      * get coordinate system information.
      *
-     * @param listeners Where to send the warnings.
-     * @param file The NetCDF file from which to read data.
+     * @param listeners  where to send the warnings.
+     * @param file       the NetCDF file from which to read data.
      */
     public DecoderWrapper(final WarningListeners<?> listeners, final NetcdfFile file) {
         super(listeners);
@@ -98,9 +98,9 @@ public final class DecoderWrapper extend
     /**
      * Creates a new decoder for the given filename.
      *
-     * @param  listeners Where to send the warnings.
-     * @param  filename  The name of the NetCDF file from which to read data.
-     * @throws IOException If an error occurred while opening the NetCDF file.
+     * @param  listeners  where to send the warnings.
+     * @param  filename   the name of the NetCDF file from which to read data.
+     * @throws IOException if an error occurred while opening the NetCDF file.
      */
     public DecoderWrapper(final WarningListeners<?> listeners, final String filename) throws IOException {
         super(listeners);
@@ -119,7 +119,7 @@ public final class DecoderWrapper extend
             if (name != null) {
                 final Group group = file.findGroup(name);
                 if (group == null) {
-                    continue; // Group not found - do not increment the counter.
+                    continue;                   // Group not found - do not increment the counter.
                 }
                 groups[count] = group;
             }
@@ -133,7 +133,7 @@ public final class DecoderWrapper extend
      * a subset of the array given to {@link #setSearchPath(String[])} since only the name of
      * groups which have been found in the NetCDF file are returned by this method.
      *
-     * @return The current search path.
+     * @return the current search path.
      */
     @Override
     public String[] getSearchPath() {
@@ -156,9 +156,9 @@ public final class DecoderWrapper extend
      * <p>The {@code name} argument is typically (but is not restricted too) one of the constants
      * defined in the {@link AttributeNames} class.</p>
      *
-     * @param  group The group in which to search the attribute, or {@code null} for global attributes.
-     * @param  name  The name of the attribute to search (can not be null).
-     * @return The attribute, or {@code null} if none.
+     * @param  group  the group in which to search the attribute, or {@code null} for global attributes.
+     * @param  name   the name of the attribute to search (can not be null).
+     * @return the attribute, or {@code null} if none.
      */
     private Attribute findAttribute(final Group group, final String name) {
         return (group != null) ? group.findAttributeIgnoreCase(name) : file.findGlobalAttributeIgnoreCase(name);
@@ -169,12 +169,12 @@ public final class DecoderWrapper extend
      * This method searches in the groups specified by the last call to {@link #setSearchPath(String[])}.
      * Null values and empty strings are ignored.
      *
-     * @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.
+     * @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.
      */
     @Override
     public String stringValue(final String name) {
-        if (name != null) { // For createResponsibleParty(...) convenience.
+        if (name != null) {                                 // For createResponsibleParty(...) convenience.
             for (final Group group : groups) {
                 final Attribute attribute = findAttribute(group, name);
                 if (attribute != null && attribute.isString()) {
@@ -191,8 +191,8 @@ public final class DecoderWrapper extend
     /**
      * 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.
+     * @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.
      */
     @Override
     public Number numericValue(final String name) {
@@ -217,8 +217,8 @@ public final class DecoderWrapper extend
     /**
      * Returns the value of the attribute of the given name as a date, 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.
+     * @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.
      */
     @Override
     public Date dateValue(final String name) {
@@ -247,8 +247,8 @@ public final class DecoderWrapper extend
      * Converts the given numerical values to date, using the information provided in the given unit symbol.
      * The unit symbol is typically a string like <cite>"days since 1970-01-01T00:00:00Z"</cite>.
      *
-     * @param  values The values to convert. May contains {@code null} elements.
-     * @return The converted values. May contains {@code null} elements.
+     * @param  values  the values to convert. May contains {@code null} elements.
+     * @return the converted values. May contains {@code null} elements.
      */
     @Override
     public Date[] numberToDate(final String symbol, final Number... values) {
@@ -272,7 +272,7 @@ public final class DecoderWrapper extend
     /**
      * Returns the globally unique dataset identifier as determined by the UCAR library.
      *
-     * @return The global dataset identifier, or {@code null} if none.
+     * @return the global dataset identifier, or {@code null} if none.
      */
     @Override
     public String getId() {
@@ -282,7 +282,7 @@ public final class DecoderWrapper extend
     /**
      * Returns the human readable title as determined by the UCAR library.
      *
-     * @return The dataset title, or {@code null} if none.
+     * @return the dataset title, or {@code null} if none.
      */
     @Override
     public String getTitle() {
@@ -293,10 +293,10 @@ public final class DecoderWrapper extend
      * Returns all variables found in the NetCDF file.
      * This method returns a direct reference to an internal array - do not modify.
      *
-     * @return All variables, or an empty array if none.
+     * @return all variables, or an empty array if none.
      */
     @Override
-    @SuppressWarnings("null")
+    @SuppressWarnings({"ReturnOfCollectionOrArrayField", "null"})
     public Variable[] getVariables() {
         if (variables == null) {
             final List<Dimension> dimensions = file.getDimensions();
@@ -313,11 +313,11 @@ public final class DecoderWrapper extend
      * 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.
      *
-     * @return All grid geometries, or an empty array if none.
-     * @throws IOException If an I/O operation was necessary but failed.
+     * @return all grid geometries, or an empty array if none.
+     * @throws IOException if an I/O operation was necessary but failed.
      */
     @Override
-    @SuppressWarnings("null")
+    @SuppressWarnings({"ReturnOfCollectionOrArrayField", "null"})
     public GridGeometry[] getGridGeometries() throws IOException {
         if (geometries == null) {
             List<CoordinateSystem> systems = null;
@@ -341,7 +341,7 @@ public final class DecoderWrapper extend
      * Invoked by the UCAR NetCDF library for checking if the reading process has been canceled.
      * This method returns the {@link #canceled} flag.
      *
-     * @return The {@link #canceled} flag.
+     * @return the {@link #canceled} flag.
      */
     @Override
     public boolean isCancel() {
@@ -351,8 +351,8 @@ public final class DecoderWrapper extend
     /**
      * Invoked by the UCAR library during the reading process for progress information.
      *
-     * @param message The message to show to the user.
-     * @param progress Count of progress, or -1 if unknown. This is not necessarily a percentage done.
+     * @param  message   the message to show to the user.
+     * @param  progress  count of progress, or -1 if unknown. This is not necessarily a percentage done.
      */
     @Override
     public void setProgress(final String message, final int progress) {
@@ -361,7 +361,7 @@ public final class DecoderWrapper extend
     /**
      * Invoked by the UCAR NetCDF library when an error occurred.
      *
-     * @param message The error message.
+     * @param  message  the error message.
      */
     @Override
     public void setError(final String message) {
@@ -371,7 +371,7 @@ public final class DecoderWrapper extend
     /**
      * Closes the NetCDF file.
      *
-     * @throws IOException If an error occurred while closing the file.
+     * @throws IOException if an error occurred while closing the file.
      */
     @Override
     public void close() throws IOException {

Modified: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridGeometryWrapper.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridGeometryWrapper.java?rev=1760780&r1=1760779&r2=1760780&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridGeometryWrapper.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridGeometryWrapper.java [UTF-8] Wed Sep 14 21:29:50 2016
@@ -53,7 +53,7 @@ final class GridGeometryWrapper extends
     /**
      * Creates a new grid geometry for the given NetCDF coordinate system.
      *
-     * @param cs The NetCDF coordinate system, or {@code null} if none.
+     * @param  cs  the NetCDF coordinate system, or {@code null} if none.
      */
     GridGeometryWrapper(final CoordinateSystem cs) {
         netcdfCS = cs;

Modified: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java?rev=1760780&r1=1760779&r2=1760780&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java [UTF-8] Wed Sep 14 21:29:50 2016
@@ -190,10 +190,10 @@ final class VariableWrapper extends Vari
     /**
      * Reads a sub-sampled sub-area of the variable.
      *
-     * @param  areaLower   Index of the first value to read along each dimension.
-     * @param  areaUpper   Index after the last value to read along each dimension.
-     * @param  subsampling Sub-sampling along each dimension. 1 means no sub-sampling.
-     * @return The data as an array of a Java primitive type.
+     * @param  areaLower    index of the first value to read along each dimension.
+     * @param  areaUpper    index after the last value to read along each dimension.
+     * @param  subsampling  sub-sampling along each dimension. 1 means no sub-sampling.
+     * @return the data as an array of a Java primitive type.
      */
     @Override
     public Object read(final int[] areaLower, final int[] areaUpper, final int[] subsampling)

Modified: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/package-info.java?rev=1760780&r1=1760779&r2=1760780&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/package-info.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/package-info.java [UTF-8] Wed Sep 14 21:29:50 2016
@@ -21,7 +21,7 @@
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.8
  * @module
  */
 package org.apache.sis.internal.netcdf.ucar;

Modified: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/AttributeNames.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/AttributeNames.java?rev=1760780&r1=1760779&r2=1760780&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/AttributeNames.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/AttributeNames.java [UTF-8] Wed Sep 14 21:29:50 2016
@@ -493,13 +493,12 @@ public class AttributeNames {
         /**
          * Creates a new set of attribute names. Any argument can be {@code null} if not applicable.
          *
-         * @param name        The attribute name for the responsible's name.
-         * @param institution The attribute name for the responsible's institution.
-         * @param url         The attribute name for the responsible's URL.
-         * @param email       The attribute name for the responsible's email address.
-         * @param role        The attribute name for the responsible's role.
-         * @param defaultRole The role to use as a fallback if no attribute value is associated to the
-         *                    {@code role} key.
+         * @param name         the attribute name for the responsible's name.
+         * @param institution  the attribute name for the responsible's institution.
+         * @param url          the attribute name for the responsible's URL.
+         * @param email        the attribute name for the responsible's email address.
+         * @param role         the attribute name for the responsible's role.
+         * @param defaultRole  the role to use as a fallback if no attribute value is associated to the {@code role} key.
          */
         public Responsible(final String name, final String institution, final String url, final String email,
                 final String role, final Role defaultRole)
@@ -789,13 +788,13 @@ public class AttributeNames {
         /**
          * Creates a new set of attribute names.
          *
-         * @param type       The default ISO-19115 dimension name type, or {@code null} if none.
-         * @param min        The attribute name for the minimal value of the bounding box.
-         * @param max        The attribute name for the maximal value of the bounding box.
-         * @param span       The attribute name for the difference between the minimal and maximal values.
-         * @param resolution The attribute name for a further refinement of the geospatial bounding box.
-         * @param units      The attribute name for the bounding box units of measurement.
-         * @param positive   The attribute name for indicating which direction is positive.
+         * @param type        the default ISO-19115 dimension name type, or {@code null} if none.
+         * @param min         the attribute name for the minimal value of the bounding box.
+         * @param max         the attribute name for the maximal value of the bounding box.
+         * @param span        the attribute name for the difference between the minimal and maximal values.
+         * @param resolution  the attribute name for a further refinement of the geospatial bounding box.
+         * @param units       the attribute name for the bounding box units of measurement.
+         * @param positive    the attribute name for indicating which direction is positive.
          */
         public Dimension(final DimensionNameType type, final String min, final String max, final String span,
                 final String resolution,final String units, final String positive)

Modified: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java?rev=1760780&r1=1760779&r2=1760780&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java [UTF-8] Wed Sep 14 21:29:50 2016
@@ -177,8 +177,8 @@ final class MetadataReader {
     /**
      * Creates a new <cite>NetCDF to ISO</cite> mapper for the given source.
      *
-     * @param  decoder The source of NetCDF attributes.
-     * @throws IOException If an I/O operation was necessary but failed.
+     * @param  decoder  the source of NetCDF attributes.
+     * @throws IOException if an I/O operation was necessary but failed.
      */
     MetadataReader(final Decoder decoder) throws IOException {
         this.decoder = decoder;
@@ -198,7 +198,7 @@ final class MetadataReader {
     /**
      * Returns the localized error resource bundle for the locale given by {@link #getLocale()}.
      *
-     * @return The localized error resource bundle.
+     * @return the localized error resource bundle.
      */
     private Errors errors() {
         return Errors.getResources(decoder.listeners.getLocale());
@@ -298,8 +298,8 @@ final class MetadataReader {
      * Returns {@code true} if the given NetCDF attribute is either null or equals to one
      * of the values in the given collection.
      *
-     * @param metadata  The value stored in the metadata object.
-     * @param attribute The value parsed from the NetCDF file.
+     * @param  metadata   the value stored in the metadata object.
+     * @param  attribute  the value parsed from the NetCDF file.
      */
     private static boolean canShare(final Collection<String> metadata, final String attribute) {
         return (attribute == null) || metadata.contains(attribute);
@@ -308,8 +308,8 @@ final class MetadataReader {
     /**
      * Returns {@code true} if the given URL is null, or if the given resource contains that URL.
      *
-     * @param resource  The value stored in the metadata object.
-     * @param url       The value parsed from the NetCDF file.
+     * @param  resource  the value stored in the metadata object.
+     * @param  url       the value parsed from the NetCDF file.
      */
     private static boolean canShare(final OnlineResource resource, final String url) {
         return (url == null) || (resource != null && canShare(resource.getLinkage().toString(), url));
@@ -318,8 +318,8 @@ final class MetadataReader {
     /**
      * Returns {@code true} if the given email is null, or if the given address contains that email.
      *
-     * @param address  The value stored in the metadata object.
-     * @param email    The value parsed from the NetCDF file.
+     * @param  address  the value stored in the metadata object.
+     * @param  email    the value parsed from the NetCDF file.
      */
     private static boolean canShare(final Address address, final String email) {
         return (email == null) || (address != null && canShare(address.getElectronicMailAddresses(), email));
@@ -330,8 +330,8 @@ final class MetadataReader {
      * declares the URL as a mandatory attribute, this method will ignore all other attributes
      * if the given URL is null.
      *
-     * @param  url The URL (mandatory - if {@code null}, no resource will be created).
-     * @return The online resource, or {@code null} if the URL was null.
+     * @param  url  the URL (mandatory - if {@code null}, no resource will be created).
+     * @return the online resource, or {@code null} if the URL was null.
      */
     private OnlineResource createOnlineResource(final String url) {
         if (url != null) try {
@@ -379,10 +379,10 @@ final class MetadataReader {
      * <p>Implementation note: this method tries to reuse the existing {@link #pointOfContact} instance,
      * or part of it, if it is suitable.</p>
      *
-     * @param  keys The group of attribute names to use for fetching the values.
+     * @param  keys  the group of attribute names to use for fetching the values.
      * @param  isPointOfContact {@code true} for forcing the role to {@link Role#POINT_OF_CONTACT}.
-     * @return The responsible party, or {@code null} if none.
-     * @throws IOException If an I/O operation was necessary but failed.
+     * @return the responsible party, or {@code null} if none.
+     * @throws IOException if an I/O operation was necessary but failed.
      *
      * @see AttributeNames#CREATOR
      * @see AttributeNames#CONTRIBUTOR
@@ -469,8 +469,8 @@ final class MetadataReader {
      * Creates a {@code Citation} element if at least one of the required attributes is non-null.
      * This method will reuse the {@link #pointOfContact} field, if non-null and suitable.
      *
-     * @param  identifier The citation {@code <gmd:identifier>} attribute.
-     * @throws IOException If an I/O operation was necessary but failed.
+     * @param  identifier  the citation {@code <gmd:identifier>} attribute.
+     * @throws IOException if an I/O operation was necessary but failed.
      */
     private Citation createCitation(final Identifier identifier) throws IOException {
         String title = stringValue(TITLE);
@@ -518,9 +518,9 @@ final class MetadataReader {
      * Creates a {@code DataIdentification} element if at least one of the required attributes is non-null.
      * This method will reuse the {@link #pointOfContact} value, if non-null and suitable.
      *
-     * @param  identifier The citation {@code <gmd:identifier>} attribute.
-     * @param  publisher  The publisher names, built by the caller in an opportunist way.
-     * @throws IOException If an I/O operation was necessary but failed.
+     * @param  identifier  the citation {@code <gmd:identifier>} attribute.
+     * @param  publisher   the publisher names, built by the caller in an opportunist way.
+     * @throws IOException if an I/O operation was necessary but failed.
      */
     private DataIdentification createIdentificationInfo(final Identifier identifier,
             final Set<InternationalString> publisher) throws IOException
@@ -611,7 +611,7 @@ final class MetadataReader {
      * For more consistent results, the caller should restrict the {@linkplain Decoder#setSearchPath
      * search path} to a single group before invoking this method.
      *
-     * @throws IOException If an I/O operation was necessary but failed.
+     * @throws IOException if an I/O operation was necessary but failed.
      */
     private Keywords createKeywords(final KeywordType type, final boolean standard) throws IOException {
         final String list = stringValue(standard ? STANDARD_NAME : KEYWORDS);
@@ -640,9 +640,9 @@ final class MetadataReader {
     /**
      * Creates a {@code <gmd:spatialRepresentationInfo>} element from the given grid geometries.
      *
-     * @param  cs The grid geometry (related to the NetCDF coordinate system).
-     * @return The grid spatial representation info.
-     * @throws IOException If an I/O operation was necessary but failed.
+     * @param  cs  the grid geometry (related to the NetCDF coordinate system).
+     * @return the grid spatial representation info.
+     * @throws IOException if an I/O operation was necessary but failed.
      */
     private GridSpatialRepresentation createSpatialRepresentationInfo(final GridGeometry cs) throws IOException {
         final DefaultGridSpatialRepresentation grid = new DefaultGridSpatialRepresentation();
@@ -785,8 +785,8 @@ final class MetadataReader {
     /**
      * Creates a {@code <gmd:contentInfo>} elements from all applicable NetCDF attributes.
      *
-     * @return The content information.
-     * @throws IOException If an I/O operation was necessary but failed.
+     * @return the content information.
+     * @throws IOException if an I/O operation was necessary but failed.
      */
     private Collection<DefaultCoverageDescription> createContentInfo() throws IOException {
         final Map<List<String>, DefaultCoverageDescription> contents = new HashMap<>(4);
@@ -845,9 +845,9 @@ final class MetadataReader {
     /**
      * Creates a {@code <gmd:dimension>} element from the given variable.
      *
-     * @param  variable The NetCDF variable.
-     * @return The sample dimension information.
-     * @throws IOException If an I/O operation was necessary but failed.
+     * @param  variable  the NetCDF variable.
+     * @return the sample dimension information.
+     * @throws IOException if an I/O operation was necessary but failed.
      */
     private Band createSampleDimension(final Variable variable) throws IOException {
         final DefaultBand band = new DefaultBand();
@@ -878,13 +878,13 @@ final class MetadataReader {
      * <p><b>Note:</b> ISO 19115 range elements are approximatively equivalent to
      * {@link org.apache.sis.coverage.Category} in the {@code sis-coverage} module.</p>
      *
-     * @param  variable The NetCDF variable.
-     * @param  name     One of the elements in the {@link AttributeNames#FLAG_NAMES} attribute, or {@code null}.
-     * @param  meaning  One of the elements in the {@link AttributeNames#FLAG_MEANINGS} attribute or {@code null}.
-     * @param  mask     One of the elements in the {@link AttributeNames#FLAG_MASKS} attribute or {@code null}.
-     * @param  value    One of the elements in the {@link AttributeNames#FLAG_VALUES} attribute or {@code null}.
-     * @return The sample dimension information or {@code null} if none.
-     * @throws IOException If an I/O operation was necessary but failed.
+     * @param  variable  the NetCDF variable.
+     * @param  name      one of the elements in the {@link AttributeNames#FLAG_NAMES} attribute, or {@code null}.
+     * @param  meaning   one of the elements in the {@link AttributeNames#FLAG_MEANINGS} attribute or {@code null}.
+     * @param  mask      one of the elements in the {@link AttributeNames#FLAG_MASKS} attribute or {@code null}.
+     * @param  value     one of the elements in the {@link AttributeNames#FLAG_VALUES} attribute or {@code null}.
+     * @return the sample dimension information or {@code null} if none.
+     * @throws IOException if an I/O operation was necessary but failed.
      */
     private RangeElementDescription createRangeElementDescription(final Variable variable,
             final String name, final String meaning, final Number mask, final Number value) throws IOException
@@ -909,8 +909,8 @@ final class MetadataReader {
      *   <li>{@value #IDENTIFIER}, or {@link ucar.nc2.NetcdfFile#getId()} if no identifier attribute was found.</li>
      * </ul>
      *
-     * @return The globally unique identifier, or {@code null} if none.
-     * @throws IOException If an I/O operation was necessary but failed.
+     * @return the globally unique identifier, or {@code null} if none.
+     * @throws IOException if an I/O operation was necessary but failed.
      */
     private Identifier getFileIdentifier() throws IOException {
         String identifier = stringValue(IDENTIFIER);
@@ -927,8 +927,8 @@ final class MetadataReader {
     /**
      * Creates an ISO {@code Metadata} object from the information found in the NetCDF file.
      *
-     * @return The ISO metadata object.
-     * @throws IOException If an I/O operation was necessary but failed.
+     * @return the ISO metadata object.
+     * @throws IOException if an I/O operation was necessary but failed.
      */
     public Metadata read() throws IOException {
         final DefaultMetadata metadata = new DefaultMetadata();

Modified: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java?rev=1760780&r1=1760779&r2=1760780&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java [UTF-8] Wed Sep 14 21:29:50 2016
@@ -83,7 +83,7 @@ public class NetcdfStore extends DataSto
      * @throws DataStoreException if an error occurred while reading the data.
      */
     @Override
-    public Metadata getMetadata() throws DataStoreException {
+    public synchronized Metadata getMetadata() throws DataStoreException {
         if (metadata == null) try {
             final MetadataReader reader = new MetadataReader(decoder);
             metadata = reader.read();
@@ -102,7 +102,7 @@ public class NetcdfStore extends DataSto
      * @throws DataStoreException if an error occurred while closing the NetCDF file.
      */
     @Override
-    public void close() throws DataStoreException {
+    public synchronized void close() throws DataStoreException {
         metadata = null;
         try {
             decoder.close();

Modified: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/package-info.java?rev=1760780&r1=1760779&r2=1760780&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/package-info.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/package-info.java [UTF-8] Wed Sep 14 21:29:50 2016
@@ -49,7 +49,7 @@
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.8
  * @module
  */
 package org.apache.sis.storage.netcdf;

Modified: sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/impl/AttributeTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/impl/AttributeTest.java?rev=1760780&r1=1760779&r2=1760780&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/impl/AttributeTest.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/impl/AttributeTest.java [UTF-8] Wed Sep 14 21:29:50 2016
@@ -19,7 +19,7 @@ package org.apache.sis.internal.netcdf.i
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
-import static org.apache.sis.test.Assert.*;
+import static org.junit.Assert.*;
 
 
 /**
@@ -27,21 +27,17 @@ import static org.apache.sis.test.Assert
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.5 (derived from 0.3)
- * @version 0.5
+ * @version 0.8
  * @module
  */
 public final strictfp class AttributeTest extends TestCase {
     /**
-     * Tests the {@link Attribute#dateToISO(String)} method.
+     * Tests the {@link Attribute#numberValues()} method.
      */
     @Test
-    public void testDateToISO() {
-        assertEquals("2009-01-01T06:00:00+01:00", Attribute.dateToISO("2009-01-01T06:00:00+01:00"));
-        assertEquals("2005-09-22T04:30:15Z",      Attribute.dateToISO("2005-09-22T04:30:15Z"));
-        assertEquals("2005-09-22T04:30:15Z",      Attribute.dateToISO("2005-09-22T04:30:15"));
-        assertEquals("2005-09-22T04:30:00Z",      Attribute.dateToISO("2005-09-22T04:30"));
-        assertEquals("2005-09-22T04:00:00Z",      Attribute.dateToISO("2005-09-22T04"));
-        assertEquals("2005-09-22T00:00:00Z",      Attribute.dateToISO("2005-09-22"));
-        assertEquals("2005-09-22T00:00:00Z",      Attribute.dateToISO("2005-9-22"));
+    public void testNumberValues() {
+        final Attribute a = new Attribute("aName", new float[] {10, 20, 1});
+        assertArrayEquals("numberValues", new Number[] { 10f,    20f,    1f  }, a.numberValues());
+        assertArrayEquals("stringValues", new String[] {"10.0", "20.0", "1.0"}, a.stringValues());
     }
 }

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java?rev=1760780&r1=1760779&r2=1760780&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java [UTF-8] Wed Sep 14 21:29:50 2016
@@ -17,43 +17,77 @@
 package org.apache.sis.internal.storage;
 
 import java.util.Date;
+import java.util.Locale;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.nio.charset.Charset;
 import org.opengis.util.InternationalString;
+import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Role;
 import org.opengis.metadata.citation.DateType;
+import org.opengis.metadata.spatial.Dimension;
+import org.opengis.metadata.spatial.DimensionNameType;
 import org.opengis.metadata.constraint.Restriction;
+import org.opengis.metadata.maintenance.ScopeCode;
+import org.opengis.metadata.acquisition.Context;
+import org.opengis.metadata.acquisition.OperationType;
+import org.opengis.metadata.identification.Progress;
 import org.opengis.referencing.ReferenceSystem;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.operation.TransformException;
 import org.apache.sis.geometry.AbstractEnvelope;
 import org.apache.sis.metadata.iso.DefaultMetadata;
+import org.apache.sis.metadata.iso.DefaultIdentifier;
+import org.apache.sis.metadata.iso.DefaultMetadataScope;
 import org.apache.sis.metadata.iso.extent.DefaultExtent;
+import org.apache.sis.metadata.iso.extent.DefaultTemporalExtent;
+import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
+import org.apache.sis.metadata.iso.spatial.DefaultDimension;
+import org.apache.sis.metadata.iso.spatial.DefaultGridSpatialRepresentation;
 import org.apache.sis.metadata.iso.content.DefaultAttributeGroup;
 import org.apache.sis.metadata.iso.content.DefaultSampleDimension;
 import org.apache.sis.metadata.iso.content.DefaultCoverageDescription;
+import org.apache.sis.metadata.iso.content.DefaultFeatureCatalogueDescription;
+import org.apache.sis.metadata.iso.content.DefaultImageDescription;
+import org.apache.sis.metadata.iso.content.DefaultFeatureTypeInfo;
 import org.apache.sis.metadata.iso.citation.AbstractParty;
 import org.apache.sis.metadata.iso.citation.DefaultCitation;
 import org.apache.sis.metadata.iso.citation.DefaultCitationDate;
 import org.apache.sis.metadata.iso.citation.DefaultResponsibility;
+import org.apache.sis.metadata.iso.citation.DefaultIndividual;
+import org.apache.sis.metadata.iso.citation.DefaultOrganisation;
 import org.apache.sis.metadata.iso.constraint.DefaultLegalConstraints;
+import org.apache.sis.metadata.iso.identification.DefaultResolution;
 import org.apache.sis.metadata.iso.identification.DefaultDataIdentification;
 import org.apache.sis.metadata.iso.distribution.DefaultDistribution;
 import org.apache.sis.metadata.iso.distribution.DefaultFormat;
+import org.apache.sis.metadata.iso.acquisition.DefaultAcquisitionInformation;
+import org.apache.sis.metadata.iso.acquisition.DefaultEvent;
+import org.apache.sis.metadata.iso.acquisition.DefaultInstrument;
+import org.apache.sis.metadata.iso.acquisition.DefaultOperation;
+import org.apache.sis.metadata.iso.acquisition.DefaultPlatform;
+import org.apache.sis.metadata.iso.acquisition.DefaultRequirement;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.Utilities;
 import org.apache.sis.util.iso.Types;
 
+import static java.util.Collections.singleton;
 import static org.apache.sis.internal.util.StandardDateFormat.MILLISECONDS_PER_DAY;
 
 // Branch-dependent imports
 import org.apache.sis.internal.jdk8.LocalDate;
+import org.apache.sis.internal.jdk8.JDK8;
+import org.opengis.feature.FeatureType;
 
 
 /**
  * Helper methods for the metadata created by {@code DataStore} implementations.
- * This class creates the metadata objects only when first needed.
+ * This is not yet a general-purpose builder suitable for public API, since the
+ * methods provided in this class are tailored for Apache SIS data store needs.
+ * API of this class may change in any future SIS versions.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Rémi Marechal (Geomatys)
@@ -63,6 +97,24 @@ import org.apache.sis.internal.jdk8.Loca
  */
 public class MetadataBuilder {
     /**
+     * Instructs {@link #newParty(byte)} that the next party to create should be an instance of
+     * {@link DefaultIndividual}.
+     *
+     * @see #partyType
+     * @see #newParty(byte)
+     */
+    public static final byte INDIVIDUAL = 1;
+
+    /**
+     * Instructs {@link #newParty(byte)} that the next party to create should be an instance of
+     * {@link DefaultOrganisation}.
+     *
+     * @see #partyType
+     * @see #newParty(byte)
+     */
+    public static final byte ORGANISATION = 2;
+
+    /**
      * The metadata created by this reader, or {@code null} if none.
      */
     private DefaultMetadata metadata;
@@ -98,14 +150,35 @@ public class MetadataBuilder {
     private DefaultExtent extent;
 
     /**
+     * Information about the platforms and sensors that collected the data, or {@code null} if none.
+     */
+    private DefaultAcquisitionInformation acquisition;
+
+    /**
+     * Platform where are installed the sensors that collected the data, or {@code null} if none.
+     */
+    private DefaultPlatform platform;
+
+    /**
+     * Information about the grid shape, or {@code null} if none.
+     */
+    private DefaultGridSpatialRepresentation gridRepresentation;
+
+    /**
      * Information about the content of a grid data cell, or {@code null} if none.
+     * May also be an instance of {@link DefaultImageDescription} if {@link #electromagnetic} is {@code true}.
      */
     private DefaultCoverageDescription coverageDescription;
 
     /**
+     * Information about the feature types, or {@code null} if none.
+     */
+    private DefaultFeatureCatalogueDescription featureDescription;
+
+    /**
      * Information about content type for groups of attributes for a specific range dimension, or {@code null} if none.
      */
-    private DefaultAttributeGroup attributGroup;
+    private DefaultAttributeGroup attributeGroup;
 
     /**
      * The characteristic of each dimension (layer) included in the resource, or {@code null} if none.
@@ -123,41 +196,69 @@ public class MetadataBuilder {
     private DefaultDistribution distribution;
 
     /**
+     * Whether the next party to create should be an instance of {@link DefaultIndividual} or {@link DefaultOrganisation}.
+     * Value can be {@link #INDIVIDUAL}, {@link #ORGANISATION} or 0 if unknown, in which case an {@link AbstractParty}
+     * will be created.
+     *
+     * @see #INDIVIDUAL
+     * @see #ORGANISATION
+     * @see #newParty(byte)
+     */
+    private byte partyType;
+
+    /**
+     * {@code true} if the next {@code CoverageDescription} to create will be a description of measurements
+     * in the electromagnetic spectrum. In that case, the coverage description will actually be an instance
+     * of {@code ImageDescription}.
+     */
+    private boolean electromagnetic;
+
+    /**
+     * For using the same instance of {@code Double} when the value is the same.
+     * We use this map because the same values appear many time in a Landsat file.
+     *
+     * @see #parseDouble(String)
+     */
+    private final Map<Number,Number> sharedNumbers = new HashMap<>();
+
+    /**
      * Creates a new metadata reader.
      */
     public MetadataBuilder() {
     }
 
     /**
-     * Returns the metadata as an unmodifiable object, or {@cod null} if none.
-     * After this method has been invoked, the metadata can not be modified anymore.
+     * Commits all pending information under the "responsible party" node (author, address, <i>etc</i>).
+     * If there is no pending party information, then invoking this method has no effect
+     * except setting the {@code type} flag.
+     * If new party information are added after this method call, they will be stored in a new element.
      *
-     * @return the metadata, or {@code null} if none.
+     * <p>This method does not need to be invoked unless a new "responsible party" node,
+     * separated from the previous one, is desired.</p>
+     *
+     * @param  type  {@link #INDIVIDUAL}, {@link #ORGANISATION} or 0 if unknown.
      */
-    public final DefaultMetadata result() {
-        commit();
-        if (metadata != null) {
-            metadata.freeze();
+    public final void newParty(final byte type) {
+        if (party != null) {
+            responsibility().getParties().add(party);
+            party = null;
         }
-        return metadata;
+        partyType = type;
     }
 
     /**
-     * Performs the links between the objects created in this builder. After this method has been invoked,
-     * all metadata objects should be reachable from the root {@link DefaultMetadata} object.
+     * Commits all pending information under the metadata "identification info" node (author, bounding box, <i>etc</i>).
+     * If there is no pending identification information, then invoking this method has no effect.
+     * If new identification info are added after this method call, they will be stored in a new element.
+     *
+     * <p>This method does not need to be invoked unless a new "identification info" node,
+     * separated from the previous one, is desired.</p>
      */
-    private void commit() {
+    public final void newIdentification() {
         /*
          * Construction shall be ordered from children to parents.
          */
-        if (extent != null) {
-            identification().getExtents().add(extent);
-            extent = null;
-        }
-        if (party != null) {
-            responsibility().getParties().add(party);
-            party = null;
-        }
+        newParty((byte) 0);
         if (responsibility != null) {
             citation().getCitedResponsibleParties().add(responsibility);
             responsibility = null;
@@ -166,26 +267,107 @@ public class MetadataBuilder {
             identification().setCitation(citation);
             citation = null;
         }
+        if (extent != null) {
+            identification().getExtents().add(extent);
+            extent = null;
+        }
         if (constraints != null) {
             identification().getResourceConstraints().add(constraints);
             constraints = null;
         }
+        if (identification != null) {
+            metadata().getIdentificationInfo().add(identification);
+            identification = null;
+        }
+    }
+
+    /**
+     * Commits all pending information under the metadata "acquisition" node (station, sensors, <i>etc</i>).
+     * If there is no pending acquisition information, then invoking this method has no effect.
+     * If new acquisition info are added after this method call, they will be stored in a new element.
+     *
+     * <p>This method does not need to be invoked unless a new "acquisition info" node,
+     * separated from the previous one, is desired.</p>
+     */
+    public final void newAcquisition() {
+        if (platform != null) {
+            acquisition().getPlatforms().add(platform);
+        }
+        if (acquisition != null) {
+            metadata().getAcquisitionInformation().add(acquisition);
+            acquisition = null;
+        }
+    }
+
+    /**
+     * Commits all pending information under the metadata "spatial representation" node (dimensions, <i>etc</i>).
+     * If there is no pending spatial representation information, then invoking this method has no effect.
+     * If new spatial representation info are added after this method call, they will be stored in a new element.
+     *
+     * <p>This method does not need to be invoked unless a new "spatial representation info" node,
+     * separated from the previous one, is desired.</p>
+     */
+    public final void newGridRepresentation() {
+        if (gridRepresentation != null) {
+            if (!gridRepresentation.isEmpty()) {
+                gridRepresentation.setNumberOfDimensions(shared(gridRepresentation.getAxisDimensionProperties().size()));
+            }
+            metadata.getSpatialRepresentationInfo().add(gridRepresentation);
+            gridRepresentation = null;
+        }
+    }
+
+    /**
+     * Commits all pending information under the metadata "content info" node (bands, <i>etc</i>).
+     * If there is no pending coverage description, then invoking this method has no effect
+     * except setting the {@code electromagnetic} flag.
+     * If new coverage descriptions are added after this method call, they will be stored in a new element.
+     *
+     * <p>This method does not need to be invoked unless a new "coverage description" node is desired,
+     * or the {@code electromagnetic} flag needs to be set to {@code true}.</p>
+     *
+     * @param  electromagnetic  {@code true} if the next {@code CoverageDescription} to create
+     *         will be a description of measurements in the electromagnetic spectrum.
+     */
+    public final void newCoverage(final boolean electromagnetic) {
         if (sampleDimension != null) {
             attributGroup().getAttributes().add(sampleDimension);
             sampleDimension = null;
         }
-        if (attributGroup != null) {
-            coverageDescription().getAttributeGroups().add(attributGroup);
-            attributGroup = null;
+        if (attributeGroup != null) {
+            coverageDescription().getAttributeGroups().add(attributeGroup);
+            attributeGroup = null;
         }
         if (coverageDescription != null) {
             metadata().getContentInfo().add(coverageDescription);
             coverageDescription = null;
         }
-        if (identification != null) {
-            metadata().getIdentificationInfo().add(identification);
-            identification = null;
+        this.electromagnetic = electromagnetic;
+    }
+
+    /**
+     * Commits all pending information under the metadata "feature catalog" node.
+     * If there is no pending feature description, then invoking this method has no effect.
+     * If new feature descriptions are added after this method call, they will be stored in a new element.
+     *
+     * <p>This method does not need to be invoked unless a new "feature catalog description" node is desired.</p>
+     */
+    public final void newFeatureTypes() {
+        if (featureDescription != null) {
+            metadata().getContentInfo().add(featureDescription);
+            featureDescription = null;
         }
+    }
+
+    /**
+     * Commits all pending information under the metadata "distribution info" node (format, <i>etc</i>).
+     * If there is no pending distribution information, then invoking this method has no effect.
+     * If new distribution information are added after this method call, they will be stored in a new element.
+     *
+     * <p>This method does not need to be invoked unless a new "distribution info" node,
+     * separated from the previous one, is desired.</p>
+     */
+    public final void newDistribution() {
         if (format != null) {
             distribution().getDistributionFormats().add(format);
             format = null;
@@ -197,7 +379,7 @@ public class MetadataBuilder {
     }
 
     /**
-     * Creates the metadata object if it does not already exists, then return it.
+     * Creates the metadata object if it does not already exists, then returns it.
      *
      * @return the metadata (never {@code null}).
      */
@@ -209,7 +391,7 @@ public class MetadataBuilder {
     }
 
     /**
-     * Creates the identification information object if it does not already exists, then return it.
+     * Creates the identification information object if it does not already exists, then returns it.
      *
      * @return the identification information (never {@code null}).
      */
@@ -221,7 +403,7 @@ public class MetadataBuilder {
     }
 
     /**
-     * Creates the citation object if it does not already exists, then return it.
+     * Creates the citation object if it does not already exists, then returns it.
      *
      * @return the citation information (never {@code null}).
      */
@@ -233,7 +415,7 @@ public class MetadataBuilder {
     }
 
     /**
-     * Creates the responsibility object if it does not already exists, then return it.
+     * Creates the responsibility object if it does not already exists, then returns it.
      *
      * @return the responsibility party (never {@code null}).
      */
@@ -245,22 +427,28 @@ public class MetadataBuilder {
     }
 
     /**
-     * Creates the person or organization information object if it does not already exists, then return it.
+     * Creates the individual or organization information object if it does not already exists, then returns it.
      *
-     * <p><b>Limitation:</b> current implementation creates an {@code AbstractParty} instead than one of the subtypes.
-     * This is not valid, but we currently have no way to know if the party is an individual or an organization.</p>
+     * <p><b>Limitation:</b> if the party type is unknown, then this method creates an {@code AbstractParty} instead
+     * than one of the subtypes. This is not valid, but we currently have no way to guess if a party is an individual
+     * or an organization. For now we prefer to let users know that the type is unknown rather than to pick a
+     * potentially wrong type.</p>
      *
-     * @return the person or organization information (never {@code null}).
+     * @return the individual or organization information (never {@code null}).
      */
     private AbstractParty party() {
         if (party == null) {
-            party = new AbstractParty();        // See limitation in above javadoc.
+            switch (partyType) {
+                case INDIVIDUAL:   party = new DefaultIndividual();   break;
+                case ORGANISATION: party = new DefaultOrganisation(); break;
+                default:           party = new AbstractParty();       break;
+            }
         }
         return party;
     }
 
     /**
-     * Creates the constraints information object if it does not already exists, then return it.
+     * Creates the constraints information object if it does not already exists, then returns it.
      *
      * @return the constraints information (never {@code null}).
      */
@@ -272,7 +460,7 @@ public class MetadataBuilder {
     }
 
     /**
-     * Creates the extent information object if it does not already exists, then return it.
+     * Creates the extent information object if it does not already exists, then returns it.
      *
      * @return the extent information (never {@code null}).
      */
@@ -284,7 +472,43 @@ public class MetadataBuilder {
     }
 
     /**
-     * Creates the sample dimension object if it does not already exists, then return it.
+     * Creates the acquisition information object if it does not already exists, then returns it.
+     *
+     * @return the acquisition information (never {@code null}).
+     */
+    private DefaultAcquisitionInformation acquisition() {
+        if (acquisition == null) {
+            acquisition = new DefaultAcquisitionInformation();
+        }
+        return acquisition;
+    }
+
+    /**
+     * Creates a platform object if it does not already exists, then returns it.
+     *
+     * @return the platform information (never {@code null}).
+     */
+    private DefaultPlatform platform() {
+        if (platform == null) {
+            platform = new DefaultPlatform();
+        }
+        return platform;
+    }
+
+    /**
+     * Creates a grid representation object if it does not already exists, then returns it.
+     *
+     * @return the grid representation object (never {@code null}).
+     */
+    private DefaultGridSpatialRepresentation gridRepresentation() {
+        if (gridRepresentation == null) {
+            gridRepresentation = new DefaultGridSpatialRepresentation();
+        }
+        return gridRepresentation;
+    }
+
+    /**
+     * Creates the sample dimension object if it does not already exists, then returns it.
      *
      * @return the sample dimension (never {@code null}).
      */
@@ -296,31 +520,46 @@ public class MetadataBuilder {
     }
 
     /**
-     * Creates the attribut group object if it does not already exists, then return it.
+     * Creates the attribut group object if it does not already exists, then returns it.
      *
      * @return the attribut group (never {@code null}).
      */
     private DefaultAttributeGroup attributGroup() {
-        if (attributGroup == null) {
-            attributGroup = new DefaultAttributeGroup();
+        if (attributeGroup == null) {
+            attributeGroup = new DefaultAttributeGroup();
         }
-        return attributGroup;
+        return attributeGroup;
     }
 
     /**
-     * Creates the coverage description object if it does not already exists, then return it.
+     * Creates the coverage description object if it does not already exists, then returns it.
      *
      * @return the coverage description (never {@code null}).
      */
     private DefaultCoverageDescription coverageDescription() {
         if (coverageDescription == null) {
-            coverageDescription = new DefaultCoverageDescription();
+            coverageDescription = electromagnetic ? new DefaultImageDescription() : new DefaultCoverageDescription();
         }
         return coverageDescription;
     }
 
     /**
-     * Creates the distribution format object if it does not already exists, then return it.
+     * Creates the feature descriptions object if it does not already exists, then returns it.
+     * This method sets the {@code includedWithDataset} property to {@code true} because the
+     * metadata built by this helper class are typically encoded together with the data.
+     *
+     * @return the feature descriptions (never {@code null}).
+     */
+    private DefaultFeatureCatalogueDescription featureDescription() {
+        if (featureDescription == null) {
+            featureDescription = new DefaultFeatureCatalogueDescription();
+            featureDescription.setIncludedWithDataset(true);
+        }
+        return featureDescription;
+    }
+
+    /**
+     * Creates the distribution format object if it does not already exists, then returns it.
      *
      * @return the distribution format (never {@code null}).
      */
@@ -332,7 +571,7 @@ public class MetadataBuilder {
     }
 
     /**
-     * Creates the distribution information object if it does not already exists, then return it.
+     * Creates the distribution information object if it does not already exists, then returns it.
      *
      * @return the distribution information (never {@code null}).
      */
@@ -344,9 +583,33 @@ public class MetadataBuilder {
     }
 
     /**
+     * Adds the given element in the collection if not already present.
+     * This method is used only for properties that are usually stored in {@code List} rather than {@code Set}
+     * and for which we do not keep a reference in this {@code MetadataBuilder} after the element has been added.
+     * This method is intended for adding elements that despite being modifiable, are not going to be modified by
+     * this {@code MetadataBuilder} class.
+     */
+    private static <E> void addIfNotPresent(final Collection<E> collection, final E element) {
+        if (!collection.contains(element)) {
+            collection.add(element);
+        }
+    }
+
+    /**
+     * Adds a language used for documenting metadata.
+     *
+     * @param  language  a language used for documenting metadata.
+     */
+    public final void add(final Locale language) {
+        if (language != null) {
+            metadata().getLanguages().add(language);
+        }
+    }
+
+    /**
      * Adds the given character encoding to the metadata.
      *
-     * @param encoding  the character encoding to add.
+     * @param  encoding  the character encoding to add.
      */
     public final void add(final Charset encoding) {
         if (encoding != null) {
@@ -355,6 +618,34 @@ public class MetadataBuilder {
     }
 
     /**
+     * Adds information about the scope of the resource.
+     * The scope is typically {@link ScopeCode#DATASET}.
+     *
+     * @param  scope  the scope of the resource, or {@code null} if none.
+     */
+    public final void add(final ScopeCode scope) {
+        if (scope != null) {
+            metadata().getMetadataScopes().add(new DefaultMetadataScope(scope, null));
+        }
+    }
+
+    /**
+     * Adds descriptions for the given feature.
+     *
+     * @param  type         the feature type to add, or {@code null}.
+     * @param  occurrences  number of instances of the given features, or {@code null} if unknown.
+     */
+    public final void add(final FeatureType type, final Integer occurrences) {
+        if (type != null) {
+            final DefaultFeatureTypeInfo info = new DefaultFeatureTypeInfo(type.getName());
+            if (occurrences != null) {
+                info.setFeatureInstanceCount(shared(occurrences));
+            }
+            featureDescription().getFeatureTypeInfo().add(info);
+        }
+    }
+
+    /**
      * Adds the given coordinate reference system to metadata, if it does not already exists.
      * This method ensures that there is no duplicated values. Comparisons ignore metadata.
      *
@@ -379,7 +670,7 @@ public class MetadataBuilder {
      * @param  envelope  the extent to add in the metadata, or {@code null} if none.
      * @throws TransformException if an error occurred while converting the given envelope to extents.
      */
-    public final void add(final AbstractEnvelope envelope) throws TransformException {
+    public final void addExtent(final AbstractEnvelope envelope) throws TransformException {
         if (envelope != null) {
             add(envelope.getCoordinateReferenceSystem());
             if (!envelope.isAllNaN()) {
@@ -389,14 +680,54 @@ public class MetadataBuilder {
     }
 
     /**
-     * Adds a date of the given type.
+     * Adds a geographic bounding box initialized to the values in the given array.
+     * The array must contains at least 4 values starting at the given index in this exact order:
+     *
+     * <ul>
+     *   <li>{@code westBoundLongitude} (the minimal λ value), or {@code NaN}</li>
+     *   <li>{@code eastBoundLongitude} (the maximal λ value), or {@code NaN}</li>
+     *   <li>{@code southBoundLatitude} (the minimal φ value), or {@code NaN}</li>
+     *   <li>{@code northBoundLatitude} (the maximal φ value), or {@code NaN}</li>
+     * </ul>
+     *
+     * @param  ordinates  the geographic coordinates.
+     * @param  index      index of the first value to use in the given array.
+     */
+    public final void addExtent(final double[] ordinates, int index) {
+        final DefaultGeographicBoundingBox bbox = new DefaultGeographicBoundingBox(
+                    ordinates[index], ordinates[++index], ordinates[++index], ordinates[++index]);
+        if (!bbox.isEmpty()) {
+            addIfNotPresent(extent().getGeographicElements(), bbox);
+        }
+    }
+
+    /**
+     * Adds a temporal extent covered by the data.
+     *
+     * @param  startTime  when the data begins, or {@code null}.
+     * @param  endTime    when the data ends, or {@code null}.
+     * @throws UnsupportedOperationException if the temporal module is not on the classpath.
+     *
+     * @see #addAcquisitionTime(Date)
+     */
+    public final void addExtent(final Date startTime, final Date endTime) {
+        if (startTime != null || endTime != null) {
+            final DefaultTemporalExtent t = new DefaultTemporalExtent();
+            t.setBounds(startTime, endTime);
+            addIfNotPresent(extent().getTemporalElements(), t);
+        }
+    }
+
+    /**
+     * Adds a date of the given type. This is not the data acquisition time,
+     * but rather the metadata creation or last update time.
      *
      * @param date  the date to add, or {@code null}.
      * @param type  the type of the date to add, or {@code null}.
      */
     public final void add(final Date date, final DateType type) {
         if (date != null) {
-            citation().getDates().add(new DefaultCitationDate(date, type));
+            addIfNotPresent(citation().getDates(), new DefaultCitationDate(date, type));
         }
     }
 
@@ -404,10 +735,10 @@ public class MetadataBuilder {
      * Returns the given character sequence as a non-empty character string with leading and trailing spaces removed.
      * If the given character sequence is null, empty or blank, then this method returns {@code null}.
      */
-    private static InternationalString trim(CharSequence string) {
-        string = CharSequences.trimWhitespaces(string);
-        if (string != null && string.length() != 0) {
-            return Types.toInternationalString(string);
+    private static InternationalString trim(CharSequence value) {
+        value = CharSequences.trimWhitespaces(value);
+        if (value != null && value.length() != 0) {
+            return Types.toInternationalString(value);
         } else {
             return null;
         }
@@ -430,17 +761,31 @@ public class MetadataBuilder {
     }
 
     /**
-     * Adds a title of the resource.
+     * Returns {@code true} if the given character sequences have equal content.
+     */
+    private static boolean equals(final CharSequence s1, final CharSequence s2) {
+        if (s1 == s2) {
+            return true;
+        }
+        if (s1 == null || s2 == null) {
+            return false;
+        }
+        return s1.toString().equals(s2.toString());
+    }
+
+    /**
+     * Adds a title or alternate title of the resource.
      *
-     * @param title  the resource title, or {@code null} if none.
+     * @param value  the resource title or alternate title, or {@code null} if none.
      */
-    public final void addTitle(final CharSequence title) {
-        final InternationalString i18n = trim(title);
+    public final void addTitle(final CharSequence value) {
+        final InternationalString i18n = trim(value);
         if (i18n != null) {
             final DefaultCitation citation = citation();
-            if (citation.getTitle() == null) {
+            final InternationalString current = citation.getTitle();
+            if (current == null) {
                 citation.setTitle(i18n);
-            } else {
+            } else if (!equals(current, i18n)) {
                 citation.getAlternateTitles().add(i18n);
             }
         }
@@ -461,22 +806,52 @@ public class MetadataBuilder {
     }
 
     /**
-     * Adds an author name.
+     * Adds an author name. If an author was already defined with a different name,
+     * then a new party instance is created.
      *
-     * @param  author  the name of the author or publisher, or {@code null} if none.
+     * @param  name  the name of the author or publisher, or {@code null} if none.
      */
-    public final void addAuthor(final CharSequence author) {
-        final InternationalString i18n = trim(author);
+    public final void addAuthor(final CharSequence name) {
+        final InternationalString i18n = trim(name);
         if (i18n != null) {
             if (party != null) {
-                responsibility().getParties().add(party);       // Save the previous party before to create a new one.
-                party = null;
+                final InternationalString current = party.getName();
+                if (current != null) {
+                    if (equals(current, name)) {
+                        return;
+                    }
+                    newParty(partyType);
+                }
             }
             party().setName(i18n);
         }
     }
 
     /**
+     * Adds recognition of those who contributed to the resource(s).
+     *
+     * @param  credit  recognition of those who contributed to the resource(s).
+     */
+    public final void addCredits(final CharSequence credit) {
+        final InternationalString i18n = trim(credit);
+        if (i18n != null) {
+            addIfNotPresent(identification().getCredits(), i18n);
+        }
+    }
+
+    /**
+     * Adds a data identifier (not necessarily the same as the metadata identifier).
+     * Empty strings (ignoring spaces) are ignored.
+     *
+     * @param  code  the identifier code, or {@code null} if none.
+     */
+    public final void addIdentifier(String code) {
+        if (code != null && !(code = code.trim()).isEmpty()) {
+            addIfNotPresent(citation().getIdentifiers(), new DefaultIdentifier(code));
+        }
+    }
+
+    /**
      * Elements to omit in the legal notice to be parsed by {@link MetadataBuilder#parseLegalNotice(String)}.
      * Some of those elements are implied by the metadata were the legal notice will be stored.
      */
@@ -691,8 +1066,186 @@ parse:      for (int i = 0; i < length;)
     }
 
     /**
+     * Adds a platform on which instrument are installed. If a platform was already defined
+     * with a different identifier, then a new platform instance will be created.
+     *
+     * @param  identifier  identifier of the platform to add, or {@code null}.
+     */
+    public final void addPlatform(String identifier) {
+        if (identifier != null && !(identifier = identifier.trim()).isEmpty()) {
+            if (platform != null) {
+                final Identifier current = platform.getIdentifier();
+                if (current != null) {
+                    if (identifier.equals(current.getCode())) {
+                        return;
+                    }
+                    acquisition().getPlatforms().add(platform);
+                    platform = null;
+                }
+            }
+            platform().setIdentifier(new DefaultIdentifier(identifier));
+        }
+    }
+
+    /**
+     * Adds an instrument or sensor on the platform.
+     *
+     * @param  identifier  identifier of the sensor to add, or {@code null}.
+     */
+    public final void addInstrument(String identifier) {
+        if (identifier != null && !(identifier = identifier.trim()).isEmpty()) {
+            final DefaultInstrument instrument = new DefaultInstrument();
+            instrument.setIdentifier(new DefaultIdentifier(identifier));
+            addIfNotPresent(platform().getInstruments(), instrument);
+        }
+    }
+
+    /**
+     * Adds an event that describe the time at which data were acquired.
+     *
+     * @param  time  the acquisition time, or {@code null}.
+     *
+     * @see #addExtent(Date, Date)
+     */
+    public final void addAcquisitionTime(final Date time) {
+        if (time != null) {
+            final DefaultEvent event = new DefaultEvent();
+            event.setContext(Context.ACQUISITION);
+            event.setTime(time);
+            final DefaultOperation op = new DefaultOperation();
+            op.setSignificantEvents(singleton(event));
+            op.setType(OperationType.REAL);
+            op.setStatus(Progress.COMPLETED);
+            addIfNotPresent(acquisition().getOperations(), op);
+        }
+    }
+
+    /**
+     * Returns the identifier of the requirement to be satisfied by data acquisition.
+     *
+     * @param  identifier  requirement identifier, or {@code null}.
+     */
+    public final void addAcquisitionRequirement(String identifier) {
+        if (identifier != null && !(identifier = identifier.trim()).isEmpty()) {
+            final DefaultRequirement r = new DefaultRequirement();
+            r.setIdentifier(new DefaultIdentifier(identifier));
+            acquisition().getAcquisitionRequirements().add(r);
+        }
+    }
+
+    /**
+     * Sets the area of the dataset obscured by clouds, expressed as a percentage of the spatial extent.
+     * This method does nothing if the given value is {@link Double#NaN}.
+     *
+     * <p>This method is available only if {@link #commitCoverageDescription(boolean)}
+     * has been invoked with the {@code electromagnetic} parameter set to {@code true}.</p>
+     *
+     * @param  value  the new cloud percentage.
+     * @throws IllegalArgumentException if the given value is out of range.
+     */
+    public final void setCloudCoverPercentage(final double value) {
+        if (!Double.isNaN(value)) {
+            ((DefaultImageDescription) coverageDescription()).setCloudCoverPercentage(shared(value));
+        }
+    }
+
+    /**
+     * Sets the illumination azimuth measured in degrees clockwise from true north at the time the image is taken.
+     * For images from a scanning device, refer to the centre pixel of the image.
+     * This method does nothing if the given value is {@link Double#NaN}.
+     *
+     * <p>This method is available only if {@link #commitCoverageDescription(boolean)}
+     * has been invoked with the {@code electromagnetic} parameter set to {@code true}.</p>
+     *
+     * @param  value  the new illumination azimuth angle, or {@code null}.
+     * @throws IllegalArgumentException if the given value is out of range.
+     */
+    public final void setIlluminationAzimuthAngle(final double value) {
+        if (!Double.isNaN(value)) {
+            ((DefaultImageDescription) coverageDescription()).setIlluminationAzimuthAngle(shared(value));
+        }
+    }
+
+    /**
+     * Sets the illumination elevation measured in degrees clockwise from the target plane
+     * at intersection of the optical line of sight with the Earth's surface.
+     * For images from a canning device, refer to the centre pixel of the image.
+     * This method does nothing if the given value is {@link Double#NaN}.
+     *
+     * <p>This method is available only if {@link #commitCoverageDescription(boolean)}
+     * has been invoked with the {@code electromagnetic} parameter set to {@code true}.</p>
+     *
+     * @param  value  the new illumination azimuth angle, or {@code null}.
+     * @throws IllegalArgumentException if the given value is out of range.
+     */
+    public final void setIlluminationElevationAngle(final double value) {
+        if (!Double.isNaN(value)) {
+            ((DefaultImageDescription) coverageDescription()).setIlluminationElevationAngle(shared(value));
+        }
+    }
+
+    /**
+     * Adds a linear resolution in metres.
+     *
+     * @param  distance  the resolution in metres, or {@code NaN} if none.
+     */
+    public final void addResolution(final double distance) {
+        if (!Double.isNaN(distance)) {
+            final DefaultResolution r = new DefaultResolution();
+            r.setDistance(shared(distance));
+            addIfNotPresent(identification().getSpatialResolutions(), r);
+        }
+    }
+
+    /**
+     * Adds a new format. The given name should be a short name like "GeoTIFF".
+     * The long name will be inferred from the given short name, if possible.
+     *
+     * @param  abbreviation  the format short name or abbreviation, or {@code null}.
+     */
+    public final void addFormat(final CharSequence abbreviation) {
+        if (abbreviation != null && abbreviation.length() != 0) {
+            addIfNotPresent(identification().getResourceFormats(), new DefaultFormat(abbreviation, null));
+        }
+    }
+
+    /**
+     * Returns the axis at the given dimension index. All previous dimensions are created if needed.
+     *
+     * @param  index  index of the desired dimension.
+     * @return dimension at the given index.
+     */
+    private DefaultDimension axis(final short index) {
+        final List<Dimension> axes = gridRepresentation().getAxisDimensionProperties();
+        for (int i=axes.size(); i <= index; i++) {
+            axes.add(new DefaultDimension());
+        }
+        return (DefaultDimension) axes.get(index);
+    }
+
+    /**
+     * Sets the number of cells along the given dimension.
+     *
+     * @param  dimension  the axis dimension, as a {@code short} for avoiding excessive values.
+     * @param  name       the name to set for the given dimension.
+     */
+    public final void setAxisName(final short dimension, final DimensionNameType name) {
+        axis(dimension).setDimensionName(name);
+    }
+
+    /**
+     * Sets the number of cells along the given dimension.
+     *
+     * @param  dimension  the axis dimension, as a {@code short} for avoiding excessive values.
+     * @param  length     number of cell values along the given dimension.
+     */
+    public final void setAxisLength(final short dimension, final int length) {
+        axis(dimension).setDimensionSize(shared(length));
+    }
+
+    /**
      * Adds a minimal value for the current sample dimension. If a minimal value was already defined, then
-     * the new value will set only if it is smaller than the existing one. {@code NaN} values are ignored.
+     * the new value will be set only if it is smaller than the existing one. {@code NaN} values are ignored.
      *
      * @param value  the minimal value to add to the existing range of sample values, or {@code NaN}.
      */
@@ -701,14 +1254,14 @@ parse:      for (int i = 0; i < length;)
             final DefaultSampleDimension sampleDimension = sampleDimension();
             final Double current = sampleDimension.getMinValue();
             if (current == null || value < current) {
-                sampleDimension.setMinValue(value);
+                sampleDimension.setMinValue(shared(value));
             }
         }
     }
 
     /**
      * Adds a maximal value for the current sample dimension. If a maximal value was already defined, then
-     * the new value will set only if it is greater than the existing one. {@code NaN} values are ignored.
+     * the new value will be set only if it is greater than the existing one. {@code NaN} values are ignored.
      *
      * @param value  the maximal value to add to the existing range of sample values, or {@code NaN}.
      */
@@ -717,7 +1270,7 @@ parse:      for (int i = 0; i < length;)
             final DefaultSampleDimension sampleDimension = sampleDimension();
             final Double current = sampleDimension.getMaxValue();
             if (current == null || value > current) {
-                sampleDimension.setMaxValue(value);
+                sampleDimension.setMaxValue(shared(value));
             }
         }
     }
@@ -734,4 +1287,53 @@ parse:      for (int i = 0; i < length;)
             format.setFileDecompressionTechnique(append(format.getFileDecompressionTechnique(), i18n));
         }
     }
+
+    /**
+     * Returns the metadata (optionally as an unmodifiable object), or {@code null} if none.
+     * If {@code freeze} is {@code true}, then the returned metadata instance can not be modified.
+     *
+     * @param  freeze  {@code true} if this method should {@linkplain DefaultMetadata#freeze() freeze}
+     *         the metadata instance before to return it.
+     * @return the metadata, or {@code null} if none.
+     */
+    public final DefaultMetadata build(final boolean freeze) {
+        newIdentification();
+        newGridRepresentation();
+        newFeatureTypes();
+        newCoverage(false);
+        newDistribution();
+        newAcquisition();
+        final DefaultMetadata md = metadata;
+        metadata = null;
+        if (freeze && md != null) {
+            md.freeze();
+        }
+        return md;
+    }
+
+    /**
+     * Returns a shared instance of the given value.
+     * This is a helper method for callers who want to set themselves some additional
+     * metadata values on the instance returned by {@link #build(boolean)}.
+     *
+     * @param   value  a double value.
+     * @return  the same value, but as an existing instance if possible.
+     */
+    public final Double shared(final Double value) {
+        final Number existing = JDK8.putIfAbsent(sharedNumbers, value, value);
+        return (existing != null) ? (Double) existing : value;
+    }
+
+    /**
+     * Returns a shared instance of the given value.
+     * This is a helper method for callers who want to set themselves some additional
+     * metadata values on the instance returned by {@link #build(boolean)}.
+     *
+     * @param   value  an integer value.
+     * @return  the same value, but as an existing instance if possible.
+     */
+    public final Integer shared(final Integer value) {
+        final Number existing = JDK8.putIfAbsent(sharedNumbers, value, value);
+        return (existing != null) ? (Integer) existing : value;
+    }
 }

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreTypeDetector.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreTypeDetector.java?rev=1760780&r1=1760779&r2=1760780&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreTypeDetector.java [UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreTypeDetector.java [UTF-8] Wed Sep 14 21:29:50 2016
@@ -43,8 +43,8 @@ public class StoreTypeDetector extends F
     /**
      * Probes the given file by delegating to {@link DataStores#probeContentType(Object)}.
      *
-     * @param  path the path to the file to probe.
-     * @return The content type or {@code null} if the file type is not recognized.
+     * @param  path  the path to the file to probe.
+     * @return the content type or {@code null} if the file type is not recognized.
      * @throws IOException if an I/O error occurs while reading the file.
      *
      * @see java.nio.file.Files#probeContentType(Path)



Mime
View raw message