# Class OptionalInstallations

Object
InstallationResources
OptionalInstallations

All Implemented Interfaces:
  `Localized`

Direct Known Subclasses:
  `ResourcesDownloader`

public abstract class OptionalInstallations extends InstallationResources implements Localized
A predefined set of data important to Apache SIS but not redistributed for space or licensing reasons. This class is in charge of downloading the data if necessary and asking user's agreement before to install them. Authorities managed by the current implementation are:

- `"EPSG"` for the EPSG geodetic dataset.

Data are downloaded from URLs hard-coded in this class. Those URLs depend on the Apache SIS versions in use, typically because more recent SIS versions will reference more recent data. The default URLs can be overridden using system properties documented below. This is useful as a workaround if a URL is no longer accessible.

Properties for configuring download URLs
Authority | System property
--- | ---
EPSG | `org.apache.sis.epsg.downloadURL`

## Asking user's permission to download EPSG data

If an application does not want to bundle EPSG data by default, either for licensing reasons or for saving space, the application can ask user's permission the first time that EPSG data are needed, then (if agreed) download and install the data automatically. It can be done as below:

    public class OptionalInstallDialog extends OptionalInstallations {
        public OptionalInstallDialog() {
            super("text/plain");     // Desired format for the `license` argument below.
        }

        @Override
        protected boolean askUserAgreement(String authority, String license) {
            if ("EPSG".equals(authority)) {
                return false;    // If not interested in data other than EPSG.
            } else if (license == null) {
                // Ask here to user if she wants to download the EPSG data.
            } else {
                // Ask here to user if she accepts the EPSG terms of use.
            }
        }
    }

The above class needs to be declared as an implementation of the `InstallationResources` service. This is done either in `module-info​.java` or, if the application does not use Java modules, in the `META-INF/services/org​.apache​.sis​.setup​.InstallationResources` file. In addition, the `SIS_DATA` environment variable (not to be confused with Java property) needs to be set to the destination directory where to write data on the user's machine. With this configuration, Apache SIS will automatically asks for user agreement and, if agreed, download EPSG data when first needed. If the user does not agree, Apache SIS will still work but with a small set of hard-coded EPSG codes listed here.

Since:
  1.1

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `protected final Path`
  `destinationDirectory`
  The target directory where to install the resources, or `null` if none.

- ## Constructor Summary

  Constructors
  Modifier
  Constructor
  Description
  `protected`
  `OptionalInstallations(String licenseMimeType)`
  Creates a new installation resources downloader.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `protected abstract boolean`
  `askUserAgreement(String authority, String license)`
  Asks to the user if (s)he agree to download and install the resource for the given authority.
  `Set<String>`
  `getAuthorities()`
  Returns the names of the authorities providing data that can be installed.
  `String`
  `getLicense(String authority, Locale locale, String mimeType)`
  Returns the terms of use of the dataset provided by the given authority, or `null` if none.
  `Locale`
  `getLocale()`
  Returns the locale to use for messages shown to the user.
  `Object`
  `getResource(String authority, int index)`
  Returns an installation resource for the given authority.
  `String[]`
  `getResourceNames(String authority)`
  Returns the names of installation scripts provided by the given authority.
  `int`
  `getSpaceRequirement(String authority)`
  Returns an estimation of the space required on the host computer after download and installation.
  `BufferedReader`
  `openScript(String authority, int resource)`
  Returns a reader for the installation script at the given index.

  ### Methods inherited from class InstallationResources

  `getInstructionURL, load`

  ### Methods inherited from class Object

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

- ## Field Details

  - ### destinationDirectory

    protected final Path destinationDirectory
    The target directory where to install the resources, or `null` if none. This is the directory specified by the `SIS_DATA` environment variable.

- ## Constructor Details

  - ### OptionalInstallations

    protected OptionalInstallations(String licenseMimeType)
    Creates a new installation resources downloader.
    Parameters:
      `licenseMimeType` - either `"text/plain"` or `"text/html"`.

- ## Method Details

  - ### askUserAgreement

    protected abstract boolean askUserAgreement(String authority, String license)
    Asks to the user if (s)he agree to download and install the resource for the given authority. This method may be invoked twice for the same `authority` argument:
    1. With a null `license` argument for asking if the user agrees to download the data.
    2. With a non-null `license` argument for asking if the user agrees with the license terms.

    #### Design note

    The download action needs to be initiated before to ask for license agreement because the license text is bundled in the resource to download.
    Parameters:
      `authority` - one of the authorities returned by `getAuthorities()`.
      `license` - the license, or `null` for asking if the user wants to download the data.
    Returns:
      whether user accepted.

  - ### getLocale

    public Locale getLocale()
    Returns the locale to use for messages shown to the user. The default implementation returns the system default locale.
    Specified by:
      `getLocale` in interface `Localized`
    Returns:
      the locale of messages shown to the user.

  - ### getAuthorities

    public Set<String> getAuthorities()
    Returns the names of the authorities providing data that can be installed. The default implementation returns the authorities listed in class javadoc, or a subset of those authorities if some of them cannot be installed (for example because the `SIS_DATA` environment variable is not set).
    Specified by:
      `getAuthorities` in class `InstallationResources`
    Returns:
      authorities of data that can be installed (may be an empty set).

  - ### getSpaceRequirement

    public int getSpaceRequirement(String authority)
    Returns an estimation of the space required on the host computer after download and installation. This information can be shown to the user before to ask for confirmation.
    Parameters:
      `authority` - one of the authorities returned by `getAuthorities()`.
    Returns:
      an estimation of space requirement in megabytes.
    Throws:
      `IllegalArgumentException` - if the given `authority` argument is not one of the expected values.

  - ### getLicense

    public String getLicense(String authority, Locale locale, String mimeType) throws IOException
    Returns the terms of use of the dataset provided by the given authority, or `null` if none. The terms of use can be returned in either plain text or HTML.
    Specified by:
      `getLicense` in class `InstallationResources`
    Parameters:
      `authority` - one of the values returned by `getAuthorities()`.
      `locale` - the preferred locale for the terms of use.
      `mimeType` - either `"text/plain"` or `"text/html"`.
    Returns:
      the terms of use in plain text or HTML, or `null` if none.
    Throws:
      `IllegalArgumentException` - if the given `authority` argument is not one of the expected values.
      `IOException` - if an error occurred while reading the license file.

  - ### getResourceNames

    public String[] getResourceNames(String authority) throws IOException
    Returns the names of installation scripts provided by the given authority. This method is invoked by `EPSGFactory​.install(Connection)` for listing the SQL scripts to execute during EPSG dataset installation.

    If that question has not already been asked, this method asks to the user if (s)he accepts EPSG terms of use. If (s)he refuses, then an `AccessDeniedException` will be thrown.

    Specified by:
      `getResourceNames` in class `InstallationResources`
    Parameters:
      `authority` - one of the values returned by `getAuthorities()`.
    Returns:
      the names of all SQL scripts to execute.
    Throws:
      `IllegalArgumentException` - if the given `authority` argument is not one of the expected values.
      `IOException` - if an error occurred while fetching the script names.

  - ### getResource

    public Object getResource(String authority, int index) throws IOException
    Returns an installation resource for the given authority. If that question has not already been asked, this method asks to the user if (s)he accepts EPSG terms of use. If (s)he refuses, then an `AccessDeniedException` will be thrown.
    Overrides:
      `getResource` in class `InstallationResources`
    Parameters:
      `authority` - one of the values returned by `getAuthorities()`.
      `index` - index of the resource to get, from 0 inclusive to `getResourceNames(authority)​.length` exclusive.
    Returns:
      the resource as an URL or any other type, at implementation choice.
    Throws:
      `IllegalArgumentException` - if the given `authority` argument is not one of the expected values.
      `IndexOutOfBoundsException` - if the given `resource` argument is out of bounds.
      `IOException` - if an error occurred while fetching the resource.
    See Also:
      - `ClassLoader​.getResource(String)`

  - ### openScript

    public BufferedReader openScript(String authority, int resource) throws IOException
    Returns a reader for the installation script at the given index. This method is invoked by `EPSGFactory​.install(Connection)` for getting the SQL scripts to execute during EPSG dataset installation.

    If that question has not already been asked, this method asks to the user if (s)he accepts EPSG terms of use. If (s)he refuses, then an `AccessDeniedException` will be thrown.

    Specified by:
      `openScript` in class `InstallationResources`
    Parameters:
      `authority` - one of the values returned by `getAuthorities()`.
      `resource` - index of the script to open, from 0 inclusive to `getResourceNames(authority)​.length` exclusive.
    Returns:
      a reader for the installation script content.
    Throws:
      `IllegalArgumentException` - if the given `authority` argument is not one of the expected values.
      `IndexOutOfBoundsException` - if the given `resource` argument is out of bounds.
      `FileNotFoundException` - if the SQL script of the given name has not been found.
      `IOException` - if an error occurred while creating the reader.