188 lines
5.7 KiB
Java
188 lines
5.7 KiB
Java
/*
|
|
* 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.converter;
|
|
|
|
import java.io.Serializable;
|
|
|
|
/**
|
|
* <p> This class represents a converter of numeric values.</p>
|
|
*
|
|
* <p> It is not required for sub-classes to be immutable
|
|
* (e.g. currency converter).</p>
|
|
*
|
|
* <p> Sub-classes must ensure unicity of the {@link #IDENTITY identity}
|
|
* converter. In other words, if the result of an operation is equivalent
|
|
* to the identity converter, then the unique {@link #IDENTITY} instance
|
|
* should be returned.</p>
|
|
*
|
|
* @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
|
|
* @version 3.1, April 22, 2006
|
|
*/
|
|
public abstract class UnitConverter implements Serializable {
|
|
|
|
/**
|
|
* Holds the identity converter (unique). This converter does nothing
|
|
* (<code>ONE.convert(x) == x</code>).
|
|
*/
|
|
public static final UnitConverter IDENTITY = new Identity();
|
|
|
|
/**
|
|
* Default constructor.
|
|
*/
|
|
protected UnitConverter() {
|
|
}
|
|
|
|
/**
|
|
* Returns the inverse of this converter. If <code>x</code> is a valid
|
|
* value, then <code>x == inverse().convert(convert(x))</code> to within
|
|
* the accuracy of computer arithmetic.
|
|
*
|
|
* @return the inverse of this converter.
|
|
*/
|
|
public abstract UnitConverter inverse();
|
|
|
|
/**
|
|
* Converts a double value.
|
|
*
|
|
* @param x the numeric value to convert.
|
|
* @return the converted numeric value.
|
|
* @throws ConversionException if an error occurs during conversion.
|
|
*/
|
|
public abstract double convert(double x) throws ConversionException;
|
|
|
|
/**
|
|
* Indicates if this converter is linear. A converter is linear if
|
|
* <code>convert(u + v) == convert(u) + convert(v)</code> and
|
|
* <code>convert(r * u) == r * convert(u)</code>.
|
|
* For linear converters the following property always hold:[code]
|
|
* y1 = c1.convert(x1);
|
|
* y2 = c2.convert(x2);
|
|
* then y1*y2 = c1.concatenate(c2).convert(x1*x2)[/code]
|
|
*
|
|
* @return <code>true</code> if this converter is linear;
|
|
* <code>false</code> otherwise.
|
|
*/
|
|
public abstract boolean isLinear();
|
|
|
|
/**
|
|
* Indicates whether this converter is considered the same as the
|
|
* converter specified. To be considered equal this converter
|
|
* concatenated with the one specified must returns the {@link #IDENTITY}.
|
|
*
|
|
* @param cvtr the converter with which to compare.
|
|
* @return <code>true</code> if the specified object is a converter
|
|
* considered equals to this converter;<code>false</code> otherwise.
|
|
*/
|
|
public boolean equals(Object cvtr) {
|
|
if (!(cvtr instanceof UnitConverter)) return false;
|
|
return this.concatenate(((UnitConverter)cvtr).inverse()) == IDENTITY;
|
|
}
|
|
|
|
/**
|
|
* Returns a hash code value for this converter. Equals object have equal
|
|
* hash codes.
|
|
*
|
|
* @return this converter hash code value.
|
|
* @see #equals
|
|
*/
|
|
public int hashCode() {
|
|
return Float.floatToIntBits((float)convert(1.0));
|
|
}
|
|
|
|
/**
|
|
* Concatenates this converter with another converter. The resulting
|
|
* converter is equivalent to first converting by the specified converter,
|
|
* and then converting by this converter.
|
|
*
|
|
* <p>Note: Implementations must ensure that the {@link #IDENTITY} instance
|
|
* is returned if the resulting converter is an identity
|
|
* converter.</p>
|
|
*
|
|
* @param converter the other converter.
|
|
* @return the concatenation of this converter with the other converter.
|
|
*/
|
|
public UnitConverter concatenate(UnitConverter converter) {
|
|
return (converter == IDENTITY) ? this : new Compound(converter, this);
|
|
}
|
|
|
|
/**
|
|
* This inner class represents the identity converter (singleton).
|
|
*/
|
|
private static final class Identity extends UnitConverter {
|
|
|
|
@Override
|
|
public UnitConverter inverse() {
|
|
return this;
|
|
}
|
|
|
|
@Override
|
|
public double convert(double x) {
|
|
return x;
|
|
}
|
|
|
|
@Override
|
|
public boolean isLinear() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public UnitConverter concatenate(UnitConverter converter) {
|
|
return converter;
|
|
}
|
|
|
|
private static final long serialVersionUID = 1L;
|
|
|
|
}
|
|
|
|
/**
|
|
* This inner class represents a compound converter.
|
|
*/
|
|
private static final class Compound extends UnitConverter {
|
|
|
|
/**
|
|
* Holds the first converter.
|
|
*/
|
|
private final UnitConverter _first;
|
|
|
|
/**
|
|
* Holds the second converter.
|
|
*/
|
|
private final UnitConverter _second;
|
|
|
|
/**
|
|
* Creates a compound converter resulting from the combined
|
|
* transformation of the specified converters.
|
|
*
|
|
* @param first the first converter.
|
|
* @param second the second converter.
|
|
*/
|
|
private Compound(UnitConverter first, UnitConverter second) {
|
|
_first = first;
|
|
_second = second;
|
|
}
|
|
|
|
@Override
|
|
public UnitConverter inverse() {
|
|
return new Compound(_second.inverse(), _first.inverse());
|
|
}
|
|
|
|
@Override
|
|
public double convert(double x) {
|
|
return _second.convert(_first.convert(x));
|
|
}
|
|
|
|
@Override
|
|
public boolean isLinear() {
|
|
return _first.isLinear() && _second.isLinear();
|
|
}
|
|
|
|
private static final long serialVersionUID = 1L;
|
|
|
|
}
|
|
} |