001:/*
002: * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
003: * Copyright (C) 2006 - JScience (http://jscience.org/)
004: * All rights reserved.
005: *
006: * Permission to use, copy, modify, and distribute this software is
007: * freely granted, provided that this notice is preserved.
008: */
009:package javax.measure.unit;
010:
011:import java.io.Serializable;
012:
013:import javax.measure.converter.RationalConverter;
014:import javax.measure.converter.UnitConverter;
015:import javax.measure.quantity.Dimensionless;
016:
017:/**
018: * <p> This class represents the dimension of an unit. Two units <code>u1</code>
019: * and <code>u2</code> are {@link Unit#isCompatible compatible} if and
020: * only if <code>(u1.getDimension().equals(u2.getDimension())))</code>
021: * </p>
022: *
023: * <p> Instances of this class are immutable.</p>
024: *
025: * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
026: * @version 3.1, April 22, 2006
027: * @see <a href="http://en.wikipedia.org/wiki/Dimensional_analysis">
028: * Wikipedia: Dimensional Analysis</a>
029: */
030:public final class Dimension implements Serializable {
031:
032: /**
033: * Holds the current physical model.
034: */
035: private static Model CurrentModel = Model.STANDARD;
036:
037: /**
038: * Holds dimensionless.
039: */
040: public static final Dimension NONE = new Dimension(Unit.ONE);
041:
042: /**
043: * Holds length dimension (L).
044: */
045: public static final Dimension LENGTH = new Dimension('L');
046:
047: /**
048: * Holds mass dimension (M).
049: */
050: public static final Dimension MASS = new Dimension('M');
051:
052: /**
053: * Holds time dimension (T).
054: */
055: public static final Dimension TIME = new Dimension('T');
056:
057: /**
058: * Holds electric current dimension (I).
059: */
060: public static final Dimension ELECTRIC_CURRENT = new Dimension('I');
061:
062: /**
063: * Holds temperature dimension (θ).
064: */
065: public static final Dimension TEMPERATURE = new Dimension('θ');
066:
067: /**
068: * Holds amount of substance dimension (N).
069: */
070: public static final Dimension AMOUNT_OF_SUBSTANCE = new Dimension('N');
071:
072: /**
073: * Holds the pseudo unit associated to this dimension.
074: */
075: private final Unit<?> _pseudoUnit;
076:
077: /**
078: * Creates a new dimension associated to the specified symbol.
079: *
080: * @param symbol the associated symbol.
081: */
082: public Dimension(char symbol) {
083: _pseudoUnit = new BaseUnit<Dimensionless>("[" + symbol + "]");
084: }
085:
086: /**
087: * Creates a dimension having the specified pseudo-unit
088: * (base unit or product of base unit).
089: *
090: * @param pseudoUnit the pseudo-unit identifying this dimension.
091: */
092: private Dimension(Unit<?> pseudoUnit) {
093: _pseudoUnit = pseudoUnit;
094: }
095:
096: /**
097: * Returns the product of this dimension with the one specified.
098: *
099: * @param that the dimension multiplicand.
100: * @return <code>this * that</code>
101: */
102: public final Dimension times(Dimension that) {
103: return new Dimension(this ._pseudoUnit.times(that._pseudoUnit));
104: }
105:
106: /**
107: * Returns the quotient of this dimension with the one specified.
108: *
109: * @param that the dimension divisor.
110: * @return <code>this / that</code>
111: */
112: public final Dimension divide(Dimension that) {
113: return new Dimension(this ._pseudoUnit.divide(that._pseudoUnit));
114: }
115:
116: /**
117: * Returns this dimension raised to an exponent.
118: *
119: * @param n the exponent.
120: * @return the result of raising this dimension to the exponent.
121: */
122: public final Dimension pow(int n) {
123: return new Dimension(this ._pseudoUnit.pow(n));
124: }
125:
126: /**
127: * Returns the given root of this dimension.
128: *
129: * @param n the root's order.
130: * @return the result of taking the given root of this dimension.
131: * @throws ArithmeticException if <code>n == 0</code>.
132: */
133: public final Dimension root(int n) {
134: return new Dimension(this ._pseudoUnit.root(n));
135: }
136:
137: /**
138: * Returns the representation of this dimension.
139: *
140: * @return the representation of this dimension.
141: */
142: public String toString() {
143: return _pseudoUnit.toString();
144: }
145:
146: /**
147: * Indicates if the specified dimension is equals to the one specified.
148: *
149: * @param that the object to compare to.
150: * @return <code>true</code> if this dimension is equals to that dimension;
151: * <code>false</code> otherwise.
152: */
153: public boolean equals(Object that) {
154: if (this == that)
155: return true;
156: return (that instanceof Dimension)
157: && _pseudoUnit.equals(((Dimension) that)._pseudoUnit);
158: }
159:
160: /**
161: * Returns the hash code for this dimension.
162: *
163: * @return this dimension hashcode value.
164: */
165: public int hashCode() {
166: return _pseudoUnit.hashCode();
167: }
168:
169: /**
170: * Sets the model used to determinate the units dimensions.
171: *
172: * @param model the new model to be used when calculating unit dimensions.
173: */
174: public static void setModel(Model model) {
175: Dimension.CurrentModel = model;
176: }
177:
178: /**
179: * Returns the model used to determinate the units dimensions
180: * (default {@link Model#STANDARD STANDARD}).
181: *
182: * @return the model used when calculating unit dimensions.
183: */
184: public static Model getModel() {
185: return Dimension.CurrentModel;
186: }
187:
188: /**
189: * This interface represents the mapping between {@link BaseUnit base units}
190: * and {@link Dimension dimensions}. Custom models may allow
191: * conversions not possible using the {@link #STANDARD standard} model.
192: * For example:[code]
193: * public static void main(String[] args) {
194: * Dimension.Model relativistic = new Dimension.Model() {
195: * RationalConverter meterToSecond = new RationalConverter(1, 299792458); // 1/c
196: *
197: * public Dimension getDimension(BaseUnit unit) {
198: * if (unit.equals(SI.METER)) return Dimension.TIME;
199: * return Dimension.Model.STANDARD.getDimension(unit);
200: * }
201: *
202: * public UnitConverter getTransform(BaseUnit unit) {
203: * if (unit.equals(SI.METER)) return meterToSecond;
204: * return Dimension.Model.STANDARD.getTransform(unit);
205: * }};
206: * Dimension.setModel(relativistic);
207: *
208: * // Converts 1.0 GeV (energy) to kg (mass).
209: * System.out.println(Unit.valueOf("GeV").getConverterTo(KILOGRAM).convert(1.0));
210: * }
211: *
212: * > 1.7826617302520883E-27[/code]
213: */
214: public interface Model {
215:
216: /**
217: * Holds the standard model (default).
218: */
219: public Model STANDARD = new Model() {
220:
221: public Dimension getDimension(BaseUnit<?> unit) {
222: if (unit.equals(SI.METRE)) return Dimension.LENGTH;
223: if (unit.equals(SI.KILOGRAM)) return Dimension.MASS;
224: if (unit.equals(SI.KELVIN)) return Dimension.TEMPERATURE;
225: if (unit.equals(SI.SECOND)) return Dimension.TIME;
226: if (unit.equals(SI.AMPERE)) return Dimension.ELECTRIC_CURRENT;
227: if (unit.equals(SI.MOLE)) return Dimension.AMOUNT_OF_SUBSTANCE;
228: if (unit.equals(SI.CANDELA)) return SI.WATT.getDimension();
229: return new Dimension(new BaseUnit<Dimensionless>("[" + unit.getSymbol() + "]"));
230: }
231:
232: public UnitConverter getTransform(BaseUnit<?> unit) {
233: if (unit.equals(SI.CANDELA)) return new RationalConverter(1, 683);
234: return UnitConverter.IDENTITY;
235: }
236: };
237:
238: /**
239: * Returns the dimension of the specified base unit (a dimension
240: * particular to the base unit if the base unit is not recognized).
241: *
242: * @param unit the base unit for which the dimension is returned.
243: * @return the dimension of the specified unit.
244: */
245: Dimension getDimension(BaseUnit<?> unit);
246:
247: /**
248: * Returns the normalization transform of the specified base unit
249: * ({@link UnitConverter#IDENTITY IDENTITY} if the base unit is
250: * not recognized).
251: *
252: * @param unit the base unit for which the transform is returned.
253: * @return the normalization transform.
254: */
255: UnitConverter getTransform(BaseUnit<?> unit);
256: }
257:
258: private static final long serialVersionUID = 1L;
259:}
|