Package org.apache.sis.io.wkt

# Class WKTDictionary

Object
AbstractFactory
GeodeticAuthorityFactory
WKTDictionary

All Implemented Interfaces:
  `AuthorityFactory`, `Factory`

public class WKTDictionary extends GeodeticAuthorityFactory
A factory providing CRS objects parsed from WKT definitions associated to authority codes. Each WKT definition is associated to a key according the authority:version:code pattern where code is mandatory and authority:version are optional. Coordinate Reference Systems or other kinds of objects are created from WKT definitions when a `create(…)` method is invoked for the first time for a given key.

## Sub-classing and instantiation

Newly constructed `WKTDictionary` are initially empty. The dictionary can be populated in the following ways:

- Invoke `load(BufferedReader)` for reading definitions from file(s).
- Invoke `addDefinitions(Stream)` for providing definitions from an arbitrary source.
- Override `fetchDefinition(DefaultIdentifier)` in a subclass for fetching WKT definitions on-the-fly (for example from the `"spatial_ref_sys"` table of a spatial database.

Sub-classing may be necessary even if `fetchDefinition(…)` is not overridden because `WKTDictionary` does not implement any of the `CRSAuthorityFactory`, `CSAuthorityFactory` or `DatumAuthorityFactory`. The choice of interfaces to implement is left to subclasses.
Example: extend the set of Coordinate Reference Systems recognized by `CRS​.forCode(String)`. The additional CRS are defined by Well-Known Text strings in a `"MyCRS​.txt"` file. First step is to create a CRS factory with those definitions:

>     public final class MyCRS extends WKTDictionary implements CRSAuthorityFactory {
>         MyCRS() throws IOException, FactoryException {
>             super(new DefaultCitation("MyAuthority"));
>             try (BufferedReader source = Files.newBufferedReader(Paths.get("MyCRS.txt"))) {
>                 load(source);
>             }
>         }
>     }

The second step is to register this factory as a service with a `META-INF/services/org​.opengis​.referencing​.crs​.CRSAuthorityFactory` file on the classpath. That file shall contain the fully qualified class name of above `MyCRS` class.

## Errors management

Well-Known Text parsing is performed in two steps, each of them executed at a different time:

### Early validation

WKT strings added by `load(…)` or `addDefinitions(…)` methods are verified for matching quotes, balanced parenthesis or brackets, and valid number or date formats. If a syntax error is detected, the loading process is interrupted at the point the error occurred; CRS definitions after the error location are not loaded. However WKT keywords and geodetic parameters (e.g. map projections) are not validated at this stage.

### Late validation

WKT keywords and geodetic parameters inside WKT elements are validated only when `createObject(String)` is invoked. If an error occurs at this stage, only the CRS (or other geodetic object) for the code given to the `createFoo(…)` method become invalid. Objects associated to other codes are not impacted.

## Multi-threading

This class is thread-safe but not necessarily concurrent. This class is designed for a relatively small amount of WKT; it is not a replacement for database-backed factory such as `EPSGFactory`.

Since:
  1.1

Defined in the `sis-referencing` module

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `protected final WKTFormat`
  `parser`
  The parser to use for creating geodetic objects from WKT definitions.

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `WKTDictionary(Citation authority)`
  Creates an initially empty factory.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `void`
  `addDefinitions(Stream<String> objects)`
  Adds definitions of CRS (or other geodetic objects) from Well-Known Texts.
  `IdentifiedObject`
  `createObject(String code)`
  Returns an arbitrary object from a code.
  `protected String`
  `fetchDefinition(DefaultIdentifier identifier)`
  Fetches the Well-Known Text for a user-specified identifier not found in this `WKTDictionary`.
  `Citation`
  `getAuthority()`
  Returns the authority or specification that defines the codes recognized by this factory.
  `Set<String>`
  `getAuthorityCodes(Class<? extends IdentifiedObject> type)`
  Returns the set of authority codes for objects of the given type.
  `Set<String>`
  `getCodeSpaces()`
  Returns all namespaces recognized by this factory.
  `InternationalString`
  `getDescriptionText(String code)`
  Gets a description of the object corresponding to a code.
  `void`
  `load(BufferedReader source)`
  Adds to this factory all definitions read from the given source.

  ### Methods inherited from class GeodeticAuthorityFactory

  `createCartesianCS, createCompoundCRS, createCoordinateOperation, createCoordinateReferenceSystem, createCoordinateSystem, createCoordinateSystemAxis, createCylindricalCS, createDatum, createDerivedCRS, createEllipsoid, createEllipsoidalCS, createEngineeringCRS, createEngineeringDatum, createExtent, createFromCoordinateReferenceSystemCodes, createGeocentricCRS, createGeodeticDatum, createGeographicCRS, createImageCRS, createImageDatum, createOperationMethod, createParameterDescriptor, createParametricCRS, createParametricCS, createParametricDatum, createPolarCS, createPrimeMeridian, createProjectedCRS, createSphericalCS, createTemporalCRS, createTemporalDatum, createTimeCS, createUnit, createVerticalCRS, createVerticalCS, createVerticalDatum, newIdentifiedObjectFinder, toString, trimNamespace`

  ### Methods inherited from class AbstractFactory

  `getVendor`

  ### Methods inherited from class Object

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

  ### Methods inherited from interface Factory

  `getVendor`

- ## Field Details

  - ### parser

    protected final WKTFormat parser
    The parser to use for creating geodetic objects from WKT definitions. Subclasses can modify the `WKTFormat` configuration in their constructor, but should not use it directly after construction (for thread safety reasons).

- ## Constructor Details

  - ### WKTDictionary

    public WKTDictionary(Citation authority)
    Creates an initially empty factory. The authority can specified explicitly or inferred from the WKTs. In the later case (when the given authority is `null`), an authority will be inferred from all `ID[…]` or `AUTHORITY[…]` elements found in WKT strings as below, in preference order:
    1. Most frequent `CITATION[…]` value.
    2. If there is no citation, then most frequent code space in `ID[…]` or `AUTHORITY[…]` elements.
    The WKT strings are specified by calls to `load(BufferedReader)` or `addDefinitions(Stream)` after construction.
    Parameters:
      `authority` - organization that defines the codes recognized by this factory, or `null`.

- ## Method Details

  - ### load

    public void load(BufferedReader source) throws FactoryException
    Adds to this factory all definitions read from the given source. Each Coordinate Reference System (or other geodetic object) is defined by a string in WKT format. The key associated to each object is given by the `ID[…]` or `AUTHORITY[…]` element, which is typically the last element of a WKT string and is mandatory for definitions in this file.

    WKT strings can span many lines. All lines after the first line shall be indented with at least one white space. Non-indented lines start new definitions.

    Blank lines and lines starting with the `#` character (ignoring white spaces) are ignored.

    #### Aliases for WKT fragments

    Files with more than one WKT definition tend to repeat the same WKT fragments many times. For example the same `BaseGeogCRS[…]` element may be repeated in every `ProjectedCRS` definitions. Redundant fragments can be replaced by aliases for making the file more compact, easier to read, faster to parse and with smaller memory footprint.

    Each line starting with "`SET <identifier>=<WKT>`" defines an alias for a fragment of WKT string. The WKT can span many lines as described above. Aliases are local to the file where they are defined. Aliases can be expanded in other WKT strings by "`$<identifier>`".

    #### Validation

    This method verifies that definitions have matching quotes, balanced parenthesis or brackets, and valid number or date formats. It does not verify WKT keywords or geodetic parameters. See class javadoc for more details.

    #### Example

    An example is available here.
    Parameters:
      `source` - the source of WKT definitions.
    Throws:
      `FactoryException` - if the definition file can not be read.

  - ### addDefinitions

    public void addDefinitions(Stream<String> objects) throws FactoryException
    Adds definitions of CRS (or other geodetic objects) from Well-Known Texts. Blank strings are ignored. Each non-blank `String` shall contain the complete definition of exactly one geodetic object. A geodetic object can not have its definition splitted in two or more `String`s.

    The key associated to each object is given by the `ID[…]` or `AUTHORITY[…]` element, which is typically the last element of a WKT string and is mandatory. WKT strings can contain line separators for human readability.

    Parameters:
      `objects` - CRS (or other geodetic objects) definitions as WKT strings.
    Throws:
      `FactoryException` - if a WKT can not be parsed, or does not contain an `ID[…]` or `AUTHORITY[…]` element, or if the same `codespace:version:code` tuple is used for two objects.

  - ### fetchDefinition

    protected String fetchDefinition(DefaultIdentifier identifier) throws FactoryException
    Fetches the Well-Known Text for a user-specified identifier not found in this `WKTDictionary`. Subclasses can override this method if WKT strings are not loaded or specified in advance, but instead fetched when first needed. An example of such scenario is WKTs provided by the `"spatial_ref_sys"` table of a spatial database. If no WKT is found for the given identifier, then this method returns `null`.

    On input, `identifier` contains only the pieces of information provided by user. For example if user invoked `createGeographicCRS("Foo")`, then the identifier code will be `"Foo"` but the codespace and version will be undefined (`null`). On output, `identifier` should be completed with missing code space and version (if available).

    #### Overriding

    The default implementation returns `null`. If a subclass overrides this method, then it should also override `getAuthorityCodes(Class)` because `WKTDictionary` does not know the codes that this method can recognize.
    Parameters:
      `identifier` - the code specified by user, possible with code space and version.
    Returns:
      Well-Known Text (WKT) for the given identifier, or `null` if none.
    Throws:
      `FactoryException` - if an error occurred while fetching the WKT.

  - ### getAuthority

    public Citation getAuthority()
    Returns the authority or specification that defines the codes recognized by this factory. This is the first of the following values, in preference order:
    1. The authority explicitly specified at construction time.
    2. A citation built from the most frequent value found in `CITATION` elements.
    3. A citation built from the most frequent value found in `ID` or `AUTHORITY` elements.
    Specified by:
      `getAuthority` in interface `AuthorityFactory`
    Specified by:
      `getAuthority` in class `GeodeticAuthorityFactory`
    Returns:
      the organization responsible for CRS definitions, or `null` if unknown.
    See Also:
      - `AbstractFactory​.getVendor()`

  - ### getCodeSpaces

    public Set<String> getCodeSpaces()
    Returns all namespaces recognized by this factory. Those namespaces can appear before codes in calls to `createFoo(String)` methods, for example `"ESRI"` in `"ESRI:102018"`. Namespaces are case-insensitive.
    Overrides:
      `getCodeSpaces` in class `GeodeticAuthorityFactory`
    Returns:
      the namespaces recognized by this factory.

  - ### getAuthorityCodes

    public Set<String> getAuthorityCodes(Class<? extends IdentifiedObject> type) throws FactoryException
    Returns the set of authority codes for objects of the given type. The `type` argument specifies the base type of identified objects.
    Parameters:
      `type` - the spatial reference objects type.
    Returns:
      the set of authority codes for spatial reference objects of the given type.
    Throws:
      `FactoryException` - if an error occurred while fetching the codes.

  - ### getDescriptionText

    public InternationalString getDescriptionText(String code) throws FactoryException
    Gets a description of the object corresponding to a code.
    Specified by:
      `getDescriptionText` in interface `AuthorityFactory`
    Overrides:
      `getDescriptionText` in class `GeodeticAuthorityFactory`
    Parameters:
      `code` - value allocated by authority.
    Returns:
      a description of the object, or `null` if `null` if none.
    Throws:
      `NoSuchAuthorityCodeException` - if the specified `code` was not found.
      `FactoryException` - if the query failed for some other reason.

  - ### createObject

    public IdentifiedObject createObject(String code) throws FactoryException
    Returns an arbitrary object from a code.
    Specified by:
      `createObject` in interface `AuthorityFactory`
    Specified by:
      `createObject` in class `GeodeticAuthorityFactory`
    Parameters:
      `code` - value allocated by authority.
    Returns:
      the object for the given code.
    Throws:
      `NoSuchAuthorityCodeException` - if the specified `code` was not found.
      `FactoryException` - if the object creation failed for some other reason.
    See Also:
      - `AbstractIdentifiedObject`