blob: 17156f0cc43c35738409697357a4565010ec1a40 [file] [log] [blame]
/**
* Copyright (c) 2005, 2017, Werner Keil and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Werner Keil and others - initial API and implementation
*/
package org.eclipse.uomo.units.impl;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.uomo.units.AbstractConverter;
import org.eclipse.uomo.units.AbstractUnit;
import org.eclipse.uomo.units.SI;
import javax.measure.quantity.Dimensionless;
import javax.measure.Dimension;
import javax.measure.Unit;
import javax.measure.UnitConverter;
/**
* <p>
* This class represents the dimension of an unit. Two units <code>u1</code> and
* <code>u2</code> are {@linkplain 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>
* @author <a href="mailto:uomo@catmedia.us">Werner Keil</a>
*
* @version 1.0.6, $Date: 2017-12-20 $
* @see <a href="http://www.bipm.org/en/si/si_brochure/chapter1/1-3.html"> BIPM:
* SI Brochure Chapter 1.3</a>
*/
public final class DimensionImpl implements Dimension, Serializable {
/**
* For cross-version compatibility.
*/
private static final long serialVersionUID = 2377803885472362640L;
/**
* Holds the current physical model.
*/
private static Model model = Model.STANDARD;
/**
* Holds dimensionless.
*/
public static final Dimension NONE = new DimensionImpl(AbstractUnit.ONE);
/**
* Holds length dimension (L).
*/
public static final Dimension LENGTH = new DimensionImpl('L');
/**
* Holds mass dimension (M).
*/
public static final Dimension MASS = new DimensionImpl('M');
/**
* Holds time dimension (T).
*/
public static final Dimension TIME = new DimensionImpl('T');
/**
* Holds electric current dimension (I).
*/
public static final Dimension ELECTRIC_CURRENT = new DimensionImpl('I');
/**
* Holds temperature dimension (Θ). TODO use Theta again, currently not
* working (Bug 351656)
*/
public static final Dimension TEMPERATURE = new DimensionImpl('Q');
/**
* Holds amount of substance dimension (N).
*/
public static final Dimension AMOUNT_OF_SUBSTANCE = new DimensionImpl('N');
/**
* Holds luminous intensity dimension (J).
*/
public static final Dimension LUMINOUS_INTENSITY = new DimensionImpl('J');
/**
* 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.
*/
private DimensionImpl(char symbol) {
pseudoUnit = new BaseUnit<Dimensionless>("[" + symbol + "]"); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Creates a dimension having the specified pseudo-unit (base unit or
* product of base unit).
*
* @param pseudoUnit
* the pseudo-unit identifying this dimension.
*/
private DimensionImpl(Unit<?> pseudoUnit) {
this.pseudoUnit = pseudoUnit;
}
/**
* Returns the product of this dimension with the one specified.
*
* @param that
* the dimension multiplicand.
* @return <code>this * that</code>
*/
@Override
public final Dimension multiply(Dimension that) {
return new DimensionImpl(
this.pseudoUnit.multiply(((DimensionImpl) 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 DimensionImpl(
this.pseudoUnit.divide(((DimensionImpl) 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 DimensionImpl(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 DimensionImpl(this.pseudoUnit.root(n));
}
/**
* Returns the fundamental dimensions and their exponent whose product is
* this dimension or <code>null</code> if this dimension is a fundamental
* dimension.
*
* @return the mapping between the fundamental dimensions and their
* exponent.
*/
public Map<Dimension, Integer> getProductDimensions() {
if (pseudoUnit == null)
return null;
@SuppressWarnings("unchecked")
Map<? extends Unit<?>, Integer> pseudoUnits = (Map<? extends Unit<?>, Integer>) pseudoUnit
.getBaseUnits();
Map<Dimension, Integer> fundamentalDimensions = new HashMap<Dimension, Integer>();
for (Entry<? extends Unit<?>, Integer> entry : pseudoUnits.entrySet()) {
fundamentalDimensions.put(new DimensionImpl(entry.getKey()),
entry.getValue());
}
return fundamentalDimensions;
}
/**
* Returns the representation of this dimension.
*
* @return the representation of this dimension.
*/
@Override
public String toString() {
return String.valueOf(pseudoUnit);
}
/**
* 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.
*/
@Override
public boolean equals(Object that) {
if (this == that)
return true;
return (that instanceof DimensionImpl)
&& pseudoUnit.equals(((DimensionImpl) that).pseudoUnit);
}
/**
* Returns the hash code for this dimension.
*
* @return this dimension hashcode value.
*/
@Override
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) {
DimensionImpl.model = 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 DimensionImpl.model;
}
/**
* Creates a new dimension associated to the specified symbol.
*
* @param symbol
* the associated symbol.
*/
public static Dimension valueOf(char symbol) {
return new DimensionImpl(symbol);
}
/**
* This interface represents the mapping between {@linkplain BaseUnit base
* units} and {@linkplain DimensionImpl dimensions}. Custom models may allow
* conversions not possible using the {@linkplain #STANDARD standard} model.
* For example:[code] public static void main(String[] args) {
* Dimension.Model relativistic = new Dimension.Model() { RationalConverter
* metreToSecond = new RationalConverter(BigInteger.ONE,
* BigInteger.valueOf(299792458)); // 1/c
*
* public Dimension getDimension(BaseUnit unit) { if (unit.equals(METRE))
* return Dimension.TIME; return
* Dimension.Model.STANDARD.getDimension(unit); }
*
* public UnitConverter getTransform(BaseUnit unit) { if
* (unit.equals(METRE)) return metreToSecond; 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(Unit<?> unit) {
if (unit.equals(SI.METRE))
return DimensionImpl.LENGTH;
if (unit.equals(SI.KILOGRAM))
return DimensionImpl.MASS;
if (unit.equals(SI.KELVIN))
return DimensionImpl.TEMPERATURE;
if (unit.equals(SI.SECOND))
return DimensionImpl.TIME;
if (unit.equals(SI.AMPERE))
return DimensionImpl.ELECTRIC_CURRENT;
if (unit.equals(SI.MOLE))
return DimensionImpl.AMOUNT_OF_SUBSTANCE;
if (unit.equals(SI.CANDELA))
return DimensionImpl.LUMINOUS_INTENSITY;
return new DimensionImpl(new BaseUnit<Dimensionless>(
"[" + unit.getSymbol() + "]")); //$NON-NLS-1$ //$NON-NLS-2$
}
public UnitConverter getTransform(Unit<?> unit) {
return AbstractConverter.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(Unit<?> 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(Unit<?> unit);
}
@Override
public Map<? extends Dimension, Integer> getBaseDimensions() {
// TODO Auto-generated method stub
return null;
}
}