17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Copyright (C) 2002-2012, International Business Machines Corporation and    *
47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * others. All Rights Reserved.                                                *
57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.dev.util;
87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.ArrayList;
107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Arrays;
117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.BitSet;
127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Collection;
137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.HashMap;
147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.HashSet;
157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Iterator;
167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.List;
177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Locale;
187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Map;
197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Set;
207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.TreeMap;
217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.TreeSet;
227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.lang.UCharacter;
247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.lang.UProperty;
257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.lang.UScript;
267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.Normalizer;
277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.UTF16;
287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.VersionInfo;
297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/**
327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Provides a general interface for Unicode Properties, and
337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * extracting sets based on those values.
347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @author Davis
357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic class ICUPropertyFactory extends UnicodeProperty.Factory {
387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static class ICUProperty extends UnicodeProperty {
407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected int propEnum = Integer.MIN_VALUE;
417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected ICUProperty(String propName, int propEnum) {
437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setName(propName);
447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            this.propEnum = propEnum;
457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setType(internalGetPropertyType(propEnum));
467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (propEnum == UProperty.DEFAULT_IGNORABLE_CODE_POINT || propEnum == UProperty.BIDI_CLASS || propEnum == UProperty.GENERAL_CATEGORY) {
477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                setUniformUnassigned(false);
487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                setUniformUnassigned(true);
507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean shownException = false;
547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public String _getValue(int codePoint) {
567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            switch (propEnum) {
577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.AGE:
587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return getAge(codePoint);
597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.BIDI_MIRRORING_GLYPH:
607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UTF16.valueOf(UCharacter.getMirror(codePoint));
617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.CASE_FOLDING:
627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UCharacter.foldCase(UTF16.valueOf(codePoint), true);
637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.ISO_COMMENT:
647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UCharacter.getISOComment(codePoint);
657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.LOWERCASE_MAPPING:
667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UCharacter.toLowerCase(Locale.ENGLISH, UTF16.valueOf(codePoint));
677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.NAME:
687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UCharacter.getName(codePoint);
697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.SIMPLE_CASE_FOLDING:
707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UTF16.valueOf(UCharacter.foldCase(codePoint, true));
717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.SIMPLE_LOWERCASE_MAPPING:
727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UTF16.valueOf(UCharacter.toLowerCase(codePoint));
737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.SIMPLE_TITLECASE_MAPPING:
747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UTF16.valueOf(UCharacter.toTitleCase(codePoint));
757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.SIMPLE_UPPERCASE_MAPPING:
767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UTF16.valueOf(UCharacter.toUpperCase(codePoint));
777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.TITLECASE_MAPPING:
787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UCharacter.toTitleCase(Locale.ENGLISH, UTF16.valueOf(codePoint), null);
797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.UNICODE_1_NAME:
807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UCharacter.getName1_0(codePoint);
817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.UPPERCASE_MAPPING:
827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UCharacter.toUpperCase(Locale.ENGLISH, UTF16.valueOf(codePoint));
837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // case NFC: return Normalizer.normalize(codePoint, Normalizer.NFC);
847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // case NFD: return Normalizer.normalize(codePoint, Normalizer.NFD);
857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // case NFKC: return Normalizer.normalize(codePoint, Normalizer.NFKC);
867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // case NFKD: return Normalizer.normalize(codePoint, Normalizer.NFKD);
877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case isNFC:
887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return String.valueOf(Normalizer.normalize(codePoint, Normalizer.NFC).equals(UTF16.valueOf(codePoint)));
897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case isNFD:
907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return String.valueOf(Normalizer.normalize(codePoint, Normalizer.NFD).equals(UTF16.valueOf(codePoint)));
917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case isNFKC:
927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return String
937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        .valueOf(Normalizer.normalize(codePoint, Normalizer.NFKC).equals(UTF16.valueOf(codePoint)));
947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case isNFKD:
957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return String
967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        .valueOf(Normalizer.normalize(codePoint, Normalizer.NFKD).equals(UTF16.valueOf(codePoint)));
977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case isLowercase:
987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return String.valueOf(UCharacter.toLowerCase(Locale.ENGLISH, UTF16.valueOf(codePoint)).equals(
997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        UTF16.valueOf(codePoint)));
1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case isUppercase:
1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return String.valueOf(UCharacter.toUpperCase(Locale.ENGLISH, UTF16.valueOf(codePoint)).equals(
1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        UTF16.valueOf(codePoint)));
1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case isTitlecase:
1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return String.valueOf(UCharacter.toTitleCase(Locale.ENGLISH, UTF16.valueOf(codePoint), null).equals(
1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        UTF16.valueOf(codePoint)));
1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case isCasefolded:
1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return String.valueOf(UCharacter.foldCase(UTF16.valueOf(codePoint), true).equals(
1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        UTF16.valueOf(codePoint)));
1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case isCased:
1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return String.valueOf(UCharacter.toLowerCase(Locale.ENGLISH, UTF16.valueOf(codePoint)).equals(
1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        UTF16.valueOf(codePoint)));
1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.SCRIPT_EXTENSIONS:
1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return getStringScriptExtensions(codePoint);
1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (propEnum < UProperty.INT_LIMIT) {
1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int enumValue = -1;
1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                String value = null;
1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                try {
1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    enumValue = UCharacter.getIntPropertyValue(codePoint, propEnum);
1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (enumValue >= 0)
1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        value = fixedGetPropertyValueName(propEnum, enumValue, UProperty.NameChoice.LONG);
1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } catch (IllegalArgumentException e) {
1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (!shownException) {
1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        System.out.println("Fail: " + getName() + ", " + Integer.toHexString(codePoint));
1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        shownException = true;
1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return value != null ? value : String.valueOf(enumValue);
1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (propEnum < UProperty.DOUBLE_LIMIT) {
1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                double num = UCharacter.getUnicodeNumericValue(codePoint);
1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (num == UCharacter.NO_NUMERIC_VALUE)
1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    return null;
1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return Double.toString(num);
1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // TODO: Fix HACK -- API deficient
1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return null;
1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private String getAge(int codePoint) {
1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String temp = UCharacter.getAge(codePoint).toString();
1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (temp.equals("0.0.0.0"))
1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return "unassigned";
1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (temp.endsWith(".0.0"))
1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return temp.substring(0, temp.length() - 4);
1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return temp;
1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /**
1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @param valueAlias null if unused.
1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @param valueEnum -1 if unused
1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @param nameChoice
1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @return
1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private String getFixedValueAlias(String valueAlias, int valueEnum, int nameChoice) {
1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (propEnum >= UProperty.STRING_START) {
1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (nameChoice > UProperty.NameChoice.LONG)
1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    throw new IllegalArgumentException();
1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (nameChoice != UProperty.NameChoice.LONG)
1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    return null;
1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return "<string>";
1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (propEnum >= UProperty.DOUBLE_START) {
1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (nameChoice > UProperty.NameChoice.LONG)
1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    throw new IllegalArgumentException();
1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (nameChoice != UProperty.NameChoice.LONG)
1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    return null;
1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return "<number>";
1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (valueAlias != null && !valueAlias.equals("<integer>")) {
1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                valueEnum = fixedGetPropertyValueEnum(propEnum, valueAlias);
1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // because these are defined badly, there may be no normal (long) name.
1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // if there is
1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String result = fixedGetPropertyValueName(propEnum, valueEnum, nameChoice);
1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (result != null)
1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return result;
1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // HACK try other namechoice
1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (nameChoice == UProperty.NameChoice.LONG) {
1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result = fixedGetPropertyValueName(propEnum, valueEnum, UProperty.NameChoice.SHORT);
1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (result != null)
1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    return result;
1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (isCombiningClassProperty())
1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    return null;
1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return "<integer>";
1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return null;
1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public boolean isCombiningClassProperty() {
1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return (propEnum == UProperty.CANONICAL_COMBINING_CLASS
1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    || propEnum == UProperty.LEAD_CANONICAL_COMBINING_CLASS
1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    || propEnum == UProperty.TRAIL_CANONICAL_COMBINING_CLASS);
1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static int fixedGetPropertyValueEnum(int propEnum, String valueAlias) {
1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            try {
1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (propEnum < BINARY_LIMIT) {
1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    propEnum = UProperty.ALPHABETIC;
1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UCharacter.getPropertyValueEnum(propEnum, valueAlias);
2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } catch (Exception e) {
2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return Integer.parseInt(valueAlias);
2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        static Map fixSkeleton = new HashMap();
2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static String fixedGetPropertyValueName(int propEnum, int valueEnum, int nameChoice) {
2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String value = UCharacter.getPropertyValueName(propEnum, valueEnum, nameChoice);
2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String newValue = (String) fixSkeleton.get(value);
2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (newValue == null) {
2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                newValue = value;
2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (propEnum == UProperty.JOINING_GROUP) {
2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    newValue = newValue == null ? null : newValue.toLowerCase(Locale.ENGLISH);
2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                newValue = regularize(newValue, true);
2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                fixSkeleton.put(value, newValue);
2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return newValue;
2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public List _getNameAliases(List result) {
2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (result == null)
2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result = new ArrayList();
2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // String alias = String_Extras.get(propEnum);
2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // if (alias == null)
2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String alias = Binary_Extras.get(propEnum);
2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (alias != null) {
2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                addUnique(alias, result);
2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                addUnique(getFixedPropertyName(propEnum, UProperty.NameChoice.SHORT), result);
2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                addUnique(getFixedPropertyName(propEnum, UProperty.NameChoice.LONG), result);
2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return result;
2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public String getFixedPropertyName(int propName, int nameChoice) {
2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            try {
2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UCharacter.getPropertyName(propEnum, nameChoice);
2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } catch (IllegalArgumentException e) {
2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return null;
2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static Map cccHack = new HashMap();
2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static Set cccExtras = new HashSet();
2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        static {
2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (int i = 0; i <= 255; ++i) {
2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                String alias = UCharacter.getPropertyValueName(UProperty.CANONICAL_COMBINING_CLASS, i,
2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        UProperty.NameChoice.LONG);
2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                String numStr = String.valueOf(i);
2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (alias != null) {
2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    cccHack.put(alias, numStr);
2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    cccHack.put(numStr, numStr);
2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    cccExtras.add(numStr);
2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public List _getAvailableValues(List result) {
2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (result == null)
2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result = new ArrayList();
2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (propEnum == UProperty.AGE) {
2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                addAllUnique(getAges(), result);
2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return result;
2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (propEnum < UProperty.INT_LIMIT) {
2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (Binary_Extras.isInRange(propEnum)) {
2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    propEnum = UProperty.BINARY_START; // HACK
2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int start = UCharacter.getIntPropertyMinValue(propEnum);
2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int end = UCharacter.getIntPropertyMaxValue(propEnum);
2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                for (int i = start; i <= end; ++i) {
2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    String alias = getFixedValueAlias(null, i, UProperty.NameChoice.LONG);
2767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    String alias2 = getFixedValueAlias(null, i, UProperty.NameChoice.SHORT);
2777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (alias == null) {
2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        alias = alias2;
2797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (alias == null && isCombiningClassProperty()) {
2807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            alias = String.valueOf(i);
2817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
2827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // System.out.println(propertyAlias + "\t" + i + ":\t" + alias);
2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    addUnique(alias, result);
2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (propEnum >= UProperty.DOUBLE_START && propEnum < UProperty.DOUBLE_LIMIT) {
2877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                UnicodeMap map = getUnicodeMap();
2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                Collection values = map.values();
2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                addAllUnique(values, result);
2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
2917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                String alias = getFixedValueAlias(null, -1, UProperty.NameChoice.LONG);
2927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                addUnique(alias, result);
2937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return result;
2957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        static String[] AGES = null;
2987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private String[] getAges() {
3007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (AGES == null) {
3017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                Set ages = new TreeSet();
3027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                for (int i = 0; i < 0x10FFFF; ++i) {
3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    ages.add(getAge(i));
3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                AGES = (String[]) ages.toArray(new String[ages.size()]);
3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return AGES;
3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public List _getValueAliases(String valueAlias, List result) {
3117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (result == null)
3127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result = new ArrayList();
3137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (propEnum == UProperty.AGE) {
3147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                addUnique(valueAlias, result);
3157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return result;
3167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
3177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (isCombiningClassProperty()) {
3187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                addUnique(cccHack.get(valueAlias), result); // add number
3197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
3207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int type = getType();
3217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (type == UnicodeProperty.NUMERIC || type == EXTENDED_NUMERIC) {
3227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                addUnique(valueAlias, result);
3237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (valueAlias.endsWith(".0")) {
3247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    addUnique(valueAlias.substring(0, valueAlias.length() - 2), result);
3257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
3267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
3277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                for (int nameChoice = UProperty.NameChoice.SHORT;; ++nameChoice) {
3287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    try {
3297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        addUnique(getFixedValueAlias(valueAlias, -1, nameChoice), result);
3307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } catch (Exception e) {
3317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        break;
3327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
3337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
3347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
3357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return result;
3367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /* (non-Javadoc)
3397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @see com.ibm.icu.dev.test.util.UnicodePropertySource#getPropertyType()
3407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
3417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private int internalGetPropertyType(int prop) {
3427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            switch (prop) {
3437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.AGE:
3447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.BLOCK:
3457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.SCRIPT:
3467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UnicodeProperty.CATALOG;
3477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.ISO_COMMENT:
3487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.NAME:
3497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.UNICODE_1_NAME:
3507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.SCRIPT_EXTENSIONS:
3517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UnicodeProperty.MISC;
3527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.BIDI_MIRRORING_GLYPH:
3537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.CASE_FOLDING:
3547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.LOWERCASE_MAPPING:
3557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.SIMPLE_CASE_FOLDING:
3567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.SIMPLE_LOWERCASE_MAPPING:
3577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.SIMPLE_TITLECASE_MAPPING:
3587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.SIMPLE_UPPERCASE_MAPPING:
3597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.TITLECASE_MAPPING:
3607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case UProperty.UPPERCASE_MAPPING:
3617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UnicodeProperty.EXTENDED_STRING;
3627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
3637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (prop < UProperty.BINARY_START)
3647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UnicodeProperty.UNKNOWN;
3657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (prop < UProperty.BINARY_LIMIT)
3667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UnicodeProperty.BINARY;
3677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (prop < UProperty.INT_START)
3687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UnicodeProperty.EXTENDED_BINARY;
3697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (prop < UProperty.INT_LIMIT)
3707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UnicodeProperty.ENUMERATED;
3717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (prop < UProperty.DOUBLE_START)
3727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UnicodeProperty.EXTENDED_ENUMERATED;
3737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (prop < UProperty.DOUBLE_LIMIT)
3747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UnicodeProperty.NUMERIC;
3757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (prop < UProperty.STRING_START)
3767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UnicodeProperty.EXTENDED_NUMERIC;
3777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (prop < UProperty.STRING_LIMIT)
3787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UnicodeProperty.STRING;
3797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return UnicodeProperty.EXTENDED_STRING;
3807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /*
3837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * (non-Javadoc)
3847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         *
3857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @see com.ibm.icu.dev.test.util.UnicodeProperty#getVersion()
3867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
3877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public String _getVersion() {
3887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return VersionInfo.ICU_VERSION.toString();
3897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert  /*{
3937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            matchIterator = new UnicodeSetIterator(
3947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                new UnicodeSet("[^[:Cn:]-[:Default_Ignorable_Code_Point:]]"));
3957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }*/
3967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
4007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Other Missing Functions:
4017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Expands_On_NFC
4027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Expands_On_NFD
4037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Expands_On_NFKC
4047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Expands_On_NFKD
4057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Composition_Exclusion
4067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Decomposition_Mapping
4077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            FC_NFKC_Closure
4087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ISO_Comment
4097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            NFC_Quick_Check
4107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            NFD_Quick_Check
4117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            NFKC_Quick_Check
4127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            NFKD_Quick_Check
4137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Special_Case_Condition
4147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Unicode_Radical_Stroke
4157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
4167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
4177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final Names Binary_Extras = new Names(UProperty.BINARY_LIMIT,
4187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          new String[] {
4197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          "isNFC", "isNFD", "isNFKC", "isNFKD",
4207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          "isLowercase", "isUppercase", "isTitlecase", "isCasefolded", "isCased",
4217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    });
4227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
4237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//    static final Names String_Extras = new Names(UProperty.STRING_LIMIT,
4247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//          new String[] {
4257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//          "toNFC", "toNFD", "toNFKC", "toNKFD",
4267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//    });
4277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
4287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final int
4297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        isNFC = UProperty.BINARY_LIMIT,
4307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        isNFD = UProperty.BINARY_LIMIT+1,
4317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        isNFKC = UProperty.BINARY_LIMIT+2,
4327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        isNFKD = UProperty.BINARY_LIMIT+3,
4337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        isLowercase = UProperty.BINARY_LIMIT+4,
4347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        isUppercase = UProperty.BINARY_LIMIT+5,
4357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        isTitlecase = UProperty.BINARY_LIMIT+6,
4367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        isCasefolded = UProperty.BINARY_LIMIT+7,
4377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        isCased = UProperty.BINARY_LIMIT+8,
4387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        BINARY_LIMIT = UProperty.BINARY_LIMIT+9
4397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
4407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//        NFC  = UProperty.STRING_LIMIT,
4417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//        NFD  = UProperty.STRING_LIMIT+1,
4427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//        NFKC = UProperty.STRING_LIMIT+2,
4437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//        NFKD = UProperty.STRING_LIMIT+3
4447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ;
4457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
4467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected ICUPropertyFactory() {
4477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Collection c = getInternalAvailablePropertyAliases(new ArrayList());
4487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Iterator it = c.iterator();
4497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (it.hasNext()) {
4507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            add(getInternalProperty((String) it.next()));
4517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
4527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
4537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
4547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static BitSet BITSET = new BitSet();
4557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static synchronized String getStringScriptExtensions(int codePoint) {
4567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int result = UScript.getScriptExtensions(codePoint, BITSET);
4577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (result >= 0) {
4587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return UScript.getName(result);
4597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
4607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        TreeMap<String,String> sorted = new TreeMap<String,String>();
4617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (int scriptCode = BITSET.nextSetBit(0); scriptCode >= 0; scriptCode = BITSET.nextSetBit(scriptCode+1)) {
4627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // sort by short form
4637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            sorted.put(UScript.getShortName(scriptCode), UScript.getName(scriptCode));
4647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
4657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return CollectionUtilities.join(sorted.values(), " ");
4667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
4677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
4687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static ICUPropertyFactory singleton = null;
4697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
4707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static synchronized ICUPropertyFactory make() {
4717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (singleton != null)
4727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return singleton;
4737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        singleton = new ICUPropertyFactory();
4747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return singleton;
4757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
4767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
4777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public List getInternalAvailablePropertyAliases(List result) {
4787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int[][] ranges = {
4797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                {UProperty.BINARY_START,    UProperty.BINARY_LIMIT},
4807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                {UProperty.INT_START,       UProperty.INT_LIMIT},
4817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                {UProperty.DOUBLE_START,    UProperty.DOUBLE_LIMIT},
4827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                {UProperty.STRING_START,    UProperty.STRING_LIMIT},
4837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                {UProperty.OTHER_PROPERTY_START, UProperty.OTHER_PROPERTY_LIMIT},
4847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
4857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        };
4867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (int i = 0; i < ranges.length; ++i) {
4877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (int j = ranges[i][0]; j < ranges[i][1]; ++j) {
4887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                String alias = UCharacter.getPropertyName(j, UProperty.NameChoice.LONG);
4897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                UnicodeProperty.addUnique(alias, result);
4907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (!result.contains(alias))
4917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    result.add(alias);
4927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
4937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
4947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // result.addAll(String_Extras.getNames());
4957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        result.addAll(Binary_Extras.getNames());
4967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return result;
4977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
4987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
4997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public UnicodeProperty getInternalProperty(String propertyAlias) {
5007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int propEnum;
5017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        main: {
5027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int possibleItem = Binary_Extras.get(propertyAlias);
5037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (possibleItem >= 0) {
5047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                propEnum = possibleItem;
5057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break main;
5067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
5077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // possibleItem = String_Extras.get(propertyAlias);
5087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // if (possibleItem >= 0) {
5097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // propEnum = possibleItem;
5107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // break main;
5117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // }
5127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            propEnum = UCharacter.getPropertyEnum(propertyAlias);
5137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
5147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return new ICUProperty(propertyAlias, propEnum);
5157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
5167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
5177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
5187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * (non-Javadoc)
5197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
5207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see com.ibm.icu.dev.test.util.UnicodePropertySource#getProperty(java.lang.String)
5217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
5227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // TODO file bug on getPropertyValueName for Canonical_Combining_Class
5237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static class Names {
5247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private String[] names;
5257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private int base;
5267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
5277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public Names(int base, String[] names) {
5287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            this.base = base;
5297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            this.names = names;
5307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
5317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
5327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public int get(String name) {
5337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (int i = 0; i < names.length; ++i) {
5347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (name.equalsIgnoreCase(names[i]))
5357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    return base + i;
5367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
5377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return -1;
5387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
5397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
5407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public String get(int number) {
5417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            number -= base;
5427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (number < 0 || names.length <= number)
5437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return null;
5447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return names[number];
5457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
5467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
5477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public boolean isInRange(int number) {
5487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            number -= base;
5497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return (0 <= number && number < names.length);
5507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
5517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
5527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public List getNames() {
5537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return Arrays.asList(names);
5547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
5557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
5567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
557