# Class DefaultParameterValue<T>

Object
FormattableObject
DefaultParameterValue<T>

Type Parameters:
  `T` - the type of the value stored in this parameter.

All Implemented Interfaces:
  `Serializable, Cloneable, LenientComparable, Printable, GeneralParameterValue, ParameterValue<T>`

public class DefaultParameterValue<T> extends FormattableObject implements ParameterValue<T>, LenientComparable, Serializable, Cloneable
A single parameter value used by an operation method. Each `ParameterValue` is a (key, value) pair, and an arbitrary number of those pairs can be stored in a a parameter value group. In the context of coordinate operations, parameter values are often numeric and can be obtained by the `intValue()` or `doubleValue()` methods. But other types of parameter values are possible and can be handled by the more generic `getValue()` and `setValue(Object)` methods. All `xxxValue()` methods in this class are convenience methods converting the value from `Object` to some commonly used types. Those types are specified in ISO 19111 as a union of attributes, listed below with the corresponding getter and setter methods:

Mapping from ISO attributes to getters and setters
ISO attribute | Java type | Getter method | Setter method
--- | --- | --- | ---
| `Object` | `getValue()` | `setValue(Object)`
stringValue | `String` | `stringValue()` | `setValue(Object)`
value | `double` | `doubleValue()` | `setValue(double)`
| `double` | `doubleValue(Unit)` | `setValue(double, Unit)`
valueList | `double[]` | `doubleValueList()` | `setValue(Object)`
| `double[]` | `doubleValueList(Unit)` | `setValue(double[], Unit)`
integerValue | `int` | `intValue()` | `setValue(int)`
integerValueList | `int[]` | `intValueList()` | `setValue(Object)`
booleanValue | `boolean` | `booleanValue()` | `setValue(boolean)`
valueFile | `URI` | `valueFile()` | `setValue(Object)`
valueFileCitation | `Citation` | `getValue()` | `setValue(Object)`

The type and constraints on parameter values are given by the descriptor, which is specified at construction time. The parameter type can be fetch with the following idiom:

    Class<T> valueClass = parameter.getDescriptor().getValueClass();

## Absolute paths of value files

Parameters that are too complex for being expressed as an `int[]`, `double[]` or `String` type may be encoded in auxiliary files. It is the case, for example, of gridded data such as datum shift grids. The name of an auxiliary file is given by `valueFile()`, but often as a relative path. The directory where that file is located depends on the operation using the parameter. For example, datum shift grids used by coordinate transformations are searched in the `$SIS_DATA/DatumChanges` directory, where `$SIS_DATA` is the value of the environment variable. However, the latest approach requires that all potentially used auxiliary files are preexisting on the local machine. This assumption may be applicable for parameters coming from a well-known registry such as EPSG, but cannot work with arbitrary operations where the auxiliary files need to be transferred together with the parameter values. For the latter case, an alternative is to consider the auxiliary files as relative to the GML document or WKT file that provides the parameter values. For allowing users to resolve or download auxiliary files in that way, a `getSourceFile()` method is provided. Operations can then use `URI​.resolve(URI)` for getting the absolute path of an auxiliary file from the same server or directory than the GML or WKT file of parameter values.

## Instantiation

A parameter descriptor must be defined before parameter value can be created. Descriptors are usually predefined (often hard-coded) by map projection or process providers. Given a descriptor, the preferred way to create a parameter value is to invoke the `ParameterDescriptor​.createValue()` method. It is also possible to invoke the constructor directly, but the former is recommended because it allows descriptors to return specialized implementations.

## Implementation note for subclasses

All read and write operations except constructors, `equals(Object)` and `hashCode()`, ultimately delegates to the following methods:

- The source file property is accessed by `getSourceFile()` and `setSourceFile(URI)`.
- All other getter methods will invoke `getValue()` and `getUnit()` (if needed), then perform their processing on the values returned by those methods.
- All other setter methods delegate to the `setValue(Object, Unit)` method.

Consequently, the above-cited methods provide single points that subclasses can override for modifying the behavior of all getter and setter methods.

Since:
  0.4
See Also:
  - `DefaultParameterDescriptor`
  - `DefaultParameterValueGroup`
  - Serialized Form

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `protected Unit<?>`
  `unit`
  The unit of measure for the value, or `null` if it does not apply.
  `protected T`
  `value`
  The value, or `null` if undefined.

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `DefaultParameterValue(ParameterDescriptor<T> descriptor)`
  Creates a parameter value from the specified descriptor.
  `DefaultParameterValue(ParameterValue<T> parameter)`
  Creates a new instance initialized with the values from the specified parameter object.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `boolean`
  `booleanValue()`
  Returns the boolean value of this parameter.
  `DefaultParameterValue<T>`
  `clone()`
  Returns a clone of this parameter value.
  `double`
  `doubleValue()`
  Returns the numeric value of this parameter.
  `double`
  `doubleValue(Unit<?> unit)`
  Returns the numeric value of this parameter in the given unit of measure.
  `double[]`
  `doubleValueList()`
  Returns an ordered sequence of two or more numeric values of this parameter, where each value has the same associated unit of measure.
  `double[]`
  `doubleValueList(Unit<?> unit)`
  Returns an ordered sequence of numeric values in the specified unit of measure.
  `final boolean`
  `equals(Object object)`
  Compares the specified object with this parameter for equality.
  `boolean`
  `equals(Object object, ComparisonMode mode)`
  Compares the specified object with this parameter for equality.
  `protected String`
  `formatTo(Formatter formatter)`
  Formats this parameter as a Well Known Text `Parameter[…]` element.
  `ParameterDescriptor<T>`
  `getDescriptor()`
  Returns the definition of this parameter.
  `Optional<URI>`
  `getSourceFile()`
  Returns the URI of the GML document or WKT file from which the parameter values are read.
  `Unit<?>`
  `getUnit()`
  Returns the unit of measure of the parameter value.
  `T`
  `getValue()`
  Returns the parameter value as an object.
  `int`
  `hashCode()`
  Returns a hash value for this parameter.
  `int`
  `intValue()`
  Returns the integer value of this parameter, usually used for a count.
  `int[]`
  `intValueList()`
  Returns an ordered sequence of two or more integer values of this parameter, usually used for counts.
  `void`
  `setSourceFile(URI document)`
  Sets the URI of the GML document or WKT file from which this parameter value has been read.
  `void`
  `setValue(boolean newValue)`
  Sets the parameter value as a boolean.
  `void`
  `setValue(double newValue)`
  Sets the parameter value as a floating point.
  `void`
  `setValue(double[] newValues, Unit<?> unit)`
  Sets the parameter value as an array of floating point and their associated unit.
  `void`
  `setValue(double newValue, Unit<?> unit)`
  Sets the parameter value as a floating point and its associated unit.
  `void`
  `setValue(int newValue)`
  Sets the parameter value as an integer.
  `void`
  `setValue(Object newValue)`
  Sets the parameter value as an object.
  `protected void`
  `setValue(Object newValue, Unit<?> unit)`
  Sets the parameter value and its associated unit.
  `String`
  `stringValue()`
  Returns the string value of this parameter.
  `static <T> DefaultParameterValue<T>`
  `unmodifiable(ParameterValue<T> parameter)`
  Returns an unmodifiable implementation of the given parameter value.
  `protected void`
  `validate(T newValue)`
  Invoked by `setValue(Object, Unit)` after the basic verifications have been done and before the value is stored.
  `URI`
  `valueFile()`
  Returns a reference to a file or a part of a file containing one or more parameter values.

  ### Methods inherited from class FormattableObject

  `print, toString, toString, toWKT`

  ### Methods inherited from class Object

  `finalize, getClass, notify, notifyAll, wait, wait, wait`

- ## Field Details

  - ### value

    protected T value
    The value, or `null` if undefined. Except for the constructors, the `equals(Object)` and the `hashCode()` methods, this field should be read only by `getValue()` and written only by `setValue(Object, Unit)`.
    Since:
      0.7

  - ### unit

    protected Unit<?> unit
    The unit of measure for the value, or `null` if it does not apply. Except for the constructors, the `equals(Object)` and the `hashCode()` methods, this field should be read only by `getUnit()` and written only by `setValue(Object, Unit)`.
    Since:
      0.7

- ## Constructor Details

  - ### DefaultParameterValue

    public DefaultParameterValue(ParameterDescriptor<T> descriptor)
    Creates a parameter value from the specified descriptor. The value will be initialized to the default value, if any.
    Parameters:
      `descriptor` - the abstract definition of this parameter.

  - ### DefaultParameterValue

    public DefaultParameterValue(ParameterValue<T> parameter)
    Creates a new instance initialized with the values from the specified parameter object. This is a shallow copy constructor, since the value contained in the given object is not cloned.
    Parameters:
      `parameter` - the parameter to copy values from.
    See Also:
      - `clone()`
      - `unmodifiable(ParameterValue)`

- ## Method Details

  - ### getDescriptor

    public ParameterDescriptor<T> getDescriptor()
    Returns the definition of this parameter.
    Specified by:
      `getDescriptor` in interface `GeneralParameterValue`
    Specified by:
      `getDescriptor` in interface `ParameterValue<T>`
    Returns:
      description of this parameter.

  - ### getSourceFile

    public Optional<URI> getSourceFile()
    Returns the URI of the GML document or WKT file from which the parameter values are read. This information allows to interpret `valueFile()` as a path relative to the file that defined this parameter value. For example, the following snippet gets the file, then tries to make it absolute:

        DefaultParameterValue<?> pv = ...;
        URI file = pv.valueFile();
        file = pv.getSourceFile().map((base) -> base.resolve(file)).orElse(file);

    Returns:
      the URI of the document from which the parameter values are read.
    Since:
      1.5
    See Also:
      - `setSourceFile(URI)`
      - `Parameters​.getSourceFile(ParameterDescriptor)`
      - `WKTFormat​.getSourceFile()`
      - `MarshalContext​.getDocumentURI()`
      - `URI​.resolve(URI)`

  - ### getUnit

    public Unit<?> getUnit()
    Returns the unit of measure of the parameter value. If the parameter value has no unit (for example because it is a `String` type), then this method returns `null`. Note that "no unit" does not mean "dimensionless".

    #### Implementation note for subclasses

    All getter methods which need unit information will invoke this `getUnit()` method. Subclasses can override this method if they need to compute the unit dynamically.
    Specified by:
      `getUnit` in interface `ParameterValue<T>`
    Returns:
      the unit of measure, or `null` if none.
    See Also:
      - `doubleValue()`
      - `doubleValueList()`
      - `getValue()`

  - ### getValue

    public T getValue()
    Returns the parameter value as an object. If no value has been set, then this method returns the default value (which may be null).

    #### Implementation note for subclasses

    All getter methods will invoke this `getValue()` method. Subclasses can override this method if they need to compute the value dynamically.
    Specified by:
      `getValue` in interface `ParameterValue<T>`
    Returns:
      the parameter value as an object, or `null` if no value has been set and there is no default value.
    See Also:
      - `setValue(Object)`
      - `Parameters​.getValue(ParameterDescriptor)`

  - ### booleanValue

    public boolean booleanValue() throws IllegalStateException
    Returns the boolean value of this parameter. A boolean value does not have an associated unit of measure.

    The default implementation invokes `getValue()` and casts the result if possible, or throws an exception otherwise.

    Specified by:
      `booleanValue` in interface `ParameterValue<T>`
    Returns:
      the boolean value represented by this parameter.
    Throws:
      `InvalidParameterTypeException` - if the value is not a boolean type.
      `IllegalStateException` - if the value is not defined and there is no default value.
    See Also:
      - `setValue(boolean)`
      - `Parameters​.booleanValue(ParameterDescriptor)`

  - ### intValue

    public int intValue() throws IllegalStateException
    Returns the integer value of this parameter, usually used for a count. An integer value does not have an associated unit of measure.

    The default implementation invokes `getValue()` and casts the result if possible, or throws an exception otherwise.

    Specified by:
      `intValue` in interface `ParameterValue<T>`
    Returns:
      the numeric value represented by this parameter after conversion to type `int`.
    Throws:
      `InvalidParameterTypeException` - if the value is not an integer type.
      `IllegalStateException` - if the value is not defined and there is no default value.
    See Also:
      - `setValue(int)`
      - `intValueList()`
      - `Parameters​.intValue(ParameterDescriptor)`

  - ### intValueList

    public int[] intValueList() throws IllegalStateException
    Returns an ordered sequence of two or more integer values of this parameter, usually used for counts.

    The default implementation invokes `getValue()` and casts the result if possible, or throws an exception otherwise. If the value can be cast, then the array is cloned before to be returned.

    Specified by:
      `intValueList` in interface `ParameterValue<T>`
    Returns:
      a copy of the sequence of values represented by this parameter.
    Throws:
      `InvalidParameterTypeException` - if the value is not an array of `int`s.
      `IllegalStateException` - if the value is not defined and there is no default value.
    See Also:
      - `setValue(Object)`
      - `intValue()`
      - `Parameters​.intValueList(ParameterDescriptor)`

  - ### doubleValue

    public double doubleValue() throws IllegalStateException
    Returns the numeric value of this parameter. The units of measurement are specified by `getUnit()`.

    The default implementation invokes `getValue()` and casts the result if possible, or throws an exception otherwise.

    Specified by:
      `doubleValue` in interface `ParameterValue<T>`
    Returns:
      the numeric value represented by this parameter after conversion to type `double`. This method returns `Double​.NaN` only if such "value" has been explicitly set.
    Throws:
      `InvalidParameterTypeException` - if the value is not a numeric type.
      `IllegalStateException` - if the value is not defined and there is no default value.
    See Also:
      - `getUnit()`
      - `setValue(double)`
      - `doubleValueList()`
      - `Parameters​.doubleValue(ParameterDescriptor)`

  - ### doubleValueList

    public double[] doubleValueList() throws IllegalStateException
    Returns an ordered sequence of two or more numeric values of this parameter, where each value has the same associated unit of measure.

    The default implementation invokes `getValue()` and casts the result if possible, or throws an exception otherwise. If the value can be cast, then the array is cloned before to be returned.

    Specified by:
      `doubleValueList` in interface `ParameterValue<T>`
    Returns:
      a copy of the sequence of values represented by this parameter.
    Throws:
      `InvalidParameterTypeException` - if the value is not an array of `double`s.
      `IllegalStateException` - if the value is not defined and there is no default value.
    See Also:
      - `getUnit()`
      - `setValue(Object)`
      - `doubleValue()`

  - ### doubleValue

    public double doubleValue(Unit<?> unit) throws IllegalArgumentException, IllegalStateException
    Returns the numeric value of this parameter in the given unit of measure. This convenience method applies unit conversions on the fly as needed.

    The default implementation invokes `doubleValue()` and `getUnit()`, then converts the values to the given unit of measurement.

    Specified by:
      `doubleValue` in interface `ParameterValue<T>`
    Parameters:
      `unit` - the unit of measure for the value to be returned.
    Returns:
      the numeric value represented by this parameter after conversion to type `double` and conversion to `unit`.
    Throws:
      `IllegalArgumentException` - if the specified unit is invalid for this parameter.
      `InvalidParameterTypeException` - if the value is not a numeric type.
      `IllegalStateException` - if the value is not defined and there is no default value.
    See Also:
      - `getUnit()`
      - `setValue(double,Unit)`
      - `doubleValueList(Unit)`
      - `Parameters​.doubleValue(ParameterDescriptor)`

  - ### doubleValueList

    public double[] doubleValueList(Unit<?> unit) throws IllegalArgumentException, IllegalStateException
    Returns an ordered sequence of numeric values in the specified unit of measure. This convenience method applies unit conversions on the fly as needed.

    The default implementation invokes `doubleValueList()` and `getUnit()`, then converts the values to the given unit of measurement.

    Specified by:
      `doubleValueList` in interface `ParameterValue<T>`
    Parameters:
      `unit` - the unit of measure for the value to be returned.
    Returns:
      the sequence of values represented by this parameter after conversion to type `double` and conversion to `unit`.
    Throws:
      `IllegalArgumentException` - if the specified unit is invalid for this parameter.
      `InvalidParameterTypeException` - if the value is not an array of `double`s.
      `IllegalStateException` - if the value is not defined and there is no default value.
    See Also:
      - `getUnit()`
      - `setValue(double[],Unit)`
      - `doubleValue(Unit)`
      - `Parameters​.doubleValueList(ParameterDescriptor)`

  - ### stringValue

    public String stringValue() throws IllegalStateException
    Returns the string value of this parameter. A string value does not have an associated unit of measure.
    Specified by:
      `stringValue` in interface `ParameterValue<T>`
    Returns:
      the string value represented by this parameter.
    Throws:
      `InvalidParameterTypeException` - if the value is not a string.
      `IllegalStateException` - if the value is not defined and there is no default value.
    See Also:
      - `getValue()`
      - `setValue(Object)`
      - `Parameters​.stringValue(ParameterDescriptor)`

  - ### valueFile

    public URI valueFile() throws IllegalStateException
    Returns a reference to a file or a part of a file containing one or more parameter values. The default implementation can convert the following value types: `URI`, `URL`, `Path`, `File`.

    #### Relative paths to absolute paths

    This parameter value is often a path relative to an unspecified directory. The base directory depends on the context. For example, it may be a directory where all datum grids are cached. Sometime, it is convenient to interpret the path as relative to the GML document or WKT file that defined this parameter value. For such resolution, see `getSourceFile()`.
    Specified by:
      `valueFile` in interface `ParameterValue<T>`
    Returns:
      the reference to a file containing parameter values.
    Throws:
      `InvalidParameterTypeException` - if the value is not a reference to a file or a URI.
      `IllegalStateException` - if the value is not defined and there is no default value.
    See Also:
      - `getValue()`
      - `setValue(Object)`

  - ### setSourceFile

    public void setSourceFile(URI document)
    Sets the URI of the GML document or WKT file from which this parameter value has been read. The given URI is a hint to be returned by `getSourceFile()` for allowing callers to resolve relative value files.
    Parameters:
      `document` - URI of the document from which this parameter value has been read, or `null` if none.
    See Also:
      - `getSourceFile()`
      - `WKTFormat​.setSourceFile(URI)`
      - `URI​.resolve(URI)`

  - ### setValue

    public void setValue(Object newValue) throws InvalidParameterValueException
    Sets the parameter value as an object. The object type is typically (but not limited to) `Double`, `double[]`, `Integer`, `int[]`, `Boolean`, `String` or `URI`. If the given value is `null`, then this parameter is set to the default value. If the given value is not an instance of the expected type, then this method may perform automatically a type conversion (for example from `Float` to `Double` or from `Path` to `URI`) if such conversion can be done without information lost.
    Specified by:
      `setValue` in interface `ParameterValue<T>`
    Parameters:
      `newValue` - the parameter value, or `null` to restore the default.
    Throws:
      `InvalidParameterValueException` - if the type of `value` is inappropriate for this parameter, or if the value is illegal for some other reason (for example the value is numeric and out of range).
    See Also:
      - `getValue()`

  - ### setValue

    public void setValue(boolean newValue) throws InvalidParameterValueException
    Sets the parameter value as a boolean.
    Specified by:
      `setValue` in interface `ParameterValue<T>`
    Parameters:
      `newValue` - the parameter value.
    Throws:
      `InvalidParameterValueException` - if the boolean type is inappropriate for this parameter.
    See Also:
      - `booleanValue()`

  - ### setValue

    public void setValue(int newValue) throws InvalidParameterValueException
    Sets the parameter value as an integer. This method automatically wraps the given integer in an object of the type specified by the descriptor if that conversion can be done without information lost.
    Specified by:
      `setValue` in interface `ParameterValue<T>`
    Parameters:
      `newValue` - the parameter value.
    Throws:
      `InvalidParameterValueException` - if the integer type is inappropriate for this parameter, or if the value is illegal for some other reason (for example a value out of range).
    See Also:
      - `intValue()`

  - ### setValue

    public void setValue(double newValue) throws InvalidParameterValueException
    Sets the parameter value as a floating point. The unit, if any, stay unchanged. This method automatically wraps the given number in an object of the type specified by the descriptor.
    Specified by:
      `setValue` in interface `ParameterValue<T>`
    Parameters:
      `newValue` - the parameter value.
    Throws:
      `InvalidParameterValueException` - if the floating point type is inappropriate for this parameter, or if the value is illegal for some other reason (for example a value out of range).
    See Also:
      - `setValue(double,Unit)`
      - `doubleValue()`

  - ### setValue

    public void setValue(double newValue, Unit<?> unit) throws InvalidParameterValueException
    Sets the parameter value as a floating point and its associated unit. This method automatically wraps the given number in an object of the type specified by the descriptor.
    Specified by:
      `setValue` in interface `ParameterValue<T>`
    Parameters:
      `newValue` - the parameter value.
      `unit` - the unit for the specified value.
    Throws:
      `InvalidParameterValueException` - if the floating point type is inappropriate for this parameter, or if the value is illegal for some other reason (for example a value out of range).
    See Also:
      - `setValue(double)`
      - `doubleValue(Unit)`

  - ### setValue

    public void setValue(double[] newValues, Unit<?> unit) throws InvalidParameterValueException
    Sets the parameter value as an array of floating point and their associated unit.
    Specified by:
      `setValue` in interface `ParameterValue<T>`
    Parameters:
      `newValues` - the parameter values.
      `unit` - the unit for the specified value.
    Throws:
      `InvalidParameterValueException` - if the floating point array type is inappropriate for this parameter, or if the value is illegal for some other reason (for example a value out of range).

  - ### setValue

    protected void setValue(Object newValue, Unit<?> unit) throws InvalidParameterValueException
    Sets the parameter value and its associated unit. If the given value is `null`, then this parameter is set to the default value. Otherwise the given value shall be an instance of the class expected by the descriptor.
    - This method does not perform any type conversion. Type conversion, if desired, should be applied by the public `setValue(…)` methods before to invoke this protected method.
    - This method does not clone the given value. In particular, references to `int[]` and `double[]` arrays are stored as-is.

    #### Implementation note for subclasses

    This method is invoked by all setter methods in this class, thus providing a single point that subclasses can override if they want to perform more processing on the value before its storage, or to be notified about value changes.
    Parameters:
      `newValue` - the parameter value, or `null` to restore the default.
      `unit` - the unit associated to the new parameter value, or `null`.
    Throws:
      `InvalidParameterValueException` - if the type of `value` is inappropriate for this parameter, or if the value is illegal for some other reason (for example the value is numeric and out of range).
    See Also:
      - `validate(Object)`

  - ### validate

    protected void validate(T newValue) throws InvalidParameterValueException
    Invoked by `setValue(Object, Unit)` after the basic verifications have been done and before the value is stored. Subclasses can override this method for performing additional verifications.

    #### Unit of measurement

    If the user specified a unit of measurement, then the value given to this method has been converted to the unit specified by the descriptor, for easier comparisons against standardized values. This converted value may be different than the value to be stored in this `ParameterValue`, since the latter value will be stored in the unit specified by the user.

    #### Standard validations

    The checks for value class, for value domain and for valid values are performed before this method is invoked. The default implementation of this method does nothing.
    Parameters:
      `newValue` - the value converted to the unit of measurement specified by the descriptor.
    Throws:
      `InvalidParameterValueException` - if the given value is invalid for implementation-specific reasons.

  - ### equals

    public boolean equals(Object object, ComparisonMode mode)
    Compares the specified object with this parameter for equality. The strictness level is controlled by the second argument.
    Specified by:
      `equals` in interface `LenientComparable`
    Parameters:
      `object` - the object to compare to `this`.
      `mode` - the strictness level of the comparison.
    Returns:
      `true` if both objects are equal according the given comparison mode.
    See Also:
      - `Utilities​.deepEquals(Object, Object, ComparisonMode)`

  - ### equals

    public final boolean equals(Object object)
    Compares the specified object with this parameter for equality. This method is implemented as below:

        return equals(other, ComparisonMode.STRICT);

    Subclasses shall override `equals(Object, ComparisonMode)` instead of this method.
    Specified by:
      `equals` in interface `LenientComparable`
    Overrides:
      `equals` in class `Object`
    Parameters:
      `object` - the object to compare to `this`.
    Returns:
      `true` if both objects are equal.
    See Also:
      - `ComparisonMode​.STRICT`

  - ### hashCode

    public int hashCode()
    Returns a hash value for this parameter. This value does not need to be the same in past or future versions of this class.
    Overrides:
      `hashCode` in class `Object`
    Returns:
      the hash code value.

  - ### clone

    public DefaultParameterValue<T> clone()
    Returns a clone of this parameter value.
    Specified by:
      `clone` in interface `GeneralParameterValue`
    Specified by:
      `clone` in interface `ParameterValue<T>`
    Overrides:
      `clone` in class `Object`
    Returns:
      A copy of this parameter value.
    See Also:
      - `DefaultParameterValue(ParameterValue)`
      - `unmodifiable(ParameterValue)`

  - ### unmodifiable

    public static <T> DefaultParameterValue<T> unmodifiable(ParameterValue<T> parameter)
    Returns an unmodifiable implementation of the given parameter value. This method shall be used only with:
    - immutable descriptor,
    - immutable or null unit, and
    - immutable or cloneable parameter value.
    If the parameter value implements the `Cloneable` interface and has a public `clone()` method, then that value will be cloned every time the `getValue()` method is invoked. The value is not cloned by this method however; it is caller's responsibility to not modify the value of the given `parameter` instance after this method call.

    #### Instances sharing

    If this method is invoked more than once with equal descriptor, value and unit, then this method will return the same `DefaultParameterValue` instance on a best effort basis. The rational for sharing is because the same parameter value is often used in many different coordinate operations. For example, all Universal Transverse Mercator (UTM) projections use the same scale factor (0.9996) and the same false easting (500000 metres).
    Type Parameters:
      `T` - the type of the value stored in the given parameter.
    Parameters:
      `parameter` - the parameter to make unmodifiable, or `null`.
    Returns:
      an unmodifiable implementation of the given parameter, or `null` if the given parameter was null.
    Since:
      0.6
    See Also:
      - `Parameters​.unmodifiable(ParameterValueGroup)`

  - ### formatTo

    protected String formatTo(Formatter formatter)
    Formats this parameter as a Well Known Text `Parameter[…]` element. Example:

        Parameter["False easting", 0.0, LengthUnit["metre", 1]]

    #### Unit of measurement

    The units of measurement were never specified in WKT 1 format, and are optional in WKT 2 format. If the units are not specified, then they are inferred from the context. Typically, parameter values that are lengths are given in the unit for the projected CRS axes while parameter values that are angles are given in the unit for the base geographic CRS.

    #### Example

    The snippet below show WKT representations of the map projection parameters of a projected CRS (most other elements are omitted). The map projection uses a Latitude of natural origin parameters which is set to 52 grads, as defined in the `UNIT[…]` element of the enclosing CRS. A similar rule applies to False easting and False northing parameters, which are in kilometres in this example.

    WKT 1:

        PROJCS[…,
          GEOGCS[…,
            UNIT[“grad”, 0.015707963267948967]],       // Unit for all angles
          PROJECTION[“Lambert_Conformal_Conic_1SP”]
          PARAMETER[“latitude_of_origin”, 52.0],       // In grads
          PARAMETER[“scale_factor”, 0.99987742],
          PARAMETER[“false_easting”, 600.0],           // In kilometres
          PARAMETER[“false_northing”, 2200.0],         // In kilometres
          UNIT[“kilometre”, 1000]]                     // Unit for all lengths

    WKT 2:

        ProjectedCRS[…
          BaseGeogCRS[…
            AngleUnit[“grad”, 0.015707963267948967]],
          Conversion[“Lambert zone II”,
            Method[“Lambert Conic Conformal (1SP)”],
            Parameter[“Latitude of natural origin”, 52.0],
            Parameter[“Scale factor at natural origin”, 0.99987742],
            Parameter[“False easting”, 600.0],
            Parameter[“False northing”, 2200.0]],
          CS[“Cartesian”, 2],
            LengthUnit[“kilometre”, 1000]]

    Specified by:
      `formatTo` in class `FormattableObject`
    Parameters:
      `formatter` - the formatter where to format the inner content of this WKT element.
    Returns:
      `"Parameter"` or `"ParameterFile"`.
    See Also:
      - `FormattableObject​.toWKT()`
      - `FormattableObject​.toString()`