001/*
002 *  Units of Measurement Systems 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 tec.units.ri.AbstractSystemOfUnits;
031import tec.units.ri.AbstractUnit;
032import tec.units.ri.format.SimpleUnitFormat;
033import tec.units.ri.function.RationalConverter;
034import tec.units.ri.unit.ProductUnit;
035import tec.units.ri.unit.TransformedUnit;
036
037import javax.measure.Unit;
038import javax.measure.quantity.Angle;
039import javax.measure.quantity.Area;
040
041import javax.measure.quantity.Energy;
042import javax.measure.quantity.Length;
043import javax.measure.quantity.Mass;
044import javax.measure.quantity.Power;
045import javax.measure.quantity.Temperature;
046import javax.measure.quantity.Time;
047import javax.measure.quantity.Speed;
048import javax.measure.quantity.Volume;
049import javax.measure.spi.SystemOfUnits;
050
051/**
052 * <p>
053 * This class contains units from the United States customary system.
054 * </p>
055 * <p>
056 * 
057 * @noextend This class is not intended to be extended by clients.
058 * 
059 * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
060 * @author <a href="mailto:units@catmedia.us">Werner Keil</a>
061 * @version 1.27, October 20, 2016
062 * @see <a href="http://en.wikipedia.org/wiki/United_States_customary_units">
063 *      Wikipedia: United State Customary Units</a>
064 * @see <a href="https://en.wikipedia.org/wiki/Imperial_and_US_customary_measurement_systems">
065 *      Wikipedia: United State Customary Units</a>
066 * @since 0.3
067 */
068public final class USCustomary extends AbstractSystemOfUnits {
069        private static final String SYSTEM_NAME = "United States Customary Units";
070
071        /**
072         * Default constructor (prevents this class from being instantiated).
073         */
074        private USCustomary() {
075        }
076
077        /**
078         * Returns the unique instance of this class.
079         * 
080         * @return the USCustomary instance.
081         */
082        public static SystemOfUnits getInstance() {
083                return INSTANCE;
084        }
085
086        private static final USCustomary INSTANCE = new USCustomary();
087
088        ////////////
089        // Length //
090        ////////////
091        /**
092         * US name for {@link SI#METRE}.
093         */
094        public static final Unit<Length> METER = addUnit(METRE);
095
096        /**
097         * A unit of length equal to <code>0.3048 m</code> (standard name
098         * <code>ft</code>).
099         */
100        public static final Unit<Length> FOOT = addUnit(METER.multiply(3048).divide(10000), "Foot", "ft");
101
102        /**
103         * A unit of length equal to <code>1200/3937 m</code> (standard name
104         * <code>foot_survey_us</code>). See also:
105         * <a href="http://www.sizes.com/units/foot.htm">foot</a>
106         */
107        public static final Unit<Length> FOOT_SURVEY = addUnit(METER.multiply(1200).divide(3937), "US Survey foot",
108                        "ft_survey_us");
109
110        /**
111         * A unit of length equal to <code>0.9144 m</code> (standard name
112         * <code>yd</code>).
113         */
114        public static final Unit<Length> YARD = addUnit(FOOT.multiply(3), "Yard", "yd");
115
116        /**
117         * A unit of length equal to <code>0.0254 m</code> (standard name
118         * <code>in</code>).
119         */
120        public static final Unit<Length> INCH = addUnit(FOOT.divide(12), "in");
121
122        /**
123         * A unit of length equal to <code>1609.344 m</code> (standard name
124         * <code>mi</code>).
125         */
126        public static final Unit<Length> MILE = addUnit(METER.multiply(1609344).divide(1000), "Mile", "mi");
127
128        /**
129         * A unit of length equal to the distance that light travels in one year
130         * through a vacuum (standard name <code>ly</code>).
131         */
132        public static final Unit<Length> LIGHT_YEAR = addUnit(METRE.multiply(9.460528405e15), "Light year", "ly");
133
134        /**
135         * A unit of length equal to <code>1852.0 m</code> (standard name
136         * <code>nmi</code>).
137         */
138        public static final Unit<Length> NAUTICAL_MILE = addUnit(METER.multiply(1852), "Nautical mile", "nmi");
139
140        //////////
141        // Mass //
142        //////////
143
144        /**
145         * A unit of mass equal to <code>453.59237 grams</code> (avoirdupois pound,
146         * standard name <code>lb</code>).
147         */
148        public static final Unit<Mass> POUND = addUnit(KILOGRAM.multiply(45359237).divide(100000000), "Pound", "lb"); // ,
149        // Messages.US_lb_name);
150
151        /**
152         * A unit of mass equal to <code>1 / 16 {@link #POUND}</code> (standard name
153         * <code>oz</code>).
154         */
155        public static final Unit<Mass> OUNCE = addUnit(POUND.divide(16), "oz");
156
157        /**
158         * A unit of mass equal to <code>2000 {@link #POUND}</code> (short ton,
159         * standard name <code>ton</code>).
160         */
161        public static final Unit<Mass> TON = addUnit(POUND.multiply(2000), "ton_us");
162
163        /////////////////
164        // Temperature //
165        /////////////////
166
167        /**
168         * A unit of temperature equal to <code>5/9 °K</code> (standard name
169         * <code>°R</code>).
170         */
171        public static final Unit<Temperature> RANKINE = addUnit(KELVIN.multiply(5).divide(9));
172
173        /**
174         * A unit of temperature equal to degree Rankine minus
175         * <code>459.67 °R</code> (standard name <code>°F</code>).
176         * 
177         * @see #RANKINE
178         */
179        public static final Unit<Temperature> FAHRENHEIT = addUnit(RANKINE.shift(459.67), "°F");
180
181        ///////////
182        // Angle //
183        ///////////
184
185        /**
186         * A unit of angle equal to a full circle or <code>2<i>&pi;</i>
187         * {@link SI#RADIAN}</code> (standard name <code>rev</code>).
188         */
189        public static final Unit<Angle> REVOLUTION = addUnit(RADIAN.multiply(2).multiply(Math.PI).asType(Angle.class),
190                        "rev");
191
192        /**
193         * A unit of angle equal to <code>1/360 {@link #REVOLUTION}</code> (standard
194         * name <code>deg</code>).
195         */
196        public static final Unit<Angle> DEGREE_ANGLE = addUnit(REVOLUTION.divide(360));
197
198        /**
199         * A unit of angle equal to <code>1/60 {@link #DEGREE_ANGLE}</code>
200         * (standard name <code>'</code>).
201         */
202        public static final Unit<Angle> MINUTE_ANGLE = addUnit(DEGREE_ANGLE.divide(60));
203
204        /**
205         * A unit of angle equal to <code>1/60 {@link #MINUTE_ANGLE}</code>
206         * (standard name <code>"</code>).
207         */
208        public static final Unit<Angle> SECOND_ANGLE = addUnit(MINUTE_ANGLE.divide(60));
209
210        /**
211         * A unit of angle equal to <code>0.01 {@link SI#RADIAN}</code> (standard
212         * name <code>centiradian</code>).
213         */
214        public static final Unit<Angle> CENTIRADIAN = addUnit(RADIAN.divide(100));
215
216        /**
217         * A unit of angle measure equal to <code>1/400 {@link #REVOLUTION}</code>
218         * (standard name <code>grade</code> ).
219         */
220        public static final Unit<Angle> GRADE = addUnit(REVOLUTION.divide(400));
221
222        // ////////////
223        // Time //
224        // ////////////
225        /**
226         * A unit of time equal to <code>60 s</code> (standard name <code>min</code>
227         * ).
228         */
229        public static final Unit<Time> MINUTE = addUnit(SECOND.multiply(60));
230
231        /**
232         * A unit of duration equal to <code>60 {@link #MINUTE}</code> (standard
233         * name <code>h</code>).
234         */
235        public static final Unit<Time> HOUR = addUnit(MINUTE.multiply(60));
236
237        // ////////////
238        // Speed //
239        // ////////////
240        /**
241         * A unit of velocity expressing the number of {@link #FOOT feet} per
242         * {@link SI#SECOND second}.
243         * 
244         * @since 0.5.1
245         */
246        public static final Unit<Speed> FOOT_PER_SECOND = addUnit(FOOT.divide(SECOND)).asType(Speed.class);
247
248        /**
249         * Alias for {@link FOOT_PER_SECOND}
250         * 
251         * @deprecated use FOOT_PER_SECOND.
252         */
253        public static final Unit<Speed> FEET_PER_SECOND = FOOT_PER_SECOND;
254
255        /**
256         * A unit of velocity expressing the number of international {@link #MILE
257         * miles} per {@link #HOUR hour} (abbreviation <code>mph</code>).
258         */
259        public static final Unit<Speed> MILE_PER_HOUR = addUnit(MILE.divide(HOUR).asType(Speed.class), "Mile per hour",
260                        "mph");
261
262        /**
263         * Alias for {@link MILE_PER_HOUR}
264         * 
265         * @deprecated use MILE_PER_HOUR.
266         */
267        public static final Unit<Speed> MILES_PER_HOUR = MILE_PER_HOUR;
268
269        /**
270         * A unit of velocity expressing the number of {@link #NAUTICAL_MILE
271         * nautical miles} per {@link #HOUR hour} (abbreviation <code>kn</code>).
272         */
273        public static final Unit<Speed> KNOT = addUnit(NAUTICAL_MILE.divide(HOUR).asType(Speed.class), "Knot", "kn");
274
275        //////////
276        // Area //
277        //////////
278
279        /**
280         * A unit of area (standard name <code>sft</code> ).
281         */
282        public static final Unit<Area> SQUARE_FOOT = addUnit(new ProductUnit<Area>((AbstractUnit<?>) FOOT.multiply(FOOT)), "sft");
283
284        /**
285         * A unit of area equal to <code>100 m²</code> (standard name <code>a</code>
286         * ).
287         */
288        public static final Unit<Area> ARE = addUnit(SQUARE_METRE.multiply(100), "Are", "a");
289
290        /**
291         * A unit of area equal to <code>100 {@link #ARE}</code> (standard name
292         * <code>ha</code>).
293         */
294        public static final Unit<Area> HECTARE = addUnit(ARE.multiply(100), "Hectare", "ha"); // Exact.
295
296        /**
297         * The acre is a unit of area used in the imperial and U.S. customary
298         * systems. It is equivalent to <code>43,560 square feet</code>. An acre is
299         * about 40% of a <code>HECTARE</code> – slightly smaller than an American
300         * football field. (standard name <code>ac</code> ).
301         * 
302         * @see <a href="http://en.wikipedia.org/wiki/Acre">Wikipedia: Acre</a>
303         */
304        public static final Unit<Area> ACRE = addUnit(SQUARE_FOOT.multiply(43560), "Acre", "ac");
305
306        ////////////
307        // Energy //
308        ////////////
309
310        /**
311         * A unit of energy equal to one electron-volt (standard name
312         * <code>eV</code>, also recognized <code>keV, MeV, GeV</code>).
313         */
314        public static final Unit<Energy> ELECTRON_VOLT = addUnit(JOULE.multiply(1.602176462e-19), "Electron Volt", "eV");
315
316        ////////////
317        // Power //
318        ////////////
319
320        /**
321         * Horsepower (HP) is the name of several units of measurement of power. The
322         * most common definitions equal between 735.5 and 750 watts. Horsepower was
323         * originally defined to compare the output of steam engines with the power
324         * of draft horses. The unit was widely adopted to measure the output of
325         * piston engines, turbines, electric motors, and other machinery. The
326         * definition of the unit varied between geographical regions. Most
327         * countries now use the SI unit watt for measurement of power. With the
328         * implementation of the EU Directive 80/181/EEC on January 1, 2010, the use
329         * of horsepower in the EU is only permitted as supplementary unit.
330         */
331        public static final Unit<Power> HORSEPOWER = addUnit(WATT.multiply(735.499), "Horsepower", "HP");
332
333        // //////////
334        // Volume //
335        // //////////
336        /**
337         * A unit of volume equal to one cubic decimeter (default label
338         * <code>L</code>, also recognized <code>µL, mL, cL, dL</code>).
339         */
340        public static final Unit<Volume> LITER = addUnit(
341                        new TransformedUnit<Volume>(CUBIC_METRE, new RationalConverter(1, 1000)), "Liter", "L");
342
343        /**
344         * A unit of volume equal to one cubic inch (<code>in³</code>).
345         */
346        public static final Unit<Volume> CUBIC_INCH = addUnit(INCH.pow(3).asType(Volume.class), "in³");
347
348        /**
349         * The cubic foot is an imperial and US customary (non-metric) unit of
350         * volume, used in the United States, Canada, and the United Kingdom. It is
351         * defined as the volume of a cube with sides of one foot (0.3048 m) in
352         * length. Its volume is 28.3168 liters or about 1⁄35 of a cubic meter. (
353         * <code>ft³</code>).
354         */
355        public static final Unit<Volume> CUBIC_FOOT = addUnit(CUBIC_INCH.multiply(1728), "ft³");
356
357        /**
358         * An acre-foot is a unit of volume commonly used in the United States in
359         * reference to large-scale water resources, such as reservoirs, aqueducts,
360         * canals, sewer flow capacity, irrigation water, and river flows.
361         */
362        public static final Unit<Volume> ACRE_FOOT = addUnit(CUBIC_FOOT.multiply(43560), "Acre-foot", "ac ft");
363
364        /**
365         * A unit of volume equal to one US dry gallon. (standard name
366         * <code>gallon_dry_us</code>).
367         */
368        public static final Unit<Volume> GALLON_DRY = addUnit(CUBIC_INCH.multiply(2688025).divide(10000), "US dry gallon",
369                        "gal_dry_us");
370
371        /**
372         * A unit of volume equal to one US gallon, Liquid Unit. The U.S. liquid
373         * gallon is based on the Queen Anne or Wine gallon occupying 231 cubic
374         * inches (standard name <code>gal</code>).
375         */
376        public static final Unit<Volume> GALLON_LIQUID = addUnit(CUBIC_INCH.multiply(231), "US gallon", "gal");
377
378        /**
379         * A unit of volume equal to <code>1 / 128 {@link #GALLON_LIQUID}</code>
380         * (standard name <code>oz_fl</code>).
381         */
382        public static final Unit<Volume> FLUID_OUNCE = addUnit(GALLON_LIQUID.divide(128), "Fluid Ounze", "fl oz");
383
384        /**
385         * A unit of volume equal to 4 US oz_fl (standard name <code>liq.gi</code>).
386         */
387        public static final Unit<Volume> GILL_LIQUID = addUnit(FLUID_OUNCE.multiply(4), "Liquid Gill", "liq.gi");
388
389        /**
390         * A unit of volume <code>~ 1 drop or 0.95 grain of water </code> (standard
391         * name <code>min</code>).
392         */
393        public static final Unit<Volume> MINIM = addUnit(MICRO(LITER).multiply(61.61152d), "Minim", "min_us");
394
395        /**
396         * A unit of volume equal to <code>60 {@link #MINIM}</code> (standard name
397         * <code>fl dr</code>).
398         */
399        public static final Unit<Volume> FLUID_DRAM = addUnit(MINIM.multiply(60), "Fluid dram", "fl dr");
400
401        /**
402         * The cup is a unit of measurement for volume, used in cooking to measure
403         * liquids (fluid measurement) and bulk foods such as granulated sugar (dry
404         * measurement). A cup is equal to <code>8 {@link #FLUID_OUNCE}</code>
405         * (standard name <code>cup</code>).
406         */
407        public static final Unit<Volume> CUP = addUnit(FLUID_OUNCE.multiply(8), "Cup", "cup");
408
409        /**
410         * A unit of volume equal to <code>80 {@link #MINIM}</code> (standard name
411         * <code>tsp</code>).
412         */
413        public static final Unit<Volume> TEASPOON = addUnit(MINIM.multiply(80), "Teaspoon", "tsp");
414
415        /**
416         * A unit of volume equal to <code>3 {@link #TEASPOON}</code> (standard name
417         * <code>Tbsp</code>).
418         */
419        public static final Unit<Volume> TABLESPOON = addUnit(TEASPOON.multiply(3), "Tablespoon", "Tbsp");
420
421        /**
422         * A unit of volume equal to <code>238.4810 {@link #LITER}</code> (standard
423         * name <code>bbl</code>).
424         */
425        public static final Unit<Volume> BARREL = addUnit(LITER.multiply(238.4810d), "Barrel", "bbl");
426
427        /**
428         * A unit of volume equal to <code>4 {@link #GILL_LIQUID}</code> (standard
429         * name <code>pt</code>).
430         */
431        public static final Unit<Volume> PINT = addUnit(GILL_LIQUID.multiply(4), "Pint", "pt");
432
433        @Override
434        public String getName() {
435                return SYSTEM_NAME;
436        }
437
438        /**
439         * Holds the international foot: 0.3048 m exact.
440         */
441        // private static final int INTERNATIONAL_FOOT_DIVIDEND = 3048;
442
443        // private static final int INTERNATIONAL_FOOT_DIViSOR = 10000;
444
445        /**
446         * Adds a new unit not mapped to any specified quantity type.
447         *
448         * @param unit
449         *            the unit being added.
450         * @return <code>unit</code>.
451         */
452        private static <U extends Unit<?>> U addUnit(U unit) {
453                INSTANCE.units.add(unit);
454                return unit;
455        }
456
457        /**
458         * Adds a new unit not mapped to any specified quantity type and puts a text
459         * as symbol or label.
460         *
461         * @param unit
462         *            the unit being added.
463         * @param name
464         *            the string to use as name
465         * @param text
466         *            the string to use as label or symbol
467         * @param isLabel
468         *            if the string should be used as a label or not
469         * @return <code>unit</code>.
470         */
471        private static <U extends Unit<?>> U addUnit(U unit, String name, String text, boolean isLabel) {
472                if (isLabel) {
473                        SimpleUnitFormat.getInstance().label(unit, text);
474                }
475                if (name != null && unit instanceof AbstractUnit) {
476                        return Helper.addUnit(INSTANCE.units, unit, name);
477                } else {
478                        INSTANCE.units.add(unit);
479                }
480                return unit;
481        }
482
483        /**
484         * Adds a new unit not mapped to any specified quantity type and puts a text
485         * as symbol or label.
486         *
487         * @param unit
488         *            the unit being added.
489         * @param name
490         *            the string to use as name
491         * @param label
492         *            the string to use as label
493         * @return <code>unit</code>.
494         */
495        private static <U extends Unit<?>> U addUnit(U unit, String name, String label) {
496                return addUnit(unit, name, label, true);
497        }
498
499        /**
500         * Adds a new unit not mapped to any specified quantity type and puts a text
501         * as label.
502         *
503         * @param unit
504         *            the unit being added.
505         * @param text
506         *            the string to use as label or symbol
507         * @return <code>unit</code>.
508         */
509        private static <U extends Unit<?>> U addUnit(U unit, String text) {
510                return addUnit(unit, null, text, true);
511        }
512}