diff --git a/icu4j/main/core/src/main/java/com/ibm/icu/impl/personname/FieldModifierImpl.java b/icu4j/main/core/src/main/java/com/ibm/icu/impl/personname/FieldModifierImpl.java index 34fe76dee44..e8657a9365f 100644 --- a/icu4j/main/core/src/main/java/com/ibm/icu/impl/personname/FieldModifierImpl.java +++ b/icu4j/main/core/src/main/java/com/ibm/icu/impl/personname/FieldModifierImpl.java @@ -36,6 +36,12 @@ abstract class FieldModifierImpl { return NOOP_MODIFIER; case MONOGRAM: return MONOGRAM_MODIFIER; + case GENITIVE: + // no built-in implementation for deriving genitive from nominative; PersonName object must supply + return NOOP_MODIFIER; + case VOCATIVE: + // no built-in implementation for deriving vocative from nominative; PersonName object must supply + return NOOP_MODIFIER; default: throw new IllegalArgumentException("Invalid modifier ID " + modifierID); } @@ -142,7 +148,10 @@ abstract class FieldModifierImpl { } else { result = initialSequenceFormatter.format(result, initialFormatter.format(curInitial)); } - } else if (!Character.isWhitespace(word.charAt(0))) { + } else if (Character.isWhitespace(word.charAt(0))) { + // coalesce a sequence of whitespace characters down to a single space + separator = separator + word.charAt(0); + } else { separator = separator + word; } } diff --git a/icu4j/main/core/src/main/java/com/ibm/icu/text/PersonName.java b/icu4j/main/core/src/main/java/com/ibm/icu/text/PersonName.java index 0d3ec00e924..2c19590cbfe 100644 --- a/icu4j/main/core/src/main/java/com/ibm/icu/text/PersonName.java +++ b/icu4j/main/core/src/main/java/com/ibm/icu/text/PersonName.java @@ -176,7 +176,23 @@ public interface PersonName { * selectively. * @draft ICU 73 */ - INITIAL_CAP("initialCap"); + INITIAL_CAP("initialCap"), + + /** + * Requests the genitive form of the field's contents, if possible. The default implementation + * does nothing, but subclasses of PersonName can override getFieldValue() to produce the genitive + * form (or just add an "xxx-genitive" entry to a SimplePersonName). + * @draft ICU 74 + */ + GENITIVE("genitive"), + + /** + * Requests the vocative form of the field's contents, if possible. The default implementation + * does nothing, but subclasses of PersonName can override getFieldValue() to produce the vocative + * form (or just add an "xxx-vocative" entry to a SimplePersonName). + * @draft ICU 74 + */ + VOCATIVE("vocative"); private final String name; diff --git a/icu4j/main/core/src/test/java/com/ibm/icu/dev/test/format/PersonNameConsistencyTest.java b/icu4j/main/core/src/test/java/com/ibm/icu/dev/test/format/PersonNameConsistencyTest.java index a9da36e612b..95a450dade5 100644 --- a/icu4j/main/core/src/test/java/com/ibm/icu/dev/test/format/PersonNameConsistencyTest.java +++ b/icu4j/main/core/src/test/java/com/ibm/icu/dev/test/format/PersonNameConsistencyTest.java @@ -3,11 +3,7 @@ package com.ibm.icu.dev.test.format; import java.io.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Locale; +import java.util.*; import com.ibm.icu.dev.test.TestFmwk; import com.ibm.icu.dev.test.TestUtil; @@ -34,14 +30,23 @@ public class PersonNameConsistencyTest extends TestFmwk { */ private static boolean RUN_ALL_TESTS = false; + /** + * Change this to true to write log output to stdout (this is a workaround for the fact that + * AbstractTestLog.logln() doesn't currently do anything). + */ + private static boolean VERBOSE_OUTPUT = false; + private static final String DATA_PATH = TestUtil.DATA_PATH + "cldr/personNameTest/"; - static private Collection FILENAMES_TO_SKIP = - Arrays.asList("gaa.txt", "gd.txt", "lv.txt", "syr.txt", "lij.txt"); + private static Map KNOWN_ISSUES = makeKnownIssuesList(); - static private Collection FILENAMES_TO_SKIP_FOR_17028 = - Arrays.asList("yue_Hans.txt", "to.txt", "gl.txt", "ie.txt", "fr.txt", "fr_CA.txt" ); + private static Map makeKnownIssuesList() { + Map knownIssues = new HashMap<>(); + // there are no current locales for which we have known issues + + return knownIssues; + } static List readTestCases() throws Exception { List tests = new ArrayList<>(); InputStream catalogFileStream = TestUtil.class.getResourceAsStream(DATA_PATH + "catalog.txt"); @@ -60,30 +65,10 @@ public class PersonNameConsistencyTest extends TestFmwk { return tests; } - private boolean shouldSkipTest(String filename, String errorMsg) { - if (FILENAMES_TO_SKIP.contains(filename)) { - return true; - } - if (FILENAMES_TO_SKIP_FOR_17028.contains(filename) && - logKnownIssue("ICU-17028", errorMsg)) { - return true; - } - if (filename.equals("my.txt") && RBBITstUtils.skipDictionaryTest()) { - return true; - } - return false; - } - @Test @Parameters(method = "readTestCases") public void TestPersonNames(String filename) throws IOException { - boolean shouldSkip = shouldSkipTest(filename, ""); - - if (shouldSkip && !RUN_ALL_TESTS) { - logln("Skipping " + filename + "..."); - return; - } - + String knownIssue = KNOWN_ISSUES.get(filename); LineNumberReader in = new LineNumberReader(new InputStreamReader(TestUtil.class.getResourceAsStream(DATA_PATH + filename))); String line = null; PersonNameTester tester = new PersonNameTester(filename); @@ -95,7 +80,9 @@ public class PersonNameConsistencyTest extends TestFmwk { } errors = tester.getErrorCount(); } catch (Exception e) { - if (shouldSkip) { + if (knownIssue != null) { + logKnownIssue(knownIssue, "Exception thrown on " + filename + ": " + e.toString()); + } else if (RUN_ALL_TESTS) { logln("Exception thrown on " + filename + ": " + e.toString()); } else { throw e; @@ -103,7 +90,9 @@ public class PersonNameConsistencyTest extends TestFmwk { } if (errors != 0) { - if (shouldSkip) { + if (knownIssue != null) { + logKnownIssue(knownIssue, "Failure in " + filename + ": Found " + errors + " errors."); + } else if (RUN_ALL_TESTS) { logln("Failure in " + filename + ": Found " + errors + " errors."); } else { errln("Failure in " + filename + ": Found " + errors + " errors."); @@ -252,6 +241,9 @@ public class PersonNameConsistencyTest extends TestFmwk { private void reportError(String error, int lineNumber) { logln(" " + error + " at line " + lineNumber); + if (VERBOSE_OUTPUT) { + System.out.println(" " + error + " at line " + lineNumber); + } ++errorCount; } }