Difference between revisions of "Weight"

From DarkWiki
Jump to: navigation, search
(Created page with "==Java source code== <source lang="java"> package pa.common; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import ...")
 
(Java source code)
 
Line 2: Line 2:
  
 
<source lang="java">
 
<source lang="java">
package pa.common;
 
  
 
import com.fasterxml.jackson.annotation.JsonCreator;
 
import com.fasterxml.jackson.annotation.JsonCreator;

Latest revision as of 09:16, 16 June 2017

Java source code

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

}