001/*
002 *  Unit-API - Units of Measurement API for Java
003 *  Copyright (c) 2005-2016, Jean-Marie Dautelle, Werner Keil, V2COM.
004 *
005 * All rights reserved.
006 *
007 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
008 *
009 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
010 *
011 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
012 *
013 * 3. Neither the name of JSR-363 nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
014 *
015 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
016 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
017 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
018 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
019 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
020 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
021 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
022 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
023 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
024 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
025 */
026package systems.uom.common;
027
028import static tec.units.ri.unit.MetricPrefix.MICRO;
029import static tec.units.ri.unit.Units.*;
030import static systems.uom.common.NonSI.AVOIRDUPOIS_POUND_DIVIDEND;
031import static systems.uom.common.NonSI.AVOIRDUPOIS_POUND_DIVISOR;
032
033import javax.measure.Unit;
034import javax.measure.quantity.Area;
035import javax.measure.quantity.Length;
036import javax.measure.quantity.Mass;
037import javax.measure.quantity.Temperature;
038import javax.measure.quantity.Time;
039import javax.measure.quantity.Volume;
040import javax.measure.spi.SystemOfUnits;
041
042import tec.units.ri.AbstractSystemOfUnits;
043import tec.units.ri.AbstractUnit;
044import tec.units.ri.format.SimpleUnitFormat;
045import tec.units.ri.unit.ProductUnit;
046
047/**
048 * <p>
049 * This class contains units from the Imperial system.
050 * </p>
051 * <p>
052 * 
053 * @noextend This class is not intended to be extended by clients.
054 * 
055 * @author <a href="mailto:units@catmedia.us">Werner Keil</a>
056 * @version 0.7.2, $Date: 2016-09-17 $
057 * @see <a
058 *      href="http://en.wikipedia.org/wiki/Imperial_unit">Wikipedia:
059 *      Imperial Units</a>
060 */
061public final class Imperial extends AbstractSystemOfUnits {
062    private static final String SYSTEM_NAME = "Imperial";
063
064    /**
065     * Default constructor (prevents this class from being instantiated).
066     */
067    private Imperial() {
068    }
069
070    /**
071     * Returns the unique instance of this class.
072     * 
073     * @return the Imperial instance.
074     */
075    public static SystemOfUnits getInstance() {
076        return INSTANCE;
077    }
078
079    private static final Imperial INSTANCE = new Imperial();
080
081    // //////////
082    // Length //
083    // //////////
084
085    /**
086     * A unit of length equal to <code>0.0254 m</code> (standard name
087     * <code>in</code>).
088     */
089    public static final Unit<Length> INCH = addUnit(USCustomary.INCH, "Inch",
090            "in", true);
091
092    // ////////
093    // Mass //
094    // ////////
095
096    /**
097     * A unit of mass equal to <code>453.59237 grams</code> (avoirdupois pound,
098     * standard name <code>lb</code>).
099     */
100    static final Unit<Mass> POUND = addUnit(
101            KILOGRAM.multiply(AVOIRDUPOIS_POUND_DIVIDEND).divide(
102                    AVOIRDUPOIS_POUND_DIVISOR), "Pound", "lb", true);
103    // LABEL);
104    /**
105     * An English and imperial unit of weight or mass now equal to 14
106     * avoirdupois pounds or 6.35029318 kg (<code>st</code>).
107     */
108    public static final Unit<Mass> STONE = addUnit(
109            KILOGRAM.multiply(6.35029318), "st", true);
110
111    /**
112     * A unit of mass equal to <code>1 / 16 {@link #POUND}</code> (standard name
113     * <code>oz</code>).
114     */
115    public static final Unit<Mass> OUNCE = addUnit(POUND.divide(16));
116
117    /**
118     * A unit of mass equal to <code>2240 {@link #POUND}</code> (long ton,
119     * standard name <code>ton_uk</code>).
120     */
121    public static final Unit<Mass> TON_UK = addUnit(POUND.multiply(2240));
122
123    /**
124     * A unit of mass equal to <code>1000 kg</code> (metric ton, standard name
125     * <code>t</code>).
126     */
127    public static final Unit<Mass> METRIC_TON = addUnit(KILOGRAM.multiply(1000));
128
129    // ///////////////
130    // Temperature //
131    // ///////////////
132
133    /**
134     * A unit of temperature equal to <code>5/9 °K</code> (standard name
135     * <code>°R</code>).
136     */
137    static final Unit<Temperature> RANKINE = addUnit(
138            KELVIN.multiply(5).divide(9), "°R", true);
139
140    /**
141     * A unit of temperature equal to degree Rankine minus
142     * <code>459.67 °R</code> (standard name <code>°F</code>).
143     * 
144     * @see #RANKINE
145     */
146    static final Unit<Temperature> FAHRENHEIT = addUnit(RANKINE.shift(459.67),
147            "°F", true);
148
149    // /////////
150    // Angle //
151    // /////////
152
153    // ////////////
154    // TimeUnit //
155    // ////////////
156    /**
157     * A unit of time equal to <code>60 s</code> (standard name <code>min</code>
158     * ).
159     */
160    static final Unit<Time> MINUTE = addUnit(SECOND.multiply(60));
161
162    /**
163     * A unit of duration equal to <code>60 {@link #MINUTE}</code> (standard
164     * name <code>h</code>).
165     */
166    static final Unit<Time> HOUR = addUnit(MINUTE.multiply(60));
167
168    // ////////////
169    // Velocity //
170    // ////////////
171
172    // ////////
173    // Area //
174    // ////////
175
176    /**
177     * A unit of area (standard name <code>sft</code> ).
178     */
179    public static final Unit<Area> SQUARE_FOOT = addUnit(
180            USCustomary.SQUARE_FOOT, "sft", true);
181
182    /**
183     * One acre is 43,560 <code>square feet</code> (standard name <code>a</code>
184     * ).
185     */
186    public static final Unit<Area> ACRE = addUnit(
187            USCustomary.SQUARE_FOOT.multiply(43560), "Acre", "a", true);
188
189    // //////////
190    // Energy //
191    // //////////
192
193    // //////////
194    // Volume //
195    // //////////
196    /**
197     * A unit of volume equal to one cubic decimeter (default label
198     * <code>L</code>, also recognized <code>µL, mL, cL, dL</code>).
199     */
200    public static final Unit<Volume> LITRE = addUnit(CUBIC_METRE.divide(1000),
201            "L", true);
202
203    /**
204     * A unit of volume equal to one cubic inch (<code>in³</code>).
205     */
206    public static final Unit<Volume> CUBIC_INCH = addUnit(
207            new ProductUnit<Volume>(USCustomary.INCH.pow(3)), "Cubic Inch",
208            "in³", true);
209
210    /**
211     * A unit of volume equal to <code>4.546 09 {@link #LITRE}</code> (standard
212     * name <code>gal_uk</code>).
213     */
214    public static final Unit<Volume> GALLON_UK = addUnit(LITRE.multiply(454609)
215            .divide(100000), "gal_uk", true);
216
217    /**
218     * A unit of volume equal to one UK gallon, Liquid Unit.
219     */
220    public static final Unit<Volume> GALLON_LIQUID = addUnit(CUBIC_INCH
221            .multiply(277.42));
222
223    /**
224     * A unit of volume equal to <code>1 / 160 {@link #GALLON_UK}</code>
225     * (standard name <code>oz_fl_uk</code>).
226     */
227    static final Unit<Volume> OUNCE_LIQUID_UK = addUnit(GALLON_UK.divide(160), "oz_fl_uk", true);
228
229    /**
230     * A unit of volume equal to <code>1 / 160 {@link #GALLON_LIQUID}</code>
231     * (standard name <code>oz_fl</code>).
232     */
233    public static final Unit<Volume> OUNCE_LIQUID = addUnit(OUNCE_LIQUID_UK, "oz_fl", true);
234
235    /**
236     * A unit of volume equal to <code>5 {@link #OUNCE_LIQUID}</code> (standard
237     * name <code>gi</code>).
238     */
239    public static final Unit<Volume> GILL = addUnit(OUNCE_LIQUID.multiply(5), "gi", true);
240
241    /**
242     * A unit of volume equal to <code>20 {@link #OUNCE_LIQUID}</code> (standard
243     * name <code>pt</code>).
244     */
245    public static final Unit<Volume> PINT = addUnit(OUNCE_LIQUID.multiply(20),
246            "pt", true);
247
248    /**
249     * A unit of volume equal to <code>40 {@link #OUNCE_LIQUID}</code> (standard
250     * name <code>qt</code>).
251     */
252    public static final Unit<Volume> QUART = addUnit(OUNCE_LIQUID.multiply(40));
253
254    /**
255     * A unit of volume <code>~ 1 drop or 0.95 grain of water </code> (standard
256     * name <code>min</code>).
257     */
258    public static final Unit<Volume> MINIM = addUnit(MICRO(LITRE).multiply(
259            59.1938802d));
260
261    /**
262     * A unit of volume equal to <code>20 {@link #MINIM}</code> (standard name
263     * <code>fl scr</code>).
264     */
265    public static final Unit<Volume> FLUID_SCRUPLE = addUnit(
266            MINIM.multiply(60), "fl scr", true);
267
268    /**
269     * A unit of volume equal to <code>3 {@link #FLUID_SCRUPLE}</code> (standard
270     * name <code>fl drc</code>).
271     */
272    public static final Unit<Volume> FLUID_DRACHM = addUnit(
273            FLUID_SCRUPLE.multiply(3), "fl drc", true);
274
275    /**
276     * Adds a new unit not mapped to any specified quantity type.
277     *
278     * @param unit
279     *            the unit being added.
280     * @return <code>unit</code>.
281     */
282    private static <U extends Unit<?>> U addUnit(U unit) {
283        INSTANCE.units.add(unit);
284        return unit;
285    }
286
287    /**
288     * Adds a new unit not mapped to any specified quantity type and puts a text
289     * as symbol or label.
290     *
291     * @param unit
292     *            the unit being added.
293     * @param name
294     *            the string to use as name
295     * @param text
296     *            the string to use as label or symbol
297     * @param isLabel
298     *            if the string should be used as a label or not
299     * @return <code>unit</code>.
300     */
301    private static <U extends Unit<?>> U addUnit(U unit, String name,
302            String text, boolean isLabel) {
303        if (isLabel) {
304            SimpleUnitFormat.getInstance().label(unit, text);
305        }
306        if (name != null && unit instanceof AbstractUnit) {
307            return Helper.addUnit(INSTANCE.units, unit, name);
308        } else {
309            INSTANCE.units.add(unit);
310        }
311        return unit;
312    }
313
314    /**
315     * Adds a new unit not mapped to any specified quantity type and puts a text
316     * as symbol or label.
317     *
318     * @param unit
319     *            the unit being added.
320     * @param text
321     *            the string to use as label or symbol
322     * @param isLabel
323     *            if the string should be used as a label or not
324     * @return <code>unit</code>.
325     */
326    private static <U extends Unit<?>> U addUnit(U unit, String text,
327            boolean isLabel) {
328        return addUnit(unit, null, text, isLabel);
329    }
330
331    // ///////////////////
332    // Collection View //
333    // ///////////////////
334
335    @Override
336    public String getName() {
337        return SYSTEM_NAME;
338    }
339}