/*
 * 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;

/**
 * 

This class represents a converter of numeric values.

* *

It is not required for sub-classes to be immutable * (e.g. currency converter).

* *

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.

* * @author Jean-Marie Dautelle * @version 3.1, April 22, 2006 */ public abstract class UnitConverter implements Serializable { /** * Holds the identity converter (unique). This converter does nothing * (ONE.convert(x) == x). */ public static final UnitConverter IDENTITY = new Identity(); /** * Default constructor. */ protected UnitConverter() { } /** * Returns the inverse of this converter. If x is a valid * value, then x == inverse().convert(convert(x)) 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 * convert(u + v) == convert(u) + convert(v) and * convert(r * u) == r * convert(u). * 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 true if this converter is linear; * false 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 true if the specified object is a converter * considered equals to this converter;false 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. * *

Note: Implementations must ensure that the {@link #IDENTITY} instance * is returned if the resulting converter is an identity * converter.

* * @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; } }

Ads help maintain this website.