@Test
  public void testOverriddenBuiltinFormat() {
    final Calendar cal = Calendar.getInstance();
    cal.set(2007, Calendar.JANUARY, 23);
    final Object[] args = new Object[] {cal.getTime()};
    final Locale[] availableLocales = DateFormat.getAvailableLocales();
    final Map<String, ? extends FormatFactory> dateRegistry =
        Collections.singletonMap("date", new OverrideShortDateFormatFactory());

    // check the non-overridden builtins:
    checkBuiltInFormat("1: {0,date}", dateRegistry, args, availableLocales);
    checkBuiltInFormat("2: {0,date,medium}", dateRegistry, args, availableLocales);
    checkBuiltInFormat("3: {0,date,long}", dateRegistry, args, availableLocales);
    checkBuiltInFormat("4: {0,date,full}", dateRegistry, args, availableLocales);
    checkBuiltInFormat("5: {0,date,d MMM yy}", dateRegistry, args, availableLocales);

    // check the overridden format:
    for (int i = -1; i < availableLocales.length; i++) {
      final Locale locale = i < 0 ? null : availableLocales[i];
      final MessageFormat dateDefault = createMessageFormat("{0,date}", locale);
      final String pattern = "{0,date,short}";
      final ExtendedMessageFormat dateShort =
          new ExtendedMessageFormat(pattern, locale, dateRegistry);
      assertEquals(
          "overridden date,short format", dateDefault.format(args), dateShort.format(args));
      assertEquals("overridden date,short pattern", pattern, dateShort.toPattern());
    }
  }
  @Test
  public void basicFormats() {

    ExtendedMessageFormat extformat =
        new ExtendedMessageFormat("hello {0, number} xxx {1, date, ddmmyy}", Locale.ENGLISH);
    Object[] params = new Object[] {100000, new Date(0)};
    String out = extformat.format(params);
    Assert.assertEquals(out, "hello 100,000 xxx  010070");

    out =
        ExtendedMessageFormat.format(
            "hello {0, number} '{hello}' xxx {1, date,'a' ddmmyy}", params);
    Assert.assertEquals(out, "hello 100,000 {hello} xxx a 010070");

    extformat = new ExtendedMessageFormat("hello {0, number} xxx {1, date, ddmmyy}");
    out = extformat.format(params);
    Assert.assertEquals(out, "hello 100,000 xxx  010070");

    extformat =
        new ExtendedMessageFormat(
            "hello {0, number} 'aa' {0, date,'dd'dd} {1, date, ddmmyy}",
            (Map<String, FormatFactory>) null);
    out = extformat.format(params);
    Assert.assertEquals(out, "hello 100,000 aa dd01  010070");
  }
 /** Test extended formats. */
 @Test
 public void testExtendedFormats() {
   final String pattern = "Lower: {0,lower} Upper: {1,upper}";
   final ExtendedMessageFormat emf = new ExtendedMessageFormat(pattern, registry);
   assertPatternsEqual("TOPATTERN", pattern, emf.toPattern());
   assertEquals("Lower: foo Upper: BAR", emf.format(new Object[] {"foo", "bar"}));
   assertEquals("Lower: foo Upper: BAR", emf.format(new Object[] {"Foo", "Bar"}));
   assertEquals("Lower: foo Upper: BAR", emf.format(new Object[] {"FOO", "BAR"}));
   assertEquals("Lower: foo Upper: BAR", emf.format(new Object[] {"FOO", "bar"}));
   assertEquals("Lower: foo Upper: BAR", emf.format(new Object[] {"foo", "BAR"}));
 }
  /** Test Bug LANG-948 - Exception while using ExtendedMessageFormat and escaping braces */
  @Test
  public void testEscapedBraces_LANG_948() {
    // message without placeholder because braces are escaped by quotes
    final String pattern = "Message without placeholders '{}'";
    final ExtendedMessageFormat emf = new ExtendedMessageFormat(pattern, registry);
    assertEquals("Message without placeholders {}", emf.format(new Object[] {"DUMMY"}));

    // message with placeholder because quotes are escaped by quotes
    final String pattern2 = "Message with placeholder ''{0}''";
    final ExtendedMessageFormat emf2 = new ExtendedMessageFormat(pattern2, registry);
    assertEquals("Message with placeholder 'DUMMY'", emf2.format(new Object[] {"DUMMY"}));
  }
  /** Test extended and built in formats. */
  @Test
  public void testExtendedAndBuiltInFormats() {
    final Calendar cal = Calendar.getInstance();
    cal.set(2007, Calendar.JANUARY, 23, 18, 33, 05);
    final Object[] args = new Object[] {"John Doe", cal.getTime(), Double.valueOf("12345.67")};
    final String builtinsPattern = "DOB: {1,date,short} Salary: {2,number,currency}";
    final String extendedPattern = "Name: {0,upper} ";
    final String pattern = extendedPattern + builtinsPattern;

    final HashSet<Locale> testLocales = new HashSet<Locale>();
    testLocales.addAll(Arrays.asList(DateFormat.getAvailableLocales()));
    testLocales.retainAll(Arrays.asList(NumberFormat.getAvailableLocales()));
    testLocales.add(null);

    for (final Locale locale : testLocales) {
      final MessageFormat builtins = createMessageFormat(builtinsPattern, locale);
      final String expectedPattern = extendedPattern + builtins.toPattern();
      DateFormat df = null;
      NumberFormat nf = null;
      ExtendedMessageFormat emf = null;
      if (locale == null) {
        df = DateFormat.getDateInstance(DateFormat.SHORT);
        nf = NumberFormat.getCurrencyInstance();
        emf = new ExtendedMessageFormat(pattern, registry);
      } else {
        df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
        nf = NumberFormat.getCurrencyInstance(locale);
        emf = new ExtendedMessageFormat(pattern, locale, registry);
      }
      final StringBuilder expected = new StringBuilder();
      expected.append("Name: ");
      expected.append(args[0].toString().toUpperCase());
      expected.append(" DOB: ");
      expected.append(df.format(args[1]));
      expected.append(" Salary: ");
      expected.append(nf.format(args[2]));
      assertPatternsEqual(
          "pattern comparison for locale " + locale, expectedPattern, emf.toPattern());
      assertEquals(String.valueOf(locale), expected.toString(), emf.format(args));
    }
  }
 /**
  * Create an ExtendedMessageFormat for the specified pattern and locale and check the formated
  * output matches the expected result for the parameters.
  *
  * @param pattern string
  * @param registryUnused map (currently unused)
  * @param args Object[]
  * @param locale Locale
  */
 private void checkBuiltInFormat(
     final String pattern,
     final Map<String, ?> registryUnused,
     final Object[] args,
     final Locale locale) {
   final StringBuilder buffer = new StringBuilder();
   buffer.append("Pattern=[");
   buffer.append(pattern);
   buffer.append("], locale=[");
   buffer.append(locale);
   buffer.append("]");
   final MessageFormat mf = createMessageFormat(pattern, locale);
   // System.out.println(buffer + ", result=[" + mf.format(args) +"]");
   ExtendedMessageFormat emf = null;
   if (locale == null) {
     emf = new ExtendedMessageFormat(pattern);
   } else {
     emf = new ExtendedMessageFormat(pattern, locale);
   }
   assertEquals("format " + buffer.toString(), mf.format(args), emf.format(args));
   assertPatternsEqual("toPattern " + buffer.toString(), mf.toPattern(), emf.toPattern());
 }
 /**
  * Test Bug LANG-917 - IndexOutOfBoundsException and/or infinite loop when using a choice pattern
  */
 @Test
 public void testEmbeddedPatternInChoice() {
   final String pattern = "Hi {0,lower}, got {1,choice,0#none|1#one|1<{1,number}}, {2,upper}!";
   final ExtendedMessageFormat emf = new ExtendedMessageFormat(pattern, registry);
   assertEquals(emf.format(new Object[] {"there", 3, "great"}), "Hi there, got 3, GREAT!");
 }
 /** Test Bug LANG-477 - out of memory error with escaped quote */
 @Test
 public void testEscapedQuote_LANG_477() {
   final String pattern = "it''s a {0,lower} 'test'!";
   final ExtendedMessageFormat emf = new ExtendedMessageFormat(pattern, registry);
   assertEquals("it's a dummy test!", emf.format(new Object[] {"DUMMY"}));
 }
  /** Test equals() and hashcode. */
  @Test
  public void testEqualsHashcode() {
    final Map<String, ? extends FormatFactory> fmtRegistry =
        Collections.singletonMap("testfmt", new LowerCaseFormatFactory());
    final Map<String, ? extends FormatFactory> otherRegitry =
        Collections.singletonMap("testfmt", new UpperCaseFormatFactory());

    final String pattern = "Pattern: {0,testfmt}";
    final ExtendedMessageFormat emf = new ExtendedMessageFormat(pattern, Locale.US, fmtRegistry);

    ExtendedMessageFormat other = null;

    // Same object
    assertTrue("same, equals()", emf.equals(emf));
    assertTrue("same, hashcode()", emf.hashCode() == emf.hashCode());

    // Equal Object
    other = new ExtendedMessageFormat(pattern, Locale.US, fmtRegistry);
    assertTrue("equal, equals()", emf.equals(other));
    assertTrue("equal, hashcode()", emf.hashCode() == other.hashCode());

    // Different Class
    other = new OtherExtendedMessageFormat(pattern, Locale.US, fmtRegistry);
    assertFalse("class, equals()", emf.equals(other));
    assertTrue("class, hashcode()", emf.hashCode() == other.hashCode()); // same hashcode

    // Different pattern
    other = new ExtendedMessageFormat("X" + pattern, Locale.US, fmtRegistry);
    assertFalse("pattern, equals()", emf.equals(other));
    assertFalse("pattern, hashcode()", emf.hashCode() == other.hashCode());

    // Different registry
    other = new ExtendedMessageFormat(pattern, Locale.US, otherRegitry);
    assertFalse("registry, equals()", emf.equals(other));
    assertFalse("registry, hashcode()", emf.hashCode() == other.hashCode());

    // Different Locale
    other = new ExtendedMessageFormat(pattern, Locale.FRANCE, fmtRegistry);
    assertFalse("locale, equals()", emf.equals(other));
    assertTrue("locale, hashcode()", emf.hashCode() == other.hashCode()); // same hashcode
  }