package kont2015;
/**
* A class for (scientific) units like meter (m), grams (g) and Kelwin (K).
* Units may be derived from each other by a linear formula, e.g. km from m and C (Celcius) from Kelwin.
* @author hal
*
*/
public class Unit {
/**
* Constructor for base units, e.g. meter, gram, kelwin etc.
* Initialises with the symbol, e.g. "m" for meters, "g" for grams, "K" for kelwin.
* @param symbol The symbol of this Unit, must contain only alphabetic characters.
* @throws IllegalArgumentException if the symbol contains characters that are not alphabetic
*/
public Unit(String symbol) throws IllegalArgumentException {
...
}
/**
* Constructor for derived units, e.g. kilometer, milligram and Celcius, derived from meter, gram and Kelwin respectively.
* A derived unit includes the factor and offset for the linear formula for computing the base unit from the derived one.
* base-unit-value = derived-unit-value * factor + offset
* @param symbol The symbol for the derived Unit
* @param base The base unit, e.g. meter for kilometer, gram for milligram
* @param factor The factor in the formula, e.g. 1000 for km to m or 0.001 for mg to g.
* @param offset The offset in the formula.
* @throws IllegalArgumentException if the symbol contains characters that are not alphabetic
*/
public Unit(String symbol, Unit base, double factor, double offset) throws IllegalArgumentException {
...
}
/**
* Constructor for derived units, e.g. kilometer, milligram and Celcius, derived from meter, gram and Kelwin respectively.
* A derived unit includes the factor and offset for the linear formula for computing the base unit from the derived one.
* base-unit-value = derived-unit-value * factor + offset
* @param symbol The symbol for the derived Unit
* @param base The base unit, e.g. meter for kilometer, gram for milligram
* @param factor The factor in the formula, e.g. 1000 for km to m or 0.001 for mg to g. The offset is set to 0.0.
* @throws IllegalArgumentException if the symbol contains characters that are not alphabetic
*/
public Unit(String symbol, Unit base, double factor) throws IllegalArgumentException {
...
}
@Override
public String toString() {
return symbol;
}
/**
* Finds the first common unit from which both this and the other Unit is derived.
* If other is derived from this, then this is returned, or if this is derived from other, then other is returned.
* Otherwise it finds the first base unit that both are derived from.
* @param other The other unit.
* @return The first common unit that is a common base unit for both this and other.
*/
public Unit findCommonBaseUnit(Unit other) {
...
}
/**
* Converts value from this unit to the other unit.
* @param value The value to convert.
* @param other The other unit, that value is converted to.
* @return value converted from this unit to the other unit
* @throws IllegalArgumentException if there is no common base unit.
*/
public double convert(double value, Unit other) throws IllegalArgumentException {
Unit base = findCommonBaseUnit(other);
if (base == null) {
throw new IllegalArgumentException("Cannot convert from " + this + " to " + other);
}
double baseValue = convertToBase(value, base);
return other.convertFromBase(baseValue, base);
}
/**
* Helper method for converting from this unit to a specific base unit.
* @param value The value to convert.
* @param base The base unit to convert to.
* @return The converted value.
*/
private double convertToBase(double value, Unit base) {
if (this == base) {
return value;
}
if (this.base == null) {
throw new IllegalArgumentException(base + " is not a base for " + this);
}
return this.base.convertToBase(value * factor + offset, base);
}
/**
* Helper method for converting from a specific base unit to this unit.
* @param value The value to convert.
* @param base The base unit to convert from.
* @return The converted value.
*/
private double convertFromBase(double value, Unit base) {
if (this == base) {
return value;
}
if (this.base == null) {
throw new IllegalArgumentException(base + " is not a base for " + this);
}
return this.base.convertFromBase(value, base) / factor - offset / factor;
}
// The currently supported predefined units, that are considered by the valueOf method
private static Unit
m = new Unit("m"),
km = new Unit("km", m, 1000.0),
dm = new Unit("dm", m, 0.1),
cm = new Unit("cm", dm, 0.1),
ALL_UNITS[] = {m, km, dm, cm};
/**
* Finds the Unit for the given symbol among all predefined units.
* Currently supported units are m, km, dm, cm
* @param symbol the symbol to search for, e.g. "m" or "dm"
* @return the Unit with the given symbol, or null, of no such Unit was found
*/
public static Unit valueOf(String symbol) {
...
}
}
package java.util.function;
/**
* Represents a function that accepts two arguments and produces a result.
* This is the two-arity specialization of {@link Function}.
*/
public interface BinaryOperator<T> {
/**
* Applies this function to the given arguments.
*
* @param t the first function argument
* @param u the second function argument
* @return the function result
*/
T apply(T t1, T t2);
}
package kont2015;
import java.util.function.BinaryOperator;
/**
* A class representing a double value in a certain Unit.
* Instances are immutable, i.e. cannot be modified once created.
* @author hal
*
*/
public class Value implements Comparable<Value> {
/**
* Creates a new value with the provided Unit and (double) value.
* @param unit the Unit of the new Value
* @param value the double value of the new Value
*/
public Value(Unit unit, double value) {
...
}
@Override
public String toString() {
return getValue() + unit.toString();
}
/**
* Returns this Value's Unit
* @return this Value's Unit
*/
... get... {
...
}
/**
* Returns this Value's double value
* @return this Value's double value
*/
... get... {
...
}
/**
* Returns a Value instance from the provided String.
* The format is a double (as parsed by Double.valueOf) followed by a Unit symbol (as parsed by Unit.valueOf), e.g. "1.0m" or "2.5km".
* @param s
* @return the String parses as a Value instance
*/
public static Value valueOf(String s) {
...
}
/**
* Computes the sum of this and other (both Value objects).
* The Unit of the returned Value is the common base Unit of this and other's Units.
* Hence, both Value object's double values are properly converted before adding.
* @param other the other Value
* @return a new Value object representing the sum of this and other
*/
public Value add(Value other) {
...
}
/**
* Computes a new value that is the combination of this Value's double value and the provided double.
* The double values are combined using the provided BinaryOperator.
* The Unit of the returned Value is the this Value's Unit.
* @param other the double value to combine with this
* @return a new Value object representing the sum of this and other
*/
public Value compute(BinaryOperator<Double> op, double other) {
...
}
/**
* Computes the product of this Value and other (a double) using the compute method.
* @param other the other factor
* @return the product of this Value's double value and other (also a double)
*/
public Value mult(double other) {
...
}
/**
* Compares this Value with other according the the requirements of Comparable.
* Note that this Value and other may have different Units.
* @throws IllegalArgumentException if this and other don't have a common base Unit.
*/
@Override
public int compareTo(Value other) {
...
}
}
package kont2015;
/**
* Interface implemented by classes wanting to be notified of changes to a Values object.
* @author hal
*
*/
public interface ValuesListener {
public void valuesChanged(Values values);
}
package kont2015;
/**
* An interface representing a sequence of doubles, all with the same Unit.
* Implementing classes may support adding and removing elements. If modifiable,
* the class must support notifying ValuesListeners.
* @author hal
*
*/
public interface Values extends Iterable<Double> {
/**
* @return this Values' Unit
*/
public Unit getUnit();
/**
* @return the number of values in the sequence.
*/
public int size();
/**
* Computes the average of this Values object's double values.
* @return the average as a double (implicitly in this Values' Unit).
*/
public double average();
/**
* Creates a new Values object where each element is the sum of corresponding elements in this and the other Values object.
* @param other the other Values
* @return a new Values object that represents the sum of this and other.
*/
public Values add(Values other);
// ValuesListener support
/**
* Adds a ValuesListener to be notified of changes to this Values object.
* @param listener
*/
...
/**
* Removes a previously added ValuesListener.
* @param listener
*/
...
}
package kont2015;
/**
* A class representing series of doubles, all with the same (unmodifiable) Unit.
* A Values object can only be modified by appending another value.
* @author hal
*
*/
public class ValueSeries implements Values {
/**
* Constructs a new ValueSeries object, with the provided Unit.
* @param unit
*/
public ValueSeries(...) {
...
}
/**
* Appends the provided double to this ValueSeries. The double value is assumed to be in the Unit of this ValueSeries.
* @param value the double to append
*/
public void appendValue(double value) {
...
}
/**
* Appends the provided Value to this ValueSeries, by first converting it to this ValueSeries' unit and then appending it.
* @param value the Value to append, after converting it to this ValueSeries' Unit.
*/
public void appendValue(Value value) {
...
}
// Values methods
...
} |