blob: 094f22d871f8b40654cf1da0ff7ab0c5e7d2feff [file] [log] [blame]
/*
* JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
* Copyright (C) 2006 - JScience (http://jscience.org/)
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software is
* freely granted, provided that this notice is preserved.
*/
package javax.measure.unit;
import java.io.Serializable;
import javax.measure.converter.RationalConverter;
import javax.measure.converter.UnitConverter;
import javax.measure.quantity.Dimensionless;
/**
* <p> This class represents the dimension of an unit. Two units <code>u1</code>
* and <code>u2</code> are {@link Unit#isCompatible compatible} if and
* only if <code>(u1.getDimension().equals(u2.getDimension())))</code>
* </p>
*
* <p> Instances of this class are immutable.</p>
*
* @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
* @version 3.1, April 22, 2006
* @see <a href="http://en.wikipedia.org/wiki/Dimensional_analysis">
* Wikipedia: Dimensional Analysis</a>
*/
public final class Dimension implements Serializable {
/**
* Holds the current physical model.
*/
private static Model CurrentModel = Model.STANDARD;
/**
* Holds dimensionless.
*/
public static final Dimension NONE = new Dimension(Unit.ONE);
/**
* Holds length dimension (L).
*/
public static final Dimension LENGTH = new Dimension('L');
/**
* Holds mass dimension (M).
*/
public static final Dimension MASS = new Dimension('M');
/**
* Holds time dimension (T).
*/
public static final Dimension TIME = new Dimension('T');
/**
* Holds electric current dimension (I).
*/
public static final Dimension ELECTRIC_CURRENT = new Dimension('I');
/**
* Holds temperature dimension (θ).
*/
public static final Dimension TEMPERATURE = new Dimension('θ');
/**
* Holds amount of substance dimension (N).
*/
public static final Dimension AMOUNT_OF_SUBSTANCE = new Dimension('N');
/**
* Holds the pseudo unit associated to this dimension.
*/
private final Unit<?> _pseudoUnit;
/**
* Creates a new dimension associated to the specified symbol.
*
* @param symbol the associated symbol.
*/
public Dimension(char symbol) {
_pseudoUnit = new BaseUnit<Dimensionless>("[" + symbol + "]");
}
/**
* Creates a dimension having the specified pseudo-unit
* (base unit or product of base unit).
*
* @param pseudoUnit the pseudo-unit identifying this dimension.
*/
private Dimension(Unit<?> pseudoUnit) {
_pseudoUnit = pseudoUnit;
}
/**
* Returns the product of this dimension with the one specified.
*
* @param that the dimension multiplicand.
* @return <code>this * that</code>
*/
public final Dimension times(Dimension that) {
return new Dimension(this._pseudoUnit.times(that._pseudoUnit));
}
/**
* Returns the quotient of this dimension with the one specified.
*
* @param that the dimension divisor.
* @return <code>this / that</code>
*/
public final Dimension divide(Dimension that) {
return new Dimension(this._pseudoUnit.divide(that._pseudoUnit));
}
/**
* Returns this dimension raised to an exponent.
*
* @param n the exponent.
* @return the result of raising this dimension to the exponent.
*/
public final Dimension pow(int n) {
return new Dimension(this._pseudoUnit.pow(n));
}
/**
* Returns the given root of this dimension.
*
* @param n the root's order.
* @return the result of taking the given root of this dimension.
* @throws ArithmeticException if <code>n == 0</code>.
*/
public final Dimension root(int n) {
return new Dimension(this._pseudoUnit.root(n));
}
/**
* Returns the representation of this dimension.
*
* @return the representation of this dimension.
*/
public String toString() {
return _pseudoUnit.toString();
}
/**
* Indicates if the specified dimension is equals to the one specified.
*
* @param that the object to compare to.
* @return <code>true</code> if this dimension is equals to that dimension;
* <code>false</code> otherwise.
*/
public boolean equals(Object that) {
if (this == that)
return true;
return (that instanceof Dimension)
&& _pseudoUnit.equals(((Dimension) that)._pseudoUnit);
}
/**
* Returns the hash code for this dimension.
*
* @return this dimension hashcode value.
*/
public int hashCode() {
return _pseudoUnit.hashCode();
}
/**
* Sets the model used to determinate the units dimensions.
*
* @param model the new model to be used when calculating unit dimensions.
*/
public static void setModel(Model model) {
Dimension.CurrentModel = model;
}
/**
* Returns the model used to determinate the units dimensions
* (default {@link Model#STANDARD STANDARD}).
*
* @return the model used when calculating unit dimensions.
*/
public static Model getModel() {
return Dimension.CurrentModel;
}
/**
* This interface represents the mapping between {@link BaseUnit base units}
* and {@link Dimension dimensions}. Custom models may allow
* conversions not possible using the {@link #STANDARD standard} model.
* For example:[code]
* public static void main(String[] args) {
* Dimension.Model relativistic = new Dimension.Model() {
* RationalConverter meterToSecond = new RationalConverter(1, 299792458); // 1/c
*
* public Dimension getDimension(BaseUnit unit) {
* if (unit.equals(SI.METER)) return Dimension.TIME;
* return Dimension.Model.STANDARD.getDimension(unit);
* }
*
* public UnitConverter getTransform(BaseUnit unit) {
* if (unit.equals(SI.METER)) return meterToSecond;
* return Dimension.Model.STANDARD.getTransform(unit);
* }};
* Dimension.setModel(relativistic);
*
* // Converts 1.0 GeV (energy) to kg (mass).
* System.out.println(Unit.valueOf("GeV").getConverterTo(KILOGRAM).convert(1.0));
* }
*
* > 1.7826617302520883E-27[/code]
*/
public interface Model {
/**
* Holds the standard model (default).
*/
public Model STANDARD = new Model() {
public Dimension getDimension(BaseUnit<?> unit) {
if (unit.equals(SI.METRE)) return Dimension.LENGTH;
if (unit.equals(SI.KILOGRAM)) return Dimension.MASS;
if (unit.equals(SI.KELVIN)) return Dimension.TEMPERATURE;
if (unit.equals(SI.SECOND)) return Dimension.TIME;
if (unit.equals(SI.AMPERE)) return Dimension.ELECTRIC_CURRENT;
if (unit.equals(SI.MOLE)) return Dimension.AMOUNT_OF_SUBSTANCE;
if (unit.equals(SI.CANDELA)) return SI.WATT.getDimension();
return new Dimension(new BaseUnit<Dimensionless>("[" + unit.getSymbol() + "]"));
}
public UnitConverter getTransform(BaseUnit<?> unit) {
if (unit.equals(SI.CANDELA)) return new RationalConverter(1, 683);
return UnitConverter.IDENTITY;
}
};
/**
* Returns the dimension of the specified base unit (a dimension
* particular to the base unit if the base unit is not recognized).
*
* @param unit the base unit for which the dimension is returned.
* @return the dimension of the specified unit.
*/
Dimension getDimension(BaseUnit<?> unit);
/**
* Returns the normalization transform of the specified base unit
* ({@link UnitConverter#IDENTITY IDENTITY} if the base unit is
* not recognized).
*
* @param unit the base unit for which the transform is returned.
* @return the normalization transform.
*/
UnitConverter getTransform(BaseUnit<?> unit);
}
private static final long serialVersionUID = 1L;
}