KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > osgi > util > measurement > Unit


1 /*
2  * $Header: /cvshome/build/org.osgi.util.measurement/src/org/osgi/util/measurement/Unit.java,v 1.15 2006/06/16 16:31:34 hargrave Exp $
3  *
4  * Copyright (c) OSGi Alliance (2002, 2006). All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18 package org.osgi.util.measurement;
19
20 import java.util.Hashtable JavaDoc;
21
22 /**
23  * A unit system for measurements.
24  *
25  * This class contains definitions of the most common SI units.
26  * <p>
27  *
28  * <p>
29  * This class only support exponents for the base SI units in the range -64 to
30  * +63. Any operation which produces an exponent outside of this range will
31  * result in a <code>Unit</code> object with undefined exponents.
32  *
33  * @version $Revision: 1.15 $
34  */

35 /*
36  * This local class maintains the information about units. It can calculate new
37  * units when two values are multiplied, divided, added or subtracted. <p> The
38  * unit works with the 7 basic SI types + rad + up to 2^6 custom types. For each
39  * type, the unit keeps a bit mask with the exponents of the basic types. Eg.
40  * m/s is m = 1, s = -1. Multiplying one unit with another means that the bit
41  * masks are added, dividing means that the bit masks are subtracted. <p> This
42  * class can handle any reasonable combination of SI units. However, it will
43  * always try to coerce results back into the basic set. E.g. when you do V*A
44  * you should get W and not m2.kg/s3 . Only when the existing types do not match
45  * does the unit fallback to the expanded form. <p> This class uses offset
46  * arithmetic. This means that the exponents are stored in an long. The special
47  * field is used for units that should not be arithmetically divided or
48  * multiplied, like longitude and lattitude. These special units can however, be
49  * divided and multiplied by the basic 7 constants of the SI, e.g. deg/s.
50  */

51 public class Unit {
52     private final static long UNITY = createType(0, 0, 0, 0, 0, 0, 0,
53                                                     0, 0);
54     private final static long ZERO = 0x40L;
55     private final static long MASK = 0x7fL;
56     private final static int m_SHIFT = 0;
57     private final static int s_SHIFT = 7;
58     private final static int kg_SHIFT = 14;
59     private final static int K_SHIFT = 21;
60     private final static int A_SHIFT = 28;
61     private final static int mol_SHIFT = 35;
62     private final static int cd_SHIFT = 42;
63     private final static int rad_SHIFT = 49;
64     private final static int x_SHIFT = 56;
65     private final static long x_MASK = MASK << x_SHIFT;
66     /** No Unit (Unity) */
67     public final static Unit unity = new Unit("", UNITY); // Unity
68
/* SI Base Units */
69     /** The length unit meter (m) */
70     public final static Unit m = new Unit("m", createType(0, 0, 0,
71                                                     0, 0, 0, 0, 0, 1)); // Distance
72
// meter
73
/** The time unit second (s) */
74     public final static Unit s = new Unit("s", createType(0, 0, 0,
75                                                     0, 0, 0, 0, 1, 0)); // Time
76
// Seconds
77
// s
78
/** The mass unit kilogram (kg) */
79     public final static Unit kg = new Unit("kg", createType(0, 0,
80                                                     0, 0, 0, 0, 1, 0, 0)); // Mass
81
// kilogram
82
// kg
83
/** The temperature unit kelvin (K) */
84     public final static Unit K = new Unit("K", createType(0, 0, 0,
85                                                     0, 0, 1, 0, 0, 0)); // Temperature
86
// kelvin
87
// K
88
/** The electric current unit ampere (A) */
89     public final static Unit A = new Unit("A", createType(0, 0, 0,
90                                                     0, 1, 0, 0, 0, 0)); // Current
91
// ampere
92
// A
93
/** The amount of substance unit mole (mol) */
94     public final static Unit mol = new Unit("mol", createType(0, 0,
95                                                     0, 1, 0, 0, 0, 0, 0)); // Substance
96
// mole
97
// mol
98
/** The luminous intensity unit candela (cd) */
99     public final static Unit cd = new Unit("cd", createType(0, 0,
100                                                     1, 0, 0, 0, 0, 0, 0)); // Light
101
// candela
102
// cd
103
/* SI Derived Units */
104     /** The speed unit meter per second (m/s) */
105     public final static Unit m_s = new Unit("m/s", createType(0, 0,
106                                                     0, 0, 0, 0, 0, -1, 1)); // Speed
107
// m/s
108
/** The acceleration unit meter per second squared (m/s <sup>2 </sup>) */
109     public final static Unit m_s2 = new Unit("m/s2", createType(0, 0,
110                                                     0, 0, 0, 0, 0, -2, 1)); // Acceleration
111
// m/s^2
112
/** The area unit square meter(m <sup>2 </sup>) */
113     public final static Unit m2 = new Unit("m2", createType(0, 0,
114                                                     0, 0, 0, 0, 0, 0, 2)); // Surface
115
// m^2
116
/** The volume unit cubic meter (m <sup>3 </sup>) */
117     public final static Unit m3 = new Unit("m3", createType(0, 0,
118                                                     0, 0, 0, 0, 0, 0, 3)); // Volume
119
// m^3
120
/**
121      * The frequency unit hertz (Hz).
122      * <p>
123      * hertz is expressed in SI units as 1/s
124      */

125     public final static Unit Hz = new Unit("Hz", createType(0, 0,
126                                                     0, 0, 0, 0, 0, -1, 0)); // Frequency
127
// 1/s
128
/**
129      * The force unit newton (N).
130      * <p>
131      * N is expressed in SI units as m&#183;kg/s <sup>2 </sup>
132      */

133     public final static Unit N = new Unit("N", createType(0, 0, 0,
134                                                     0, 0, 0, 1, -2, 1)); // Force
135
// newton
136
// (m*kg)/s^2
137
/**
138      * The pressure unit pascal (Pa).
139      * <p>
140      * Pa is equal to N/m <sup>2 </sup> or is expressed in SI units as
141      * kg/m&#183;s <sup>2 </sup>
142      */

143     public final static Unit Pa = new Unit("Pa", createType(0, 0,
144                                                     0, 0, 0, 0, 1, -2, -1)); // Pressure
145
// pascal
146
// kg/(m*s^2)
147
/**
148      * The energy unit joule (J).
149      * <p>
150      * joule is equal to N&#183;m or is expressed in SI units as m <sup>2
151      * </sup>&#183;kg/s <sup>2
152      */

153     public final static Unit J = new Unit("J", createType(0, 0, 0,
154                                                     0, 0, 0, 1, -2, 2)); // Energy
155
// joule
156
// (m^2*kg)/s^2
157
/**
158      * The power unit watt (W).
159      * <p>
160      * watt is equal to J/s or is expressed in SI units as m <sup>2
161      * </sup>&#183;kg/s <sup>3 </sup>
162      */

163     public final static Unit W = new Unit("W", createType(0, 0, 0,
164                                                     0, 0, 0, 1, -3, 2)); // Power
165
// watt
166
// (m^2*kg)/s^3
167
/**
168      * The electric charge unit coulomb (C).
169      * <p>
170      * coulomb is expressed in SI units as s&#183;A
171      */

172     public final static Unit C = new Unit("C", createType(0, 0, 0,
173                                                     0, 1, 0, 0, 1, 0)); // Charge
174
// coulumb
175
// s*A
176
/**
177      * The electric potential difference unit volt (V).
178      * <p>
179      * volt is equal to W/A or is expressed in SI units as m <sup>2
180      * </sup>&#183;kg/s <sup>3 </sup>&#183;A
181      */

182     public final static Unit V = new Unit("V", createType(0, 0, 0,
183                                                     0, -1, 0, 1, -3, 2)); // El.
184
// Potent.
185
// volt
186
// (m^2*kg)/(s^3*A)
187
/**
188      * The capacitance unit farad (F).
189      * <p>
190      * farad is equal to C/V or is expressed in SI units as s <sup>4
191      * </sup>&#183;A <sup>2 </sup>/m <sup>2 </sup>&#183;kg
192      */

193     public final static Unit F = new Unit("F", createType(0, 0, 0,
194                                                     0, 2, 0, -1, 4, -2)); // Capacitance
195
// farad
196
// (s^4*A^2)/(m^2*kg)
197
/**
198      * The electric resistance unit ohm.
199      * <p>
200      * ohm is equal to V/A or is expressed in SI units as m <sup>2
201      * </sup>&#183;kg/s <sup>3 </sup>&#183;A <sup>2 </sup>
202      */

203     public final static Unit Ohm = new Unit("Ohm", createType(0, 0,
204                                                     0, 0, -2, 0, 1, -3, 2)); // Resistance
205
// ohm
206
// (m^2*kg)/(s^3*A^2)
207
/**
208      * The electric conductance unit siemens (S).
209      * <p>
210      * siemens is equal to A/V or is expressed in SI units as s <sup>3
211      * </sup>&#183;A <sup>2 </sup>/m <sup>2 </sup>&#183;kg
212      */

213     public final static Unit S = new Unit("S", createType(0, 0, 0,
214                                                     0, 2, 0, -1, 3, -2)); // Conductance
215
// siemens
216
// (s^3*A^2)/(m^2*kg)
217
/**
218      * The magnetic flux unit weber (Wb).
219      * <p>
220      * weber is equal to V&#183;s or is expressed in SI units as m <sup>2
221      * </sup>&#183;kg/s <sup>2 </sup>&#183;A
222      */

223     public final static Unit Wb = new Unit("Wb", createType(0, 0,
224                                                     0, 0, -1, 0, 1, -2, 2)); // Magn.
225
// Flux
226
// weber
227
// (m^2*kg)/(s^2*A)
228
/**
229      * The magnetic flux density unit tesla (T).
230      * <p>
231      * tesla is equal to Wb/m <sup>2 </sup> or is expressed in SI units as kg/s
232      * <sup>2 </sup>&#183;A
233      */

234     public final static Unit T = new Unit("T", createType(0, 0, 0,
235                                                     0, -1, 0, 1, -2, 0)); // Magn.
236
// Flux
237
// Dens.
238
// tesla
239
// kg/(s^2*A)
240
/**
241      * The illuminance unit lux (lx).
242      * <p>
243      * lux is expressed in SI units as cd/m <sup>2 </sup>
244      */

245     public final static Unit lx = new Unit("lx", createType(0, 0,
246                                                     1, 0, 0, 0, 0, 0, -2)); // Illuminace
247
// lux
248
// cd/m^2
249
/**
250      * The absorbed dose unit gray (Gy).
251      * <p>
252      * Gy is equal to J/kg or is expressed in SI units as m <sup>2 </sup>/s
253      * <sup>2 </sup>
254      */

255     public final static Unit Gy = new Unit("Gy", createType(0, 0,
256                                                     0, 0, 0, 0, 0, -2, 2)); // Absorbed
257
// dose
258
// gray
259
// m^2/s^2
260
/**
261      * The catalytic activity unit katal (kat).
262      * <p>
263      * katal is expressed in SI units as mol/s
264      */

265     public final static Unit kat = new Unit("kat", createType(0, 0,
266                                                     0, 1, 0, 0, 0, -1, 0)); // Catalytic
267
// Act.
268
// katal
269
// mol/s
270
/** The angle unit radians (rad) */
271     public final static Unit rad = new Unit("rad", createType(0, 1,
272                                                     0, 0, 0, 0, 0, 0, 0)); // Angle
273
// radians
274
// rad
275
/**
276      * An array containing all units defined. The first seven items must be m,
277      * s, kg, K, A, mol, cd, rad in this order!
278      */

279     private final static Unit[] allUnits = new Unit[] {m, s, kg, K, A, mol,
280             cd, rad, m_s, m_s2, m2, m3, Hz, N, Pa, J, W, C, V, F, Ohm, S, Wb,
281             T, lx, Gy, kat, unity };
282     private static Hashtable JavaDoc base;
283     private String JavaDoc name;
284     private long type;
285
286     /**
287      * Creates a new <code>Unit</code> instance.
288      *
289      * @param name the name of the <code>Unit</code>
290      * @param type the type of the <code>Unit</code>
291      */

292     private Unit(String JavaDoc name, long type) {
293         this.name = name;
294         this.type = type;
295         //System.out.println( name + " " + Long.toHexString( type ) );
296
}
297
298     /**
299      * Create a type field from the base SI unit exponent values.
300      *
301      */

302     private static long createType(int x, int rad, int cd, int mol, int A,
303             int K, int kg, int s, int m) {
304         return (((ZERO + m) & MASK) << m_SHIFT)
305                 | (((ZERO + s) & MASK) << s_SHIFT)
306                 | (((ZERO + kg) & MASK) << kg_SHIFT)
307                 | (((ZERO + K) & MASK) << K_SHIFT)
308                 | (((ZERO + A) & MASK) << A_SHIFT)
309                 | (((ZERO + mol) & MASK) << mol_SHIFT)
310                 | (((ZERO + cd) & MASK) << cd_SHIFT)
311                 | (((ZERO + rad) & MASK) << rad_SHIFT)
312                 | (((long) x) << x_SHIFT);
313     }
314
315     /**
316      * Checks whether this <code>Unit</code> object is equal to the specified
317      * <code>Unit</code> object. The <code>Unit</code> objects are considered equal
318      * if their exponents are equal.
319      *
320      * @param obj the <code>Unit</code> object that should be checked for equality
321      *
322      * @return true if the specified <code>Unit</code> object is equal to this
323      * <code>Unit</code> object.
324      */

325     public boolean equals(Object JavaDoc obj) {
326         if (this == obj) {
327             return true;
328         }
329         if (!(obj instanceof Unit)) {
330             return false;
331         }
332         return ((Unit) obj).type == type;
333     }
334
335     /**
336      * Returns the hash code for this object.
337      *
338      * @return This object's hash code.
339      */

340     public int hashCode() {
341         return (int) ((type >>> 32) ^ type);
342     }
343
344     /**
345      * Returns a new <code>Unit</code> that is the multiplication of this
346      * <code>Unit</code> and the <code>Unit</code> specified
347      *
348      * @param that the <code>Unit</code> that will be multiplied with this
349      * <code>Unit</code>
350      *
351      * @return a new <code>Unit</code> that is the multiplication of this
352      * <code>Unit</code> and the <code>Unit</code> specified
353      *
354      * @throws RuntimeException if both <code>Unit</code> s are special
355      *
356      * @see Unit#isSpecial
357      */

358     Unit mul(Unit that) {
359         if (this.isSpecial() && that.isSpecial()) {
360             throw new ArithmeticException JavaDoc("Cannot multiply " + this + " with "
361                     + that);
362         }
363         return find(this.type - UNITY + that.type);
364     }
365
366     /**
367      * Returns a new <code>Unit</code> that is the division of this <code>Unit</code>
368      * and the <code>Unit</code> specified
369      *
370      * @param that the <code>Unit</code> that this <code>Unit</code> will be divided
371      * with
372      * @return a new <code>Unit</code> that is the division of this <code>Unit</code>
373      * and the <code>Unit</code> specified
374      *
375      * @throws RuntimeException if both <code>Unit</code> s are special
376      *
377      * @see Unit#isSpecial
378      */

379     Unit div(Unit that) {
380         if (this.isSpecial() && that.isSpecial()) {
381             if (this.type == that.type) {
382                 return Unit.unity;
383             }
384             throw new ArithmeticException JavaDoc("Cannot divide " + this + " by "
385                     + that);
386         }
387         return find(this.type - that.type + UNITY);
388     }
389
390     /**
391      * Returns a new <code>Unit</code> that is the addition of this <code>Unit</code>
392      * and the <code>Unit</code> specified.
393      *
394      * @param that the <code>Unit</code> that should be added to this
395      * <code>Unit</code>
396      *
397      * @return a new <code>Unit</code> that is the addition of this <code>Unit</code>
398      * and the <code>Unit</code> specified.
399      *
400      * @throws RuntimeException if the two <code>Unit</code> s are not the same
401      */

402     Unit add(Unit that) {
403         if (!this.equals(that)) {
404             throw new ArithmeticException JavaDoc("Cannot add " + this + " to " + that);
405         }
406         return this;
407     }
408
409     /**
410      * Returns a new <code>Unit</code> that is the subtraction between this
411      * <code>Unit</code> and the <code>Unit</code> specified.
412      *
413      * @param that the <code>Unit</code> that will be subtracted from this
414      * <code>Unit</code>
415      * @return a new <code>Unit</code> that is the subtraction between this
416      * <code>Unit</code> and the <code>Unit</code> specified.
417      *
418      * @throws RuntimeException if the <code>Unit</code> specified is not the same
419      * as this <code>Unit</code>
420      */

421     Unit sub(Unit that) {
422         if (!this.equals(that)) {
423             throw new ArithmeticException JavaDoc("Cannot subtract " + that + " from "
424                     + this);
425         }
426         return this;
427     }
428
429     /**
430      * Finds a <code>Unit</code> based on a type. If the <code>Unit</code> is not
431      * found, it will be created and added to the list of all units under a null
432      * name.
433      *
434      * @param type the type of the <code>Unit</code> to find
435      *
436      * @return the <code>Unit</code>
437      */

438     static Unit find(long type) {
439         if (base == null) {
440             synchronized (Unit.class) {
441                 if (base == null) {
442                     int size = allUnits.length;
443                     base = new Hashtable JavaDoc(size << 1);
444                     for (int i = 0; i < size; i++) {
445                         base.put(allUnits[i], allUnits[i]);
446                     }
447                 }
448             }
449         }
450         Unit unit = new Unit(null, type);
451         Unit out = (Unit) base.get(unit);
452         if (out == null) {
453             base.put(unit, unit);
454             out = unit;
455         }
456         return out;
457     }
458
459     /**
460      * Returns a <code>String</code> object representing the <code>Unit</code>
461      *
462      * @return A <code>String</code> object representing the <code>Unit</code>
463      */

464     public String JavaDoc toString() {
465         if (name == null) {
466             int m = (int) (((type >> m_SHIFT) & MASK) - ZERO);
467             int s = (int) (((type >> s_SHIFT) & MASK) - ZERO);
468             int kg = (int) (((type >> kg_SHIFT) & MASK) - ZERO);
469             int K = (int) (((type >> K_SHIFT) & MASK) - ZERO);
470             int A = (int) (((type >> A_SHIFT) & MASK) - ZERO);
471             int mol = (int) (((type >> mol_SHIFT) & MASK) - ZERO);
472             int cd = (int) (((type >> cd_SHIFT) & MASK) - ZERO);
473             int rad = (int) (((type >> rad_SHIFT) & MASK) - ZERO);
474             StringBuffer JavaDoc numerator = new StringBuffer JavaDoc();
475             StringBuffer JavaDoc denominator = new StringBuffer JavaDoc();
476             addSIname(m, "m", numerator, denominator);
477             addSIname(s, "s", numerator, denominator);
478             addSIname(kg, "kg", numerator, denominator);
479             addSIname(K, "K", numerator, denominator);
480             addSIname(A, "A", numerator, denominator);
481             addSIname(mol, "mol", numerator, denominator);
482             addSIname(cd, "cd", numerator, denominator);
483             addSIname(rad, "rad", numerator, denominator);
484             if (denominator.length() > 0) {
485                 if (numerator.length() == 0) {
486                     numerator.append("1");
487                 }
488                 numerator.append("/");
489                 numerator.append((Object JavaDoc) denominator); /*
490                                                          * we use (Object) to
491                                                          * avoid using new 1.4
492                                                          * method
493                                                          * append(StringBuffer)
494                                                          */

495             }
496             name = numerator.toString();
497         }
498         return name;
499     }
500
501     private void addSIname(int si, String JavaDoc name, StringBuffer JavaDoc numerator,
502             StringBuffer JavaDoc denominator) {
503         if (si != 0) {
504             StringBuffer JavaDoc sb = (si > 0) ? numerator : denominator;
505             if (sb.length() > 0) {
506                 sb.append("*");
507             }
508             sb.append(name);
509             int power = Math.abs(si);
510             if (power > 1) {
511                 sb.append("^");
512                 sb.append(power);
513             }
514         }
515     }
516
517     /**
518      * Checks whether the unit has a special type, i.e. not a SI unit.
519      *
520      * @return true if the type is special, otherwise false.
521      */

522     private boolean isSpecial() {
523         return (type & x_MASK) != 0;
524     }
525 }
526
Popular Tags