You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2020/05/29 18:35:57 UTC

[sis] branch geoapi-4.0 updated (6722ec6 -> bc27996)

This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a change to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git.


    from 6722ec6  lfix(Feature): improve envelope operation to ensure attribute envelopes have a CRS defined if possible
     new e213eb5  Fix a NullPointerException when using directly a `new Formatter()` instance.
     new aa195d2  Trivial comments formatting (no code change).
     new bc27996  Better determination of the inverse of an OperationMethod.

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../internal/referencing/SignReversalComment.java  |  2 +-
 .../referencing/provider/AbstractProvider.java     | 15 ++++--
 .../sis/internal/referencing/provider/Affine.java  |  8 +--
 .../provider/FranceGeocentricInterpolation.java    |  6 +--
 .../provider/GeocentricToGeographic.java           |  8 +--
 .../referencing/provider/GeodeticOperation.java    |  8 +--
 .../referencing/provider/Geographic2Dto3D.java     |  8 +++
 .../referencing/provider/Geographic3Dto2D.java     | 22 ++++++++
 .../provider/GeographicToGeocentric.java           |  8 +--
 .../main/java/org/apache/sis/io/wkt/Formatter.java |  1 +
 .../org/apache/sis/referencing/Properties.java     | 37 ++++++++-----
 .../factory/ConcurrentAuthorityFactory.java        | 20 ++++----
 .../factory/IdentifiedObjectFinder.java            |  2 +-
 .../referencing/factory/sql/EPSGDataAccess.java    | 40 +++++++--------
 .../operation/CoordinateOperationRegistry.java     | 20 ++++++--
 .../operation/InverseOperationMethod.java          | 60 ++++++++++++----------
 .../referencing/operation/SubOperationInfo.java    |  5 +-
 17 files changed, 165 insertions(+), 105 deletions(-)


[sis] 02/03: Trivial comments formatting (no code change).

Posted by de...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git

commit aa195d2de07566aed26ce3bd19ed7618a4cdb74d
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Fri May 29 14:20:29 2020 +0200

    Trivial comments formatting (no code change).
---
 .../factory/ConcurrentAuthorityFactory.java        | 20 +++++------
 .../factory/IdentifiedObjectFinder.java            |  2 +-
 .../referencing/factory/sql/EPSGDataAccess.java    | 40 +++++++++++-----------
 3 files changed, 31 insertions(+), 31 deletions(-)

diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
index 0cb4656..421b7a9 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
@@ -299,7 +299,7 @@ public abstract class ConcurrentAuthorityFactory<DAO extends GeodeticAuthorityFa
          * Key collision is usually an error. But in this case we allow them in order to enable recursivity.
          * If during the creation of an object the program asks to this ConcurrentAuthorityFactory for the same
          * object (using the same key), then the default Cache implementation considers that situation as an
-         * error unless the above property has been set to 'true'.
+         * error unless the above property has been set to `true`.
          */
         remainingDAOs = maxConcurrentQueries;
         cache = new Cache<>(20, maxStrongReferences, false);
@@ -407,8 +407,8 @@ public abstract class ConcurrentAuthorityFactory<DAO extends GeodeticAuthorityFa
                 usage.timestamp = System.nanoTime();
             } catch (Throwable e) {
                 /*
-                 * If any kind of error occurred, restore the 'remainingDAO' field as if no code were executed.
-                 * This code would not have been needed if we were allowed to decrement 'remainingDAO' only as
+                 * If any kind of error occurred, restore the `remainingDAO` field as if no code were executed.
+                 * This code would not have been needed if we were allowed to decrement `remainingDAO` only as
                  * the very last step (when we know that everything else succeed).
                  * But it needed to be decremented inside the synchronized block.
                  */
@@ -548,7 +548,7 @@ public abstract class ConcurrentAuthorityFactory<DAO extends GeodeticAuthorityFa
 
     /**
      * Closes the expired Data Access Objects. This method should be invoked from a background task only.
-     * This method may reschedule the task again for an other execution if it appears that at least one
+     * This method may reschedule the task again for another execution if it appears that at least one
      * Data Access Object was not ready for disposal.
      *
      * @see #close()
@@ -610,7 +610,7 @@ public abstract class ConcurrentAuthorityFactory<DAO extends GeodeticAuthorityFa
          * all other kind of elements in the cache were dependencies searched as a side effect of the CRS search.
          * Since we have the result of the CRS search, we often do not need anymore the result of dependency search.
          *
-         * Touching 'findPool' also has the desired side-effect of letting WeakHashMap expunges stale entries.
+         * Touching `findPool` also has the desired side-effect of letting WeakHashMap expunges stale entries.
          */
         if (isEmpty) {
             synchronized (findPool) {
@@ -1805,7 +1805,7 @@ public abstract class ConcurrentAuthorityFactory<DAO extends GeodeticAuthorityFa
             if (acquireCount == 0) {
                 final GeodeticAuthorityFactory delegate = ((ConcurrentAuthorityFactory<?>) factory).getDataAccess();
                 /*
-                 * Set 'acquireCount' only after we succeed in fetching the factory, and before any operation on it.
+                 * Set `acquireCount` only after we succeed in fetching the factory, and before any operation on it.
                  * The intent is to get ConcurrentAuthorityFactory.release() invoked if and only if the getDataAccess()
                  * method succeed, no matter what happen after this point.
                  */
@@ -1855,7 +1855,7 @@ public abstract class ConcurrentAuthorityFactory<DAO extends GeodeticAuthorityFa
             synchronized (findPool) {
                 final FindEntry entry = findPool.get(object);
                 if (entry != null) {
-                    // 'finder' may be null if this method is invoked directly by this Finder.
+                    // `finder` may be null if this method is invoked directly by this Finder.
                     return entry.get((finder != null ? finder : this).isIgnoringAxes());
                 }
             }
@@ -1876,7 +1876,7 @@ public abstract class ConcurrentAuthorityFactory<DAO extends GeodeticAuthorityFa
                 if (c != null) {
                     entry = c;          // May happen if the same set has been computed in another thread.
                 }
-                // 'finder' should never be null since this method is not invoked directly by this Finder.
+                // `finder` should never be null since this method is not invoked directly by this Finder.
                 result = entry.set(finder.isIgnoringAxes(), result, object == searching);
             }
             return result;
@@ -1892,8 +1892,8 @@ public abstract class ConcurrentAuthorityFactory<DAO extends GeodeticAuthorityFa
             if (candidate == null) {
                 /*
                  * Nothing has been found in the cache. Delegates the search to the Data Access Object.
-                 * Note that the Data Access Object will itself callbacks our 'cache(…)' method, so there
-                 * is no need that we cache the result here.
+                 * Note that the Data Access Object will itself callbacks our `cache(…)` method,
+                 * so there is no need that we cache the result here.
                  */
                 synchronized (this) {
                     try {
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/IdentifiedObjectFinder.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/IdentifiedObjectFinder.java
index 6182293..469d90d 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/IdentifiedObjectFinder.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/IdentifiedObjectFinder.java
@@ -564,7 +564,7 @@ public class IdentifiedObjectFinder {
      */
     private static void exceptionOccurred(final FactoryException exception) {
         /*
-         * use 'getMessage()' instead of 'getLocalizedMessage()' for
+         * use `getMessage()` instead of `getLocalizedMessage()` for
          * giving preference to the locale of system administrator.
          */
         final LogRecord record = new LogRecord(Level.FINER, exception.getMessage());
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
index 7dc1e3b..e2f26ba 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
@@ -550,7 +550,7 @@ addURIs:    for (int i=0; ; i++) {
         Map<String,String> result = Collections.emptyMap();
         for (final TableInfo table : TableInfo.EPSG) {
             /*
-             * We test 'isAssignableFrom' in the two ways for catching the following use cases:
+             * We test `isAssignableFrom` in the two ways for catching the following use cases:
              *
              *  - table.type.isAssignableFrom(type)
              *    is for the case where a table is for CoordinateReferenceSystem while the user type is some subtype
@@ -749,7 +749,7 @@ codes:  for (int i=0; i<codes.length; i++) {
                 } while ((alias = !alias) == true);
             }
             /*
-             * At this point, 'identifier' should be the primary key. It may still be a non-numerical string
+             * At this point, `identifier` should be the primary key. It may still be a non-numerical string
              * if the above code did not found a match in the name column or in the alias table.
              */
             try {
@@ -1371,8 +1371,8 @@ codes:  for (int i=0; i<codes.length; i++) {
                 final boolean deprecated = getOptionalBoolean(result, 6);
                 final String  type       = getString   (code, result, 7);
                 /*
-                 * Note: Do not invoke 'createProperties' now, even if we have all required information,
-                 *       because the 'properties' map is going to overwritten by calls to 'createDatum', etc.
+                 * Note: Do not invoke `createProperties` now, even if we have all required information,
+                 *       because the `properties` map is going to overwritten by calls to `createDatum`, etc.
                  *
                  * The following switch statement should have a case for all "epsg_crs_kind" values enumerated
                  * in the "EPSG_Prepare.sql" file, except that the values in this Java code are in lower cases.
@@ -1383,8 +1383,8 @@ codes:  for (int i=0; i<codes.length; i++) {
                     /* ----------------------------------------------------------------------
                      *   GEOGRAPHIC CRS
                      *
-                     *   NOTE: 'createProperties' MUST be invoked after any call to an other
-                     *         'createFoo' method. Consequently, do not factor out.
+                     *   NOTE: `createProperties` MUST be invoked after any call to an other
+                     *         `createFoo` method. Consequently, do not factor out.
                      * ---------------------------------------------------------------------- */
                     case "geographic 2d":
                     case "geographic 3d": {
@@ -1415,7 +1415,7 @@ codes:  for (int i=0; i<codes.length; i++) {
                      *   PROJECTED CRS
                      *
                      *   NOTE: This method invokes itself indirectly, through createGeographicCRS.
-                     *         Consequently we can not use 'result' anymore after this block.
+                     *         Consequently we can not use `result` anymore after this block.
                      * ---------------------------------------------------------------------- */
                     case "projected": {
                         final String csCode  = getString(code, result,  8);
@@ -1445,7 +1445,7 @@ codes:  for (int i=0; i<codes.length; i++) {
                                  * Apache SIS can not instantiate a ProjectedCRS when the baseCRS uses such units, so we
                                  * set a flag asking to replace the deprecated CS by a supported one. Since that baseCRS
                                  * would not be exactly as defined by EPSG, we must not cache it because we do not want
-                                 * 'owner.createGeographicCRS(geoCode)' to return that modified CRS. Since the same CRS
+                                 * `owner.createGeographicCRS(geoCode)` to return that modified CRS. Since the same CRS
                                  * may be recreated every time a deprecated ProjectedCRS is created, we temporarily
                                  * shutdown the loggings in order to avoid the same warning to be logged many time.
                                  */
@@ -1471,7 +1471,7 @@ codes:  for (int i=0; i<codes.length; i++) {
                             try {
                                 /*
                                  * For a ProjectedCRS, the baseCRS is always geographic. So in theory we would not
-                                 * need the 'instanceof' check. However the EPSG dataset version 8.9 also uses the
+                                 * need the `instanceof` check. However the EPSG dataset version 8.9 also uses the
                                  * "projected" type for CRS that are actually derived CRS. See EPSG:5820 and 5821.
                                  */
                                 final Map<String, Object> properties = createProperties("Coordinate Reference System",
@@ -1519,7 +1519,7 @@ codes:  for (int i=0; i<codes.length; i++) {
                      *   COMPOUND CRS
                      *
                      *   NOTE: This method invokes itself recursively.
-                     *         Consequently, we can not use 'result' anymore.
+                     *         Consequently, we can not use `result` anymore.
                      * ---------------------------------------------------------------------- */
                     case "compound": {
                         final String code1 = getString(code, result, 12);
@@ -1533,7 +1533,7 @@ codes:  for (int i=0; i<codes.length; i++) {
                         } finally {
                             endOfRecursivity(CompoundCRS.class, epsg);
                         }
-                        // Note: Do not invoke 'createProperties' sooner.
+                        // Note: Do not invoke `createProperties` sooner.
                         crs  = crsFactory.createCompoundCRS(createProperties("Coordinate Reference System",
                                 name, epsg, area, scope, remarks, deprecated), crs1, crs2);
                         break;
@@ -1779,7 +1779,7 @@ codes:  for (int i=0; i<codes.length; i++) {
     {
         /*
          * We do not provide TOWGS84 information for WGS84 itself or for any other datum on our list of target datum,
-         * in order to avoid infinite recursivity. The 'ensureNonRecursive' call is an extra safety check which should
+         * in order to avoid infinite recursivity. The `ensureNonRecursive` call is an extra safety check which should
          * never fail, unless TARGET_CRS and TARGET_DATUM values do not agree with database content.
          */
         if (code == BursaWolfInfo.TARGET_DATUM) {
@@ -1922,8 +1922,8 @@ codes:  for (int i=0; i<codes.length; i++) {
         {
             while (result.next()) {
                 /*
-                 * One of 'semiMinorAxis' and 'inverseFlattening' values can be NULL in the database.
-                 * Consequently, we don't use 'getString(ResultSet, int)' for those parameters because
+                 * One of `semiMinorAxis` and `inverseFlattening` values can be NULL in the database.
+                 * Consequently, we don't use `getString(ResultSet, int)` for those parameters because
                  * we do not want to thrown an exception if a NULL value is found.
                  */
                 final Integer epsg              = getInteger  (code, result, 1);
@@ -1948,7 +1948,7 @@ codes:  for (int i=0; i<codes.length; i++) {
                     }
                 } else {
                     if (!Double.isNaN(semiMinorAxis)) {
-                        // Both 'inverseFlattening' and 'semiMinorAxis' are defined.
+                        // Both `inverseFlattening` and `semiMinorAxis` are defined.
                         // Log a warning and create the ellipsoid using the inverse flattening.
                         final LogRecord record = resources().getLogRecord(Level.WARNING,
                                 Resources.Keys.AmbiguousEllipsoid_1, Constants.EPSG + Constants.DEFAULT_SEPARATOR + code);
@@ -2296,7 +2296,7 @@ codes:  for (int i=0; i<codes.length; i++) {
                 final String axis = getString(cs, result, 1);
                 if (i < axes.length) {
                     /*
-                     * If 'i' is out of bounds, an exception will be thrown after the loop.
+                     * If `i` is out of bounds, an exception will be thrown after the loop.
                      * We do not want to thrown an ArrayIndexOutOfBoundsException here.
                      */
                     axes[i] = owner.createCoordinateSystemAxis(axis);
@@ -2455,7 +2455,7 @@ codes:  for (int i=0; i<codes.length; i++) {
                 if (source == target) {
                     /*
                      * The unit is a base unit. Verify its consistency:
-                     * conversion from 'source' to itself shall be the identity function.
+                     * conversion from `source` to itself shall be the identity function.
                      */
                     final boolean pb = (b != 1);
                     if (pb || c != 1) {
@@ -2899,7 +2899,7 @@ next:               while (r.next()) {
                         fillParameterValues(methodCode, epsg, parameters);
                     }
                     /*
-                     * Creates common properties. The 'version' and 'accuracy' are usually defined
+                     * Creates common properties. The `version` and `accuracy` are usually defined
                      * for transformations only. However, we check them for all kind of operations
                      * (including conversions) and copy the information unconditionally if present.
                      *
@@ -3050,7 +3050,7 @@ next:               while (r.next()) {
             boolean searchTransformations = false;
             do {
                 /*
-                 * This 'do' loop is executed twice: the first time for searching defining conversions, and the second
+                 * This `do` loop is executed twice: the first time for searching defining conversions, and the second
                  * time for searching all other kind of operations. Defining conversions are searched first because
                  * they are, by definition, the most accurate operations.
                  */
@@ -3378,7 +3378,7 @@ next:               while (r.next()) {
             if (exception == null) {
                 exception = e;
             } else {
-                e.addSuppressed(exception);     // Keep the connection thrown be Connection as the main one to report.
+                e.addSuppressed(exception);     // Keep the connection thrown by Connection as the main one to report.
             }
         }
         if (exception != null) {


[sis] 03/03: Better determination of the inverse of an OperationMethod.

Posted by de...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git

commit bc27996b5e9991ea35c58b10591224f2d3ab1daa
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Fri May 29 20:35:35 2020 +0200

    Better determination of the inverse of an OperationMethod.
---
 .../internal/referencing/SignReversalComment.java  |  2 +-
 .../referencing/provider/AbstractProvider.java     | 15 ++++--
 .../sis/internal/referencing/provider/Affine.java  |  8 +--
 .../provider/FranceGeocentricInterpolation.java    |  6 +--
 .../provider/GeocentricToGeographic.java           |  8 +--
 .../referencing/provider/GeodeticOperation.java    |  8 +--
 .../referencing/provider/Geographic2Dto3D.java     |  8 +++
 .../referencing/provider/Geographic3Dto2D.java     | 22 ++++++++
 .../provider/GeographicToGeocentric.java           |  8 +--
 .../org/apache/sis/referencing/Properties.java     | 37 ++++++++-----
 .../operation/CoordinateOperationRegistry.java     | 20 ++++++--
 .../operation/InverseOperationMethod.java          | 60 ++++++++++++----------
 .../referencing/operation/SubOperationInfo.java    |  5 +-
 13 files changed, 133 insertions(+), 74 deletions(-)

diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/SignReversalComment.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/SignReversalComment.java
index 8f68a91..750b7be 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/SignReversalComment.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/SignReversalComment.java
@@ -32,7 +32,7 @@ import org.apache.sis.util.iso.AbstractInternationalString;
  * @author  Martin Desruisseaux (Geomatys)
  * @version 0.7
  *
- * @see org.apache.sis.internal.referencing.provider.AbstractProvider#isInvertible()
+ * @see org.apache.sis.internal.referencing.provider.AbstractProvider#inverse()
  *
  * @since 0.7
  * @module
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java
index 6678ee3..86a3889 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java
@@ -239,8 +239,13 @@ public abstract class AbstractProvider extends DefaultOperationMethod implements
     }
 
     /**
-     * Returns {@code true} if the inverse of this operation method is the same operation method with some parameter
-     * values changed (typically with sign inverted). The default implementation returns {@code false}.
+     * Returns the operation method which is the inverse of this method.
+     * <ul>
+     *   <li>If {@code null}, no inverse method is easily available. This is the default.</li>
+     *   <li>If {@code this}, the inverse of this operation method is the same operation method
+     *       with some parameter values changed (typically with sign inverted).</li>
+     *   <li>If another method, it should take the same parameter values.</li>
+     * </ul>
      *
      * <p>This is a SIS-specific information which may be changed in any future SIS version.
      * Current implementation provides this information in a "all or nothing" way: either all parameter values
@@ -257,12 +262,12 @@ public abstract class AbstractProvider extends DefaultOperationMethod implements
      *       does not differentiate the map projection methods from <em>inverse</em> map projection methods.</li>
      * </ul>
      *
-     * @return {@code true} if the inverse of this operation method can be described by the same operation method.
+     * @return the inverse of this operation method (possibly {@code this}), or {@code null} if none.
      *
      * @see org.apache.sis.internal.referencing.SignReversalComment
      */
-    public boolean isInvertible() {
-        return false;
+    public AbstractProvider inverse() {
+        return null;
     }
 
     /**
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Affine.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Affine.java
index 6bd499a..348b637 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Affine.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Affine.java
@@ -57,7 +57,7 @@ import org.apache.sis.referencing.operation.transform.MathTransforms;
  * </table>
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.8
+ * @version 1.1
  * @since   0.5
  * @module
  */
@@ -180,11 +180,11 @@ public final class Affine extends AbstractProvider {
     /**
      * The inverse of this operation can be described by the same operation with different parameter values.
      *
-     * @return {@code true} for all {@code Affine}.
+     * @return {@code this} for all {@code Affine}.
      */
     @Override
-    public final boolean isInvertible() {
-        return true;
+    public AbstractProvider inverse() {
+        return this;
     }
 
     /**
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java
index 6596f2e..862570b 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java
@@ -219,11 +219,11 @@ public class FranceGeocentricInterpolation extends GeodeticOperation {
     /**
      * The inverse of {@code FranceGeocentricInterpolation} is a different operation.
      *
-     * @return {@code false}.
+     * @return {@code null}.
      */
     @Override
-    public final boolean isInvertible() {
-        return false;
+    public AbstractProvider inverse() {
+        return null;
     }
 
     /**
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricToGeographic.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricToGeographic.java
index 37cf1d2..dcb90c1 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricToGeographic.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricToGeographic.java
@@ -32,7 +32,7 @@ import org.apache.sis.parameter.Parameters;
  * This provider creates transforms from geocentric to geographic coordinate reference systems.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.8
+ * @version 1.1
  *
  * @see GeographicToGeocentric
  *
@@ -104,11 +104,11 @@ public final class GeocentricToGeographic extends GeodeticOperation {
     /**
      * Specifies that the inverse of this operation is a different kind of operation.
      *
-     * @return {@code false}.
+     * @return {@code null}.
      */
     @Override
-    public boolean isInvertible() {
-        return false;
+    public AbstractProvider inverse() {
+        return null;
     }
 
     /**
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeodeticOperation.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeodeticOperation.java
index a6641d3..9367b3f 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeodeticOperation.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeodeticOperation.java
@@ -31,7 +31,7 @@ import org.opengis.referencing.operation.Transformation;
  * variants are specific to Apache SIS and can be fetched only by a call to {@link #redimension(int, int)}.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.7
+ * @version 1.1
  * @since   0.7
  * @module
  */
@@ -127,10 +127,10 @@ abstract class GeodeticOperation extends AbstractProvider {
     /**
      * The inverse of {@code GeodeticOperation} is usually the same operation with parameter signs inverted.
      *
-     * @return {@code true} for most {@code GeodeticOperation} instances.
+     * @return {@code this} for most {@code GeodeticOperation} instances.
      */
     @Override
-    public boolean isInvertible() {
-        return true;
+    public AbstractProvider inverse() {
+        return this;
     }
 }
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Geographic2Dto3D.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Geographic2Dto3D.java
index 9083d76..0d01f25 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Geographic2Dto3D.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Geographic2Dto3D.java
@@ -100,6 +100,14 @@ public final class Geographic2Dto3D extends GeographicRedimension {
     }
 
     /**
+     * Returns the inverse of this operation.
+     */
+    @Override
+    public AbstractProvider inverse() {
+        return Geographic3Dto2D.getMethod(Geographic3Dto2D.PARAMETERS);
+    }
+
+    /**
      * Returns the transform.
      *
      * @param  factory  the factory for creating affine transforms.
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Geographic3Dto2D.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Geographic3Dto2D.java
index 880641f..71e8afc 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Geographic3Dto2D.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Geographic3Dto2D.java
@@ -83,6 +83,28 @@ public final class Geographic3Dto2D extends GeographicRedimension {
     }
 
     /**
+     * Returns the inverse of this operation.
+     */
+    @Override
+    public AbstractProvider inverse() {
+        return getMethod(Geographic2Dto3D.PARAMETERS);
+    }
+
+    /**
+     * Workaround while waiting for JDK 9. After migration to Jigsaw, {@link #inverse()}
+     * should return directly the unique provider instance.
+     */
+    static AbstractProvider getMethod(final ParameterDescriptorGroup desc) {
+        try {
+            return (AbstractProvider) org.apache.sis.internal.system.DefaultFactories.forBuildin(MathTransformFactory.class,
+                    org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory.class)
+                    .getOperationMethod(desc.getName().getCode());
+        } catch (FactoryException e) {
+            throw new org.apache.sis.util.collection.BackingStoreException(e);
+        }
+    }
+
+    /**
      * Returns the transform.
      *
      * <div class="note"><b>Implementation note:</b>
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicToGeocentric.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicToGeocentric.java
index 97c283e..c9b9bcc 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicToGeocentric.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicToGeocentric.java
@@ -41,7 +41,7 @@ import org.apache.sis.internal.util.Constants;
  * This provider creates transforms from geographic to geocentric coordinate reference systems.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.8
+ * @version 1.1
  *
  * @see GeocentricToGeographic
  *
@@ -165,11 +165,11 @@ public final class GeographicToGeocentric extends GeodeticOperation {
     /**
      * Specifies that the inverse of this operation is a different kind of operation.
      *
-     * @return {@code false}.
+     * @return {@code null}.
      */
     @Override
-    public boolean isInvertible() {
-        return false;
+    public AbstractProvider inverse() {
+        return null;
     }
 
     /**
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java
index 8a4b0af..6ad7f91 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java
@@ -27,8 +27,10 @@ import org.opengis.referencing.ReferenceSystem;
 import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.referencing.operation.OperationMethod;
+import org.opengis.referencing.operation.SingleOperation;
 import org.opengis.metadata.quality.PositionalAccuracy;
 import org.apache.sis.internal.util.AbstractMap;
+import org.apache.sis.internal.referencing.CoordinateOperations;
 import org.apache.sis.util.Deprecable;
 
 
@@ -40,8 +42,8 @@ import org.apache.sis.util.Deprecable;
  * <p>This map is read-only. Whether it is serializable, immutable or thread-safe depends if the
  * underlying {@code IdentifiedObject} instance is itself serializable, immutable or thread-safe.</p>
  *
- * @author  Martin Desruisseaux (IRD)
- * @version 0.7
+ * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @version 1.1
  * @since   0.4
  * @module
  */
@@ -49,23 +51,24 @@ final class Properties extends AbstractMap<String,Object> implements Serializabl
     /**
      * For cross-version compatibility.
      */
-    private static final long serialVersionUID = 6391635771714311314L;
+    private static final long serialVersionUID = 836068852472172370L;
 
     /**
      * The keys to search for. The index of each element in this array must matches the index searched by
      * {@link #getAt(int)}. In other words, this array performs the reverse mapping of {@link #INDICES}.
      */
     private static final String[] KEYS = {
-        /*[0]*/ IdentifiedObject        .NAME_KEY,
-        /*[1]*/ IdentifiedObject        .IDENTIFIERS_KEY,
-        /*[2]*/ IdentifiedObject        .ALIAS_KEY,
-        /*[3]*/ IdentifiedObject        .REMARKS_KEY,
-        /*[4]*/ CoordinateOperation     .SCOPE_KEY,                     // same in Datum and ReferenceSystem
-        /*[5]*/ CoordinateOperation     .DOMAIN_OF_VALIDITY_KEY,        // same in Datum and ReferenceSystem
-        /*[6]*/ CoordinateOperation     .OPERATION_VERSION_KEY,
-        /*[7]*/ CoordinateOperation     .COORDINATE_OPERATION_ACCURACY_KEY,
-        /*[8]*/ OperationMethod         .FORMULA_KEY,
-        /*[9]*/ AbstractIdentifiedObject.DEPRECATED_KEY
+        /*[ 0]*/ IdentifiedObject        .NAME_KEY,
+        /*[ 1]*/ IdentifiedObject        .IDENTIFIERS_KEY,
+        /*[ 2]*/ IdentifiedObject        .ALIAS_KEY,
+        /*[ 3]*/ IdentifiedObject        .REMARKS_KEY,
+        /*[ 4]*/ CoordinateOperation     .SCOPE_KEY,                    // same in Datum and ReferenceSystem
+        /*[ 5]*/ CoordinateOperation     .DOMAIN_OF_VALIDITY_KEY,       // same in Datum and ReferenceSystem
+        /*[ 6]*/ CoordinateOperation     .OPERATION_VERSION_KEY,
+        /*[ 7]*/ CoordinateOperation     .COORDINATE_OPERATION_ACCURACY_KEY,
+        /*[ 8]*/ OperationMethod         .FORMULA_KEY,
+        /*[ 9]*/ CoordinateOperations    .PARAMETERS_KEY,
+        /*[10]*/ AbstractIdentifiedObject.DEPRECATED_KEY
 
         /*
          * The current implementation does not look for minimum and maximum values in ParameterDescriptor
@@ -191,7 +194,13 @@ final class Properties extends AbstractMap<String,Object> implements Serializabl
                     }
                     break;
                 }
-                case 9: {   // DEPRECATED_KEY
+                case 9: {   // PARAMETERS_KEY
+                    if (object instanceof SingleOperation) {
+                        return ((SingleOperation) object).getParameterValues();
+                    }
+                    break;
+                }
+                case 10: {  // DEPRECATED_KEY
                     if (object instanceof Deprecable) {
                         return ((Deprecable) object).isDeprecated();
                     }
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
index 7827710..5a0aadd 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
@@ -234,8 +234,7 @@ class CoordinateOperationRegistry {
             } else try {
                 codeFinder = IdentifiedObjects.newFinder(Citations.toCodeSpace(registry.getAuthority()));
             } catch (NoSuchAuthorityFactoryException e) {
-                Logging.recoverableException(Logging.getLogger(Loggers.COORDINATE_OPERATION),
-                        CoordinateOperationRegistry.class, "<init>", e);
+                recoverableException("<init>", e);
             }
             if (codeFinder != null) {
                 codeFinder.setIgnoringAxes(true);
@@ -315,7 +314,7 @@ class CoordinateOperationRegistry {
     {
         CoordinateReferenceSystem source = sourceCRS;
         CoordinateReferenceSystem target = targetCRS;
-        for (int combine=0; ;combine++) {
+        for (int combine=0; ; combine++) {
             /*
              * First, try directly the provided (sourceCRS, targetCRS) pair. If that pair does not work,
              * try to use different combinations of user-provided CRS and two-dimensional components of
@@ -575,7 +574,7 @@ class CoordinateOperationRegistry {
         final CoordinateReferenceSystem sourceCRS = op.getSourceCRS();
         final CoordinateReferenceSystem targetCRS = op.getTargetCRS();
         final MathTransform transform = op.getMathTransform().inverse();
-        final OperationMethod method = InverseOperationMethod.create(op.getMethod());
+        final OperationMethod method = InverseOperationMethod.create(op.getMethod(), factorySIS);
         final Map<String,Object> properties = properties(INVERSE_OPERATION);
         InverseOperationMethod.properties(op, properties);
         /*
@@ -1195,4 +1194,17 @@ class CoordinateOperationRegistry {
         }
         Logging.log(CoordinateOperationFinder.class, "createOperations", record);
     }
+
+    /**
+     * Logs an ignorable exception. This method pretends that the logging come from
+     * {@link CoordinateOperationFinder} since this is the public API which use this
+     * {@code CoordinateOperationRegistry} class.
+     *
+     * @param  method     the method name where the error occurred.
+     * @param  exception  the exception which occurred, or {@code null} if a {@code record} is specified instead.
+     */
+    static void recoverableException(final String method, final Exception exception) {
+        Logging.recoverableException(Logging.getLogger(Loggers.COORDINATE_OPERATION),
+                CoordinateOperationFinder.class, method, exception);
+    }
 }
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/InverseOperationMethod.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/InverseOperationMethod.java
index fe59da1..8f937b6 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/InverseOperationMethod.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/InverseOperationMethod.java
@@ -24,6 +24,8 @@ import javax.measure.Unit;
 import org.opengis.metadata.Identifier;
 import org.opengis.metadata.quality.PositionalAccuracy;
 import org.opengis.util.InternationalString;
+import org.opengis.util.FactoryException;
+import org.opengis.util.NoSuchIdentifierException;
 import org.opengis.parameter.ParameterValue;
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.parameter.ParameterDescriptor;
@@ -44,7 +46,7 @@ import org.apache.sis.util.Deprecable;
  * for the inverse, or when the inverse operation can not be represented by inverting the sign of parameters.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @version 1.1
  * @since   0.7
  * @module
  */
@@ -69,41 +71,45 @@ final class InverseOperationMethod extends DefaultOperationMethod {
     }
 
     /**
-     * Returns {@code true} if the given method flags itself as invertible.
-     */
-    private static boolean isInvertible(final OperationMethod method) {
-        return method instanceof AbstractProvider && ((AbstractProvider) method).isInvertible();
-    }
-
-    /**
      * Returns or create the inverse of the given operation method. If the same operation method can be used
      * for the inverse operation either with the exact same parameter values or with the sign of some values
      * reversed, then the given method is returned as-is. Otherwise a synthetic method is created.
      */
-    static OperationMethod create(final OperationMethod method) {
+    static OperationMethod create(OperationMethod method, final DefaultCoordinateOperationFactory factorySIS)
+            throws FactoryException
+    {
         if (method instanceof InverseOperationMethod) {
             return ((InverseOperationMethod) method).inverse;
         }
-        if (!isInvertible(method)) {
-            boolean useSameParameters = false;
-            for (final GeneralParameterDescriptor descriptor : method.getParameters().descriptors()) {
-                useSameParameters = (descriptor.getRemarks() instanceof SignReversalComment);
-                if (!useSameParameters) break;
-            }
-            if (!useSameParameters) {
-                Identifier name = method.getName();
-                name = new ImmutableIdentifier(null, null, "Inverse of " + name.getCode());
-                final Map<String,Object> properties = new HashMap<>(6);
-                properties.put(NAME_KEY,    name);
-                properties.put(FORMULA_KEY, method.getFormula());
-                properties.put(REMARKS_KEY, method.getRemarks());
-                if (method instanceof Deprecable) {
-                    properties.put(DEPRECATED_KEY, ((Deprecable) method).isDeprecated());
-                }
-                return new InverseOperationMethod(properties, method);
+        if (!(method instanceof AbstractProvider)) try {
+            method = factorySIS.getOperationMethod(method.getName().getCode());
+        } catch (NoSuchIdentifierException e) {
+            CoordinateOperationRegistry.recoverableException("inverse", e);
+        }
+        if (method instanceof AbstractProvider) {
+            final AbstractProvider inverse = ((AbstractProvider) method).inverse();
+            if (inverse != null) {
+                return inverse;
             }
         }
-        return method;
+        boolean useSameParameters = false;
+        for (final GeneralParameterDescriptor descriptor : method.getParameters().descriptors()) {
+            useSameParameters = (descriptor.getRemarks() instanceof SignReversalComment);
+            if (!useSameParameters) break;
+        }
+        if (useSameParameters) {
+            return method;
+        }
+        Identifier name = method.getName();
+        name = new ImmutableIdentifier(null, null, "Inverse of " + name.getCode());
+        final Map<String,Object> properties = new HashMap<>(6);
+        properties.put(NAME_KEY,    name);
+        properties.put(FORMULA_KEY, method.getFormula());
+        properties.put(REMARKS_KEY, method.getRemarks());
+        if (method instanceof Deprecable) {
+            properties.put(DEPRECATED_KEY, ((Deprecable) method).isDeprecated());
+        }
+        return new InverseOperationMethod(properties, method);
     }
 
     /**
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java
index 0b80fd8..8318030 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java
@@ -22,8 +22,6 @@ import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.referencing.operation.OperationNotFoundException;
 import org.opengis.referencing.operation.TransformException;
 import org.opengis.util.FactoryException;
-import org.apache.sis.util.logging.Logging;
-import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.referencing.operation.matrix.Matrices;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 
@@ -215,8 +213,7 @@ next:   for (int targetComponentIndex = 0; targetComponentIndex < infos.length;
                                             operation, null, sourceStartAtDimension, sourceEndAtDimension);
 
                                     if (failure != null) {
-                                        Logging.recoverableException(Logging.getLogger(Loggers.COORDINATE_OPERATION),
-                                                CoordinateOperationFinder.class, "decompose", failure);
+                                        CoordinateOperationRegistry.recoverableException("decompose", failure);
                                     }
                                     continue next;
                                 }


[sis] 01/03: Fix a NullPointerException when using directly a `new Formatter()` instance.

Posted by de...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git

commit e213eb51581ee8a3bd99eed8d58b0bc3aa88b653
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Fri May 29 11:37:07 2020 +0200

    Fix a NullPointerException when using directly a `new Formatter()` instance.
---
 core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Formatter.java | 1 +
 1 file changed, 1 insertion(+)

diff --git a/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Formatter.java b/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Formatter.java
index 3657a23..5f28fbd 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Formatter.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/Formatter.java
@@ -367,6 +367,7 @@ public class Formatter implements Localized {
         this.convention       = convention;
         this.authority        = convention.getNameAuthority();
         this.symbols          = symbols.immutable();
+        this.transliterator   = (convention == Convention.INTERNAL) ? Transliterator.IDENTITY : Transliterator.DEFAULT;
         this.separatorNewLine = this.symbols.separatorNewLine();
         this.indentation      = (byte) indentation;
         this.numberFormat     = symbols.createNumberFormat();