]> granicus.if.org Git - icu/commitdiff
ICU-22081 More API-review fixes: Hoisted the PersonName object to the top level ...
authorRich Gillam <richard_gillam@apple.com>
Wed, 31 Aug 2022 00:43:30 +0000 (17:43 -0700)
committerRich Gillam <62772518+richgillam@users.noreply.github.com>
Thu, 1 Sep 2022 20:36:05 +0000 (13:36 -0700)
NameField and FieldModifier there, plus a number of smaller changes.

icu4j/main/classes/core/src/com/ibm/icu/impl/personname/FieldModifierImpl.java
icu4j/main/classes/core/src/com/ibm/icu/impl/personname/PersonNameFormatterImpl.java
icu4j/main/classes/core/src/com/ibm/icu/impl/personname/PersonNamePattern.java
icu4j/main/classes/core/src/com/ibm/icu/text/PersonName.java [new file with mode: 0644]
icu4j/main/classes/core/src/com/ibm/icu/text/PersonNameFormatter.java
icu4j/main/classes/core/src/com/ibm/icu/text/SimplePersonName.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/PersonNameFormatterTest.java

index 521c4aeb3fbc6241afd0949add1e1a59affb802c..6cfe7a4177a9431fac0715892c67d98e82647a8a 100644 (file)
@@ -3,10 +3,7 @@
 package com.ibm.icu.impl.personname;
 
 import com.ibm.icu.lang.UCharacter;
-import com.ibm.icu.text.BreakIterator;
-import com.ibm.icu.text.CaseMap;
-import com.ibm.icu.text.PersonNameFormatter;
-import com.ibm.icu.text.SimpleFormatter;
+import com.ibm.icu.text.*;
 
 import java.util.Locale;
 import java.util.StringTokenizer;
@@ -17,7 +14,7 @@ import java.util.StringTokenizer;
 abstract class FieldModifierImpl {
     public abstract String modifyField(String fieldValue);
 
-    public static FieldModifierImpl forName(PersonNameFormatter.FieldModifier modifierID, PersonNameFormatterImpl formatterImpl) {
+    public static FieldModifierImpl forName(PersonName.FieldModifier modifierID, PersonNameFormatterImpl formatterImpl) {
         switch (modifierID) {
             case INFORMAL:
                 return NOOP_MODIFIER;
index 807f100f57d4d8eceb5aeda4ccae0162a21abfde..7f319b0f819f8aa5f59c9fb078f88e84c74aad9e 100644 (file)
@@ -5,6 +5,7 @@ package com.ibm.icu.impl.personname;
 import com.ibm.icu.impl.ICUData;
 import com.ibm.icu.impl.ICUResourceBundle;
 import com.ibm.icu.lang.UScript;
+import com.ibm.icu.text.PersonName;
 import com.ibm.icu.text.PersonNameFormatter;
 import com.ibm.icu.util.ULocale;
 import com.ibm.icu.util.UResourceBundle;
@@ -124,7 +125,7 @@ public class PersonNameFormatterImpl {
 
     }
 
-    public String formatToString(PersonNameFormatter.PersonName name) {
+    public String formatToString(PersonName name) {
         // TODO: Should probably return a FormattedPersonName object
 
         // if the formatter is for a language that doesn't use spaces between words and the name is from a language
@@ -201,10 +202,10 @@ public class PersonNameFormatterImpl {
      * @param name The name to be formatted.
      * @return If true, use given-first order to format the name; if false, use surname-first order.
      */
-    private boolean nameIsGnFirst(PersonNameFormatter.PersonName name) {
+    private boolean nameIsGnFirst(PersonName name) {
         // the name can declare its order-- check that first (it overrides any locale-based calculation)
-        Set<PersonNameFormatter.FieldModifier> modifiers = new HashSet<>();
-        String preferredOrder = name.getFieldValue(PersonNameFormatter.NameField.PREFERRED_ORDER, modifiers);
+        Set<PersonName.FieldModifier> modifiers = new HashSet<>();
+        String preferredOrder = name.getFieldValue(PersonName.NameField.PREFERRED_ORDER, modifiers);
         if (preferredOrder != null) {
             if (preferredOrder.equals("givenFirst")) {
                 return true;
@@ -235,7 +236,7 @@ public class PersonNameFormatterImpl {
         return true;
     }
 
-    private PersonNamePattern getBestPattern(PersonNamePattern[] patterns, PersonNameFormatter.PersonName name) {
+    private PersonNamePattern getBestPattern(PersonNamePattern[] patterns, PersonName name) {
         // early out if there's only one pattern
         if (patterns.length == 1) {
             return patterns[0];
@@ -270,14 +271,14 @@ public class PersonNameFormatterImpl {
      * @param name The name for which we need the locale
      * @return The name's (real or guessed) locale.
      */
-    private Locale getNameLocale(PersonNameFormatter.PersonName name) {
+    private Locale getNameLocale(PersonName name) {
         // if the name specifies its locale, we can just return it
         Locale nameLocale = name.getNameLocale();
         if (nameLocale == null) {
             // if not, we look at the characters in the name.  If their script matches the default script for the formatter's
             // locale, we use the formatter's locale as the name's locale
             int formatterScript = UScript.getCodeFromName(ULocale.addLikelySubtags(ULocale.forLocale(locale)).getScript());
-            String givenName = name.getFieldValue(PersonNameFormatter.NameField.GIVEN, new HashSet<PersonNameFormatter.FieldModifier>());
+            String givenName = name.getFieldValue(PersonName.NameField.GIVEN, new HashSet<PersonName.FieldModifier>());
             int nameScript = UScript.INVALID_CODE;
             for (int i = 0; nameScript == UScript.INVALID_CODE && i < givenName.length(); i++) {
                 // the script of the name is the script of the first character in the name whose script isn't
index c7d547f10cfb90534e85a771fc6f550d33cdc39c..0407ef87591157dd76789dfbfeae5901eceb9a8d 100644 (file)
@@ -2,7 +2,7 @@
 // License & terms of use: http://www.unicode.org/copyright.html
 package com.ibm.icu.impl.personname;
 
-import com.ibm.icu.text.PersonNameFormatter;
+import com.ibm.icu.text.PersonName;
 
 import java.util.*;
 
@@ -74,7 +74,7 @@ class PersonNamePattern {
         this.patternElements = elements.toArray(new Element[0]);
     }
 
-    public String format(PersonNameFormatter.PersonName name) {
+    public String format(PersonName name) {
         StringBuilder result = new StringBuilder();
         boolean seenLeadingField = false;
         boolean seenEmptyLeadingField = false;
@@ -131,7 +131,7 @@ class PersonNamePattern {
         return result.toString();
     }
 
-    public int numPopulatedFields(PersonNameFormatter.PersonName name) {
+    public int numPopulatedFields(PersonName name) {
         int result = 0;
         for (Element element : patternElements) {
             result += element.isPopulated(name) ? 1 : 0;
@@ -139,7 +139,7 @@ class PersonNamePattern {
         return result;
     }
 
-    public int numEmptyFields(PersonNameFormatter.PersonName name) {
+    public int numEmptyFields(PersonName name) {
         int result = 0;
         for (Element element : patternElements) {
             result += element.isPopulated(name) ? 0 : 1;
@@ -190,8 +190,8 @@ class PersonNamePattern {
      */
     private interface Element {
         boolean isLiteral();
-        String format(PersonNameFormatter.PersonName name);
-        boolean isPopulated(PersonNameFormatter.PersonName name);
+        String format(PersonName name);
+        boolean isPopulated(PersonName name);
     }
 
     /**
@@ -208,11 +208,11 @@ class PersonNamePattern {
             return true;
         }
 
-        public String format(PersonNameFormatter.PersonName name) {
+        public String format(PersonName name) {
             return text;
         }
 
-        public boolean isPopulated(PersonNameFormatter.PersonName name) {
+        public boolean isPopulated(PersonName name) {
             return false;
         }
     }
@@ -223,23 +223,23 @@ class PersonNamePattern {
      * PersonName object and applying any modifiers to it.
      */
     private static class NameFieldImpl implements Element {
-        private PersonNameFormatter.NameField fieldID;
-        private Map<PersonNameFormatter.FieldModifier, FieldModifierImpl> modifiers;
+        private PersonName.NameField fieldID;
+        private Map<PersonName.FieldModifier, FieldModifierImpl> modifiers;
 
         public NameFieldImpl(String fieldNameAndModifiers, PersonNameFormatterImpl formatterImpl) {
-            List<PersonNameFormatter.FieldModifier> modifierIDs = new ArrayList<>();
+            List<PersonName.FieldModifier> modifierIDs = new ArrayList<>();
             StringTokenizer tok = new StringTokenizer(fieldNameAndModifiers, "-");
 
-            this.fieldID = PersonNameFormatter.NameField.forString(tok.nextToken());
+            this.fieldID = PersonName.NameField.forString(tok.nextToken());
             while (tok.hasMoreTokens()) {
-                modifierIDs.add(PersonNameFormatter.FieldModifier.forString(tok.nextToken()));
+                modifierIDs.add(PersonName.FieldModifier.forString(tok.nextToken()));
             }
-            if (this.fieldID == PersonNameFormatter.NameField.SURNAME && formatterImpl.shouldCapitalizeSurname()) {
-                modifierIDs.add(PersonNameFormatter.FieldModifier.ALL_CAPS);
+            if (this.fieldID == PersonName.NameField.SURNAME && formatterImpl.shouldCapitalizeSurname()) {
+                modifierIDs.add(PersonName.FieldModifier.ALL_CAPS);
             }
 
             this.modifiers = new HashMap<>();
-            for (PersonNameFormatter.FieldModifier modifierID : modifierIDs) {
+            for (PersonName.FieldModifier modifierID : modifierIDs) {
                 this.modifiers.put(modifierID, FieldModifierImpl.forName(modifierID, formatterImpl));
             }
         }
@@ -248,20 +248,20 @@ class PersonNamePattern {
             return false;
         }
 
-        public String format(PersonNameFormatter.PersonName name) {
-            Set<PersonNameFormatter.FieldModifier> modifierIDs = new HashSet<>(modifiers.keySet());
+        public String format(PersonName name) {
+            Set<PersonName.FieldModifier> modifierIDs = new HashSet<>(modifiers.keySet());
             String result = name.getFieldValue(fieldID, modifierIDs);
             if (result != null) {
-                for (PersonNameFormatter.FieldModifier modifierID : modifierIDs) {
+                for (PersonName.FieldModifier modifierID : modifierIDs) {
                     result = modifiers.get(modifierID).modifyField(result);
                 }
             }
             return result;
         }
 
-        public boolean isPopulated(PersonNameFormatter.PersonName name) {
+        public boolean isPopulated(PersonName name) {
             // just check whether the unmodified field contains a value
-            Set<PersonNameFormatter.FieldModifier> modifierIDs = new HashSet<>();
+            Set<PersonName.FieldModifier> modifierIDs = new HashSet<>();
             String fieldValue = name.getFieldValue(fieldID, modifierIDs);
             return fieldValue != null && !fieldValue.isEmpty();
         }
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/PersonName.java b/icu4j/main/classes/core/src/com/ibm/icu/text/PersonName.java
new file mode 100644 (file)
index 0000000..a59f5ff
--- /dev/null
@@ -0,0 +1,241 @@
+package com.ibm.icu.text;
+
+import java.util.Locale;
+import java.util.Set;
+
+/**
+ * An object used to provide name data to the PersonNameFormatter for formatting.
+ * Clients can implement this interface to talk directly to some other subsystem
+ * that actually contains the name data (instead of having to copy it into a separate
+ * object just for formatting) or to override the default modifier behavior described
+ * above.  A concrete SimplePersonName object that does store the field values directly
+ * is provided.
+ *
+ * @internal ICU 72 technology preview
+ * @see SimplePersonName
+ * @deprecated This API is for technology preview only.
+ */
+public interface PersonName {
+    //==============================================================================
+    // Identifiers used to request field values from the PersonName object
+
+    /**
+     * Identifiers for the name fields supported by the PersonName object.
+     * @internal ICU 72 technology preview
+     * @deprecated This API is for technology preview only.
+     */
+    enum NameField {
+        /**
+         * Contains titles and other words that precede the actual name, such as "Mr."
+         * @internal ICU 72 technology preview
+         * @deprecated This API is for technology preview only.
+         */
+        PREFIX("prefix"),
+
+        /**
+         * The given name.  May contain more than one token.
+         * @internal ICU 72 technology preview
+         * @deprecated This API is for technology preview only.
+         */
+        GIVEN("given"),
+
+        /**
+         * Additional given names.  (In English, this is usually the "middle name" and
+         * may contain more than one word.)
+         * @internal ICU 72 technology preview
+         * @deprecated This API is for technology preview only.
+         */
+        GIVEN2("given2"),
+
+        /**
+         * The surname.  In Spanish, this is the patronymic surname.
+         * @internal ICU 72 technology preview
+         * @deprecated This API is for technology preview only.
+         */
+        SURNAME("surname"),
+
+        /**
+         * Additional surnames.  This is only used in a few languages, such as Spanish,
+         * where it is the matronymic surname.  (In most languages, multiple surnames all
+         * just go in the SURNAME field.)
+         * @internal ICU 72 technology preview
+         * @deprecated This API is for technology preview only.
+         */
+        SURNAME2("surname2"),
+
+        /**
+         * Generational and professional qualifiers that generally follow the actual name,
+         * such as "Jr." or "M.D."
+         * @internal ICU 72 technology preview
+         * @deprecated This API is for technology preview only.
+         */
+        SUFFIX("suffix"),
+
+        /**
+         * The preferred field order for the name.  PersonName objects generally shouldn't provide
+         * this field, allowing the PersonNameFormatter to deduce the proper field order based on
+         * the locales of the name of the formatter.  But this can be used to force a particular
+         * field order, generally in cases where the deduction logic in PersonNameFormatter would
+         * guess wrong.  When used, the only valid values are "givenFirst" and "surnameFirst".
+         * @internal ICU 72 technology preview
+         * @deprecated This API is for technology preview only.
+         */
+        PREFERRED_ORDER("preferredOrder");
+
+        private final String name;
+
+        private NameField(String name) {
+            this.name = name;
+        }
+
+        /**
+         * Returns the NameField's display name.
+         * @internal
+         */
+        @Override
+        public String toString() {
+            return name;
+        }
+
+        /**
+         * Returns the appropriate NameField for its display name.
+         * @internal
+         */
+        public static NameField forString(String name) {
+            for (NameField field : values()) {
+                if (field.name.equals(name)) {
+                    return field;
+                }
+            }
+            throw new IllegalArgumentException("Invalid field name " + name);
+        }
+    }
+
+    /**
+     * Identifiers for the name field modifiers supported by the PersonName and PersonNameFormatter objects.
+     * @internal ICU 72 technology preview
+     * @deprecated This API is for technology preview only.
+     */
+    enum FieldModifier {
+        /**
+         * Requests an "informal" variant of the field, generally a nickname of some type:
+         * if "given" is "James", "given-informal" might be "Jimmy".  Only applied to the "given"
+         * field.  If the PersonName object doesn't apply this modifier, PersonNameFormatter just
+         * uses the unmodified version of "given".
+         * @internal ICU 72 technology preview
+         * @deprecated This API is for technology preview only.
+         */
+        INFORMAL("informal"),
+
+        /**
+         * If the field contains a main word with one or more separate prefixes, such as
+         * "van den Hul", this requests just the prefixes ("van den").  Only applied to the "surname"
+         * field.  If the PersonName object doesn't apply this modifier, PersonNameFormatter
+         * assumes there are no prefixes.
+         * @internal ICU 72 technology preview
+         * @deprecated This API is for technology preview only.
+         */
+        PREFIX("prefix"),
+
+        /**
+         * If the field contains a main word with one or more separate prefixes, such as
+         * "van den Hul", this requests just the main word ("Hul").  Only applied to the "surname"
+         * field.  If the implementing class doesn't apply this modifier, PersonNameFormatter
+         * assumes the entire "surname" field is the "core".
+         * @internal ICU 72 technology preview
+         * @deprecated This API is for technology preview only.
+         */
+        CORE("core"),
+
+        /**
+         * Requests an initial for the specified field.  PersonNameFormatter will do
+         * this algorithmically, but a PersonName object can apply this modifier itself if it wants
+         * different initial-generation logic (or stores the initial separately).
+         * @internal ICU 72 technology preview
+         * @deprecated This API is for technology preview only.
+         */
+        INITIAL("initial"),
+
+        /**
+         * Requests an initial for the specified field, suitable for use in a monogram
+         * (this usually differs from "initial" in that "initial" often adds a period and "monogram"
+         * never does).  PersonNameFormatter will do this algorithmically, but a PersonName object can
+         * apply this modifier itself if it wants different monogram-generation logic.
+         * @internal ICU 72 technology preview
+         * @deprecated This API is for technology preview only.
+         */
+        MONOGRAM("monogram"),
+
+        /**
+         * Requests the field value converted to ALL CAPS.  PersonName objects
+         * generally won't need to handle this modifier themselves.
+         * @internal ICU 72 technology preview
+         * @deprecated This API is for technology preview only.
+         */
+        ALL_CAPS("allCaps"),
+
+        /**
+         * Requests the field value with the first grapheme of each word converted to titlecase.
+         * A PersonName object might handle this modifier itself to capitalize words more
+         * selectively.
+         * @internal ICU 72 technology preview
+         * @deprecated This API is for technology preview only.
+         */
+        INITIAL_CAP("initialCap");
+
+        private final String name;
+
+        private FieldModifier(String name) {
+            this.name = name;
+        }
+
+        /**
+         * Returns the FieldModifier's display name.
+         * @internal
+         */
+        @Override
+        public String toString() {
+            return name;
+        }
+
+        /**
+         * Returns the appropriate fieldModifier for its display name.
+         * @internal
+         */
+        public static FieldModifier forString(String name) {
+            for (FieldModifier modifier : values()) {
+                if (modifier.name.equals(name)) {
+                    return modifier;
+                }
+            }
+            throw new IllegalArgumentException("Invalid modifier name " + name);
+        }
+    }
+
+    //==============================================================================
+    // Public API on PersonName
+    /**
+     * Returns the locale of the name-- that is, the language or country of origin for the person being named.
+     * An implementing class is allowed to return null here to indicate the name's locale is unknown.
+     *
+     * @return The name's locale, or null if it's not known.
+     * @internal ICU 72 technology preview
+     * @deprecated This API is for technology preview only.
+     */
+    public Locale getNameLocale();
+
+    /**
+     * Returns one field of the name, possibly in a modified form.
+     *
+     * @param identifier The identifier of the requested field.
+     * @param modifiers  An **IN/OUT** parameter that specifies modifiers to apply to the basic field value.
+     *                   An implementing class can choose to handle or ignore any modifiers; it should modify
+     *                   the passed-in Set so that on exit, it contains only the requested modifiers that it
+     *                   DIDN'T handle.  This parameter may not be null, and must either be mutable or empty.
+     * @return The value of the requested field, optionally modified by some or all of the requested modifiers, or
+     * null if the requested field isn't present in the name.
+     * @internal ICU 72 technology preview
+     * @deprecated This API is for technology preview only.
+     */
+    public String getFieldValue(NameField identifier, Set<FieldModifier> modifiers);
+}
index 5156b1c6758ac2670856bafc54fe000031467373..d96273ba98db504b4ab669a148222913131320a6 100644 (file)
@@ -136,264 +136,29 @@ public class PersonNameFormatter {
         SURNAME_ALLCAPS
     }
 
-    //==============================================================================
-    // Identifiers used to request field values from the PersonName object
-
-    /**
-     * Identifiers for the name fields supported by the PersonName object.
-     * @internal ICU 72 technology preview
-     * @deprecated This API is for technology preview only.
-     */
-    public enum NameField {
-        /**
-         * Contains titles and other words that precede the actual name, such as "Mr."
-         * @internal ICU 72 technology preview
-         * @deprecated This API is for technology preview only.
-         */
-        PREFIX("prefix"),
-
-        /**
-         * The given name.  May contain more than one token.
-         * @internal ICU 72 technology preview
-         * @deprecated This API is for technology preview only.
-         */
-        GIVEN("given"),
-
-        /**
-         * Additional given names.  (In English, this is usually the "middle name" and
-         * may contain more than one word.)
-         * @internal ICU 72 technology preview
-         * @deprecated This API is for technology preview only.
-         */
-        GIVEN2("given2"),
-
-        /**
-         * The surname.  In Spanish, this is the patronymic surname.
-         * @internal ICU 72 technology preview
-         * @deprecated This API is for technology preview only.
-         */
-        SURNAME("surname"),
-
-        /**
-         * Additional surnames.  This is only used in a few languages, such as Spanish,
-         * where it is the matronymic surname.  (In most languages, multiple surnames all
-         * just go in the SURNAME field.)
-         * @internal ICU 72 technology preview
-         * @deprecated This API is for technology preview only.
-         */
-        SURNAME2("surname2"),
-
-        /**
-         * Generational and professional qualifiers that generally follow the actual name,
-         * such as "Jr." or "M.D."
-         * @internal ICU 72 technology preview
-         * @deprecated This API is for technology preview only.
-         */
-        SUFFIX("suffix"),
-
-        /**
-         * The preferred field order for the name.  PersonName objects generally shouldn't provide
-         * this field, allowing the PersonNameFormatter to deduce the proper field order based on
-         * the locales of the name of the formatter.  But this can be used to force a particular
-         * field order, generally in cases where the deduction logic in PersonNameFormatter would
-         * guess wrong.  When used, the only valid values are "givenFirst" and "surnameFirst".
-         * @internal ICU 72 technology preview
-         * @deprecated This API is for technology preview only.
-         */
-        PREFERRED_ORDER("preferredOrder");
-
-        private final String name;
-
-        private NameField(String name) {
-            this.name = name;
-        }
-
-        /**
-         * Returns the NameField's display name.
-         * @internal ICU 72 technology preview
-         * @deprecated This API is for technology preview only.
-         */
-        @Override
-        public String toString() {
-            return name;
-        }
-
-        /**
-         * Returns the appropriate NameField for its display name.
-         * @internal ICU 72 technology preview
-         * @deprecated This API is for technology preview only.
-         */
-        public static NameField forString(String name) {
-            for (NameField field : values()) {
-                if (field.name.equals(name)) {
-                    return field;
-                }
-            }
-            throw new IllegalArgumentException("Invalid field name " + name);
-        }
-    }
-
-    /**
-     * Identifiers for the name field modifiers supported by the PersonName and PersonNameFormatter objects.
-     * @internal ICU 72 technology preview
-     * @deprecated This API is for technology preview only.
-     */
-    public enum FieldModifier {
-        /**
-         * Requests an "informal" variant of the field, generally a nickname of some type:
-         * if "given" is "James", "given-informal" might be "Jimmy".  Only applied to the "given"
-         * field.  If the PersonName object doesn't apply this modifier, PersonNameFormatter just
-         * uses the unmodified version of "given".
-         * @internal ICU 72 technology preview
-         * @deprecated This API is for technology preview only.
-         */
-        INFORMAL("informal"),
-
-        /**
-         * If the field contains a main word with one or more separate prefixes, such as
-         * "van den Hul", this requests just the prefixes ("van den").  Only applied to the "surname"
-         * field.  If the PersonName object doesn't apply this modifier, PersonNameFormatter
-         * assumes there are no prefixes.
-         * @internal ICU 72 technology preview
-         * @deprecated This API is for technology preview only.
-         */
-        PREFIX("prefix"),
-
-        /**
-         * If the field contains a main word with one or more separate prefixes, such as
-         * "van den Hul", this requests just the main word ("Hul").  Only applied to the "surname"
-         * field.  If the implementing class doesn't apply this modifier, PersonNameFormatter
-         * assumes the entire "surname" field is the "core".
-         * @internal ICU 72 technology preview
-         * @deprecated This API is for technology preview only.
-         */
-        CORE("core"),
-
-        /**
-         * Requests an initial for the specified field.  PersonNameFormatter will do
-         * this algorithmically, but a PersonName object can apply this modifier itself if it wants
-         * different initial-generation logic (or stores the initial separately).
-         * @internal ICU 72 technology preview
-         * @deprecated This API is for technology preview only.
-         */
-        INITIAL("initial"),
-
-        /**
-         * Requests an initial for the specified field, suitable for use in a monogram
-         * (this usually differs from "initial" in that "initial" often adds a period and "monogram"
-         * never does).  PersonNameFormatter will do this algorithmically, but a PersonName object can
-         * apply this modifier itself if it wants different monogram-generation logic.
-         * @internal ICU 72 technology preview
-         * @deprecated This API is for technology preview only.
-         */
-        MONOGRAM("monogram"),
-
-        /**
-         * Requests the field value converted to ALL CAPS.  PersonName objects
-         * generally won't need to handle this modifier themselves.
-         * @internal ICU 72 technology preview
-         * @deprecated This API is for technology preview only.
-         */
-        ALL_CAPS("allCaps"),
-
-        /**
-         * Requests the field value with the first grapheme of each word converted to titlecase.
-         * A PersonName object might handle this modifier itself to capitalize words more
-         * selectively.
-         * @internal ICU 72 technology preview
-         * @deprecated This API is for technology preview only.
-         */
-        INITIAL_CAP("initialCap");
-
-        private final String name;
-
-        private FieldModifier(String name) {
-            this.name = name;
-        }
-
-        /**
-         * Returns the FieldModifier's display name.
-         * @internal ICU 72 technology preview
-         * @deprecated This API is for technology preview only.
-         */
-        @Override
-        public String toString() {
-            return name;
-        }
-
-        /**
-         * Returns the appropriate fieldModifier for its display name.
-         * @internal ICU 72 technology preview
-         * @deprecated This API is for technology preview only.
-         */
-        public static FieldModifier forString(String name) {
-            for (FieldModifier modifier : values()) {
-                if (modifier.name.equals(name)) {
-                    return modifier;
-                }
-            }
-            throw new IllegalArgumentException("Invalid modifier name " + name);
-        }
-    }
-
-    //==============================================================================
-    // The PersonName object
-
-    /**
-     * An object used to provide name data to the PersonNameFormatter for formatting.
-     * Clients can implement this interface to talk directly to some other subsystem
-     * that actually contains the name data (instead of having to copy it into a separate
-     * object just for formatting) or to override the default modifier behavior described
-     * above.  A concrete SimplePersonName object that does store the field values directly
-     * is provided.
-     * @internal ICU 72 technology preview
-     * @deprecated This API is for technology preview only.
-     * @see SimplePersonName
-     */
-    public interface PersonName {
-        /**
-         * Returns the locale of the name-- that is, the language or country of origin for the person being named.
-         * @return The name's locale, or null if it's not known.
-         * @internal ICU 72 technology preview
-         * @deprecated This API is for technology preview only.
-         */
-        public Locale getNameLocale();
-
-        /**
-         * Returns one field of the name, possibly in a modified form.
-         * @param identifier The identifier of the requested field.
-         * @param modifiers An **IN/OUT** parameter that specifies modifiers to apply to the basic field value.
-         *                  An implementing class can choose to handle or ignore any modifiers; it should modify
-         *                  this parameter so that on exit, it contains only the requested modifiers that it
-         *                  DIDN'T handle.
-         * @return The value of the requested field, optionally modified by some or all of the requested modifiers, or
-         * null if the requested field isn't present in the name.
-         * @internal ICU 72 technology preview
-         * @deprecated This API is for technology preview only.
-         */
-        public String getFieldValue(NameField identifier, Set<FieldModifier> modifiers);
-    }
-
     private final PersonNameFormatterImpl impl;
 
     //==============================================================================
-    // Builder for PersonNameformatter
+    // Builder for PersonNameFormatter
 
     /**
      * A utility class that can be used to construct a PersonNameFormatter.
+     * Use PersonNameFormatter.builder() to get a new instance.
      * @internal ICU 72 technology preview
      * @deprecated This API is for technology preview only.
      */
     public static class Builder {
         /**
          * Sets the locale for the formatter to be constructed.
-         * @param locale The new formatter locale.
+         * @param locale The new formatter locale.  May not be null.
          * @return This builder.
          * @internal ICU 72 technology preview
          * @deprecated This API is for technology preview only.
          */
         public Builder setLocale(Locale locale) {
-            this.locale = locale;
+            if (locale != null) {
+                this.locale = locale;
+            }
             return this;
         }
 
@@ -434,7 +199,9 @@ public class PersonNameFormatter {
         }
 
         /**
-         * Sets the options set for the formatter to be constructed.
+         * Sets the options set for the formatter to be constructed.  The Set passed in
+         * here replaces the entire options set the builder already has (if one has
+         * already been set); this method doesn't modify the builder's options set.
          * @param options The new options set.
          * @return This builder.
          * @internal ICU 72 technology preview
@@ -447,6 +214,9 @@ public class PersonNameFormatter {
 
         /**
          * Returns a new PersonNameFormatter with the values that were passed to this builder.
+         * This method doesn't freeze or delete the builder; you can call build() more than once
+         * (presumably after calling the other methods to change the parameter) to create more
+         * than one PersonNameFormatter; you don't need a new Builder for each PersonNameFormatter.
          * @return A new PersonNameFormatter.
          * @internal ICU 72 technology preview
          * @deprecated This API is for technology preview only.
@@ -458,7 +228,7 @@ public class PersonNameFormatter {
         private Builder() {
        }
 
-        private Locale locale = null;
+        private Locale locale = Locale.getDefault();
         private Length length = Length.MEDIUM;
         private Usage usage = Usage.REFERRING;
         private Formality formality = Formality.FORMAL;
@@ -485,7 +255,7 @@ public class PersonNameFormatter {
      * @internal ICU 72 technology preview
      * @deprecated This API is for technology preview only.
      */
-    public Builder builderFromThis() {
+    public Builder toBuilder() {
         Builder builder = builder();
         builder.setLocale(impl.getLocale());
         builder.setLength(impl.getLength());
index 1d3b088e4cd3890dc64c388632af7f0065929dea..758b1aae62107b37f404d57eae337e3e1408e0d8 100644 (file)
@@ -21,8 +21,10 @@ import java.util.TreeSet;
  * @internal ICU 72 technology preview
  * @deprecated This API is for technology preview only.
  */
-public class SimplePersonName implements PersonNameFormatter.PersonName {
+public class SimplePersonName implements PersonName {
     /**
+     * A utility class for constructing a SimplePersonName.  Use SimplePersonName.builder()
+     * to get a new Builder instance.
      * @internal ICU 72 technology preview
      * @deprecated This API is for technology preview only.
      *
@@ -30,7 +32,8 @@ public class SimplePersonName implements PersonNameFormatter.PersonName {
     public static class Builder {
         /**
          * Set the locale for the new name object.
-         * @param locale The locale for the new name object.
+         * @param locale The locale for the new name object.  Can be null, which indicates the
+         *               name's locale is unknown.
          * @return This builder.
          * @internal ICU 72 technology preview
          * @deprecated This API is for technology preview only.
@@ -50,13 +53,13 @@ public class SimplePersonName implements PersonNameFormatter.PersonName {
          * @internal ICU 72 technology preview
          * @deprecated This API is for technology preview only.
          */
-        public Builder addField(PersonNameFormatter.NameField field,
-                                Collection<PersonNameFormatter.FieldModifier> modifiers,
+        public Builder addField(NameField field,
+                                Collection<FieldModifier> modifiers,
                                 String value) {
             // generate the modifiers' internal names, and sort them alphabetically
             Set<String> modifierNames = new TreeSet<>();
             if (modifiers != null) {
-                for (PersonNameFormatter.FieldModifier modifier : modifiers) {
+                for (FieldModifier modifier : modifiers) {
                     modifierNames.add(modifier.toString());
                 }
             }
@@ -147,7 +150,7 @@ public class SimplePersonName implements PersonNameFormatter.PersonName {
      * @deprecated This API is for technology preview only.
      */
     @Override
-    public String getFieldValue(PersonNameFormatter.NameField nameField, Set<PersonNameFormatter.FieldModifier> modifiers) {
+    public String getFieldValue(NameField nameField, Set<FieldModifier> modifiers) {
         // first look for the fully modified name in the internal table
         String fieldName = nameField.toString();
         String result = fieldValues.get(makeModifiedFieldName(nameField, modifiers));
@@ -170,7 +173,7 @@ public class SimplePersonName implements PersonNameFormatter.PersonName {
         int winningScore = 0;
         for (String key : fieldValues.keySet()) {
             if (key.startsWith(fieldName)) {
-                Set<PersonNameFormatter.FieldModifier> keyModifiers = makeModifiersFromName(key);
+                Set<FieldModifier> keyModifiers = makeModifiersFromName(key);
                 if (modifiers.containsAll(keyModifiers)) {
                     if (keyModifiers.size() > winningScore || (keyModifiers.size() == winningScore && key.compareTo(winningKey) < 0)) {
                         winningKey = key;
@@ -184,13 +187,13 @@ public class SimplePersonName implements PersonNameFormatter.PersonName {
         return result;
     }
 
-    private static String makeModifiedFieldName(PersonNameFormatter.NameField fieldName,
-                                                Collection<PersonNameFormatter.FieldModifier> modifiers) {
+    private static String makeModifiedFieldName(NameField fieldName,
+                                                Collection<FieldModifier> modifiers) {
         StringBuilder result = new StringBuilder();
         result.append(fieldName);
 
         TreeSet<String> sortedModifierNames = new TreeSet<>();
-        for (PersonNameFormatter.FieldModifier modifier : modifiers) {
+        for (FieldModifier modifier : modifiers) {
             sortedModifierNames.add(modifier.toString());
         }
         for (String modifierName : sortedModifierNames) {
@@ -200,12 +203,12 @@ public class SimplePersonName implements PersonNameFormatter.PersonName {
         return result.toString();
     }
 
-    private static Set<PersonNameFormatter.FieldModifier> makeModifiersFromName(String modifiedName) {
+    private static Set<FieldModifier> makeModifiersFromName(String modifiedName) {
         StringTokenizer tok = new StringTokenizer(modifiedName, "-");
-        Set<PersonNameFormatter.FieldModifier> result = new HashSet<>();
+        Set<FieldModifier> result = new HashSet<>();
         String fieldName = tok.nextToken(); // throw away the field name
         while (tok.hasMoreTokens()) {
-            result.add(PersonNameFormatter.FieldModifier.forString(tok.nextToken()));
+            result.add(PersonName.FieldModifier.forString(tok.nextToken()));
         }
         return result;
     }
index e5d624ddeb65393deaaf35d1abf788206bb5ff45..365290bb02ebb38f00fc11abf106bc2c971cf55b 100644 (file)
@@ -3,6 +3,7 @@
 package com.ibm.icu.dev.test.format;
 
 import com.ibm.icu.dev.test.TestFmwk;
+import com.ibm.icu.text.PersonName;
 import com.ibm.icu.text.PersonNameFormatter;
 import com.ibm.icu.text.SimplePersonName;
 import org.junit.Test;
@@ -41,13 +42,13 @@ public class PersonNameFormatterTest extends TestFmwk{
                 // locale ID
                 builder.setLocale(Locale.forLanguageTag(fieldValue.replace("_", "-")));
             } else if (fieldName.indexOf('-') < 0) {
-                builder.addField(PersonNameFormatter.NameField.forString(fieldName), null, fieldValue);
+                builder.addField(PersonName.NameField.forString(fieldName), null, fieldValue);
             } else {
                 StringTokenizer fieldNameSplitter = new StringTokenizer(fieldName, "-");
-                Set<PersonNameFormatter.FieldModifier> modifiers = new HashSet<>();
-                PersonNameFormatter.NameField fieldID = PersonNameFormatter.NameField.forString(fieldNameSplitter.nextToken());
+                Set<PersonName.FieldModifier> modifiers = new HashSet<>();
+                PersonName.NameField fieldID = PersonName.NameField.forString(fieldNameSplitter.nextToken());
                 while (fieldNameSplitter.hasMoreTokens()) {
-                    modifiers.add(PersonNameFormatter.FieldModifier.forString(fieldNameSplitter.nextToken()));
+                    modifiers.add(PersonName.FieldModifier.forString(fieldNameSplitter.nextToken()));
                 }
                 builder.addField(fieldID, modifiers, fieldValue);
             }