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


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new 1f4f8a9  Reduce the number of CRS created during search of coordinate 
operations. We address the issue by adding 
IdentifiedObjectFinder.Domain.EXHAUSTIVE_VALID_DATASET enumeration value, whih 
also appears to simplify code as a side-effect.
1f4f8a9 is described below

commit 1f4f8a9deafda2625e3dc87aab0b052dcc9b17da
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Thu Feb 10 14:59:49 2022 +0100

    Reduce the number of CRS created during search of coordinate operations.
    We address the issue by adding 
IdentifiedObjectFinder.Domain.EXHAUSTIVE_VALID_DATASET
    enumeration value, whih also appears to simplify code as a side-effect.
    
    https://issues.apache.org/jira/browse/SIS-535
---
 .../referencing/factory/AuthorityFactoryProxy.java |  16 +--
 .../factory/ConcurrentAuthorityFactory.java        |  33 +++--
 .../factory/IdentifiedObjectFinder.java            |  63 +++++-----
 .../factory/MultiAuthoritiesFactory.java           |   4 +-
 .../operation/CoordinateOperationRegistry.java     | 134 +++++++++------------
 5 files changed, 115 insertions(+), 135 deletions(-)

diff --git 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java
 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java
index b3cf48a..5d7feaf 100644
--- 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java
+++ 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java
@@ -58,7 +58,7 @@ import org.apache.sis.internal.util.Strings;
  * }</div>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 0.7
  * @since   0.7
  * @module
  */
@@ -91,20 +91,6 @@ abstract class AuthorityFactoryProxy<T> {
     }
 
     /**
-     * Returns whether the objects created by this proxy may have axes.
-     */
-    final boolean hasAxes() {
-        final Class<? extends IdentifiedObject> base;
-        switch (factoryType) {
-            default: return false;
-            case AuthorityFactoryIdentifier.CRS: return true;
-            case AuthorityFactoryIdentifier.CS:  base = 
CoordinateSystem.class; break;
-            case AuthorityFactoryIdentifier.ANY: base = 
IdentifiedObject.class; break;
-        }
-        return base.isAssignableFrom(type);
-    }
-
-    /**
      * Casts the given factory into a datum authority factory, or throws a 
{@code FactoryException}
      * if the given factory is not of the expected type.
      */
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 328ea7c..cbc8d9d 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
@@ -1896,7 +1896,7 @@ public abstract class ConcurrentAuthorityFactory<DAO 
extends GeodeticAuthorityFa
                 final FindEntry entry = findPool.get(object);
                 if (entry != null) {
                     // `finder` may be null if this method is invoked directly 
by this Finder.
-                    return entry.get(finder != null ? finder : this);
+                    return entry.get(finder != null ? finder : this, object == 
searching);
                 }
             }
             return null;
@@ -1917,7 +1917,7 @@ public abstract class ConcurrentAuthorityFactory<DAO 
extends GeodeticAuthorityFa
                     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.
-                result = entry.set(finder, result, object != searching);
+                result = entry.set(finder, result, object == searching);
             }
             return result;
         }
@@ -1967,7 +1967,7 @@ public abstract class ConcurrentAuthorityFactory<DAO 
extends GeodeticAuthorityFa
          * Hard-coded for efficiency. Value is verified using reflection by 
the test
          * {@code ConcurrentAuthorityFactoryTest.verifyDomainCount()}.
          */
-        private static final int DOMAIN_COUNT = 3;
+        private static final int DOMAIN_COUNT = 4;
 
         /** Result of the search with or without ignoring axes. */
         private final Set<IdentifiedObject>[] caches;
@@ -1989,17 +1989,30 @@ public abstract class ConcurrentAuthorityFactory<DAO 
extends GeodeticAuthorityFa
         }
 
         /** Returns the cached instance, or {@code null} if none. */
-        Set<IdentifiedObject> get(final IdentifiedObjectFinder finder) {
-            return caches[index(finder)];
+        Set<IdentifiedObject> get(final IdentifiedObjectFinder finder, final 
boolean explicit) {
+            final int i = index(finder);
+            if (explicit) {
+                dependencyFlags &= ~(1 << i);     // Clear the bit telling 
that this cache was only for a dependency.
+            }
+            return caches[i];
         }
 
         /** Caches an instance, or return previous instance if computed 
concurrently. */
-        Set<IdentifiedObject> set(final IdentifiedObjectFinder finder, final 
Set<IdentifiedObject> result, final boolean dependency) {
+        Set<IdentifiedObject> set(final IdentifiedObjectFinder finder, 
Set<IdentifiedObject> result, final boolean explicit) {
             final int i = index(finder);
-            if (dependency) dependencyFlags |= (1 << i);
-            Set<IdentifiedObject> existing = caches[i];
-            if (existing != null) return existing;
-            else return caches[i] = result;
+            final Set<IdentifiedObject> existing = caches[i];
+            if (existing != null) {
+                if (explicit) dependencyFlags &= ~(1 << i);
+                return existing;
+            }
+            if (!explicit) dependencyFlags |= (1 << i);
+            for (Set<IdentifiedObject> other : caches) {
+                if (result.equals(other)) {
+                    result = other;             // Share existing instance.
+                    break;
+                }
+            }
+            return caches[i] = result;
         }
 
         /** Forgets the sets that were not explicitly requested. */
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 af7af50..cac325a 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
@@ -72,8 +72,11 @@ public class IdentifiedObjectFinder {
      * The domain of the search (for example whether to include deprecated 
objects in the search).
      *
      * @author  Martin Desruisseaux (Geomatys)
-     * @version 0.7
-     * @since   0.7
+     * @version 1.2
+     *
+     * @see #getSearchDomain()
+     *
+     * @since 0.7
      * @module
      */
     public enum Domain {
@@ -106,10 +109,34 @@ public class IdentifiedObjectFinder {
          * {@link #DECLARATION} will give no result. The {@code find(…)} 
method will then scan the dataset for
          * geographic CRS using equivalent datum and coordinate system. This 
may be a costly operation.
          * </div>
+         *
+         * This is the default domain of {@link IdentifiedObjectFinder}.
          */
         VALID_DATASET,
 
         /**
+         * Lookup unconditionally based on all valid (non-deprecated) objects 
known to the factory.
+         * This is similar to {@link #VALID_DATASET} except that the fast 
{@link #DECLARATION} lookup is skipped.
+         * Instead, a potentially costly scan of the database is 
unconditionally performed
+         * (unless the result is already in the cache).
+         *
+         * <p>This domain can be useful when the search {@linkplain 
#isIgnoringAxes() ignores axis order}.
+         * If axis order is <em>not</em> ignored, then this domain usually has 
no advantage over {@link #VALID_DATASET}
+         * (unless the geodetic dataset contains duplicated entries) to 
justify the performance cost.</p>
+         *
+         * <div class="note"><b>Use case:</b>
+         * the EPSG database sometime contains two definitions for almost 
identical geographic CRS,
+         * one with (<var>latitude</var>, <var>longitude</var>) axis order and 
one with reverse order
+         * (e.g. EPSG::4171 versus EPSG::7084). It is sometime useful to know 
all variants of a given CRS.
+         * The {@link #VALID_DATASET} domain may not give a complete set 
because the "fast lookup by identifier"
+         * optimization may prevent {@link IdentifiedObjectFinder} to scan the 
rest of the database.
+         * This {@code EXHAUSTIVE_VALID_DATASET} domain forces such scan.</div>
+         *
+         * @since 1.2
+         */
+        EXHAUSTIVE_VALID_DATASET,
+
+        /**
          * Lookup based on all objects (both valid and deprecated) known to 
the factory.
          * This is the same search than {@link #VALID_DATASET} except that 
deprecated objects
          * are included in the search.
@@ -156,22 +183,9 @@ public class IdentifiedObjectFinder {
     private boolean ignoreAxes;
 
     /**
-     * {@code true} if the search should ignore names, aliases and 
identifiers. This is set to {@code true}
-     * only when this finder is wrapped by a {@link MultiAuthoritiesFactory} 
finder, which performs it own
-     * search based on identifiers.
-     */
-    boolean ignoreIdentifiers;
-
-    /**
-     * {@code true} if the result can be restricted to a singleton.
-     * This is set by {@link #findSingleton(IdentifiedObject)} only.
-     */
-    private boolean wantSingleton;
-
-    /**
      * Creates a finder using the specified factory.
      *
-     * <div class="note"><b>Design note:</b>
+     * <div class="note"><b>API note:</b>
      * this constructor is protected because instances of this class should 
not be created directly.
      * Use {@link GeodeticAuthorityFactory#newIdentifiedObjectFinder()} 
instead.</div>
      *
@@ -306,24 +320,15 @@ public class IdentifiedObjectFinder {
         ArgumentChecks.ensureNonNull("object", object);
         Set<IdentifiedObject> result = getFromCache(object);
         if (result == null) {
-            final boolean previousIgnoreAxes = ignoreAxes;
             final AuthorityFactoryProxy<?> previousProxy = proxy;
             proxy = AuthorityFactoryProxy.getInstance(object.getClass());
             try {
-                /*
-                 * If user wants to ignore axes, we need to return all 
matches. We can not use the identifier
-                 * because it would reduce the set to a single element. Having 
all elements is necessary when
-                 * `CoordinateOperationRegistry` searches for a coordinate 
operation between a pair of CRS.
-                 * The only exceptions to this rule are when this method is 
invoked from `findSingleton(…)`,
-                 * or when axes are irrelevant to the object to search.
-                 */
-                if (!ignoreIdentifiers && (!previousIgnoreAxes || 
wantSingleton || !proxy.hasAxes())) {
+                if (domain != Domain.EXHAUSTIVE_VALID_DATASET) {
                     /*
                      * First check if one of the identifiers can be used to 
find directly an identified object.
                      * Verify that the object that we found is actually equal 
to given one; we do not blindly
                      * trust the identifiers in the user object.
                      */
-                    ignoreAxes = false;             // It makes a difference 
only if `wantSingleton = true`.
                     IdentifiedObject candidate = createFromIdentifiers(object);
                     if (candidate == null) {
                         /*
@@ -349,8 +354,7 @@ public class IdentifiedObjectFinder {
                     }
                 }
             } finally {
-                proxy      = previousProxy;
-                ignoreAxes = previousIgnoreAxes;
+                proxy = previousProxy;
             }
             result = cache(object, result);     // Costly operations (even if 
the result is empty) are worth to cache.
         }
@@ -382,7 +386,6 @@ public class IdentifiedObjectFinder {
         IdentifiedObject result = null;
         boolean sameAxisOrder = false;
         boolean ambiguous = false;
-        wantSingleton = true;
         try {
             for (final IdentifiedObject candidate : find(object)) {
                 final boolean equalsIncludingAxes = !ignoreAxes || 
Utilities.deepEquals(candidate, object, COMPARISON_MODE);
@@ -397,8 +400,6 @@ public class IdentifiedObjectFinder {
             }
         } catch (BackingStoreException e) {
             throw e.unwrapOrRethrow(FactoryException.class);
-        } finally {
-            wantSingleton = false;
         }
         return (sameAxisOrder || !ambiguous) ? result : null;
     }
diff --git 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
index 33a1d0d..77f579a 100644
--- 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
+++ 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
@@ -146,7 +146,7 @@ import org.apache.sis.util.collection.BackingStoreException;
  * do not need to be thread-safe. See constructor Javadoc for more information.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.8
+ * @version 1.2
  *
  * @see org.apache.sis.referencing.CRS#getAuthorityFactory(String)
  *
@@ -1807,7 +1807,7 @@ public class MultiAuthoritiesFactory extends 
GeodeticAuthorityFactory implements
                     if (candidate instanceof GeodeticAuthorityFactory && 
unique.put(candidate, Boolean.TRUE) == null) {
                         IdentifiedObjectFinder finder = 
((GeodeticAuthorityFactory) candidate).newIdentifiedObjectFinder();
                         if (finder != null) {   // Should never be null 
according method contract, but we are paranoiac.
-                            finder.ignoreIdentifiers = true;
+                            
finder.setSearchDomain(Domain.EXHAUSTIVE_VALID_DATASET);
                             finder.setWrapper(this);
                             list.add(finder);
                         }
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 72eb053..1696af5 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
@@ -44,6 +44,7 @@ import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.crs.GeneralDerivedCRS;
 import org.opengis.referencing.crs.GeodeticCRS;
 import org.opengis.referencing.crs.SingleCRS;
+import org.opengis.referencing.crs.CompoundCRS;
 import org.opengis.referencing.cs.EllipsoidalCS;
 import org.opengis.referencing.operation.*;
 
@@ -170,7 +171,7 @@ class CoordinateOperationRegistry {
      * operation, even if an equivalent definition was provided by another 
authority.</div>
      *
      * @see #authorityCodes
-     * @see #findCode(CoordinateReferenceSystem, boolean)
+     * @see #findCode(CoordinateReferenceSystem)
      */
     private final IdentifiedObjectFinder codeFinder;
 
@@ -214,7 +215,7 @@ class CoordinateOperationRegistry {
      * This field is set to {@code true} when the caller is interested only in 
the "best" operation
      * instead of all of possibilities.
      *
-     * @see #search(CoordinateReferenceSystem, boolean, 
CoordinateReferenceSystem, boolean)
+     * @see #search(CoordinateReferenceSystem, CoordinateReferenceSystem)
      */
     boolean stopAtFirst;
 
@@ -227,7 +228,7 @@ class CoordinateOperationRegistry {
     private Predicate<CoordinateOperation> filter;
 
     /**
-     * Authority codes found for CRS. This is a cache for {@link 
#findCode(CoordinateReferenceSystem, boolean)}.
+     * Authority codes found for CRS. This is a cache for {@link 
#findCode(CoordinateReferenceSystem)}.
      * This map may be non-empty only if {@link #codeFinder} is non-null.
      *
      * <div class="note"><b>Design note:</b>
@@ -237,20 +238,11 @@ class CoordinateOperationRegistry {
      * provide such cache, and the values cached here are the result of a 
little bit more work.</div>
      *
      * @see #codeFinder
-     * @see #findCode(CoordinateReferenceSystem, boolean)
+     * @see #findCode(CoordinateReferenceSystem)
      */
     private final Map<CoordinateReferenceSystem, List<String>> authorityCodes;
 
     /**
-     * The authority codes of source and target CRSs examined during the last 
call to {@code search(…)}.
-     * This is used for determining if a new call will make any difference 
compared to previous call.
-     * This is usually a reference to a value in the {@link #authorityCodes} 
map.
-     *
-     * @see #search(CoordinateReferenceSystem, boolean, 
CoordinateReferenceSystem, boolean)
-     */
-    private List<String> lastSourceCodes, lastTargetCodes;
-
-    /**
      * Creates a new instance for the given factory and context.
      *
      * @param  registry  the factory to use for creating operations as defined 
by authority.
@@ -313,41 +305,34 @@ class CoordinateOperationRegistry {
      * This method may return codes even if the axis order does not match;
      * it will be caller's responsibility to make necessary adjustments.
      *
-     * @param  crs   the CRS for which to search authority codes.
-     * @param  full  whether to perform the most expensive search.
+     * @param  crs  the CRS for which to search authority codes.
      * @return authority codes for the given CRS, or an empty list if none.
      *         <b>Do not modify</b> since this list may be cached.
      */
-    private List<String> findCode(final CoordinateReferenceSystem crs, final 
boolean full) throws FactoryException {
+    private List<String> findCode(final CoordinateReferenceSystem crs) throws 
FactoryException {
         List<String> codes = authorityCodes.get(crs);
         if (codes == null) {
             if (codeFinder == null) {
                 return Collections.emptyList();
             }
             codes = new ArrayList<>();
-            codeFinder.setIgnoringAxes(full);
-            codeFinder.setSearchDomain(full ? 
IdentifiedObjectFinder.Domain.VALID_DATASET
-                                            : 
IdentifiedObjectFinder.Domain.DECLARATION);
+            codeFinder.setIgnoringAxes(true);
+            codeFinder.setSearchDomain(isEasySearch(crs)
+                    ? IdentifiedObjectFinder.Domain.EXHAUSTIVE_VALID_DATASET
+                    : IdentifiedObjectFinder.Domain.VALID_DATASET);
             final Citation authority = registry.getAuthority();
             for (final IdentifiedObject candidate : codeFinder.find(crs)) {
                 final Identifier identifier = 
IdentifiedObjects.getIdentifier(candidate, authority);
                 if (identifier != null) {
                     final String code = identifier.getCode();
-                    if (full && Utilities.deepEquals(candidate, crs, 
ComparisonMode.APPROXIMATE)) {
+                    if (Utilities.deepEquals(candidate, crs, 
ComparisonMode.APPROXIMATE)) {
                         codes.add(0, code);     // If axis order matches, give 
precedence to that CRS.
                     } else {
                         codes.add(code);
                     }
                 }
             }
-            /*
-             * Cache only the result of full search. The result of non-full 
search is fast enough that it
-             * does not need to be cached. Note that it may cause the next 
call to `findCode(crs, false)`
-             * to return the full search even if `full` argument was false; 
this is okay.
-             */
-            if (full) {
-                authorityCodes.put(crs, codes);
-            }
+            authorityCodes.put(crs, codes);
         }
         return codes;
     }
@@ -429,7 +414,17 @@ class CoordinateOperationRegistry {
      * because they may be the only ones available.</p>
      */
     private static boolean isEasySearch(final CoordinateReferenceSystem crs) {
-        return (crs instanceof SingleCRS) && !(crs instanceof 
GeneralDerivedCRS);
+        if (crs instanceof GeneralDerivedCRS) {
+            return false;
+        }
+        if (crs instanceof CompoundCRS) {
+            for (CoordinateReferenceSystem c : ((CompoundCRS) 
crs).getComponents()) {
+                if (!isEasySearch(c)) {
+                    return false;
+                }
+            }
+        }
+        return true;
     }
 
     /**
@@ -483,45 +478,37 @@ class CoordinateOperationRegistry {
                 target = target2D;
             }
             /*
-             * The search for coordinate operations can be costly if we 
consider the full set of CRS
-             * candidates that `IdentifiedObjectFinder` can find. In an 
attempt to reduce the cost,
-             * we will initially allow full search only for geographic CRS or 
other CRS that are easy
-             * to find (using their properties, not using their authority 
code) in the EPSG database.
-             * Only if we can not find easily the CRS, we will allow extensive 
search for all CRSs.
+             * Search for coordinate operations between the pair of CRS 
components that we just found.
+             * We may need to force a search of all CRS variants (equivalent 
CRS except for axis order)
+             * for resolving the case where the geodetic database contains 
such pairs of equivalent CRS
+             * (e.g. EPSG::4171 versus EPSG::7084). For reducing the cost, we 
will force full scan only
+             * for CRS for which `isEasySearch(…)` returns `true`.
              */
             if (source != null && target != null) try {
-                boolean allSources = isEasySearch(source);
-                boolean allTargets = isEasySearch(target);
-                boolean done;
-                do {
-                    final List<CoordinateOperation> operations = 
search(source, allSources, target, allTargets);
-                    if (operations != null) {
-                        /*
-                         * Found at least one operation. If we had to extract 
the horizontal part of some 3D CRS, then
-                         * we need to modify the coordinate operation in order 
to match the new number of dimensions.
-                         * Some operations may be lost if we do not know how 
to propagate the vertical CRS.
-                         * If at least one operation remains, we are done.
-                         */
-                        if (decompose.source | decompose.target) {
-                            for (int i=operations.size(); --i >= 0;) {
-                                CoordinateOperation operation = 
operations.get(i);
-                                operation = propagateVertical(sourceCRS, 
targetCRS, operation, decompose);
-                                if (operation != null) {
-                                    operation = complete(operation, sourceCRS, 
targetCRS);
-                                    operations.set(i, operation);
-                                } else {
-                                    operations.remove(i);
-                                }
+                final List<CoordinateOperation> operations = search(source, 
target);
+                if (operations != null) {
+                    /*
+                     * Found at least one operation. If we had to extract the 
horizontal part of some 3D CRS, then
+                     * we need to modify the coordinate operation in order to 
match the new number of dimensions.
+                     * Some operations may be lost if we do not know how to 
propagate the vertical CRS.
+                     * If at least one operation remains, we are done.
+                     */
+                    if (decompose.source | decompose.target) {
+                        for (int i=operations.size(); --i >= 0;) {
+                            CoordinateOperation operation = operations.get(i);
+                            operation = propagateVertical(sourceCRS, 
targetCRS, operation, decompose);
+                            if (operation != null) {
+                                operation = complete(operation, sourceCRS, 
targetCRS);
+                                operations.set(i, operation);
+                            } else {
+                                operations.remove(i);
                             }
                         }
-                        if (!operations.isEmpty()) {
-                            return operations;
-                        }
                     }
-                    done = (allSources & allTargets);
-                    allSources = true;
-                    allTargets = true;
-                } while (!done);
+                    if (!operations.isEmpty()) {
+                        return operations;
+                    }
+                }
             } catch (IllegalArgumentException | IncommensurableException e) {
                 String message = 
Resources.format(Resources.Keys.CanNotInstantiateGeodeticObject_1, new 
CRSPair(sourceCRS, targetCRS));
                 String details = e.getLocalizedMessage();
@@ -537,30 +524,23 @@ class CoordinateOperationRegistry {
     /**
      * Returns operations for conversions or transformations between two 
coordinate reference systems.
      * This method extracts the authority code from the supplied {@code 
sourceCRS} and {@code targetCRS},
-     * and submit them to the {@link #registry}. If no operation is found for 
those codes, then this method
+     * and submits them to the {@link #registry}. If no operation is found for 
those codes, then this method
      * returns {@code null}.
      *
-     * @param  sourceCRS   source coordinate reference system.
-     * @param  targetCRS   target coordinate reference system.
-     * @param  allSources  whether to perform an extensive search for source 
CRS candidates.
-     * @param  allTargets  whether to perform an extensive search for target 
CRS candidates.
+     * @param  sourceCRS  source coordinate reference system.
+     * @param  targetCRS  target coordinate reference system.
      * @return a coordinate operation from {@code sourceCRS} to {@code 
targetCRS},
      *         or {@code null} if no such operation is explicitly defined in 
the underlying database.
      * @throws IllegalArgumentException if the coordinate systems are not of 
the same type or axes do not match.
      * @throws IncommensurableException if the units are not compatible or a 
unit conversion is non-linear.
      * @throws FactoryException if an error occurred while creating the 
operation.
      */
-    private List<CoordinateOperation> search(final CoordinateReferenceSystem 
sourceCRS, final boolean allSources,
-                                             final CoordinateReferenceSystem 
targetCRS, final boolean allTargets)
+    private List<CoordinateOperation> search(final CoordinateReferenceSystem 
sourceCRS,
+                                             final CoordinateReferenceSystem 
targetCRS)
             throws IllegalArgumentException, IncommensurableException, 
FactoryException
     {
-        final List<String> sources = findCode(sourceCRS, allSources); if 
(sources.isEmpty()) return null;
-        final List<String> targets = findCode(targetCRS, allTargets); if 
(targets.isEmpty()) return null;
-        if (sources.equals(lastSourceCodes) && 
targets.equals(lastTargetCodes)) {
-            return null;
-        }
-        lastSourceCodes = sources;
-        lastTargetCodes = targets;
+        final List<String> sources = findCode(sourceCRS); if 
(sources.isEmpty()) return null;
+        final List<String> targets = findCode(targetCRS); if 
(targets.isEmpty()) return null;
         final List<CoordinateOperation> operations = new ArrayList<>();
         boolean foundDirectOperations = false;
         boolean useDeprecatedOperations = false;

Reply via email to