sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1803070 [15/20] - in /sis/branches/JDK9: ./ application/sis-console/src/main/java/org/apache/sis/console/ core/sis-build-helper/ core/sis-build-helper/src/main/java/org/apache/sis/internal/book/ core/sis-build-helper/src/main/java/org/apac...
Date Wed, 26 Jul 2017 16:14:14 GMT
Modified: sis/branches/JDK9/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/earthobservation/LandsatReader.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/earthobservation/LandsatReader.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/earthobservation/LandsatReader.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/earthobservation/LandsatReader.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -27,12 +27,10 @@ import java.util.regex.Pattern;
 import java.io.LineNumberReader;
 
 import org.opengis.metadata.Metadata;
-import org.opengis.metadata.citation.Citation;
 import org.opengis.metadata.citation.DateType;
 import org.opengis.metadata.spatial.DimensionNameType;
 import org.opengis.metadata.content.CoverageContentType;
 import org.opengis.metadata.content.TransferFunctionType;
-import org.opengis.metadata.identification.Identification;
 import org.opengis.metadata.maintenance.ScopeCode;
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.referencing.crs.ProjectedCRS;
@@ -50,6 +48,7 @@ import org.apache.sis.metadata.iso.conte
 import org.apache.sis.metadata.sql.MetadataStoreException;
 import org.apache.sis.referencing.CRS;
 import org.apache.sis.referencing.CommonCRS;
+import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.DataStoreReferencingException;
 import org.apache.sis.util.Characters;
@@ -67,7 +66,6 @@ import org.apache.sis.internal.util.Stan
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.internal.util.Utilities;
 
-import static java.util.Collections.singleton;
 import static org.apache.sis.internal.util.CollectionsExt.singletonOrNull;
 
 // Branch-dependent imports
@@ -220,7 +218,7 @@ final class LandsatReader {
     /**
      * Where to send the warnings.
      */
-    private final WarningListeners<?> listeners;
+    private final WarningListeners<DataStore> listeners;
 
     /**
      * Group in process of being parsed, or {@code null} if none.
@@ -297,7 +295,7 @@ final class LandsatReader {
      * @param  filename   an identifier of the file being read, or {@code null} if unknown.
      * @param  listeners  where to sent warnings that may occur during the parsing process.
      */
-    LandsatReader(final String filename, final WarningListeners<?> listeners) {
+    LandsatReader(final String filename, final WarningListeners<DataStore> listeners) {
         this.filename  = filename;
         this.listeners = listeners;
         this.metadata  = new MetadataBuilder();
@@ -458,7 +456,7 @@ final class LandsatReader {
              * Example: "0501403126384_00011"
              */
             case "REQUEST_ID": {
-                metadata.addAcquisitionRequirement(value);
+                metadata.addAcquisitionRequirement(null, value);
                 break;
             }
             /*
@@ -467,7 +465,7 @@ final class LandsatReader {
              * Example: "LC81230522014071LGN00".
              */
             case "LANDSAT_SCENE_ID": {
-                metadata.addIdentifier(value);
+                metadata.addIdentifier(null, value, MetadataBuilder.Scope.ALL);
                 break;
             }
             /*
@@ -477,7 +475,8 @@ final class LandsatReader {
              * Example: "2014-03-12T06:06:35Z".
              */
             case "FILE_DATE": {
-                metadata.add(StandardDateFormat.toDate(OffsetDateTime.parse(value)), DateType.CREATION);
+                metadata.addCitationDate(StandardDateFormat.toDate(OffsetDateTime.parse(value)),
+                                         DateType.CREATION, MetadataBuilder.Scope.ALL);
                 break;
             }
             /*
@@ -511,8 +510,8 @@ final class LandsatReader {
              * Value is "GEOTIFF".
              */
             case "OUTPUT_FORMAT": {
-                if ("GeoTIFF".equalsIgnoreCase(value)) {
-                    value = "GeoTIFF";                      // Because 'metadata.setFormat(…)' is case-sensitive.
+                if (Constants.GEOTIFF.equalsIgnoreCase(value)) {
+                    value = Constants.GEOTIFF;              // Because 'metadata.setFormat(…)' is case-sensitive.
                 }
                 try {
                     metadata.setFormat(value);
@@ -526,7 +525,7 @@ final class LandsatReader {
              * Example: "LANDSAT_8".
              */
             case "SPACECRAFT_ID": {
-                metadata.addPlatform(value);
+                metadata.addPlatform(null, value);
                 break;
             }
             /*
@@ -534,7 +533,7 @@ final class LandsatReader {
              * Example: "OLI", "TIRS" or "OLI_TIRS".
              */
             case "SENSOR_ID": {
-                metadata.addInstrument(value);
+                metadata.addInstrument(null, value);
                 break;
             }
             /*
@@ -844,7 +843,7 @@ final class LandsatReader {
             final Date t = StandardDateFormat.toDate(st);
             metadata.addAcquisitionTime(t);
             try {
-                metadata.addExtent(t, t);
+                metadata.addTemporalExtent(t, t);
             } catch (UnsupportedOperationException e) {
                 // May happen if the temporal module (which is optional) is not on the classpath.
                 warning(null, null, e);
@@ -889,8 +888,8 @@ final class LandsatReader {
      * @throws FactoryException if an error occurred while creating the Coordinate Reference System.
      */
     final Metadata getMetadata() throws FactoryException {
-        metadata.add(Locale.ENGLISH, MetadataBuilder.Scope.METADATA);
-        metadata.add(ScopeCode.COVERAGE);
+        metadata.addLanguage(Locale.ENGLISH, MetadataBuilder.Scope.METADATA);
+        metadata.addResourceScope(ScopeCode.COVERAGE, null);
         try {
             flushSceneTime();
         } catch (DateTimeException e) {
@@ -904,7 +903,7 @@ final class LandsatReader {
          */
         if (datum != null) {
             if (utmZone > 0) {
-                metadata.add(datum.universal(1, TransverseMercator.Zoner.UTM.centralMeridian(utmZone)));
+                metadata.addReferenceSystem(datum.universal(1, TransverseMercator.Zoner.UTM.centralMeridian(utmZone)));
             }
             if (projection != null) {
                 final double sp = projection.parameter(Constants.STANDARD_PARALLEL_1).doubleValue();
@@ -920,7 +919,7 @@ final class LandsatReader {
                             Collections.singletonMap(ProjectedCRS.NAME_KEY, "Polar stereographic"),
                             datum.geographic(), projection, crs.getCoordinateSystem());
                 }
-                metadata.add(crs);
+                metadata.addReferenceSystem(crs);
             }
         }
         /*
@@ -933,11 +932,11 @@ final class LandsatReader {
             final int width  = gridSizes[i  ];
             final int height = gridSizes[i+1];
             if (width != 0 || height != 0) {
-                metadata.newGridRepresentation();
-                metadata.setAxisName((short) 0, DimensionNameType.SAMPLE);
-                metadata.setAxisName((short) 1, DimensionNameType.LINE);
-                metadata.setAxisLength((short) 0, width);
-                metadata.setAxisLength((short) 1, height);
+                metadata.newGridRepresentation(MetadataBuilder.GridType.GEORECTIFIED);
+                metadata.setAxisName(0, DimensionNameType.SAMPLE);
+                metadata.setAxisName(1, DimensionNameType.LINE);
+                metadata.setAxisLength(0, width);
+                metadata.setAxisLength(1, height);
             }
         }
         /*
@@ -948,18 +947,6 @@ final class LandsatReader {
         final DefaultMetadata result = metadata.build(false);
         if (result != null) {
             /*
-             * If there is exactly one data identification (which is usually the case, unless the user has invoked the
-             * read(BufferedReader) method many times), use the same identifier and date for the metadata as a whole.
-             */
-            final Identification id = singletonOrNull(result.getIdentificationInfo());
-            if (id != null) {
-                final Citation citation = id.getCitation();
-                if (citation != null) {
-                    result.setMetadataIdentifier(singletonOrNull(citation.getIdentifiers()));
-                    result.setDateInfo(singleton(singletonOrNull(citation.getDates())));
-                }
-            }
-            /*
              * Set information about all non-null bands. The bands are categorized in three groups:
              * PANCHROMATIC, REFLECTIVE and THERMAL. The group in which each band belong is encoded
              * in the BAND_GROUPS bitmask.

Modified: sis/branches/JDK9/storage/sis-earth-observation/src/test/java/org/apache/sis/storage/earthobservation/LandsatReaderTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-earth-observation/src/test/java/org/apache/sis/storage/earthobservation/LandsatReaderTest.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-earth-observation/src/test/java/org/apache/sis/storage/earthobservation/LandsatReaderTest.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-earth-observation/src/test/java/org/apache/sis/storage/earthobservation/LandsatReaderTest.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -97,36 +97,29 @@ public class LandsatReaderTest extends T
                 + "  ├─Language…………………………………………………………………………………………… en\n"
                 + "  ├─Spatial representation info (1 of 2)\n"
                 + "  │   ├─Number of dimensions………………………………………………… 2\n"
-                + "  │   ├─Axis dimension properties (1 of 2)\n"
-                + "  │   │   ├─Dimension name……………………………………………………… Sample\n"
+                + "  │   ├─Axis dimension properties (1 of 2)…………… Sample\n"
                 + "  │   │   └─Dimension size……………………………………………………… 15000\n"
-                + "  │   ├─Axis dimension properties (2 of 2)\n"
-                + "  │   │   ├─Dimension name……………………………………………………… Line\n"
+                + "  │   ├─Axis dimension properties (2 of 2)…………… Line\n"
                 + "  │   │   └─Dimension size……………………………………………………… 15500\n"
                 + "  │   ├─Transformation parameter availability…… false\n"
                 + "  │   └─Check point availability……………………………………… false\n"
                 + "  ├─Spatial representation info (2 of 2)\n"
                 + "  │   ├─Number of dimensions………………………………………………… 2\n"
-                + "  │   ├─Axis dimension properties (1 of 2)\n"
-                + "  │   │   ├─Dimension name……………………………………………………… Sample\n"
+                + "  │   ├─Axis dimension properties (1 of 2)…………… Sample\n"
                 + "  │   │   └─Dimension size……………………………………………………… 7600\n"
-                + "  │   ├─Axis dimension properties (2 of 2)\n"
-                + "  │   │   ├─Dimension name……………………………………………………… Line\n"
+                + "  │   ├─Axis dimension properties (2 of 2)…………… Line\n"
                 + "  │   │   └─Dimension size……………………………………………………… 7800\n"
                 + "  │   ├─Transformation parameter availability…… false\n"
                 + "  │   └─Check point availability……………………………………… false\n"
                 + "  ├─Reference system info………………………………………………………… EPSG:WGS 84 / UTM zone 49N\n"
                 + "  ├─Identification info\n"
                 + "  │   ├─Citation\n"
-                + "  │   │   ├─Date\n"
-                + "  │   │   │   ├─Date……………………………………………………………………… 2016-06-27 16:48:12\n"
+                + "  │   │   ├─Date………………………………………………………………………………… 2016-06-27 16:48:12\n"
                 + "  │   │   │   └─Date type………………………………………………………… Creation\n"
-                + "  │   │   └─Identifier\n"
-                + "  │   │       └─Code……………………………………………………………………… LandsatTest\n"
+                + "  │   │   └─Identifier………………………………………………………………… LandsatTest\n"
                 + "  │   ├─Credit……………………………………………………………………………………… Derived from U.S. Geological Survey data\n"
                 + "  │   ├─Resource format\n"
-                + "  │   │   └─Format specification citation\n"
-                + "  │   │       ├─Title…………………………………………………………………… GeoTIFF Coverage Encoding Profile\n"
+                + "  │   │   └─Format specification citation……………… GeoTIFF Coverage Encoding Profile\n"
                 + "  │   │       └─Alternate title………………………………………… GeoTIFF\n"
                 + "  │   ├─Spatial resolution (1 of 2)\n"
                 + "  │   │   └─Distance……………………………………………………………………… 15.0\n"
@@ -154,8 +147,7 @@ public class LandsatReaderTest extends T
                 + "  │   │   │   ├─Transfer function type……………………… Linear\n"
                 + "  │   │   │   ├─Bound units…………………………………………………… nm\n"
                 + "  │   │   │   ├─Description…………………………………………………… Coastal Aerosol\n"
-                + "  │   │   │   └─Name\n"
-                + "  │   │   │       └─Code…………………………………………………………… TestImage_B1.TIF\n"
+                + "  │   │   │   └─Name……………………………………………………………………… TestImage_B1.TIF\n"
                 + "  │   │   ├─Attribute (2 of 8)\n"
                 + "  │   │   │   ├─Max value………………………………………………………… 65535.0\n"
                 + "  │   │   │   ├─Min value………………………………………………………… 1.0\n"
@@ -165,8 +157,7 @@ public class LandsatReaderTest extends T
                 + "  │   │   │   ├─Transfer function type……………………… Linear\n"
                 + "  │   │   │   ├─Bound units…………………………………………………… nm\n"
                 + "  │   │   │   ├─Description…………………………………………………… Blue\n"
-                + "  │   │   │   └─Name\n"
-                + "  │   │   │       └─Code…………………………………………………………… TestImage_B2.TIF\n"
+                + "  │   │   │   └─Name……………………………………………………………………… TestImage_B2.TIF\n"
                 + "  │   │   ├─Attribute (3 of 8)\n"
                 + "  │   │   │   ├─Max value………………………………………………………… 65535.0\n"
                 + "  │   │   │   ├─Min value………………………………………………………… 1.0\n"
@@ -176,8 +167,7 @@ public class LandsatReaderTest extends T
                 + "  │   │   │   ├─Transfer function type……………………… Linear\n"
                 + "  │   │   │   ├─Bound units…………………………………………………… nm\n"
                 + "  │   │   │   ├─Description…………………………………………………… Green\n"
-                + "  │   │   │   └─Name\n"
-                + "  │   │   │       └─Code…………………………………………………………… TestImage_B3.TIF\n"
+                + "  │   │   │   └─Name……………………………………………………………………… TestImage_B3.TIF\n"
                 + "  │   │   ├─Attribute (4 of 8)\n"
                 + "  │   │   │   ├─Max value………………………………………………………… 65535.0\n"
                 + "  │   │   │   ├─Min value………………………………………………………… 1.0\n"
@@ -187,8 +177,7 @@ public class LandsatReaderTest extends T
                 + "  │   │   │   ├─Transfer function type……………………… Linear\n"
                 + "  │   │   │   ├─Bound units…………………………………………………… nm\n"
                 + "  │   │   │   ├─Description…………………………………………………… Red\n"
-                + "  │   │   │   └─Name\n"
-                + "  │   │   │       └─Code…………………………………………………………… TestImage_B4.TIF\n"
+                + "  │   │   │   └─Name……………………………………………………………………… TestImage_B4.TIF\n"
                 + "  │   │   ├─Attribute (5 of 8)\n"
                 + "  │   │   │   ├─Max value………………………………………………………… 65535.0\n"
                 + "  │   │   │   ├─Min value………………………………………………………… 1.0\n"
@@ -198,8 +187,7 @@ public class LandsatReaderTest extends T
                 + "  │   │   │   ├─Transfer function type……………………… Linear\n"
                 + "  │   │   │   ├─Bound units…………………………………………………… nm\n"
                 + "  │   │   │   ├─Description…………………………………………………… Near-Infrared\n"
-                + "  │   │   │   └─Name\n"
-                + "  │   │   │       └─Code…………………………………………………………… TestImage_B5.TIF\n"
+                + "  │   │   │   └─Name……………………………………………………………………… TestImage_B5.TIF\n"
                 + "  │   │   ├─Attribute (6 of 8)\n"
                 + "  │   │   │   ├─Max value………………………………………………………… 65535.0\n"
                 + "  │   │   │   ├─Min value………………………………………………………… 1.0\n"
@@ -209,8 +197,7 @@ public class LandsatReaderTest extends T
                 + "  │   │   │   ├─Transfer function type……………………… Linear\n"
                 + "  │   │   │   ├─Bound units…………………………………………………… nm\n"
                 + "  │   │   │   ├─Description…………………………………………………… Short Wavelength Infrared (SWIR) 1\n"
-                + "  │   │   │   └─Name\n"
-                + "  │   │   │       └─Code…………………………………………………………… TestImage_B6.TIF\n"
+                + "  │   │   │   └─Name……………………………………………………………………… TestImage_B6.TIF\n"
                 + "  │   │   ├─Attribute (7 of 8)\n"
                 + "  │   │   │   ├─Max value………………………………………………………… 65535.0\n"
                 + "  │   │   │   ├─Min value………………………………………………………… 1.0\n"
@@ -220,8 +207,7 @@ public class LandsatReaderTest extends T
                 + "  │   │   │   ├─Transfer function type……………………… Linear\n"
                 + "  │   │   │   ├─Bound units…………………………………………………… nm\n"
                 + "  │   │   │   ├─Description…………………………………………………… Short Wavelength Infrared (SWIR) 2\n"
-                + "  │   │   │   └─Name\n"
-                + "  │   │   │       └─Code…………………………………………………………… TestImage_B7.TIF\n"
+                + "  │   │   │   └─Name……………………………………………………………………… TestImage_B7.TIF\n"
                 + "  │   │   └─Attribute (8 of 8)\n"
                 + "  │   │       ├─Max value………………………………………………………… 65535.0\n"
                 + "  │   │       ├─Min value………………………………………………………… 1.0\n"
@@ -231,8 +217,7 @@ public class LandsatReaderTest extends T
                 + "  │   │       ├─Transfer function type……………………… Linear\n"
                 + "  │   │       ├─Bound units…………………………………………………… nm\n"
                 + "  │   │       ├─Description…………………………………………………… Cirrus\n"
-                + "  │   │       └─Name\n"
-                + "  │   │           └─Code…………………………………………………………… TestImage_B9.TIF\n"
+                + "  │   │       └─Name……………………………………………………………………… TestImage_B9.TIF\n"
                 + "  │   ├─Attribute group (2 of 3)\n"
                 + "  │   │   ├─Content type…………………………………………………………… Physical measurement\n"
                 + "  │   │   └─Attribute\n"
@@ -244,8 +229,7 @@ public class LandsatReaderTest extends T
                 + "  │   │       ├─Transfer function type……………………… Linear\n"
                 + "  │   │       ├─Bound units…………………………………………………… nm\n"
                 + "  │   │       ├─Description…………………………………………………… Panchromatic\n"
-                + "  │   │       └─Name\n"
-                + "  │   │           └─Code…………………………………………………………… TestImage_B8.TIF\n"
+                + "  │   │       └─Name……………………………………………………………………… TestImage_B8.TIF\n"
                 + "  │   └─Attribute group (3 of 3)\n"
                 + "  │       ├─Content type…………………………………………………………… Physical measurement\n"
                 + "  │       ├─Attribute (1 of 2)\n"
@@ -257,8 +241,7 @@ public class LandsatReaderTest extends T
                 + "  │       │   ├─Transfer function type……………………… Linear\n"
                 + "  │       │   ├─Bound units…………………………………………………… nm\n"
                 + "  │       │   ├─Description…………………………………………………… Thermal Infrared Sensor (TIRS) 1\n"
-                + "  │       │   └─Name\n"
-                + "  │       │       └─Code…………………………………………………………… TestImage_B10.TIF\n"
+                + "  │       │   └─Name……………………………………………………………………… TestImage_B10.TIF\n"
                 + "  │       └─Attribute (2 of 2)\n"
                 + "  │           ├─Max value………………………………………………………… 65535.0\n"
                 + "  │           ├─Min value………………………………………………………… 1.0\n"
@@ -268,12 +251,10 @@ public class LandsatReaderTest extends T
                 + "  │           ├─Transfer function type……………………… Linear\n"
                 + "  │           ├─Bound units…………………………………………………… nm\n"
                 + "  │           ├─Description…………………………………………………… Thermal Infrared Sensor (TIRS) 2\n"
-                + "  │           └─Name\n"
-                + "  │               └─Code…………………………………………………………… TestImage_B11.TIF\n"
+                + "  │           └─Name……………………………………………………………………… TestImage_B11.TIF\n"
                 + "  ├─Acquisition information\n"
                 + "  │   ├─Acquisition requirement\n"
-                + "  │   │   └─Identifier\n"
-                + "  │   │       └─Code……………………………………………………………………… Software unit tests\n"
+                + "  │   │   └─Identifier………………………………………………………………… Software unit tests\n"
                 + "  │   ├─Operation\n"
                 + "  │   │   ├─Status…………………………………………………………………………… Completed\n"
                 + "  │   │   ├─Type………………………………………………………………………………… Real\n"
@@ -281,40 +262,30 @@ public class LandsatReaderTest extends T
                 + "  │   │       ├─Context……………………………………………………………… Acquisition\n"
                 + "  │   │       └─Time……………………………………………………………………… 2016-06-26 03:02:01\n"
                 + "  │   └─Platform\n"
-                + "  │       ├─Identifier\n"
-                + "  │       │   └─Code……………………………………………………………………… Pseudo LANDSAT\n"
+                + "  │       ├─Identifier………………………………………………………………… Pseudo LANDSAT\n"
                 + "  │       └─Instrument\n"
-                + "  │           └─Identifier\n"
-                + "  │               └─Code…………………………………………………………… Pseudo TIRS\n"
-                + "  ├─Date info\n"
-                + "  │   ├─Date…………………………………………………………………………………………… 2016-06-27 16:48:12\n"
+                + "  │           └─Identifier……………………………………………………… Pseudo TIRS\n"
+                + "  ├─Date info………………………………………………………………………………………… 2016-06-27 16:48:12\n"
                 + "  │   └─Date type……………………………………………………………………………… Creation\n"
                 + "  ├─Metadata scope\n"
                 + "  │   └─Resource scope………………………………………………………………… Coverage\n"
-                + "  ├─Metadata identifier\n"
-                + "  │   └─Code…………………………………………………………………………………………… LandsatTest\n"
-                + "  ├─Metadata standard (1 of 2)\n"
-                + "  │   ├─Title………………………………………………………………………………………… Geographic Information — Metadata Part 1: Fundamentals\n"
+                + "  ├─Metadata identifier……………………………………………………………… LandsatTest\n"
+                + "  ├─Metadata standard (1 of 2)…………………………………………… Geographic Information — Metadata Part 1: Fundamentals\n"
                 + "  │   ├─Edition…………………………………………………………………………………… ISO 19115-1:2014(E)\n"
-                + "  │   ├─Identifier\n"
-                + "  │   │   ├─Code………………………………………………………………………………… 19115-1\n"
+                + "  │   ├─Identifier…………………………………………………………………………… 19115-1\n"
                 + "  │   │   ├─Code space………………………………………………………………… ISO\n"
                 + "  │   │   └─Version………………………………………………………………………… 2014(E)\n"
                 + "  │   ├─Cited responsible party\n"
-                + "  │   │   ├─Party\n"
-                + "  │   │   │   └─Name……………………………………………………………………… International Organization for Standardization\n"
+                + "  │   │   ├─Organisation…………………………………………………………… International Organization for Standardization\n"
                 + "  │   │   └─Role………………………………………………………………………………… Principal investigator\n"
                 + "  │   └─Presentation form………………………………………………………… Document digital\n"
-                + "  └─Metadata standard (2 of 2)\n"
-                + "      ├─Title………………………………………………………………………………………… Geographic Information — Metadata Part 2: Extensions for imagery and gridded data\n"
+                + "  └─Metadata standard (2 of 2)…………………………………………… Geographic Information — Metadata Part 2: Extensions for imagery and gridded data\n"
                 + "      ├─Edition…………………………………………………………………………………… ISO 19115-2:2009(E)\n"
-                + "      ├─Identifier\n"
-                + "      │   ├─Code………………………………………………………………………………… 19115-2\n"
+                + "      ├─Identifier…………………………………………………………………………… 19115-2\n"
                 + "      │   ├─Code space………………………………………………………………… ISO\n"
                 + "      │   └─Version………………………………………………………………………… 2009(E)\n"
                 + "      ├─Cited responsible party\n"
-                + "      │   ├─Party\n"
-                + "      │   │   └─Name……………………………………………………………………… International Organization for Standardization\n"
+                + "      │   ├─Organisation…………………………………………………………… International Organization for Standardization\n"
                 + "      │   └─Role………………………………………………………………………………… Principal investigator\n"
                 + "      └─Presentation form………………………………………………………… Document digital\n", text);
     }

Modified: sis/branches/JDK9/storage/sis-gdal/pom.xml
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-gdal/pom.xml?rev=1803070&r1=1803065&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-gdal/pom.xml (original)
+++ sis/branches/JDK9/storage/sis-gdal/pom.xml Wed Jul 26 16:14:09 2017
@@ -28,7 +28,7 @@
   <parent>
     <groupId>org.apache.sis</groupId>
     <artifactId>storage</artifactId>
-    <version>0.8-jdk8-SNAPSHOT</version>
+    <version>0.8-jdk9-SNAPSHOT</version>
   </parent>
 
 

Modified: sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -98,6 +98,12 @@ public final class Resources extends Ind
         public static final short IgnoredTag_1 = 7;
 
         /**
+         * Map projection parameter “{2}” will be ignored because its value ({3}) is inconsistent with
+         * the “{0} = {1}” parameter.
+         */
+        public static final short InconsistentMapProjParameter_4 = 24;
+
+        /**
          * TIFF image “{0}” shall be either tiled or organized into strips.
          */
         public static final short InconsistentTileStrip_1 = 8;
@@ -140,6 +146,11 @@ public final class Resources extends Ind
         public static final short RandomizedProcessApplied = 15;
 
         /**
+         * The “{0}” GeoTIFF file does not specify the values format.
+         */
+        public static final short UndefinedDataFormat_1 = 25;
+
+        /**
          * A single value was expected for the “{0}” key but {1} values have been found.
          */
         public static final short UnexpectedListOfValues_2 = 16;
@@ -155,6 +166,11 @@ public final class Resources extends Ind
         public static final short UnexpectedTileCount_3 = 18;
 
         /**
+         * TIFF file “{0}” uses an unknown coordinate reference system.
+         */
+        public static final short UnknownCRS_1 = 22;
+
+        /**
          * Coordinate system kind {0} is unsupported.
          */
         public static final short UnsupportedCoordinateSystemKind_1 = 19;
@@ -168,6 +184,11 @@ public final class Resources extends Ind
          * Unsupported storage location for the “{0}” GeoTIFF value.
          */
         public static final short UnsupportedGeoKeyStorage_1 = 21;
+
+        /**
+         * TIFF file “{0}” uses an unsupported map projection.
+         */
+        public static final short UnsupportedProjectionMethod_1 = 23;
     }
 
     /**

Modified: sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources.properties?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources.properties [ISO-8859-1] (original)
+++ sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources.properties [ISO-8859-1] Wed Jul 26 16:14:09 2017
@@ -26,6 +26,7 @@ DefaultValueForAttribute_2        = No v
 DitheringOrHalftoningApplied_2    = An ordered dither or halftone technique has been applied to the image data. The dithering or halftoning matrix size is {0}\u00d7{1}.
 IgnoredTag_1                      = The \u201c{0}\u201d TIFF tag has been ignored.
 IgnoredGeoKeys_1                  = The following GeoTIFF keys have been ignored: {0}
+InconsistentMapProjParameter_4    = Map projection parameter \u201c{2}\u201d will be ignored because its value ({3}) is inconsistent with the \u201c{0} = {1}\u201d parameter.
 InconsistentTileStrip_1           = TIFF image \u201c{0}\u201d shall be either tiled or organized into strips.
 InvalidGeoValue_2                 = \u201c{1}\u201d is not a valid value for the \u201c{0}\u201d GeoTIFF key.
 ListTooShort_3                    = TIFF tag \u201c{0}\u201d shall contain at least {1} values but found only {2}.
@@ -34,9 +35,12 @@ MissingGeoValue_1                 = No v
 MissingValue_2                    = Can not read TIFF image from \u201c{0}\u201d because the \u201c{1}\u201d tag is missing.
 NotTheEpsgValue_5                 = The file defines \u201c{2}\u201d with value {3}{4}, but that value should be {1}{4} according parent definition ({0}).
 RandomizedProcessApplied          = A randomized process such as error diffusion has been applied to the image data.
+UndefinedDataFormat_1             = The \u201c{0}\u201d GeoTIFF file does not specify the values format.
 UnexpectedListOfValues_2          = A single value was expected for the \u201c{0}\u201d key but {1} values have been found.
 UnexpectedParameter_2             = The \u201c{1}\u201d parameter was not expected for the \u201c{0}\u201d projection method.
 UnexpectedTileCount_3             = Found {2} tiles or strips in the \u201c{0}\u201d file while {1} were expected.
+UnknownCRS_1                      = TIFF file \u201c{0}\u201d uses an unknown coordinate reference system.
 UnsupportedCoordinateSystemKind_1 = Coordinate system kind {0} is unsupported.
 UnsupportedGeoKeyDirectory_1      = Version {0}\u00a0of GeoTIFF key directory is not supported.
 UnsupportedGeoKeyStorage_1        = Unsupported storage location for the \u201c{0}\u201d GeoTIFF value.
+UnsupportedProjectionMethod_1     = TIFF file \u201c{0}\u201d uses an unsupported map projection.

Modified: sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources_fr.properties?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources_fr.properties [ISO-8859-1] (original)
+++ sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources_fr.properties [ISO-8859-1] Wed Jul 26 16:14:09 2017
@@ -31,6 +31,7 @@ DefaultValueForAttribute_2        = Aucu
 DitheringOrHalftoningApplied_2    = Un tramage ordonn\u00e9 ou une technique en demi-teinte a \u00e9t\u00e9 appliqu\u00e9. La taille de la matrice de tramage est {0}\u00d7{1}.
 IgnoredTag_1                      = Le tag TIFF \u00ab\u202f{0}\u202f\u00bb a \u00e9t\u00e9 ignor\u00e9.
 IgnoredGeoKeys_1                  = Les cl\u00e9s GeoTIFF suivantes ont \u00e9t\u00e9 ignor\u00e9es\u2008: {0}
+InconsistentMapProjParameter_4    = Le param\u00e8tre de projection cartographique \u00ab\u202f{2}\u202f\u00bb sera ignor\u00e9 car sa valeur ({3}) est incoh\u00e9rente avec le param\u00e8tre \u00ab\u202f{0} = {1}\u202f\u00bb.
 InconsistentTileStrip_1           = L\u2019image TIFF \u00ab\u202f{0}\u202f\u00bb doit \u00eatre soit tuil\u00e9e, soit organis\u00e9e par bandes.
 InvalidGeoValue_2                 = La valeur \u00ab\u202f{1}\u202f\u00bb n\u2019est pas valide pour la cl\u00e9 GeoTIFF \u00ab\u202f{0}\u202f\u00bb.
 ListTooShort_3                    = Le tag TIFF \u00ab\u202f{0}\u202f\u00bb devrait contenir au moins {1} valeurs alors qu\u2019on n\u2019en a trouv\u00e9 que {2}.
@@ -39,9 +40,12 @@ MissingGeoValue_1                 = Aucu
 MissingValue_2                    = Ne peut pas lire l\u2019image TIFF provenant de \u00ab\u202f{0}\u202f\u00bb car le tag \u00ab\u202f{1}\u202f\u00bb est manquant.
 NotTheEpsgValue_5                 = Le fichier d\u00e9finit \u00ab\u202f{2}\u202f\u00bb avec la valeur {3}{4}, mais cette valeur devrait \u00eatre {1}{4} pour \u00eatre en accord avec la d\u00e9finition du parent {0}.
 RandomizedProcessApplied          = Un processus randomis\u00e9 comme la diffusion d\u2019erreur a \u00e9t\u00e9 appliqu\u00e9.
+UndefinedDataFormat_1             = Le fichier GeoTIFF \u00ab\u202f{0}\u202f\u00bb ne sp\u00e9cifie pas le format de ses valeurs.
 UnexpectedListOfValues_2          = Une seule valeur \u00e9tait attendue pour la cl\u00e9 \u00ab\u202f{0}\u202f\u00bb, mais on en a trouv\u00e9es {1}.
 UnexpectedParameter_2             = Le param\u00e8tre \u00ab\u202f{1}\u202f\u00bb est inattendu pour la m\u00e9thode de projection \u00ab\u202f{0}\u202f\u00bb.
 UnexpectedTileCount_3             = {2} tuiles ont \u00e9t\u00e9 trouv\u00e9es dans le fichier \u00ab\u202f{0}\u202f\u00bb alors qu\u2019on en attendait {1}.
+UnknownCRS_1                      = Le fichier TIFF \u00ab\u202f{0}\u202f\u00bb utilise un syst\u00e8me de r\u00e9f\u00e9rence des coordonn\u00e9es inconnu.
 UnsupportedCoordinateSystemKind_1 = Le type de syst\u00e8me de coordonn\u00e9es {0} n\u2019est pas support\u00e9.
 UnsupportedGeoKeyDirectory_1      = La version {0} du r\u00e9pertoire de cl\u00e9s GeoTIFF n\u2019est pas support\u00e9e.
 UnsupportedGeoKeyStorage_1        = La valeur GeoTIFF \u00ab\u202f{0}\u202f\u00bb utilise un mode de stockage non-support\u00e9.
+UnsupportedProjectionMethod_1     = Le fichier TIFF \u00ab\u202f{0}\u202f\u00bb utilise une projection cartographique non-support\u00e9e.

Modified: sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CRSBuilder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CRSBuilder.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CRSBuilder.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CRSBuilder.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -71,7 +71,6 @@ import org.apache.sis.internal.util.Util
 import org.apache.sis.internal.util.Numerics;
 import org.apache.sis.math.Vector;
 import org.apache.sis.measure.Units;
-import org.apache.sis.util.iso.DefaultNameSpace;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.referencing.CRS;
 import org.apache.sis.referencing.CommonCRS;
@@ -82,6 +81,8 @@ import org.apache.sis.referencing.crs.De
 import org.apache.sis.referencing.factory.GeodeticAuthorityFactory;
 import org.apache.sis.referencing.factory.GeodeticObjectFactory;
 import org.apache.sis.io.TableAppender;
+import org.apache.sis.util.iso.DefaultNameSpace;
+import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.Characters;
 import org.apache.sis.util.Debug;
@@ -247,6 +248,13 @@ final class CRSBuilder {
     private Identifier lastName;
 
     /**
+     * {@code true} when an exception has been thrown but this {@code CRSBuilder} already reported a warning,
+     * so there is no need for the caller to report a warning again. {@code CRSBuilder} sometime reports warnings
+     * itself when it can provide a better warning message than what the caller can do.
+     */
+    boolean alreadyReported;
+
+    /**
      * Creates a new builder of coordinate reference systems.
      *
      * @param reader  where to report warnings if any.
@@ -391,6 +399,7 @@ final class CRSBuilder {
             return Integer.parseInt(value.toString());
         } catch (NumberFormatException e) {
             invalidValue(key, value);
+            alreadyReported = true;
             throw e;
         }
     }
@@ -414,6 +423,7 @@ final class CRSBuilder {
             return Double.parseDouble(value.toString());
         } catch (NumberFormatException e) {
             invalidValue(key, value);
+            alreadyReported = true;
             throw e;
         }
     }
@@ -432,6 +442,7 @@ final class CRSBuilder {
         if (value != null) {
             return value;
         }
+        alreadyReported = true;
         throw new NoSuchElementException(missingValue(key));
     }
 
@@ -450,6 +461,7 @@ final class CRSBuilder {
         if (!Double.isNaN(value)) {
             return value;
         }
+        alreadyReported = true;
         throw new NoSuchElementException(missingValue(key));
     }
 
@@ -728,6 +740,8 @@ final class CRSBuilder {
      * <ul>
      *   <li>{@link #build(Vector, Vector, String)} must have been invoked before this method.</li>
      *   <li>{@link ImageFileDirectory} must have filled its part of metadata before to invoke this method.</li>
+     *   <li>{@link MetadataBuilder#newGridRepresentation(MetadataBuilder.GridType)} should have been invoked
+     *       with the appropriate {@code GEORECTIFIED} or {@code GEOREFERENCEABLE} type.</li>
      * </ul>
      *
      * After execution, this method emits a warning for unprocessed GeoTIFF tags.
@@ -900,13 +914,13 @@ final class CRSBuilder {
     private PrimeMeridian createPrimeMeridian(final String[] names, final Unit<Angle> unit) throws FactoryException {
         final int epsg = getAsInteger(GeoKeys.PrimeMeridian);
         switch (epsg) {
-            case GeoCodes.undefined: {
-                break;                      // If not specified, default to Greenwich.
-            }
+            case GeoCodes.undefined:      // If not specified, should default to Greenwich but we nevertheless verify.
             case GeoCodes.userDefined: {
                 final double longitude = getAsDouble(GeoKeys.PrimeMeridianLong);
                 if (Double.isNaN(longitude)) {
-                    missingValue(GeoKeys.PrimeMeridianLong);
+                    if (epsg != GeoCodes.undefined) {
+                        missingValue(GeoKeys.PrimeMeridianLong);
+                    }
                 } else if (longitude != 0) {
                     /*
                      * If the prime meridian is not Greenwich, create that meridian but do not use the
@@ -971,6 +985,7 @@ final class CRSBuilder {
         final int epsg = getAsInteger(GeoKeys.Ellipsoid);
         switch (epsg) {
             case GeoCodes.undefined: {
+                alreadyReported = true;
                 throw new NoSuchElementException(missingValue(GeoKeys.GeodeticDatum));
             }
             case GeoCodes.userDefined: {
@@ -1053,6 +1068,7 @@ final class CRSBuilder {
         final int epsg = getAsInteger(GeoKeys.GeodeticDatum);
         switch (epsg) {
             case GeoCodes.undefined: {
+                alreadyReported = true;
                 throw new NoSuchElementException(missingValue(GeoKeys.GeodeticDatum));
             }
             case GeoCodes.userDefined: {
@@ -1174,7 +1190,7 @@ final class CRSBuilder {
     }
 
     /**
-     * Returns the name at the given index if non-null. If that name is null, search for a name is a sister element
+     * Returns the name at the given index if non-null. If that name is null, search for a name in a sister element
      * (e.g. the datum name or the geographic CRS name). If none is found, returns {@code null}.
      */
     private static String getOrDefault(final String[] names, int component) {
@@ -1219,6 +1235,7 @@ final class CRSBuilder {
         final int epsg = getAsInteger(GeoKeys.GeographicType);
         switch (epsg) {
             case GeoCodes.undefined: {
+                alreadyReported = true;
                 throw new NoSuchElementException(missingValue(GeoKeys.GeographicType));
             }
             case GeoCodes.userDefined: {
@@ -1287,6 +1304,7 @@ final class CRSBuilder {
         final int epsg = getAsInteger(GeoKeys.GeographicType);
         switch (epsg) {
             case GeoCodes.undefined: {
+                alreadyReported = true;
                 throw new NoSuchElementException(missingValue(GeoKeys.GeographicType));
             }
             case GeoCodes.userDefined: {
@@ -1348,6 +1366,51 @@ final class CRSBuilder {
     //////////////////////////////////////////////////////////////////////////////////////////////////
 
     /**
+     * Map projection parameters to be considered as aliases. This table is used for reading GeoTIFF files
+     * that are not really well-formed, but for which we can reasonably guess what was the producer intend
+     * and which parameters were confused. See {@link #aliases(Map)} for more explanation.
+     */
+    private static final short[][] PARAMETER_ALIASES = {
+        {GeoKeys.NatOriginLong, GeoKeys.FalseOriginLong,     GeoKeys.CenterLong},
+        {GeoKeys.NatOriginLat,  GeoKeys.FalseOriginLat,      GeoKeys.CenterLat},
+        {GeoKeys.FalseEasting,  GeoKeys.FalseOriginEasting,  GeoKeys.CenterEasting},
+        {GeoKeys.FalseNorthing, GeoKeys.FalseOriginNorthing, GeoKeys.CenterNorthing},
+        {GeoKeys.ScaleAtNatOrigin,                           GeoKeys.ScaleAtCenter}
+    };
+
+    /**
+     * Updates a mapping from GeoTIFF numerical identifiers to parameter names by adding parameter aliases.
+     * This method adds to the given map some GeoTIFF keys to be considered synonymous to an existing key.
+     * Those "synonymous" parameters are strictly speaking not for the map projection that we are parsing,
+     * but it is common to see GeoTIFF files with "wrong" projection parameter codes. For example:
+     *
+     * <ul>
+     *   <li>The {@code "CT_LambertConfConic_1SP"} projection uses a {@code "NatOriginLong"} parameter.</li>
+     *   <li>The {@code "CT_LambertConfConic_2SP"} projection uses a {@code "FalseOriginLong"} parameter.</li>
+     * </ul>
+     *
+     * but we sometime see {@code "NatOriginLong"} parameter used for the {@code "CT_LambertConfConic_2SP"} projection.
+     * Semantically those two parameters are for two different things but mathematically they are used in the same way.
+     * Those "synonymous" will be invisible to the user; the map projection that (s)he will get uses the names defined
+     * in the descriptor (not in the GeoTIFF file).
+     */
+    private static void aliases(final Map<Integer,String> mapping) {
+        for (final short[] codes : PARAMETER_ALIASES) {
+            for (int i=0; i<codes.length; i++) {
+                final String name = mapping.get(Short.toUnsignedInt(codes[i]));
+                if (name != null) {
+                    for (int j=0; j<codes.length; j++) {
+                        if (j != i) {
+                            mapping.putIfAbsent(Short.toUnsignedInt(codes[j]), name);
+                        }
+                    }
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
      * Creates a projected CRS from an EPSG code or from user-defined parameters.
      * Some GeoTIFF values used by this method are:
      *
@@ -1374,6 +1437,7 @@ final class CRSBuilder {
         final int epsg = getAsInteger(GeoKeys.ProjectedCSType);
         switch (epsg) {
             case GeoCodes.undefined: {
+                alreadyReported = true;
                 throw new NoSuchElementException(missingValue(GeoKeys.ProjectedCSType));
             }
             case GeoCodes.userDefined: {
@@ -1437,6 +1501,7 @@ final class CRSBuilder {
      * @param  linearUnit   the linear unit of easting and northing values.
      * @throws NoSuchElementException if a mandatory value is missing.
      * @throws NumberFormatException if a numeric value was stored as a string and can not be parsed.
+     * @throws ParameterNotFoundException if the GeoTIFF file defines an unexpected map projection parameter.
      * @throws ClassCastException if an object defined by an EPSG code is not of the expected type.
      * @throws FactoryException if an error occurred during objects creation with the factories.
      */
@@ -1446,18 +1511,22 @@ final class CRSBuilder {
         final int epsg = getAsInteger(GeoKeys.Projection);
         switch (epsg) {
             case GeoCodes.undefined: {
+                alreadyReported = true;
                 throw new NoSuchElementException(missingValue(GeoKeys.Projection));
             }
             case GeoCodes.userDefined: {
                 final Unit<Angle>         azimuthUnit = createUnit(GeoKeys.AzimuthUnits, (short) 0, Angle.class, Units.DEGREE);
                 final String              type        = getMandatoryString(GeoKeys.CoordTrans);
-                final OperationMethod     method      = operationFactory().getOperationMethod(type);
+                final OperationMethod     method      = operationFactory().getOperationMethod(Constants.GEOTIFF + ':' + type);
                 final ParameterValueGroup parameters  = method.getParameters().createValue();
+                final Map<Integer,String> toNames     = ReferencingUtilities.identifierToName(parameters.getDescriptor(), Citations.GEOTIFF);
+                final Map<Object,Number>  paramValues = new HashMap<>();    // Keys: [String|Short] instances for [known|unknown] parameters.
+                final Map<Short,Unit<?>>  deferred    = new HashMap<>();    // Only unknown parameters.
                 final Iterator<Map.Entry<Short,Object>> it = geoKeys.entrySet().iterator();
                 while (it.hasNext()) {
                     final Unit<?> unit;
                     final Map.Entry<Short,?> entry = it.next();
-                    final short key = entry.getKey();
+                    final Short key = entry.getKey();
                     switch (GeoKeys.unitOf(key)) {
                         case GeoKeys.RATIO:   unit = Units.UNITY; break;
                         case GeoKeys.LINEAR:  unit = linearUnit;  break;
@@ -1465,15 +1534,52 @@ final class CRSBuilder {
                         case GeoKeys.AZIMUTH: unit = azimuthUnit; break;
                         default: continue;
                     }
-                    final double value = ((Number) entry.getValue()).doubleValue();
+                    final Number value = (Number) entry.getValue();
                     it.remove();
-                    parameters.parameter("GeoTIFF:" + key).setValue(value, unit);
+                    final String paramName = toNames.get(Short.toUnsignedInt(key));
+                    if (paramName != null) {
+                        paramValues.put(paramName, value);
+                        parameters.parameter(paramName).setValue(value.doubleValue(), unit);
+                    } else {
+                        paramValues.put(key, value);
+                        deferred.put(key, unit);
+                    }
+                }
+                /*
+                 * At this point we finished to set all known map projection parameters. Sometime GeoTIFF files
+                 * set the same parameter many times using different names as a safety for GeoTIFF readers that
+                 * expect wrong parameters. If this is the case, verify that the parameter values are consistent.
+                 * It is also possible that we found new parameters (actually parameters using the wrong names).
+                 */
+                if (!deferred.isEmpty()) {
+                    aliases(toNames);
+                    for (final Map.Entry<Short,Unit<?>> entry : deferred.entrySet()) {
+                        final Short key = entry.getKey();
+                        String paramName = toNames.get(Short.toUnsignedInt(key));
+                        if (paramName == null) {
+                            paramName = GeoKeys.name(key);
+                            throw new ParameterNotFoundException(reader.errors().getString(
+                                    Errors.Keys.UnexpectedParameter_1, paramName), paramName);
+                        }
+                        final Number value  = paramValues.get(key);
+                        final Number actual = paramValues.putIfAbsent(paramName, value);
+                        if (actual == null) {
+                            parameters.parameter(paramName).setValue(value.doubleValue(), entry.getValue());
+                        } else if (!actual.equals(value)) {
+                            warning(Resources.Keys.InconsistentMapProjParameter_4, paramName, actual, GeoKeys.name(key), value);
+                        }
+                    }
                 }
                 final Conversion c = operationFactory().createDefiningConversion(properties(name), method, parameters);
                 lastName = c.getName();
                 return c;
             }
             default: {
+                /*
+                 * Conversion defined by EPSG code. In principle we should just use the EPSG code.
+                 * But if the file also defines the components, verify that those components are
+                 * consistent with what we would expect for a conversion of the given EPSG code.
+                 */
                 final Conversion projection = (Conversion) epsgFactory().createCoordinateOperation(String.valueOf(epsg));
                 verify(projection, angularUnit, linearUnit);
                 return projection;
@@ -1546,6 +1652,7 @@ final class CRSBuilder {
         switch (epsg) {
             case GeoCodes.undefined:
             case GeoCodes.userDefined: {
+                alreadyReported = true;
                 throw new NoSuchElementException(missingValue(GeoKeys.VerticalDatum));
             }
             default: {

Modified: sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -33,6 +33,7 @@ import org.apache.sis.storage.DataStoreC
 import org.apache.sis.storage.UnsupportedStorageException;
 import org.apache.sis.internal.storage.io.ChannelDataInput;
 import org.apache.sis.internal.storage.MetadataBuilder;
+import org.apache.sis.internal.util.Constants;
 import org.apache.sis.metadata.sql.MetadataStoreException;
 import org.apache.sis.storage.DataStoreClosedException;
 import org.apache.sis.util.resources.Errors;
@@ -107,12 +108,12 @@ public class GeoTiffStore extends DataSt
             final Reader reader = reader();
             final MetadataBuilder builder = reader.metadata;
             try {
-                builder.setFormat("GeoTIFF");
+                builder.setFormat(Constants.GEOTIFF);
             } catch (MetadataStoreException e) {
                 warning(null, e);
             }
-            builder.add(encoding, MetadataBuilder.Scope.METADATA);
-            builder.add(ScopeCode.COVERAGE);
+            builder.addEncoding(encoding, MetadataBuilder.Scope.METADATA);
+            builder.addResourceScope(ScopeCode.COVERAGE, null);
             final Locale locale = getLocale();
             int n = 0;
             try {
@@ -136,7 +137,7 @@ public class GeoTiffStore extends DataSt
     private Reader reader() throws DataStoreException {
         final Reader r = reader;
         if (r == null) {
-            throw new DataStoreClosedException(getLocale(), "GeoTIFF", StandardOpenOption.READ);
+            throw new DataStoreClosedException(getLocale(), Constants.GEOTIFF, StandardOpenOption.READ);
         }
         return r;
     }

Modified: sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStoreProvider.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStoreProvider.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStoreProvider.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStoreProvider.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -26,6 +26,7 @@ import org.apache.sis.storage.ProbeResul
 import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.internal.storage.Capabilities;
 import org.apache.sis.internal.storage.Capability;
+import org.apache.sis.internal.util.Constants;
 
 
 /**
@@ -69,7 +70,7 @@ public class GeoTiffStoreProvider extend
      */
     @Override
     public String getShortName() {
-        return "GeoTIFF";
+        return Constants.GEOTIFF;
     }
 
     /**

Modified: sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -28,11 +28,18 @@ import javax.measure.Unit;
 import javax.measure.quantity.Length;
 import org.opengis.metadata.citation.DateType;
 import org.opengis.util.FactoryException;
+import org.opengis.util.NoSuchIdentifierException;
+import org.opengis.parameter.ParameterNotFoundException;
+import org.opengis.referencing.NoSuchAuthorityCodeException;
+import org.opengis.referencing.operation.TransformException;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.apache.sis.referencing.operation.matrix.Matrices;
+import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.internal.geotiff.Resources;
+import org.apache.sis.internal.storage.MetadataBuilder;
 import org.apache.sis.internal.storage.io.ChannelDataInput;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.DataStoreContentException;
-import org.apache.sis.internal.storage.MetadataBuilder;
 import org.apache.sis.math.Vector;
 import org.apache.sis.measure.Units;
 
@@ -60,6 +67,13 @@ final class ImageFileDirectory {
     private static final byte TILE = 1, STRIP = 2;
 
     /**
+     * Possible value for {@link #sampleFormat} specifying how to interpret each data sample in a pixel.
+     * Those values are not necessarily the same than the ones documented in {@link Tags#SampleFormat}.
+     * Default value is {@link #UNSIGNED}.
+     */
+    private static final byte SIGNED = 1, UNSIGNED = 0, FLOAT = 3;
+
+    /**
      * The GeoTIFF reader which contain this {@code ImageFileDirectory}.
      * Used for fetching information like the input channel and where to report warnings.
      */
@@ -153,6 +167,12 @@ final class ImageFileDirectory {
     private boolean isPlanar;
 
     /**
+     * How to interpret each data sample in a pixel.
+     * Possible values are {@link #SIGNED}, {@link #UNSIGNED} or {@link #FLOAT}.
+     */
+    private byte sampleFormat;
+
+    /**
      * Whether the bit order should be reversed. This boolean value is determined from the {@code FillOrder} TIFF tag.
      *
      * <ul>
@@ -262,9 +282,10 @@ final class ImageFileDirectory {
     private short cellWidth = -1, cellHeight = -1;
 
     /**
-     * The minimum or maximum sample value found in the image, or {@code NaN} if unspecified.
+     * The minimum or maximum sample value found in the image, with one value per band.
+     * May be a vector of length 1 if the same single value applies to all bands.
      */
-    private double minValue = Double.NaN, maxValue = Double.NaN;
+    private Vector minValues, maxValues;
 
     /**
      * The number of pixels per {@link #resolutionUnit} in the {@link #imageWidth} and the {@link #imageHeight}
@@ -308,6 +329,38 @@ final class ImageFileDirectory {
     private String asciiGeoParameters;
 
     /**
+     * Raster model tie points. This vector contains ordinate values structured as (I,J,K, X,Y,Z) records.
+     * The (I,J,K) ordinate values specify the point at location (I,J) in raster space with pixel-value K,
+     * and (X,Y,Z) ordinate values specify the point in the Coordinate Reference System. In most cases the
+     * coordinate system is only two-dimensional, in which case both K and Z should be set to zero.
+     */
+    private Vector modelTiePoints;
+
+    /**
+     * The conversion from grid coordinates to CRS coordinates. It can be determined in different ways,
+     * from simpler to more complex:
+     *
+     * <ul>
+     *   <li>By a combination of a single {@link #modelTiePoints} with the 3 values given in
+     *       {@link Tags#ModelPixelScaleTag} as documented in the Javadoc of that tag.</li>
+     *   <li>By a {@link Tags#ModelTransformation} giving all coefficients of the 4×4 matrix}.
+     *       Note that the third row and the third column have all their value set to 0 if the
+     *       space model (or the coordinate reference system) should be two-dimensional.</li>
+     *   <li>By building a non-linear transformation from all {@link #modelTiePoints}.
+     *       Such transformation can not be stored in a matrix, so will leave this field {@code null}.</li>
+     * </ul>
+     *
+     * By convention, the translation column is set to NaN values if it needs to be computed from the tie point.
+     */
+    private MatrixSIS gridToCRS;
+
+    /**
+     * {@code true} if {@link #gridToCRS} has been specified by a complete matrix ({@link Tags#ModelTransformation}),
+     * or {@code false} if it has been specified by the scale factors only ({@link Tags#ModelPixelScaleTag}).
+     */
+    private boolean completeMatrixSpecified;
+
+    /**
      * Creates a new image file directory.
      *
      * @param reader  information about the input stream to read, the metadata and the character encoding.
@@ -326,6 +379,13 @@ final class ImageFileDirectory {
     /**
      * Shortcut for a frequently requested information.
      */
+    private String filename() {
+        return input().filename;
+    }
+
+    /**
+     * Shortcut for a frequently requested information.
+     */
     private Charset encoding() {
         return reader.owner.encoding;
     }
@@ -480,6 +540,21 @@ final class ImageFileDirectory {
                 break;
             }
             /*
+             * How to interpret each data sample in a pixel. The size of data samples is still
+             * specified by the BitsPerSample field.
+             */
+            case Tags.SampleFormat: {
+                final int value = type.readInt(input(), count);
+                switch (value) {
+                    default: return value;                          // Warning to be reported by the caller.
+                    case 1: sampleFormat = UNSIGNED; break;         // Unsigned integer data (default).
+                    case 2: sampleFormat = SIGNED;   break;         // Two’s complement signed integer data.
+                    case 3: sampleFormat = FLOAT;    break;         // IEEE floating point data.
+                    case 4: warning(Level.WARNING, Resources.Keys.UndefinedDataFormat_1, filename()); break;
+                }
+                break;
+            }
+            /*
              * Number of bits per component. The array length should be the number of components in a
              * pixel (e.g. 3 for RGB values). Typically, all components have the same number of bits.
              * But the TIFF specification allows different values.
@@ -496,7 +571,7 @@ final class ImageFileDirectory {
                 for (int i = 1; i < length; i++) {
                     if (values.shortValue(i) != bitsPerSample) {
                         throw new DataStoreContentException(reader.resources().getString(
-                                Resources.Keys.ConstantValueRequired_3, "BitsPerSample", input().filename, values));
+                                Resources.Keys.ConstantValueRequired_3, "BitsPerSample", filename(), values));
                     }
                 }
                 break;
@@ -553,11 +628,12 @@ final class ImageFileDirectory {
                 break;
             }
             /*
-             * The minimum component value used. Default is 0.
+             * The minimum component value used. MinSampleValue is a single value that apply to all bands
+             * while SMinSampleValue lists separated values for each band. Default is 0.
              */
-            case Tags.MinSampleValue: {
-                final double v = type.readDouble(input(), count);
-                if (Double.isNaN(minValue) || v < minValue) minValue = v;
+            case Tags.MinSampleValue:
+            case Tags.SMinSampleValue: {
+                minValues = extremum(minValues, type.readVector(input(), count), false);
                 break;
             }
             /*
@@ -565,9 +641,9 @@ final class ImageFileDirectory {
              * This field is for statistical purposes and should not to be used to affect the
              * visual appearance of an image, unless a map styling is applied.
              */
-            case Tags.MaxSampleValue: {
-                final double v = type.readDouble(input(), count);
-                if (Double.isNaN(maxValue) || v > maxValue) maxValue = v;
+            case Tags.MaxSampleValue:
+            case Tags.SMaxSampleValue: {
+                maxValues = extremum(maxValues, type.readVector(input(), count), true);
                 break;
             }
 
@@ -645,6 +721,58 @@ final class ImageFileDirectory {
                 // TODO
                 break;
             }
+            /*
+             * The "grid to CRS" conversion as a 4×4 matrix in row-major fashion. The third matrix row and
+             * the third matrix column may contain only zero values; this block does not reduce the number
+             * of dimensions from 3 to 2.
+             */
+            case Tags.ModelTransformation: {
+                final Vector m = type.readVector(input(), count);
+                final int size = m.size();
+                final int n;
+                switch (size) {
+                    case  6:                    // Assume 2D model with implicit [0 0 1] last row.
+                    case  9: n = 3; break;      // Assume 2D model with full 3×3 matrix.
+                    case 12:                    // Assume 3D model with implicit [0 0 0 1] last row.
+                    case 16: n = 4; break;      // 3D model with full 4×4 matrix, as required by GeoTIFF spec.
+                    default: return m;
+                }
+                completeMatrixSpecified = true;
+                gridToCRS = Matrices.createZero(n, n);
+                gridToCRS.setElement(n-1, n-1, 1);
+                for (int i=0; i<size; i++) {
+                    gridToCRS.setElement(i / n, i % n, m.doubleValue(i));
+                }
+                break;
+            }
+            /*
+             * The "grid to CRS" conversion with only the scale factor specified. This block sets the
+             * translation column to NaN, meaning that it will need to be computed from the tie point.
+             */
+            case Tags.ModelPixelScaleTag: {
+                final Vector m = type.readVector(input(), count);
+                final int size = m.size();
+                if (size < 2 || size > 3) {     // Length should be exactly 3, but we make this reader tolerant.
+                    return m;
+                }
+                completeMatrixSpecified = false;
+                gridToCRS = Matrices.createZero(size+1, size+1);
+                gridToCRS.setElement(size, size, 1);
+                for (int i=0; i<size; i++) {
+                    double e = m.doubleValue(i);
+                    if (i == 1) e = -e;                             // Make y scale factor negative.
+                    gridToCRS.setElement(i, i, e);
+                    gridToCRS.setElement(i, size, Double.NaN);
+                }
+                break;
+            }
+            /*
+             * The mapping from pixel coordinates to CRS coordinates as a sequence of (I,J,K, X,Y,Z) records.
+             */
+            case Tags.ModelTiePoints: {
+                modelTiePoints = type.readVector(input(), count);
+                break;
+            }
 
             ////////////////////////////////////////////////////////////////////////////////////////////////
             ////                                                                                        ////
@@ -689,7 +817,8 @@ final class ImageFileDirectory {
              */
             case Tags.DateTime: {
                 for (final String value : type.readString(input(), count, encoding())) {
-                    reader.metadata.add(reader.getDateFormat().parse(value), DateType.CREATION);
+                    reader.metadata.addCitationDate(reader.getDateFormat().parse(value),
+                            DateType.CREATION, MetadataBuilder.Scope.RESOURCE);
                 }
                 break;
             }
@@ -726,7 +855,7 @@ final class ImageFileDirectory {
              */
             case Tags.Model: {
                 for (final String value : type.readString(input(), count, encoding())) {
-                    reader.metadata.addInstrument(value);
+                    reader.metadata.addInstrument(null, value);
                 }
                 break;
             }
@@ -824,12 +953,39 @@ final class ImageFileDirectory {
     private void setTileTagFamily(final byte family) throws DataStoreContentException {
         if (tileTagFamily != family && tileTagFamily != 0) {
             throw new DataStoreContentException(reader.resources().getString(
-                    Resources.Keys.InconsistentTileStrip_1, input().filename));
+                    Resources.Keys.InconsistentTileStrip_1, filename()));
         }
         tileTagFamily = family;
     }
 
     /**
+     * Computes the minimal or maximal values of the given vector. Those vectors do not need to have the same length.
+     * One of those two vector will be modified in-place.
+     *
+     * @param  a    the first vector, or {@code null} if none.
+     * @param  b    the new vector to combine with the existing one. Can not be null.
+     * @param  max  {@code true} for computing the maximal values, or {@code false} for the minimal value.
+     */
+    private static Vector extremum(Vector a, Vector b, final boolean max) {
+        if (a != null) {
+            int s = b.size();
+            int i = a.size();
+            if (i > s) {                            // If a vector is longer than b, swap a and b.
+                i = s;
+                final Vector t = a; a = b; b = t;
+            }
+            while (--i >= 0) {                      // At this point, 'b' shall be the longest vector.
+                final double va = a.doubleValue(i);
+                final double vb = b.doubleValue(i);
+                if (Double.isNaN(vb) || (max ? va > vb : va < vb)) {
+                    b.set(i, va);
+                }
+            }
+        }
+        return b;
+    }
+
+    /**
      * Multiplies the given value by the number of bytes in one pixel,
      * or return -1 if the result is not an integer.
      *
@@ -873,6 +1029,9 @@ final class ImageFileDirectory {
      *   <li>Otherwise throws an exception.</li>
      * </ul>
      *
+     * This method opportunistically computes default value of optional fields
+     * when those values can be computed from other (usually mandatory) fields.
+     *
      * @throws DataStoreContentException if a mandatory tag is missing and can not be inferred.
      */
     final void validateMandatoryTags() throws DataStoreContentException {
@@ -894,7 +1053,7 @@ final class ImageFileDirectory {
             }
             default: {
                 throw new DataStoreContentException(reader.resources().getString(
-                        Resources.Keys.InconsistentTileStrip_1, input().filename));
+                        Resources.Keys.InconsistentTileStrip_1, filename()));
             }
         }
         if (tileOffsets == null) {
@@ -911,6 +1070,25 @@ final class ImageFileDirectory {
         if (colorMap != null) {
             ensureSameLength(Tags.ColorMap, Tags.BitsPerSample, colorMap.size(),  3 * (1 << bitsPerSample));
         }
+        if (sampleFormat != FLOAT) {
+            long minValue, maxValue;
+            if (sampleFormat == UNSIGNED) {
+                minValue =  0L;
+                maxValue = -1L;                 // All bits set to 1.
+            } else {
+                minValue = Long.MIN_VALUE;
+                maxValue = Long.MAX_VALUE;
+            }
+            final int shift = Long.SIZE - bitsPerSample;
+            if (shift >= 0 && shift < Long.SIZE) {
+                minValue >>>= shift;
+                maxValue >>>= shift;
+                if (minValue < maxValue) {      // Exclude the unsigned long case since we can not represent it.
+                    minValues = extremum(minValues, Vector.createSequence(minValue, 0, samplesPerPixel), false);
+                    maxValues = extremum(maxValues, Vector.createSequence(maxValue, 0, samplesPerPixel), true);
+                }
+            }
+        }
         /*
          * All of tile width, height and length information should be provided. But if only one of them is missing,
          * we can compute it provided that the file does not use any compression method. If there is a compression,
@@ -955,9 +1133,9 @@ final class ImageFileDirectory {
             }
         }
         /*
-         * Log a warning if the tile offset and tile byte count vectors do not have the same length. Then
-         * ensure that the number of tiles is equal to the expected number.  The formula below is the one
-         * documented in the TIFF specification and reproduced in tileWidth & tileHeight fields javadoc.
+         * Report an error if the tile offset and tile byte count vectors do not have the same length.
+         * Then ensure that the number of tiles is equal to the expected number. The formula below is the
+         * one documented in the TIFF specification and reproduced in tileWidth & tileHeight fields javadoc.
          */
         ensureSameLength(offsetsTag, byteCountsTag, tileOffsets.size(), tileByteCounts.size());
         long expectedCount = Math.multiplyExact(
@@ -969,7 +1147,16 @@ final class ImageFileDirectory {
         final int actualCount = Math.min(tileOffsets.size(), tileByteCounts.size());
         if (actualCount != expectedCount) {
             throw new DataStoreContentException(reader.resources().getString(Resources.Keys.UnexpectedTileCount_3,
-                    input().filename, expectedCount, actualCount));
+                    filename(), expectedCount, actualCount));
+        }
+        /*
+         * If a "grid to CRS" conversion has been specified with only the scale factor, we need to compute
+         * the translation terms now.
+         */
+        if (gridToCRS != null && !completeMatrixSpecified) {
+            if (!GridGeometry.setTranslationTerms(gridToCRS, modelTiePoints)) {
+                throw missingTag(Tags.ModelTiePoints);
+            }
         }
     }
 
@@ -990,8 +1177,13 @@ final class ImageFileDirectory {
         if (compression != null) {
             metadata.addCompression(compression.name().toLowerCase(locale));
         }
-        metadata.addMinimumSampleValue(minValue);
-        metadata.addMaximumSampleValue(maxValue);
+        for (int band = 0; band < samplesPerPixel;) {
+            metadata.newSampleDimension();
+            metadata.setBitPerSample(bitsPerSample);
+            if (minValues != null) metadata.addMinimumSampleValue(minValues.doubleValue(Math.min(band, minValues.size()-1)));
+            if (maxValues != null) metadata.addMaximumSampleValue(maxValues.doubleValue(Math.min(band, maxValues.size()-1)));
+            metadata.setBandIdentifier(++band);
+        }
         /*
          * Add the resolution into the metadata. Our current ISO 19115 implementation restricts
          * the resolution unit to metres, but it may be relaxed in a future SIS version.
@@ -1029,20 +1221,40 @@ final class ImageFileDirectory {
          * in which case the CRS builder returns null. This is safe since all MetadataBuilder methods
          * ignore null values (a design choice because this pattern come very often).
          */
+        final boolean isGeorectified = (modelTiePoints == null) || (gridToCRS != null);
+        metadata.newGridRepresentation(isGeorectified ? MetadataBuilder.GridType.GEORECTIFIED
+                                                      : MetadataBuilder.GridType.GEOREFERENCEABLE);
+        metadata.setGeoreferencingAvailability(gridToCRS != null, false, false);
+        CoordinateReferenceSystem crs = null;
         if (geoKeyDirectory != null) {
             final CRSBuilder helper = new CRSBuilder(reader);
             try {
-                metadata.add(helper.build(geoKeyDirectory, numericGeoParameters, asciiGeoParameters));
+                crs = helper.build(geoKeyDirectory, numericGeoParameters, asciiGeoParameters);
+                metadata.addReferenceSystem(crs);
                 helper.complete(metadata);
-            } catch (ClassCastException e) {
-                reader.owner.warning(null, e);
-            } catch (NumberFormatException | NoSuchElementException e) {
-                // Ignore - a warning with a better message has already been emitted.
-            }
-            geoKeyDirectory      = null;            // Not needed anymore, so let GC do its work.
-            numericGeoParameters = null;
-            asciiGeoParameters   = null;
+            } catch (NoSuchIdentifierException | ParameterNotFoundException e) {
+                short key = Resources.Keys.UnsupportedProjectionMethod_1;
+                if (e instanceof NoSuchAuthorityCodeException) {
+                    key = Resources.Keys.UnknownCRS_1;
+                }
+                reader.owner.warning(reader.resources().getString(key, reader.owner.getDisplayName()), e);
+            } catch (IllegalArgumentException | NoSuchElementException | ClassCastException e) {
+                if (!helper.alreadyReported) {
+                    reader.owner.warning(null, e);
+                }
+            }
+        }
+        try {
+            if (!isGeorectified) {
+                metadata.addGeolocation(new GridGeometry(filename(), crs, modelTiePoints));
+            }
+        } catch (TransformException e) {
+            reader.owner.warning(null, e);
         }
+        geoKeyDirectory      = null;            // Not needed anymore, so let GC do its work.
+        numericGeoParameters = null;
+        asciiGeoParameters   = null;
+        modelTiePoints       = null;
     }
 
     /**
@@ -1086,6 +1298,6 @@ final class ImageFileDirectory {
      */
     private DataStoreContentException missingTag(final short missing) {
         return new DataStoreContentException(reader.resources().getString(
-                Resources.Keys.MissingValue_2, input().filename, Tags.name(missing)));
+                Resources.Keys.MissingValue_2, filename(), Tags.name(missing)));
     }
 }

Modified: sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/Tags.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/Tags.java?rev=1803070&r1=1803069&r2=1803070&view=diff
==============================================================================
--- sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/Tags.java [UTF-8] (original)
+++ sis/branches/JDK9/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/Tags.java [UTF-8] Wed Jul 26 16:14:09 2017
@@ -161,6 +161,35 @@ final class Tags {
     public static final short GeoAsciiParams = (short) 0x87B1;            // 34737
 
     /**
+     * The tie points as (I,J,K,X,Y,Z) records in an array of floating-point numbers.
+     * This tag is also known as {@code Georeference}.
+     */
+    public static final short ModelTiePoints = (short) 0x8482;            // 33922
+
+    /**
+     * A vector of 3 floating-point values defining the "grid to CRS" conversion without rotation.
+     * The conversion is defined as below, when (I,J,K,X,Y,Z) is the tie point singleton record:
+     *
+     * ┌                       ┐
+     * │   Sx   0    0    Tx   │       Tx = X - I/Sx
+     * │   0   -Sy   0    Ty   │       Ty = Y + J/Sy
+     * │   0    0    Sz   Tz   │       Tz = Z - K/Sz  (if not 0)
+     * │   0    0    0    1    │
+     * └                       ┘
+     *
+     * Only one of {@code ModelPixelScaleTag} and {@link #ModelTransformation} should be used.
+     */
+    public static final short ModelPixelScaleTag = (short) 0x830E;        // 33550
+
+    /**
+     * Specifies the "grid to CRS" conversion (the transformation matrix between the raster space and the model space).
+     * If specified, the tag shall have the 16 values of a 4×4 matrix in row-major fashion. The last matrix row (i.e.
+     * the last 4 values) should be [0 0 0 1]. The row before should be [0 0 0 0] if the conversion is two-dimensional.
+     * Only one of {@link #ModelPixelScaleTag} and {@code ModelTransformation} should be used.
+     */
+    public static final short ModelTransformation = (short) 0x85D8;       // 34264
+
+    /**
      * Do not allow instantiation of this class.
      */
     private Tags() {



Mime
View raw message