diff --git a/app/build.gradle b/app/build.gradle index 0755b9a8..2bf0e75b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -74,7 +74,7 @@ dependencies { implementation "com.android.support:support-v4:${versions.supportLib}" implementation "com.android.support:appcompat-v7:${versions.supportLib}" implementation "com.android.support:design:${versions.supportLib}" - implementation "javax.measure:jsr-275:0.9.1" + implementation project(":measure") implementation 'com.squareup:otto:1.3.9-SNAPSHOT' annotationProcessor 'com.squareup:otto:1.3.9-SNAPSHOT' annotationProcessor 'com.squareup:otto-compiler:1.3.9-SNAPSHOT' diff --git a/measure/.gitignore b/measure/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/measure/.gitignore @@ -0,0 +1 @@ +/build diff --git a/measure/build.gradle b/measure/build.gradle new file mode 100644 index 00000000..c367e675 --- /dev/null +++ b/measure/build.gradle @@ -0,0 +1,9 @@ +apply plugin: 'java-library' + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + +} + +sourceCompatibility = "7" +targetCompatibility = "7" diff --git a/measure/src/main/java/javax/measure/DecimalMeasure.java b/measure/src/main/java/javax/measure/DecimalMeasure.java new file mode 100644 index 00000000..05f337a9 --- /dev/null +++ b/measure/src/main/java/javax/measure/DecimalMeasure.java @@ -0,0 +1,178 @@ +/* + * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences. + * Copyright (C) 2007 - 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; + +import java.math.BigDecimal; +import java.math.MathContext; + +import javax.measure.converter.AddConverter; +import javax.measure.converter.RationalConverter; +import javax.measure.converter.UnitConverter; +import javax.measure.quantity.Quantity; +import javax.measure.unit.Unit; + +/** + *

This class represents a measure whose value is an arbitrary-precision + * decimal number.

+ * + *

When converting, applications may supply the + * java.math.Context:[code] + * DecimalMeasure c = DecimalMeasure.valueOf("299792458 m/s"); + * DecimalMeasure milesPerHour = c.to(MILES_PER_HOUR, MathContext.DECIMAL128); + * System.out.println(milesPerHour); + * + * > 670616629.3843951324266284896206156 mph + * [/code] + * + * @author Jean-Marie Dautelle + * @version 4.3, October 3, 2007 + */ +public class DecimalMeasure extends Measure { + + /** + * Holds the BigDecimal value. + */ + private final BigDecimal _value; + + /** + * Holds the unit. + */ + private final Unit _unit; + + /** + * Creates a decimal measure for the specified number stated in the + * specified unit. + */ + public DecimalMeasure(BigDecimal value, Unit unit) { + _value = value; + _unit = unit; + } + + /** + * Returns the decimal measure for the specified number stated in the + * specified unit. + * + * @param decimal the measurement value. + * @param unit the measurement unit. + */ + public static DecimalMeasure valueOf( + BigDecimal decimal, Unit unit) { + return new DecimalMeasure(decimal, unit); + } + + /** + * Returns the decimal measure for the specified textual representation. + * This method first reads the BigDecimal value, then + * the unit if any (value and unit should be separated by white spaces). + * + * @param csq the decimal measure representation (including unit if any). + * @throws NumberFormatException if the specified character sequence is + * not a valid representation of decimal measure. + */ + @SuppressWarnings("unchecked") + public static DecimalMeasure valueOf(CharSequence csq) { + String str = csq.toString(); + int numberLength = str.length(); + int unitStartIndex = -1; + for (int i=0; i < str.length(); i++) { + if (Character.isWhitespace(str.charAt(i))) { + for (int j=i+1; j < str.length(); j++) { + if (!Character.isWhitespace(str.charAt(j))) { + unitStartIndex = j; + break; + } + } + numberLength = i; + break; + } + } + BigDecimal decimal = new BigDecimal(str.substring(0, numberLength)); + Unit unit = Unit.ONE; + if (unitStartIndex > 0) { + unit = Unit.valueOf(str.substring(unitStartIndex)); + } + return new DecimalMeasure(decimal, unit); + } + + @Override + public Unit getUnit() { + return _unit; + } + + @Override + public BigDecimal getValue() { + return _value; + } + + /** + * Returns the decimal measure equivalent to this measure but stated in the + * specified unit. This method will raise an ArithmeticException if the + * resulting measure does not have a terminating decimal expansion. + * + * @param unit the new measurement unit. + * @return the measure stated in the specified unit. + * @throws ArithmeticException if the converted measure value does not have + * a terminating decimal expansion + * @see #to(Unit, MathContext) + */ + @Override + public DecimalMeasure to(Unit unit) { + return to(unit, null); + } + + /** + * Returns the decimal measure equivalent to this measure but stated in the + * specified unit, the conversion is performed using the specified math + * context. + * + * @param unit the new measurement unit. + * @param mathContext the mathContext used to convert + * BigDecimal values or null if none. + * @return the measure stated in the specified unit. + * @throws ArithmeticException if the result is inexact but the + * rounding mode is MathContext.UNNECESSARY or + * mathContext.precision == 0 and the quotient has a + * non-terminating decimal expansion. + */ + public DecimalMeasure to(Unit unit, MathContext mathContext) { + if ((unit == _unit) || (unit.equals(_unit))) + return this; + UnitConverter cvtr = _unit.getConverterTo(unit); + if (cvtr instanceof RationalConverter) { + RationalConverter factor = (RationalConverter) cvtr; + BigDecimal dividend = BigDecimal.valueOf(factor.getDividend()); + BigDecimal divisor = BigDecimal.valueOf(factor.getDivisor()); + BigDecimal result = mathContext == null ? + _value.multiply(dividend).divide(divisor) : + _value.multiply(dividend, mathContext).divide(divisor, mathContext); + return new DecimalMeasure(result, unit); + } else if (cvtr.isLinear()) { + BigDecimal factor = BigDecimal.valueOf(cvtr.convert(1.0)); + BigDecimal result = mathContext == null ? + _value.multiply(factor) : _value.multiply(factor, mathContext); + return new DecimalMeasure(result, unit); + } else if (cvtr instanceof AddConverter) { + BigDecimal offset = BigDecimal.valueOf(((AddConverter)cvtr).getOffset()); + BigDecimal result = mathContext == null ? + _value.add(offset) : _value.add(offset, mathContext); + return new DecimalMeasure(result, unit); + } else { // Non-linear and not an offset, convert the double value. + BigDecimal result = BigDecimal.valueOf(cvtr.convert(_value.doubleValue())); + return new DecimalMeasure(result, unit); + } + } + + public double doubleValue(Unit unit) { + if ((unit == _unit) || (unit.equals(_unit))) + return _value.doubleValue(); + return _unit.getConverterTo(unit).convert(_value.doubleValue()); + } + + private static final long serialVersionUID = 1L; +} diff --git a/measure/src/main/java/javax/measure/Measurable.java b/measure/src/main/java/javax/measure/Measurable.java new file mode 100644 index 00000000..6d632b48 --- /dev/null +++ b/measure/src/main/java/javax/measure/Measurable.java @@ -0,0 +1,76 @@ +/* + * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences. + * Copyright (C) 2007 - 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; + +import javax.measure.quantity.Quantity; +import javax.measure.unit.Unit; + +/** + *

This interface represents the measurable, countable, or comparable + * property or aspect of a thing.

+ * + *

Implementing instances are typically the result of a measurement:[code] + * Measurable weight = Measure.valueOf(180.0, POUND); + * [/code] + * They can also be created from custom classes:[code] + * class Delay implements Measurable { + * private long nanoSeconds; // Implicit internal unit. + * public double doubleValue(Unit unit) { ... } + * public long longValue(Unit unit) { ... } + * } + * Thread.wait(new Delay(24, HOUR)); // Assuming Thread.wait(Measurable) method. + * [/code]

+ * + *

Although measurable instances are for the most part scalar quantities; + * more complex implementations (e.g. vectors, data set) are allowed as + * long as an aggregate magnitude can be determined. For example:[code] + * class Velocity3D implements Measurable { + * private double x, y, z; // Meter per seconds. + * public double doubleValue(Unit unit) { ... } // Returns vector norm. + * ... + * } + * class Sensors extends Measure { + * public doubleValue(Unit unit) { ... } // Returns median value. + * ... + * } [/code]

+ * + * @author Jean-Marie Dautelle + * @version 4.1, June 8, 2007 + */ +public interface Measurable extends Comparable> { + + /** + * Returns the value of this measurable stated in the specified unit as + * a double. If the measurable has too great a magnitude to + * be represented as a double, it will be converted to + * Double.NEGATIVE_INFINITY or + * Double.POSITIVE_INFINITY as appropriate. + * + * @param unit the unit in which this measurable value is stated. + * @return the numeric value after conversion to type double. + */ + double doubleValue(Unit unit); + + /** + * Returns the estimated integral value of this measurable stated in + * the specified unit as a long. + * + *

Note: This method differs from the Number.longValue() + * in the sense that the closest integer value is returned + * and an ArithmeticException is raised instead + * of a bit truncation in case of overflow (safety critical).

+ * + * @param unit the unit in which the measurable value is stated. + * @return the numeric value after conversion to type long. + * @throws ArithmeticException if this quantity cannot be represented + * as a long number in the specified unit. + */ + long longValue(Unit unit) throws ArithmeticException; + +} diff --git a/measure/src/main/java/javax/measure/Measure.java b/measure/src/main/java/javax/measure/Measure.java new file mode 100644 index 00000000..610727a9 --- /dev/null +++ b/measure/src/main/java/javax/measure/Measure.java @@ -0,0 +1,449 @@ +/* + * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences. + * Copyright (C) 2007 - 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; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.math.MathContext; + +import javax.measure.quantity.Quantity; +import javax.measure.unit.CompoundUnit; +import javax.measure.unit.Unit; + +/** + *

This class represents the result of a measurement stated in a + * known unit.

+ * + *

There is no constraint upon the measurement value itself: scalars, + * vectors, or even data sets are valid values as long as + * an aggregate magnitude can be determined (see {@link Measurable}).

+ * + * @author Jean-Marie Dautelle + * @version 4.2, August 26, 2007 + */ +public abstract class Measure implements Measurable, + Serializable { + + /** + * Default constructor. + */ + protected Measure() { + } + + /** + * Returns the scalar measure for the specified double + * stated in the specified unit. + * + * @param doubleValue the measurement value. + * @param unit the measurement unit. + */ + public static Measure valueOf( + double doubleValue, Unit unit) { + return new Double(doubleValue, unit); + } + + /** + * Returns the scalar measure for the specified double + * stated in the specified unit. + * + * @param longValue the measurement value. + * @param unit the measurement unit. + */ + public static Measure valueOf( + long longValue, Unit unit) { + return new Long(longValue, unit); + } + + /** + * Returns the scalar measure for the specified float + * stated in the specified unit. + * + * @param floatValue the measurement value. + * @param unit the measurement unit. + */ + public static Measure valueOf( + float floatValue, Unit unit) { + return new Float(floatValue, unit); + } + + /** + * Returns the scalar measure for the specified int + * stated in the specified unit. + * + * @param intValue the measurement value. + * @param unit the measurement unit. + */ + public static Measure valueOf( + int intValue, Unit unit) { + return new Integer(intValue, unit); + } + + /** + * Returns the measurement value of this measure. + * + * @return the measurement value. + */ + public abstract V getValue(); + + /** + * Returns the measurement unit of this measure. + * + * @return the measurement unit. + */ + public abstract Unit getUnit(); + + /** + * Returns the measure equivalent to this measure but stated in the + * specified unit. This method may result in lost of precision + * (e.g. measure of integral value). + * + * @param unit the new measurement unit. + * @return the measure stated in the specified unit. + */ + public abstract Measure to(Unit unit); + + /** + * Returns the value of this measure stated in the specified unit as + * a double. If the measure has too great a magnitude to + * be represented as a double, it will be converted to + * Double.NEGATIVE_INFINITY or + * Double.POSITIVE_INFINITY as appropriate. + * + * @param unit the unit in which this measure is stated. + * @return the numeric value after conversion to type double. + */ + public abstract double doubleValue(Unit unit); + + /** + * Returns the estimated integral value of this measure stated in + * the specified unit as a long. + * + *

Note: This method differs from the Number.longValue() + * in the sense that the closest integer value is returned + * and an ArithmeticException is raised instead + * of a bit truncation in case of overflow (safety critical).

+ * + * @param unit the unit in which the measurable value is stated. + * @return the numeric value after conversion to type long. + * @throws ArithmeticException if this quantity cannot be represented + * as a long number in the specified unit. + */ + public long longValue(Unit unit) throws ArithmeticException { + double doubleValue = doubleValue(unit); + if (java.lang.Double.isNaN(doubleValue) + || (doubleValue < java.lang.Long.MIN_VALUE) + || (doubleValue > java.lang.Long.MAX_VALUE)) + throw new ArithmeticException(doubleValue + " " + unit + + " cannot be represented as long"); + return Math.round(doubleValue); + } + + /** + * Returns the value of this measure stated in the specified unit as a + * float. If the measure has too great a magnitude to be + * represented as a float, it will be converted to + * Float.NEGATIVE_INFINITY or + * Float.POSITIVE_INFINITY as appropriate. + * + * @param unit the unit in which the measure is stated. + * @return the numeric value after conversion to type float. + */ + public float floatValue(Unit unit) { + return (float) doubleValue(unit); + } + + /** + * Returns the estimated integral value of this measure stated in + * the specified unit as a int. + * + *

Note: This method differs from the Number.intValue() + * in the sense that the closest integer value is returned + * and an ArithmeticException is raised instead + * of a bit truncation in case of overflow (safety critical).

+ * + * @param unit the unit in which the measurable value is stated. + * @return the numeric value after conversion to type int. + * @throws ArithmeticException if this quantity cannot be represented + * as a int number in the specified unit. + */ + public int intValue(Unit unit) { + long longValue = longValue(unit); + if ((longValue > java.lang.Integer.MAX_VALUE) + || (longValue < java.lang.Integer.MIN_VALUE)) + throw new ArithmeticException("Overflow"); + return (int) longValue; + } + + /** + * Compares this measure against the specified object for + * strict equality (same unit and amount). + * To compare measures stated using different units the + * {@link #compareTo} method should be used. + * + * @param obj the object to compare with. + * @return true if both objects are identical (same + * unit and same amount); false otherwise. + */ + @SuppressWarnings("unchecked") + public boolean equals(Object obj) { + if (!(obj instanceof Measure)) + return false; + Measure that = (Measure) obj; + return this.getUnit().equals(that.getUnit()) + && this.getValue().equals(that.getValue()); + } + + /** + * Returns the hash code for this scalar. + * + * @return the hash code value. + */ + public int hashCode() { + return getUnit().hashCode() + getValue().hashCode(); + } + + /** + * Returns the String representation of this measure + * The string produced for a given measure is always the same; + * it is not affected by locale. This means that it can be used + * as a canonical string representation for exchanging data, + * or as a key for a Hashtable, etc. Locale-sensitive + * measure formatting and parsing is handled by the {@link + * MeasureFormat} class and its subclasses. + * + * @return the string representation of this measure. + */ + public String toString() { + if (getUnit() instanceof CompoundUnit) + return MeasureFormat.DEFAULT.formatCompound(doubleValue(getUnit()), + getUnit(), new StringBuffer(), null).toString(); + return getValue() + " " + getUnit(); + } + + /** + * Compares this measure to the specified measurable quantity. + * This method compares the {@link Measurable#doubleValue(Unit)} of + * both this measure and the specified measurable stated in the + * same unit (this measure's {@link #getUnit() unit}). + * + * @return a negative integer, zero, or a positive integer as this measure + * is less than, equal to, or greater than the specified measurable + * quantity. + * @return Double.compare(this.doubleValue(getUnit()), + * that.doubleValue(getUnit())) + */ + public int compareTo(Measurable that) { + return java.lang.Double.compare(doubleValue(getUnit()), that + .doubleValue(getUnit())); + } + + /** + * Holds scalar implementation for double values. + */ + private static final class Double extends + Measure { + + private final double _value; + + private final Unit _unit; + + public Double(double value, Unit unit) { + _value = value; + _unit = unit; + } + + @Override + public Unit getUnit() { + return _unit; + } + + @Override + public java.lang.Double getValue() { + return _value; + } + + @Override + public Measure to(Unit unit) { + if ((unit == _unit) || (unit.equals(_unit))) + return this; + return new Double(doubleValue(unit), unit); + } + + public double doubleValue(Unit unit) { + if ((unit == _unit) || (unit.equals(_unit))) + return _value; + return _unit.getConverterTo(unit).convert(_value); + } + + private static final long serialVersionUID = 1L; + } + + /** + * Holds scalar implementation for long values. + */ + private static final class Long extends + Measure { + + private final long _value; + + private final Unit _unit; + + public Long(long value, Unit unit) { + _value = value; + _unit = unit; + } + + @Override + public Unit getUnit() { + return _unit; + } + + @Override + public java.lang.Long getValue() { + return _value; + } + + @Override + public Measure to(Unit unit) { + if ((unit == _unit) || (unit.equals(_unit))) + return this; + return new Long(longValue(unit), unit); + } + + public double doubleValue(Unit unit) { + if ((unit == _unit) || (unit.equals(_unit))) + return _value; + return _unit.getConverterTo(unit).convert(_value); + } + + public long longValue(Unit unit) throws ArithmeticException { + if ((unit == _unit) || (unit.equals(_unit))) + return _value; // No conversion, returns value directly. + return super.longValue(unit); + } + + private static final long serialVersionUID = 1L; + + } + + /** + * Holds scalar implementation for float values. + */ + private static final class Float extends + Measure { + + private final float _value; + + private final Unit _unit; + + public Float(float value, Unit unit) { + _value = value; + _unit = unit; + } + + @Override + public Unit getUnit() { + return _unit; + } + + @Override + public java.lang.Float getValue() { + return _value; + } + + @Override + public Measure to(Unit unit) { + if ((unit == _unit) || (unit.equals(_unit))) + return this; + return new Float(floatValue(unit), unit); + } + + public double doubleValue(Unit unit) { + if ((unit == _unit) || (unit.equals(_unit))) + return _value; + return _unit.getConverterTo(unit).convert(_value); + } + + private static final long serialVersionUID = 1L; + } + + /** + * Holds scalar implementation for long values. + */ + private static final class Integer extends + Measure { + + private final int _value; + + private final Unit _unit; + + public Integer(int value, Unit unit) { + _value = value; + _unit = unit; + } + + @Override + public Unit getUnit() { + return _unit; + } + + @Override + public java.lang.Integer getValue() { + return _value; + } + + @Override + public Measure to(Unit unit) { + if ((unit == _unit) || (unit.equals(_unit))) + return this; + return new Integer(intValue(unit), unit); + } + + public double doubleValue(Unit unit) { + if ((unit == _unit) || (unit.equals(_unit))) + return _value; + return _unit.getConverterTo(unit).convert(_value); + } + + public long longValue(Unit unit) throws ArithmeticException { + if ((unit == _unit) || (unit.equals(_unit))) + return _value; // No conversion, returns value directly. + return super.longValue(unit); + } + + private static final long serialVersionUID = 1L; + + } + + /** + * @deprecated {@link DecimalMeasure} should be used directly. + */ + public static Measure valueOf( + BigDecimal decimal, Unit unit) { + return DecimalMeasure.valueOf(decimal, unit); + } + + /** + * @deprecated {@link DecimalMeasure} should be used directly and + * MathContext specified explicitly when + * {@link DecimalMeasure#to(Unit, MathContext) converting}. + */ + public static Measure valueOf( + BigDecimal decimal, Unit unit, MathContext mathContext) { + return DecimalMeasure.valueOf(decimal, unit); + } + + /** + * @deprecated {@link VectorMeasure} should be used directly. + */ + public static Measure valueOf( + double[] components, Unit unit) { + return VectorMeasure.valueOf(components, unit); + } +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/MeasureFormat.java b/measure/src/main/java/javax/measure/MeasureFormat.java new file mode 100644 index 00000000..cd6bb68a --- /dev/null +++ b/measure/src/main/java/javax/measure/MeasureFormat.java @@ -0,0 +1,169 @@ +/* + * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences. + * Copyright (C) 2007 - 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; + +import java.math.BigDecimal; +import java.text.FieldPosition; +import java.text.Format; +import java.text.NumberFormat; +import java.text.ParseException; +import java.text.ParsePosition; + +import javax.measure.unit.CompoundUnit; +import javax.measure.unit.Unit; +import javax.measure.unit.UnitFormat; + +/** + *

This class provides the interface for formatting and parsing {@link + * Measure measures}.

+ * + *

As a minimum, instances of this class should be able to parse/format + * measure using {@link CompoundUnit}.

+ * + * @author Jean-Marie Dautelle + * @version 4.2, August 26, 2007 + */ +public abstract class MeasureFormat extends Format { + + /** + * Returns the measure format for the default locale. + * + * @return getInstance(Number.getInstance(), Unit.getInstance()) + */ + public static MeasureFormat getInstance() { + return DEFAULT; + } + + static final NumberUnit DEFAULT = new NumberUnit(NumberFormat + .getInstance(), UnitFormat.getInstance()); + + /** + * Returns the measure format using the specified number format and + * unit format (the number and unit are separated by a space). + * + * @param numberFormat the number format. + * @param unitFormat the unit format. + * @return the corresponding format. + */ + public static MeasureFormat getInstance(NumberFormat numberFormat, + UnitFormat unitFormat) { + return new NumberUnit(numberFormat, unitFormat); + } + + // Holds default implementation. + static final class NumberUnit extends MeasureFormat { + private final NumberFormat _numberFormat; + + private final UnitFormat _unitFormat; + + private NumberUnit(NumberFormat numberFormat, UnitFormat unitFormat) { + _numberFormat = numberFormat; + _unitFormat = unitFormat; + } + + @Override + public StringBuffer format(Object obj, StringBuffer toAppendTo, + FieldPosition pos) { + Measure measure = (Measure) obj; + Object value = measure.getValue(); + Unit unit = measure.getUnit(); + if (value instanceof Number) { + if (unit instanceof CompoundUnit) + return formatCompound(((Number) value).doubleValue(), + (CompoundUnit) unit, toAppendTo, pos); + _numberFormat.format(value, toAppendTo, pos); + } else { + toAppendTo.append(value); + } + if (!measure.getUnit().equals(Unit.ONE)) { + toAppendTo.append(' '); + _unitFormat.format(unit, toAppendTo, pos); + } + return toAppendTo; + } + + // Measure using Compound unit have no separators in their representation. + StringBuffer formatCompound(double value, Unit unit, + StringBuffer toAppendTo, FieldPosition pos) { + if (!(unit instanceof CompoundUnit)) { + toAppendTo.append((long) value); + return _unitFormat.format(unit, toAppendTo, pos); + } + Unit high = ((CompoundUnit) unit).getHigher(); + Unit low = ((CompoundUnit) unit).getLower(); // The unit in which the value is stated. + long highValue = (long) low.getConverterTo(high).convert(value); + double lowValue = value + - high.getConverterTo(low).convert(highValue); + formatCompound(highValue, high, toAppendTo, pos); + formatCompound(lowValue, low, toAppendTo, pos); + return toAppendTo; + } + + @Override + public Object parseObject(String source, ParsePosition pos) { + int start = pos.getIndex(); + try { + int i = start; + Number value = _numberFormat.parse(source, pos); + if (i == pos.getIndex()) + return null; // Cannot parse. + i = pos.getIndex(); + if (i >= source.length()) + return measureOf(value, Unit.ONE); // No unit. + boolean isCompound = !Character.isWhitespace(source.charAt(i)); + if (isCompound) + return parseCompound(value, source, pos); + if (++i >= source.length()) + return measureOf(value, Unit.ONE); // No unit. + pos.setIndex(i); // Skips separator. + Unit unit = _unitFormat.parseProductUnit(source, pos); + return measureOf(value, unit); + } catch (ParseException e) { + pos.setIndex(start); + pos.setErrorIndex(e.getErrorOffset()); + return null; + } + } + + @SuppressWarnings("unchecked") + private Object parseCompound(Number highValue, String source, + ParsePosition pos) throws ParseException { + Unit high = _unitFormat.parseSingleUnit(source, pos); + int i = pos.getIndex(); + if (i >= source.length() + || Character.isWhitespace(source.charAt(i))) + return measureOf(highValue, high); + Measure lowMeasure = (Measure) parseObject(source, pos); + Unit unit = lowMeasure.getUnit(); + long l = lowMeasure.longValue(unit) + + (long) high.getConverterTo(unit).convert( + highValue.longValue()); + return Measure.valueOf(l, unit); + } + + @SuppressWarnings("unchecked") + private static Measure measureOf(Number value, Unit unit) { + if (value instanceof Double) { + return Measure.valueOf(value.doubleValue(), unit); + } else if (value instanceof Long) { + return Measure.valueOf(value.longValue(), unit); + } else if (value instanceof Float) { + return Measure.valueOf(value.floatValue(), unit); + } else if (value instanceof Integer) { + return Measure.valueOf(value.intValue(), unit); + } else if (value instanceof BigDecimal) { + return DecimalMeasure.valueOf((BigDecimal) value, unit); + } else { + return Measure.valueOf(value.doubleValue(), unit); + } + } + + private static final long serialVersionUID = 1L; + } +} diff --git a/measure/src/main/java/javax/measure/VectorMeasure.java b/measure/src/main/java/javax/measure/VectorMeasure.java new file mode 100644 index 00000000..1fd4f322 --- /dev/null +++ b/measure/src/main/java/javax/measure/VectorMeasure.java @@ -0,0 +1,273 @@ +/* + * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences. + * Copyright (C) 2007 - 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; + +import javax.measure.converter.UnitConverter; +import javax.measure.quantity.Quantity; +import javax.measure.unit.CompoundUnit; +import javax.measure.unit.Unit; + +/** + *

This class represents a measurement vector of two or more dimensions. + * For example:[code] + * VectorMeasure dimension = VectorMeasure.valueOf(12.0, 30.0, 40.0, MILLIMETER); + * VectorMeasure v2d = VectorMeasure.valueOf(-2.2, -3.0, KNOTS); + * VectorMeasure c2d = VectorMeasure.valueOf(-7.3, 3.5, NANOAMPERE); + * [/code] + *

+ * + *

Subclasses may provide fixed dimensions specializations:[code] + * class Velocity2D extends VectorMeasure { + * public Velocity2D(double x, double y, Unit unit) { + * ... + * } + * } + * [/code]

+ * + *

Measurement vectors may use {@link CompoundUnit compound units}:[code] + * VectorMeasure latLong = VectorMeasure.valueOf(12.345, 22.23, DEGREE_ANGLE); + * Unit HOUR_MINUTE_SECOND_ANGLE = DEGREE_ANGLE.compound(MINUTE_ANGLE).compound(SECOND_ANGLE); + * System.out.println(latLong.to(HOUR_MINUTE_SECOND_ANGLE)); + * + * > [12°19'42", 22°12'48"] [/code]

+ * + *

Instances of this class (and sub-classes) are immutable.

+ * + * @author Jean-Marie Dautelle + * @version 4.3, October 3, 2007 + */ +public abstract class VectorMeasure extends Measure { + + /** + * Default constructor (for sub-classes). + */ + protected VectorMeasure() { + } + + /** + * Returns a 2-dimensional measurement vector. + * + * @param x the first vector component value. + * @param y the second vector component value. + * @param unit the measurement unit. + */ + public static VectorMeasure valueOf( + double x, double y, Unit unit) { + return new TwoDimensional(x, y, unit); + } + + /** + * Returns a 3-dimensional measurement vector. + * + * @param x the first vector component value. + * @param y the second vector component value. + * @param z the third vector component value. + * @param unit the measurement unit. + */ + public static VectorMeasure valueOf( + double x, double y, double z, Unit unit) { + return new ThreeDimensional(x, y, z, unit); + } + + /** + * Returns a multi-dimensional measurement vector. + * + * @param components the vector component values. + * @param unit the measurement unit. + */ + public static VectorMeasure valueOf(double[] components, + Unit unit) { + return new MultiDimensional(components, unit); + } + + /** + * Returns the measurement vector equivalent to this one but stated in the + * specified unit. + * + * @param unit the new measurement unit. + * @return the vector measure stated in the specified unit. + */ + public abstract VectorMeasure to(Unit unit); + + /** + * Returns the norm of this measurement vector stated in the specified + * unit. + * + * @param unit the unit in which the norm is stated. + * @return |this| + */ + public abstract double doubleValue(Unit unit); + + /** + * Returns the String representation of this measurement + * vector (for example [2.3 m/s, 5.6 m/s]). + * + * @return the textual representation of the measurement vector. + */ + public String toString() { + double[] values = getValue(); + Unit unit = getUnit(); + StringBuffer tmp = new StringBuffer(); + tmp.append('['); + for (double v : values) { + if (tmp.length() > 1) { + tmp.append(", "); + } + if (unit instanceof CompoundUnit) { + MeasureFormat.DEFAULT.formatCompound(v, unit, tmp, null); + } else { + tmp.append(v).append(" ").append(unit); + } + } + tmp.append("] "); + return tmp.toString(); + } + + // Holds 2-dimensional implementation. + private static class TwoDimensional extends VectorMeasure { + + private final double _x; + + private final double _y; + + private final Unit _unit; + + private TwoDimensional(double x, double y, Unit unit) { + _x = x; + _y = y; + _unit = unit; + + } + @Override + public double doubleValue(Unit unit) { + double norm = Math.sqrt(_x * _x + _y * _y); + if ((unit == _unit) || (unit.equals(_unit))) + return norm; + return _unit.getConverterTo(unit).convert(norm); + } + + @Override + public Unit getUnit() { + return _unit; + } + + @Override + public double[] getValue() { + return new double[] { _x, _y }; + } + + @Override + public TwoDimensional to(Unit unit) { + if ((unit == _unit) || (unit.equals(_unit))) + return this; + UnitConverter cvtr = _unit.getConverterTo(unit); + return new TwoDimensional(cvtr.convert(_x), cvtr.convert(_y), unit); + } + + private static final long serialVersionUID = 1L; + + } + + // Holds 3-dimensional implementation. + private static class ThreeDimensional extends VectorMeasure { + + private final double _x; + + private final double _y; + + private final double _z; + + private final Unit _unit; + + private ThreeDimensional(double x, double y, double z, Unit unit) { + _x = x; + _y = y; + _z = z; + _unit = unit; + + } + @Override + public double doubleValue(Unit unit) { + double norm = Math.sqrt(_x * _x + _y * _y + _z * _z); + if ((unit == _unit) || (unit.equals(_unit))) + return norm; + return _unit.getConverterTo(unit).convert(norm); + } + + @Override + public Unit getUnit() { + return _unit; + } + + @Override + public double[] getValue() { + return new double[] { _x, _y, _z }; + } + + @Override + public ThreeDimensional to(Unit unit) { + if ((unit == _unit) || (unit.equals(_unit))) + return this; + UnitConverter cvtr = _unit.getConverterTo(unit); + return new ThreeDimensional(cvtr.convert(_x), cvtr.convert(_y), cvtr.convert(_z), unit); + } + + private static final long serialVersionUID = 1L; + + } + // Holds multi-dimensional implementation. + private static class MultiDimensional extends VectorMeasure { + + private final double[] _components; + + private final Unit _unit; + + private MultiDimensional(double[] components, Unit unit) { + _components = components.clone(); + _unit = unit; + } + + @Override + public double doubleValue(Unit unit) { + double normSquare = _components[0] * _components[0]; + for (int i=1, n=_components.length; i < n;) { + double d = _components[i++]; + normSquare += d * d; + } + if ((unit == _unit) || (unit.equals(_unit))) + return Math.sqrt(normSquare); + return _unit.getConverterTo(unit).convert(Math.sqrt(normSquare)); + } + + @Override + public Unit getUnit() { + return _unit; + } + + @Override + public double[] getValue() { + return _components.clone(); + } + + @Override + public MultiDimensional to(Unit unit) { + if ((unit == _unit) || (unit.equals(_unit))) + return this; + UnitConverter cvtr = _unit.getConverterTo(unit); + double[] newValues = new double[_components.length]; + for (int i=0; i < _components.length; i++) { + newValues[i] = cvtr.convert(_components[i]); + } + return new MultiDimensional(newValues, unit); + } + + private static final long serialVersionUID = 1L; + + } +} diff --git a/measure/src/main/java/javax/measure/converter/AddConverter.java b/measure/src/main/java/javax/measure/converter/AddConverter.java new file mode 100644 index 00000000..2c0b8d35 --- /dev/null +++ b/measure/src/main/java/javax/measure/converter/AddConverter.java @@ -0,0 +1,80 @@ +/* + * 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; + + +/** + *

This class represents a converter adding a constant offset + * (approximated as a double) to numeric values.

+ * + *

Instances of this class are immutable.

+ * + * @author Jean-Marie Dautelle + * @version 3.1, April 22, 2006 + */ +public final class AddConverter extends UnitConverter { + + /** + * Holds the offset. + */ + private final double _offset; + + /** + * Creates an add converter with the specified offset. + * + * @param offset the offset value. + * @throws IllegalArgumentException if offset is zero (or close to zero). + */ + public AddConverter(double offset) { + if ((float)offset == 0.0) + throw new IllegalArgumentException("Identity converter not allowed"); + _offset = offset; + } + + /** + * Returns the offset value for this add converter. + * + * @return the offset value. + */ + public double getOffset() { + return _offset; + } + + @Override + public UnitConverter inverse() { + return new AddConverter(- _offset); + } + + @Override + public double convert(double amount) { + return amount + _offset; + } + + @Override + public boolean isLinear() { + return false; + } + + @Override + public UnitConverter concatenate(UnitConverter converter) { + if (converter instanceof AddConverter) { + double offset = _offset + ((AddConverter)converter)._offset; + return valueOf(offset); + } else { + return super.concatenate(converter); + } + } + + private static UnitConverter valueOf(double offset) { + float asFloat = (float) offset; + return asFloat == 0.0f ? UnitConverter.IDENTITY : new AddConverter(offset); + } + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/converter/ConversionException.java b/measure/src/main/java/javax/measure/converter/ConversionException.java new file mode 100644 index 00000000..39bd2eba --- /dev/null +++ b/measure/src/main/java/javax/measure/converter/ConversionException.java @@ -0,0 +1,38 @@ +/* + * 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; + +/** + * Signals that a problem of some sort has occurred either when creating a + * converter between two units or during the conversion itself. + * + * @author Jean-Marie Dautelle + * @version 3.1, April 2, 2006 + */ +public class ConversionException extends RuntimeException { + + /** + * Constructs a ConversionException with no detail message. + */ + public ConversionException() { + super(); + } + + /** + * Constructs a ConversionException with the specified detail + * message. + * + * @param message the detail message. + */ + public ConversionException(String message) { + super(message); + } + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/converter/LogConverter.java b/measure/src/main/java/javax/measure/converter/LogConverter.java new file mode 100644 index 00000000..f10c30b9 --- /dev/null +++ b/measure/src/main/java/javax/measure/converter/LogConverter.java @@ -0,0 +1,107 @@ +/* + * 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; + +/** + *

This class represents a logarithmic converter. Such converter + * is typically used to create logarithmic unit. For example:[code] + * Unit BEL = Unit.ONE.transform(new LogConverter(10).inverse()); + * [/code]

+ * + *

Instances of this class are immutable.

+ * + * @author Jean-Marie Dautelle + * @version 3.1, April 22, 2006 + */ +public final class LogConverter extends UnitConverter { + + /** + * Holds the logarithmic base. + */ + private final double _base; + + /** + * Holds the natural logarithm of the base. + */ + private final double _logBase; + + /** + * Holds the inverse of the natural logarithm of the base. + */ + private final double _invLogBase; + + /** + * Holds the inverse of this converter. + */ + private final Inverse _inverse = new Inverse(); + + /** + * Creates a logarithmic converter having the specified base. + * + * @param base the logarithmic base (e.g. Math.E for + * the Natural Logarithm). + */ + public LogConverter(double base) { + _base = base; + _logBase = Math.log(base); + _invLogBase = 1.0 / _logBase; + } + + /** + * Returns the logarithmic base of this converter. + * + * @return the logarithmic base (e.g. Math.E for + * the Natural Logarithm). + */ + public double getBase() { + return _base; + } + + @Override + public UnitConverter inverse() { + return _inverse; + } + + @Override + public double convert(double amount) { + return _invLogBase * Math.log(amount); + } + + @Override + public boolean isLinear() { + return false; + } + + /** + * This inner class represents the inverse of the logarithmic converter + * (exponentiation converter). + */ + private class Inverse extends UnitConverter { + + + @Override + public UnitConverter inverse() { + return LogConverter.this; + } + + @Override + public double convert(double amount) { + return Math.exp(_logBase * amount); + } + + @Override + public boolean isLinear() { + return false; + } + + private static final long serialVersionUID = 1L; + } + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/converter/MultiplyConverter.java b/measure/src/main/java/javax/measure/converter/MultiplyConverter.java new file mode 100644 index 00000000..2dfa32af --- /dev/null +++ b/measure/src/main/java/javax/measure/converter/MultiplyConverter.java @@ -0,0 +1,86 @@ +/* + * 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; + +/** + *

This class represents a converter multiplying numeric values by a + * constant scaling factor (approximated as a double). + * For exact scaling conversions {@link RationalConverter} is preferred.

+ * + *

Instances of this class are immutable.

+ * + * @author Jean-Marie Dautelle + * @version 3.1, April 22, 2006 + */ +public final class MultiplyConverter extends UnitConverter { + + /** + * Holds the scale factor. + */ + private final double _factor; + + /** + * Creates a multiply converter with the specified scale factor. + * + * @param factor the scale factor. + * @throws IllegalArgumentException if offset is one (or close to one). + */ + public MultiplyConverter(double factor) { + if ((float)factor == 1.0) + throw new IllegalArgumentException("Identity converter not allowed"); + _factor = factor; + } + + /** + * Returns the scale factor. + * + * @return the scale factor. + */ + public double getFactor() { + return _factor; + } + + @Override + public UnitConverter inverse() { + return new MultiplyConverter(1.0 / _factor); + } + + @Override + public double convert(double amount) { + return _factor * amount; + } + + @Override + public boolean isLinear() { + return true; + } + + @Override + public UnitConverter concatenate(UnitConverter converter) { + if (converter instanceof MultiplyConverter) { + double factor = _factor * ((MultiplyConverter) converter)._factor; + return valueOf(factor); + } else if (converter instanceof RationalConverter) { + double factor = _factor + * ((RationalConverter) converter).getDividend() + / ((RationalConverter) converter).getDivisor(); + return valueOf(factor); + } else { + return super.concatenate(converter); + } + } + + private static UnitConverter valueOf(double factor) { + float asFloat = (float) factor; + return asFloat == 1.0f ? UnitConverter.IDENTITY + : new MultiplyConverter(factor); + } + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/converter/RationalConverter.java b/measure/src/main/java/javax/measure/converter/RationalConverter.java new file mode 100644 index 00000000..0186683b --- /dev/null +++ b/measure/src/main/java/javax/measure/converter/RationalConverter.java @@ -0,0 +1,127 @@ +/* + * 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; + +/** + *

This class represents a converter multiplying numeric values by an + * exact scaling factor (represented as the quotient of two + * long numbers).

+ * + *

Instances of this class are immutable.

+ * + * @author Jean-Marie Dautelle + * @version 3.1, April 22, 2006 + */ +public final class RationalConverter extends UnitConverter { + + /** + * Holds the converter dividend. + */ + private final long _dividend; + + /** + * Holds the converter divisor (always positive). + */ + private final long _divisor; + + /** + * Creates a rational converter with the specified dividend and + * divisor. + * + * @param dividend the dividend. + * @param divisor the positive divisor. + * @throws IllegalArgumentException if divisor < 0 + * @throws IllegalArgumentException if dividend == divisor + */ + public RationalConverter(long dividend, long divisor) { + if (divisor < 0) + throw new IllegalArgumentException("Negative divisor"); + if (dividend == divisor) + throw new IllegalArgumentException("Identity converter not allowed"); + _dividend = dividend; + _divisor = divisor; + } + + /** + * Returns the dividend for this rational converter. + * + * @return this converter dividend. + */ + public long getDividend() { + return _dividend; + } + + /** + * Returns the positive divisor for this rational converter. + * + * @return this converter divisor. + */ + public long getDivisor() { + return _divisor; + } + + @Override + public UnitConverter inverse() { + return _dividend < 0 ? new RationalConverter(-_divisor, -_dividend) + : new RationalConverter(_divisor, _dividend); + } + + @Override + public double convert(double amount) { + return amount * _dividend / _divisor; + } + + @Override + public boolean isLinear() { + return true; + } + + @Override + public UnitConverter concatenate(UnitConverter converter) { + if (converter instanceof RationalConverter) { + RationalConverter that = (RationalConverter) converter; + long dividendLong = this._dividend * that._dividend; + long divisorLong = this._divisor * that._divisor; + double dividendDouble = ((double)this._dividend) * that._dividend; + double divisorDouble = ((double)this._divisor) * that._divisor; + if ((dividendLong != dividendDouble) || + (divisorLong != divisorDouble)) { // Long overflows. + return new MultiplyConverter(dividendDouble / divisorDouble); + } + long gcd = gcd(dividendLong, divisorLong); + return RationalConverter.valueOf(dividendLong / gcd, divisorLong / gcd); + } else if (converter instanceof MultiplyConverter) { + return converter.concatenate(this); + } else { + return super.concatenate(converter); + } + } + + private static UnitConverter valueOf(long dividend, long divisor) { + return (dividend == 1L) && (divisor == 1L) ? UnitConverter.IDENTITY + : new RationalConverter(dividend, divisor); + } + + /** + * Returns the greatest common divisor (Euclid's algorithm). + * + * @param m the first number. + * @param nn the second number. + * @return the greatest common divisor. + */ + private static long gcd(long m, long n) { + if (n == 0L) { + return m; + } else { + return gcd(n, m % n); + } + } + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/converter/UnitConverter.java b/measure/src/main/java/javax/measure/converter/UnitConverter.java new file mode 100644 index 00000000..03dcd05e --- /dev/null +++ b/measure/src/main/java/javax/measure/converter/UnitConverter.java @@ -0,0 +1,188 @@ +/* + * 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; + + } +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/converter/doc-files/converter.png b/measure/src/main/java/javax/measure/converter/doc-files/converter.png new file mode 100644 index 00000000..4a2fdba4 Binary files /dev/null and b/measure/src/main/java/javax/measure/converter/doc-files/converter.png differ diff --git a/measure/src/main/java/javax/measure/converter/package.html b/measure/src/main/java/javax/measure/converter/package.html new file mode 100644 index 00000000..667176ee --- /dev/null +++ b/measure/src/main/java/javax/measure/converter/package.html @@ -0,0 +1,5 @@ + +

Provides support for unit conversion.

+

UML Diagram

+ UML Diagram + \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/package.html b/measure/src/main/java/javax/measure/package.html new file mode 100644 index 00000000..3579c941 --- /dev/null +++ b/measure/src/main/java/javax/measure/package.html @@ -0,0 +1,77 @@ + +

Provides strongly typed measurements to enforce compile-time + check of parameters consistency and avoid interface errors.

+ +

Let's take the following example:[code] + class Person { + void setWeight(double weight); + }[/code] + Should the weight be in pound, kilogram ??
+ Using measures there is no room for error:[code] + class Person { + void setWeight(Measurable weight); + }[/code] + Not only the interface is cleaner (the weight has to be of mass type); + but also there is no confusion on the measurement unit:[code] + double weightInKg = weight.doubleValue(KILOGRAM); + double weightInLb = weight.doubleValue(POUND);[/code] + Measurable work hand-in-hand with units (also parameterized). + For example, the following would result in compile-time error:[code] + double weightInLiter = weight.doubleValue(LITER); // Compile error, Unit required. + [/code]

+ +

Users may create their own {@link javax.measure.Measurable + Measurable} implementation:[code] + + public class Period implements Measurable { + long nanoseconds; + ... + } + + public class Distance implements Measurable { + double meters; + ... + } + + public class Velocity3D implements Measurable { + double x, y, z; // In meters. + ... + } + + +[/code]

+ +

Users may also combine a definite amount (scalar, vector, collection, etc.) + to a unit and make it a {@link javax.measure.Measure Measure} (and + a {@link javax.measure.Measurable Measurable} instance). For example: + [code] + + // Scalar measurement (numerical). + person.setWeight(Measure.valueOf(180.0, POUND)); // Measure + timer.setPeriod(Measure.valueOf(20, MILLI(SECOND)); // Measure + circuit.setCurrent(Measure.valueOf(Complex.valueOf(2, -3), AMPERE); // (2 - 3i) A + bottle.setPression(Measure.valueOf(Rational.valueOf(20, 100), ATMOSPHERE)); // (20/100) Atm + + // Vector measurement. + abstract class MeasureVector extends Measure { + ... // doubleValue(Unit) returns vector norm. + } + MeasureVector v = MeasureVector.valueOf(METRE_PER_SECOND, 1.0, 2.0, 3.0); + plane.setVelocity(v); + + // Statistical measurement. + class Average extends Measure{ + ... // doubleValue(Unit) returns average value. + } + sea.setTemperature(Average.valueOf(new double[] { 33.4, 44.55, 32.33} , CELCIUS)); + + // Measurement with uncertainty (and additional operations). + public class Amount extends Measurable { + public Amount(double value, double error, Unit unit) { ... } + public Amount plus(Amount that) {...} + public Amount times(Amount that) {...} + ... // doubleValue(Unit) returns estimated value. + } + [/code]

+ + \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/Acceleration.java b/measure/src/main/java/javax/measure/quantity/Acceleration.java new file mode 100644 index 00000000..ab58ecf1 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/Acceleration.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the rate of change of velocity with respect to + * time. The system unit for this quantity is "m/s²" (meter per square second). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface Acceleration extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.METRES_PER_SQUARE_SECOND; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/AmountOfSubstance.java b/measure/src/main/java/javax/measure/quantity/AmountOfSubstance.java new file mode 100644 index 00000000..f95658d9 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/AmountOfSubstance.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the number of elementary entities (molecules, for + * example) of a substance. The system unit for this quantity is "mol" (mole). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface AmountOfSubstance extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.MOLE; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/Angle.java b/measure/src/main/java/javax/measure/quantity/Angle.java new file mode 100644 index 00000000..e0463957 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/Angle.java @@ -0,0 +1,28 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the figure formed by two lines diverging from a + * common point. The system unit for this quantity is "rad" (radian). + * This quantity is dimensionless. + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface Angle extends Dimensionless { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.RADIAN; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/AngularAcceleration.java b/measure/src/main/java/javax/measure/quantity/AngularAcceleration.java new file mode 100644 index 00000000..f951a265 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/AngularAcceleration.java @@ -0,0 +1,30 @@ +/* + * 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.quantity; +import javax.measure.unit.ProductUnit; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the rate of change of angular velocity with respect + * to time. The system unit for this quantity is "rad/s²" (radian per + * square second). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface AngularAcceleration extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT + = new ProductUnit(SI.RADIAN.divide(SI.SECOND.pow(2))); + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/AngularVelocity.java b/measure/src/main/java/javax/measure/quantity/AngularVelocity.java new file mode 100644 index 00000000..d12e9090 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/AngularVelocity.java @@ -0,0 +1,30 @@ +/* + * 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.quantity; +import javax.measure.unit.ProductUnit; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the rate of change of angular displacement + * with respect to time. The system unit for this quantity is "rad/s" + * (radian per second). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface AngularVelocity extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT + = new ProductUnit(SI.RADIAN.divide(SI.SECOND)); + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/Area.java b/measure/src/main/java/javax/measure/quantity/Area.java new file mode 100644 index 00000000..da6998b7 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/Area.java @@ -0,0 +1,28 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the extent of a planar region or of the surface of + * a solid measured in square units. The system unit for this quantity + * is "m²" (square meter). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface Area extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.SQUARE_METRE; + +} diff --git a/measure/src/main/java/javax/measure/quantity/CatalyticActivity.java b/measure/src/main/java/javax/measure/quantity/CatalyticActivity.java new file mode 100644 index 00000000..de71c9f4 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/CatalyticActivity.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents a catalytic activity. The system unit for this + * quantity is "kat" (katal). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface CatalyticActivity extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.KATAL; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/DataAmount.java b/measure/src/main/java/javax/measure/quantity/DataAmount.java new file mode 100644 index 00000000..5669b0a3 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/DataAmount.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents a measure of data amount. + * The system unit for this quantity is "bit". This quantity is dimensionless. + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface DataAmount extends Dimensionless { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.BIT; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/DataRate.java b/measure/src/main/java/javax/measure/quantity/DataRate.java new file mode 100644 index 00000000..357cbac1 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/DataRate.java @@ -0,0 +1,28 @@ +/* + * 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.quantity; +import javax.measure.unit.ProductUnit; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the speed of data-transmission. + * The system unit for this quantity is "bit/s" (bit per second). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface DataRate extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = new ProductUnit(SI.BIT.divide(SI.SECOND)); + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/Dimensionless.java b/measure/src/main/java/javax/measure/quantity/Dimensionless.java new file mode 100644 index 00000000..64b8b59e --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/Dimensionless.java @@ -0,0 +1,25 @@ +/* + * 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.quantity; +import javax.measure.unit.Unit; + +/** + * This interface represents a dimensionless quantity. + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface Dimensionless extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = Unit.ONE; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/Duration.java b/measure/src/main/java/javax/measure/quantity/Duration.java new file mode 100644 index 00000000..d2b3e7f0 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/Duration.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents a period of existence or persistence. The system + * unit for this quantity is "s" (second). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface Duration extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.SECOND; + +} diff --git a/measure/src/main/java/javax/measure/quantity/DynamicViscosity.java b/measure/src/main/java/javax/measure/quantity/DynamicViscosity.java new file mode 100644 index 00000000..614fc96e --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/DynamicViscosity.java @@ -0,0 +1,32 @@ +/* + * 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.quantity; + +import javax.measure.unit.ProductUnit; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the dynamic viscosity. + * The system unit for this quantity is "Pa·s" (Pascal-Second). + * + * @author Jean-Marie Dautelle + * @version 3.0, March 2, 2006 + * @see + * Wikipedia: Viscosity + */ +public interface DynamicViscosity extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT + = new ProductUnit(SI.PASCAL.times(SI.SECOND)); + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/ElectricCapacitance.java b/measure/src/main/java/javax/measure/quantity/ElectricCapacitance.java new file mode 100644 index 00000000..9fdba372 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/ElectricCapacitance.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents an electric capacitance. The system unit for this + * quantity is "F" (Farad). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface ElectricCapacitance extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.FARAD; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/ElectricCharge.java b/measure/src/main/java/javax/measure/quantity/ElectricCharge.java new file mode 100644 index 00000000..c530d5b3 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/ElectricCharge.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents an electric charge. The system unit for this + * quantity is "C" (Coulomb). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface ElectricCharge extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.COULOMB; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/ElectricConductance.java b/measure/src/main/java/javax/measure/quantity/ElectricConductance.java new file mode 100644 index 00000000..7b59bce9 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/ElectricConductance.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents an electric conductance. The system unit for this + * quantity "S" (Siemens). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface ElectricConductance extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.SIEMENS; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/ElectricCurrent.java b/measure/src/main/java/javax/measure/quantity/ElectricCurrent.java new file mode 100644 index 00000000..3c43eea4 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/ElectricCurrent.java @@ -0,0 +1,28 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the amount of electric charge flowing past + * a specified circuit point per unit time. The system unit for + * this quantity is "A" (Ampere). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface ElectricCurrent extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.AMPERE; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/ElectricInductance.java b/measure/src/main/java/javax/measure/quantity/ElectricInductance.java new file mode 100644 index 00000000..1dccb736 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/ElectricInductance.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents an electric inductance. The system unit for this + * quantity is "H" (Henry). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface ElectricInductance extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.HENRY; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/ElectricPotential.java b/measure/src/main/java/javax/measure/quantity/ElectricPotential.java new file mode 100644 index 00000000..f09d9864 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/ElectricPotential.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents an electric potential or electromotive force. + * The system unit for this quantity is "V" (Volt). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface ElectricPotential extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.VOLT; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/ElectricResistance.java b/measure/src/main/java/javax/measure/quantity/ElectricResistance.java new file mode 100644 index 00000000..a468e641 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/ElectricResistance.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents an electric resistance. + * The system unit for this quantity is "Ω" (Ohm). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface ElectricResistance extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.OHM; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/Energy.java b/measure/src/main/java/javax/measure/quantity/Energy.java new file mode 100644 index 00000000..23ab2232 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/Energy.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the capacity of a physical system to do work. + * The system unit for this quantity "J" (Joule). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface Energy extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.JOULE; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/Force.java b/measure/src/main/java/javax/measure/quantity/Force.java new file mode 100644 index 00000000..a3f966fc --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/Force.java @@ -0,0 +1,28 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents a quantity that tends to produce an acceleration + * of a body in the direction of its application. The system unit for + * this quantity is "N" (Newton). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface Force extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.NEWTON; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/Frequency.java b/measure/src/main/java/javax/measure/quantity/Frequency.java new file mode 100644 index 00000000..76534615 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/Frequency.java @@ -0,0 +1,28 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the number of times a specified phenomenon occurs + * within a specified interval. The system unit for this quantity is "Hz" + * (Hertz). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface Frequency extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.HERTZ; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/Illuminance.java b/measure/src/main/java/javax/measure/quantity/Illuminance.java new file mode 100644 index 00000000..86ca46a0 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/Illuminance.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents an illuminance. The system unit for this quantity + * is "lx" (lux). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface Illuminance extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.LUX; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/KinematicViscosity.java b/measure/src/main/java/javax/measure/quantity/KinematicViscosity.java new file mode 100644 index 00000000..9ff9f7f6 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/KinematicViscosity.java @@ -0,0 +1,31 @@ +/* + * 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.quantity; +import javax.measure.unit.ProductUnit; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the diffusion of momentum. + * The system unit for this quantity is "m²/s". + * + * @author Jean-Marie Dautelle + * @version 3.0, March 2, 2006 + * @see + * Wikipedia: Viscosity + */ +public interface KinematicViscosity extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT + = new ProductUnit(SI.METRE.pow(2).divide(SI.SECOND)); + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/Length.java b/measure/src/main/java/javax/measure/quantity/Length.java new file mode 100644 index 00000000..75d70daa --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/Length.java @@ -0,0 +1,28 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the extent of something along its greatest + * dimension or the extent of space between two objects or places. + * The system unit for this quantity is "m" (meter). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface Length extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.METRE; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/LuminousFlux.java b/measure/src/main/java/javax/measure/quantity/LuminousFlux.java new file mode 100644 index 00000000..81ab143d --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/LuminousFlux.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents a luminous flux. The system unit for this quantity + * is "lm" (lumen). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface LuminousFlux extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.LUMEN; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/LuminousIntensity.java b/measure/src/main/java/javax/measure/quantity/LuminousIntensity.java new file mode 100644 index 00000000..cbe6ee35 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/LuminousIntensity.java @@ -0,0 +1,28 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the luminous flux density per solid angle as + * measured in a given direction relative to the emitting source. + * The system unit for this quantity is "cd" (candela). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface LuminousIntensity extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.CANDELA; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/MagneticFlux.java b/measure/src/main/java/javax/measure/quantity/MagneticFlux.java new file mode 100644 index 00000000..855ccb4c --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/MagneticFlux.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents a magnetic flux. The system unit for this quantity + * is "Wb" (Weber). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface MagneticFlux extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.WEBER; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/MagneticFluxDensity.java b/measure/src/main/java/javax/measure/quantity/MagneticFluxDensity.java new file mode 100644 index 00000000..d23986ce --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/MagneticFluxDensity.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents a magnetic flux density. The system unit for this + * quantity is "T" (Tesla). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface MagneticFluxDensity extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.TESLA; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/Mass.java b/measure/src/main/java/javax/measure/quantity/Mass.java new file mode 100644 index 00000000..d3e68959 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/Mass.java @@ -0,0 +1,29 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the measure of the quantity of matter that a body + * or an object contains. The mass of the body is not dependent on gravity + * and therefore is different from but proportional to its weight. + * The system unit for this quantity is "kg" (kilogram). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface Mass extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.KILOGRAM; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/MassFlowRate.java b/measure/src/main/java/javax/measure/quantity/MassFlowRate.java new file mode 100644 index 00000000..5b91682f --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/MassFlowRate.java @@ -0,0 +1,31 @@ +/* + * 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.quantity; + +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the movement of mass per time. + * The system unit for this quantity is "kg/s" (kilogram per second). + * + * @author Jean-Marie Dautelle + * @version 3.0, March 2, 2006 + * @see + * Wikipedia: Mass Flow Rate + */ +public interface MassFlowRate extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + @SuppressWarnings("unchecked") + public final static Unit UNIT + = (Unit) SI.KILOGRAM.divide(SI.SECOND); +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/Power.java b/measure/src/main/java/javax/measure/quantity/Power.java new file mode 100644 index 00000000..14eef502 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/Power.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the rate at which work is done. The system unit + * for this quantity is "W" (Watt). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface Power extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.WATT; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/Pressure.java b/measure/src/main/java/javax/measure/quantity/Pressure.java new file mode 100644 index 00000000..758438e1 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/Pressure.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents a force applied uniformly over a surface. + * The system unit for this quantity is "Pa" (Pascal). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface Pressure extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.PASCAL; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/Quantity.java b/measure/src/main/java/javax/measure/quantity/Quantity.java new file mode 100644 index 00000000..0272c0a9 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/Quantity.java @@ -0,0 +1,31 @@ +/* + * 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.quantity; + +/** + *

This interface represents any type of quantitative properties or + * attributes of thing. Mass, time, distance, heat, and angular separation + * are among the familiar examples of quantitative properties.

+ * + *

Distinct quantities have usually different physical dimensions; although + * it is not required nor necessary, for example {@link Torque} and + * {@link Energy} have same dimension but are of different nature + * (vector for torque, scalar for energy).

+ * + * @author Jean-Marie Dautelle + * @version 4.0, February 25, 2007 + * @see Wikipedia: Quantity + * @see + * Wikipedia: Dimensional Analysis + */ +public interface Quantity { + + // No method - Tagging interface. + +} diff --git a/measure/src/main/java/javax/measure/quantity/RadiationDoseAbsorbed.java b/measure/src/main/java/javax/measure/quantity/RadiationDoseAbsorbed.java new file mode 100644 index 00000000..21cd2651 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/RadiationDoseAbsorbed.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the amount of energy deposited per unit of + * mass. The system unit for this quantity is "Gy" (Gray). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface RadiationDoseAbsorbed extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.GRAY; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/RadiationDoseEffective.java b/measure/src/main/java/javax/measure/quantity/RadiationDoseEffective.java new file mode 100644 index 00000000..e34ca927 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/RadiationDoseEffective.java @@ -0,0 +1,28 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the effective (or "equivalent") dose of radiation + * received by a human or some other living organism. The system unit for + * this quantity is "Sv" (Sievert). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface RadiationDoseEffective extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.SIEVERT; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/RadioactiveActivity.java b/measure/src/main/java/javax/measure/quantity/RadioactiveActivity.java new file mode 100644 index 00000000..e5423611 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/RadioactiveActivity.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents a radioactive activity. The system unit for + * this quantity is "Bq" (Becquerel). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface RadioactiveActivity extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.BECQUEREL; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/SolidAngle.java b/measure/src/main/java/javax/measure/quantity/SolidAngle.java new file mode 100644 index 00000000..bcdd5af4 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/SolidAngle.java @@ -0,0 +1,28 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the angle formed by three or more planes intersecting + * at a common point. The system unit for this quantity is "sr" (steradian). + * This quantity is dimensionless. + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface SolidAngle extends Dimensionless { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.STERADIAN; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/Temperature.java b/measure/src/main/java/javax/measure/quantity/Temperature.java new file mode 100644 index 00000000..1b4e600d --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/Temperature.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This class represents the degree of hotness or coldness of a body or + * an environment. The system unit for this quantity is "K" (Kelvin). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface Temperature extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.KELVIN; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/Torque.java b/measure/src/main/java/javax/measure/quantity/Torque.java new file mode 100644 index 00000000..d12ac674 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/Torque.java @@ -0,0 +1,34 @@ +/* + * 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.quantity; +import javax.measure.unit.ProductUnit; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the moment of a force. The system unit for this + * quantity is "N·m" (Newton-Meter). + * + *

Note: The Newton-metre ("N·m") is also a way of exressing a Joule (unit + * of energy). However, torque is not energy. So, to avoid confusion, we + * will use the units "N·m" for torque and not "J". This distinction occurs + * due to the scalar nature of energy and the vector nature of torque.

+ * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface Torque extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = + new ProductUnit(SI.NEWTON.times(SI.METRE)); + +} diff --git a/measure/src/main/java/javax/measure/quantity/Velocity.java b/measure/src/main/java/javax/measure/quantity/Velocity.java new file mode 100644 index 00000000..29fbbea9 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/Velocity.java @@ -0,0 +1,27 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents a distance traveled divided by the time of travel. + * The system unit for this quantity is "m/s" (meter per second). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface Velocity extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.METRES_PER_SECOND; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/Volume.java b/measure/src/main/java/javax/measure/quantity/Volume.java new file mode 100644 index 00000000..7a76371e --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/Volume.java @@ -0,0 +1,28 @@ +/* + * 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.quantity; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the amount of space occupied by a three-dimensional + * object or region of space, expressed in cubic units. The system unit for + * this quantity is "m³" (cubic meter). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface Volume extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = SI.CUBIC_METRE; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/VolumetricDensity.java b/measure/src/main/java/javax/measure/quantity/VolumetricDensity.java new file mode 100644 index 00000000..72873f68 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/VolumetricDensity.java @@ -0,0 +1,30 @@ +/* + * 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.quantity; + +import javax.measure.unit.ProductUnit; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents a mass per unit volume of a substance under + * specified conditions of pressure and temperature. The system unit for + * this quantity is "kg/m³" (kilogram per cubic meter). + * + * @author Jean-Marie Dautelle + * @version 1.0, January 14, 2006 + */ +public interface VolumetricDensity extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + public final static Unit UNIT = new ProductUnit( + SI.KILOGRAM.divide(SI.METRE.pow(3))); +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/VolumetricFlowRate.java b/measure/src/main/java/javax/measure/quantity/VolumetricFlowRate.java new file mode 100644 index 00000000..2d288072 --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/VolumetricFlowRate.java @@ -0,0 +1,32 @@ +/* + * 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.quantity; + +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +/** + * This interface represents the volume of fluid passing a point in a system + * per unit of time. The system unit for this quantity is "m³/s" + * (cubic meter per second). + * + * @author Jean-Marie Dautelle + * @version 3.0, March 2, 2006 + * @see + * Wikipedia: Volumetric Flow Rate + */ +public interface VolumetricFlowRate extends Quantity { + + /** + * Holds the SI unit (Système International d'Unités) for this quantity. + */ + @SuppressWarnings("unchecked") + public final static Unit UNIT + = (Unit) SI.METRE.pow(3).divide(SI.SECOND); +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/quantity/package.html b/measure/src/main/java/javax/measure/quantity/package.html new file mode 100644 index 00000000..b6994cac --- /dev/null +++ b/measure/src/main/java/javax/measure/quantity/package.html @@ -0,0 +1,6 @@ + +

Provides quantitative properties or attributes of thing such as + mass, time, distance, heat, and angular separation.

+

Each quantity sub-interface holds a static UNIT field + holding the standard unit for the quantity.

+ \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/unit/AlternateUnit.java b/measure/src/main/java/javax/measure/unit/AlternateUnit.java new file mode 100644 index 00000000..39aca239 --- /dev/null +++ b/measure/src/main/java/javax/measure/unit/AlternateUnit.java @@ -0,0 +1,126 @@ +/* + * 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.unit; + +import javax.measure.converter.UnitConverter; +import javax.measure.quantity.Quantity; + +/** + *

This class represents the units used in expressions to distinguish + * between quantities of a different nature but of the same dimensions.

+ * + *

Instances of this class are created through the + * {@link Unit#alternate(String)} method.

+ * + * @author Jean-Marie Dautelle + * @version 4.2, August 26, 2007 + */ +public final class AlternateUnit extends DerivedUnit { + + /** + * Holds the symbol. + */ + private final String _symbol; + + /** + * Holds the parent unit (a system unit). + */ + private final Unit _parent; + + /** + * Creates an alternate unit for the specified unit identified by the + * specified symbol. + * + * @param symbol the symbol for this alternate unit. + * @param parent the system unit from which this alternate unit is + * derived. + * @throws UnsupportedOperationException if the source is not + * a standard unit. + * @throws IllegalArgumentException if the specified symbol is + * associated to a different unit. + */ + AlternateUnit(String symbol, Unit parent) { + if (!parent.isStandardUnit()) + throw new UnsupportedOperationException(this + + " is not a standard unit"); + _symbol = symbol; + _parent = parent; + // Checks if the symbol is associated to a different unit. + synchronized (Unit.SYMBOL_TO_UNIT) { + Unit unit = Unit.SYMBOL_TO_UNIT.get(symbol); + if (unit == null) { + Unit.SYMBOL_TO_UNIT.put(symbol, this); + return; + } + if (unit instanceof AlternateUnit) { + AlternateUnit existingUnit = (AlternateUnit) unit; + if (symbol.equals(existingUnit._symbol) + && _parent.equals(existingUnit._parent)) + return; // OK, same unit. + } + throw new IllegalArgumentException("Symbol " + symbol + + " is associated to a different unit"); + } + } + + /** + * Returns the symbol for this alternate unit. + * + * @return this alternate unit symbol. + */ + public final String getSymbol() { + return _symbol; + } + + /** + * Returns the parent unit from which this alternate unit is derived + * (a system unit itself). + * + * @return the parent of the alternate unit. + */ + @SuppressWarnings("unchecked") + public final Unit getParent() { + return (Unit) _parent; + } + + @Override + public final Unit getStandardUnit() { + return this; + } + + @Override + public final UnitConverter toStandardUnit() { + return UnitConverter.IDENTITY; + } + + /** + * Indicates if this alternate unit is considered equals to the specified + * object (both are alternate units with equal symbol, equal base units + * and equal converter to base units). + * + * @param that the object to compare for equality. + * @return true if this and that + * are considered equals; falseotherwise. + */ + public boolean equals(Object that) { + if (this == that) + return true; + if (!(that instanceof AlternateUnit)) + return false; + AlternateUnit thatUnit = (AlternateUnit) that; + return this._symbol.equals(thatUnit._symbol); // Symbols are unique. + } + + // Implements abstract method. + public int hashCode() { + return _symbol.hashCode(); + } + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/unit/BaseUnit.java b/measure/src/main/java/javax/measure/unit/BaseUnit.java new file mode 100644 index 00000000..96403b83 --- /dev/null +++ b/measure/src/main/java/javax/measure/unit/BaseUnit.java @@ -0,0 +1,112 @@ +/* + * 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.unit; + +import javax.measure.converter.UnitConverter; +import javax.measure.quantity.Quantity; + +/** + *

This class represents the building blocks on top of which all others + * units are created. Base units are typically dimensionally independent. + * The actual unit dimension is determinated by the current + * {@link Dimension.Model model}. For example using the {@link + * Dimension.Model#STANDARD standard} model, {@link SI#CANDELA} + * has the dimension of {@link SI#WATT watt}:[code] + * // Standard model. + * BaseUnit METER = new BaseUnit("m"); + * BaseUnit CANDELA = new BaseUnit("cd"); + * System.out.println(METER.getDimension()); + * System.out.println(CANDELA.getDimension()); + * + * > [L] + * > [L]²·[M]/[T]³ + * [/code]

+ *

This class represents the "standard base units" which includes SI base + * units and possibly others user-defined base units. It does not represent + * the base units of any specific {@link SystemOfUnits} (they would have + * be base units accross all possible systems otherwise).

+ * + * @author Jean-Marie Dautelle + * @version 3.1, April 22, 2006 + * @see + * Wikipedia: SI base unit + */ +public class BaseUnit extends Unit { + + /** + * Holds the symbol. + */ + private final String _symbol; + + /** + * Creates a base unit having the specified symbol. + * + * @param symbol the symbol of this base unit. + * @throws IllegalArgumentException if the specified symbol is + * associated to a different unit. + */ + public BaseUnit(String symbol) { + _symbol = symbol; + // Checks if the symbol is associated to a different unit. + synchronized (Unit.SYMBOL_TO_UNIT) { + Unit unit = Unit.SYMBOL_TO_UNIT.get(symbol); + if (unit == null) { + Unit.SYMBOL_TO_UNIT.put(symbol, this); + return; + } + if (!(unit instanceof BaseUnit)) + throw new IllegalArgumentException("Symbol " + symbol + + " is associated to a different unit"); + } + } + + /** + * Returns the unique symbol for this base unit. + * + * @return this base unit symbol. + */ + public final String getSymbol() { + return _symbol; + } + + /** + * Indicates if this base unit is considered equals to the specified + * object (both are base units with equal symbol, standard dimension and + * standard transform). + * + * @param that the object to compare for equality. + * @return true if this and that + * are considered equals; falseotherwise. + */ + public boolean equals(Object that) { + if (this == that) + return true; + if (!(that instanceof BaseUnit)) + return false; + BaseUnit thatUnit = (BaseUnit) that; + return this._symbol.equals(thatUnit._symbol); + } + + @Override + public int hashCode() { + return _symbol.hashCode(); + } + + @Override + public Unit getStandardUnit() { + return this; + } + + @Override + public UnitConverter toStandardUnit() { + return UnitConverter.IDENTITY; + } + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/unit/CompoundUnit.java b/measure/src/main/java/javax/measure/unit/CompoundUnit.java new file mode 100644 index 00000000..82bc88dd --- /dev/null +++ b/measure/src/main/java/javax/measure/unit/CompoundUnit.java @@ -0,0 +1,109 @@ +/* + * 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.unit; + +import javax.measure.converter.UnitConverter; +import javax.measure.quantity.Quantity; + +/** + *

This class represents the multi-radix units (such as "hour:min:sec"). + * Instances of this class are created using the {@link Unit#compound + * Unit.compound} method.

+ * + *

Examples of compound units:[code] + * Unit HOUR_MINUTE_SECOND = HOUR.compound(MINUTE).compound(SECOND); + * Unit DEGREE_MINUTE_ANGLE = DEGREE_ANGLE.compound(MINUTE_ANGLE); + * [/code]

+ * + * @author Jean-Marie Dautelle + * @version 3.1, April 22, 2006 + */ +public final class CompoundUnit extends DerivedUnit { + + /** + * Holds the higher unit. + */ + private final Unit _high; + + /** + * Holds the lower unit. + */ + private final Unit _low; + + /** + * Creates a compound unit from the specified units. + * + * @param high the high unit. + * @param low the lower unit(s) + * @throws IllegalArgumentException if both units do not the same system + * unit. + */ + CompoundUnit(Unit high, Unit low) { + if (!high.getStandardUnit().equals(low.getStandardUnit())) + throw new IllegalArgumentException( + "Both units do not have the same system unit"); + _high = high; + _low = low; + + } + + /** + * Returns the lower unit of this compound unit. + * + * @return the lower unit. + */ + public Unit getLower() { + return _low; + } + + /** + * Returns the higher unit of this compound unit. + * + * @return the higher unit. + */ + public Unit getHigher() { + return _high; + } + + /** + * Indicates if this compound unit is considered equals to the specified + * object (both are compound units with same composing units in the + * same order). + * + * @param that the object to compare for equality. + * @return true if this and that + * are considered equals; falseotherwise. + */ + public boolean equals(Object that) { + if (this == that) + return true; + if (!(that instanceof CompoundUnit)) + return false; + CompoundUnit thatUnit = (CompoundUnit) that; + return this._high.equals(thatUnit._high) + && this._low.equals(thatUnit._low); + } + + @Override + public int hashCode() { + return _high.hashCode() ^ _low.hashCode(); + } + + @Override + public Unit getStandardUnit() { + return _low.getStandardUnit(); + } + + @Override + public UnitConverter toStandardUnit() { + return _low.toStandardUnit(); + } + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/unit/DerivedUnit.java b/measure/src/main/java/javax/measure/unit/DerivedUnit.java new file mode 100644 index 00000000..5dd1d51f --- /dev/null +++ b/measure/src/main/java/javax/measure/unit/DerivedUnit.java @@ -0,0 +1,27 @@ +/* + * 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.unit; + +import javax.measure.quantity.Quantity; + +/** + *

This class identifies the units created by combining or transforming + * other units.

+ * + * @author Jean-Marie Dautelle + * @version 3.1, April 22, 2006 + */ +public abstract class DerivedUnit extends Unit { + + /** + * Default constructor. + */ + protected DerivedUnit() { + } +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/unit/Dimension.java b/measure/src/main/java/javax/measure/unit/Dimension.java new file mode 100644 index 00000000..094f22d8 --- /dev/null +++ b/measure/src/main/java/javax/measure/unit/Dimension.java @@ -0,0 +1,259 @@ +/* + * 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.unit; + +import java.io.Serializable; + +import javax.measure.converter.RationalConverter; +import javax.measure.converter.UnitConverter; +import javax.measure.quantity.Dimensionless; + +/** + *

This class represents the dimension of an unit. Two units u1 + * and u2 are {@link Unit#isCompatible compatible} if and + * only if (u1.getDimension().equals(u2.getDimension()))) + *

+ * + *

Instances of this class are immutable.

+ * + * @author Jean-Marie Dautelle + * @version 3.1, April 22, 2006 + * @see + * Wikipedia: Dimensional Analysis + */ +public final class Dimension implements Serializable { + + /** + * Holds the current physical model. + */ + private static Model CurrentModel = Model.STANDARD; + + /** + * Holds dimensionless. + */ + public static final Dimension NONE = new Dimension(Unit.ONE); + + /** + * Holds length dimension (L). + */ + public static final Dimension LENGTH = new Dimension('L'); + + /** + * Holds mass dimension (M). + */ + public static final Dimension MASS = new Dimension('M'); + + /** + * Holds time dimension (T). + */ + public static final Dimension TIME = new Dimension('T'); + + /** + * Holds electric current dimension (I). + */ + public static final Dimension ELECTRIC_CURRENT = new Dimension('I'); + + /** + * Holds temperature dimension (θ). + */ + public static final Dimension TEMPERATURE = new Dimension('θ'); + + /** + * Holds amount of substance dimension (N). + */ + public static final Dimension AMOUNT_OF_SUBSTANCE = new Dimension('N'); + + /** + * Holds the pseudo unit associated to this dimension. + */ + private final Unit _pseudoUnit; + + /** + * Creates a new dimension associated to the specified symbol. + * + * @param symbol the associated symbol. + */ + public Dimension(char symbol) { + _pseudoUnit = new BaseUnit("[" + symbol + "]"); + } + + /** + * Creates a dimension having the specified pseudo-unit + * (base unit or product of base unit). + * + * @param pseudoUnit the pseudo-unit identifying this dimension. + */ + private Dimension(Unit pseudoUnit) { + _pseudoUnit = pseudoUnit; + } + + /** + * Returns the product of this dimension with the one specified. + * + * @param that the dimension multiplicand. + * @return this * that + */ + public final Dimension times(Dimension that) { + return new Dimension(this._pseudoUnit.times(that._pseudoUnit)); + } + + /** + * Returns the quotient of this dimension with the one specified. + * + * @param that the dimension divisor. + * @return this / that + */ + public final Dimension divide(Dimension that) { + return new Dimension(this._pseudoUnit.divide(that._pseudoUnit)); + } + + /** + * Returns this dimension raised to an exponent. + * + * @param n the exponent. + * @return the result of raising this dimension to the exponent. + */ + public final Dimension pow(int n) { + return new Dimension(this._pseudoUnit.pow(n)); + } + + /** + * Returns the given root of this dimension. + * + * @param n the root's order. + * @return the result of taking the given root of this dimension. + * @throws ArithmeticException if n == 0. + */ + public final Dimension root(int n) { + return new Dimension(this._pseudoUnit.root(n)); + } + + /** + * Returns the representation of this dimension. + * + * @return the representation of this dimension. + */ + public String toString() { + return _pseudoUnit.toString(); + } + + /** + * Indicates if the specified dimension is equals to the one specified. + * + * @param that the object to compare to. + * @return true if this dimension is equals to that dimension; + * false otherwise. + */ + public boolean equals(Object that) { + if (this == that) + return true; + return (that instanceof Dimension) + && _pseudoUnit.equals(((Dimension) that)._pseudoUnit); + } + + /** + * Returns the hash code for this dimension. + * + * @return this dimension hashcode value. + */ + public int hashCode() { + return _pseudoUnit.hashCode(); + } + + /** + * Sets the model used to determinate the units dimensions. + * + * @param model the new model to be used when calculating unit dimensions. + */ + public static void setModel(Model model) { + Dimension.CurrentModel = model; + } + + /** + * Returns the model used to determinate the units dimensions + * (default {@link Model#STANDARD STANDARD}). + * + * @return the model used when calculating unit dimensions. + */ + public static Model getModel() { + return Dimension.CurrentModel; + } + + /** + * This interface represents the mapping between {@link BaseUnit base units} + * and {@link Dimension dimensions}. Custom models may allow + * conversions not possible using the {@link #STANDARD standard} model. + * For example:[code] + * public static void main(String[] args) { + * Dimension.Model relativistic = new Dimension.Model() { + * RationalConverter meterToSecond = new RationalConverter(1, 299792458); // 1/c + * + * public Dimension getDimension(BaseUnit unit) { + * if (unit.equals(SI.METER)) return Dimension.TIME; + * return Dimension.Model.STANDARD.getDimension(unit); + * } + * + * public UnitConverter getTransform(BaseUnit unit) { + * if (unit.equals(SI.METER)) return meterToSecond; + * return Dimension.Model.STANDARD.getTransform(unit); + * }}; + * Dimension.setModel(relativistic); + * + * // Converts 1.0 GeV (energy) to kg (mass). + * System.out.println(Unit.valueOf("GeV").getConverterTo(KILOGRAM).convert(1.0)); + * } + * + * > 1.7826617302520883E-27[/code] + */ + public interface Model { + + /** + * Holds the standard model (default). + */ + public Model STANDARD = new Model() { + + public Dimension getDimension(BaseUnit unit) { + if (unit.equals(SI.METRE)) return Dimension.LENGTH; + if (unit.equals(SI.KILOGRAM)) return Dimension.MASS; + if (unit.equals(SI.KELVIN)) return Dimension.TEMPERATURE; + if (unit.equals(SI.SECOND)) return Dimension.TIME; + if (unit.equals(SI.AMPERE)) return Dimension.ELECTRIC_CURRENT; + if (unit.equals(SI.MOLE)) return Dimension.AMOUNT_OF_SUBSTANCE; + if (unit.equals(SI.CANDELA)) return SI.WATT.getDimension(); + return new Dimension(new BaseUnit("[" + unit.getSymbol() + "]")); + } + + public UnitConverter getTransform(BaseUnit unit) { + if (unit.equals(SI.CANDELA)) return new RationalConverter(1, 683); + return UnitConverter.IDENTITY; + } + }; + + /** + * Returns the dimension of the specified base unit (a dimension + * particular to the base unit if the base unit is not recognized). + * + * @param unit the base unit for which the dimension is returned. + * @return the dimension of the specified unit. + */ + Dimension getDimension(BaseUnit unit); + + /** + * Returns the normalization transform of the specified base unit + * ({@link UnitConverter#IDENTITY IDENTITY} if the base unit is + * not recognized). + * + * @param unit the base unit for which the transform is returned. + * @return the normalization transform. + */ + UnitConverter getTransform(BaseUnit unit); + } + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/unit/NonSI.java b/measure/src/main/java/javax/measure/unit/NonSI.java new file mode 100644 index 00000000..14fb2f73 --- /dev/null +++ b/measure/src/main/java/javax/measure/unit/NonSI.java @@ -0,0 +1,758 @@ +/* + * 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.unit; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import javax.measure.converter.LogConverter; +import javax.measure.converter.RationalConverter; +import javax.measure.quantity.*; + +import static javax.measure.unit.SI.*; + +/** + *

This class contains units that are not part of the International + * System of Units, that is, they are outside the SI, but are important + * and widely used.

+ * + * @author Jean-Marie Dautelle + * @version 4.2, August 26, 2007 + */ +public final class NonSI extends SystemOfUnits { + + /** + * Holds collection of NonSI units. + */ + private static HashSet> UNITS = new HashSet>(); + + /** + * Holds the standard gravity constant: 9.80665 m/s² exact. + */ + private static final int STANDARD_GRAVITY_DIVIDEND = 980665; + private static final int STANDARD_GRAVITY_DIVISOR = 100000; + + /** + * Holds the international foot: 0.3048 m exact. + */ + private static final int INTERNATIONAL_FOOT_DIVIDEND = 3048; + private static final int INTERNATIONAL_FOOT_DIViSOR = 10000; + + /** + * Holds the avoirdupois pound: 0.45359237 kg exact + */ + private static final int AVOIRDUPOIS_POUND_DIVIDEND = 45359237; + private static final int AVOIRDUPOIS_POUND_DIVISOR = 100000000; + + /** + * Holds the Avogadro constant. + */ + private static final double AVOGADRO_CONSTANT = 6.02214199e23; // (1/mol). + + /** + * Holds the electric charge of one electron. + */ + private static final double ELEMENTARY_CHARGE = 1.602176462e-19; // (C). + + /** + * Default constructor (prevents this class from being instantiated). + */ + private NonSI() { + } + + /** + * Returns the unique instance of this class. + * + * @return the NonSI instance. + */ + public static NonSI getInstance() { + return INSTANCE; + } + private static final NonSI INSTANCE = new NonSI(); + + /////////////////// + // Dimensionless // + /////////////////// + + /** + * A dimensionless unit equals to 0.01 + * (standard name %). + */ + public static final Unit PERCENT = nonSI(Unit.ONE.divide(100)); + + /** + * A logarithmic unit used to describe a ratio + * (standard name dB). + */ + public static final Unit DECIBEL = nonSI(Unit.ONE + .transform(new LogConverter(10).inverse().concatenate( + new RationalConverter(1, 10)))); + + ///////////////////////// + // Amount of substance // + ///////////////////////// + + /** + * A unit of amount of substance equals to one atom + * (standard name atom). + */ + public static final Unit ATOM = nonSI(MOLE + .divide(AVOGADRO_CONSTANT)); + + //////////// + // Length // + //////////// + + /** + * A unit of length equal to 0.3048 m + * (standard name ft). + */ + public static final Unit FOOT = nonSI(METRE.times(INTERNATIONAL_FOOT_DIVIDEND).divide(INTERNATIONAL_FOOT_DIViSOR)); + + /** + * A unit of length equal to 1200/3937 m + * (standard name foot_survey_us). + * See also: foot + */ + public static final Unit FOOT_SURVEY_US = nonSI(METRE + .times(1200).divide(3937)); + + /** + * A unit of length equal to 0.9144 m + * (standard name yd). + */ + public static final Unit YARD = nonSI(FOOT.times(3)); + + /** + * A unit of length equal to 0.0254 m + * (standard name in). + */ + public static final Unit INCH = nonSI(FOOT.divide(12)); + + /** + * A unit of length equal to 1609.344 m + * (standard name mi). + */ + public static final Unit MILE = nonSI(METRE.times(1609344).divide(1000)); + + /** + * A unit of length equal to 1852.0 m + * (standard name nmi). + */ + public static final Unit NAUTICAL_MILE = nonSI(METRE.times(1852)); + + /** + * A unit of length equal to 1E-10 m + * (standard name Å). + */ + public static final Unit ANGSTROM = nonSI(METRE.divide(10000000000L)); + + /** + * A unit of length equal to the average distance from the center of the + * Earth to the center of the Sun (standard name ua). + */ + public static final Unit ASTRONOMICAL_UNIT = nonSI(METRE + .times(149597870691.0)); + + /** + * A unit of length equal to the distance that light travels in one year + * through a vacuum (standard name ly). + */ + public static final Unit LIGHT_YEAR = nonSI(METRE.times(9.460528405e15)); + + /** + * A unit of length equal to the distance at which a star would appear to + * shift its position by one arcsecond over the course the time + * (about 3 months) in which the Earth moves a distance of + * {@link #ASTRONOMICAL_UNIT} in the direction perpendicular to the + * direction to the star (standard name pc). + */ + public static final Unit PARSEC = nonSI(METRE.times(30856770e9)); + + /** + * A unit of length equal to 0.013837 {@link #INCH} exactly + * (standard name pt). + * @see #PIXEL + */ + public static final Unit POINT = nonSI(INCH.times(13837).divide(1000000)); + + /** + * A unit of length equal to 1/72 {@link #INCH} + * (standard name pixel). + * It is the American point rounded to an even 1/72 inch. + * @see #POINT + */ + public static final Unit PIXEL = nonSI(INCH.divide(72)); + + /** + * Equivalent {@link #PIXEL} + */ + public static final Unit COMPUTER_POINT = PIXEL; + + ////////////// + // Duration // + ////////////// + + /** + * A unit of duration equal to 60 s + * (standard name min). + */ + public static final Unit MINUTE = nonSI(SI.SECOND.times(60)); + + /** + * A unit of duration equal to 60 {@link #MINUTE} + * (standard name h). + */ + public static final Unit HOUR = nonSI(MINUTE.times(60)); + + /** + * A unit of duration equal to 24 {@link #HOUR} + * (standard name d). + */ + public static final Unit DAY = nonSI(HOUR.times(24)); + + /** + * A unit of duration equal to 7 {@link #DAY} + * (standard name week). + */ + public static final Unit WEEK = nonSI(DAY.times(7)); + + /** + * A unit of duration equal to 365 days, 5 hours, 49 minutes, + * and 12 seconds (standard name year). + */ + public static final Unit YEAR = nonSI(SECOND.times(31556952)); + + /** + * A unit of duration equal to one twelfth of a year + * (standard name month). + */ + public static final Unit MONTH = nonSI(YEAR.divide(12)); + + /** + * A unit of duration equal to the time required for a complete rotation of + * the earth in reference to any star or to the vernal equinox at the + * meridian, equal to 23 hours, 56 minutes, 4.09 seconds + * (standard name day_sidereal). + */ + public static final Unit DAY_SIDEREAL = nonSI(SECOND.times(86164.09)); + + /** + * A unit of duration equal to one complete revolution of the + * earth about the sun, relative to the fixed stars, or 365 days, 6 hours, + * 9 minutes, 9.54 seconds (standard name year_sidereal). + */ + public static final Unit YEAR_SIDEREAL = nonSI(SECOND + .times(31558149.54)); + + /** + * A unit of duration equal to 365 {@link #DAY} + * (standard name year_calendar). + */ + public static final Unit YEAR_CALENDAR = nonSI(DAY.times(365)); + + ////////// + // Mass // + ////////// + + /** + * A unit of mass equal to 1/12 the mass of the carbon-12 atom + * (standard name u). + */ + public static final Unit ATOMIC_MASS = nonSI(KILOGRAM + .times(1e-3 / AVOGADRO_CONSTANT)); + + /** + * A unit of mass equal to the mass of the electron + * (standard name me). + */ + public static final Unit ELECTRON_MASS = nonSI(KILOGRAM + .times(9.10938188e-31)); + + /** + * A unit of mass equal to 453.59237 grams (avoirdupois pound, + * standard name lb). + */ + public static final Unit POUND = nonSI(KILOGRAM.times(AVOIRDUPOIS_POUND_DIVIDEND).divide(AVOIRDUPOIS_POUND_DIVISOR)); + + /** + * A unit of mass equal to 1 / 16 {@link #POUND} + * (standard name oz). + */ + public static final Unit OUNCE = nonSI(POUND.divide(16)); + + /** + * A unit of mass equal to 2000 {@link #POUND} (short ton, + * standard name ton_us). + */ + public static final Unit TON_US = nonSI(POUND.times(2000)); + + /** + * A unit of mass equal to 2240 {@link #POUND} (long ton, + * standard name ton_uk). + */ + public static final Unit TON_UK = nonSI(POUND.times(2240)); + + /** + * A unit of mass equal to 1000 kg (metric ton, + * standard name t). + */ + public static final Unit METRIC_TON = nonSI(KILOGRAM.times(1000)); + + ///////////////////// + // Electric charge // + ///////////////////// + + /** + * A unit of electric charge equal to the charge on one electron + * (standard name e). + */ + public static final Unit E = nonSI(COULOMB + .times(ELEMENTARY_CHARGE)); + + /** + * A unit of electric charge equal to equal to the product of Avogadro's + * number (see {@link SI#MOLE}) and the charge (1 e) on a single electron + * (standard name Fd). + */ + public static final Unit FARADAY = nonSI(COULOMB + .times(ELEMENTARY_CHARGE * AVOGADRO_CONSTANT)); // e/mol + + /** + * A unit of electric charge which exerts a force of one dyne on an equal + * charge at a distance of one centimeter + * (standard name Fr). + */ + public static final Unit FRANKLIN = nonSI(COULOMB + .times(3.3356e-10)); + + ///////////////// + // Temperature // + ///////////////// + + /** + * A unit of temperature equal to 5/9 °K + * (standard name °R). + */ + public static final Unit RANKINE = nonSI(KELVIN.times(5).divide(9)); + + /** + * A unit of temperature equal to degree Rankine minus + * 459.67 °R (standard name °F). + * @see #RANKINE + */ + public static final Unit FAHRENHEIT = nonSI(RANKINE.plus(459.67)); + + /////////// + // Angle // + /////////// + + /** + * A unit of angle equal to a full circle or 2π + * {@link SI#RADIAN} (standard name rev). + */ + public static final Unit REVOLUTION = nonSI(RADIAN.times(2.0 * Math.PI)); + + /** + * A unit of angle equal to 1/360 {@link #REVOLUTION} + * (standard name °). + */ + public static final Unit DEGREE_ANGLE = nonSI(REVOLUTION.divide(360)); + + /** + * A unit of angle equal to 1/60 {@link #DEGREE_ANGLE} + * (standard name ). + */ + public static final Unit MINUTE_ANGLE = nonSI(DEGREE_ANGLE.divide(60)); + + /** + * A unit of angle equal to 1/60 {@link #MINUTE_ANGLE} + * (standard name "). + */ + public static final Unit SECOND_ANGLE = nonSI(MINUTE_ANGLE.divide(60)); + + /** + * A unit of angle equal to 0.01 {@link SI#RADIAN} + * (standard name centiradian). + */ + public static final Unit CENTIRADIAN = nonSI(RADIAN.divide(100)); + + /** + * A unit of angle measure equal to 1/400 {@link #REVOLUTION} + * (standard name grade). + */ + public static final Unit GRADE = nonSI(REVOLUTION.divide(400)); + + ////////////// + // Velocity // + ////////////// + + /** + * A unit of velocity expressing the number of international {@link + * #MILE miles} per {@link #HOUR hour} (abbreviation mph). + */ + public static final Unit MILES_PER_HOUR + = nonSI(NonSI.MILE.divide(NonSI.HOUR)).asType(Velocity.class); + + /** + * A unit of velocity expressing the number of {@link SI#KILOMETRE} per + * {@link #HOUR hour}. + */ + public static final Unit KILOMETRES_PER_HOUR + = nonSI(SI.KILOMETRE.divide(NonSI.HOUR)).asType(Velocity.class); + + /** + * Equivalent to {@link #KILOMETRES_PER_HOUR}. + */ + public static final Unit KILOMETERS_PER_HOUR = KILOMETRES_PER_HOUR; + + /** + * A unit of velocity expressing the number of {@link #NAUTICAL_MILE + * nautical miles} per {@link #HOUR hour} (abbreviation kn). + */ + public static final Unit KNOT + = nonSI(NonSI.NAUTICAL_MILE.divide(NonSI.HOUR)).asType(Velocity.class); + + /** + * A unit of velocity to express the speed of an aircraft relative to + * the speed of sound (standard name Mach). + */ + public static final Unit MACH = nonSI(METRES_PER_SECOND.times(331.6)); + + /** + * A unit of velocity relative to the speed of light + * (standard name c). + */ + public static final Unit C = nonSI(METRES_PER_SECOND.times(299792458)); + + ////////////////// + // Acceleration // + ////////////////// + + /** + * A unit of acceleration equal to the gravity at the earth's surface + * (standard name grav). + */ + public static final Unit G = nonSI(METRES_PER_SQUARE_SECOND + .times(STANDARD_GRAVITY_DIVIDEND).divide(STANDARD_GRAVITY_DIVISOR)); + + ////////// + // Area // + ////////// + + /** + * A unit of area equal to 100 m² + * (standard name a). + */ + public static final Unit ARE = nonSI(SQUARE_METRE.times(100)); + + /** + * A unit of area equal to 100 {@link #ARE} + * (standard name ha). + */ + public static final Unit HECTARE = nonSI(ARE.times(100)); // Exact. + + ///////////////// + // Data Amount // + ///////////////// + + /** + * A unit of data amount equal to 8 {@link SI#BIT} + * (BinarY TErm, standard name byte). + */ + public static final Unit BYTE = nonSI(BIT.times(8)); + + /** + * Equivalent {@link #BYTE} + */ + public static final Unit OCTET = BYTE; + + + ////////////////////// + // Electric current // + ////////////////////// + + /** + * A unit of electric charge equal to the centimeter-gram-second + * electromagnetic unit of magnetomotive force, equal to 10/4 + * πampere-turn (standard name Gi). + */ + public static final Unit GILBERT = nonSI(SI.AMPERE + .times(10.0 / (4.0 * Math.PI))); + + //////////// + // Energy // + //////////// + + /** + * A unit of energy equal to 1E-7 J + * (standard name erg). + */ + public static final Unit ERG = nonSI(JOULE.divide(10000000)); + + /** + * A unit of energy equal to one electron-volt (standard name + * eV, also recognized keV, MeV, GeV). + */ + public static final Unit ELECTRON_VOLT = nonSI(JOULE + .times(ELEMENTARY_CHARGE)); + + ///////////////// + // Illuminance // + ///////////////// + + /** + * A unit of illuminance equal to 1E4 Lx + * (standard name La). + */ + public static final Unit LAMBERT = nonSI(LUX.times(10000)); + + /////////////////// + // Magnetic Flux // + /////////////////// + + /** + * A unit of magnetic flux equal 1E-8 Wb + * (standard name Mx). + */ + public static final Unit MAXWELL = nonSI(WEBER.divide(100000000)); + + /////////////////////////// + // Magnetic Flux Density // + /////////////////////////// + + /** + * A unit of magnetic flux density equal 1000 A/m + * (standard name G). + */ + public static final Unit GAUSS = nonSI(TESLA.divide(10000)); + + /////////// + // Force // + /////////// + + /** + * A unit of force equal to 1E-5 N + * (standard name dyn). + */ + public static final Unit DYNE = nonSI(NEWTON.divide(100000)); + + /** + * A unit of force equal to 9.80665 N + * (standard name kgf). + */ + public static final Unit KILOGRAM_FORCE = nonSI(NEWTON + .times(STANDARD_GRAVITY_DIVIDEND).divide(STANDARD_GRAVITY_DIVISOR)); + + /** + * A unit of force equal to {@link #POUND}·{@link #G} + * (standard name lbf). + */ + public static final Unit POUND_FORCE = nonSI(NEWTON + .times(1L * AVOIRDUPOIS_POUND_DIVIDEND * STANDARD_GRAVITY_DIVIDEND).divide( + 1L * AVOIRDUPOIS_POUND_DIVISOR * STANDARD_GRAVITY_DIVISOR)); + + /////////// + // Power // + /////////// + + /** + * A unit of power equal to the power required to raise a mass of 75 + * kilograms at a velocity of 1 meter per second (metric, + * standard name hp). + */ + public static final Unit HORSEPOWER = nonSI(WATT.times(735.499)); + + ////////////// + // Pressure // + ////////////// + + /** + * A unit of pressure equal to the average pressure of the Earth's + * atmosphere at sea level (standard name atm). + */ + public static final Unit ATMOSPHERE = nonSI(PASCAL.times(101325)); + + /** + * A unit of pressure equal to 100 kPa + * (standard name bar). + */ + public static final Unit BAR = nonSI(PASCAL.times(100000)); + + /** + * A unit of pressure equal to the pressure exerted at the Earth's + * surface by a column of mercury 1 millimeter high + * (standard name mmHg). + */ + public static final Unit MILLIMETER_OF_MERCURY =nonSI(PASCAL + .times(133.322)); + + /** + * A unit of pressure equal to the pressure exerted at the Earth's + * surface by a column of mercury 1 inch high + * (standard name inHg). + */ + public static final Unit INCH_OF_MERCURY = nonSI(PASCAL.times(3386.388)); + + ///////////////////////////// + // Radiation dose absorbed // + ///////////////////////////// + + /** + * A unit of radiation dose absorbed equal to a dose of 0.01 joule of + * energy per kilogram of mass (J/kg) (standard name rd). + */ + public static final Unit RAD = nonSI(GRAY.divide(100)); + + /** + * A unit of radiation dose effective equal to 0.01 Sv + * (standard name rem). + */ + public static final Unit REM = nonSI(SIEVERT.divide(100)); + + ////////////////////////// + // Radioactive activity // + ////////////////////////// + + /** + * A unit of radioctive activity equal to the activity of a gram of radium + * (standard name Ci). + */ + public static final Unit CURIE = nonSI(BECQUEREL + .times(37000000000L)); + + /** + * A unit of radioctive activity equal to 1 million radioactive + * disintegrations per second (standard name Rd). + */ + public static final Unit RUTHERFORD = nonSI(SI.BECQUEREL + .times(1000000)); + + ///////////////// + // Solid angle // + ///////////////// + + /** + * A unit of solid angle equal to 4 π steradians + * (standard name sphere). + */ + public static final Unit SPHERE = nonSI(STERADIAN + .times(4.0 * Math.PI)); + + //////////// + // Volume // + //////////// + + /** + * A unit of volume equal to one cubic decimeter (default label + * L, also recognized µL, mL, cL, dL). + */ + public static final Unit LITRE = nonSI(CUBIC_METRE.divide(1000)); + + /** + * Equivalent to {@link #LITRE} (American spelling). + */ + public static final Unit LITER = LITRE; + + /** + * A unit of volume equal to one cubic inch (in³). + */ + public static final Unit CUBIC_INCH = nonSI( + INCH.pow(3).asType(Volume.class)); + + /** + * A unit of volume equal to one US gallon, Liquid Unit. The U.S. liquid + * gallon is based on the Queen Anne or Wine gallon occupying 231 cubic + * inches (standard name gal). + */ + public static final Unit GALLON_LIQUID_US = nonSI(CUBIC_INCH.times(231)); + + /** + * A unit of volume equal to 1 / 128 {@link #GALLON_LIQUID_US} + * (standard name oz_fl). + */ + public static final Unit OUNCE_LIQUID_US = nonSI(GALLON_LIQUID_US + .divide(128)); + + /** + * A unit of volume equal to one US dry gallon. + * (standard name gallon_dry_us). + */ + public static final Unit GALLON_DRY_US = nonSI(CUBIC_INCH.times(2688025).divide(10000)); + + /** + * A unit of volume equal to 4.546 09 {@link #LITRE} + * (standard name gal_uk). + */ + public static final Unit GALLON_UK = nonSI(LITRE.times(454609).divide(100000)); + + /** + * A unit of volume equal to 1 / 160 {@link #GALLON_UK} + * (standard name oz_fl_uk). + */ + public static final Unit OUNCE_LIQUID_UK = nonSI(GALLON_UK.divide(160)); + + /////////////// + // Viscosity // + /////////////// + + /** + * A unit of dynamic viscosity equal to 1 g/(cm·s) + * (cgs unit). + */ + @SuppressWarnings("unchecked") + public static final Unit + POISE = nonSI((Unit) GRAM.divide(CENTI(METRE).times(SECOND))); + + /** + * A unit of kinematic viscosity equal to 1 cm²/s + * (cgs unit). + */ + @SuppressWarnings("unchecked") + public static final Unit + STOKE = nonSI((Unit) CENTI(METRE).pow(2).divide(SECOND)); + + + //////////// + // Others // + //////////// + + /** + * A unit used to measure the ionizing ability of radiation + * (standard name Roentgen). + */ + public static final Unit ROENTGEN = nonSI(COULOMB.divide(KILOGRAM).times(2.58e-4)); + + + ///////////////////// + // Collection View // + ///////////////////// + + /** + * Returns a read only view over the units defined in this class. + * + * @return the collection of NonSI units. + */ + public Set> getUnits() { + return Collections.unmodifiableSet(UNITS); + } + + /** + * Adds a new unit to the collection. + * + * @param unit the unit being added. + * @return unit. + */ + private static > U nonSI(U unit) { + UNITS.add(unit); + return unit; + } + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/unit/ProductUnit.java b/measure/src/main/java/javax/measure/unit/ProductUnit.java new file mode 100644 index 00000000..5f673085 --- /dev/null +++ b/measure/src/main/java/javax/measure/unit/ProductUnit.java @@ -0,0 +1,471 @@ +/* + * 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.unit; + +import java.io.Serializable; + +import javax.measure.converter.ConversionException; +import javax.measure.converter.UnitConverter; +import javax.measure.quantity.Quantity; + +/** + *

This class represents units formed by the product of rational powers of + * existing units.

+ * + *

This class maintains the canonical form of this product (simplest + * form after factorization). For example: + * METER.pow(2).divide(METER) returns + * METER.

+ * + * @author Jean-Marie Dautelle + * @version 3.1, April 22, 2006 + * @see Unit#times(Unit) + * @see Unit#divide(Unit) + * @see Unit#pow(int) + * @see Unit#root(int) + */ +public final class ProductUnit extends DerivedUnit { + + /** + * Holds the units composing this product unit. + */ + private final Element[] _elements; + + /** + * Holds the hashcode (optimization). + */ + private int _hashCode; + + /** + * Default constructor (used solely to create ONE instance). + */ + ProductUnit() { + _elements = new Element[0]; + } + + /** + * Copy constructor (allows for parameterization of product units). + * + * @param productUnit the product unit source. + * @throws ClassCastException if the specified unit is not + * a product unit. + */ + public ProductUnit(Unit productUnit) { + _elements = ((ProductUnit)productUnit)._elements; + } + + /** + * Product unit constructor. + * + * @param elements the product elements. + */ + private ProductUnit(Element[] elements) { + _elements = elements; + } + + /** + * Returns the unit defined from the product of the specifed elements. + * + * @param leftElems left multiplicand elements. + * @param rightElems right multiplicand elements. + * @return the corresponding unit. + */ + @SuppressWarnings("unchecked") + private static Unit getInstance(Element[] leftElems, + Element[] rightElems) { + + // Merges left elements with right elements. + Element[] result = new Element[leftElems.length + rightElems.length]; + int resultIndex = 0; + for (int i = 0; i < leftElems.length; i++) { + Unit unit = leftElems[i]._unit; + int p1 = leftElems[i]._pow; + int r1 = leftElems[i]._root; + int p2 = 0; + int r2 = 1; + for (int j = 0; j < rightElems.length; j++) { + if (unit.equals(rightElems[j]._unit)) { + p2 = rightElems[j]._pow; + r2 = rightElems[j]._root; + break; // No duplicate. + } + } + int pow = (p1 * r2) + (p2 * r1); + int root = r1 * r2; + if (pow != 0) { + int gcd = gcd(Math.abs(pow), root); + result[resultIndex++] = new Element(unit, pow / gcd, root / gcd); + } + } + + // Appends remaining right elements not merged. + for (int i = 0; i < rightElems.length; i++) { + Unit unit = rightElems[i]._unit; + boolean hasBeenMerged = false; + for (int j = 0; j < leftElems.length; j++) { + if (unit.equals(leftElems[j]._unit)) { + hasBeenMerged = true; + break; + } + } + if (!hasBeenMerged) { + result[resultIndex++] = rightElems[i]; + } + } + + // Returns or creates instance. + if (resultIndex == 0) { + return ONE; + } else if ((resultIndex == 1) && (result[0]._pow == result[0]._root)) { + return result[0]._unit; + } else { + Element[] elems = new Element[resultIndex]; + for (int i = 0; i < resultIndex; i++) { + elems[i] = result[i]; + } + return new ProductUnit(elems); + } + } + + /** + * Returns the product of the specified units. + * + * @param left the left unit operand. + * @param right the right unit operand. + * @return left * right + */ + static Unit getProductInstance(Unit left, Unit right) { + Element[] leftElems; + if (left instanceof ProductUnit) { + leftElems = ((ProductUnit) left)._elements; + } else { + leftElems = new Element[] { new Element(left, 1, 1) }; + } + Element[] rightElems; + if (right instanceof ProductUnit) { + rightElems = ((ProductUnit) right)._elements; + } else { + rightElems = new Element[] { new Element(right, 1, 1) }; + } + return getInstance(leftElems, rightElems); + } + + /** + * Returns the quotient of the specified units. + * + * @param left the dividend unit operand. + * @param right the divisor unit operand. + * @return dividend / divisor + */ + static Unit getQuotientInstance(Unit left, Unit right) { + Element[] leftElems; + if (left instanceof ProductUnit) { + leftElems = ((ProductUnit) left)._elements; + } else { + leftElems = new Element[] { new Element(left, 1, 1) }; + } + Element[] rightElems; + if (right instanceof ProductUnit) { + Element[] elems = ((ProductUnit) right)._elements; + rightElems = new Element[elems.length]; + for (int i = 0; i < elems.length; i++) { + rightElems[i] = new Element(elems[i]._unit, -elems[i]._pow, + elems[i]._root); + } + } else { + rightElems = new Element[] { new Element(right, -1, 1) }; + } + return getInstance(leftElems, rightElems); + } + + /** + * Returns the product unit corresponding to the specified root of + * the specified unit. + * + * @param unit the unit. + * @param n the root's order (n > 0). + * @return unit^(1/nn) + * @throws ArithmeticException if n == 0. + */ + static Unit getRootInstance(Unit unit, int n) { + Element[] unitElems; + if (unit instanceof ProductUnit) { + Element[] elems = ((ProductUnit) unit)._elements; + unitElems = new Element[elems.length]; + for (int i = 0; i < elems.length; i++) { + int gcd = gcd(Math.abs(elems[i]._pow), elems[i]._root * n); + unitElems[i] = new Element(elems[i]._unit, elems[i]._pow / gcd, + elems[i]._root * n / gcd); + } + } else { + unitElems = new Element[] { new Element(unit, 1, n) }; + } + return getInstance(unitElems, new Element[0]); + } + + /** + * Returns the product unit corresponding to this unit raised to + * the specified exponent. + * + * @param unit the unit. + * @param nn the exponent (nn > 0). + * @return unit^n + */ + static Unit getPowInstance(Unit unit, int n) { + Element[] unitElems; + if (unit instanceof ProductUnit) { + Element[] elems = ((ProductUnit) unit)._elements; + unitElems = new Element[elems.length]; + for (int i = 0; i < elems.length; i++) { + int gcd = gcd(Math.abs(elems[i]._pow * n), elems[i]._root); + unitElems[i] = new Element(elems[i]._unit, elems[i]._pow * n + / gcd, elems[i]._root / gcd); + } + } else { + unitElems = new Element[] { new Element(unit, n, 1) }; + } + return getInstance(unitElems, new Element[0]); + } + + /** + * Returns the number of units in this product. + * + * @return the number of units being multiplied. + */ + public int getUnitCount() { + return _elements.length; + } + + /** + * Returns the unit at the specified position. + * + * @param index the index of the unit to return. + * @return the unit at the specified position. + * @throws IndexOutOfBoundsException if index is out of range + * (index < 0 || index >= size()). + */ + @SuppressWarnings("unchecked") + public Unit getUnit(int index) { + return _elements[index].getUnit(); + } + + /** + * Returns the power exponent of the unit at the specified position. + * + * @param index the index of the unit to return. + * @return the unit power exponent at the specified position. + * @throws IndexOutOfBoundsException if index is out of range + * (index < 0 || index >= size()). + */ + public int getUnitPow(int index) { + return _elements[index].getPow(); + } + + /** + * Returns the root exponent of the unit at the specified position. + * + * @param index the index of the unit to return. + * @return the unit root exponent at the specified position. + * @throws IndexOutOfBoundsException if index is out of range + * (index < 0 || index >= size()). + */ + public int getUnitRoot(int index) { + return _elements[index].getRoot(); + } + + /** + * Indicates if this product unit is considered equals to the specified + * object. + * + * @param that the object to compare for equality. + * @return true if this and that + * are considered equals; falseotherwise. + */ + public boolean equals(Object that) { + if (this == that) + return true; + if (that instanceof ProductUnit) { + // Two products are equals if they have the same elements + // regardless of the elements' order. + Element[] elems = ((ProductUnit) that)._elements; + if (_elements.length == elems.length) { + for (int i = 0; i < _elements.length; i++) { + boolean unitFound = false; + for (int j = 0; j < elems.length; j++) { + if (_elements[i]._unit.equals(elems[j]._unit)) { + if ((_elements[i]._pow != elems[j]._pow) + || (_elements[i]._root != elems[j]._root)) { + return false; + } else { + unitFound = true; + break; + } + } + } + if (!unitFound) { + return false; + } + } + return true; + } + } + return false; + } + + @Override + // Implements abstract method. + public int hashCode() { + if (_hashCode != 0) + return _hashCode; + int code = 0; + for (int i = 0; i < _elements.length; i++) { + code += _elements[i]._unit.hashCode() + * (_elements[i]._pow * 3 - _elements[i]._root * 2); + } + _hashCode = code; + return code; + } + + @Override + @SuppressWarnings("unchecked") + public Unit getStandardUnit() { + if (hasOnlyStandardUnit()) + return this; + Unit systemUnit = ONE; + for (int i = 0; i < _elements.length; i++) { + Unit unit = _elements[i]._unit.getStandardUnit(); + unit = unit.pow(_elements[i]._pow); + unit = unit.root(_elements[i]._root); + systemUnit = systemUnit.times(unit); + } + return systemUnit; + } + + @Override + public UnitConverter toStandardUnit() { + if (hasOnlyStandardUnit()) + return UnitConverter.IDENTITY; + UnitConverter converter = UnitConverter.IDENTITY; + for (int i = 0; i < _elements.length; i++) { + UnitConverter cvtr = _elements[i]._unit.toStandardUnit(); + if (!cvtr.isLinear()) + throw new ConversionException(_elements[i]._unit + + " is non-linear, cannot convert"); + if (_elements[i]._root != 1) + throw new ConversionException(_elements[i]._unit + + " holds a base unit with fractional exponent"); + int pow = _elements[i]._pow; + if (pow < 0) { // Negative power. + pow = -pow; + cvtr = cvtr.inverse(); + } + for (int j = 0; j < pow; j++) { + converter = converter.concatenate(cvtr); + } + } + return converter; + } + + /** + * Indicates if this product unit is a standard unit. + * + * @return true if all elements are standard units; + * false otherwise. + */ + private boolean hasOnlyStandardUnit() { + for (int i = 0; i < _elements.length; i++) { + Unit u = _elements[i]._unit; + if (!u.isStandardUnit()) + return false; + } + return true; + } + + /** + * Returns the greatest common divisor (Euclid's algorithm). + * + * @param m the first number. + * @param nn the second number. + * @return the greatest common divisor. + */ + private static int gcd(int m, int n) { + if (n == 0) { + return m; + } else { + return gcd(n, m % n); + } + } + + /** + * Inner product element represents a rational power of a single unit. + */ + private final static class Element implements Serializable { + + /** + * Holds the single unit. + */ + private final Unit _unit; + + /** + * Holds the power exponent. + */ + private final int _pow; + + /** + * Holds the root exponent. + */ + private final int _root; + + /** + * Structural constructor. + * + * @param unit the unit. + * @param pow the power exponent. + * @param root the root exponent. + */ + private Element(Unit unit, int pow, int root) { + _unit = unit; + _pow = pow; + _root = root; + } + + /** + * Returns this element's unit. + * + * @return the single unit. + */ + public Unit getUnit() { + return _unit; + } + + /** + * Returns the power exponent. The power exponent can be negative + * but is always different from zero. + * + * @return the power exponent of the single unit. + */ + public int getPow() { + return _pow; + } + + /** + * Returns the root exponent. The root exponent is always greater + * than zero. + * + * @return the root exponent of the single unit. + */ + public int getRoot() { + return _root; + } + + private static final long serialVersionUID = 1L; + } + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/unit/SI.java b/measure/src/main/java/javax/measure/unit/SI.java new file mode 100644 index 00000000..b856035c --- /dev/null +++ b/measure/src/main/java/javax/measure/unit/SI.java @@ -0,0 +1,719 @@ +/* + * 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.unit; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import javax.measure.converter.MultiplyConverter; +import javax.measure.converter.RationalConverter; +import javax.measure.quantity.*; + +/** + *

This class contains SI (Système International d'Unités) base units, + * and derived units.

+ * + *

It also defines the 20 SI prefixes used to form decimal multiples and + * submultiples of SI units. For example:[code] + * import static org.jscience.physics.units.SI.*; // Static import. + * ... + * Unit HECTO_PASCAL = HECTO(PASCAL); + * Unit KILO_METER = KILO(METER); + * [/code]

+ * + * @author Jean-Marie Dautelle + * @version 4.2, August 26, 2006 + * @see Wikipedia: SI + * @see Wikipedia: SI prefix + */ +public final class SI extends SystemOfUnits { + + /** + * Holds collection of SI units. + */ + private static HashSet> UNITS = new HashSet>(); + + /** + * Default constructor (prevents this class from being instantiated). + */ + private SI() { + } + + + /** + * Returns the unique instance of this class. + * + * @return the SI instance. + */ + public static SI getInstance() { + return INSTANCE; + } + private static final SI INSTANCE = new SI(); + + //////////////// + // BASE UNITS // + //////////////// + + /** + * The base unit for electric current quantities (A). + * The Ampere is that constant current which, if maintained in two straight + * parallel conductors of infinite length, of negligible circular + * cross-section, and placed 1 metre apart in vacuum, would produce between + * these conductors a force equal to 2 × 10-7 newton per metre of length. + * It is named after the French physicist Andre Ampere (1775-1836). + */ + public static final BaseUnit AMPERE = si(new BaseUnit( + "A")); + + /** + * The base unit for luminous intensity quantities (cd). + * The candela is the luminous intensity, in a given direction, + * of a source that emits monochromatic radiation of frequency + * 540 × 1012 hertz and that has a radiant intensity in that + * direction of 1/683 watt per steradian + * @see + * Wikipedia: Candela + */ + public static final BaseUnit CANDELA = si(new BaseUnit( + "cd")); + + /** + * The base unit for thermodynamic temperature quantities (K). + * The kelvin is the 1/273.16th of the thermodynamic temperature of the + * triple point of water. It is named after the Scottish mathematician and + * physicist William Thomson 1st Lord Kelvin (1824-1907) + */ + public static final BaseUnit KELVIN = si(new BaseUnit( + "K")); + + /** + * The base unit for mass quantities (kg). + * It is the only SI unit with a prefix as part of its name and symbol. + * The kilogram is equal to the mass of an international prototype in the + * form of a platinum-iridium cylinder kept at Sevres in France. + * @see #GRAM + */ + public static final BaseUnit KILOGRAM = si(new BaseUnit("kg")); + + /** + * The base unit for length quantities (m). + * One meter was redefined in 1983 as the distance traveled by light in + * a vacuum in 1/299,792,458 of a second. + */ + public static final BaseUnit METRE = si(new BaseUnit("m")); + + /** + * Equivalent to {@link #METRE} (American spelling). + */ + public static final Unit METER = METRE; + + /** + * The base unit for amount of substance quantities (mol). + * The mole is the amount of substance of a system which contains as many + * elementary entities as there are atoms in 0.012 kilogram of carbon 12. + */ + public static final BaseUnit MOLE = si(new BaseUnit( + "mol")); + + /** + * The base unit for duration quantities (s). + * It is defined as the duration of 9,192,631,770 cycles of radiation + * corresponding to the transition between two hyperfine levels of + * the ground state of cesium (1967 Standard). + */ + public static final BaseUnit SECOND = si(new BaseUnit( + "s")); + + //////////////////////////////// + // SI DERIVED ALTERNATE UNITS // + //////////////////////////////// + + /** + * The derived unit for mass quantities (g). + * The base unit for mass quantity is {@link #KILOGRAM}. + */ + public static final Unit GRAM = KILOGRAM.divide(1000); + + /** + * The unit for plane angle quantities (rad). + * One radian is the angle between two radii of a circle such that the + * length of the arc between them is equal to the radius. + */ + public static final AlternateUnit RADIAN = si(new AlternateUnit( + "rad", Unit.ONE)); + + /** + * The unit for solid angle quantities (sr). + * One steradian is the solid angle subtended at the center of a sphere by + * an area on the surface of the sphere that is equal to the radius squared. + * The total solid angle of a sphere is 4*Pi steradians. + */ + public static final AlternateUnit STERADIAN = si(new AlternateUnit( + "sr", Unit.ONE)); + + /** + * The unit for binary information (bit). + */ + public static final AlternateUnit BIT = si(new AlternateUnit( + "bit", Unit.ONE)); + + /** + * The derived unit for frequency (Hz). + * A unit of frequency equal to one cycle per second. + * After Heinrich Rudolf Hertz (1857-1894), German physicist who was the + * first to produce radio waves artificially. + */ + public static final AlternateUnit HERTZ = si(new AlternateUnit( + "Hz", Unit.ONE.divide(SECOND))); + + /** + * The derived unit for force (N). + * One newton is the force required to give a mass of 1 kilogram an Force + * of 1 metre per second per second. It is named after the English + * mathematician and physicist Sir Isaac Newton (1642-1727). + */ + public static final AlternateUnit NEWTON = si(new AlternateUnit( + "N", METRE.times(KILOGRAM).divide(SECOND.pow(2)))); + + /** + * The derived unit for pressure, stress (Pa). + * One pascal is equal to one newton per square meter. It is named after + * the French philosopher and mathematician Blaise Pascal (1623-1662). + */ + public static final AlternateUnit PASCAL = si(new AlternateUnit( + "Pa", NEWTON.divide(METRE.pow(2)))); + + /** + * The derived unit for energy, work, quantity of heat (J). + * One joule is the amount of work done when an applied force of 1 newton + * moves through a distance of 1 metre in the direction of the force. + * It is named after the English physicist James Prescott Joule (1818-1889). + */ + public static final AlternateUnit JOULE = si(new AlternateUnit( + "J", NEWTON.times(METRE))); + + /** + * The derived unit for power, radiant, flux (W). + * One watt is equal to one joule per second. It is named after the British + * scientist James Watt (1736-1819). + */ + public static final AlternateUnit WATT = si(new AlternateUnit( + "W", JOULE.divide(SECOND))); + + /** + * The derived unit for electric charge, quantity of electricity + * (C). + * One Coulomb is equal to the quantity of charge transferred in one second + * by a steady current of one ampere. It is named after the French physicist + * Charles Augustin de Coulomb (1736-1806). + */ + public static final AlternateUnit COULOMB = si(new AlternateUnit( + "C", SECOND.times(AMPERE))); + + /** + * The derived unit for electric potential difference, electromotive force + * (V). + * One Volt is equal to the difference of electric potential between two + * points on a conducting wire carrying a constant current of one ampere + * when the power dissipated between the points is one watt. It is named + * after the Italian physicist Count Alessandro Volta (1745-1827). + */ + public static final AlternateUnit VOLT = si(new AlternateUnit( + "V", WATT.divide(AMPERE))); + + /** + * The derived unit for capacitance (F). + * One Farad is equal to the capacitance of a capacitor having an equal + * and opposite charge of 1 coulomb on each plate and a potential difference + * of 1 volt between the plates. It is named after the British physicist + * and chemist Michael Faraday (1791-1867). + */ + public static final AlternateUnit FARAD = si(new AlternateUnit( + "F", COULOMB.divide(VOLT))); + + /** + * The derived unit for electric resistance (Ω or + * Ohm). + * One Ohm is equal to the resistance of a conductor in which a current of + * one ampere is produced by a potential of one volt across its terminals. + * It is named after the German physicist Georg Simon Ohm (1789-1854). + */ + public static final AlternateUnit OHM = si(new AlternateUnit( + "Ω", VOLT.divide(AMPERE))); + + /** + * The derived unit for electric conductance (S). + * One Siemens is equal to one ampere per volt. It is named after + * the German engineer Ernst Werner von Siemens (1816-1892). + */ + public static final AlternateUnit SIEMENS = si(new AlternateUnit( + "S", AMPERE.divide(VOLT))); + + /** + * The derived unit for magnetic flux (Wb). + * One Weber is equal to the magnetic flux that in linking a circuit of one + * turn produces in it an electromotive force of one volt as it is uniformly + * reduced to zero within one second. It is named after the German physicist + * Wilhelm Eduard Weber (1804-1891). + */ + public static final AlternateUnit WEBER = si(new AlternateUnit( + "Wb", VOLT.times(SECOND))); + + /** + * The derived unit for magnetic flux density (T). + * One Tesla is equal equal to one weber per square meter. It is named + * after the Serbian-born American electrical engineer and physicist + * Nikola Tesla (1856-1943). + */ + public static final AlternateUnit TESLA = si(new AlternateUnit( + "T", WEBER.divide(METRE.pow(2)))); + + /** + * The derived unit for inductance (H). + * One Henry is equal to the inductance for which an induced electromotive + * force of one volt is produced when the current is varied at the rate of + * one ampere per second. It is named after the American physicist + * Joseph Henry (1791-1878). + */ + public static final AlternateUnit HENRY = si(new AlternateUnit( + "H", WEBER.divide(AMPERE))); + + /** + * The derived unit for Celsius temperature (). + * This is a unit of temperature such as the freezing point of water + * (at one atmosphere of pressure) is 0 ℃, while the boiling point is + * 100 ℃. + */ + public static final Unit CELSIUS = si(KELVIN.plus(273.15)); + + /** + * The derived unit for luminous flux (lm). + * One Lumen is equal to the amount of light given out through a solid angle + * by a source of one candela intensity radiating equally in all directions. + */ + public static final AlternateUnit LUMEN = si(new AlternateUnit( + "lm", CANDELA.times(STERADIAN))); + + /** + * The derived unit for illuminance (lx). + * One Lux is equal to one lumen per square meter. + */ + public static final AlternateUnit LUX = si(new AlternateUnit( + "lx", LUMEN.divide(METRE.pow(2)))); + + /** + * The derived unit for activity of a radionuclide (Bq). + * One becquerel is the radiation caused by one disintegration per second. + * It is named after the French physicist, Antoine-Henri Becquerel + * (1852-1908). + */ + public static final AlternateUnit BECQUEREL = si(new AlternateUnit( + "Bq", Unit.ONE.divide(SECOND))); + + /** + * The derived unit for absorbed dose, specific energy (imparted), kerma + * (Gy). + * One gray is equal to the dose of one joule of energy absorbed per one + * kilogram of matter. It is named after the British physician + * L. H. Gray (1905-1965). + */ + public static final AlternateUnit GRAY = si(new AlternateUnit( + "Gy", JOULE.divide(KILOGRAM))); + + /** + * The derived unit for dose equivalent (Sv). + * One Sievert is equal is equal to the actual dose, in grays, multiplied + * by a "quality factor" which is larger for more dangerous forms of + * radiation. It is named after the Swedish physicist Rolf Sievert + * (1898-1966). + */ + public static final AlternateUnit SIEVERT = si(new AlternateUnit( + "Sv", JOULE.divide(KILOGRAM))); + + /** + * The derived unit for catalytic activity (kat). + */ + public static final AlternateUnit KATAL = si(new AlternateUnit( + "kat", MOLE.divide(SECOND))); + + ////////////////////////////// + // SI DERIVED PRODUCT UNITS // + ////////////////////////////// + + /** + * The metric unit for velocity quantities (m/s). + */ + public static final Unit METRES_PER_SECOND = si(new ProductUnit( + METRE.divide(SECOND))); + + /** + * Equivalent to {@link #METRES_PER_SECOND}. + */ + public static final Unit METERS_PER_SECOND = METRES_PER_SECOND; + + /** + * The metric unit for acceleration quantities (m/s²). + */ + public static final Unit METRES_PER_SQUARE_SECOND = si(new ProductUnit( + METRES_PER_SECOND.divide(SECOND))); + + /** + * Equivalent to {@link #METRES_PER_SQUARE_SECOND}. + */ + public static final Unit METERS_PER_SQUARE_SECOND = METRES_PER_SQUARE_SECOND; + + /** + * The metric unit for area quantities (). + */ + public static final Unit SQUARE_METRE = si(new ProductUnit( + METRE.times(METRE))); + + /** + * The metric unit for volume quantities (). + */ + public static final Unit CUBIC_METRE = si(new ProductUnit( + SQUARE_METRE.times(METRE))); + + /** + * Equivalent to KILO(METRE). + */ + public static final Unit KILOMETRE = METER.times(1000); + + /** + * Equivalent to {@link #KILOMETRE}. + */ + public static final Unit KILOMETER = KILOMETRE; + + /** + * Equivalent to CENTI(METRE). + */ + public static final Unit CENTIMETRE = METRE.divide(100); + + /** + * Equivalent to {@link #CENTIMETRE}. + */ + public static final Unit CENTIMETER = CENTIMETRE; + + /** + * Equivalent to MILLI(METRE). + */ + public static final Unit MILLIMETRE = METRE.divide(1000); + + /** + * Equivalent to {@link #MILLIMETRE}. + */ + public static final Unit MILLIMETER = MILLIMETRE; + + ///////////////// + // SI PREFIXES // + ///////////////// + + /** + * Returns the specified unit multiplied by the factor + * 1024 + * + * @param unit any unit. + * @return unit.multiply(1e24). + */ + public static Unit YOTTA(Unit unit) { + return unit.transform(E24); + } + + /** + * Returns the specified unit multiplied by the factor + * 1021 + * + * @param unit any unit. + * @return unit.multiply(1e21). + */ + public static Unit ZETTA(Unit unit) { + return unit.transform(E21); + } + + /** + * Returns the specified unit multiplied by the factor + * 1018 + * + * @param unit any unit. + * @return unit.multiply(1e18). + */ + public static Unit EXA(Unit unit) { + return unit.transform(E18); + } + + /** + * Returns the specified unit multiplied by the factor + * 1015 + * + * @param unit any unit. + * @return unit.multiply(1e15). + */ + public static Unit PETA(Unit unit) { + return unit.transform(E15); + } + + /** + * Returns the specified unit multiplied by the factor + * 1012 + * + * @param unit any unit. + * @return unit.multiply(1e12). + */ + public static Unit TERA(Unit unit) { + return unit.transform(E12); + } + + /** + * Returns the specified unit multiplied by the factor + * 109 + * + * @param unit any unit. + * @return unit.multiply(1e9). + */ + public static Unit GIGA(Unit unit) { + return unit.transform(E9); + } + + /** + * Returns the specified unit multiplied by the factor + * 106 + * + * @param unit any unit. + * @return unit.multiply(1e6). + */ + public static Unit MEGA(Unit unit) { + return unit.transform(E6); + } + + /** + * Returns the specified unit multiplied by the factor + * 103 + * + * @param unit any unit. + * @return unit.multiply(1e3). + */ + public static Unit KILO(Unit unit) { + return unit.transform(E3); + } + + /** + * Returns the specified unit multiplied by the factor + * 102 + * + * @param unit any unit. + * @return unit.multiply(1e2). + */ + public static Unit HECTO(Unit unit) { + return unit.transform(E2); + } + + /** + * Returns the specified unit multiplied by the factor + * 101 + * + * @param unit any unit. + * @return unit.multiply(1e1). + */ + public static Unit DEKA(Unit unit) { + return unit.transform(E1); + } + + /** + * Returns the specified unit multiplied by the factor + * 10-1 + * + * @param unit any unit. + * @return unit.multiply(1e-1). + */ + public static Unit DECI(Unit unit) { + return unit.transform(Em1); + } + + /** + * Returns the specified unit multiplied by the factor + * 10-2 + * + * @param unit any unit. + * @return unit.multiply(1e-2). + */ + public static Unit CENTI(Unit unit) { + return unit.transform(Em2); + } + + /** + * Returns the specified unit multiplied by the factor + * 10-3 + * + * @param unit any unit. + * @return unit.multiply(1e-3). + */ + public static Unit MILLI(Unit unit) { + return unit.transform(Em3); + } + + /** + * Returns the specified unit multiplied by the factor + * 10-6 + * + * @param unit any unit. + * @return unit.multiply(1e-6). + */ + public static Unit MICRO(Unit unit) { + return unit.transform(Em6); + } + + /** + * Returns the specified unit multiplied by the factor + * 10-9 + * + * @param unit any unit. + * @return unit.multiply(1e-9). + */ + public static Unit NANO(Unit unit) { + return unit.transform(Em9); + } + + /** + * Returns the specified unit multiplied by the factor + * 10-12 + * + * @param unit any unit. + * @return unit.multiply(1e-12). + */ + public static Unit PICO(Unit unit) { + return unit.transform(Em12); + } + + /** + * Returns the specified unit multiplied by the factor + * 10-15 + * + * @param unit any unit. + * @return unit.multiply(1e-15). + */ + public static Unit FEMTO(Unit unit) { + return unit.transform(Em15); + } + + /** + * Returns the specified unit multiplied by the factor + * 10-18 + * + * @param unit any unit. + * @return unit.multiply(1e-18). + */ + public static Unit ATTO(Unit unit) { + return unit.transform(Em18); + } + + /** + * Returns the specified unit multiplied by the factor + * 10-21 + * + * @param unit any unit. + * @return unit.multiply(1e-21). + */ + public static Unit ZEPTO(Unit unit) { + return unit.transform(Em21); + } + + /** + * Returns the specified unit multiplied by the factor + * 10-24 + * + * @param unit any unit. + * @return unit.multiply(1e-24). + */ + public static Unit YOCTO(Unit unit) { + return unit.transform(Em24); + } + + ///////////////////// + // Collection View // + ///////////////////// + + /** + * Returns a read only view over theunits defined in this class. + * + * @return the collection of SI units. + */ + public Set> getUnits() { + return Collections.unmodifiableSet(UNITS); + } + + /** + * Adds a new unit to the collection. + * + * @param unit the unit being added. + * @return unit. + */ + private static > U si(U unit) { + UNITS.add(unit); + return unit; + } + + // Holds prefix converters (optimization). + + static final MultiplyConverter E24 = new MultiplyConverter(1E24); + + static final MultiplyConverter E21 = new MultiplyConverter(1E21); + + static final RationalConverter E18 = new RationalConverter( + 1000000000000000000L, 1); + + static final RationalConverter E15 = new RationalConverter( + 1000000000000000L, 1); + + static final RationalConverter E12 = new RationalConverter(1000000000000L, + 1); + + static final RationalConverter E9 = new RationalConverter(1000000000L, 1); + + static final RationalConverter E6 = new RationalConverter(1000000L, 1); + + static final RationalConverter E3 = new RationalConverter(1000L, 1); + + static final RationalConverter E2 = new RationalConverter(100L, 1); + + static final RationalConverter E1 = new RationalConverter(10L, 1); + + static final RationalConverter Em1 = new RationalConverter(1, 10L); + + static final RationalConverter Em2 = new RationalConverter(1, 100L); + + static final RationalConverter Em3 = new RationalConverter(1, 1000L); + + static final RationalConverter Em6 = new RationalConverter(1, 1000000L); + + static final RationalConverter Em9 = new RationalConverter(1, 1000000000L); + + static final RationalConverter Em12 = new RationalConverter(1, + 1000000000000L); + + static final RationalConverter Em15 = new RationalConverter(1, + 1000000000000000L); + + static final RationalConverter Em18 = new RationalConverter(1, + 1000000000000000000L); + + static final MultiplyConverter Em21 = new MultiplyConverter(1E-21); + + static final MultiplyConverter Em24 = new MultiplyConverter(1E-24); + + /** + * @deprecated replaced by {@link #METRES_PER_SECOND}. + */ + public static final Unit METRE_PER_SECOND = METRES_PER_SECOND; + + /** + * @deprecated replaced by {@link #METRES_PER_SQUARE_SECOND}. + */ + public static final Unit METRE_PER_SQUARE_SECOND = METRES_PER_SQUARE_SECOND; +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/unit/SystemOfUnits.java b/measure/src/main/java/javax/measure/unit/SystemOfUnits.java new file mode 100644 index 00000000..843e9663 --- /dev/null +++ b/measure/src/main/java/javax/measure/unit/SystemOfUnits.java @@ -0,0 +1,32 @@ +/* + * 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.unit; + +import java.util.Set; + +/** + *

This class represents a system of units, it groups units together + * for historical or cultural reasons. Nothing prevents a unit from + * belonging to several system of units at the same time + * (for example an imperial system would have many of the units + * held by {@link NonSI}).

+ * + * @author Jean-Marie Dautelle + * @version 4.2, August 26, 2007 + */ +public abstract class SystemOfUnits { + + /** + * Returns a read only view over the units defined in this system. + * + * @return the collection of units. + */ + public abstract Set> getUnits(); + +} diff --git a/measure/src/main/java/javax/measure/unit/TransformedUnit.java b/measure/src/main/java/javax/measure/unit/TransformedUnit.java new file mode 100644 index 00000000..1026b8f8 --- /dev/null +++ b/measure/src/main/java/javax/measure/unit/TransformedUnit.java @@ -0,0 +1,121 @@ +/* + * 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.unit; + +import javax.measure.converter.UnitConverter; +import javax.measure.quantity.Quantity; + +/** + *

This class represents the units derived from other units using + * {@link UnitConverter converters}.

+ * + *

Examples of transformed units:[code] + * CELSIUS = KELVIN.add(273.15); + * FOOT = METER.multiply(0.3048); + * MILLISECOND = MILLI(SECOND); + * [/code]

+ * + *

Transformed units have no label. But like any other units, + * they may have labels attached to them:[code] + * UnitFormat.getStandardInstance().label(FOOT, "ft"); + * [/code] + * or aliases: [code] + * UnitFormat.getStandardInstance().alias(CENTI(METER)), "centimeter"); + * UnitFormat.getStandardInstance().alias(CENTI(METER)), "centimetre"); + * [/code]

+ * + * @author Jean-Marie Dautelle + * @version 3.1, April 22, 2006 + * @see Unit#plus(double) + * @see Unit#times(double) + * @see Unit#transform(UnitConverter) + * @see UnitFormat + */ +public final class TransformedUnit extends DerivedUnit { + + /** + * Holds the parent unit (not a transformed unit). + */ + private final Unit _parentUnit; + + /** + * Holds the converter to the parent unit. + */ + private final UnitConverter _toParentUnit; + + /** + * Creates a transformed unit from the specified parent unit. + * + * @param parentUnit the untransformed unit from which this unit is + * derived. + * @param toParentUnit the converter to the parent units. + * @throws IllegalArgumentException if toParentUnit == + * {@link UnitConverter#IDENTITY UnitConverter.IDENTITY} + */ + TransformedUnit(Unit parentUnit, UnitConverter toParentUnit) { + if (toParentUnit == UnitConverter.IDENTITY) + throw new IllegalArgumentException("Identity not allowed"); + _parentUnit = parentUnit; + _toParentUnit = toParentUnit; + } + + /** + * Returns the parent unit for this unit. The parent unit is the + * untransformed unit from which this unit is derived. + * + * @return the untransformed unit from which this unit is derived. + */ + public Unit getParentUnit() { + return _parentUnit; + } + + /** + * Returns the converter to the parent unit. + * + * @return the converter to the parent unit. + */ + public UnitConverter toParentUnit() { + return _toParentUnit; + } + + /** + * Indicates if this transformed unit is considered equals to the specified + * object (both are transformed units with equal parent unit and equal + * converter to parent unit). + * + * @param that the object to compare for equality. + * @return true if this and that + * are considered equals; falseotherwise. + */ + public boolean equals(Object that) { + if (this == that) return true; + if (!(that instanceof TransformedUnit)) return false; + TransformedUnit thatUnit = (TransformedUnit) that; + return this._parentUnit.equals(thatUnit._parentUnit) && + this._toParentUnit.equals(thatUnit._toParentUnit); + } + + // Implements abstract method. + public int hashCode() { + return _parentUnit.hashCode() + _toParentUnit.hashCode(); + } + + // Implements abstract method. + public Unit getStandardUnit() { + return _parentUnit.getStandardUnit(); + } + + // Implements abstract method. + public UnitConverter toStandardUnit() { + return _parentUnit.toStandardUnit().concatenate(_toParentUnit); + } + + private static final long serialVersionUID = 1L; + +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/unit/Unit.java b/measure/src/main/java/javax/measure/unit/Unit.java new file mode 100644 index 00000000..520d682d --- /dev/null +++ b/measure/src/main/java/javax/measure/unit/Unit.java @@ -0,0 +1,501 @@ +/* + * 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.unit; + +import java.io.Serializable; +import java.text.ParseException; +import java.text.ParsePosition; +import java.util.HashMap; + +import javax.measure.MeasureFormat; +import javax.measure.converter.AddConverter; +import javax.measure.converter.ConversionException; +import javax.measure.converter.MultiplyConverter; +import javax.measure.converter.RationalConverter; +import javax.measure.converter.UnitConverter; +import javax.measure.quantity.Dimensionless; +import javax.measure.quantity.Quantity; + +/** + *

This class represents a determinate {@link javax.measure.quantity.Quantity + * quantity} (as of length, time, heat, or value) adopted as a standard + * of measurement.

+ * + *

It is helpful to think of instances of this class as recording the + * history by which they are created. Thus, for example, the string + * "g/kg" (which is a dimensionless unit) would result from invoking + * the method toString() on a unit that was created by dividing a + * gram unit by a kilogram unit. Yet, "kg" divided by "kg" returns + * {@link #ONE} and not "kg/kg" due to automatic unit factorization.

+ * + *

This class supports the multiplication of offsets units. The result is + * usually a unit not convertible to its {@link #getStandardUnit standard unit}. + * Such units may appear in derivative quantities. For example °C/m is an + * unit of gradient, which is common in atmospheric and oceanographic + * research.

+ * + *

Units raised at rational powers are also supported. For example + * the cubic root of "liter" is a unit compatible with meter.

+ * + *

Instances of this class are immutable.

+ * + * @author Jean-Marie Dautelle + * @author Steve Emmerson + * @author Martin Desruisseaux + * @version 3.2, August 28, 2006 + * @see + * Wikipedia: Units of measurement + */ +public abstract class Unit implements Serializable { + + /** + * Holds the dimensionless unit ONE. + */ + public static final Unit ONE = new ProductUnit(); + + /** + * Holds the unique symbols collection (base unit or alternate units). + */ + static final HashMap> SYMBOL_TO_UNIT = new HashMap>(); + + /** + * Default constructor. + */ + protected Unit() { + } + + ////////////////////////////////////////////////////// + // Contract methods (for sub-classes to implement). // + ////////////////////////////////////////////////////// + + /** + * Returns the {@link BaseUnit base unit}, {@link AlternateUnit alternate + * unit} or product of base units and alternate units this unit is derived + * from. The standard unit identifies the "type" of + * {@link javax.measure.quantity.Quantity quantity} for which this unit is employed. + * For example:[code] + * boolean isAngularVelocity(Unit u) { + * return u.getStandardUnit().equals(RADIAN.divide(SECOND)); + * } + * assert(REVOLUTION.divide(MINUTE).isAngularVelocity()); + * [/code] + * + *

Note: Having the same system unit is not sufficient to ensure + * that a converter exists between the two units + * (e.g. °C/m and K/m).

+ * @return the system unit this unit is derived from. + */ + public abstract Unit getStandardUnit(); + + + /** + * Returns the converter from this unit to its system unit. + * + * @return this.getConverterTo(this.getSystemUnit()) + */ + public abstract UnitConverter toStandardUnit(); + + /** + * Returns the hash code for this unit. + * + * @return this unit hashcode value. + */ + public abstract int hashCode(); + + /** + * Indicates if the specified unit can be considered equals to + * the one specified. + * + * @param that the object to compare to. + * @return true if this unit is considered equal to + * that unit; false otherwise. + */ + public abstract boolean equals(Object that); + + /** + * Indicates if this unit is a standard unit (base units and + * alternate units are standard units). The standard unit identifies + * the "type" of {@link javax.measure.quantity.Quantity quantity} for + * which the unit is employed. + * + * @return getStandardUnit().equals(this) + */ + public boolean isStandardUnit() { + return getStandardUnit().equals(this); + } + + /** + * Indicates if this unit is compatible with the unit specified. + * Units don't need to be equals to be compatible. For example:[code] + * RADIAN.equals(ONE) == false + * RADIAN.isCompatible(ONE) == true + * [/code] + * @param that the other unit. + * @return this.getDimension().equals(that.getDimension()) + * @see #getDimension() + */ + public final boolean isCompatible(Unit that) { + return (this == that) + || this.getStandardUnit().equals(that.getStandardUnit()) + || this.getDimension().equals(that.getDimension()); + } + + /** + * Casts this unit to a parameterized unit of specified nature or + * throw a ClassCastException if the dimension of the + * specified quantity and this unit's dimension do not match. + * For example:[code] + * Unit LIGHT_YEAR = NonSI.C.times(NonSI.YEAR).asType(Length.class); + * [/code] + * + * @param type the quantity class identifying the nature of the unit. + * @return this unit parameterized with the specified type. + * @throws ClassCastException if the dimension of this unit is different + * from the specified quantity dimension. + * @throws UnsupportedOperationException if the specified quantity class + * does not have a public static field named "UNIT" holding the + * standard unit for the quantity. + */ + @SuppressWarnings("unchecked") + public final Unit asType(Class type) throws ClassCastException { + Dimension dim1 = this.getDimension(); + Unit u = null; + try { + u = (Unit)type.getField("UNIT").get(null); + } catch (Exception e) { + throw new Error(e); + } + Dimension dim2 = u.getDimension(); + if (!dim1.equals(dim2)) + throw new ClassCastException(); + return (Unit)this; + } + + /** + * Returns the dimension of this unit (depends upon the current + * dimensional {@link Dimension.Model model}). + * + * @return the dimension of this unit for the current model. + */ + public final Dimension getDimension() { + Unit systemUnit = this.getStandardUnit(); + if (systemUnit instanceof BaseUnit) + return Dimension.getModel().getDimension((BaseUnit) systemUnit); + if (systemUnit instanceof AlternateUnit) + return ((AlternateUnit) systemUnit).getParent().getDimension(); + // Product of units. + ProductUnit productUnit = (ProductUnit) systemUnit; + Dimension dimension = Dimension.NONE; + for (int i = 0; i < productUnit.getUnitCount(); i++) { + Unit unit = productUnit.getUnit(i); + Dimension d = unit.getDimension().pow(productUnit.getUnitPow(i)) + .root(productUnit.getUnitRoot(i)); + dimension = dimension.times(d); + } + return dimension; + } + + /** + * Returns a converter of numeric values from this unit to another unit. + * + * @param that the unit to which to convert the numeric values. + * @return the converter from this unit to that unit. + * @throws ConversionException if the conveter cannot be constructed + * (e.g. !this.isCompatible(that)). + */ + public final UnitConverter getConverterTo(Unit that) + throws ConversionException { + if (this.equals(that)) + return UnitConverter.IDENTITY; + Unit thisSystemUnit = this.getStandardUnit(); + Unit thatSystemUnit = that.getStandardUnit(); + if (thisSystemUnit.equals(thatSystemUnit)) + return that.toStandardUnit().inverse().concatenate( + this.toStandardUnit()); + // Use dimensional transforms. + if (!thisSystemUnit.getDimension() + .equals(thatSystemUnit.getDimension())) + throw new ConversionException(this + " is not compatible with " + + that); + // Transform between SystemUnit and BaseUnits is Identity. + UnitConverter thisTransform = this.toStandardUnit().concatenate( + transformOf(this.getBaseUnits())); + UnitConverter thatTransform = that.toStandardUnit().concatenate( + transformOf(that.getBaseUnits())); + return thatTransform.inverse().concatenate(thisTransform); + } + + private Unit getBaseUnits() { + Unit systemUnit = this.getStandardUnit(); + if (systemUnit instanceof BaseUnit) return systemUnit; + if (systemUnit instanceof AlternateUnit) + return ((AlternateUnit)systemUnit).getParent().getBaseUnits(); + if (systemUnit instanceof ProductUnit) { + ProductUnit productUnit = (ProductUnit)systemUnit; + Unit baseUnits = ONE; + for (int i = 0; i < productUnit.getUnitCount(); i++) { + Unit unit = productUnit.getUnit(i).getBaseUnits(); + unit = unit.pow(productUnit.getUnitPow(i)); + unit = unit.root(productUnit.getUnitRoot(i)); + baseUnits = baseUnits.times(unit); + } + return baseUnits; + } else { + throw new InternalError( + "System Unit cannot be an instance of " + this.getClass()); + } + } + private static UnitConverter transformOf(Unit baseUnits) { + if (baseUnits instanceof BaseUnit) + return Dimension.getModel().getTransform((BaseUnit) baseUnits); + // Product of units. + ProductUnit productUnit = (ProductUnit) baseUnits; + UnitConverter converter = UnitConverter.IDENTITY; + for (int i = 0; i < productUnit.getUnitCount(); i++) { + Unit unit = productUnit.getUnit(i); + UnitConverter cvtr = transformOf(unit); + if (!cvtr.isLinear()) + throw new ConversionException(baseUnits + + " is non-linear, cannot convert"); + if (productUnit.getUnitRoot(i) != 1) + throw new ConversionException(productUnit + + " holds a base unit with fractional exponent"); + int pow = productUnit.getUnitPow(i); + if (pow < 0) { // Negative power. + pow = -pow; + cvtr = cvtr.inverse(); + } + for (int j = 0; j < pow; j++) { + converter = converter.concatenate(cvtr); + } + } + return converter; + } + + /** + * Returns a unit equivalent to this unit but used in expressions to + * distinguish between quantities of a different nature but of the same + * dimensions. + * + *

Examples of alternate units:[code] + * Unit RADIAN = ONE.alternate("rad"); + * Unit NEWTON = METER.times(KILOGRAM).divide(SECOND.pow(2)).alternate("N"); + * Unit PASCAL = NEWTON.divide(METER.pow(2)).alternate("Pa"); + * [/code]

+ * + * @param symbol the new symbol for the alternate unit. + * @return the alternate unit. + * @throws UnsupportedOperationException if this unit is not a standard unit. + * @throws IllegalArgumentException if the specified symbol is already + * associated to a different unit. + */ + public final AlternateUnit alternate(String symbol) { + return new AlternateUnit(symbol, this); + } + + /** + * Returns the combination of this unit with the specified sub-unit. + * Compound units are typically used for formatting purpose. + * Examples of compound units:[code] + * HOUR_MINUTE = NonSI.HOUR.compound(NonSI.MINUTE); + * DEGREE_MINUTE_SECOND_ANGLE = NonSI.DEGREE_ANGLE.compound( + * NonSI.DEGREE_MINUTE).compound(NonSI.SECOND_ANGLE); + * [/code] + * + * @param subunit the sub-unit to combine with this unit. + * @return the corresponding compound unit. + */ + public final CompoundUnit compound(Unit subunit) { + return new CompoundUnit(this, subunit); + } + + /** + * Returns the unit derived from this unit using the specified converter. + * The converter does not need to be linear. For example:[code] + * Unit DECIBEL = Unit.ONE.transform( + * new LogConverter(10).inverse().concatenate( + * new RationalConverter(1, 10)));[/code] + * + * @param operation the converter from the transformed unit to this unit. + * @return the unit after the specified transformation. + */ + public final Unit transform(UnitConverter operation) { + if (this instanceof TransformedUnit) { + TransformedUnit tf = (TransformedUnit) this; + Unit parent = tf.getParentUnit(); + UnitConverter toParent = tf.toParentUnit().concatenate(operation); + if (toParent == UnitConverter.IDENTITY) + return parent; + return new TransformedUnit(parent, toParent); + } + if (operation == UnitConverter.IDENTITY) + return this; + return new TransformedUnit(this, operation); + } + + /** + * Returns the result of adding an offset to this unit. The returned unit + * is convertible with all units that are convertible with this unit. + * + * @param offset the offset added (expressed in this unit, + * e.g. CELSIUS = KELVIN.plus(273.15)). + * @return this.transform(new AddConverter(offset)) + */ + public final Unit plus(double offset) { + return transform(new AddConverter(offset)); + } + + /** + * Returns the result of multiplying this unit by an exact factor. + * + * @param factor the exact scale factor + * (e.g. KILOMETER = METER.times(1000)). + * @return this.transform(new RationalConverter(factor, 1)) + */ + public final Unit times(long factor) { + return transform(new RationalConverter(factor, 1)); + } + + /** + * Returns the result of multiplying this unit by a an approximate factor + * + * @param factor the approximate factor (e.g. + * ELECTRON_MASS = KILOGRAM.times(9.10938188e-31)). + * @return this.transform(new MultiplyConverter(factor)) + */ + public final Unit times(double factor) { + return transform(new MultiplyConverter(factor)); + } + + /** + * Returns the product of this unit with the one specified. + * + * @param that the unit multiplicand. + * @return this * that + */ + public final Unit times(Unit that) { + return ProductUnit.getProductInstance(this, that); + } + + /** + * Returns the inverse of this unit. + * + * @return 1 / this + */ + public final Unit inverse() { + return ProductUnit.getQuotientInstance(ONE, this); + } + + /** + * Returns the result of dividing this unit by an exact divisor. + * + * @param divisor the exact divisor. + * (e.g. QUART = GALLON_LIQUID_US.divide(4)). + * @return this.transform(new RationalConverter(1 , divisor)) + */ + public final Unit divide(long divisor) { + return transform(new RationalConverter(1, divisor)); + } + + /** + * Returns the result of dividing this unit by an approximate divisor. + * + * @param divisor the approximate divisor. + * @return this.transform(new MultiplyConverter(1.0 / divisor)) + */ + public final Unit divide(double divisor) { + return transform(new MultiplyConverter(1.0 / divisor)); + } + + /** + * Returns the quotient of this unit with the one specified. + * + * @param that the unit divisor. + * @return this / that + */ + public final Unit divide(Unit that) { + return this.times(that.inverse()); + } + + /** + * Returns a unit equals to the given root of this unit. + * + * @param n the root's order. + * @return the result of taking the given root of this unit. + * @throws ArithmeticException if n == 0. + */ + public final Unit root(int n) { + if (n > 0) { + return ProductUnit.getRootInstance(this, n); + } else if (n == 0) { + throw new ArithmeticException("Root's order of zero"); + } else { // n < 0 + return ONE.divide(this.root(-n)); + } + } + + /** + * Returns a unit equals to this unit raised to an exponent. + * + * @param n the exponent. + * @return the result of raising this unit to the exponent. + */ + public final Unit pow(int n) { + if (n > 0) { + return this.times(this.pow(n - 1)); + } else if (n == 0) { + return ONE; + } else { // n < 0 + return ONE.divide(this.pow(-n)); + } + } + + /** + * Returns a unit instance that is defined from the specified + * character sequence using the {@link UnitFormat#getInstance() + * standard unit format}. + *

Examples of valid entries (all for meters per second squared) are: + *

    + *
  • m*s-2
  • + *
  • m/s²
  • + *
  • m·s-²
  • + *
  • m*s**-2
  • + *
  • m^+1 s^-2
  • + *

+ * + * @param csq the character sequence to parse. + * @return UnitFormat.getStandardInstance().parse(csq, new ParsePosition(0)) + * @throws IllegalArgumentException if the specified character sequence + * cannot be correctly parsed (e.g. symbol unknown). + */ + public static Unit valueOf(CharSequence csq) { + try { + return UnitFormat.getInstance() + .parseProductUnit(csq, new ParsePosition(0)); + } catch (ParseException e) { + throw new IllegalArgumentException(e); + } + } + + ////////////////////// + // GENERAL CONTRACT // + ////////////////////// + + /** + * Returns the standard String representation of this unit. + * This representation is not affected by locale. Locale-sensitive + * unit formatting and parsing is handled by the {@link MeasureFormat} + * class and its subclasses. + * + * @return UnitFormat.getStandardInstance().format(this) + */ + public final String toString() { + return UnitFormat.getInstance().format(this); + } +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/unit/UnitFormat.java b/measure/src/main/java/javax/measure/unit/UnitFormat.java new file mode 100644 index 00000000..24446562 --- /dev/null +++ b/measure/src/main/java/javax/measure/unit/UnitFormat.java @@ -0,0 +1,940 @@ +/* + * 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.unit; + +import java.io.IOException; +import java.lang.CharSequence; +import java.text.FieldPosition; +import java.text.Format; +import java.text.ParseException; +import java.text.ParsePosition; +import java.util.HashMap; +import java.util.Locale; +//@RETROWEAVER import javolution.text.Appendable; +import javax.measure.converter.AddConverter; +import javax.measure.converter.MultiplyConverter; +import javax.measure.converter.RationalConverter; +import javax.measure.converter.UnitConverter; +import javax.measure.quantity.Quantity; + +import static javax.measure.unit.SI.*; + +/** + *

This class provides the interface for formatting and parsing {@link + * Unit units}.

+ * + *

For all {@link SI} units, the 20 SI prefixes used to form decimal + * multiples and sub-multiples of SI units are recognized. + * {@link NonSI} units are directly recognized. For example:[code] + * Unit.valueOf("m°C").equals(SI.MILLI(SI.CELSIUS)) + * Unit.valueOf("kW").equals(SI.KILO(SI.WATT)) + * Unit.valueOf("ft").equals(SI.METER.multiply(0.3048))[/code]

+ * + * @author
Jean-Marie Dautelle + * @author Eric Russell + * @version 1.3, August 29, 2006 + */ +public abstract class UnitFormat extends Format { + + /** + * Holds the standard unit format. + */ + private static final DefaultFormat DEFAULT = new DefaultFormat(); + + /** + * Holds the ASCIIFormat unit format. + */ + private static final ASCIIFormat ASCII = new ASCIIFormat(); + + /** + * Returns the unit format for the default locale (format used by + * {@link Unit#valueOf(CharSequence) Unit.valueOf(CharSequence)} and + * {@link Unit#toString() Unit.toString()}). + * + * @return the default unit format (locale sensitive). + */ + public static UnitFormat getInstance() { + return UnitFormat.getInstance(Locale.getDefault()); + } + + /** + * Returns the unit format for the specified locale. + * + * @return the unit format for the specified locale. + */ + public static UnitFormat getInstance(Locale inLocale) { + return DEFAULT; // TBD: Implement Locale Format. + } + + /** + * Returns the UCUM + * international unit format; this format uses characters range + * 0000-007F exclusively and is not locale-sensitive. + * For example: kg.m/s2 + * + * @return the UCUM international format. + */ + public static UnitFormat getUCUMInstance() { + return UnitFormat.ASCII; // TBD - Provide UCUM implementation. + } + + /** + * Base constructor. + */ + protected UnitFormat() { + } + + /** + * Formats the specified unit. + * + * @param unit the unit to format. + * @param appendable the appendable destination. + * @throws IOException if an error occurs. + */ + public abstract Appendable format(Unit unit, Appendable appendable) + throws IOException; + + /** + * Parses a sequence of character to produce a unit or a rational product + * of unit. + * + * @param csq the CharSequence to parse. + * @param pos an object holding the parsing index and error position. + * @return an {@link Unit} parsed from the character sequence. + * @throws IllegalArgumentException if the character sequence contains + * an illegal syntax. + */ + public abstract Unit parseProductUnit(CharSequence csq, ParsePosition pos) + throws ParseException; + + /** + * Parses a sequence of character to produce a single unit. + * + * @param csq the CharSequence to parse. + * @param pos an object holding the parsing index and error position. + * @return an {@link Unit} parsed from the character sequence. + * @throws IllegalArgumentException if the character sequence does not contain + * a valid unit identifier. + */ + public abstract Unit parseSingleUnit(CharSequence csq, ParsePosition pos) + throws ParseException; + + /** + * Attaches a system-wide label to the specified unit. For example: + * [code] + * UnitFormat.getInstance().label(DAY.multiply(365), "year"); + * UnitFormat.getInstance().label(METER.multiply(0.3048), "ft"); + * [/code] + * If the specified label is already associated to an unit the previous + * association is discarded or ignored. + * + * @param unit the unit being labelled. + * @param label the new label for this unit. + * @throws IllegalArgumentException if the label is not a + * {@link UnitFormat#isValidIdentifier(String)} valid identifier. + */ + public abstract void label(Unit unit, String label); + + /** + * Attaches a system-wide alias to this unit. Multiple aliases may + * be attached to the same unit. Aliases are used during parsing to + * recognize different variants of the same unit. For example: + * [code] + * UnitFormat.getLocaleInstance().alias(METER.multiply(0.3048), "foot"); + * UnitFormat.getLocaleInstance().alias(METER.multiply(0.3048), "feet"); + * UnitFormat.getLocaleInstance().alias(METER, "meter"); + * UnitFormat.getLocaleInstance().alias(METER, "metre"); + * [/code] + * If the specified label is already associated to an unit the previous + * association is discarded or ignored. + * + * @param unit the unit being aliased. + * @param alias the alias attached to this unit. + * @throws IllegalArgumentException if the label is not a + * {@link UnitFormat#isValidIdentifier(String)} valid identifier. + */ + public abstract void alias(Unit unit, String alias); + + /** + * Indicates if the specified name can be used as unit identifier. + * + * @param name the identifier to be tested. + * @return true if the name specified can be used as + * label or alias for this format;false otherwise. + */ + public abstract boolean isValidIdentifier(String name); + + /** + * Formats an unit and appends the resulting text to a given string + * buffer (implements java.text.Format). + * + * @param unit the unit to format. + * @param toAppendTo where the text is to be appended + * @param pos the field position (not used). + * @return toAppendTo + */ + public final StringBuffer format(Object unit, final StringBuffer toAppendTo, + FieldPosition pos) { + try { + Object dest = toAppendTo; + if (dest instanceof Appendable) { + format((Unit) unit, (Appendable)dest); + } else { // When retroweaver is used to produce 1.4 binaries. + format((Unit) unit, new Appendable() { + + public Appendable append(char arg0) throws IOException { + toAppendTo.append(arg0); + return null; + } + + public Appendable append(CharSequence arg0) throws IOException { + toAppendTo.append(arg0); + return null; + } + + public Appendable append(CharSequence arg0, int arg1, int arg2) throws IOException { + toAppendTo.append(arg0.subSequence(arg1, arg2)); + return null; + }}); + } + return toAppendTo; + } catch (IOException e) { + throw new Error(e); // Should never happen. + } + } + + /** + * Parses the text from a string to produce an object + * (implements java.text.Format). + * + * @param source the string source, part of which should be parsed. + * @param pos the cursor position. + * @return the corresponding unit or null if the string + * cannot be parsed. + */ + public final Unit parseObject(String source, ParsePosition pos) { + int start = pos.getIndex(); + try { + return parseProductUnit(source, pos); + } catch (ParseException e) { + pos.setIndex(start); + pos.setErrorIndex(e.getErrorOffset()); + return null; + } + } + + + /** + * This class represents an exponent with both a power (numerator) + * and a root (denominator). + */ + private static class Exponent { + public final int pow; + public final int root; + public Exponent (int pow, int root) { + this.pow = pow; + this.root = root; + } + } + + /** + * This class represents the standard format. + */ + protected static class DefaultFormat extends UnitFormat { + + /** + * Holds the name to unit mapping. + */ + final HashMap> _nameToUnit = new HashMap>(); + + /** + * Holds the unit to name mapping. + */ + final HashMap, String> _unitToName = new HashMap, String>(); + + @Override + public void label(Unit unit, String label) { + if (!isValidIdentifier(label)) + throw new IllegalArgumentException("Label: " + label + + " is not a valid identifier."); + synchronized (this) { + _nameToUnit.put(label, unit); + _unitToName.put(unit, label); + } + } + + @Override + public void alias(Unit unit, String alias) { + if (!isValidIdentifier(alias)) + throw new IllegalArgumentException("Alias: " + alias + + " is not a valid identifier."); + synchronized (this) { + _nameToUnit.put(alias, unit); + } + } + + @Override + public boolean isValidIdentifier(String name) { + if ((name == null) || (name.length() == 0)) + return false; + for (int i = 0; i < name.length(); i++) { + if (!isUnitIdentifierPart(name.charAt(i))) + return false; + } + return true; + } + + static boolean isUnitIdentifierPart(char ch) { + return Character.isLetter(ch) || + (!Character.isWhitespace(ch) && !Character.isDigit(ch) + && (ch != '·') && (ch != '*') && (ch != '/') + && (ch != '(') && (ch != ')') && (ch != '[') && (ch != ']') + && (ch != '¹') && (ch != '²') && (ch != '³') + && (ch != '^') && (ch != '+') && (ch != '-')); + } + + // Returns the name for the specified unit or null if product unit. + public String nameFor(Unit unit) { + // Searches label database. + String label = _unitToName.get(unit); + if (label != null) + return label; + if (unit instanceof BaseUnit) + return ((BaseUnit) unit).getSymbol(); + if (unit instanceof AlternateUnit) + return ((AlternateUnit) unit).getSymbol(); + if (unit instanceof TransformedUnit) { + TransformedUnit tfmUnit = (TransformedUnit) unit; + Unit baseUnits = tfmUnit.getStandardUnit(); + UnitConverter cvtr = tfmUnit.toStandardUnit(); + StringBuffer result = new StringBuffer(); + String baseUnitName = baseUnits.toString(); + if ((baseUnitName.indexOf('·') >= 0) || + (baseUnitName.indexOf('*') >= 0) || + (baseUnitName.indexOf('/') >= 0)) { + // We could use parentheses whenever baseUnits is an + // instanceof ProductUnit, but most ProductUnits have aliases, + // so we'd end up with a lot of unnecessary parentheses. + result.append('('); + result.append(baseUnitName); + result.append(')'); + } else { + result.append(baseUnitName); + } + if (cvtr instanceof AddConverter) { + result.append('+'); + result.append(((AddConverter) cvtr).getOffset()); + } else if (cvtr instanceof RationalConverter) { + long dividend = ((RationalConverter) cvtr).getDividend(); + if (dividend != 1) { + result.append('*'); + result.append(dividend); + } + long divisor = ((RationalConverter) cvtr).getDivisor(); + if (divisor != 1) { + result.append('/'); + result.append(divisor); + } ; + } else if (cvtr instanceof MultiplyConverter) { + result.append('*'); + result.append(((MultiplyConverter) cvtr).getFactor()); + } else { // Other converters. + return "[" + baseUnits + "?]"; + } + return result.toString(); + } + // Compound unit. + if (unit instanceof CompoundUnit) { + CompoundUnit cpdUnit = (CompoundUnit) unit; + return nameFor(cpdUnit.getHigher()).toString() + ":" + + nameFor(cpdUnit.getLower()); + } + return null; // Product unit. + } + + // Returns the unit for the specified name. + public Unit unitFor(String name) { + Unit unit = _nameToUnit.get(name); + if (unit != null) + return unit; + unit = Unit.SYMBOL_TO_UNIT.get(name); + return unit; + } + + //////////////////////////// + // Parsing. + + @SuppressWarnings("unchecked") + public Unit parseSingleUnit(CharSequence csq, ParsePosition pos) + throws ParseException { + int startIndex = pos.getIndex(); + String name = readIdentifier(csq, pos); + Unit unit = unitFor(name); + check(unit != null, name + " not recognized", csq, startIndex); + return unit; + } + + @SuppressWarnings("unchecked") + @Override + public Unit parseProductUnit(CharSequence csq, ParsePosition pos) + throws ParseException { + Unit result = Unit.ONE; + int token = nextToken(csq, pos); + switch (token) { + case IDENTIFIER: + result = parseSingleUnit(csq, pos); + break; + case OPEN_PAREN: + pos.setIndex(pos.getIndex() + 1); + result = parseProductUnit(csq, pos); + token = nextToken(csq, pos); + check(token == CLOSE_PAREN, "')' expected", csq, pos.getIndex()); + pos.setIndex(pos.getIndex() + 1); + break; + } + token = nextToken(csq, pos); + while (true) { + switch (token) { + case EXPONENT: + Exponent e = readExponent(csq, pos); + if (e.pow != 1) { + result = result.pow(e.pow); + } + if (e.root != 1) { + result = result.root(e.root); + } + break; + case MULTIPLY: + pos.setIndex(pos.getIndex() + 1); + token = nextToken(csq, pos); + if (token == INTEGER) { + long n = readLong(csq, pos); + if (n != 1) { + result = result.times(n); + } + } else if (token == FLOAT) { + double d = readDouble(csq, pos); + if (d != 1.0) { + result = result.times(d); + } + } else { + result = result.times(parseProductUnit(csq, pos)); + } + break; + case DIVIDE: + pos.setIndex(pos.getIndex() + 1); + token = nextToken(csq, pos); + if (token == INTEGER) { + long n = readLong(csq, pos); + if (n != 1) { + result = result.divide(n); + } + } else if (token == FLOAT) { + double d = readDouble(csq, pos); + if (d != 1.0) { + result = result.divide(d); + } + } else { + result = result.divide(parseProductUnit(csq, pos)); + } + break; + case PLUS: + pos.setIndex(pos.getIndex() + 1); + token = nextToken(csq, pos); + if (token == INTEGER) { + long n = readLong(csq, pos); + if (n != 1) { + result = result.plus(n); + } + } else if (token == FLOAT) { + double d = readDouble(csq, pos); + if (d != 1.0) { + result = result.plus(d); + } + } else { + throw new ParseException("not a number", pos.getIndex()); + } + break; + case EOF: + case CLOSE_PAREN: + return result; + default: + throw new ParseException("unexpected token " + token, pos.getIndex()); + } + token = nextToken(csq, pos); + } + } + + private static final int EOF = 0; + private static final int IDENTIFIER = 1; + private static final int OPEN_PAREN= 2; + private static final int CLOSE_PAREN= 3; + private static final int EXPONENT = 4; + private static final int MULTIPLY = 5; + private static final int DIVIDE = 6; + private static final int PLUS = 7; + private static final int INTEGER = 8; + private static final int FLOAT = 9; + + private int nextToken(CharSequence csq, ParsePosition pos) { + final int length = csq.length(); + while (pos.getIndex() < length) { + char c = csq.charAt(pos.getIndex()); + if (isUnitIdentifierPart(c)) { + return IDENTIFIER; + } else if (c == '(') { + return OPEN_PAREN; + } else if (c == ')') { + return CLOSE_PAREN; + } else if ((c == '^') || (c == '¹') || (c == '²') || (c == '³')) { + return EXPONENT; + } else if (c == '*') { + char c2 = csq.charAt(pos.getIndex() + 1); + if (c2 == '*') { + return EXPONENT; + } else { + return MULTIPLY; + } + } else if (c == '·') { + return MULTIPLY; + } else if (c == '/') { + return DIVIDE; + } else if (c == '+') { + return PLUS; + } else if ((c == '-') || Character.isDigit(c)) { + int index = pos.getIndex()+1; + while ((index < length) && + (Character.isDigit(c) || (c == '-') || (c == '.') || (c == 'E'))) { + c = csq.charAt(index++); + if (c == '.') { + return FLOAT; + } + } + return INTEGER; + } + pos.setIndex(pos.getIndex() + 1); + } + return EOF; + } + + private void check(boolean expr, String message, CharSequence csq, + int index) throws ParseException { + if (!expr) { + throw new ParseException(message + " (in " + csq + + " at index " + index + ")", index); + } + } + + private Exponent readExponent (CharSequence csq, ParsePosition pos) { + char c = csq.charAt(pos.getIndex()); + if (c == '^') { + pos.setIndex(pos.getIndex()+1); + } else if (c == '*') { + pos.setIndex(pos.getIndex()+2); + } + final int length = csq.length(); + int pow = 0; + boolean isPowNegative = false; + int root = 0; + boolean isRootNegative = false; + boolean isRoot = false; + while (pos.getIndex() < length) { + c = csq.charAt(pos.getIndex()); + if (c == '¹') { + if (isRoot) { + root = root * 10 + 1; + } else { + pow = pow * 10 + 1; + } + } else if (c == '²') { + if (isRoot) { + root = root * 10 + 2; + } else { + pow = pow * 10 + 2; + } + } else if (c == '³') { + if (isRoot) { + root = root * 10 + 3; + } else { + pow = pow * 10 + 3; + } + } else if (c == '-') { + if (isRoot) { + isRootNegative = true; + } else { + isPowNegative = true; + } + } else if ((c >= '0') && (c <= '9')) { + if (isRoot) { + root = root * 10 + (c - '0'); + } else { + pow = pow * 10 + (c - '0'); + } + } else if (c == ':') { + isRoot = true; + } else { + break; + } + pos.setIndex(pos.getIndex()+1); + } + if (pow == 0) pow = 1; + if (root == 0) root = 1; + return new Exponent(isPowNegative ? -pow : pow, + isRootNegative ? -root : root); + } + + private long readLong (CharSequence csq, ParsePosition pos) { + final int length = csq.length(); + int result = 0; + boolean isNegative = false; + while (pos.getIndex() < length) { + char c = csq.charAt(pos.getIndex()); + if (c == '-') { + isNegative = true; + } else if ((c >= '0') && (c <= '9')) { + result = result * 10 + (c - '0'); + } else { + break; + } + pos.setIndex(pos.getIndex()+1); + } + return isNegative ? -result : result; + } + + private double readDouble (CharSequence csq, ParsePosition pos) { + final int length = csq.length(); + int start = pos.getIndex(); + int end = start+1; + while (end < length) { + if ("012356789+-.E".indexOf(csq.charAt(end)) < 0) { + break; + } + end += 1; + } + pos.setIndex(end+1); + return Double.parseDouble(csq.subSequence(start,end).toString()); + } + + private String readIdentifier(CharSequence csq, ParsePosition pos) { + final int length = csq.length(); + int start = pos.getIndex(); + int i = start; + while ((++i < length) && isUnitIdentifierPart(csq.charAt(i))) { } + pos.setIndex(i); + return csq.subSequence(start, i).toString(); + } + + //////////////////////////// + // Formatting. + + @Override + public Appendable format(Unit unit, Appendable appendable) + throws IOException { + String name = nameFor(unit); + if (name != null) + return appendable.append(name); + if (!(unit instanceof ProductUnit)) + throw new IllegalArgumentException("Cannot format given Object as a Unit"); + + // Product unit. + ProductUnit productUnit = (ProductUnit) unit; + int invNbr = 0; + + // Write positive exponents first. + boolean start = true; + for (int i = 0; i < productUnit.getUnitCount(); i++) { + int pow = productUnit.getUnitPow(i); + if (pow >= 0) { + if (!start) { + appendable.append('·'); // Separator. + } + name = nameFor(productUnit.getUnit(i)); + int root = productUnit.getUnitRoot(i); + append(appendable, name, pow, root); + start = false; + } else { + invNbr++; + } + } + + // Write negative exponents. + if (invNbr != 0) { + if (start) { + appendable.append('1'); // e.g. 1/s + } + appendable.append('/'); + if (invNbr > 1) { + appendable.append('('); + } + start = true; + for (int i = 0; i < productUnit.getUnitCount(); i++) { + int pow = productUnit.getUnitPow(i); + if (pow < 0) { + name = nameFor(productUnit.getUnit(i)); + int root = productUnit.getUnitRoot(i); + if (!start) { + appendable.append('·'); // Separator. + } + append(appendable, name, -pow, root); + start = false; + } + } + if (invNbr > 1) { + appendable.append(')'); + } + } + return appendable; + } + + private void append(Appendable appendable, CharSequence symbol, + int pow, int root) throws IOException { + appendable.append(symbol); + if ((pow != 1) || (root != 1)) { + // Write exponent. + if ((pow == 2) && (root == 1)) { + appendable.append('²'); // Square + } else if ((pow == 3) && (root == 1)) { + appendable.append('³'); // Cubic + } else { + // Use general exponent form. + appendable.append('^'); + appendable.append(String.valueOf(pow)); + if (root != 1) { + appendable.append(':'); + appendable.append(String.valueOf(root)); + } + } + } + } + + private static final long serialVersionUID = 1L; + } + + /** + * This class represents the ASCIIFormat format. + */ + protected static class ASCIIFormat extends DefaultFormat { + + @Override + public String nameFor(Unit unit) { + // First search if specific ASCII name should be used. + String name = _unitToName.get(unit); + if (name != null) + return name; + // Else returns default name. + return DEFAULT.nameFor(unit); + } + + @Override + public Unit unitFor(String name) { + // First search if specific ASCII name. + Unit unit = _nameToUnit.get(name); + if (unit != null) + return unit; + // Else returns default mapping. + return DEFAULT.unitFor(name); + } + + @Override + public Appendable format(Unit unit, Appendable appendable) + throws IOException { + String name = nameFor(unit); + if (name != null) + return appendable.append(name); + if (!(unit instanceof ProductUnit)) + throw new IllegalArgumentException( + "Cannot format given Object as a Unit"); + + ProductUnit productUnit = (ProductUnit) unit; + for (int i = 0; i < productUnit.getUnitCount(); i++) { + if (i != 0) { + appendable.append('*'); // Separator. + } + name = nameFor(productUnit.getUnit(i)); + int pow = productUnit.getUnitPow(i); + int root = productUnit.getUnitRoot(i); + appendable.append(name); + if ((pow != 1) || (root != 1)) { + // Use general exponent form. + appendable.append('^'); + appendable.append(String.valueOf(pow)); + if (root != 1) { + appendable.append(':'); + appendable.append(String.valueOf(root)); + } + } + } + return appendable; + } + + private static final long serialVersionUID = 1L; + } + + + //////////////////////////////////////////////////////////////////////////// + // Initializes the standard unit database for SI units. + + private static final Unit[] SI_UNITS = { SI.AMPERE, SI.BECQUEREL, + SI.CANDELA, SI.COULOMB, SI.FARAD, SI.GRAY, SI.HENRY, SI.HERTZ, + SI.JOULE, SI.KATAL, SI.KELVIN, SI.LUMEN, SI.LUX, SI.METRE, SI.MOLE, + SI.NEWTON, SI.OHM, SI.PASCAL, SI.RADIAN, SI.SECOND, SI.SIEMENS, + SI.SIEVERT, SI.STERADIAN, SI.TESLA, SI.VOLT, SI.WATT, SI.WEBER }; + + private static final String[] PREFIXES = { "Y", "Z", "E", "P", "T", "G", + "M", "k", "h", "da", "d", "c", "m", "µ", "n", "p", "f", "a", "z", + "y" }; + + private static final UnitConverter[] CONVERTERS = { E24, E21, E18, E15, E12, + E9, E6, E3, E2, E1, Em1, Em2, Em3, Em6, Em9, Em12, + Em15, Em18, Em21, Em24 }; + + private static String asciiPrefix(String prefix) { + return prefix == "µ" ? "micro" : prefix; + } + + static { + for (int i = 0; i < SI_UNITS.length; i++) { + for (int j = 0; j < PREFIXES.length; j++) { + Unit si = SI_UNITS[i]; + Unit u = si.transform(CONVERTERS[j]); + String symbol = (si instanceof BaseUnit) ? ((BaseUnit) si) + .getSymbol() : ((AlternateUnit) si).getSymbol(); + DEFAULT.label(u, PREFIXES[j] + symbol); + if (PREFIXES[j] == "µ") { + ASCII.label(u, "micro" + symbol); + } + } + } + // Special case for KILOGRAM. + DEFAULT.label(SI.GRAM, "g"); + for (int i = 0; i < PREFIXES.length; i++) { + if (CONVERTERS[i] == E3) continue; // kg is already defined. + DEFAULT.label(SI.KILOGRAM.transform(CONVERTERS[i].concatenate(Em3)), + PREFIXES[i] + "g"); + if (PREFIXES[i] == "µ") { + ASCII.label(SI.KILOGRAM.transform(CONVERTERS[i].concatenate(Em3)), "microg"); + } + } + + // Alias and ASCIIFormat for Ohm + DEFAULT.alias(SI.OHM, "Ohm"); + ASCII.label(SI.OHM, "Ohm"); + for (int i = 0; i < PREFIXES.length; i++) { + DEFAULT.alias(SI.OHM.transform(CONVERTERS[i]), PREFIXES[i] + "Ohm"); + ASCII.label(SI.OHM.transform(CONVERTERS[i]), asciiPrefix(PREFIXES[i]) + "Ohm"); + } + + // Special case for DEGREE_CElSIUS. + DEFAULT.label(SI.CELSIUS, "℃"); + DEFAULT.alias(SI.CELSIUS, "°C"); + ASCII.label(SI.CELSIUS, "Celsius"); + for (int i = 0; i < PREFIXES.length; i++) { + DEFAULT.label(SI.CELSIUS.transform(CONVERTERS[i]), PREFIXES[i] + "℃"); + DEFAULT.alias(SI.CELSIUS.transform(CONVERTERS[i]), PREFIXES[i] + "°C"); + ASCII.label(SI.CELSIUS.transform(CONVERTERS[i]), asciiPrefix(PREFIXES[i]) + "Celsius"); + } + } + + //////////////////////////////////////////////////////////////////////////// + // To be moved in resource bundle in future release (locale dependent). + static { + DEFAULT.label(NonSI.PERCENT, "%"); + DEFAULT.label(NonSI.DECIBEL, "dB"); + DEFAULT.label(NonSI.G, "grav"); + DEFAULT.label(NonSI.ATOM, "atom"); + DEFAULT.label(NonSI.REVOLUTION, "rev"); + DEFAULT.label(NonSI.DEGREE_ANGLE, "°"); + ASCII.label(NonSI.DEGREE_ANGLE, "degree_angle"); + DEFAULT.label(NonSI.MINUTE_ANGLE, "'"); + DEFAULT.label(NonSI.SECOND_ANGLE, "\""); + DEFAULT.label(NonSI.CENTIRADIAN, "centiradian"); + DEFAULT.label(NonSI.GRADE, "grade"); + DEFAULT.label(NonSI.ARE, "a"); + DEFAULT.label(NonSI.HECTARE, "ha"); + DEFAULT.label(NonSI.BYTE, "byte"); + DEFAULT.label(NonSI.MINUTE, "min"); + DEFAULT.label(NonSI.HOUR, "h"); + DEFAULT.label(NonSI.DAY, "day"); + DEFAULT.label(NonSI.WEEK, "week"); + DEFAULT.label(NonSI.YEAR, "year"); + DEFAULT.label(NonSI.MONTH, "month"); + DEFAULT.label(NonSI.DAY_SIDEREAL, "day_sidereal"); + DEFAULT.label(NonSI.YEAR_SIDEREAL, "year_sidereal"); + DEFAULT.label(NonSI.YEAR_CALENDAR, "year_calendar"); + DEFAULT.label(NonSI.E, "e"); + DEFAULT.label(NonSI.FARADAY, "Fd"); + DEFAULT.label(NonSI.FRANKLIN, "Fr"); + DEFAULT.label(NonSI.GILBERT, "Gi"); + DEFAULT.label(NonSI.ERG, "erg"); + DEFAULT.label(NonSI.ELECTRON_VOLT, "eV"); + DEFAULT.label(SI.KILO(NonSI.ELECTRON_VOLT), "keV"); + DEFAULT.label(SI.MEGA(NonSI.ELECTRON_VOLT), "MeV"); + DEFAULT.label(SI.GIGA(NonSI.ELECTRON_VOLT), "GeV"); + DEFAULT.label(NonSI.LAMBERT, "La"); + DEFAULT.label(NonSI.FOOT, "ft"); + DEFAULT.label(NonSI.FOOT_SURVEY_US, "foot_survey_us"); + DEFAULT.label(NonSI.YARD, "yd"); + DEFAULT.label(NonSI.INCH, "in"); + DEFAULT.label(NonSI.MILE, "mi"); + DEFAULT.label(NonSI.NAUTICAL_MILE, "nmi"); + DEFAULT.label(NonSI.MILES_PER_HOUR, "mph"); + DEFAULT.label(NonSI.ANGSTROM, "Å"); + ASCII.label(NonSI.ANGSTROM, "Angstrom"); + DEFAULT.label(NonSI.ASTRONOMICAL_UNIT, "ua"); + DEFAULT.label(NonSI.LIGHT_YEAR, "ly"); + DEFAULT.label(NonSI.PARSEC, "pc"); + DEFAULT.label(NonSI.POINT, "pt"); + DEFAULT.label(NonSI.PIXEL, "pixel"); + DEFAULT.label(NonSI.MAXWELL, "Mx"); + DEFAULT.label(NonSI.GAUSS, "G"); + DEFAULT.label(NonSI.ATOMIC_MASS, "u"); + DEFAULT.label(NonSI.ELECTRON_MASS, "me"); + DEFAULT.label(NonSI.POUND, "lb"); + DEFAULT.label(NonSI.OUNCE, "oz"); + DEFAULT.label(NonSI.TON_US, "ton_us"); + DEFAULT.label(NonSI.TON_UK, "ton_uk"); + DEFAULT.label(NonSI.METRIC_TON, "t"); + DEFAULT.label(NonSI.DYNE, "dyn"); + DEFAULT.label(NonSI.KILOGRAM_FORCE, "kgf"); + DEFAULT.label(NonSI.POUND_FORCE, "lbf"); + DEFAULT.label(NonSI.HORSEPOWER, "hp"); + DEFAULT.label(NonSI.ATMOSPHERE, "atm"); + DEFAULT.label(NonSI.BAR, "bar"); + DEFAULT.label(NonSI.MILLIMETER_OF_MERCURY, "mmHg"); + DEFAULT.label(NonSI.INCH_OF_MERCURY, "inHg"); + DEFAULT.label(NonSI.RAD, "rd"); + DEFAULT.label(NonSI.REM, "rem"); + DEFAULT.label(NonSI.CURIE, "Ci"); + DEFAULT.label(NonSI.RUTHERFORD, "Rd"); + DEFAULT.label(NonSI.SPHERE, "sphere"); + DEFAULT.label(NonSI.RANKINE, "°R"); + ASCII.label(NonSI.RANKINE, "degree_rankine"); + DEFAULT.label(NonSI.FAHRENHEIT, "°F"); + ASCII.label(NonSI.FAHRENHEIT, "degree_fahrenheit"); + DEFAULT.label(NonSI.KNOT, "kn"); + DEFAULT.label(NonSI.MACH, "Mach"); + DEFAULT.label(NonSI.C, "c"); + DEFAULT.label(NonSI.LITRE, "L"); + DEFAULT.label(SI.MICRO(NonSI.LITRE), "µL"); + ASCII.label(SI.MICRO(NonSI.LITRE), "microL"); + DEFAULT.label(SI.MILLI(NonSI.LITRE), "mL"); + DEFAULT.label(SI.CENTI(NonSI.LITRE), "cL"); + DEFAULT.label(SI.DECI(NonSI.LITRE), "dL"); + DEFAULT.label(NonSI.GALLON_LIQUID_US, "gal"); + DEFAULT.label(NonSI.OUNCE_LIQUID_US, "oz"); + DEFAULT.label(NonSI.GALLON_DRY_US, "gallon_dry_us"); + DEFAULT.label(NonSI.GALLON_UK, "gallon_uk"); + DEFAULT.label(NonSI.OUNCE_LIQUID_UK, "oz_uk"); + DEFAULT.label(NonSI.ROENTGEN, "Roentgen"); + if (Locale.getDefault().getCountry().equals("GB")) { + DEFAULT.label(NonSI.GALLON_UK, "gal"); + DEFAULT.label(NonSI.OUNCE_LIQUID_UK, "oz"); + } + } +} \ No newline at end of file diff --git a/measure/src/main/java/javax/measure/unit/doc-files/momey.png b/measure/src/main/java/javax/measure/unit/doc-files/momey.png new file mode 100644 index 00000000..e9209f8b Binary files /dev/null and b/measure/src/main/java/javax/measure/unit/doc-files/momey.png differ diff --git a/measure/src/main/java/javax/measure/unit/doc-files/unit.png b/measure/src/main/java/javax/measure/unit/doc-files/unit.png new file mode 100644 index 00000000..072dd8ee Binary files /dev/null and b/measure/src/main/java/javax/measure/unit/doc-files/unit.png differ diff --git a/measure/src/main/java/javax/measure/unit/package.html b/measure/src/main/java/javax/measure/unit/package.html new file mode 100644 index 00000000..e1800aed --- /dev/null +++ b/measure/src/main/java/javax/measure/unit/package.html @@ -0,0 +1,61 @@ + +

Provides support for programatic unit handling.

+

Standart/NonStandard Units

+ Standard units and prefixes are provided by the + {@link javax.measure.unit.SI SI} class (Système International d'Unités) and + about 50 non-standard units are available through the + {@link javax.measure.unit.NonSI NonSI} class. + +

Usage examples:

+[code] +import javax.measure.Scalar; +import javax.measure.Measure; +import javax.measure.unit.*; +import javax.measure.quantity.*; +import static javax.measure.unit.SI.*; +import static javax.measure.unit.NonSI.*; +import static javax.measure.unit.Dimension.*; +public class Main { + public void main(String[] args) { + + // Conversion between units. + System.out.println(KILO(METRE).getConverterTo(MILE).convert(10)); + + // Retrieval of the system unit (identifies the measurement type). + System.out.println(REVOLUTION.divide(MINUTE).getSystemUnit()); + + // Dimension checking (allows/disallows conversions) + System.out.println(ELECTRON_VOLT.isCompatible(WATT.times(HOUR))); + + // Retrieval of the unit dimension (depends upon the current model). + System.out.println(ELECTRON_VOLT.getDimension()); + } +} + +> 6.2137119223733395 +> rad/s +> true +> [L]²·[M]/[T]² +[/code] + +

Unit Parameterization

+ + Units are parameterized (<Q extends {@link javax.measure.quantity.Quantity Quantity}>) to + enforce compile-time checks of units/measures consistency, for example:[code] + + Unit MINUTE = SECONDS.times(60); // Ok. + Unit MINUTE = METRE.times(60); // Compile error. + + Unit HECTOPASCAL = HECTO(PASCAL); // Ok. + Unit HECTOPASCAL = HECTO(NEWTON); // Compile error. + + Measurable duration = Measure.valueOf(2, MINUTE); // Ok. + Measurable duration = Measure.valueOf(2, CELSIUS); // Compile error. + + long milliseconds = duration.longValue(MILLI(SECOND)); // Ok. + long milliseconds = duration.longValue(POUND); // Compile error. + [/code]

+ +

UML Diagram

+ UML Diagram + \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index f8aaa77f..d3ee4fd1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,2 @@ include ':app', ':jscl', ':translations', ':dragbutton' +include ':measure'