1/*
2 *******************************************************************************
3 * Copyright (C) 2004-2015, Google Inc, International Business Machines        *
4 * Corporation and others. All Rights Reserved.                                *
5 *******************************************************************************
6 */
7package com.ibm.icu.util;
8
9import java.io.Externalizable;
10import java.io.IOException;
11import java.io.ObjectInput;
12import java.io.ObjectOutput;
13import java.io.ObjectStreamException;
14import java.io.Serializable;
15import java.util.Collections;
16import java.util.Enumeration;
17import java.util.HashMap;
18import java.util.HashSet;
19import java.util.Map;
20import java.util.MissingResourceException;
21import java.util.Set;
22
23import com.ibm.icu.impl.ICUResourceBundle;
24import com.ibm.icu.impl.Pair;
25import com.ibm.icu.text.UnicodeSet;
26
27/**
28 * A unit such as length, mass, volume, currency, etc.  A unit is
29 * coupled with a numeric amount to produce a Measure. MeasureUnit objects are immutable.
30 * All subclasses must guarantee that. (However, subclassing is discouraged.)
31
32 *
33 * @see com.ibm.icu.util.Measure
34 * @author Alan Liu
35 * @stable ICU 3.0
36 */
37public class MeasureUnit implements Serializable {
38    private static final long serialVersionUID = -1839973855554750484L;
39
40    // Used to pre-fill the cache. These same constants appear in MeasureFormat too.
41    private static final String[] unitKeys = new String[]{"units", "unitsShort", "unitsNarrow"};
42
43    private static final Map<String, Map<String,MeasureUnit>> cache
44    = new HashMap<String, Map<String,MeasureUnit>>();
45
46    /**
47     * @internal
48     * @deprecated This API is ICU internal only.
49     */
50    @Deprecated
51    protected final String type;
52
53    /**
54     * @internal
55     * @deprecated This API is ICU internal only.
56     */
57    @Deprecated
58    protected final String subType;
59
60    /**
61     * @internal
62     * @deprecated This API is ICU internal only.
63     */
64    @Deprecated
65    protected MeasureUnit(String type, String subType) {
66        this.type = type;
67        this.subType = subType;
68    }
69
70    /**
71     * Get the type, such as "length"
72     *
73     * @stable ICU 53
74     */
75    public String getType() {
76        return type;
77    }
78
79
80    /**
81     * Get the subType, such as “foot”.
82     *
83     * @stable ICU 53
84     */
85    public String getSubtype() {
86        return subType;
87    }
88
89
90
91    /**
92     * {@inheritDoc}
93     *
94     * @stable ICU 53
95     */
96    @Override
97    public int hashCode() {
98        return 31 * type.hashCode() + subType.hashCode();
99    }
100
101    /**
102     * {@inheritDoc}
103     *
104     * @stable ICU 53
105     */
106    @Override
107    public boolean equals(Object rhs) {
108        if (rhs == this) {
109            return true;
110        }
111        if (!(rhs instanceof MeasureUnit)) {
112            return false;
113        }
114        MeasureUnit c = (MeasureUnit) rhs;
115        return type.equals(c.type) && subType.equals(c.subType);
116    }
117
118    /**
119     * {@inheritDoc}
120     *
121     * @stable ICU 53
122     */
123    @Override
124    public String toString() {
125        return type + "-" + subType;
126    }
127
128    /**
129     * Get all of the available units' types. Returned set is unmodifiable.
130     *
131     * @stable ICU 53
132     */
133    public synchronized static Set<String> getAvailableTypes() {
134        return Collections.unmodifiableSet(cache.keySet());
135    }
136
137    /**
138     * For the given type, return the available units.
139     * @param type the type
140     * @return the available units for type. Returned set is unmodifiable.
141     * @stable ICU 53
142     */
143    public synchronized static Set<MeasureUnit> getAvailable(String type) {
144        Map<String, MeasureUnit> units = cache.get(type);
145        // Train users not to modify returned set from the start giving us more
146        // flexibility for implementation.
147        return units == null ? Collections.<MeasureUnit>emptySet()
148                : Collections.unmodifiableSet(new HashSet<MeasureUnit>(units.values()));
149    }
150
151    /**
152     * Get all of the available units. Returned set is unmodifiable.
153     *
154     * @stable ICU 53
155     */
156    public synchronized static Set<MeasureUnit> getAvailable() {
157        Set<MeasureUnit> result = new HashSet<MeasureUnit>();
158        for (String type : new HashSet<String>(MeasureUnit.getAvailableTypes())) {
159            for (MeasureUnit unit : MeasureUnit.getAvailable(type)) {
160                result.add(unit);
161            }
162        }
163        // Train users not to modify returned set from the start giving us more
164        // flexibility for implementation.
165        return Collections.unmodifiableSet(result);
166    }
167
168    /**
169     * Create a MeasureUnit instance (creates a singleton instance).
170     * <p>
171     * Normally this method should not be used, since there will be no formatting data
172     * available for it, and it may not be returned by getAvailable().
173     * However, for special purposes (such as CLDR tooling), it is available.
174     *
175     * @internal
176     * @deprecated This API is ICU internal only.
177     */
178    @Deprecated
179    public static MeasureUnit internalGetInstance(String type, String subType) {
180        if (type == null || subType == null) {
181            throw new NullPointerException("Type and subType must be non-null");
182        }
183        if (!"currency".equals(type)) {
184            if (!ASCII.containsAll(type) || !ASCII_HYPHEN.containsAll(subType)) {
185                throw new IllegalArgumentException("The type or subType are invalid.");
186            }
187        }
188        Factory factory;
189        if ("currency".equals(type)) {
190            factory = CURRENCY_FACTORY;
191        } else if ("duration".equals(type)) {
192            factory = TIMEUNIT_FACTORY;
193        } else {
194            factory = UNIT_FACTORY;
195        }
196        return MeasureUnit.addUnit(type, subType, factory);
197    }
198
199    /**
200     * For ICU use only.
201     * @internal
202     * @deprecated This API is ICU internal only.
203     */
204    @Deprecated
205    public static MeasureUnit resolveUnitPerUnit(MeasureUnit unit, MeasureUnit perUnit) {
206        return unitPerUnitToSingleUnit.get(Pair.of(unit, perUnit));
207    }
208
209    static final UnicodeSet ASCII = new UnicodeSet('a', 'z').freeze();
210    static final UnicodeSet ASCII_HYPHEN = new UnicodeSet('-', '-', 'a', 'z').freeze();
211
212    /**
213     * @internal
214     * @deprecated This API is ICU internal only.
215     */
216    @Deprecated
217    protected interface Factory {
218        /**
219         * @internal
220         * @deprecated This API is ICU internal only.
221         */
222        @Deprecated
223        MeasureUnit create(String type, String subType);
224    }
225
226    private static Factory UNIT_FACTORY = new Factory() {
227        public MeasureUnit create(String type, String subType) {
228            return new MeasureUnit(type, subType);
229        }
230    };
231
232    static Factory CURRENCY_FACTORY = new Factory() {
233        public MeasureUnit create(String unusedType, String subType) {
234            return new Currency(subType);
235        }
236    };
237
238    static Factory TIMEUNIT_FACTORY = new Factory() {
239        public MeasureUnit create(String type, String subType) {
240           return new TimeUnit(type, subType);
241        }
242    };
243
244    static {
245        // load all of the units for English, since we know that that is a superset.
246        /**
247         *     units{
248         *            duration{
249         *                day{
250         *                    one{"{0} ден"}
251         *                    other{"{0} дена"}
252         *                }
253         */
254        ICUResourceBundle resource = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, "en");
255        for (String key : unitKeys) {
256            try {
257                ICUResourceBundle unitsTypeRes = resource.getWithFallback(key);
258                int size = unitsTypeRes.getSize();
259                for ( int index = 0; index < size; ++index) {
260                    UResourceBundle unitsRes = unitsTypeRes.get(index);
261                    String type = unitsRes.getKey();
262                    if (type.equals("compound")) {
263                        continue; // special type, does not have any unit plurals
264                    }
265                    int unitsSize = unitsRes.getSize();
266                    for ( int index2 = 0; index2 < unitsSize; ++index2) {
267                        ICUResourceBundle unitNameRes = (ICUResourceBundle)unitsRes.get(index2);
268                        if (unitNameRes.get("other") != null) {
269                            internalGetInstance(type, unitNameRes.getKey());
270                        }
271                    }
272                }
273            } catch ( MissingResourceException e ) {
274                continue;
275            }
276        }
277        // preallocate currencies
278        try {
279            UResourceBundle bundle = UResourceBundle.getBundleInstance(
280                    ICUResourceBundle.ICU_BASE_NAME,
281                    "currencyNumericCodes",
282                    ICUResourceBundle.ICU_DATA_CLASS_LOADER);
283            UResourceBundle codeMap = bundle.get("codeMap");
284            for (Enumeration<String> it = codeMap.getKeys(); it.hasMoreElements();) {
285                MeasureUnit.internalGetInstance("currency", it.nextElement());
286            }
287        } catch (MissingResourceException e) {
288            // fall through
289        }
290    }
291
292    // Must only be called at static initialization, or inside synchronized block.
293    /**
294     * @internal
295     * @deprecated This API is ICU internal only.
296     */
297    @Deprecated
298    protected synchronized static MeasureUnit addUnit(String type, String unitName, Factory factory) {
299        Map<String, MeasureUnit> tmp = cache.get(type);
300        if (tmp == null) {
301            cache.put(type, tmp = new HashMap<String, MeasureUnit>());
302        } else {
303            // "intern" the type by setting to first item's type.
304            type = tmp.entrySet().iterator().next().getValue().type;
305        }
306        MeasureUnit unit = tmp.get(unitName);
307        if (unit == null) {
308            tmp.put(unitName, unit = factory.create(type, unitName));
309        }
310        return unit;
311    }
312
313
314    /*
315     * Useful constants. Not necessarily complete: see {@link #getAvailable()}.
316     */
317
318// All code between the "Start generated MeasureUnit constants" comment and
319// the "End generated MeasureUnit constants" comment is auto generated code
320// and must not be edited manually. For instructions on how to correctly
321// update this code, refer to:
322// http://site.icu-project.org/design/formatting/measureformat/updating-measure-unit
323//
324    // Start generated MeasureUnit constants
325
326    /**
327     * Constant for unit of acceleration: g-force
328     * @stable ICU 53
329     */
330    public static final MeasureUnit G_FORCE = MeasureUnit.internalGetInstance("acceleration", "g-force");
331
332    /**
333     * Constant for unit of acceleration: meter-per-second-squared
334     * @draft ICU 54
335     * @provisional This API might change or be removed in a future release.
336     */
337    public static final MeasureUnit METER_PER_SECOND_SQUARED = MeasureUnit.internalGetInstance("acceleration", "meter-per-second-squared");
338
339    /**
340     * Constant for unit of angle: arc-minute
341     * @stable ICU 53
342     */
343    public static final MeasureUnit ARC_MINUTE = MeasureUnit.internalGetInstance("angle", "arc-minute");
344
345    /**
346     * Constant for unit of angle: arc-second
347     * @stable ICU 53
348     */
349    public static final MeasureUnit ARC_SECOND = MeasureUnit.internalGetInstance("angle", "arc-second");
350
351    /**
352     * Constant for unit of angle: degree
353     * @stable ICU 53
354     */
355    public static final MeasureUnit DEGREE = MeasureUnit.internalGetInstance("angle", "degree");
356
357    /**
358     * Constant for unit of angle: radian
359     * @draft ICU 54
360     * @provisional This API might change or be removed in a future release.
361     */
362    public static final MeasureUnit RADIAN = MeasureUnit.internalGetInstance("angle", "radian");
363
364    /**
365     * Constant for unit of area: acre
366     * @stable ICU 53
367     */
368    public static final MeasureUnit ACRE = MeasureUnit.internalGetInstance("area", "acre");
369
370    /**
371     * Constant for unit of area: hectare
372     * @stable ICU 53
373     */
374    public static final MeasureUnit HECTARE = MeasureUnit.internalGetInstance("area", "hectare");
375
376    /**
377     * Constant for unit of area: square-centimeter
378     * @draft ICU 54
379     * @provisional This API might change or be removed in a future release.
380     */
381    public static final MeasureUnit SQUARE_CENTIMETER = MeasureUnit.internalGetInstance("area", "square-centimeter");
382
383    /**
384     * Constant for unit of area: square-foot
385     * @stable ICU 53
386     */
387    public static final MeasureUnit SQUARE_FOOT = MeasureUnit.internalGetInstance("area", "square-foot");
388
389    /**
390     * Constant for unit of area: square-inch
391     * @draft ICU 54
392     * @provisional This API might change or be removed in a future release.
393     */
394    public static final MeasureUnit SQUARE_INCH = MeasureUnit.internalGetInstance("area", "square-inch");
395
396    /**
397     * Constant for unit of area: square-kilometer
398     * @stable ICU 53
399     */
400    public static final MeasureUnit SQUARE_KILOMETER = MeasureUnit.internalGetInstance("area", "square-kilometer");
401
402    /**
403     * Constant for unit of area: square-meter
404     * @stable ICU 53
405     */
406    public static final MeasureUnit SQUARE_METER = MeasureUnit.internalGetInstance("area", "square-meter");
407
408    /**
409     * Constant for unit of area: square-mile
410     * @stable ICU 53
411     */
412    public static final MeasureUnit SQUARE_MILE = MeasureUnit.internalGetInstance("area", "square-mile");
413
414    /**
415     * Constant for unit of area: square-yard
416     * @draft ICU 54
417     * @provisional This API might change or be removed in a future release.
418     */
419    public static final MeasureUnit SQUARE_YARD = MeasureUnit.internalGetInstance("area", "square-yard");
420
421    /**
422     * Constant for unit of consumption: liter-per-kilometer
423     * @draft ICU 54
424     * @provisional This API might change or be removed in a future release.
425     */
426    public static final MeasureUnit LITER_PER_KILOMETER = MeasureUnit.internalGetInstance("consumption", "liter-per-kilometer");
427
428    /**
429     * Constant for unit of consumption: mile-per-gallon
430     * @draft ICU 54
431     * @provisional This API might change or be removed in a future release.
432     */
433    public static final MeasureUnit MILE_PER_GALLON = MeasureUnit.internalGetInstance("consumption", "mile-per-gallon");
434
435    /**
436     * Constant for unit of digital: bit
437     * @draft ICU 54
438     * @provisional This API might change or be removed in a future release.
439     */
440    public static final MeasureUnit BIT = MeasureUnit.internalGetInstance("digital", "bit");
441
442    /**
443     * Constant for unit of digital: byte
444     * @draft ICU 54
445     * @provisional This API might change or be removed in a future release.
446     */
447    public static final MeasureUnit BYTE = MeasureUnit.internalGetInstance("digital", "byte");
448
449    /**
450     * Constant for unit of digital: gigabit
451     * @draft ICU 54
452     * @provisional This API might change or be removed in a future release.
453     */
454    public static final MeasureUnit GIGABIT = MeasureUnit.internalGetInstance("digital", "gigabit");
455
456    /**
457     * Constant for unit of digital: gigabyte
458     * @draft ICU 54
459     * @provisional This API might change or be removed in a future release.
460     */
461    public static final MeasureUnit GIGABYTE = MeasureUnit.internalGetInstance("digital", "gigabyte");
462
463    /**
464     * Constant for unit of digital: kilobit
465     * @draft ICU 54
466     * @provisional This API might change or be removed in a future release.
467     */
468    public static final MeasureUnit KILOBIT = MeasureUnit.internalGetInstance("digital", "kilobit");
469
470    /**
471     * Constant for unit of digital: kilobyte
472     * @draft ICU 54
473     * @provisional This API might change or be removed in a future release.
474     */
475    public static final MeasureUnit KILOBYTE = MeasureUnit.internalGetInstance("digital", "kilobyte");
476
477    /**
478     * Constant for unit of digital: megabit
479     * @draft ICU 54
480     * @provisional This API might change or be removed in a future release.
481     */
482    public static final MeasureUnit MEGABIT = MeasureUnit.internalGetInstance("digital", "megabit");
483
484    /**
485     * Constant for unit of digital: megabyte
486     * @draft ICU 54
487     * @provisional This API might change or be removed in a future release.
488     */
489    public static final MeasureUnit MEGABYTE = MeasureUnit.internalGetInstance("digital", "megabyte");
490
491    /**
492     * Constant for unit of digital: terabit
493     * @draft ICU 54
494     * @provisional This API might change or be removed in a future release.
495     */
496    public static final MeasureUnit TERABIT = MeasureUnit.internalGetInstance("digital", "terabit");
497
498    /**
499     * Constant for unit of digital: terabyte
500     * @draft ICU 54
501     * @provisional This API might change or be removed in a future release.
502     */
503    public static final MeasureUnit TERABYTE = MeasureUnit.internalGetInstance("digital", "terabyte");
504
505    /**
506     * Constant for unit of duration: day
507     * @stable ICU 4.0
508     */
509    public static final TimeUnit DAY = (TimeUnit) MeasureUnit.internalGetInstance("duration", "day");
510
511    /**
512     * Constant for unit of duration: hour
513     * @stable ICU 4.0
514     */
515    public static final TimeUnit HOUR = (TimeUnit) MeasureUnit.internalGetInstance("duration", "hour");
516
517    /**
518     * Constant for unit of duration: microsecond
519     * @draft ICU 54
520     * @provisional This API might change or be removed in a future release.
521     */
522    public static final MeasureUnit MICROSECOND = MeasureUnit.internalGetInstance("duration", "microsecond");
523
524    /**
525     * Constant for unit of duration: millisecond
526     * @stable ICU 53
527     */
528    public static final MeasureUnit MILLISECOND = MeasureUnit.internalGetInstance("duration", "millisecond");
529
530    /**
531     * Constant for unit of duration: minute
532     * @stable ICU 4.0
533     */
534    public static final TimeUnit MINUTE = (TimeUnit) MeasureUnit.internalGetInstance("duration", "minute");
535
536    /**
537     * Constant for unit of duration: month
538     *
539     * @stable ICU 4.0
540     */
541    public static final TimeUnit MONTH = (TimeUnit) MeasureUnit.internalGetInstance("duration", "month");
542
543    /**
544     * Constant for unit of duration: nanosecond
545     * @draft ICU 54
546     * @provisional This API might change or be removed in a future release.
547     */
548    public static final MeasureUnit NANOSECOND = MeasureUnit.internalGetInstance("duration", "nanosecond");
549
550    /**
551     * Constant for unit of duration: second
552     * @stable ICU 4.0
553     */
554    public static final TimeUnit SECOND = (TimeUnit) MeasureUnit.internalGetInstance("duration", "second");
555
556    /**
557     * Constant for unit of duration: week
558     * @stable ICU 4.0
559     */
560    public static final TimeUnit WEEK = (TimeUnit) MeasureUnit.internalGetInstance("duration", "week");
561
562    /**
563     * Constant for unit of duration: year
564     * @stable ICU 4.0
565     */
566    public static final TimeUnit YEAR = (TimeUnit) MeasureUnit.internalGetInstance("duration", "year");
567
568    /**
569     * Constant for unit of electric: ampere
570     * @draft ICU 54
571     * @provisional This API might change or be removed in a future release.
572     */
573    public static final MeasureUnit AMPERE = MeasureUnit.internalGetInstance("electric", "ampere");
574
575    /**
576     * Constant for unit of electric: milliampere
577     * @draft ICU 54
578     * @provisional This API might change or be removed in a future release.
579     */
580    public static final MeasureUnit MILLIAMPERE = MeasureUnit.internalGetInstance("electric", "milliampere");
581
582    /**
583     * Constant for unit of electric: ohm
584     * @draft ICU 54
585     * @provisional This API might change or be removed in a future release.
586     */
587    public static final MeasureUnit OHM = MeasureUnit.internalGetInstance("electric", "ohm");
588
589    /**
590     * Constant for unit of electric: volt
591     * @draft ICU 54
592     * @provisional This API might change or be removed in a future release.
593     */
594    public static final MeasureUnit VOLT = MeasureUnit.internalGetInstance("electric", "volt");
595
596    /**
597     * Constant for unit of energy: calorie
598     * @draft ICU 54
599     * @provisional This API might change or be removed in a future release.
600     */
601    public static final MeasureUnit CALORIE = MeasureUnit.internalGetInstance("energy", "calorie");
602
603    /**
604     * Constant for unit of energy: foodcalorie
605     * @draft ICU 54
606     * @provisional This API might change or be removed in a future release.
607     */
608    public static final MeasureUnit FOODCALORIE = MeasureUnit.internalGetInstance("energy", "foodcalorie");
609
610    /**
611     * Constant for unit of energy: joule
612     * @draft ICU 54
613     * @provisional This API might change or be removed in a future release.
614     */
615    public static final MeasureUnit JOULE = MeasureUnit.internalGetInstance("energy", "joule");
616
617    /**
618     * Constant for unit of energy: kilocalorie
619     * @draft ICU 54
620     * @provisional This API might change or be removed in a future release.
621     */
622    public static final MeasureUnit KILOCALORIE = MeasureUnit.internalGetInstance("energy", "kilocalorie");
623
624    /**
625     * Constant for unit of energy: kilojoule
626     * @draft ICU 54
627     * @provisional This API might change or be removed in a future release.
628     */
629    public static final MeasureUnit KILOJOULE = MeasureUnit.internalGetInstance("energy", "kilojoule");
630
631    /**
632     * Constant for unit of energy: kilowatt-hour
633     * @draft ICU 54
634     * @provisional This API might change or be removed in a future release.
635     */
636    public static final MeasureUnit KILOWATT_HOUR = MeasureUnit.internalGetInstance("energy", "kilowatt-hour");
637
638    /**
639     * Constant for unit of frequency: gigahertz
640     * @draft ICU 54
641     * @provisional This API might change or be removed in a future release.
642     */
643    public static final MeasureUnit GIGAHERTZ = MeasureUnit.internalGetInstance("frequency", "gigahertz");
644
645    /**
646     * Constant for unit of frequency: hertz
647     * @draft ICU 54
648     * @provisional This API might change or be removed in a future release.
649     */
650    public static final MeasureUnit HERTZ = MeasureUnit.internalGetInstance("frequency", "hertz");
651
652    /**
653     * Constant for unit of frequency: kilohertz
654     * @draft ICU 54
655     * @provisional This API might change or be removed in a future release.
656     */
657    public static final MeasureUnit KILOHERTZ = MeasureUnit.internalGetInstance("frequency", "kilohertz");
658
659    /**
660     * Constant for unit of frequency: megahertz
661     * @draft ICU 54
662     * @provisional This API might change or be removed in a future release.
663     */
664    public static final MeasureUnit MEGAHERTZ = MeasureUnit.internalGetInstance("frequency", "megahertz");
665
666    /**
667     * Constant for unit of length: astronomical-unit
668     * @draft ICU 54
669     * @provisional This API might change or be removed in a future release.
670     */
671    public static final MeasureUnit ASTRONOMICAL_UNIT = MeasureUnit.internalGetInstance("length", "astronomical-unit");
672
673    /**
674     * Constant for unit of length: centimeter
675     * @stable ICU 53
676     */
677    public static final MeasureUnit CENTIMETER = MeasureUnit.internalGetInstance("length", "centimeter");
678
679    /**
680     * Constant for unit of length: decimeter
681     * @draft ICU 54
682     * @provisional This API might change or be removed in a future release.
683     */
684    public static final MeasureUnit DECIMETER = MeasureUnit.internalGetInstance("length", "decimeter");
685
686    /**
687     * Constant for unit of length: fathom
688     * @draft ICU 54
689     * @provisional This API might change or be removed in a future release.
690     */
691    public static final MeasureUnit FATHOM = MeasureUnit.internalGetInstance("length", "fathom");
692
693    /**
694     * Constant for unit of length: foot
695     * @stable ICU 53
696     */
697    public static final MeasureUnit FOOT = MeasureUnit.internalGetInstance("length", "foot");
698
699    /**
700     * Constant for unit of length: furlong
701     * @draft ICU 54
702     * @provisional This API might change or be removed in a future release.
703     */
704    public static final MeasureUnit FURLONG = MeasureUnit.internalGetInstance("length", "furlong");
705
706    /**
707     * Constant for unit of length: inch
708     * @stable ICU 53
709     */
710    public static final MeasureUnit INCH = MeasureUnit.internalGetInstance("length", "inch");
711
712    /**
713     * Constant for unit of length: kilometer
714     * @stable ICU 53
715     */
716    public static final MeasureUnit KILOMETER = MeasureUnit.internalGetInstance("length", "kilometer");
717
718    /**
719     * Constant for unit of length: light-year
720     * @stable ICU 53
721     */
722    public static final MeasureUnit LIGHT_YEAR = MeasureUnit.internalGetInstance("length", "light-year");
723
724    /**
725     * Constant for unit of length: meter
726     * @stable ICU 53
727     */
728    public static final MeasureUnit METER = MeasureUnit.internalGetInstance("length", "meter");
729
730    /**
731     * Constant for unit of length: micrometer
732     * @draft ICU 54
733     * @provisional This API might change or be removed in a future release.
734     */
735    public static final MeasureUnit MICROMETER = MeasureUnit.internalGetInstance("length", "micrometer");
736
737    /**
738     * Constant for unit of length: mile
739     * @stable ICU 53
740     */
741    public static final MeasureUnit MILE = MeasureUnit.internalGetInstance("length", "mile");
742
743    /**
744     * Constant for unit of length: millimeter
745     * @stable ICU 53
746     */
747    public static final MeasureUnit MILLIMETER = MeasureUnit.internalGetInstance("length", "millimeter");
748
749    /**
750     * Constant for unit of length: nanometer
751     * @draft ICU 54
752     * @provisional This API might change or be removed in a future release.
753     */
754    public static final MeasureUnit NANOMETER = MeasureUnit.internalGetInstance("length", "nanometer");
755
756    /**
757     * Constant for unit of length: nautical-mile
758     * @draft ICU 54
759     * @provisional This API might change or be removed in a future release.
760     */
761    public static final MeasureUnit NAUTICAL_MILE = MeasureUnit.internalGetInstance("length", "nautical-mile");
762
763    /**
764     * Constant for unit of length: parsec
765     * @draft ICU 54
766     * @provisional This API might change or be removed in a future release.
767     */
768    public static final MeasureUnit PARSEC = MeasureUnit.internalGetInstance("length", "parsec");
769
770    /**
771     * Constant for unit of length: picometer
772     * @stable ICU 53
773     */
774    public static final MeasureUnit PICOMETER = MeasureUnit.internalGetInstance("length", "picometer");
775
776    /**
777     * Constant for unit of length: yard
778     * @stable ICU 53
779     */
780    public static final MeasureUnit YARD = MeasureUnit.internalGetInstance("length", "yard");
781
782    /**
783     * Constant for unit of light: lux
784     * @draft ICU 54
785     * @provisional This API might change or be removed in a future release.
786     */
787    public static final MeasureUnit LUX = MeasureUnit.internalGetInstance("light", "lux");
788
789    /**
790     * Constant for unit of mass: carat
791     * @draft ICU 54
792     * @provisional This API might change or be removed in a future release.
793     */
794    public static final MeasureUnit CARAT = MeasureUnit.internalGetInstance("mass", "carat");
795
796    /**
797     * Constant for unit of mass: gram
798     * @stable ICU 53
799     */
800    public static final MeasureUnit GRAM = MeasureUnit.internalGetInstance("mass", "gram");
801
802    /**
803     * Constant for unit of mass: kilogram
804     * @stable ICU 53
805     */
806    public static final MeasureUnit KILOGRAM = MeasureUnit.internalGetInstance("mass", "kilogram");
807
808    /**
809     * Constant for unit of mass: metric-ton
810     * @draft ICU 54
811     * @provisional This API might change or be removed in a future release.
812     */
813    public static final MeasureUnit METRIC_TON = MeasureUnit.internalGetInstance("mass", "metric-ton");
814
815    /**
816     * Constant for unit of mass: microgram
817     * @draft ICU 54
818     * @provisional This API might change or be removed in a future release.
819     */
820    public static final MeasureUnit MICROGRAM = MeasureUnit.internalGetInstance("mass", "microgram");
821
822    /**
823     * Constant for unit of mass: milligram
824     * @draft ICU 54
825     * @provisional This API might change or be removed in a future release.
826     */
827    public static final MeasureUnit MILLIGRAM = MeasureUnit.internalGetInstance("mass", "milligram");
828
829    /**
830     * Constant for unit of mass: ounce
831     * @stable ICU 53
832     */
833    public static final MeasureUnit OUNCE = MeasureUnit.internalGetInstance("mass", "ounce");
834
835    /**
836     * Constant for unit of mass: ounce-troy
837     * @draft ICU 54
838     * @provisional This API might change or be removed in a future release.
839     */
840    public static final MeasureUnit OUNCE_TROY = MeasureUnit.internalGetInstance("mass", "ounce-troy");
841
842    /**
843     * Constant for unit of mass: pound
844     * @stable ICU 53
845     */
846    public static final MeasureUnit POUND = MeasureUnit.internalGetInstance("mass", "pound");
847
848    /**
849     * Constant for unit of mass: stone
850     * @draft ICU 54
851     * @provisional This API might change or be removed in a future release.
852     */
853    public static final MeasureUnit STONE = MeasureUnit.internalGetInstance("mass", "stone");
854
855    /**
856     * Constant for unit of mass: ton
857     * @draft ICU 54
858     * @provisional This API might change or be removed in a future release.
859     */
860    public static final MeasureUnit TON = MeasureUnit.internalGetInstance("mass", "ton");
861
862    /**
863     * Constant for unit of power: gigawatt
864     * @draft ICU 54
865     * @provisional This API might change or be removed in a future release.
866     */
867    public static final MeasureUnit GIGAWATT = MeasureUnit.internalGetInstance("power", "gigawatt");
868
869    /**
870     * Constant for unit of power: horsepower
871     * @stable ICU 53
872     */
873    public static final MeasureUnit HORSEPOWER = MeasureUnit.internalGetInstance("power", "horsepower");
874
875    /**
876     * Constant for unit of power: kilowatt
877     * @stable ICU 53
878     */
879    public static final MeasureUnit KILOWATT = MeasureUnit.internalGetInstance("power", "kilowatt");
880
881    /**
882     * Constant for unit of power: megawatt
883     * @draft ICU 54
884     * @provisional This API might change or be removed in a future release.
885     */
886    public static final MeasureUnit MEGAWATT = MeasureUnit.internalGetInstance("power", "megawatt");
887
888    /**
889     * Constant for unit of power: milliwatt
890     * @draft ICU 54
891     * @provisional This API might change or be removed in a future release.
892     */
893    public static final MeasureUnit MILLIWATT = MeasureUnit.internalGetInstance("power", "milliwatt");
894
895    /**
896     * Constant for unit of power: watt
897     * @stable ICU 53
898     */
899    public static final MeasureUnit WATT = MeasureUnit.internalGetInstance("power", "watt");
900
901    /**
902     * Constant for unit of pressure: hectopascal
903     * @stable ICU 53
904     */
905    public static final MeasureUnit HECTOPASCAL = MeasureUnit.internalGetInstance("pressure", "hectopascal");
906
907    /**
908     * Constant for unit of pressure: inch-hg
909     * @stable ICU 53
910     */
911    public static final MeasureUnit INCH_HG = MeasureUnit.internalGetInstance("pressure", "inch-hg");
912
913    /**
914     * Constant for unit of pressure: millibar
915     * @stable ICU 53
916     */
917    public static final MeasureUnit MILLIBAR = MeasureUnit.internalGetInstance("pressure", "millibar");
918
919    /**
920     * Constant for unit of pressure: millimeter-of-mercury
921     * @draft ICU 54
922     * @provisional This API might change or be removed in a future release.
923     */
924    public static final MeasureUnit MILLIMETER_OF_MERCURY = MeasureUnit.internalGetInstance("pressure", "millimeter-of-mercury");
925
926    /**
927     * Constant for unit of pressure: pound-per-square-inch
928     * @draft ICU 54
929     * @provisional This API might change or be removed in a future release.
930     */
931    public static final MeasureUnit POUND_PER_SQUARE_INCH = MeasureUnit.internalGetInstance("pressure", "pound-per-square-inch");
932
933    /**
934     * Constant for unit of proportion: karat
935     * @draft ICU 54
936     * @provisional This API might change or be removed in a future release.
937     */
938    public static final MeasureUnit KARAT = MeasureUnit.internalGetInstance("proportion", "karat");
939
940    /**
941     * Constant for unit of speed: kilometer-per-hour
942     * @stable ICU 53
943     */
944    public static final MeasureUnit KILOMETER_PER_HOUR = MeasureUnit.internalGetInstance("speed", "kilometer-per-hour");
945
946    /**
947     * Constant for unit of speed: meter-per-second
948     * @stable ICU 53
949     */
950    public static final MeasureUnit METER_PER_SECOND = MeasureUnit.internalGetInstance("speed", "meter-per-second");
951
952    /**
953     * Constant for unit of speed: mile-per-hour
954     * @stable ICU 53
955     */
956    public static final MeasureUnit MILE_PER_HOUR = MeasureUnit.internalGetInstance("speed", "mile-per-hour");
957
958    /**
959     * Constant for unit of temperature: celsius
960     * @stable ICU 53
961     */
962    public static final MeasureUnit CELSIUS = MeasureUnit.internalGetInstance("temperature", "celsius");
963
964    /**
965     * Constant for unit of temperature: fahrenheit
966     * @stable ICU 53
967     */
968    public static final MeasureUnit FAHRENHEIT = MeasureUnit.internalGetInstance("temperature", "fahrenheit");
969
970    /**
971     * Constant for unit of temperature: kelvin
972     * @draft ICU 54
973     * @provisional This API might change or be removed in a future release.
974     */
975    public static final MeasureUnit KELVIN = MeasureUnit.internalGetInstance("temperature", "kelvin");
976
977    /**
978     * Constant for unit of volume: acre-foot
979     * @draft ICU 54
980     * @provisional This API might change or be removed in a future release.
981     */
982    public static final MeasureUnit ACRE_FOOT = MeasureUnit.internalGetInstance("volume", "acre-foot");
983
984    /**
985     * Constant for unit of volume: bushel
986     * @draft ICU 54
987     * @provisional This API might change or be removed in a future release.
988     */
989    public static final MeasureUnit BUSHEL = MeasureUnit.internalGetInstance("volume", "bushel");
990
991    /**
992     * Constant for unit of volume: centiliter
993     * @draft ICU 54
994     * @provisional This API might change or be removed in a future release.
995     */
996    public static final MeasureUnit CENTILITER = MeasureUnit.internalGetInstance("volume", "centiliter");
997
998    /**
999     * Constant for unit of volume: cubic-centimeter
1000     * @draft ICU 54
1001     * @provisional This API might change or be removed in a future release.
1002     */
1003    public static final MeasureUnit CUBIC_CENTIMETER = MeasureUnit.internalGetInstance("volume", "cubic-centimeter");
1004
1005    /**
1006     * Constant for unit of volume: cubic-foot
1007     * @draft ICU 54
1008     * @provisional This API might change or be removed in a future release.
1009     */
1010    public static final MeasureUnit CUBIC_FOOT = MeasureUnit.internalGetInstance("volume", "cubic-foot");
1011
1012    /**
1013     * Constant for unit of volume: cubic-inch
1014     * @draft ICU 54
1015     * @provisional This API might change or be removed in a future release.
1016     */
1017    public static final MeasureUnit CUBIC_INCH = MeasureUnit.internalGetInstance("volume", "cubic-inch");
1018
1019    /**
1020     * Constant for unit of volume: cubic-kilometer
1021     * @stable ICU 53
1022     */
1023    public static final MeasureUnit CUBIC_KILOMETER = MeasureUnit.internalGetInstance("volume", "cubic-kilometer");
1024
1025    /**
1026     * Constant for unit of volume: cubic-meter
1027     * @draft ICU 54
1028     * @provisional This API might change or be removed in a future release.
1029     */
1030    public static final MeasureUnit CUBIC_METER = MeasureUnit.internalGetInstance("volume", "cubic-meter");
1031
1032    /**
1033     * Constant for unit of volume: cubic-mile
1034     * @stable ICU 53
1035     */
1036    public static final MeasureUnit CUBIC_MILE = MeasureUnit.internalGetInstance("volume", "cubic-mile");
1037
1038    /**
1039     * Constant for unit of volume: cubic-yard
1040     * @draft ICU 54
1041     * @provisional This API might change or be removed in a future release.
1042     */
1043    public static final MeasureUnit CUBIC_YARD = MeasureUnit.internalGetInstance("volume", "cubic-yard");
1044
1045    /**
1046     * Constant for unit of volume: cup
1047     * @draft ICU 54
1048     * @provisional This API might change or be removed in a future release.
1049     */
1050    public static final MeasureUnit CUP = MeasureUnit.internalGetInstance("volume", "cup");
1051
1052    /**
1053     * Constant for unit of volume: deciliter
1054     * @draft ICU 54
1055     * @provisional This API might change or be removed in a future release.
1056     */
1057    public static final MeasureUnit DECILITER = MeasureUnit.internalGetInstance("volume", "deciliter");
1058
1059    /**
1060     * Constant for unit of volume: fluid-ounce
1061     * @draft ICU 54
1062     * @provisional This API might change or be removed in a future release.
1063     */
1064    public static final MeasureUnit FLUID_OUNCE = MeasureUnit.internalGetInstance("volume", "fluid-ounce");
1065
1066    /**
1067     * Constant for unit of volume: gallon
1068     * @draft ICU 54
1069     * @provisional This API might change or be removed in a future release.
1070     */
1071    public static final MeasureUnit GALLON = MeasureUnit.internalGetInstance("volume", "gallon");
1072
1073    /**
1074     * Constant for unit of volume: hectoliter
1075     * @draft ICU 54
1076     * @provisional This API might change or be removed in a future release.
1077     */
1078    public static final MeasureUnit HECTOLITER = MeasureUnit.internalGetInstance("volume", "hectoliter");
1079
1080    /**
1081     * Constant for unit of volume: liter
1082     * @stable ICU 53
1083     */
1084    public static final MeasureUnit LITER = MeasureUnit.internalGetInstance("volume", "liter");
1085
1086    /**
1087     * Constant for unit of volume: megaliter
1088     * @draft ICU 54
1089     * @provisional This API might change or be removed in a future release.
1090     */
1091    public static final MeasureUnit MEGALITER = MeasureUnit.internalGetInstance("volume", "megaliter");
1092
1093    /**
1094     * Constant for unit of volume: milliliter
1095     * @draft ICU 54
1096     * @provisional This API might change or be removed in a future release.
1097     */
1098    public static final MeasureUnit MILLILITER = MeasureUnit.internalGetInstance("volume", "milliliter");
1099
1100    /**
1101     * Constant for unit of volume: pint
1102     * @draft ICU 54
1103     * @provisional This API might change or be removed in a future release.
1104     */
1105    public static final MeasureUnit PINT = MeasureUnit.internalGetInstance("volume", "pint");
1106
1107    /**
1108     * Constant for unit of volume: quart
1109     * @draft ICU 54
1110     * @provisional This API might change or be removed in a future release.
1111     */
1112    public static final MeasureUnit QUART = MeasureUnit.internalGetInstance("volume", "quart");
1113
1114    /**
1115     * Constant for unit of volume: tablespoon
1116     * @draft ICU 54
1117     * @provisional This API might change or be removed in a future release.
1118     */
1119    public static final MeasureUnit TABLESPOON = MeasureUnit.internalGetInstance("volume", "tablespoon");
1120
1121    /**
1122     * Constant for unit of volume: teaspoon
1123     * @draft ICU 54
1124     * @provisional This API might change or be removed in a future release.
1125     */
1126    public static final MeasureUnit TEASPOON = MeasureUnit.internalGetInstance("volume", "teaspoon");
1127
1128    private static HashMap<Pair<MeasureUnit, MeasureUnit>, MeasureUnit>unitPerUnitToSingleUnit =
1129            new HashMap<Pair<MeasureUnit, MeasureUnit>, MeasureUnit>();
1130
1131    static {
1132        unitPerUnitToSingleUnit.put(Pair.<MeasureUnit, MeasureUnit>of(MeasureUnit.KILOMETER, MeasureUnit.HOUR), MeasureUnit.KILOMETER_PER_HOUR);
1133        unitPerUnitToSingleUnit.put(Pair.<MeasureUnit, MeasureUnit>of(MeasureUnit.MILE, MeasureUnit.GALLON), MeasureUnit.MILE_PER_GALLON);
1134        unitPerUnitToSingleUnit.put(Pair.<MeasureUnit, MeasureUnit>of(MeasureUnit.MILE, MeasureUnit.HOUR), MeasureUnit.MILE_PER_HOUR);
1135        unitPerUnitToSingleUnit.put(Pair.<MeasureUnit, MeasureUnit>of(MeasureUnit.METER, MeasureUnit.SECOND), MeasureUnit.METER_PER_SECOND);
1136        unitPerUnitToSingleUnit.put(Pair.<MeasureUnit, MeasureUnit>of(MeasureUnit.LITER, MeasureUnit.KILOMETER), MeasureUnit.LITER_PER_KILOMETER);
1137        unitPerUnitToSingleUnit.put(Pair.<MeasureUnit, MeasureUnit>of(MeasureUnit.POUND, MeasureUnit.SQUARE_INCH), MeasureUnit.POUND_PER_SQUARE_INCH);
1138    }
1139
1140    // End generated MeasureUnit constants
1141    /* Private */
1142
1143    private Object writeReplace() throws ObjectStreamException {
1144        return new MeasureUnitProxy(type, subType);
1145    }
1146
1147    static final class MeasureUnitProxy implements Externalizable {
1148        private static final long serialVersionUID = -3910681415330989598L;
1149
1150        private String type;
1151        private String subType;
1152
1153        public MeasureUnitProxy(String type, String subType) {
1154            this.type = type;
1155            this.subType = subType;
1156        }
1157
1158        // Must have public constructor, to enable Externalizable
1159        public MeasureUnitProxy() {
1160        }
1161
1162        public void writeExternal(ObjectOutput out) throws IOException {
1163            out.writeByte(0); // version
1164            out.writeUTF(type);
1165            out.writeUTF(subType);
1166            out.writeShort(0); // allow for more data.
1167        }
1168
1169        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
1170            /* byte version = */ in.readByte(); // version
1171            type = in.readUTF();
1172            subType = in.readUTF();
1173            // allow for more data from future version
1174            int extra = in.readShort();
1175            if (extra > 0) {
1176                byte[] extraBytes = new byte[extra];
1177                in.read(extraBytes, 0, extra);
1178            }
1179        }
1180
1181        private Object readResolve() throws ObjectStreamException {
1182            return MeasureUnit.internalGetInstance(type, subType);
1183        }
1184    }
1185}
1186