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