1/* 2 ******************************************************************************* 3 * Copyright (C) 2013-2015, International Business Machines Corporation and 4 * others. All Rights Reserved. 5 ******************************************************************************* 6 */ 7package com.ibm.icu.dev.test.format; 8 9import java.io.ByteArrayInputStream; 10import java.io.ByteArrayOutputStream; 11import java.io.IOException; 12import java.io.ObjectInputStream; 13import java.io.ObjectOutputStream; 14import java.io.Serializable; 15import java.text.FieldPosition; 16import java.util.ArrayList; 17import java.util.Collections; 18import java.util.Comparator; 19import java.util.HashMap; 20import java.util.HashSet; 21import java.util.List; 22import java.util.Locale; 23import java.util.Map; 24import java.util.TreeMap; 25 26import com.ibm.icu.dev.test.TestFmwk; 27import com.ibm.icu.dev.test.serializable.SerializableTest; 28import com.ibm.icu.impl.Pair; 29import com.ibm.icu.impl.Utility; 30import com.ibm.icu.math.BigDecimal; 31import com.ibm.icu.text.MeasureFormat; 32import com.ibm.icu.text.MeasureFormat.FormatWidth; 33import com.ibm.icu.text.NumberFormat; 34import com.ibm.icu.util.Currency; 35import com.ibm.icu.util.Measure; 36import com.ibm.icu.util.MeasureUnit; 37import com.ibm.icu.util.TimeUnit; 38import com.ibm.icu.util.TimeUnitAmount; 39import com.ibm.icu.util.ULocale; 40 41/** 42 * See https://sites.google.com/site/icusite/processes/release/tasks/standards?pli=1 43 * for information on how to update with each new release. 44 * @author markdavis 45 */ 46public class MeasureUnitTest extends TestFmwk { 47 48 static class OrderedPair<F extends Comparable, S extends Comparable> extends Pair<F, S> implements Comparable<OrderedPair<F, S>> { 49 50 OrderedPair(F first, S second) { 51 super(first, second); 52 } 53 54 public static <F extends Comparable, S extends Comparable> OrderedPair<F, S> of(F first, S second) { 55 if (first == null || second == null) { 56 throw new IllegalArgumentException("OrderedPair.of requires non null values."); 57 } 58 return new OrderedPair<F, S>(first, second); 59 } 60 61 public int compareTo(OrderedPair<F, S> other) { 62 int result = first.compareTo(other.first); 63 if (result != 0) { 64 return result; 65 } 66 return second.compareTo(other.second); 67 } 68 } 69 70 private static final String[] DRAFT_VERSIONS = {"54", "55", "56"}; 71 72 private static final HashSet<String> DRAFT_VERSION_SET = new HashSet<String>(); 73 74 private static final HashSet<String> TIME_CODES = new HashSet<String>(); 75 76 private static final String[][] JAVA_VERSIONS = { 77 {"G_FORCE", "53"}, 78 {"DEGREE", "53"}, 79 {"ARC_MINUTE", "53"}, 80 {"ARC_SECOND", "53"}, 81 {"ACRE", "53"}, 82 {"HECTARE", "53"}, 83 {"SQUARE_FOOT", "53"}, 84 {"SQUARE_KILOMETER", "53"}, 85 {"SQUARE_METER", "53"}, 86 {"SQUARE_MILE", "53"}, 87 {"MILLISECOND", "53"}, 88 {"CENTIMETER", "53"}, 89 {"FOOT", "53"}, 90 {"INCH", "53"}, 91 {"KILOMETER", "53"}, 92 {"LIGHT_YEAR", "53"}, 93 {"METER", "53"}, 94 {"MILE", "53"}, 95 {"MILLIMETER", "53"}, 96 {"PICOMETER", "53"}, 97 {"YARD", "53"}, 98 {"GRAM", "53"}, 99 {"KILOGRAM", "53"}, 100 {"OUNCE", "53"}, 101 {"POUND", "53"}, 102 {"HORSEPOWER", "53"}, 103 {"KILOWATT", "53"}, 104 {"WATT", "53"}, 105 {"HECTOPASCAL", "53"}, 106 {"INCH_HG", "53"}, 107 {"MILLIBAR", "53"}, 108 {"KILOMETER_PER_HOUR", "53"}, 109 {"METER_PER_SECOND", "53"}, 110 {"MILE_PER_HOUR", "53"}, 111 {"CELSIUS", "53"}, 112 {"FAHRENHEIT", "53"}, 113 {"CUBIC_KILOMETER", "53"}, 114 {"CUBIC_MILE", "53"}, 115 {"LITER", "53"}, 116 {"YEAR", "53"}, 117 {"MONTH", "53"}, 118 {"WEEK", "53"}, 119 {"DAY", "53"}, 120 {"HOUR", "53"}, 121 {"MINUTE", "53"}, 122 {"SECOND", "53"}, 123 {"METER_PER_SECOND_SQUARED", "54"}, 124 {"RADIAN", "54"}, 125 {"SQUARE_CENTIMETER", "54"}, 126 {"SQUARE_INCH", "54"}, 127 {"SQUARE_YARD", "54"}, 128 {"LITER_PER_KILOMETER", "54"}, 129 {"MILE_PER_GALLON", "54"}, 130 {"BIT", "54"}, 131 {"BYTE", "54"}, 132 {"GIGABIT", "54"}, 133 {"GIGABYTE", "54"}, 134 {"KILOBIT", "54"}, 135 {"KILOBYTE", "54"}, 136 {"MEGABIT", "54"}, 137 {"MEGABYTE", "54"}, 138 {"TERABIT", "54"}, 139 {"TERABYTE", "54"}, 140 {"MICROSECOND", "54"}, 141 {"NANOSECOND", "54"}, 142 {"AMPERE", "54"}, 143 {"MILLIAMPERE", "54"}, 144 {"OHM", "54"}, 145 {"VOLT", "54"}, 146 {"CALORIE", "54"}, 147 {"FOODCALORIE", "54"}, 148 {"JOULE", "54"}, 149 {"KILOCALORIE", "54"}, 150 {"KILOJOULE", "54"}, 151 {"KILOWATT_HOUR", "54"}, 152 {"GIGAHERTZ", "54"}, 153 {"HERTZ", "54"}, 154 {"KILOHERTZ", "54"}, 155 {"MEGAHERTZ", "54"}, 156 {"ASTRONOMICAL_UNIT", "54"}, 157 {"DECIMETER", "54"}, 158 {"FATHOM", "54"}, 159 {"FURLONG", "54"}, 160 {"MICROMETER", "54"}, 161 {"NANOMETER", "54"}, 162 {"NAUTICAL_MILE", "54"}, 163 {"PARSEC", "54"}, 164 {"LUX", "54"}, 165 {"CARAT", "54"}, 166 {"METRIC_TON", "54"}, 167 {"MICROGRAM", "54"}, 168 {"MILLIGRAM", "54"}, 169 {"OUNCE_TROY", "54"}, 170 {"STONE", "54"}, 171 {"TON", "54"}, 172 {"GIGAWATT", "54"}, 173 {"MEGAWATT", "54"}, 174 {"MILLIWATT", "54"}, 175 {"MILLIMETER_OF_MERCURY", "54"}, 176 {"POUND_PER_SQUARE_INCH", "54"}, 177 {"KARAT", "54"}, 178 {"KELVIN", "54"}, 179 {"ACRE_FOOT", "54"}, 180 {"BUSHEL", "54"}, 181 {"CENTILITER", "54"}, 182 {"CUBIC_CENTIMETER", "54"}, 183 {"CUBIC_FOOT", "54"}, 184 {"CUBIC_INCH", "54"}, 185 {"CUBIC_METER", "54"}, 186 {"CUBIC_YARD", "54"}, 187 {"CUP", "54"}, 188 {"DECILITER", "54"}, 189 {"FLUID_OUNCE", "54"}, 190 {"GALLON", "54"}, 191 {"HECTOLITER", "54"}, 192 {"MEGALITER", "54"}, 193 {"MILLILITER", "54"}, 194 {"PINT", "54"}, 195 {"QUART", "54"}, 196 {"TABLESPOON", "54"}, 197 {"TEASPOON", "54"}, 198 {"GENERIC_TEMPERATURE", "56"}, 199 {"REVOLUTION_ANGLE", "56"}, 200 {"LITER_PER_100KILOMETERS", "56"}, 201 {"CENTURY", "56"}, 202 {"MILE_SCANDINAVIAN", "56"}, 203 {"KNOT", "56"}, 204 {"CUP_METRIC", "56"}, 205 {"PINT_METRIC", "56"}, 206 }; 207 208 private static final HashMap<String, String> JAVA_VERSION_MAP = new HashMap<String, String>(); 209 210 static { 211 TIME_CODES.add("year"); 212 TIME_CODES.add("month"); 213 TIME_CODES.add("week"); 214 TIME_CODES.add("day"); 215 TIME_CODES.add("hour"); 216 TIME_CODES.add("minute"); 217 TIME_CODES.add("second"); 218 for (String verNum : DRAFT_VERSIONS) { 219 DRAFT_VERSION_SET.add(verNum); 220 } 221 for (String[] funcNameAndVersion : JAVA_VERSIONS) { 222 JAVA_VERSION_MAP.put(funcNameAndVersion[0], funcNameAndVersion[1]); 223 } 224 } 225 226 /** 227 * @author markdavis 228 * 229 */ 230 public static void main(String[] args) { 231 //generateConstants(); if (true) return; 232 new MeasureUnitTest().run(args); 233 } 234 235 //public void testZZZ() { 236 // // various generateXXX calls go here, see 237 // // http://site.icu-project.org/design/formatting/measureformat/updating-measure-unit 238 //} 239 240 public void TestCompatible53_1() { 241 MeasureUnit[] units = { 242 MeasureUnit.G_FORCE, 243 MeasureUnit.DEGREE, 244 MeasureUnit.ARC_MINUTE, 245 MeasureUnit.ARC_SECOND, 246 MeasureUnit.ACRE, 247 MeasureUnit.HECTARE, 248 MeasureUnit.SQUARE_FOOT, 249 MeasureUnit.SQUARE_KILOMETER, 250 MeasureUnit.SQUARE_METER, 251 MeasureUnit.SQUARE_MILE, 252 MeasureUnit.MILLISECOND, 253 MeasureUnit.CENTIMETER, 254 MeasureUnit.FOOT, 255 MeasureUnit.INCH, 256 MeasureUnit.KILOMETER, 257 MeasureUnit.LIGHT_YEAR, 258 MeasureUnit.METER, 259 MeasureUnit.MILE, 260 MeasureUnit.MILLIMETER, 261 MeasureUnit.PICOMETER, 262 MeasureUnit.YARD, 263 MeasureUnit.GRAM, 264 MeasureUnit.KILOGRAM, 265 MeasureUnit.OUNCE, 266 MeasureUnit.POUND, 267 MeasureUnit.HORSEPOWER, 268 MeasureUnit.KILOWATT, 269 MeasureUnit.WATT, 270 MeasureUnit.HECTOPASCAL, 271 MeasureUnit.INCH_HG, 272 MeasureUnit.MILLIBAR, 273 MeasureUnit.KILOMETER_PER_HOUR, 274 MeasureUnit.METER_PER_SECOND, 275 MeasureUnit.MILE_PER_HOUR, 276 MeasureUnit.CELSIUS, 277 MeasureUnit.FAHRENHEIT, 278 MeasureUnit.CUBIC_KILOMETER, 279 MeasureUnit.CUBIC_MILE, 280 MeasureUnit.LITER, 281 MeasureUnit.YEAR, 282 MeasureUnit.MONTH, 283 MeasureUnit.WEEK, 284 MeasureUnit.DAY, 285 MeasureUnit.HOUR, 286 MeasureUnit.MINUTE, 287 MeasureUnit.SECOND, 288 }; 289 assertEquals("", 46, units.length); 290 } 291 292 public void TestCompatible54_1() { 293 MeasureUnit[] units = { 294 MeasureUnit.G_FORCE, 295 MeasureUnit.METER_PER_SECOND_SQUARED, 296 MeasureUnit.ARC_MINUTE, 297 MeasureUnit.ARC_SECOND, 298 MeasureUnit.DEGREE, 299 MeasureUnit.RADIAN, 300 MeasureUnit.ACRE, 301 MeasureUnit.HECTARE, 302 MeasureUnit.SQUARE_CENTIMETER, 303 MeasureUnit.SQUARE_FOOT, 304 MeasureUnit.SQUARE_INCH, 305 MeasureUnit.SQUARE_KILOMETER, 306 MeasureUnit.SQUARE_METER, 307 MeasureUnit.SQUARE_MILE, 308 MeasureUnit.SQUARE_YARD, 309 MeasureUnit.LITER_PER_KILOMETER, 310 MeasureUnit.MILE_PER_GALLON, 311 MeasureUnit.BIT, 312 MeasureUnit.BYTE, 313 MeasureUnit.GIGABIT, 314 MeasureUnit.GIGABYTE, 315 MeasureUnit.KILOBIT, 316 MeasureUnit.KILOBYTE, 317 MeasureUnit.MEGABIT, 318 MeasureUnit.MEGABYTE, 319 MeasureUnit.TERABIT, 320 MeasureUnit.TERABYTE, 321 MeasureUnit.DAY, 322 MeasureUnit.HOUR, 323 MeasureUnit.MICROSECOND, 324 MeasureUnit.MILLISECOND, 325 MeasureUnit.MINUTE, 326 MeasureUnit.MONTH, 327 MeasureUnit.NANOSECOND, 328 MeasureUnit.SECOND, 329 MeasureUnit.WEEK, 330 MeasureUnit.YEAR, 331 MeasureUnit.AMPERE, 332 MeasureUnit.MILLIAMPERE, 333 MeasureUnit.OHM, 334 MeasureUnit.VOLT, 335 MeasureUnit.CALORIE, 336 MeasureUnit.FOODCALORIE, 337 MeasureUnit.JOULE, 338 MeasureUnit.KILOCALORIE, 339 MeasureUnit.KILOJOULE, 340 MeasureUnit.KILOWATT_HOUR, 341 MeasureUnit.GIGAHERTZ, 342 MeasureUnit.HERTZ, 343 MeasureUnit.KILOHERTZ, 344 MeasureUnit.MEGAHERTZ, 345 MeasureUnit.ASTRONOMICAL_UNIT, 346 MeasureUnit.CENTIMETER, 347 MeasureUnit.DECIMETER, 348 MeasureUnit.FATHOM, 349 MeasureUnit.FOOT, 350 MeasureUnit.FURLONG, 351 MeasureUnit.INCH, 352 MeasureUnit.KILOMETER, 353 MeasureUnit.LIGHT_YEAR, 354 MeasureUnit.METER, 355 MeasureUnit.MICROMETER, 356 MeasureUnit.MILE, 357 MeasureUnit.MILLIMETER, 358 MeasureUnit.NANOMETER, 359 MeasureUnit.NAUTICAL_MILE, 360 MeasureUnit.PARSEC, 361 MeasureUnit.PICOMETER, 362 MeasureUnit.YARD, 363 MeasureUnit.LUX, 364 MeasureUnit.CARAT, 365 MeasureUnit.GRAM, 366 MeasureUnit.KILOGRAM, 367 MeasureUnit.METRIC_TON, 368 MeasureUnit.MICROGRAM, 369 MeasureUnit.MILLIGRAM, 370 MeasureUnit.OUNCE, 371 MeasureUnit.OUNCE_TROY, 372 MeasureUnit.POUND, 373 MeasureUnit.STONE, 374 MeasureUnit.TON, 375 MeasureUnit.GIGAWATT, 376 MeasureUnit.HORSEPOWER, 377 MeasureUnit.KILOWATT, 378 MeasureUnit.MEGAWATT, 379 MeasureUnit.MILLIWATT, 380 MeasureUnit.WATT, 381 MeasureUnit.HECTOPASCAL, 382 MeasureUnit.INCH_HG, 383 MeasureUnit.MILLIBAR, 384 MeasureUnit.MILLIMETER_OF_MERCURY, 385 MeasureUnit.POUND_PER_SQUARE_INCH, 386 MeasureUnit.KARAT, 387 MeasureUnit.KILOMETER_PER_HOUR, 388 MeasureUnit.METER_PER_SECOND, 389 MeasureUnit.MILE_PER_HOUR, 390 MeasureUnit.CELSIUS, 391 MeasureUnit.FAHRENHEIT, 392 MeasureUnit.KELVIN, 393 MeasureUnit.ACRE_FOOT, 394 MeasureUnit.BUSHEL, 395 MeasureUnit.CENTILITER, 396 MeasureUnit.CUBIC_CENTIMETER, 397 MeasureUnit.CUBIC_FOOT, 398 MeasureUnit.CUBIC_INCH, 399 MeasureUnit.CUBIC_KILOMETER, 400 MeasureUnit.CUBIC_METER, 401 MeasureUnit.CUBIC_MILE, 402 MeasureUnit.CUBIC_YARD, 403 MeasureUnit.CUP, 404 MeasureUnit.DECILITER, 405 MeasureUnit.FLUID_OUNCE, 406 MeasureUnit.GALLON, 407 MeasureUnit.HECTOLITER, 408 MeasureUnit.LITER, 409 MeasureUnit.MEGALITER, 410 MeasureUnit.MILLILITER, 411 MeasureUnit.PINT, 412 MeasureUnit.QUART, 413 MeasureUnit.TABLESPOON, 414 MeasureUnit.TEASPOON, 415 }; 416 assertEquals("", 121, units.length); 417 } 418 419 public void TestCompatible55_1() { 420 MeasureUnit[] units = { 421 MeasureUnit.G_FORCE, 422 MeasureUnit.METER_PER_SECOND_SQUARED, 423 MeasureUnit.ARC_MINUTE, 424 MeasureUnit.ARC_SECOND, 425 MeasureUnit.DEGREE, 426 MeasureUnit.RADIAN, 427 MeasureUnit.ACRE, 428 MeasureUnit.HECTARE, 429 MeasureUnit.SQUARE_CENTIMETER, 430 MeasureUnit.SQUARE_FOOT, 431 MeasureUnit.SQUARE_INCH, 432 MeasureUnit.SQUARE_KILOMETER, 433 MeasureUnit.SQUARE_METER, 434 MeasureUnit.SQUARE_MILE, 435 MeasureUnit.SQUARE_YARD, 436 MeasureUnit.LITER_PER_KILOMETER, 437 MeasureUnit.MILE_PER_GALLON, 438 MeasureUnit.BIT, 439 MeasureUnit.BYTE, 440 MeasureUnit.GIGABIT, 441 MeasureUnit.GIGABYTE, 442 MeasureUnit.KILOBIT, 443 MeasureUnit.KILOBYTE, 444 MeasureUnit.MEGABIT, 445 MeasureUnit.MEGABYTE, 446 MeasureUnit.TERABIT, 447 MeasureUnit.TERABYTE, 448 MeasureUnit.DAY, 449 MeasureUnit.HOUR, 450 MeasureUnit.MICROSECOND, 451 MeasureUnit.MILLISECOND, 452 MeasureUnit.MINUTE, 453 MeasureUnit.MONTH, 454 MeasureUnit.NANOSECOND, 455 MeasureUnit.SECOND, 456 MeasureUnit.WEEK, 457 MeasureUnit.YEAR, 458 MeasureUnit.AMPERE, 459 MeasureUnit.MILLIAMPERE, 460 MeasureUnit.OHM, 461 MeasureUnit.VOLT, 462 MeasureUnit.CALORIE, 463 MeasureUnit.FOODCALORIE, 464 MeasureUnit.JOULE, 465 MeasureUnit.KILOCALORIE, 466 MeasureUnit.KILOJOULE, 467 MeasureUnit.KILOWATT_HOUR, 468 MeasureUnit.GIGAHERTZ, 469 MeasureUnit.HERTZ, 470 MeasureUnit.KILOHERTZ, 471 MeasureUnit.MEGAHERTZ, 472 MeasureUnit.ASTRONOMICAL_UNIT, 473 MeasureUnit.CENTIMETER, 474 MeasureUnit.DECIMETER, 475 MeasureUnit.FATHOM, 476 MeasureUnit.FOOT, 477 MeasureUnit.FURLONG, 478 MeasureUnit.INCH, 479 MeasureUnit.KILOMETER, 480 MeasureUnit.LIGHT_YEAR, 481 MeasureUnit.METER, 482 MeasureUnit.MICROMETER, 483 MeasureUnit.MILE, 484 MeasureUnit.MILLIMETER, 485 MeasureUnit.NANOMETER, 486 MeasureUnit.NAUTICAL_MILE, 487 MeasureUnit.PARSEC, 488 MeasureUnit.PICOMETER, 489 MeasureUnit.YARD, 490 MeasureUnit.LUX, 491 MeasureUnit.CARAT, 492 MeasureUnit.GRAM, 493 MeasureUnit.KILOGRAM, 494 MeasureUnit.METRIC_TON, 495 MeasureUnit.MICROGRAM, 496 MeasureUnit.MILLIGRAM, 497 MeasureUnit.OUNCE, 498 MeasureUnit.OUNCE_TROY, 499 MeasureUnit.POUND, 500 MeasureUnit.STONE, 501 MeasureUnit.TON, 502 MeasureUnit.GIGAWATT, 503 MeasureUnit.HORSEPOWER, 504 MeasureUnit.KILOWATT, 505 MeasureUnit.MEGAWATT, 506 MeasureUnit.MILLIWATT, 507 MeasureUnit.WATT, 508 MeasureUnit.HECTOPASCAL, 509 MeasureUnit.INCH_HG, 510 MeasureUnit.MILLIBAR, 511 MeasureUnit.MILLIMETER_OF_MERCURY, 512 MeasureUnit.POUND_PER_SQUARE_INCH, 513 MeasureUnit.KARAT, 514 MeasureUnit.KILOMETER_PER_HOUR, 515 MeasureUnit.METER_PER_SECOND, 516 MeasureUnit.MILE_PER_HOUR, 517 MeasureUnit.CELSIUS, 518 MeasureUnit.FAHRENHEIT, 519 MeasureUnit.GENERIC_TEMPERATURE, 520 MeasureUnit.KELVIN, 521 MeasureUnit.ACRE_FOOT, 522 MeasureUnit.BUSHEL, 523 MeasureUnit.CENTILITER, 524 MeasureUnit.CUBIC_CENTIMETER, 525 MeasureUnit.CUBIC_FOOT, 526 MeasureUnit.CUBIC_INCH, 527 MeasureUnit.CUBIC_KILOMETER, 528 MeasureUnit.CUBIC_METER, 529 MeasureUnit.CUBIC_MILE, 530 MeasureUnit.CUBIC_YARD, 531 MeasureUnit.CUP, 532 MeasureUnit.DECILITER, 533 MeasureUnit.FLUID_OUNCE, 534 MeasureUnit.GALLON, 535 MeasureUnit.HECTOLITER, 536 MeasureUnit.LITER, 537 MeasureUnit.MEGALITER, 538 MeasureUnit.MILLILITER, 539 MeasureUnit.PINT, 540 MeasureUnit.QUART, 541 MeasureUnit.TABLESPOON, 542 MeasureUnit.TEASPOON, 543 }; 544 assertEquals("", 122, units.length); 545 } 546 547 public void TestCompatible56_1() { 548 MeasureUnit[] units = { 549 MeasureUnit.G_FORCE, 550 MeasureUnit.METER_PER_SECOND_SQUARED, 551 MeasureUnit.ARC_MINUTE, 552 MeasureUnit.ARC_SECOND, 553 MeasureUnit.DEGREE, 554 MeasureUnit.RADIAN, 555 MeasureUnit.REVOLUTION_ANGLE, 556 MeasureUnit.ACRE, 557 MeasureUnit.HECTARE, 558 MeasureUnit.SQUARE_CENTIMETER, 559 MeasureUnit.SQUARE_FOOT, 560 MeasureUnit.SQUARE_INCH, 561 MeasureUnit.SQUARE_KILOMETER, 562 MeasureUnit.SQUARE_METER, 563 MeasureUnit.SQUARE_MILE, 564 MeasureUnit.SQUARE_YARD, 565 MeasureUnit.LITER_PER_100KILOMETERS, 566 MeasureUnit.LITER_PER_KILOMETER, 567 MeasureUnit.MILE_PER_GALLON, 568 MeasureUnit.BIT, 569 MeasureUnit.BYTE, 570 MeasureUnit.GIGABIT, 571 MeasureUnit.GIGABYTE, 572 MeasureUnit.KILOBIT, 573 MeasureUnit.KILOBYTE, 574 MeasureUnit.MEGABIT, 575 MeasureUnit.MEGABYTE, 576 MeasureUnit.TERABIT, 577 MeasureUnit.TERABYTE, 578 MeasureUnit.CENTURY, 579 MeasureUnit.DAY, 580 MeasureUnit.HOUR, 581 MeasureUnit.MICROSECOND, 582 MeasureUnit.MILLISECOND, 583 MeasureUnit.MINUTE, 584 MeasureUnit.MONTH, 585 MeasureUnit.NANOSECOND, 586 MeasureUnit.SECOND, 587 MeasureUnit.WEEK, 588 MeasureUnit.YEAR, 589 MeasureUnit.AMPERE, 590 MeasureUnit.MILLIAMPERE, 591 MeasureUnit.OHM, 592 MeasureUnit.VOLT, 593 MeasureUnit.CALORIE, 594 MeasureUnit.FOODCALORIE, 595 MeasureUnit.JOULE, 596 MeasureUnit.KILOCALORIE, 597 MeasureUnit.KILOJOULE, 598 MeasureUnit.KILOWATT_HOUR, 599 MeasureUnit.GIGAHERTZ, 600 MeasureUnit.HERTZ, 601 MeasureUnit.KILOHERTZ, 602 MeasureUnit.MEGAHERTZ, 603 MeasureUnit.ASTRONOMICAL_UNIT, 604 MeasureUnit.CENTIMETER, 605 MeasureUnit.DECIMETER, 606 MeasureUnit.FATHOM, 607 MeasureUnit.FOOT, 608 MeasureUnit.FURLONG, 609 MeasureUnit.INCH, 610 MeasureUnit.KILOMETER, 611 MeasureUnit.LIGHT_YEAR, 612 MeasureUnit.METER, 613 MeasureUnit.MICROMETER, 614 MeasureUnit.MILE, 615 MeasureUnit.MILE_SCANDINAVIAN, 616 MeasureUnit.MILLIMETER, 617 MeasureUnit.NANOMETER, 618 MeasureUnit.NAUTICAL_MILE, 619 MeasureUnit.PARSEC, 620 MeasureUnit.PICOMETER, 621 MeasureUnit.YARD, 622 MeasureUnit.LUX, 623 MeasureUnit.CARAT, 624 MeasureUnit.GRAM, 625 MeasureUnit.KILOGRAM, 626 MeasureUnit.METRIC_TON, 627 MeasureUnit.MICROGRAM, 628 MeasureUnit.MILLIGRAM, 629 MeasureUnit.OUNCE, 630 MeasureUnit.OUNCE_TROY, 631 MeasureUnit.POUND, 632 MeasureUnit.STONE, 633 MeasureUnit.TON, 634 MeasureUnit.GIGAWATT, 635 MeasureUnit.HORSEPOWER, 636 MeasureUnit.KILOWATT, 637 MeasureUnit.MEGAWATT, 638 MeasureUnit.MILLIWATT, 639 MeasureUnit.WATT, 640 MeasureUnit.HECTOPASCAL, 641 MeasureUnit.INCH_HG, 642 MeasureUnit.MILLIBAR, 643 MeasureUnit.MILLIMETER_OF_MERCURY, 644 MeasureUnit.POUND_PER_SQUARE_INCH, 645 MeasureUnit.KARAT, 646 MeasureUnit.KILOMETER_PER_HOUR, 647 MeasureUnit.KNOT, 648 MeasureUnit.METER_PER_SECOND, 649 MeasureUnit.MILE_PER_HOUR, 650 MeasureUnit.CELSIUS, 651 MeasureUnit.FAHRENHEIT, 652 MeasureUnit.GENERIC_TEMPERATURE, 653 MeasureUnit.KELVIN, 654 MeasureUnit.ACRE_FOOT, 655 MeasureUnit.BUSHEL, 656 MeasureUnit.CENTILITER, 657 MeasureUnit.CUBIC_CENTIMETER, 658 MeasureUnit.CUBIC_FOOT, 659 MeasureUnit.CUBIC_INCH, 660 MeasureUnit.CUBIC_KILOMETER, 661 MeasureUnit.CUBIC_METER, 662 MeasureUnit.CUBIC_MILE, 663 MeasureUnit.CUBIC_YARD, 664 MeasureUnit.CUP, 665 MeasureUnit.CUP_METRIC, 666 MeasureUnit.DECILITER, 667 MeasureUnit.FLUID_OUNCE, 668 MeasureUnit.GALLON, 669 MeasureUnit.HECTOLITER, 670 MeasureUnit.LITER, 671 MeasureUnit.MEGALITER, 672 MeasureUnit.MILLILITER, 673 MeasureUnit.PINT, 674 MeasureUnit.PINT_METRIC, 675 MeasureUnit.QUART, 676 MeasureUnit.TABLESPOON, 677 MeasureUnit.TEASPOON, 678 }; 679 assertEquals("", 129, units.length); 680 } 681 682 public void TestExamplesInDocs() { 683 MeasureFormat fmtFr = MeasureFormat.getInstance( 684 ULocale.FRENCH, FormatWidth.SHORT); 685 Measure measure = new Measure(23, MeasureUnit.CELSIUS); 686 assertEquals("23 °C", "23 °C", fmtFr.format(measure)); 687 Measure measureF = new Measure(70, MeasureUnit.FAHRENHEIT); 688 assertEquals("70 °F", "70 °F", fmtFr.format(measureF)); 689 MeasureFormat fmtFrFull = MeasureFormat.getInstance( 690 ULocale.FRENCH, FormatWidth.WIDE); 691 assertEquals( 692 "70 pied et 5,3 pouces", 693 "70 pieds et 5,3 pouces", 694 fmtFrFull.formatMeasures( 695 new Measure(70, MeasureUnit.FOOT), 696 new Measure(5.3, MeasureUnit.INCH))); 697 assertEquals( 698 "1 pied et 1 pouce", 699 "1 pied et 1 pouce", 700 fmtFrFull.formatMeasures( 701 new Measure(1, MeasureUnit.FOOT), 702 new Measure(1, MeasureUnit.INCH))); 703 MeasureFormat fmtFrNarrow = MeasureFormat.getInstance( 704 ULocale.FRENCH, FormatWidth.NARROW); 705 assertEquals( 706 "1′ 1″", 707 "1′ 1″", 708 fmtFrNarrow.formatMeasures( 709 new Measure(1, MeasureUnit.FOOT), 710 new Measure(1, MeasureUnit.INCH))); 711 MeasureFormat fmtEn = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.WIDE); 712 assertEquals( 713 "1 inch, 2 feet", 714 "1 inch, 2 feet", 715 fmtEn.formatMeasures( 716 new Measure(1, MeasureUnit.INCH), 717 new Measure(2, MeasureUnit.FOOT))); 718 } 719 720 public void TestFormatPeriodEn() { 721 TimeUnitAmount[] _19m = {new TimeUnitAmount(19.0, TimeUnit.MINUTE)}; 722 TimeUnitAmount[] _1h_23_5s = { 723 new TimeUnitAmount(1.0, TimeUnit.HOUR), 724 new TimeUnitAmount(23.5, TimeUnit.SECOND)}; 725 TimeUnitAmount[] _1h_23_5m = { 726 new TimeUnitAmount(1.0, TimeUnit.HOUR), 727 new TimeUnitAmount(23.5, TimeUnit.MINUTE)}; 728 TimeUnitAmount[] _1h_0m_23s = { 729 new TimeUnitAmount(1.0, TimeUnit.HOUR), 730 new TimeUnitAmount(0.0, TimeUnit.MINUTE), 731 new TimeUnitAmount(23.0, TimeUnit.SECOND)}; 732 TimeUnitAmount[] _2y_5M_3w_4d = { 733 new TimeUnitAmount(2.0, TimeUnit.YEAR), 734 new TimeUnitAmount(5.0, TimeUnit.MONTH), 735 new TimeUnitAmount(3.0, TimeUnit.WEEK), 736 new TimeUnitAmount(4.0, TimeUnit.DAY)}; 737 TimeUnitAmount[] _1m_59_9996s = { 738 new TimeUnitAmount(1.0, TimeUnit.MINUTE), 739 new TimeUnitAmount(59.9996, TimeUnit.SECOND)}; 740 TimeUnitAmount[] _5h_17m = { 741 new TimeUnitAmount(5.0, TimeUnit.HOUR), 742 new TimeUnitAmount(17.0, TimeUnit.MINUTE)}; 743 TimeUnitAmount[] _neg5h_17m = { 744 new TimeUnitAmount(-5.0, TimeUnit.HOUR), 745 new TimeUnitAmount(17.0, TimeUnit.MINUTE)}; 746 TimeUnitAmount[] _19m_28s = { 747 new TimeUnitAmount(19.0, TimeUnit.MINUTE), 748 new TimeUnitAmount(28.0, TimeUnit.SECOND)}; 749 TimeUnitAmount[] _0h_0m_9s = { 750 new TimeUnitAmount(0.0, TimeUnit.HOUR), 751 new TimeUnitAmount(0.0, TimeUnit.MINUTE), 752 new TimeUnitAmount(9.0, TimeUnit.SECOND)}; 753 TimeUnitAmount[] _0h_0m_17s = { 754 new TimeUnitAmount(0.0, TimeUnit.HOUR), 755 new TimeUnitAmount(0.0, TimeUnit.MINUTE), 756 new TimeUnitAmount(17.0, TimeUnit.SECOND)}; 757 TimeUnitAmount[] _6h_56_92m = { 758 new TimeUnitAmount(6.0, TimeUnit.HOUR), 759 new TimeUnitAmount(56.92, TimeUnit.MINUTE)}; 760 TimeUnitAmount[] _3h_4s_5m = { 761 new TimeUnitAmount(3.0, TimeUnit.HOUR), 762 new TimeUnitAmount(4.0, TimeUnit.SECOND), 763 new TimeUnitAmount(5.0, TimeUnit.MINUTE)}; 764 TimeUnitAmount[] _6_7h_56_92m = { 765 new TimeUnitAmount(6.7, TimeUnit.HOUR), 766 new TimeUnitAmount(56.92, TimeUnit.MINUTE)}; 767 TimeUnitAmount[] _3h_5h = { 768 new TimeUnitAmount(3.0, TimeUnit.HOUR), 769 new TimeUnitAmount(5.0, TimeUnit.HOUR)}; 770 771 Object[][] fullData = { 772 {_1m_59_9996s, "1 minute, 59.9996 seconds"}, 773 {_19m, "19 minutes"}, 774 {_1h_23_5s, "1 hour, 23.5 seconds"}, 775 {_1h_23_5m, "1 hour, 23.5 minutes"}, 776 {_1h_0m_23s, "1 hour, 0 minutes, 23 seconds"}, 777 {_2y_5M_3w_4d, "2 years, 5 months, 3 weeks, 4 days"}}; 778 Object[][] abbrevData = { 779 {_1m_59_9996s, "1 min, 59.9996 sec"}, 780 {_19m, "19 min"}, 781 {_1h_23_5s, "1 hr, 23.5 sec"}, 782 {_1h_23_5m, "1 hr, 23.5 min"}, 783 {_1h_0m_23s, "1 hr, 0 min, 23 sec"}, 784 {_2y_5M_3w_4d, "2 yrs, 5 mths, 3 wks, 4 days"}}; 785 Object[][] narrowData = { 786 {_1m_59_9996s, "1m 59.9996s"}, 787 {_19m, "19m"}, 788 {_1h_23_5s, "1h 23.5s"}, 789 {_1h_23_5m, "1h 23.5m"}, 790 {_1h_0m_23s, "1h 0m 23s"}, 791 {_2y_5M_3w_4d, "2y 5m 3w 4d"}}; 792 793 794 Object[][] numericData = { 795 {_1m_59_9996s, "1:59.9996"}, 796 {_19m, "19m"}, 797 {_1h_23_5s, "1:00:23.5"}, 798 {_1h_0m_23s, "1:00:23"}, 799 {_1h_23_5m, "1:23.5"}, 800 {_5h_17m, "5:17"}, 801 {_neg5h_17m, "-5h 17m"}, 802 {_19m_28s, "19:28"}, 803 {_2y_5M_3w_4d, "2y 5m 3w 4d"}, 804 {_0h_0m_9s, "0:00:09"}, 805 {_6h_56_92m, "6:56.92"}, 806 {_6_7h_56_92m, "6:56.92"}, 807 {_3h_4s_5m, "3h 4s 5m"}, 808 {_3h_5h, "3h 5h"}}; 809 Object[][] fullDataDe = { 810 {_1m_59_9996s, "1 Minute und 59,9996 Sekunden"}, 811 {_19m, "19 Minuten"}, 812 {_1h_23_5s, "1 Stunde und 23,5 Sekunden"}, 813 {_1h_23_5m, "1 Stunde und 23,5 Minuten"}, 814 {_1h_0m_23s, "1 Stunde, 0 Minuten und 23 Sekunden"}, 815 {_2y_5M_3w_4d, "2 Jahre, 5 Monate, 3 Wochen und 4 Tage"}}; 816 Object[][] numericDataDe = { 817 {_1m_59_9996s, "1:59,9996"}, 818 {_19m, "19 Min."}, 819 {_1h_23_5s, "1:00:23,5"}, 820 {_1h_0m_23s, "1:00:23"}, 821 {_1h_23_5m, "1:23,5"}, 822 {_5h_17m, "5:17"}, 823 {_19m_28s, "19:28"}, 824 {_2y_5M_3w_4d, "2 J, 5 M, 3 W und 4 T"}, 825 {_0h_0m_17s, "0:00:17"}, 826 {_6h_56_92m, "6:56,92"}, 827 {_3h_5h, "3 Std., 5 Std."}}; 828 829 NumberFormat nf = NumberFormat.getNumberInstance(ULocale.ENGLISH); 830 nf.setMaximumFractionDigits(4); 831 MeasureFormat mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.WIDE, nf); 832 verifyFormatPeriod("en FULL", mf, fullData); 833 mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.SHORT, nf); 834 verifyFormatPeriod("en SHORT", mf, abbrevData); 835 mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.NARROW, nf); 836 verifyFormatPeriod("en NARROW", mf, narrowData); 837 mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.NUMERIC, nf); 838 verifyFormatPeriod("en NUMERIC", mf, numericData); 839 840 nf = NumberFormat.getNumberInstance(ULocale.GERMAN); 841 nf.setMaximumFractionDigits(4); 842 mf = MeasureFormat.getInstance(ULocale.GERMAN, FormatWidth.WIDE, nf); 843 verifyFormatPeriod("de FULL", mf, fullDataDe); 844 mf = MeasureFormat.getInstance(ULocale.GERMAN, FormatWidth.NUMERIC, nf); 845 verifyFormatPeriod("de NUMERIC", mf, numericDataDe); 846 847 // Same tests, with Java Locale 848 nf = NumberFormat.getNumberInstance(Locale.GERMAN); 849 nf.setMaximumFractionDigits(4); 850 mf = MeasureFormat.getInstance(Locale.GERMAN, FormatWidth.WIDE, nf); 851 verifyFormatPeriod("de FULL(Java Locale)", mf, fullDataDe); 852 mf = MeasureFormat.getInstance(Locale.GERMAN, FormatWidth.NUMERIC, nf); 853 verifyFormatPeriod("de NUMERIC(Java Locale)", mf, numericDataDe); 854 855 } 856 857 private void verifyFormatPeriod(String desc, MeasureFormat mf, Object[][] testData) { 858 StringBuilder builder = new StringBuilder(); 859 boolean failure = false; 860 for (Object[] testCase : testData) { 861 String actual = mf.format((Measure[]) testCase[0]); 862 if (!testCase[1].equals(actual)) { 863 builder.append(String.format("%s: Expected: '%s', got: '%s'\n", desc, testCase[1], actual)); 864 failure = true; 865 } 866 } 867 if (failure) { 868 errln(builder.toString()); 869 } 870 } 871 872 public void Test10219FractionalPlurals() { 873 double[] values = {1.588, 1.011}; 874 String[][] expected = { 875 {"1 minute", "1.5 minutes", "1.58 minutes"}, 876 {"1 minute", "1.0 minutes", "1.01 minutes"} 877 }; 878 for (int j = 0; j < values.length; j++) { 879 for (int i = 0; i < expected[j].length; i++) { 880 NumberFormat nf = NumberFormat.getNumberInstance(ULocale.ENGLISH); 881 nf.setRoundingMode(BigDecimal.ROUND_DOWN); 882 nf.setMinimumFractionDigits(i); 883 nf.setMaximumFractionDigits(i); 884 MeasureFormat mf = MeasureFormat.getInstance( 885 ULocale.ENGLISH, FormatWidth.WIDE, nf); 886 assertEquals("Test10219", expected[j][i], mf.format(new Measure(values[j], MeasureUnit.MINUTE))); 887 } 888 } 889 } 890 891 public void TestGreek() { 892 String[] locales = {"el_GR", "el"}; 893 final MeasureUnit[] units = new MeasureUnit[]{ 894 MeasureUnit.SECOND, 895 MeasureUnit.MINUTE, 896 MeasureUnit.HOUR, 897 MeasureUnit.DAY, 898 MeasureUnit.WEEK, 899 MeasureUnit.MONTH, 900 MeasureUnit.YEAR}; 901 FormatWidth[] styles = new FormatWidth[] {FormatWidth.WIDE, FormatWidth.SHORT}; 902 int[] numbers = new int[] {1, 7}; 903 String[] expected = { 904 // "el_GR" 1 wide 905 "1 δευτερόλεπτο", 906 "1 λεπτό", 907 "1 ώρα", 908 "1 ημέρα", 909 "1 εβδομάδα", 910 "1 μήνας", 911 "1 έτος", 912 // "el_GR" 1 short 913 "1 δευτ.", 914 "1 λεπ.", 915 "1 ώρα", 916 "1 ημέρα", 917 "1 εβδ.", 918 "1 μήν.", 919 "1 έτ.", // year (one) 920 // "el_GR" 7 wide 921 "7 δευτερόλεπτα", 922 "7 λεπτά", 923 "7 ώρες", 924 "7 ημέρες", 925 "7 εβδομάδες", 926 "7 μήνες", 927 "7 έτη", 928 // "el_GR" 7 short 929 "7 δευτ.", 930 "7 λεπ.", 931 "7 ώρ.", // hour (other) 932 "7 ημέρες", 933 "7 εβδ.", 934 "7 μήν.", 935 "7 έτ.", // year (other) 936 // "el" 1 wide 937 "1 δευτερόλεπτο", 938 "1 λεπτό", 939 "1 ώρα", 940 "1 ημέρα", 941 "1 εβδομάδα", 942 "1 μήνας", 943 "1 έτος", 944 // "el" 1 short 945 "1 δευτ.", 946 "1 λεπ.", 947 "1 ώρα", 948 "1 ημέρα", 949 "1 εβδ.", 950 "1 μήν.", 951 "1 έτ.", // year (one) 952 // "el" 7 wide 953 "7 δευτερόλεπτα", 954 "7 λεπτά", 955 "7 ώρες", 956 "7 ημέρες", 957 "7 εβδομάδες", 958 "7 μήνες", 959 "7 έτη", 960 // "el" 7 short 961 "7 δευτ.", 962 "7 λεπ.", 963 "7 ώρ.", // hour (other) 964 "7 ημέρες", 965 "7 εβδ.", 966 "7 μήν.", 967 "7 έτ."}; // year (other 968 int counter = 0; 969 String formatted; 970 for ( int locIndex = 0; locIndex < locales.length; ++locIndex ) { 971 for( int numIndex = 0; numIndex < numbers.length; ++numIndex ) { 972 for ( int styleIndex = 0; styleIndex < styles.length; ++styleIndex ) { 973 for ( int unitIndex = 0; unitIndex < units.length; ++unitIndex ) { 974 Measure m = new Measure(numbers[numIndex], units[unitIndex]); 975 MeasureFormat fmt = MeasureFormat.getInstance(new ULocale(locales[locIndex]), styles[styleIndex]); 976 formatted = fmt.format(m); 977 assertEquals( 978 "locale: " + locales[locIndex] 979 + ", style: " + styles[styleIndex] 980 + ", units: " + units[unitIndex] 981 + ", value: " + numbers[numIndex], 982 expected[counter], formatted); 983 ++counter; 984 } 985 } 986 } 987 } 988 } 989 990 public void testAUnit() { 991 String lastType = null; 992 for (MeasureUnit expected : MeasureUnit.getAvailable()) { 993 String type = expected.getType(); 994 String code = expected.getSubtype(); 995 if (!type.equals(lastType)) { 996 logln(type); 997 lastType = type; 998 } 999 MeasureUnit actual = MeasureUnit.internalGetInstance(type, code); 1000 assertSame("Identity check", expected, actual); 1001 } 1002 } 1003 1004 public void testFormatSingleArg() { 1005 MeasureFormat mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.WIDE); 1006 assertEquals("", "5 meters", mf.format(new Measure(5, MeasureUnit.METER))); 1007 } 1008 1009 public void testFormatMeasuresZeroArg() { 1010 MeasureFormat mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.WIDE); 1011 assertEquals("", "", mf.formatMeasures()); 1012 } 1013 1014 public void testFormatMeasuresOneArg() { 1015 MeasureFormat mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.WIDE); 1016 assertEquals("", "5 meters", mf.formatMeasures(new Measure(5, MeasureUnit.METER))); 1017 } 1018 1019 1020 1021 public void testMultiples() { 1022 ULocale russia = new ULocale("ru"); 1023 Object[][] data = new Object[][] { 1024 {ULocale.ENGLISH, FormatWidth.WIDE, "2 miles, 1 foot, 2.3 inches"}, 1025 {ULocale.ENGLISH, FormatWidth.SHORT, "2 mi, 1 ft, 2.3 in"}, 1026 {ULocale.ENGLISH, FormatWidth.NARROW, "2mi 1\u2032 2.3\u2033"}, 1027 {russia, FormatWidth.WIDE, "2 \u043C\u0438\u043B\u0438 1 \u0444\u0443\u0442 \u0438 2,3 \u0434\u044E\u0439\u043C\u0430"}, 1028 {russia, FormatWidth.SHORT, "2 \u043C\u0438\u043B\u0438 1 \u0444\u0443\u0442 \u0438 2,3 \u0434\u044E\u0439\u043C."}, 1029 {russia, FormatWidth.NARROW, "2 \u043C\u0438\u043B\u044C 1 \u0444\u0443\u0442 2,3 \u0434\u044E\u0439\u043C\u0430"}, 1030 }; 1031 for (Object[] row : data) { 1032 MeasureFormat mf = MeasureFormat.getInstance( 1033 (ULocale) row[0], (FormatWidth) row[1]); 1034 assertEquals( 1035 "testMultiples", 1036 row[2], 1037 mf.formatMeasures( 1038 new Measure(2, MeasureUnit.MILE), 1039 new Measure(1, MeasureUnit.FOOT), 1040 new Measure(2.3, MeasureUnit.INCH))); 1041 } 1042 } 1043 1044 public void testSimplePer() { 1045 Object DONT_CARE = null; 1046 Object[][] data = new Object[][] { 1047 // per unit pattern 1048 {FormatWidth.WIDE, 1.0, MeasureUnit.SECOND, "1 pound per second", DONT_CARE, 0, 0}, 1049 {FormatWidth.WIDE, 2.0, MeasureUnit.SECOND, "2 pounds per second", DONT_CARE, 0, 0}, 1050 // compound pattern 1051 {FormatWidth.WIDE, 1.0, MeasureUnit.MINUTE, "1 pound per minute", DONT_CARE, 0, 0}, 1052 {FormatWidth.WIDE, 2.0, MeasureUnit.MINUTE, "2 pounds per minute", DONT_CARE, 0, 0}, 1053 // per unit 1054 {FormatWidth.SHORT, 1.0, MeasureUnit.SECOND, "1 lb/s", DONT_CARE, 0, 0}, 1055 {FormatWidth.SHORT, 2.0, MeasureUnit.SECOND, "2 lb/s", DONT_CARE, 0, 0}, 1056 // compound 1057 {FormatWidth.SHORT, 1.0, MeasureUnit.MINUTE, "1 lb/min", DONT_CARE, 0, 0}, 1058 {FormatWidth.SHORT, 2.0, MeasureUnit.MINUTE, "2 lb/min", DONT_CARE, 0, 0}, 1059 // per unit 1060 {FormatWidth.NARROW, 1.0, MeasureUnit.SECOND, "1#/s", DONT_CARE, 0, 0}, 1061 {FormatWidth.NARROW, 2.0, MeasureUnit.SECOND, "2#/s", DONT_CARE, 0, 0}, 1062 // compound 1063 {FormatWidth.NARROW, 1.0, MeasureUnit.MINUTE, "1#/min", DONT_CARE, 0, 0}, 1064 {FormatWidth.NARROW, 2.0, MeasureUnit.MINUTE, "2#/min", DONT_CARE, 0, 0}, 1065 // field positions 1066 {FormatWidth.SHORT, 23.3, MeasureUnit.SECOND, "23.3 lb/s", NumberFormat.Field.DECIMAL_SEPARATOR, 2, 3}, 1067 {FormatWidth.SHORT, 23.3, MeasureUnit.SECOND, "23.3 lb/s", NumberFormat.Field.INTEGER, 0, 2}, 1068 {FormatWidth.SHORT, 23.3, MeasureUnit.MINUTE, "23.3 lb/min", NumberFormat.Field.DECIMAL_SEPARATOR, 2, 3}, 1069 {FormatWidth.SHORT, 23.3, MeasureUnit.MINUTE, "23.3 lb/min", NumberFormat.Field.INTEGER, 0, 2}, 1070 1071 }; 1072 1073 for (Object[] row : data) { 1074 FormatWidth formatWidth = (FormatWidth) row[0]; 1075 Number amount = (Number) row[1]; 1076 MeasureUnit perUnit = (MeasureUnit) row[2]; 1077 String expected = row[3].toString(); 1078 NumberFormat.Field field = (NumberFormat.Field) row[4]; 1079 int startOffset = ((Integer) row[5]).intValue(); 1080 int endOffset = ((Integer) row[6]).intValue(); 1081 MeasureFormat mf = MeasureFormat.getInstance( 1082 ULocale.ENGLISH, formatWidth); 1083 FieldPosition pos = field != null ? new FieldPosition(field) : new FieldPosition(0); 1084 String prefix = "Prefix: "; 1085 assertEquals( 1086 "", 1087 prefix + expected, 1088 mf.formatMeasurePerUnit( 1089 new Measure(amount, MeasureUnit.POUND), 1090 perUnit, 1091 new StringBuilder(prefix), 1092 pos).toString()); 1093 if (field != DONT_CARE) { 1094 assertEquals("startOffset", startOffset, pos.getBeginIndex() - prefix.length()); 1095 assertEquals("endOffset", endOffset, pos.getEndIndex() - prefix.length()); 1096 } 1097 } 1098 } 1099 1100 public void testNumeratorPlurals() { 1101 ULocale polish = new ULocale("pl"); 1102 Object[][] data = new Object[][] { 1103 {1, "1 stopa na sekundę"}, 1104 {2, "2 stopy na sekundę"}, 1105 {5, "5 stóp na sekundę"}, 1106 {1.5, "1,5 stopy na sekundę"}}; 1107 1108 for (Object[] row : data) { 1109 MeasureFormat mf = MeasureFormat.getInstance(polish, FormatWidth.WIDE); 1110 assertEquals( 1111 "", 1112 row[1], 1113 mf.formatMeasurePerUnit( 1114 new Measure((Number) row[0], MeasureUnit.FOOT), 1115 MeasureUnit.SECOND, 1116 new StringBuilder(), 1117 new FieldPosition(0)).toString()); 1118 } 1119 } 1120 1121 public void testGram() { 1122 MeasureFormat mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.SHORT); 1123 assertEquals( 1124 "testGram", 1125 "1 g", 1126 mf.format(new Measure(1, MeasureUnit.GRAM))); 1127 assertEquals( 1128 "testGram", 1129 "1 G", 1130 mf.format(new Measure(1, MeasureUnit.G_FORCE))); 1131 } 1132 1133 public void testCurrencies() { 1134 Measure USD_1 = new Measure(1.0, Currency.getInstance("USD")); 1135 Measure USD_2 = new Measure(2.0, Currency.getInstance("USD")); 1136 Measure USD_NEG_1 = new Measure(-1.0, Currency.getInstance("USD")); 1137 MeasureFormat mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.WIDE); 1138 assertEquals("Wide currency", "-1.00 US dollars", mf.format(USD_NEG_1)); 1139 assertEquals("Wide currency", "1.00 US dollars", mf.format(USD_1)); 1140 assertEquals("Wide currency", "2.00 US dollars", mf.format(USD_2)); 1141 mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.SHORT); 1142 assertEquals("short currency", "-USD1.00", mf.format(USD_NEG_1)); 1143 assertEquals("short currency", "USD1.00", mf.format(USD_1)); 1144 assertEquals("short currency", "USD2.00", mf.format(USD_2)); 1145 mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.NARROW); 1146 assertEquals("narrow currency", "-$1.00", mf.format(USD_NEG_1)); 1147 assertEquals("narrow currency", "$1.00", mf.format(USD_1)); 1148 assertEquals("narrow currency", "$2.00", mf.format(USD_2)); 1149 mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.NUMERIC); 1150 assertEquals("numeric currency", "-$1.00", mf.format(USD_NEG_1)); 1151 assertEquals("numeric currency", "$1.00", mf.format(USD_1)); 1152 assertEquals("numeric currency", "$2.00", mf.format(USD_2)); 1153 1154 mf = MeasureFormat.getInstance(ULocale.JAPAN, FormatWidth.WIDE); 1155 assertEquals("Wide currency", "-1.00\u7C73\u30C9\u30EB", mf.format(USD_NEG_1)); 1156 assertEquals("Wide currency", "1.00\u7C73\u30C9\u30EB", mf.format(USD_1)); 1157 assertEquals("Wide currency", "2.00\u7C73\u30C9\u30EB", mf.format(USD_2)); 1158 } 1159 1160 public void testFieldPosition() { 1161 MeasureFormat fmt = MeasureFormat.getInstance( 1162 ULocale.ENGLISH, FormatWidth.SHORT); 1163 FieldPosition pos = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR); 1164 fmt.format(new Measure(43.5, MeasureUnit.FOOT), new StringBuffer("123456: "), pos); 1165 assertEquals("beginIndex", 10, pos.getBeginIndex()); 1166 assertEquals("endIndex", 11, pos.getEndIndex()); 1167 1168 pos = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR); 1169 fmt.format(new Measure(43, MeasureUnit.FOOT), new StringBuffer(), pos); 1170 assertEquals("beginIndex", 0, pos.getBeginIndex()); 1171 assertEquals("endIndex", 0, pos.getEndIndex()); 1172 } 1173 1174 public void testFieldPositionMultiple() { 1175 MeasureFormat fmt = MeasureFormat.getInstance( 1176 ULocale.ENGLISH, FormatWidth.SHORT); 1177 FieldPosition pos = new FieldPosition(NumberFormat.Field.INTEGER); 1178 String result = fmt.formatMeasures( 1179 new StringBuilder(), 1180 pos, 1181 new Measure(354, MeasureUnit.METER), 1182 new Measure(23, MeasureUnit.CENTIMETER)).toString(); 1183 assertEquals("result", "354 m, 23 cm", result); 1184 1185 // According to javadocs for {@link Format#format} FieldPosition is set to 1186 // beginning and end of first such field encountered instead of the last 1187 // such field encountered. 1188 assertEquals("beginIndex", 0, pos.getBeginIndex()); 1189 assertEquals("endIndex", 3, pos.getEndIndex()); 1190 1191 pos = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR); 1192 result = fmt.formatMeasures( 1193 new StringBuilder("123456: "), 1194 pos, 1195 new Measure(354, MeasureUnit.METER), 1196 new Measure(23, MeasureUnit.CENTIMETER), 1197 new Measure(5.4, MeasureUnit.MILLIMETER)).toString(); 1198 assertEquals("result", "123456: 354 m, 23 cm, 5.4 mm", result); 1199 assertEquals("beginIndex", 23, pos.getBeginIndex()); 1200 assertEquals("endIndex", 24, pos.getEndIndex()); 1201 1202 result = fmt.formatMeasures( 1203 new StringBuilder(), 1204 pos, 1205 new Measure(3, MeasureUnit.METER), 1206 new Measure(23, MeasureUnit.CENTIMETER), 1207 new Measure(5.4, MeasureUnit.MILLIMETER)).toString(); 1208 assertEquals("result", "3 m, 23 cm, 5.4 mm", result); 1209 assertEquals("beginIndex", 13, pos.getBeginIndex()); 1210 assertEquals("endIndex", 14, pos.getEndIndex()); 1211 1212 pos = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR); 1213 result = fmt.formatMeasures( 1214 new StringBuilder("123456: "), 1215 pos, 1216 new Measure(3, MeasureUnit.METER), 1217 new Measure(23, MeasureUnit.CENTIMETER), 1218 new Measure(5, MeasureUnit.MILLIMETER)).toString(); 1219 assertEquals("result", "123456: 3 m, 23 cm, 5 mm", result); 1220 assertEquals("beginIndex", 0, pos.getBeginIndex()); 1221 assertEquals("endIndex", 0, pos.getEndIndex()); 1222 1223 pos = new FieldPosition(NumberFormat.Field.INTEGER); 1224 result = fmt.formatMeasures( 1225 new StringBuilder("123456: "), 1226 pos, 1227 new Measure(57, MeasureUnit.MILLIMETER)).toString(); 1228 assertEquals("result", "123456: 57 mm", result); 1229 assertEquals("beginIndex", 8, pos.getBeginIndex()); 1230 assertEquals("endIndex", 10, pos.getEndIndex()); 1231 1232 } 1233 1234 public void testOldFormatWithList() { 1235 List<Measure> measures = new ArrayList<Measure>(2); 1236 measures.add(new Measure(5, MeasureUnit.ACRE)); 1237 measures.add(new Measure(3000, MeasureUnit.SQUARE_FOOT)); 1238 MeasureFormat fmt = MeasureFormat.getInstance( 1239 ULocale.ENGLISH, FormatWidth.WIDE); 1240 assertEquals("", "5 acres, 3,000 square feet", fmt.format(measures)); 1241 assertEquals("", "5 acres", fmt.format(measures.subList(0, 1))); 1242 List<String> badList = new ArrayList<String>(); 1243 badList.add("be"); 1244 badList.add("you"); 1245 try { 1246 fmt.format(badList); 1247 fail("Expected IllegalArgumentException."); 1248 } catch (IllegalArgumentException expected) { 1249 // Expected 1250 } 1251 } 1252 1253 public void testOldFormatWithArray() { 1254 Measure[] measures = new Measure[] { 1255 new Measure(5, MeasureUnit.ACRE), 1256 new Measure(3000, MeasureUnit.SQUARE_FOOT), 1257 }; 1258 MeasureFormat fmt = MeasureFormat.getInstance( 1259 ULocale.ENGLISH, FormatWidth.WIDE); 1260 assertEquals("", "5 acres, 3,000 square feet", fmt.format(measures)); 1261 } 1262 1263 public void testOldFormatBadArg() { 1264 MeasureFormat fmt = MeasureFormat.getInstance( 1265 ULocale.ENGLISH, FormatWidth.WIDE); 1266 try { 1267 fmt.format("be"); 1268 fail("Expected IllegalArgumentExceptino."); 1269 } catch (IllegalArgumentException e) { 1270 // Expected 1271 } 1272 } 1273 1274 public void testUnitPerUnitResolution() { 1275 // Ticket 11274 1276 MeasureFormat fmt = MeasureFormat.getInstance(Locale.ENGLISH, FormatWidth.SHORT); 1277 1278 // This fails unless we resolve to MeasureUnit.POUND_PER_SQUARE_INCH 1279 assertEquals("", "50 psi", 1280 fmt.formatMeasurePerUnit( 1281 new Measure(50, MeasureUnit.POUND), 1282 MeasureUnit.SQUARE_INCH, 1283 new StringBuilder(), 1284 new FieldPosition(0)).toString()); 1285 } 1286 1287 public void testEqHashCode() { 1288 MeasureFormat mf = MeasureFormat.getInstance(ULocale.CANADA, FormatWidth.SHORT); 1289 MeasureFormat mfeq = MeasureFormat.getInstance(ULocale.CANADA, FormatWidth.SHORT); 1290 MeasureFormat mfne = MeasureFormat.getInstance(ULocale.CANADA, FormatWidth.WIDE); 1291 MeasureFormat mfne2 = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.SHORT); 1292 verifyEqualsHashCode(mf, mfeq, mfne); 1293 verifyEqualsHashCode(mf, mfeq, mfne2); 1294 } 1295 1296 public void testEqHashCodeOfMeasure() { 1297 Measure _3feetDouble = new Measure(3.0, MeasureUnit.FOOT); 1298 Measure _3feetInt = new Measure(3, MeasureUnit.FOOT); 1299 Measure _4feetInt = new Measure(4, MeasureUnit.FOOT); 1300 verifyEqualsHashCode(_3feetDouble, _3feetInt, _4feetInt); 1301 } 1302 1303 public void testGetLocale() { 1304 MeasureFormat mf = MeasureFormat.getInstance(ULocale.GERMAN, FormatWidth.SHORT); 1305 assertEquals("", ULocale.GERMAN, mf.getLocale(ULocale.VALID_LOCALE)); 1306 } 1307 1308 public void TestSerial() { 1309 checkStreamingEquality(MeasureUnit.CELSIUS); 1310 checkStreamingEquality(MeasureFormat.getInstance(ULocale.FRANCE, FormatWidth.NARROW)); 1311 checkStreamingEquality(Currency.getInstance("EUR")); 1312 checkStreamingEquality(MeasureFormat.getInstance(ULocale.GERMAN, FormatWidth.SHORT)); 1313 checkStreamingEquality(MeasureFormat.getCurrencyFormat(ULocale.ITALIAN)); 1314 } 1315 1316 public void TestSerialFormatWidthEnum() { 1317 // FormatWidth enum values must map to the same ordinal values for all time in order for 1318 // serialization to work. 1319 assertEquals("FormatWidth.WIDE", 0, FormatWidth.WIDE.ordinal()); 1320 assertEquals("FormatWidth.SHORT", 1, FormatWidth.SHORT.ordinal()); 1321 assertEquals("FormatWidth.NARROW", 2, FormatWidth.NARROW.ordinal()); 1322 assertEquals("FormatWidth.NUMERIC", 3, FormatWidth.NUMERIC.ordinal()); 1323 } 1324 1325 public void testCurrencyFormatStandInForMeasureFormat() { 1326 MeasureFormat mf = MeasureFormat.getCurrencyFormat(ULocale.ENGLISH); 1327 assertEquals( 1328 "70 feet, 5.3 inches", 1329 "70 feet, 5.3 inches", 1330 mf.formatMeasures( 1331 new Measure(70, MeasureUnit.FOOT), 1332 new Measure(5.3, MeasureUnit.INCH))); 1333 assertEquals("getLocale", ULocale.ENGLISH, mf.getLocale()); 1334 assertEquals("getNumberFormat", ULocale.ENGLISH, mf.getNumberFormat().getLocale(ULocale.VALID_LOCALE)); 1335 assertEquals("getWidth", MeasureFormat.FormatWidth.WIDE, mf.getWidth()); 1336 } 1337 1338 public void testCurrencyFormatLocale() { 1339 MeasureFormat mfu = MeasureFormat.getCurrencyFormat(ULocale.FRANCE); 1340 MeasureFormat mfj = MeasureFormat.getCurrencyFormat(Locale.FRANCE); 1341 1342 assertEquals("getCurrencyFormat ULocale/Locale", mfu, mfj); 1343 } 1344 1345 public void testDoubleZero() { 1346 ULocale en = new ULocale("en"); 1347 NumberFormat nf = NumberFormat.getInstance(en); 1348 nf.setMinimumFractionDigits(2); 1349 nf.setMaximumFractionDigits(2); 1350 MeasureFormat mf = MeasureFormat.getInstance(en, FormatWidth.WIDE, nf); 1351 assertEquals( 1352 "Positive Rounding", 1353 "4 hours, 23 minutes, 16.00 seconds", 1354 mf.formatMeasures( 1355 new Measure(4.7, MeasureUnit.HOUR), 1356 new Measure(23, MeasureUnit.MINUTE), 1357 new Measure(16, MeasureUnit.SECOND))); 1358 assertEquals( 1359 "Negative Rounding", 1360 "-4 hours, 23 minutes, 16.00 seconds", 1361 mf.formatMeasures( 1362 new Measure(-4.7, MeasureUnit.HOUR), 1363 new Measure(23, MeasureUnit.MINUTE), 1364 new Measure(16, MeasureUnit.SECOND))); 1365 1366 } 1367 1368 public void testIndividualPluralFallback() { 1369 // See ticket #11986 "incomplete fallback in MeasureFormat". 1370 // In CLDR 28, fr_CA temperature-generic/short has only the "one" form, 1371 // and falls back to fr for the "other" form. 1372 MeasureFormat mf = MeasureFormat.getInstance(new ULocale("fr_CA"), FormatWidth.SHORT); 1373 Measure twoDeg = new Measure(2, MeasureUnit.GENERIC_TEMPERATURE); 1374 assertEquals("2 deg temp in fr_CA", "2°", mf.format(twoDeg)); 1375 } 1376 1377 // DO NOT DELETE THIS FUNCTION! It may appear as dead code, but we use this to generate code 1378 // for MeasureFormat during the release process. 1379 static Map<MeasureUnit, Pair<MeasureUnit, MeasureUnit>> getUnitsToPerParts() { 1380 TreeMap<String, List<MeasureUnit>> allUnits = getAllUnits(); 1381 Map<MeasureUnit, Pair<String, String>> unitsToPerStrings = 1382 new HashMap<MeasureUnit, Pair<String, String>>(); 1383 Map<String, MeasureUnit> namesToUnits = new HashMap<String, MeasureUnit>(); 1384 for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) { 1385 String type = entry.getKey(); 1386 // Currency types are always atomic units, so we can skip these 1387 if (type.equals("currency")) { 1388 continue; 1389 } 1390 for (MeasureUnit unit : entry.getValue()) { 1391 String javaName = toJAVAName(unit); 1392 String[] nameParts = javaName.split("_PER_"); 1393 if (nameParts.length == 1) { 1394 namesToUnits.put(nameParts[0], unit); 1395 } else if (nameParts.length == 2) { 1396 unitsToPerStrings.put(unit, Pair.of(nameParts[0], nameParts[1])); 1397 } 1398 } 1399 } 1400 Map<MeasureUnit, Pair<MeasureUnit, MeasureUnit>> unitsToPerUnits = 1401 new HashMap<MeasureUnit, Pair<MeasureUnit, MeasureUnit>>(); 1402 for (Map.Entry<MeasureUnit, Pair<String, String>> entry : unitsToPerStrings.entrySet()) { 1403 Pair<String, String> perStrings = entry.getValue(); 1404 MeasureUnit unit = namesToUnits.get(perStrings.first); 1405 MeasureUnit perUnit = namesToUnits.get(perStrings.second); 1406 if (unit != null && perUnit != null) { 1407 unitsToPerUnits.put(entry.getKey(), Pair.of(unit, perUnit)); 1408 } 1409 } 1410 return unitsToPerUnits; 1411 } 1412 1413 public void testParseObject() { 1414 MeasureFormat mf = MeasureFormat.getInstance(Locale.GERMAN, FormatWidth.NARROW); 1415 try { 1416 mf.parseObject("3m", null); 1417 fail("MeasureFormat.parseObject(String, ParsePosition) " + 1418 "should throw an UnsupportedOperationException"); 1419 } catch (UnsupportedOperationException expected) { 1420 } 1421 } 1422 1423 // DO NOT DELETE THIS FUNCTION! It may appear as dead code, but we use this to generate code 1424 // for MeasureFormat during the release process. 1425 static void generateCXXHConstants(String thisVersion) { 1426 Map<String, MeasureUnit> seen = new HashMap<String, MeasureUnit>(); 1427 System.out.println(); 1428 TreeMap<String, List<MeasureUnit>> allUnits = getAllUnits(); 1429 for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) { 1430 String type = entry.getKey(); 1431 if (type.equals("currency")) { 1432 continue; 1433 } 1434 for (MeasureUnit unit : entry.getValue()) { 1435 String code = unit.getSubtype(); 1436 String name = toCamelCase(unit); 1437 String javaName = toJAVAName(unit); 1438 checkForDup(seen, name, unit); 1439 if (isDraft(javaName)) { 1440 System.out.println("#ifndef U_HIDE_DRAFT_API"); 1441 } 1442 System.out.println(" /**"); 1443 System.out.println(" * Returns unit of " + type + ": " + code + "."); 1444 System.out.println(" * Caller owns returned value and must free it."); 1445 System.out.println(" * @param status ICU error code."); 1446 if (isDraft(javaName)) { 1447 System.out.println(" * @draft ICU " + getVersion(javaName, thisVersion)); 1448 } else { 1449 System.out.println(" * @stable ICU " + getVersion(javaName, thisVersion)); 1450 } 1451 System.out.println(" */"); 1452 System.out.printf(" static MeasureUnit *create%s(UErrorCode &status);\n\n", name); 1453 if (isDraft(javaName)) { 1454 System.out.println("#endif /* U_HIDE_DRAFT_API */"); 1455 } 1456 } 1457 } 1458 } 1459 1460 private static void checkForDup( 1461 Map<String, MeasureUnit> seen, String name, MeasureUnit unit) { 1462 if (seen.containsKey(name)) { 1463 throw new RuntimeException("\nCollision!!" + unit + ", " + seen.get(name)); 1464 } else { 1465 seen.put(name, unit); 1466 } 1467 } 1468 1469 // DO NOT DELETE THIS FUNCTION! It may appear as dead code, but we use this to generate code 1470 // for MeasureFormat during the release process. 1471 static void updateJAVAVersions(String thisVersion) { 1472 System.out.println(); 1473 Map<String, MeasureUnit> seen = new HashMap<String, MeasureUnit>(); 1474 TreeMap<String, List<MeasureUnit>> allUnits = getAllUnits(); 1475 for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) { 1476 String type = entry.getKey(); 1477 if (type.equals("currency")) { 1478 continue; 1479 } 1480 for (MeasureUnit unit : entry.getValue()) { 1481 String javaName = toJAVAName(unit); 1482 checkForDup(seen, javaName, unit); 1483 if (!JAVA_VERSION_MAP.containsKey(javaName)) { 1484 System.out.printf(" {\"%s\", \"%s\"},\n", javaName, thisVersion); 1485 } 1486 } 1487 } 1488 } 1489 1490 static TreeMap<String, List<MeasureUnit>> getAllUnits() { 1491 TreeMap<String, List<MeasureUnit>> allUnits = new TreeMap<String, List<MeasureUnit>>(); 1492 for (String type : MeasureUnit.getAvailableTypes()) { 1493 ArrayList<MeasureUnit> units = new ArrayList<MeasureUnit>(MeasureUnit.getAvailable(type)); 1494 Collections.sort( 1495 units, 1496 new Comparator<MeasureUnit>() { 1497 1498 public int compare(MeasureUnit o1, MeasureUnit o2) { 1499 return o1.getSubtype().compareTo(o2.getSubtype()); 1500 } 1501 1502 }); 1503 allUnits.put(type, units); 1504 } 1505 return allUnits; 1506 } 1507 1508 // DO NOT DELETE THIS FUNCTION! It may appear as dead code, but we use this to generate code 1509 // for MeasureFormat during the release process. 1510 static void generateCXXConstants() { 1511 System.out.println(""); 1512 TreeMap<String, List<MeasureUnit>> allUnits = getAllUnits(); 1513 1514 System.out.println("static const int32_t gOffsets[] = {"); 1515 int index = 0; 1516 for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) { 1517 System.out.printf(" %d,\n", index); 1518 index += entry.getValue().size(); 1519 } 1520 System.out.printf(" %d\n", index); 1521 System.out.println("};"); 1522 System.out.println(); 1523 System.out.println("static const int32_t gIndexes[] = {"); 1524 index = 0; 1525 for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) { 1526 System.out.printf(" %d,\n", index); 1527 if (!entry.getKey().equals("currency")) { 1528 index += entry.getValue().size(); 1529 } 1530 } 1531 System.out.printf(" %d\n", index); 1532 System.out.println("};"); 1533 System.out.println(); 1534 System.out.println("// Must be sorted alphabetically."); 1535 System.out.println("static const char * const gTypes[] = {"); 1536 boolean first = true; 1537 for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) { 1538 if (!first) { 1539 System.out.println(","); 1540 } 1541 System.out.print(" \"" + entry.getKey() + "\""); 1542 first = false; 1543 } 1544 System.out.println(); 1545 System.out.println("};"); 1546 System.out.println(); 1547 System.out.println("// Must be grouped by type and sorted alphabetically within each type."); 1548 System.out.println("static const char * const gSubTypes[] = {"); 1549 first = true; 1550 int offset = 0; 1551 int typeIdx = 0; 1552 Map<MeasureUnit, Integer> measureUnitToOffset = new HashMap<MeasureUnit, Integer>(); 1553 Map<MeasureUnit, Pair<Integer, Integer>> measureUnitToTypeSubType = 1554 new HashMap<MeasureUnit, Pair<Integer, Integer>>(); 1555 for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) { 1556 int subTypeIdx = 0; 1557 for (MeasureUnit unit : entry.getValue()) { 1558 if (!first) { 1559 System.out.println(","); 1560 } 1561 System.out.print(" \"" + unit.getSubtype() + "\""); 1562 first = false; 1563 measureUnitToOffset.put(unit, offset); 1564 measureUnitToTypeSubType.put(unit, Pair.of(typeIdx, subTypeIdx)); 1565 offset++; 1566 subTypeIdx++; 1567 } 1568 typeIdx++; 1569 } 1570 System.out.println(); 1571 System.out.println("};"); 1572 System.out.println(); 1573 1574 // Build unit per unit offsets to corresponding type sub types sorted by 1575 // unit first and then per unit. 1576 TreeMap<OrderedPair<Integer, Integer>, Pair<Integer, Integer>> unitPerUnitOffsetsToTypeSubType 1577 = new TreeMap<OrderedPair<Integer, Integer>, Pair<Integer, Integer>>(); 1578 for (Map.Entry<MeasureUnit, Pair<MeasureUnit, MeasureUnit>> entry 1579 : getUnitsToPerParts().entrySet()) { 1580 Pair<MeasureUnit, MeasureUnit> unitPerUnit = entry.getValue(); 1581 unitPerUnitOffsetsToTypeSubType.put( 1582 OrderedPair.of( 1583 measureUnitToOffset.get(unitPerUnit.first), 1584 measureUnitToOffset.get(unitPerUnit.second)), 1585 measureUnitToTypeSubType.get(entry.getKey())); 1586 } 1587 1588 System.out.println("// Must be sorted by first value and then second value."); 1589 System.out.println("static int32_t unitPerUnitToSingleUnit[][4] = {"); 1590 first = true; 1591 for (Map.Entry<OrderedPair<Integer, Integer>, Pair<Integer, Integer>> entry 1592 : unitPerUnitOffsetsToTypeSubType.entrySet()) { 1593 if (!first) { 1594 System.out.println(","); 1595 } 1596 first = false; 1597 OrderedPair<Integer, Integer> unitPerUnitOffsets = entry.getKey(); 1598 Pair<Integer, Integer> typeSubType = entry.getValue(); 1599 System.out.printf(" {%d, %d, %d, %d}", 1600 unitPerUnitOffsets.first, 1601 unitPerUnitOffsets.second, 1602 typeSubType.first, 1603 typeSubType.second); 1604 } 1605 System.out.println(); 1606 System.out.println("};"); 1607 System.out.println(); 1608 1609 Map<String, MeasureUnit> seen = new HashMap<String, MeasureUnit>(); 1610 for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) { 1611 1612 String type = entry.getKey(); 1613 if (type.equals("currency")) { 1614 continue; 1615 } 1616 for (MeasureUnit unit : entry.getValue()) { 1617 String name = toCamelCase(unit); 1618 Pair<Integer, Integer> typeSubType = measureUnitToTypeSubType.get(unit); 1619 if (typeSubType == null) { 1620 throw new IllegalStateException(); 1621 } 1622 checkForDup(seen, name, unit); 1623 System.out.printf("MeasureUnit *MeasureUnit::create%s(UErrorCode &status) {\n", name); 1624 System.out.printf(" return MeasureUnit::create(%d, %d, status);\n", 1625 typeSubType.first, typeSubType.second); 1626 System.out.println("}"); 1627 System.out.println(); 1628 } 1629 } 1630 } 1631 1632 private static String toCamelCase(MeasureUnit unit) { 1633 StringBuilder result = new StringBuilder(); 1634 boolean caps = true; 1635 String code = unit.getSubtype(); 1636 int len = code.length(); 1637 for (int i = 0; i < len; i++) { 1638 char ch = code.charAt(i); 1639 if (ch == '-') { 1640 caps = true; 1641 } else if (caps) { 1642 result.append(Character.toUpperCase(ch)); 1643 caps = false; 1644 } else { 1645 result.append(ch); 1646 } 1647 } 1648 return result.toString(); 1649 } 1650 1651 static boolean isTypeHidden(String type) { 1652 return "currency".equals(type); 1653 } 1654 1655 // DO NOT DELETE THIS FUNCTION! It may appear as dead code, but we use this to generate code 1656 // for MeasureFormat during the release process. 1657 static void generateBackwardCompatibilityTest(String version) { 1658 Map<String, MeasureUnit> seen = new HashMap<String, MeasureUnit>(); 1659 System.out.println(); 1660 System.out.printf(" public void TestCompatible%s() {\n", version.replace(".", "_")); 1661 System.out.println(" MeasureUnit[] units = {"); 1662 TreeMap<String, List<MeasureUnit>> allUnits = getAllUnits(); 1663 int count = 0; 1664 for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) { 1665 if (isTypeHidden(entry.getKey())) { 1666 continue; 1667 } 1668 for (MeasureUnit unit : entry.getValue()) { 1669 String javaName = toJAVAName(unit); 1670 checkForDup(seen, javaName, unit); 1671 System.out.printf(" MeasureUnit.%s,\n", javaName); 1672 count++; 1673 } 1674 } 1675 System.out.println(" };"); 1676 System.out.printf(" assertEquals(\"\", %d, units.length);\n", count); 1677 System.out.println(" }"); 1678 } 1679 1680 // DO NOT DELETE THIS FUNCTION! It may appear as dead code, but we use this to generate code 1681 // for MeasureFormat during the release process. 1682 static void generateCXXBackwardCompatibilityTest(String version) { 1683 System.out.println(); 1684 Map<String, MeasureUnit> seen = new HashMap<String, MeasureUnit>(); 1685 System.out.printf("void MeasureFormatTest::TestCompatible%s() {\n", version.replace(".", "_")); 1686 System.out.println(" UErrorCode status = U_ZERO_ERROR;"); 1687 System.out.println(" LocalPointer<MeasureUnit> measureUnit;"); 1688 TreeMap<String, List<MeasureUnit>> allUnits = getAllUnits(); 1689 for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) { 1690 if (isTypeHidden(entry.getKey())) { 1691 continue; 1692 } 1693 for (MeasureUnit unit : entry.getValue()) { 1694 String camelCase = toCamelCase(unit); 1695 checkForDup(seen, camelCase, unit); 1696 System.out.printf(" measureUnit.adoptInstead(MeasureUnit::create%s(status));\n", camelCase); 1697 } 1698 } 1699 System.out.println(" assertSuccess(\"\", status);"); 1700 System.out.println("}"); 1701 } 1702 1703 static String toJAVAName(MeasureUnit unit) { 1704 String code = unit.getSubtype(); 1705 String type = unit.getType(); 1706 String name = code.toUpperCase(Locale.ENGLISH).replace("-", "_"); 1707 if (type.equals("angle")) { 1708 if (code.equals("minute") || code.equals("second")) { 1709 name = "ARC_" + name; 1710 } 1711 } 1712 return name; 1713 } 1714 1715 // DO NOT DELETE THIS FUNCTION! It may appear as dead code, but we use this to generate code 1716 // for MeasureFormat during the release process. 1717 static void generateConstants(String thisVersion) { 1718 System.out.println(); 1719 Map<String, MeasureUnit> seen = new HashMap<String, MeasureUnit>(); 1720 TreeMap<String, List<MeasureUnit>> allUnits = getAllUnits(); 1721 for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) { 1722 String type = entry.getKey(); 1723 if (isTypeHidden(type)) { 1724 continue; 1725 } 1726 for (MeasureUnit unit : entry.getValue()) { 1727 String name = toJAVAName(unit); 1728 String code = unit.getSubtype(); 1729 checkForDup(seen, name, unit); 1730 System.out.println(" /**"); 1731 System.out.println(" * Constant for unit of " + type + 1732 ": " + 1733 code); 1734 // Special case JAVA had old constants for time from before. 1735 if ("duration".equals(type) && TIME_CODES.contains(code)) { 1736 System.out.println(" * @stable ICU 4.0"); 1737 } 1738 else if (isDraft(name)) { 1739 System.out.println(" * @draft ICU " + getVersion(name, thisVersion)); 1740 System.out.println(" * @provisional This API might change or be removed in a future release."); 1741 } else { 1742 System.out.println(" * @stable ICU " + getVersion(name, thisVersion)); 1743 } 1744 System.out.println(" */"); 1745 if ("duration".equals(type) && TIME_CODES.contains(code)) { 1746 System.out.println(" public static final TimeUnit " + name + " = (TimeUnit) MeasureUnit.internalGetInstance(\"" + 1747 type + 1748 "\", \"" + 1749 code + 1750 "\");"); 1751 } else { 1752 System.out.println(" public static final MeasureUnit " + name + " = MeasureUnit.internalGetInstance(\"" + 1753 type + 1754 "\", \"" + 1755 code + 1756 "\");"); 1757 } 1758 System.out.println(); 1759 } 1760 } 1761 System.out.println(" private static HashMap<Pair<MeasureUnit, MeasureUnit>, MeasureUnit>unitPerUnitToSingleUnit ="); 1762 System.out.println(" new HashMap<Pair<MeasureUnit, MeasureUnit>, MeasureUnit>();"); 1763 System.out.println(); 1764 System.out.println(" static {"); 1765 for (Map.Entry<MeasureUnit, Pair<MeasureUnit, MeasureUnit>> unitPerUnitEntry 1766 : getUnitsToPerParts().entrySet()) { 1767 Pair<MeasureUnit, MeasureUnit> unitPerUnit = unitPerUnitEntry.getValue(); 1768 System.out.println(" unitPerUnitToSingleUnit.put(Pair.<MeasureUnit, MeasureUnit>of(MeasureUnit." + toJAVAName(unitPerUnit.first) + ", MeasureUnit." + toJAVAName(unitPerUnit.second) + "), MeasureUnit." + toJAVAName(unitPerUnitEntry.getKey()) + ");"); 1769 } 1770 System.out.println(" }"); 1771 } 1772 1773 private static String getVersion(String javaName, String thisVersion) { 1774 String version = JAVA_VERSION_MAP.get(javaName); 1775 if (version == null) { 1776 return thisVersion; 1777 } 1778 return version; 1779 } 1780 1781 private static boolean isDraft(String javaName) { 1782 String version = JAVA_VERSION_MAP.get(javaName); 1783 if (version == null) { 1784 return true; 1785 } 1786 return DRAFT_VERSION_SET.contains(version); 1787 } 1788 1789 public <T extends Serializable> void checkStreamingEquality(T item) { 1790 try { 1791 ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); 1792 ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteOut); 1793 objectOutputStream.writeObject(item); 1794 objectOutputStream.close(); 1795 byte[] contents = byteOut.toByteArray(); 1796 logln("bytes: " + contents.length + "; " + item.getClass() + ": " + showBytes(contents)); 1797 ByteArrayInputStream byteIn = new ByteArrayInputStream(contents); 1798 ObjectInputStream objectInputStream = new ObjectInputStream(byteIn); 1799 Object obj = objectInputStream.readObject(); 1800 assertEquals("Streamed Object equals ", item, obj); 1801 } catch (IOException e) { 1802 e.printStackTrace(); 1803 assertNull("Test Serialization " + item.getClass(), e); 1804 } catch (ClassNotFoundException e) { 1805 assertNull("Test Serialization " + item.getClass(), e); 1806 } 1807 } 1808 1809 /** 1810 * @param contents 1811 * @return 1812 */ 1813 private String showBytes(byte[] contents) { 1814 StringBuilder b = new StringBuilder('['); 1815 for (int i = 0; i < contents.length; ++i) { 1816 int item = contents[i] & 0xFF; 1817 if (item >= 0x20 && item <= 0x7F) { 1818 b.append((char) item); 1819 } else { 1820 b.append('(').append(Utility.hex(item, 2)).append(')'); 1821 } 1822 } 1823 return b.append(']').toString(); 1824 } 1825 1826 private void verifyEqualsHashCode(Object o, Object eq, Object ne) { 1827 assertEquals("verifyEqualsHashCodeSame", o, o); 1828 assertEquals("verifyEqualsHashCodeEq", o, eq); 1829 assertNotEquals("verifyEqualsHashCodeNe", o, ne); 1830 assertNotEquals("verifyEqualsHashCodeEqTrans", eq, ne); 1831 assertEquals("verifyEqualsHashCodeHashEq", o.hashCode(), eq.hashCode()); 1832 1833 // May be a flaky test, but generally should be true. 1834 // May need to comment this out later. 1835 assertNotEquals("verifyEqualsHashCodeHashNe", o.hashCode(), ne.hashCode()); 1836 } 1837 1838 public static class MeasureUnitHandler implements SerializableTest.Handler 1839 { 1840 public Object[] getTestObjects() 1841 { 1842 MeasureUnit items[] = { 1843 MeasureUnit.CELSIUS, 1844 Currency.getInstance("EUR") 1845 }; 1846 return items; 1847 } 1848 public boolean hasSameBehavior(Object a, Object b) 1849 { 1850 MeasureUnit a1 = (MeasureUnit) a; 1851 MeasureUnit b1 = (MeasureUnit) b; 1852 return a1.getType().equals(b1.getType()) 1853 && a1.getSubtype().equals(b1.getSubtype()); 1854 } 1855 } 1856 1857 public static class MeasureFormatHandler implements SerializableTest.Handler 1858 { 1859 public Object[] getTestObjects() 1860 { 1861 MeasureFormat items[] = { 1862 MeasureFormat.getInstance(ULocale.FRANCE, FormatWidth.SHORT), 1863 MeasureFormat.getInstance( 1864 ULocale.FRANCE, 1865 FormatWidth.WIDE, 1866 NumberFormat.getIntegerInstance(ULocale.CANADA_FRENCH)), 1867 }; 1868 return items; 1869 } 1870 public boolean hasSameBehavior(Object a, Object b) 1871 { 1872 MeasureFormat a1 = (MeasureFormat) a; 1873 MeasureFormat b1 = (MeasureFormat) b; 1874 return a1.getLocale().equals(b1.getLocale()) 1875 && a1.getWidth().equals(b1.getWidth()) 1876 && a1.getNumberFormat().equals(b1.getNumberFormat()) 1877 ; 1878 } 1879 } 1880} 1881