# Class CoordinateOperationFinder

Object
CoordinateOperationFinder

public class CoordinateOperationFinder extends Object
Finds a conversion or transformation path from a source CRS to a target CRS. This class implements two strategies for searching the coordinate operation:

1. When `createOperation(sourceCRS, targetCRS)` is invoked, this class first tries to find the authority codes for the given source and target CRS. If such codes are found, they are submitted to a registry of coordinate operations. If an operation is found, it will be returned.
   Note: the above is known as the late-binding approach. The late-binding approach allows the authority to define better suited operations than what we would get if we were transforming everything from and to a pivot system (e.g. WGS84). In addition, this approach provides useful information like the coordinate operation domain of validity and accuracy.
2. If the above authority factory does not know about the specified CRS, then this class tries to infer the coordinate operation by itself. The CRS type is examined and the work is dispatched to one or many of the `createOperationStep(…)` protected methods defined in this class. Those methods use properties associated to the CRS, including `BOUNDCRS` or `TOWGS84` elements found in Well Known Text (WKT).
   Note: the use of elements like `TOWGS84` is known as the early-binding approach. The operation found by this approach may be sub-optimal. The early-binding approach is used only as a fallback when the late-binding approach gave no result.

## Customization

Instances of this class are created by `DefaultCoordinateOperationFactory`. The only public method is `createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem)`, which dispatches its work to the `createOperationStep(…)` protected methods. Developers can override those protected methods if they want to alter the way some operations are created.

## Limitations

- Each instance of this class shall be used only once.
- This class is not thread-safe. A new instance shall be created for each coordinate operation to infer.

Since:
  0.7
See Also:
  - `DefaultCoordinateOperationFactory​.createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem, CoordinateOperationContext)`

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `protected Extent`
  `areaOfInterest`
  The spatiotemporal area of interest, or `null` if none.
  `protected final CoordinateOperationContext`
  `context`
  Options such as initial area of interest, desired accuracy and coordinates that may be considered as constants.
  `protected double`
  `desiredAccuracy`
  The desired accuracy in metres, or 0 for the best accuracy available.
  `protected final CoordinateOperationFactory`
  `factory`
  The factory to use for creating coordinate operations not found in the registry.
  `protected final CoordinateOperationAuthorityFactory`
  `registry`
  The factory to use for creating operations as defined by authority, or `null` if none.

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `CoordinateOperationFinder(CoordinateOperationAuthorityFactory registry, CoordinateOperationFactory factory, CoordinateOperationContext context)`
  Creates a new instance for the given factory and context.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `CoordinateOperation`
  `createOperation(CoordinateReferenceSystem sourceCRS, CoordinateReferenceSystem targetCRS)`
  Infers an operation for conversion or transformation between two coordinate reference systems.
  `List<CoordinateOperation>`
  `createOperations(CoordinateReferenceSystem sourceCRS, CoordinateReferenceSystem targetCRS)`
  Infers operations for conversions or transformations between two coordinate reference systems.
  `protected List<CoordinateOperation>`
  `createOperationStep(CoordinateReferenceSystem sourceCRS, List<? extends SingleCRS> sourceComponents, CoordinateReferenceSystem targetCRS, List<? extends SingleCRS> targetComponents)`
  Creates an operation between at least one `CompoundCRS` (usually the source) and an arbitrary CRS.
  `protected List<CoordinateOperation>`
  `createOperationStep(GeneralDerivedCRS sourceCRS, GeneralDerivedCRS targetCRS)`
  Creates an operation between two derived coordinate reference systems.
  `protected List<CoordinateOperation>`
  `createOperationStep(GeneralDerivedCRS sourceCRS, SingleCRS targetCRS)`
  Creates an operation from a derived CRS to an arbitrary single coordinate reference system.
  `protected List<CoordinateOperation>`
  `createOperationStep(GeodeticCRS sourceCRS, GeodeticCRS targetCRS)`
  Creates an operation between two geodetic (geographic or geocentric) coordinate reference systems.
  `protected List<CoordinateOperation>`
  `createOperationStep(GeodeticCRS sourceCRS, VerticalCRS targetCRS)`
  Creates an operation between a geodetic and a vertical coordinate reference systems.
  `protected List<CoordinateOperation>`
  `createOperationStep(SingleCRS sourceCRS, GeneralDerivedCRS targetCRS)`
  Creates operations from an arbitrary single CRS to a derived coordinate reference system.
  `protected List<CoordinateOperation>`
  `createOperationStep(TemporalCRS sourceCRS, TemporalCRS targetCRS)`
  Creates an operation between two temporal coordinate reference systems.
  `protected List<CoordinateOperation>`
  `createOperationStep(VerticalCRS sourceCRS, VerticalCRS targetCRS)`
  Creates an operation between two vertical coordinate reference systems.

  ### Methods inherited from class Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Field Details

  - ### registry

    protected final CoordinateOperationAuthorityFactory registry
    The factory to use for creating operations as defined by authority, or `null` if none. This is the factory used by the late-binding approach.

  - ### factory

    protected final CoordinateOperationFactory factory
    The factory to use for creating coordinate operations not found in the registry. This is the factory used by the early-binding approach.

  - ### context

    protected final CoordinateOperationContext context
    Options such as initial area of interest, desired accuracy and coordinates that may be considered as constants. This is null if no context has been specified.
    Since:
      1.6

  - ### areaOfInterest

    protected Extent areaOfInterest
    The spatiotemporal area of interest, or `null` if none. When a new `CoordinateOperationFinder` instance is created with a non-null `CoordinateOperationContext`, the context is used for initializing this value. After initialization, this field may be updated as `CoordinateOperationFinder` progresses in its search for a coordinate operation.
    See Also:
      - `CoordinateOperationContext​.getAreaOfInterest()`

  - ### desiredAccuracy

    protected double desiredAccuracy
    The desired accuracy in metres, or 0 for the best accuracy available.
    See Also:
      - `CoordinateOperationContext​.getDesiredAccuracy()`

- ## Constructor Details

  - ### CoordinateOperationFinder

    public CoordinateOperationFinder(CoordinateOperationAuthorityFactory registry, CoordinateOperationFactory factory, CoordinateOperationContext context) throws FactoryException
    Creates a new instance for the given factory and context.
    Parameters:
      `registry` - the factory to use for creating operations as defined by authority, or `null` if none.
      `factory` - the factory to use for creating operations not found in the registry.
      `context` - the area of interest and desired accuracy, or `null` if none.
    Throws:
      `FactoryException` - if an error occurred while initializing this `CoordinateOperationFinder`.
    See Also:
      - `DefaultCoordinateOperationFactory​.createOperationFinder(CoordinateOperationAuthorityFactory, CoordinateOperationContext)`

- ## Method Details

  - ### createOperation

    public CoordinateOperation createOperation(CoordinateReferenceSystem sourceCRS, CoordinateReferenceSystem targetCRS) throws OperationNotFoundException, FactoryException
    Infers an operation for conversion or transformation between two coordinate reference systems. If a non-null authority factory – the registry – has been specified at construction time, then this method will first query that factory (late-binding approach – see class javadoc). If no operation has been found in the registry or if no registry has been specified to the constructor, this method inspects the given CRS and delegates the work to one or many `createOperationStep(…)` methods (early-binding approach).

    The default implementation invokes `createOperations(sourceCRS, targetCRS)`, then returns the first operation in the returned list or throws an exception if the list is empty.

    Parameters:
      `sourceCRS` - input coordinate reference system.
      `targetCRS` - output coordinate reference system.
    Returns:
      a coordinate operation from `sourceCRS` to `targetCRS`.
    Throws:
      `OperationNotFoundException` - if no operation path was found from `sourceCRS` to `targetCRS`.
      `FactoryException` - if the operation creation failed for some other reason.

  - ### createOperations

    public List<CoordinateOperation> createOperations(CoordinateReferenceSystem sourceCRS, CoordinateReferenceSystem targetCRS) throws FactoryException
    Infers operations for conversions or transformations between two coordinate reference systems. If a non-null authority factory – the registry – has been specified at construction time, then this method will first query that factory (late-binding approach – see class javadoc). If no operation has been found in the registry or if no registry has been specified to the constructor, this method inspects the given CRS and delegates the work to one or many `createOperationStep(…)` methods (early-binding approach).

    At first, this method is invoked with the `sourceCRS` and `targetCRS` arguments given to the `CoordinateOperationFactory​.createOperation(…)` method. But then, this method may be invoked recursively by some `createOperationStep(…)` methods with different source or target CRS, for example in order to process the base geographic CRS of a projected CRS.

    Coordinate operations are returned in preference order: best operations for the area of interest should be first. The returned list is modifiable: callers can add, remove or set elements without impact on this `CoordinateOperationFinder` instance.

    Parameters:
      `sourceCRS` - input coordinate reference system.
      `targetCRS` - output coordinate reference system.
    Returns:
      coordinate operations from `sourceCRS` to `targetCRS`.
    Throws:
      `OperationNotFoundException` - if no operation path was found from `sourceCRS` to `targetCRS`.
      `FactoryException` - if the operation creation failed for some other reason.
    Since:
      1.0

  - ### createOperationStep

    protected List<CoordinateOperation> createOperationStep(SingleCRS sourceCRS, GeneralDerivedCRS targetCRS) throws FactoryException
    Creates operations from an arbitrary single CRS to a derived coordinate reference system. Conversions from `GeographicCRS` to `ProjectedCRS` are also handled by this method, since projected CRS are a special kind of `GeneralDerivedCRS`.

    The default implementation constructs the following operation chain:

    > `sourceCRS → baseCRS → targetCRS`

    where the conversion from `baseCRS` to `targetCRS` is obtained from `targetCRS.getConversionFromBase()`.

    This method returns only one step for a chain of concatenated operations (to be built by the caller). But a list is returned because the same step may be implemented by different operation methods. Only one element in the returned list should be selected (usually the first one).

    Parameters:
      `sourceCRS` - input coordinate reference system.
      `targetCRS` - output coordinate reference system.
    Returns:
      coordinate operations from `sourceCRS` to `targetCRS`.
    Throws:
      `FactoryException` - if the operation cannot be constructed.

  - ### createOperationStep

    protected List<CoordinateOperation> createOperationStep(GeneralDerivedCRS sourceCRS, SingleCRS targetCRS) throws FactoryException
    Creates an operation from a derived CRS to an arbitrary single coordinate reference system. Conversions from `ProjectedCRS` to `GeographicCRS` are also handled by this method, since projected CRS are a special kind of `GeneralDerivedCRS`.

    The default implementation constructs the following operation chain:

    > `sourceCRS → baseCRS → targetCRS`

    where the conversion from `sourceCRS` to `baseCRS` is obtained from the inverse of `sourceCRS.getConversionFromBase()`.

    This method returns only one step for a chain of concatenated operations (to be built by the caller). But a list is returned because the same step may be implemented by different operation methods. Only one element in the returned list should be selected (usually the first one).

    Parameters:
      `sourceCRS` - input coordinate reference system.
      `targetCRS` - output coordinate reference system.
    Returns:
      a coordinate operation from `sourceCRS` to `targetCRS`.
    Throws:
      `FactoryException` - if the operation cannot be constructed.

  - ### createOperationStep

    protected List<CoordinateOperation> createOperationStep(GeneralDerivedCRS sourceCRS, GeneralDerivedCRS targetCRS) throws FactoryException
    Creates an operation between two derived coordinate reference systems. The default implementation performs three steps:
    1. Convert from `sourceCRS` to its base CRS.
    2. Convert the source base CRS to target base CRS.
    3. Convert from the target base CRS to the `targetCRS`.

    This method returns only one step for a chain of concatenated operations (to be built by the caller). But a list is returned because the same step may be implemented by different operation methods. Only one element in the returned list should be selected (usually the first one).

    Parameters:
      `sourceCRS` - input coordinate reference system.
      `targetCRS` - output coordinate reference system.
    Returns:
      a coordinate operation from `sourceCRS` to `targetCRS`.
    Throws:
      `FactoryException` - if the operation cannot be constructed.

  - ### createOperationStep

    protected List<CoordinateOperation> createOperationStep(GeodeticCRS sourceCRS, GeodeticCRS targetCRS) throws FactoryException
    Creates an operation between two geodetic (geographic or geocentric) coordinate reference systems. The default implementation can:
    - adjust axis order and orientation, for example converting from (North, West) axes to (East, North) axes,
    - apply units conversion if needed,
    - perform longitude rotation if needed,
    - perform datum shift if Bursa-Wolf parameters are available for the area of interest.
    This method returns only one step for a chain of concatenated operations (to be built by the caller). But a list is returned because the same step may be implemented by different operation methods. Only one element in the returned list should be selected (usually the first one).
    Parameters:
      `sourceCRS` - input coordinate reference system.
      `targetCRS` - output coordinate reference system.
    Returns:
      a coordinate operation from `sourceCRS` to `targetCRS`.
    Throws:
      `FactoryException` - if the operation cannot be constructed.

  - ### createOperationStep

    protected List<CoordinateOperation> createOperationStep(GeodeticCRS sourceCRS, VerticalCRS targetCRS) throws FactoryException
    Creates an operation between a geodetic and a vertical coordinate reference systems. The height returned by this method will usually be part of a pass-through operation.

    This method returns only one step for a chain of concatenated operations (to be built by the caller). But a list is returned because the same step may be implemented by different operation methods. Only one element in the returned list should be selected (usually the first one).

    Parameters:
      `sourceCRS` - input coordinate reference system.
      `targetCRS` - output coordinate reference system.
    Returns:
      a coordinate operation from `sourceCRS` to `targetCRS`.
    Throws:
      `FactoryException` - if the operation cannot be constructed.

  - ### createOperationStep

    protected List<CoordinateOperation> createOperationStep(VerticalCRS sourceCRS, VerticalCRS targetCRS) throws FactoryException
    Creates an operation between two vertical coordinate reference systems. The default implementation checks if both CRS use the same datum, then adjusts for axis direction and units.

    This method returns only one step for a chain of concatenated operations (to be built by the caller). But a list is returned because the same step may be implemented by different operation methods. Only one element in the returned list should be selected (usually the first one).

    Parameters:
      `sourceCRS` - input coordinate reference system.
      `targetCRS` - output coordinate reference system.
    Returns:
      a coordinate operation from `sourceCRS` to `targetCRS`.
    Throws:
      `FactoryException` - if the operation cannot be constructed.
    "TODO:"
      Needs to implement vertical datum shift.

  - ### createOperationStep

    protected List<CoordinateOperation> createOperationStep(TemporalCRS sourceCRS, TemporalCRS targetCRS) throws FactoryException
    Creates an operation between two temporal coordinate reference systems. The default implementation checks if both CRS use the same datum, then adjusts for axis direction, units and epoch.

    This method returns only one step for a chain of concatenated operations (to be built by the caller). But a list is returned because the same step may be implemented by different operation methods. Only one element in the returned list should be selected (usually the first one).

    Parameters:
      `sourceCRS` - input coordinate reference system.
      `targetCRS` - output coordinate reference system.
    Returns:
      a coordinate operation from `sourceCRS` to `targetCRS`.
    Throws:
      `FactoryException` - if the operation cannot be constructed.
    "TODO:"
      The current version performs only unit conversion and change of datum epoch, assuming that everything else is equivalent. This is probably not sufficient, as the relationship between two temporal datum may be non-linear. We should invoke `DatumOrEnsemble​.asTargetDatum(TemporalCRS, TemporalCRS)` for checking if the datum are equivalent, but doing so require that we remove the origin attribute from `TemporalDatum`. This change has been proposed to OGC.

  - ### createOperationStep

    protected List<CoordinateOperation> createOperationStep(CoordinateReferenceSystem sourceCRS, List<? extends SingleCRS> sourceComponents, CoordinateReferenceSystem targetCRS, List<? extends SingleCRS> targetComponents) throws FactoryException
    Creates an operation between at least one `CompoundCRS` (usually the source) and an arbitrary CRS. The default implementation tries to invoke the `createOperation(…)` method with various combinations of source and target components. A preference is given for components of the same type (e.g. source `GeodeticCRS` with target `GeodeticCRS`, etc.).

    This method returns only one step for a chain of concatenated operations (to be built by the caller). But a list is returned because the same step may be implemented by different operation methods. Only one element in the returned list should be selected (usually the first one).

    Parameters:
      `sourceCRS` - input coordinate reference system.
      `sourceComponents` - components of the source CRS.
      `targetCRS` - output coordinate reference system.
      `targetComponents` - components of the target CRS.
    Returns:
      a coordinate operation from `sourceCRS` to `targetCRS`.
    Throws:
      `FactoryException` - if the operation cannot be constructed.