Class AbstractUnit<Q extends javax.measure.Quantity<Q>>

java.lang.Object
org.apache.sis.measure.AbstractUnit<Q>
Type Parameters:
Q - the kind of quantity to be measured using this units.
All Implemented Interfaces:
Serializable, javax.measure.Unit<Q>, LenientComparable
Direct Known Subclasses:
ConventionalUnit, SystemUnit

abstract class AbstractUnit<Q extends javax.measure.Quantity<Q>> extends Object implements javax.measure.Unit<Q>, LenientComparable, Serializable
Base class of all unit implementations. There is conceptually 4 kinds of units, but some of them are implemented by the same class:
  • Base units are the 6 or 7 SI units used as building blocks for all other units. The base units are metre, second, kilogram, Kelvin degrees, Ampere and Candela, sometimes with the addition of mole.
  • Derived units are products of base units raised to some power. For example, "m/s" is a derived units.
  • Alternate units are dimensionless units handled as if they had a dimension. An example is angular degrees.
  • Conventional units are units multiplied or shifted by a constant value compared to a base, derived or alternate unit. For example, "km" is a unit equals to 1000 metres, and"°C" is a unit shifted by 237.15 degrees compared to the Kelvin unit.
In Apache SIS implementation, base and derived units are represented by the same class: SystemUnit. All unit instances shall be immutable and thread-safe.
Since:
0.8
Version:
1.0
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    (package private) static final char
    The multiplication and division symbols used for Unicode representation.
    (package private) final short
    The EPSG code, or 0 if this unit has no EPSG code.
    private static final int
    Maximum number of multiplications or divisions in the symbol of the first unit for allowing the use of that symbol for inferring a new symbol.
    (package private) static final char
    The multiplication and division symbols used for Unicode representation.
    (package private) final byte
    A code that identifies whether this unit is part of SI system, or outside SI but accepted for use with SI.
    private static final long
    For cross-version compatibility.
    private final String
    The unit symbol, or null if this unit has no specific symbol.
  • Constructor Summary

    Constructors
    Constructor
    Description
    AbstractUnit(String symbol, byte scope, short epsg)
    Creates a new unit having the given symbol and EPSG code.
  • Method Summary

    Modifier and Type
    Method
    Description
    final javax.measure.Unit<Q>
    divide(double divisor)
    Returns the result of dividing this unit by an approximate divisor.
    private static boolean
    equals(short a, short b)
    Compares the given values only if both of them are non-zero.
    final boolean
    equals(Object other)
    Compares this unit with the given object for equality.
    boolean
    Compares this unit with the given object for equality, optionally ignoring metadata and rounding errors.
    (package private) abstract Map<SystemUnit<?>,Fraction>
    Returns the base units used by Apache SIS implementations.
    abstract Map<SystemUnit<?>,Integer>
    Returns the base units and their exponent whose product is the system unit, or null if the system unit is a base unit (not a product of existing units).
    final String
    Returns the name (if any) of this unit.
    final String
    Returns the symbol (if any) of this unit.
    abstract SystemUnit<Q>
    Returns the unscaled system unit from which this unit is derived.
    int
    Returns a hash code value for this unit.
    (package private) final String
    incompatible(javax.measure.Unit<?> that)
    Returns the error message for an incompatible unit.
    (package private) final String
    inferSymbol(char operation, javax.measure.Unit<?> other)
    Infers a symbol for a unit resulting from an arithmetic operation between two units.
    (package private) final <R extends javax.measure.Quantity<R>>
    javax.measure.Unit<R>
    inferSymbol(javax.measure.Unit<R> result, char operation, javax.measure.Unit<?> other)
    If the result unit is a ConventionalUnit with no symbol, tries to infer a symbol for it.
    (package private) static int
    invalidCharForSymbol(String symbol, int maxMultiply, boolean allowExponents)
    If the given symbol contains an invalid character for a unit symbol, returns the character code point.
    final javax.measure.Unit<?>
    Returns the inverse of this unit.
    private static double
    inverse(double multiplier)
    If the inverse of the given multiplier is an integer, returns that inverse.
    final boolean
    isCompatible(javax.measure.Unit<?> that)
    Indicates if this unit is compatible with the given unit.
    (package private) final boolean
    Returns true if the use of SI prefixes is allowed for this unit.
    (package private) static boolean
    isPrefixable(javax.measure.Unit<?> unit)
    Returns true if the use of SI prefixes is allowed for the given unit.
    (package private) static boolean
    isSymbolChar(int c)
    Returns true if the given Unicode code point is a valid character for a unit symbol.
    private static boolean
    isValidSymbol(String symbol, boolean allowExponents, boolean allowMultiply)
    Returns true if the given unit symbol is valid.
    final javax.measure.Unit<Q>
    multiply(double multiplier)
    Returns the result of multiplying this unit by the specified factor.
    (package private) final Object
    Invoked on deserialization for returning a unique instance of AbstractUnit if possible.
    (package private) ConventionalUnit<Q>[]
    Returns units for the same quantity but with scale factors that are not the SI one, or null if none.
    final javax.measure.Unit<Q>
    shift(double offset)
    Returns the result of setting the origin of the scale of measurement to the given value.
    final String
    Returns the unlocalized string representation of this unit, either as a single symbol or a product of symbols or scale factors, eventually with an offset.

    Methods inherited from class java.lang.Object

    clone, finalize, getClass, notify, notifyAll, wait, wait, wait

    Methods inherited from interface javax.measure.Unit

    alternate, asType, divide, getConverterTo, getConverterToAny, getDimension, multiply, pow, root, transform
  • Field Details

    • serialVersionUID

      private static final long serialVersionUID
      For cross-version compatibility.
      See Also:
    • MULTIPLY

      static final char MULTIPLY
      The multiplication and division symbols used for Unicode representation. Also used for internal representation of symbol.
      See Also:
    • DIVIDE

      static final char DIVIDE
      The multiplication and division symbols used for Unicode representation. Also used for internal representation of symbol.
      See Also:
    • MAX_OPERATIONS_IN_SYMBOL

      private static final int MAX_OPERATIONS_IN_SYMBOL
      Maximum number of multiplications or divisions in the symbol of the first unit for allowing the use of that symbol for inferring a new symbol.
      See Also:
    • symbol

      private final String symbol
      The unit symbol, or null if this unit has no specific symbol. If null, then the toString() method is responsible for creating a representation on the fly. If non-null, this symbol should complies with the UnitFormat.Style.SYMBOL formatting (not the UCUM format). In particular, this symbol uses Unicode characters for arithmetic operators and superscripts, as in “m/s²”. However, this symbol should never contains the unit conversion terms. For example, “km” is okay, but “1000⋅m” is not. The intent of those rules is to make easier to analyze the symbol in methods like ConventionalUnit.power(String).

      Users can override this symbol by call to UnitFormat.label(Unit, String), but such overriding applies only to the target UnitFormat instance.

      The value assigned to this field is also used by getName() for fetching a localized name from the resource bundle.

      See Also:
    • scope

      final transient byte scope
      A code that identifies whether this unit is part of SI system, or outside SI but accepted for use with SI. Value can be UnitRegistry.SI, UnitRegistry.ACCEPTED, other constants or 0 if unknown.

      This information may be approximate since we cannot always guess correctly whether the result of an operation is part of SI or not. Values given to the field may be adjusted in any future version.

      This information is not serialized because readResolve() will replace the deserialized instance by a hard-coded instance with appropriate value, if possible.

      See Also:
    • epsg

      final transient short epsg
      The EPSG code, or 0 if this unit has no EPSG code.

      This information is not serialized because readResolve() will replace the deserialized instance by a hard-coded instance with appropriate value, if possible.

      See Also:
  • Constructor Details

    • AbstractUnit

      AbstractUnit(String symbol, byte scope, short epsg)
      Creates a new unit having the given symbol and EPSG code.
      Parameters:
      symbol - the unit symbol, or null if this unit has no specific symbol.
      scope - UnitRegistry.SI, UnitRegistry.ACCEPTED, other constants or 0 if unknown.
      epsg - the EPSG code, or 0 if this unit has no EPSG code.
  • Method Details

    • isPrefixable

      static boolean isPrefixable(javax.measure.Unit<?> unit)
      Returns true if the use of SI prefixes is allowed for the given unit.
    • isPrefixable

      final boolean isPrefixable()
      Returns true if the use of SI prefixes is allowed for this unit.
    • isSymbolChar

      static boolean isSymbolChar(int c)
      Returns true if the given Unicode code point is a valid character for a unit symbol. Current implementation accepts letters, subscripts and the degree sign, but the set of legal characters may be expanded in any future SIS version (however it should never allow spaces). The goal is to avoid confusion with exponents and to detect where a unit symbol ends.

      Space characters must be excluded from the set of legal characters because allowing them would make harder for UnitFormat to detect correctly where a unit symbol ends.

      Note that some units defined in the Units class break this rule. In particular, some of those units contains superscripts or division sign. But the hard-coded symbols in that class are known to be consistent with SI usage or with UnitFormat work.

    • isValidSymbol

      private static boolean isValidSymbol(String symbol, boolean allowExponents, boolean allowMultiply)
      Returns true if the given unit symbol is valid.
      Parameters:
      symbol - the symbol to verify for validity.
      allowExponents - whether to accept also exponent characters.
      allowMultiply - whether to accept a few multiplications.
      Returns:
      true if the given symbol is valid.
    • invalidCharForSymbol

      static int invalidCharForSymbol(String symbol, int maxMultiply, boolean allowExponents)
      If the given symbol contains an invalid character for a unit symbol, returns the character code point. Otherwise if the given symbol is null or empty, returns -2. Otherwise (the symbol is valid) returns -1.

      The check for valid symbols can be relaxed, for example when building a new symbol from existing units. For example, we may want to accept "W" and "m²" as valid symbols for deriving "W∕m²" without being rejected because of the "²" in "m²". We do not want to relax too much however, because a long sequence of arithmetic operations would result in a long and maybe meaningless unit symbol, while declaring "no symbol" would allow UnitFormat to create a new one from the base units. The criterion for accepting a symbol or not (for example how many multiplications) is arbitrary.

      Parameters:
      symbol - the symbol to verify for invalid characters.
      maxMultiply - maximal number of multiplication symbol to accept.
      allowExponents - whether to accept also exponent characters.
      Returns:
      Unicode code point of the invalid character, or a negative value.
    • inferSymbol

      final String inferSymbol(char operation, javax.measure.Unit<?> other)
      Infers a symbol for a unit resulting from an arithmetic operation between two units. The left operand is this unit and the right operand is the other unit.
      Parameters:
      operation - MULTIPLY, DIVIDE or an exponent.
      other - the left operand used in the operation, or null if operation is an exponent.
      Returns:
      the symbol for the operation result, or null if no suggestion.
    • inferSymbol

      final <R extends javax.measure.Quantity<R>> javax.measure.Unit<R> inferSymbol(javax.measure.Unit<R> result, char operation, javax.measure.Unit<?> other)
      If the result unit is a ConventionalUnit with no symbol, tries to infer a symbol for it. Otherwise returns result unchanged.
      Parameters:
      result - the result of an arithmetic operation.
      operation - MULTIPLY, DIVIDE or an exponent.
      other - the left operand used in the operation, or null if operation is an exponent.
      Returns:
      result or an equivalent unit augmented with a symbol.
    • getSymbol

      public final String getSymbol()
      Returns the symbol (if any) of this unit. A unit may have no symbol, in which case the toString() method is responsible for creating a string representation.
      Example: Units.METRE has the "m" symbol and the same string representation. But Units.METRES_PER_SECOND has no symbol; it has only the "m/s" string representation.
      Specified by:
      getSymbol in interface javax.measure.Unit<Q extends javax.measure.Quantity<Q>>
      Returns:
      the unit symbol, or null if this unit has no specific symbol.
      See Also:
    • getName

      public final String getName()
      Returns the name (if any) of this unit. For example, Units.METRE has the "m" symbol and the "metre" name. If this unit exists in the EPSG database, then this method should return the name as specified in the database.
      Specified by:
      getName in interface javax.measure.Unit<Q extends javax.measure.Quantity<Q>>
      Returns:
      the unit name, or null if this unit has no specific name.
      See Also:
    • getSystemUnit

      public abstract SystemUnit<Q> getSystemUnit()
      Returns the unscaled system unit from which this unit is derived. System units are either base units, alternate units or product of rational powers of system units.
      Specified by:
      getSystemUnit in interface javax.measure.Unit<Q extends javax.measure.Quantity<Q>>
      Returns:
      the system unit this unit is derived from, or this if this unit is a system unit.
    • getBaseUnits

      public abstract Map<SystemUnit<?>,Integer> getBaseUnits()
      Returns the base units and their exponent whose product is the system unit, or null if the system unit is a base unit (not a product of existing units).
      Specified by:
      getBaseUnits in interface javax.measure.Unit<Q extends javax.measure.Quantity<Q>>
      Returns:
      the base units and their exponent making up the system unit.
    • getBaseSystemUnits

      abstract Map<SystemUnit<?>,Fraction> getBaseSystemUnits()
      Returns the base units used by Apache SIS implementations. Contrarily to getBaseUnits(), this method never returns null.
    • isCompatible

      public final boolean isCompatible(javax.measure.Unit<?> that)
      Indicates if this unit is compatible with the given unit. This implementation delegates to:
      Specified by:
      isCompatible in interface javax.measure.Unit<Q extends javax.measure.Quantity<Q>>
      Parameters:
      that - the other unit to compare for compatibility.
      Returns:
      true if the given unit is compatible with this unit.
      See Also:
      • Unit.getDimension()
    • incompatible

      final String incompatible(javax.measure.Unit<?> that)
      Returns the error message for an incompatible unit.
    • shift

      public final javax.measure.Unit<Q> shift(double offset)
      Returns the result of setting the origin of the scale of measurement to the given value. For example, CELSIUS = KELVIN.shift(273.15) returns a unit where 0°C is equal to 273.15 K.
      Specified by:
      shift in interface javax.measure.Unit<Q extends javax.measure.Quantity<Q>>
      Parameters:
      offset - the value to add when converting from the new unit to this unit.
      Returns:
      this unit offset by the specified value, or this if the given offset is zero.
    • multiply

      public final javax.measure.Unit<Q> multiply(double multiplier)
      Returns the result of multiplying this unit by the specified factor. For example, KILOMETRE = METRE.multiply(1000) returns a unit where 1 km is equal to 1000 m.
      Specified by:
      multiply in interface javax.measure.Unit<Q extends javax.measure.Quantity<Q>>
      Parameters:
      multiplier - the scale factor when converting from the new unit to this unit.
      Returns:
      this unit scaled by the specified multiplier.
    • divide

      public final javax.measure.Unit<Q> divide(double divisor)
      Returns the result of dividing this unit by an approximate divisor. For example, GRAM = KILOGRAM.divide(1000) returns a unit where 1 g is equal to 0.001 kg.
      Specified by:
      divide in interface javax.measure.Unit<Q extends javax.measure.Quantity<Q>>
      Parameters:
      divisor - the inverse of the scale factor when converting from the new unit to this unit.
      Returns:
      this unit divided by the specified divisor.
    • inverse

      private static double inverse(double multiplier)
      If the inverse of the given multiplier is an integer, returns that inverse. Otherwise returns 1. This method is used for replacing e.g. multiply(0.001) calls by divide(1000) calls. The latter allows more accurate operations because of the way LinearConverter is implemented.
    • inverse

      public final javax.measure.Unit<?> inverse()
      Returns the inverse of this unit.
      Specified by:
      inverse in interface javax.measure.Unit<Q extends javax.measure.Quantity<Q>>
      Returns:
      1 / this
    • related

      ConventionalUnit<Q>[] related()
      Returns units for the same quantity but with scale factors that are not the SI one, or null if none. This method returns a direct reference to the internal field; caller shall not modify.
    • equals

      public final boolean equals(Object other)
      Compares this unit with the given object for equality.
      Specified by:
      equals in interface LenientComparable
      Overrides:
      equals in class Object
      Parameters:
      other - the other object to compare with this unit, or null.
      Returns:
      true if the given object is equal to this unit.
      See Also:
    • equals

      public boolean equals(Object other, ComparisonMode mode)
      Compares this unit with the given object for equality, optionally ignoring metadata and rounding errors.
      Specified by:
      equals in interface LenientComparable
      Parameters:
      other - 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:
    • equals

      private static boolean equals(short a, short b)
      Compares the given values only if both of them are non-zero. If at least one value is zero (meaning "unknown"), assume that values are equal. We do that because deserialized AbstractUnit instances have epsg and scope fields initialized to 0, and we need to ignore those values when comparing the deserialized instances with instances hard-coded in Units class. We should not have inconsistencies because there is no public way to set those fields; they can only be defined in the Units hard-coded constants.
    • hashCode

      public int hashCode()
      Returns a hash code value for this unit.
      Overrides:
      hashCode in class Object
    • toString

      public final String toString()
      Returns the unlocalized string representation of this unit, either as a single symbol or a product of symbols or scale factors, eventually with an offset.
      Specified by:
      toString in interface javax.measure.Unit<Q extends javax.measure.Quantity<Q>>
      Overrides:
      toString in class Object
      See Also:
    • readResolve

      final Object readResolve() throws ObjectStreamException
      Invoked on deserialization for returning a unique instance of AbstractUnit if possible.
      Throws:
      ObjectStreamException