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