All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ucar.units.DerivedUnitImpl Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 1998-2018 University Corporation for Atmospheric Research/Unidata
 * See LICENSE for license information.
 */
package ucar.units;

/**
 * Provides support for a concrete implementation of derived units.
 * 
 * @author Steven R. Emmerson
 */
// @Immutable
public class DerivedUnitImpl extends UnitImpl implements DerivedUnit, DerivableUnit {
  private static final long serialVersionUID = 1L;

  /**
   * The dimensionless derived unit.
   */
  public static final DerivedUnitImpl DIMENSIONLESS = new DerivedUnitImpl();

  /**
   * The dimension of this derived unit.
   * 
   * @serial
   */
  private /* final */ UnitDimension dimension;

  /**
   * Constructs a dimensionless derived unit from nothing.
   */
  protected DerivedUnitImpl() {
    // dimensionless derived unit
    this(new UnitDimension(), dimensionlessID());
  }

  /**
   * Returns the identifiers associated with the dimensionless, derived unit.
   * 
   * @return The identifiers of the dimensionless, derived unit.
   */
  private static UnitName dimensionlessID() {
    UnitName id;
    try {
      id = UnitName.newUnitName("1", "1", "1");
    } catch (final NameException e) {
      id = null;
    }
    return id;
  }

  /**
   * Constructs from a unit dimension. This is a trusted constructor for use
   * by subclasses only.
   * 
   * @param dimension
   *        The unit dimension.
   */
  protected DerivedUnitImpl(final UnitDimension dimension) {
    this(dimension, null);
  }

  /**
   * Constructs from identifiers. This is a trusted constructor for use by
   * subclasses only.
   * 
   * @param id
   *        The identifiers for the unit.
   */
  protected DerivedUnitImpl(final UnitName id) {
    this(null, id);
  }

  /**
   * Constructs from a unit dimension and identifiers. This is a trusted
   * constructor for use by subclasses only.
   * 
   * @param dimension
   *        The unit dimension.
   * @param id
   *        The identifiers for the unit.
   */
  protected DerivedUnitImpl(final UnitDimension dimension, final UnitName id) {
    super(id);
    this.dimension = dimension;
  }

  /**
   * Sets the unit dimension of this derived unit. This is a trusted method
   * for use by subclasses only and should be called only once immediately
   * after construction of this superinstance.
   * 
   * @param dimension
   *        The unit dimension.
   */
  protected void setDimension(final UnitDimension dimension) {
    this.dimension = dimension;
  }

  /**
   * Returns the unit dimension of this derived unit.
   * 
   * @return The unit dimension of this derived unit.
   */
  public final UnitDimension getDimension() {
    return dimension;
  }

  /**
   * Returns the quantity dimension of this derived unit.
   * 
   * @return The quantity dimension of this derived unit.
   */
  public final QuantityDimension getQuantityDimension() {
    return getDimension().getQuantityDimension();
  }

  /*
   * From DerivedUnit:
   */

  /**
   * Indicates if this derived unit is the reciprocal of another derived unit
   * (e.g. "second" and "hertz").
   * 
   * @param that
   *        The other, derived unit.
   */
  public final boolean isReciprocalOf(final DerivedUnit that) {
    return dimension.isReciprocalOf(that.getDimension());
  }

  /*
   * From UnitImpl:
   */

  /**
   * Returns the derived unit that is convertible with this unit. Obviously,
   * the method returns this derived unit.
   * 
   * @return this.
   */
  public final DerivedUnit getDerivedUnit() {
    return this;
  }

  /**
   * Clones the derived unit changing the identifiers.
   * 
   * @param id
   *        The identifiers for the new unit.
   * @return The new unit.
   */
  public final Unit clone(final UnitName id) {
    return new DerivedUnitImpl(dimension, id);
  }

  /**
   * Multiplies this derived unit by another.
   * 
   * @param that
   *        The other unit.
   * @return The product of the two units.
   * @throws MultiplyException
   *         Can't multiply these units.
   */
  @Override
  protected Unit myMultiplyBy(final Unit that) throws MultiplyException {
    Unit result;
    if (dimension.getRank() == 0) {
      result = that;
    } else {
      if (!(that instanceof DerivedUnit)) {
        result = that.multiplyBy(this);
      } else {
        final UnitDimension thatDimension = ((DerivedUnit) that).getDimension();
        result = thatDimension.getRank() == 0 ? this : new DerivedUnitImpl(dimension.multiplyBy(thatDimension));
      }
    }
    return result;
  }

  /**
   * Divides this derived unit by another.
   * 
   * @param that
   *        The other unit.
   * @return The quotient of the two units.
   * @throws OperationException
   *         Can't divide these units.
   */
  @Override
  protected Unit myDivideBy(final Unit that) throws OperationException {
    Unit result;
    if (dimension.getRank() == 0) {
      result = that.raiseTo(-1);
    } else {
      if (!(that instanceof DerivedUnit)) {
        result = that.divideInto(this);
      } else {
        final UnitDimension thatDimension = ((DerivedUnit) that).getDimension();
        result = thatDimension.getRank() == 0 ? this : new DerivedUnitImpl(dimension.divideBy(thatDimension));
      }
    }
    return result;
  }

  /**
   * Divides this derived unit into another.
   * 
   * @param that
   *        The other unit.
   * @return The quotient of the two units.
   * @throws OperationException
   *         Can't divide these units.
   */
  @Override
  protected Unit myDivideInto(final Unit that) throws OperationException {
    return that.divideBy(this);
  }

  /**
   * Raises this derived unit to a power.
   * 
   * @param power
   *        The power.
   * @return This derived unit raised to the given power.
   */
  @Override
  protected Unit myRaiseTo(final int power) {
    return power == 1 ? this : new DerivedUnitImpl(dimension.raiseTo(power));
  }

  /**
   * Converts a numerical value from this unit to the derived unit. Obviously,
   * the numerical value is unchanged.
   * 
   * @param amount
   *        The numerical values in this unit.
   * @return The numerical value in the derived unit.
   */
  public final float toDerivedUnit(final float amount) {
    return amount;
  }

  /**
   * Converts a numerical value from this unit to the derived unit. Obviously,
   * the numerical value is unchanged.
   * 
   * @param amount
   *        The numerical values in this unit.
   * @return The numerical value in the derived unit.
   */
  public final double toDerivedUnit(final double amount) {
    return amount;
  }

  /**
   * Converts numerical values from this unit to the derived unit. Obviously,
   * the numerical values are unchanged.
   * 
   * @param input
   *        The numerical values in this unit.
   * @param output
   *        The numerical values in the derived unit. May be the same
   *        array as input.
   * @return output.
   */
  public final float[] toDerivedUnit(final float[] input, final float[] output) {
    if (input != output) {
      System.arraycopy(input, 0, output, 0, input.length);
    }
    return output;
  }

  /**
   * Converts numerical values from this unit to the derived unit. Obviously,
   * the numerical values are unchanged.
   * 
   * @param input
   *        The numerical values in this unit.
   * @param output
   *        The numerical values in the derived unit. May be the same
   *        array as input.
   * @return output.
   */
  public final double[] toDerivedUnit(final double[] input, final double[] output) {
    if (input != output) {
      System.arraycopy(input, 0, output, 0, input.length);
    }
    return output;
  }

  /**
   * Converts a numerical value to this unit from the derived unit. Obviously,
   * the numerical value is unchanged.
   * 
   * @param amount
   *        The numerical values in the derived unit.
   * @return The numerical value in this unit.
   */
  public final float fromDerivedUnit(final float amount) {
    return amount;
  }

  /**
   * Converts a numerical value to this unit from the derived unit. Obviously,
   * the numerical value is unchanged.
   * 
   * @param amount
   *        The numerical values in the derived unit.
   * @return The numerical value in this unit.
   */
  public final double fromDerivedUnit(final double amount) {
    return amount;
  }

  /**
   * Converts numerical values to this unit from the derived unit. Obviously,
   * the numerical values are unchanged.
   * 
   * @param input
   *        The numerical values in the derived unit.
   * @param output
   *        The numerical values in this unit. May be the same array as
   *        input.
   * @return output.
   */
  public final float[] fromDerivedUnit(final float[] input, final float[] output) {
    return toDerivedUnit(input, output);
  }

  /**
   * Converts numerical values to this unit from the derived unit. Obviously,
   * the numerical values are unchanged.
   * 
   * @param input
   *        The numerical values in the derived unit.
   * @param output
   *        The numerical values in this unit. May be the same array as
   *        input.
   * @return output.
   */
  public final double[] fromDerivedUnit(final double[] input, final double[] output) {
    return toDerivedUnit(input, output);
  }

  /**
   * Indicates if values in this unit are convertible with another unit.
   * 
   * @param that
   *        The other unit.
   * @return true if and only if values in this unit are
   *         convertible to values in 
   *        that.
   */
  @Override
  public final boolean isCompatible(final Unit that) {
    final DerivedUnit unit = that.getDerivedUnit();
    return equals(unit) || isReciprocalOf(unit);
  }

  /**
   * Indicates if this derived unit is semantically identical to an object.
   * 
   * @param object
   *        The object
   * @return true if and only if this derived unit is
   *         semantically identical to 
   *        object.
   */
  @Override
  public boolean equals(final Object object) {
    if (this == object) {
      return true;
    }
    if (!(object instanceof DerivedUnit)) {
      return false;
    }
    final DerivedUnit that = (DerivedUnit) object;
    return (!(this instanceof BaseUnit) || !(that instanceof BaseUnit)) && dimension.equals(that.getDimension());
  }

  /**
   * Returns the hash code of this instance.
   * 
   * @return The hash code of this instance.
   */
  @Override
  public int hashCode() {
    return this instanceof BaseUnit ? System.identityHashCode(this) : dimension.hashCode();
  }

  /**
   * Indicates if this derived unit is dimensionless.
   * 
   * @return true if and only if this derived unit is
   *         dimensionless.
   */
  public boolean isDimensionless() {
    return dimension.isDimensionless();
  }

  /**
   * Returns a string representation of this unit. If the symbol or name is
   * available, then that is returned; otherwise, the corresponding expression
   * in base units is returned.
   * 
   * @return The string expression for this derived unit.
   */
  @Override
  public String toString() {
    final String string = super.toString(); // get symbol or name
    return string != null ? string : getCanonicalString();
  }

  /**
   * Returns the canonical string representation of the unit.
   * 
   * @return The canonical string representation.
   */
  public String getCanonicalString() {
    return dimension.toString();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy