Weight
From DarkWiki
Java source code
package pa.common;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import java.io.Serializable;
import java.text.DecimalFormat;
/**
* Represents a measurement of weight. When this object is serialised to/from JSON, it is done so using the
* string form.
*/
public class Weight implements Comparable<Weight>, Serializable {
private static final String NUMBER_FORMAT = "0.####";
private double value = 0;
private Units units = Units.G;
/**
* Create a zero-metre weight.
*/
public Weight() {
}
/**
* Create a weight.
*
* @param value The number of units.
* @param units The units to use.
*/
public Weight(double value, Units units) {
setValue(value);
setUnits(units);
}
/**
* Parse the input and create a weight from it. If no units are provided, grammes are assumed. This is the
* method that Jackson will use to create Weight objects from a JSON value.
*
* @param text The textual version of a weight.
* @return A new weight object.
* @throws IllegalArgumentException if the given string cannot be parsed.
*/
@JsonCreator
public static Weight parse(String text) {
return parse(text, Units.G);
}
/**
* Parse the input and create a weight from it. If no units are provided, the default units are assumed.
*
* @param text The textual version of a weight.
* @param defaultUnits The units to use if none is provided.
* @return A new weight object.
* @throws IllegalArgumentException if the given string cannot be parsed.
*/
public static Weight parse(String text, Units defaultUnits) {
Units foundUnits = null;
if (text.endsWith(Units.KG.getSymbol())) foundUnits = Units.KG;
else if (text.endsWith(Units.G.getSymbol())) foundUnits = Units.G;
else if (text.endsWith(Units.LBS.getSymbol())) foundUnits = Units.LBS;
if (foundUnits != null) {
int index = text.lastIndexOf(foundUnits.getSymbol());
String amountString = text.substring(0, index);
try {
return new Weight(Double.parseDouble(amountString), foundUnits);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("No a valid weight: '" + text + "'");
}
} else {
try {
return new Weight(Double.parseDouble(text), defaultUnits);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("No a valid weight: '" + text + "'");
}
}
}
/**
* Convert one weight value into another.
*
* @param in The value to convert.
* @param from The origin units.
* @param to The destination units.
* @return The converted value.
*/
static double convert(double in, Units from, Units to) {
return in * from.getScaleFactor() / to.getScaleFactor();
}
/**
* Get the weight in the current units.
*
* @return The weight in the current units.
*/
public double getValue() {
return value;
}
/**
* Set the weight in the current units.
*
* @param value The weight in the current units.
*/
public void setValue(double value) {
this.value = value;
}
/**
* Get the units used by this weight.
*
* @return The units used by this weight.
*/
public Units getUnits() {
return units;
}
/**
* Set the units used by this weight (without affecting the value).
*
* @param units The units used by this weight.
*/
public void setUnits(Units units) {
this.units = units;
}
/**
* Convert this weight into one with different units.
*
* @param newUnits The desired units.
* @return The new weight, in the desired units.
*/
public Weight convertTo(Units newUnits) {
return new Weight(convert(this.value, this.units, newUnits), newUnits);
}
/**
* Add a weight to this one.
*
* @param weight The weight to add.
* @return A new weight, representing the sum of the weights, in the units of the original.
*/
public Weight add(Weight weight) {
return new Weight(this.getInternalValue() + weight.getInternalValue(), Units.G)
.convertTo(this.units);
}
/**
* Format this weight as a string. A space will be inserted between the value and the unit symbol. This method
* is called when serializing this object to a JSON value.
*
* @return The textual version of this weight.
*/
@JsonValue
public String toString() {
return new DecimalFormat(NUMBER_FORMAT).format(getValue()) + " " + getUnits().getSymbol();
}
/**
* Get the value (in grammes) used to compare.
*
* @return The number of grammes this weight represents.
*/
double getInternalValue() {
if (units == Units.G) {
return value;
} else {
return convert(value, units, Units.G);
}
}
/**
* Compare two weight.
*
* @param o The weight to compare.
* @return Zero if they're the same, -1 if this value is smaller than the argument, +1 if larger.
*/
@Override
public int compareTo(Weight o) {
if (o == null) {
return 1;
} else {
double lhs = getInternalValue();
double rhs = o.getInternalValue();
if (lhs < rhs) {
return -1;
} else if (lhs > rhs) {
return 1;
} else {
return 0;
}
}
}
/**
* Compare two weights for equality.
*
* @param obj The object to check.
* @return True if they're the same, false otherwise.
*/
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
} else if (obj instanceof Weight) {
return this.getInternalValue() == ((Weight) obj).getInternalValue();
} else {
return false;
}
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int result = 17;
result ^= 31 * Double.hashCode(value);
result ^= 31 * units.hashCode();
return result;
}
/**
* The units of weight. By default, grammes are assumed.
*/
public enum Units {
/**
* Grammes
*/
G("g", 1),
/**
* Kilogrammes
*/
KG("kg", 1000),
/**
* Ounces
*/
OZ("oz", 28.3495),
/**
* Pounds
*/
LBS("lbs", 453.592);
private double scaleFactor;
private String symbol;
Units(String symbol, double scaleFactor) {
this.symbol = symbol;
this.scaleFactor = scaleFactor;
}
/**
* Get the number of metres represented by this unit.
*
* @return The number of metres represented by this unit.
*/
public double getScaleFactor() {
return scaleFactor;
}
/**
* Get the standard symbol for this unit.
*
* @return The standard symbol for this unit.
*/
public String getSymbol() {
return symbol;
}
}
}