# Class IdentifiedObjects

Object
IdentifiedObjects

public final class IdentifiedObjects extends Object
Utility methods working on arbitrary implementations of the `IdentifiedObject` interface.

Since:
  0.4
See Also:
  - `CRS`
  - `Envelopes`

- ## Method Summary

  Modifier and Type
  Method
  Description
  `static InternationalString`
  `getDisplayName(IdentifiedObject object)`
  Returns a name that can be used for display purposes.
  `static String`
  `getDisplayName(IdentifiedObject object, Locale locale)`
  Returns a name that can be used for display purposes in the specified locale.
  `static Optional<Extent>`
  `getDomainOfValidity(IdentifiedObject object)`
  Returns the domain of validity of the given object.
  `static Optional<GeographicBoundingBox>`
  `getGeographicBoundingBox(IdentifiedObject object)`
  Returns the geographic bounding box computed from the domains of the given object.
  `static Identifier`
  `getIdentifier(IdentifiedObject object, Citation authority)`
  Returns an identifier for the given object according the given authority.
  `static String`
  `getIdentifierOrName(IdentifiedObject object)`
  Returns the string representation of the first identifier, or the object name if there is no identifier.
  `static String`
  `getName(IdentifiedObject object, Citation authority)`
  Returns an object name according the given authority.
  `static Set<String>`
  `getNames(IdentifiedObject object, Citation authority)`
  Returns every object names and aliases according the given authority.
  `static Map<String,?>`
  `getProperties(IdentifiedObject object, String... excludes)`
  Returns the information provided in the specified identified object as a map of properties.
  `static String`
  `getSimpleNameOrIdentifier(IdentifiedObject object)`
  Returns the first name, alias or identifier which is a valid Unicode identifier.
  `static boolean`
  `isHeuristicMatchForName(IdentifiedObject object, String name)`
  Returns `true` if either the primary name or at least one alias matches the given string according heuristic rules.
  `static Integer`
  `lookupEPSG(IdentifiedObject object)`
  Looks up an EPSG code, such as `4326`, of the specified object.
  `static String`
  `lookupURN(IdentifiedObject object, Citation authority)`
  Looks up a URN, such as `"urn:ogc:def:crs:EPSG:9.1:4326"`, of the specified object.
  `static IdentifiedObjectFinder`
  `newFinder(String authority)`
  Creates a finder which can be used for looking up unidentified objects.
  `static String`
  `toString(Identifier identifier)`
  Returns a string representation of the given identifier.
  `static String`
  `toURN(Class<?> type, Identifier identifier)`
  Returns the URN of the given identifier, or `null` if no valid URN can be formed.

  ### Methods inherited from class Object

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

- ## Method Details

  - ### getProperties

    public static Map<String,?> getProperties(IdentifiedObject object, String... excludes)
    Returns the information provided in the specified identified object as a map of properties. The returned map contains the following entries for each key not contained in the `excludes` list and for which the corresponding method returns a non-null and non-empty value.

    Provided properties
    Key | Value
    --- | ---
    "name" | `IdentifiedObject.getName()`
    "alias" | `IdentifiedObject.getAlias()`
    "identifiers" | `IdentifiedObject.getIdentifiers()`
    "domains" | `AbstractIdentifiedObject.getDomains()`
    "remarks" | `IdentifiedObject.getRemarks()`
    "scope" | `DefaultObjectDomain.getScope()`
    "domainOfValidity" | `DefaultObjectDomain.getDomainOfValidity()`
    "operationVersion" | `CoordinateOperation.getOperationVersion()`
    "coordinateOperationAccuracy" | `CoordinateOperation.getCoordinateOperationAccuracy()`
    "formula" | `OperationMethod.getFormula()`
    "deprecated" | `AbstractIdentifiedObject.isDeprecated()`

    #### Implementation note

    The current implementation does not provide "minimumValue", "maximumValue" or "rangeMeaning" entry for `CoordinateSystemAxis` instances because the minimum and maximum values depend on the units of measurement.
    Parameters:
      `object` - the identified object to view as a properties map.
      `excludes` - the keys of properties to exclude from the map.
    Returns:
      a view of the identified object properties as an immutable map.

  - ### getNames

    public static Set<String> getNames(IdentifiedObject object, Citation authority)
    Returns every object names and aliases according the given authority. This method performs the same work as `getName(IdentifiedObject, Citation)`, except that it does not stop at the first match. This method is useful in the rare cases where the same authority declares more than one name, and all those names are of interest.
    Parameters:
      `object` - the object to get the names and aliases from, or `null`.
      `authority` - the authority for the names to return, or `null` for any authority.
    Returns:
      the object's names and aliases, or an empty set if no name or alias matching the specified authority has been found.

  - ### getName

    @OptionalCandidate public static String getName(IdentifiedObject object, Citation authority)
    Returns an object name according the given authority. This method checks first the primary name, then all aliases in their iteration order.
    - If the name or alias implements the `Identifier` interface, then this method compares the identifier authority against the specified citation using the `Citations​.identifierMatches(Citation, Citation)` method. If a matching is found, then this method returns the identifier code of that object.
    - Otherwise, if the alias implements the `GenericName` interface, then this method compares the name scope against the specified citation using the `Citations​.identifierMatches(Citation, String)` method. If a matching is found, then this method returns the string representation of that name.
    Note that alias may implement both the `Identifier` and `GenericName` interfaces (for example `NamedIdentifier`). In such cases, the identifier view has precedence.
    Parameters:
      `object` - the object to get the name from, or `null`.
      `authority` - the authority for the name to return, or `null` for any authority.
    Returns:
      the object's name (either an identifier code or a generic name), or `null` if no name matching the specified authority has been found.
    See Also:
      - `AbstractIdentifiedObject​.getName()`

  - ### getIdentifier

    @OptionalCandidate public static Identifier getIdentifier(IdentifiedObject object, Citation authority)
    Returns an identifier for the given object according the given authority. This method checks all identifiers in their iteration order and returns the first identifier with an authority citation matching the specified authority. If the specified authority implements `IdentifierSpace`, then the authority space name is also compared to the code space of each identifier.
    Parameters:
      `object` - the object to get the identifier from, or `null`.
      `authority` - the authority for the identifier to return, or `null` for the first identifier regardless its authority.
    Returns:
      the object's identifier, or `null` if no identifier matching the specified authority has been found.
    See Also:
      - `AbstractIdentifiedObject​.getIdentifier()`

  - ### getIdentifierOrName

    public static String getIdentifierOrName(IdentifiedObject object)
    Returns the string representation of the first identifier, or the object name if there is no identifier. This method searches for the first non-null element in `object.getIdentifiers()`. If there is none, then this method fallback on `object.getName()`. The first element found is formatted by `toString(Identifier)`.

    #### Recommended alternatives

    - If the code of a specific authority is wanted (typically EPSG), then consider using `getIdentifier(IdentifiedObject, Citation)` instead.
    - In many cases, the identifier is not specified. For an exhaustive scan of the EPSG database looking for a match, use one of the search methods defined below.
    Parameters:
      `object` - the identified object, or `null`.
    Returns:
      a string representation of the first identifier or name, or `null` if none.
    See Also:
      - `getIdentifier(IdentifiedObject, Citation)`
      - `lookupURN(IdentifiedObject, Citation)`

  - ### getSimpleNameOrIdentifier

    @OptionalCandidate public static String getSimpleNameOrIdentifier(IdentifiedObject object)
    Returns the first name, alias or identifier which is a valid Unicode identifier. This method considers a name or identifier as valid if `CharSequences​.isUnicodeIdentifier(CharSequence)` returns `true`. This method performs the search in the following order:
    - `object.getName()`
    - `object.getAlias()` in iteration order
    - `object.getIdentifiers()` in iteration order
    This method is can be used for fetching a more human-friendly identifier than the numerical values typically returned by `IdentifiedObject​.getIdentifiers()`. However, the returned value is not guaranteed to be unique.
    Parameters:
      `object` - the identified object, or `null`.
    Returns:
      the first name, alias or identifier which is a valid Unicode identifier, or `null` if none.
    Since:
      1.0
    See Also:
      - `ImmutableIdentifier`
      - `Citations​.toCodeSpace(Citation)`
      - `CharSequences​.isUnicodeIdentifier(CharSequence)`

  - ### getDisplayName

    public static InternationalString getDisplayName(IdentifiedObject object)
    Returns a name that can be used for display purposes. This method checks the non-blank name, alias or identifier, in that order. If the primary name seems to be the acronym of an alias, then the alias is returned. For example if the name is WGS 84 and an alias is World Geodetic System 1984, then that later alias is returned.

    The name should never be missing, but this method nevertheless fallbacks on identifiers as a safety against incomplete implementations. If an identifier implements `GenericName` (as with `NamedIdentifier`), its `toInternationalString()` method will be used.

    Parameters:
      `object` - the identified object, or `null`.
    Returns:
      a name for human reading, or `null` if the given object is null.
    Since:
      1.5
    See Also:
      - `getDisplayName(IdentifiedObject, Locale)`

  - ### getDisplayName

    public static String getDisplayName(IdentifiedObject object, Locale locale)
    Returns a name that can be used for display purposes in the specified locale. Invoking this method is equivalent to invoking `getDisplayName(object)​.toString(locale)`, except that the `object` argument can be null and the creation of an intermediate `InternationalString` object is avoided.
    Parameters:
      `object` - the identified object, or `null`.
      `locale` - the locale for the name to return, or `null` for the default.
    Returns:
      a name for human reading, or `null` if none were found.
    Since:
      1.1
    See Also:
      - `getDisplayName(IdentifiedObject)`

  - ### getDomainOfValidity

    public static Optional<Extent> getDomainOfValidity(IdentifiedObject object)
    Returns the domain of validity of the given object. If the object specifies more than one domain of validity, then this method computes their intersection (note that this is the opposite of `getGeographicBoundingBox(IdentifiedObject)`, which computes the union). If there is no intersection, then the returned object implements `Emptiable` and the `Emptiable​.isEmpty()` method returns `true`.
    Parameters:
      `object` - the object for which to get the domain of validity, or `null`.
    Returns:
      the domain of validity where the object is valid, or empty if unspecified.
    Since:
      1.5

  - ### getGeographicBoundingBox

    public static Optional<GeographicBoundingBox> getGeographicBoundingBox(IdentifiedObject object)
    Returns the geographic bounding box computed from the domains of the given object. If the given object contains more than one domain, then this method computes their union. Note that this is the opposite of `getDomainOfValidity(IdentifiedObject)`, which computes the intersection.
    Parameters:
      `object` - the object for which to get the domain of validity, or `null`.
    Returns:
      the geographic area where the object is valid, or empty if unspecified.
    Since:
      1.5
    See Also:
      - invalid reference

            IdentifiedObject#getDomains()

      - `Extents​.getGeographicBoundingBox(Stream)`

  - ### lookupURN

    @OptionalCandidate public static String lookupURN(IdentifiedObject object, Citation authority) throws FactoryException
    Looks up a URN, such as `"urn:ogc:def:crs:EPSG:9.1:4326"`, of the specified object. This method searches in all geodetic authority factories known to SIS for an object approximately equals to the specified object. Then there is a choice:
    - If a single matching object is found in the specified authority factory, then its URN is returned.
    - Otherwise if the given object is a `CompoundCRS` or `ConcatenatedOperation` and all components have an URN, then this method returns a combined URN.
    - Otherwise this method returns `null`.

    Note that this method checks the identifier validity. If the given object declares explicitly an identifier, then this method will instantiate an object from the authority factory using that identifier and compare it with the given object. If the comparison fails, then this method returns `null`. Consequently, this method may return `null` even if the given object declares explicitly its identifier. If the declared identifier is wanted unconditionally, one can use the following pattern instead:

        String urn = toURN(object.getClass(), getIdentifier(object, authority));

    This method can be seen as a converse of `CRS​.forCode(String)`.
    Parameters:
      `object` - the object (usually a coordinate reference system) whose identifier is to be found, or `null`.
      `authority` - the authority for the identifier to return, or `null` for the first identifier regardless its authority.
    Returns:
      the identifier, or `null` if none was found without ambiguity or if the given object was null.
    Throws:
      `UnavailableFactoryException` - if the factory for the authority identified in the URN is not available.
      `FactoryException` - if the lookup failed for another reason.
    Since:
      0.7
    See Also:
      - `newFinder(String)`
      - `toURN(Class, Identifier)`

  - ### lookupEPSG

    @OptionalCandidate public static Integer lookupEPSG(IdentifiedObject object) throws FactoryException
    Looks up an EPSG code, such as `4326`, of the specified object. This method searches in EPSG factories known to SIS for an object approximately equals to the specified object. If such an object is found, then its EPSG identifier is returned. Otherwise or if there is ambiguity, this method returns `null`.

    Note that this method checks the identifier validity. If the given object declares explicitly an identifier, then this method will instantiate an object from the EPSG factory using that identifier and compare it with the given object. If the comparison fails, then this method returns `null`. Consequently, this method may return `null` even if the given object declares explicitly its identifier. If the declared identifier is wanted unconditionally, one can use the following pattern instead:

        String code = toString(getIdentifier(object, Citations.EPSG));

    This method can be seen as a converse of `CRS​.forCode(String)`.
    Parameters:
      `object` - the object (usually a coordinate reference system) whose EPSG code is to be found, or `null`.
    Returns:
      the EPSG code, or `null` if none was found without ambiguity or if the given object was null.
    Throws:
      `UnavailableFactoryException` - if the EPSG factory is not available.
      `FactoryException` - if the lookup failed for another reason.
    Since:
      0.7
    See Also:
      - `newFinder(String)`

  - ### newFinder

    public static IdentifiedObjectFinder newFinder(String authority) throws NoSuchAuthorityFactoryException, FactoryException
    Creates a finder which can be used for looking up unidentified objects. This method is an alternative to `lookup(…)` methods when more control are desired.

    #### Example 1: be lenient regarding axis order

    By default, `lookup(…)` methods require that objects in the dataset have their axes in the same order as the given object. For relaxing this condition, one can use the following Java code. This example assumes that at most one object from the dataset will match the given object. If more than one object may match, then the call to `findSingleton(…)` should be replaced by `find(…)`.

        IdentifiedObjectFinder finder = IdentifiedObjects.newFinder(null);
        finder.setIgnoringAxes(true);
        IdentifiedObject found = finder.findSingleton(object);

    #### Example 2: extend the search to deprecated definitions

    By default, `lookup(…)` methods exclude deprecated objects from the search. To search also among deprecated objects, one can use the following Java code:

        IdentifiedObjectFinder finder = IdentifiedObjects.newFinder(null);
        finder.setSearchDomain(IdentifiedObjectFinder.Domain.ALL_DATASET);
        Set<IdentifiedObject> found = finder.find(object);

    Parameters:
      `authority` - the authority of the objects to search (typically `"EPSG"` or `"OGC"`), or `null` for searching among the objects created by all authorities.
    Returns:
      a finder to use for looking up unidentified objects.
    Throws:
      `NoSuchAuthorityFactoryException` - if the given authority is not found.
      `FactoryException` - if the finder cannot be created for another reason.
    See Also:
      - `lookupEPSG(IdentifiedObject)`
      - `lookupURN(IdentifiedObject, Citation)`
      - `GeodeticAuthorityFactory​.newIdentifiedObjectFinder()`
      - `IdentifiedObjectFinder​.find(IdentifiedObject)`

  - ### isHeuristicMatchForName

    public static boolean isHeuristicMatchForName(IdentifiedObject object, String name)
    Returns `true` if either the primary name or at least one alias matches the given string according heuristic rules. If the given object is an instance of `AbstractIdentifiedObject`, then this method delegates to its `isHeuristicMatchForName(String)` method in order to leverage the additional rules implemented by sub-classes. Otherwise the fallback implementation returns `true` if the given `name` is equal, ignoring aspects documented below, to one of the following names:
    - The primary name's code (without codespace).
    - Any alias's tip (without scope and namespace).
    The comparison ignores the following aspects:
    - Lower/upper cases.
    - Some Latin diacritical signs (e.g. `"Réunion"` and `"Reunion"` are considered equal).
    - All characters that are not letters or digits (e.g. `"Mercator (1SP)"` and `"Mercator_1SP"` are considered equal).
    - Namespaces or scopes, because this method is typically invoked with either the value of another `IdentifiedObject​.getName()​.getCode()` or with the Well Known Text (WKT) projection or parameter name.
    If the `object` argument is `null`, then this method returns `false`.
    Parameters:
      `object` - the object for which to check the name or alias, or `null`.
      `name` - the name to compare with the object name or aliases.
    Returns:
      `true` if the primary name or at least one alias matches the specified `name`.
    See Also:
      - `AbstractIdentifiedObject​.isHeuristicMatchForName(String)`

  - ### toURN

    public static String toURN(Class<?> type, Identifier identifier)
    Returns the URN of the given identifier, or `null` if no valid URN can be formed. This method builds a URN from the codespace, version and code of the given identifier, completed by the given `Class` argument.

    First, this method starts the URN with `"urn:"` followed by a namespace determined from the identifier codespace (which is usually an abbreviation of the identifier authority). The recognized namespaces are listed in the following table (note that the list of authorities that can be used in the `"urn:ogc:def"` namespace is specified by the OGC Naming Authority). If this method cannot determine a namespace for the given identifier, it returns `null`.

    Valid values for the authority component in URN
    Namespace | Authority in URN | Description
    --- | --- | ---
    `urn:ogc:def` | `EPSG` | EPSG dataset
    `urn:ogc:def` | `OGC` | Open Geospatial Consortium
    `urn:ogc:def` | `OGC-WFS` | OGC Web Feature Service
    `urn:ogc:def` | `SI` | Système International d'Unités
    `urn:ogc:def` | `UCUM` | Unified Code for Units of Measure
    `urn:ogc:def` | `UNSD` | United Nations Statistics Division
    `urn:ogc:def` | `USNO` | United States Naval Observatory

    The namespace is followed by the authority, then by a type determined from the given `Class` argument. That class is usually determined simply by `IdentifiedObject​.getClass()`. The given class shall be assignable to one of the following types, otherwise this method returns `null`:

    Valid values for the type component in URN
    Interface | Type in URN | Description
    --- | --- | ---
    `CoordinateSystemAxis` | `axis` | Coordinate system axe definition
    `CoordinateOperation` | `coordinateOperation` | Coordinate operation definition
    `CoordinateReferenceSystem` | `crs` | Coordinate reference system definition
    `CoordinateSystem` | `cs` | Coordinate system definition
    `Datum` | `datum` | Datum definition
    `Ellipsoid` | `ellipsoid` | Ellipsoid definition
    `PrimeMeridian` | `meridian` | Prime meridian definition
    `OperationMethod` | `method` | Operation method definition
    `ParameterDescriptor` | `parameter` | Operation parameter definition
    `ReferenceSystem` | `referenceSystem` | Value reference system definition
    `Unit` | `uom` | Unit of measure definition

    The type is followed by the codespace version if available, and finally by the code value.

    The above tables may be expanded in any future SIS version.

    Parameters:
      `type` - a type assignable to one of the types listed in above table.
      `identifier` - the identifier for which to format a URN, or `null`.
    Returns:
      the URN for the given identifier, or `null` if the given identifier was null or cannot be formatted by this method.
    Since:
      0.7
    See Also:
      - `lookupURN(IdentifiedObject, Citation)`

  - ### toString

    public static String toString(Identifier identifier)
    Returns a string representation of the given identifier. This method applies the following rules:
    - If the given identifier implements the `GenericName` interface, then this method delegates to the `GenericName​.toString()` method.
    - Otherwise if the given identifier has a code space, then formats the identifier as "`codespace:code`".
    - Otherwise if the given identifier has an authority, then formats the identifier as "`authority:code`".
    - Otherwise returns the identifier code.
    This method is provided because the `GenericName​.toString()` behavior is specified by its javadoc, while `Identifier` has no such contract. For example, like most ISO 19115 objects in SIS, the `DefaultIdentifier` implementation is formatted as a tree. This static method can be used when a "name-like" representation is needed for any implementation.
    Parameters:
      `identifier` - the identifier, or `null`.
    Returns:
      a string representation of the given identifier, or `null`.
    See Also:
      - `FormattableObject​.toString()`
      - `NamedIdentifier​.toString()`