KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jscience > physics > units > Converter


1 /*
2  * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
3  * Copyright (C) 2005 - JScience (http://jscience.org/)
4  * All rights reserved.
5  *
6  * Permission to use, copy, modify, and distribute this software is
7  * freely granted, provided that this notice is preserved.
8  */

9 package org.jscience.physics.units;
10 import java.io.Serializable JavaDoc;
11
12 /**
13  * <p> This class represents a converter of numeric values.</p>
14  * <p> It is not required for sub-classes to be immutable
15  * (e.g. currency converter).</p>
16  *
17  * @author <a HREF="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
18  * @version 1.0, October 24, 2004
19  */

20 public abstract class Converter implements Serializable JavaDoc {
21
22     /**
23      * Holds the identity converter. This converter does nothing
24      * (<code>IDENTITY.convert(x) == x</code>).
25      */

26     public static final Converter IDENTITY = new Identity();
27
28     /**
29      * Default constructor.
30      */

31     protected Converter() {}
32
33     /**
34      * Returns the inverse of this converter. If <code>x</code> is a valid
35      * value, then <code>x == inverse().convert(convert(x))</code> to within
36      * the accuracy of computer arithmetic.
37      *
38      * @return the inverse of this converter.
39      */

40     public abstract Converter inverse();
41
42     /**
43      * Converts a double value.
44      *
45      * @param x the numeric value to convert.
46      * @return the converted numeric value.
47      * @throws ConversionException if an error occurs during conversion.
48      */

49     public abstract double convert(double x) throws ConversionException;
50
51     /**
52      * Returns this converter derivative for the specified
53      * <code>x</code> value. For linear converters, this method returns
54      * a constant (the linear factor) for all <code>x</code> values.
55      *
56      * @param x the value for which the derivative is calculated.
57      * @return the derivative for the specified value.
58      */

59     public abstract double derivative(double x);
60
61     /**
62      * Indicates if this converter is linear. A converter is linear if
63      * <code>convert(u + v) == convert(u) + convert(v)</code> and
64      * <code>convert(r * u) == r * convert(u)</code>.
65      *
66      * @return <code>true</code> if this converter is linear;
67      * <code>false</code> otherwise.
68      */

69     public abstract boolean isLinear();
70
71     /**
72      * Indicates whether some other object is "equal to" this converter.
73      *
74      * @param obj the reference object with which to compare.
75      * @return <code>true</code> if this object is a linear converter and this
76      * object is also a linear converter and both have same
77      * derivatives; <code>false</code> otherwise.
78      */

79     public boolean equals(Object JavaDoc obj) {
80         if (obj instanceof Converter) {
81             Converter that = (Converter) obj;
82             // Check equality to float precision (allows for some inaccuracies)
83
return this.isLinear() && that.isLinear() &&
84             (Float.floatToIntBits((float) this.derivative(0)) ==
85              Float.floatToIntBits((float) that.derivative(0)));
86         } else {
87             return false;
88         }
89     }
90
91     /**
92      * Returns a hash code value for this converter. Equals object have equal
93      * hash codes.
94      *
95      * @return this converter hash code value.
96      * @see #equals
97      */

98     public int hashCode() {
99         int h = Float.floatToIntBits((float)derivative(0));
100         h += ~(h << 9);
101         h ^= (h >>> 14);
102         h += (h << 4);
103         return h ^ (h >>> 10);
104     }
105
106     /**
107      * Concatenates this converter with another converter. The resulting
108      * converter is equivalent to first converting by the specified converter,
109      * and then converting by this converter.
110      *
111      * @param converter the other converter.
112      * @return the concatenation of this converter with the other converter.
113      */

114     public Converter concatenate(Converter converter) {
115         if (converter == IDENTITY) {
116             return this;
117         } else {
118             return new Compound(converter, this);
119         }
120     }
121
122     /**
123      * This inner class represents the identity converter (singleton).
124      */

125     private static final class Identity extends Converter {
126
127
128         // Implements abstract method.
129
public Converter inverse() {
130             return this;
131         }
132
133         // Implements abstract method.
134
public double convert(double x) {
135             return x;
136         }
137
138         // Implements abstract method.
139
public double derivative(double x) {
140             return 1.0;
141         }
142
143         // Implements abstract method.
144
public boolean isLinear() {
145             return true;
146         }
147
148         // Overrides.
149
public Converter concatenate(Converter converter) {
150             return converter;
151         }
152
153         private static final long serialVersionUID = 1L;
154     }
155
156     /**
157      * This inner class represents a compound converter.
158      */

159     private static final class Compound extends Converter {
160
161         /**
162          * Holds the first converter.
163          */

164         private final Converter _first;
165
166         /**
167          * Holds the second converter.
168          */

169         private final Converter _second;
170
171         /**
172          * Creates a compound converter resulting from the combined
173          * transformation of the specified converters.
174          *
175          * @param first the first converter.
176          * @param second the second converter.
177          */

178         private Compound(Converter first, Converter second) {
179             _first = first;
180             _second = second;
181         }
182
183         // Implements abstract method.
184
public Converter inverse() {
185             return new Compound(_second.inverse(), _first.inverse());
186         }
187
188         // Implements abstract method.
189
public double convert(double x) {
190             return _second.convert(_first.convert(x));
191         }
192
193         // Implements abstract method.
194
public double derivative(double x) {
195             return _first.derivative(x) * _second.derivative(_first.convert(x));
196         }
197
198         // Implements abstract method.
199
public boolean isLinear() {
200             return _first.isLinear() && _second.isLinear();
201         }
202
203         // Overrides.
204
public boolean equals(Object JavaDoc obj) {
205             return super.equals(obj) ||
206                 ( (obj instanceof Compound) &&
207                    ((Compound)obj)._first.equals(_first) &&
208                    ((Compound)obj)._second.equals(_second) );
209         }
210
211         private static final long serialVersionUID = 1L;
212     }
213 }
Popular Tags