17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Copyright (C) 2002-2012, International Business Machines Corporation and    *
57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * others. All Rights Reserved.                                                *
67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.dev.util;
97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Arrays;
117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.List;
127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Locale;
137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Map;
147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Set;
157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.lang.UCharacter;
177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.lang.UProperty;
187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.Normalizer;
197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.UTF16;
207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.UnicodeSet;
217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.UnicodeSetIterator;
227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/**
257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Provides a general interface for Unicode Properties, and
267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * extracting sets based on those values.
277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @author Davis
287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic abstract class UnicodePropertySource implements Cloneable {
307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected String propertyAlias;
327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected int m_nameChoice = UProperty.NameChoice.LONG;
337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected StringFilter filter = new StringFilter();
347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected UnicodeSetIterator matchIterator = new UnicodeSetIterator(new UnicodeSet(0,0x10FFFF));
357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    abstract public String getPropertyValue(int codepoint);
377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    abstract public Set getAvailablePropertyAliases(Set result);
387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    abstract public Set getAvailablePropertyValueAliases(Set result);
397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    abstract public String getPropertyAlias(int nameChoice);
417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    abstract public String getPropertyValueAlias(String valueAlias, int nameChoice);
427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Subclasses should override
457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public Object clone() {
477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        try {
487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            UnicodePropertySource result = (UnicodePropertySource)super.clone();
497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            result.filter = (StringFilter)filter.clone();
507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return result;
517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } catch (CloneNotSupportedException e) {
527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            throw new IllegalStateException("Should never happen.");
537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public UnicodePropertySource setPropertyAlias(String propertyAlias) {
577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        this.propertyAlias = propertyAlias;
587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return this;
597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public String getPropertyAlias() {
627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return propertyAlias;
637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static final boolean equals(int codepoint, String other) {
667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (other.length() == 1) {
677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return codepoint == other.charAt(0);
687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return other.equals(UTF16.valueOf(codepoint));
707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public UnicodeSet getPropertySet(boolean charEqualsValue, UnicodeSet result){
737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (result == null) result = new UnicodeSet();
747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        matchIterator.reset();
757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (matchIterator.next()) {
767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String value = filter.remap(getPropertyValue(matchIterator.codepoint));
777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (equals(matchIterator.codepoint, value) == charEqualsValue) {
787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.add(matchIterator.codepoint);
797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return result;
827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public UnicodeSet getPropertySet(String propertyValue, UnicodeSet result){
857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (result == null) result = new UnicodeSet();
867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        matchIterator.reset();
877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (matchIterator.next()) {
887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String value = filter.remap(getPropertyValue(matchIterator.codepoint));
897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (propertyValue.equals(value)) {
907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.add(matchIterator.codepoint);
917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return result;
947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public UnicodeSet getPropertySet(Matcher matcher, UnicodeSet result) {
977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (result == null) result = new UnicodeSet();
987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        matchIterator.reset();
997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (matchIterator.next()) {
1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String value = filter.remap(getPropertyValue(matchIterator.codepoint));
1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (value == null)
1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                continue;
1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (matcher.matches(value)) {
1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.add(matchIterator.codepoint);
1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return result;
1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public interface Matcher {
1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public boolean matches(String value);
1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int getNameChoice() {
1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return m_nameChoice;
1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public UnicodePropertySource setNameChoice(int choice) {
1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        m_nameChoice = choice;
1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return this;
1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static class StringFilter implements Cloneable {
1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public String remap(String original) {
1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return original;
1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public Object clone() {
1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            try {
1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return super.clone();
1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } catch (CloneNotSupportedException e) {
1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                throw new IllegalStateException("Should never happen.");
1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static class MapFilter extends StringFilter {
1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Map valueMap;
1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public String remap(String original) {
1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Object changed = valueMap.get(original);
1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return changed == null ? original : (String) changed;
1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public Map getMap() {
1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return valueMap;
1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public MapFilter setMap(Map map) {
1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            valueMap = map;
1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return this;
1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static public class ICU extends UnicodePropertySource {
1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected int propEnum = Integer.MIN_VALUE;
1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {
1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            matchIterator = new UnicodeSetIterator(
1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                new UnicodeSet("[^[:Cn:]-[:Default_Ignorable_Code_Point:]]"));
1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public UnicodePropertySource setPropertyAlias(String propertyAlias) {
1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super.setPropertyAlias(propertyAlias);
1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int extraPosition = Extras.indexOf(propertyAlias);
1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (extraPosition >= 0) {
1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                propEnum = EXTRA_START + extraPosition;
1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                propEnum = UCharacter.getPropertyEnum(propertyAlias);
1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return this;
1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public String getPropertyValue(int codePoint) {
1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (propEnum < UProperty.INT_LIMIT) {
1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int enumValue = UCharacter.getIntPropertyValue(codePoint, propEnum);
1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UCharacter.getPropertyValueName(propEnum,enumValue, (int)m_nameChoice);
1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (propEnum < UProperty.DOUBLE_LIMIT) {
1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return Double.toString(UCharacter.getUnicodeNumericValue(codePoint));
1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // TODO: Fix HACK -- API deficient
1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else switch(propEnum) {
1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case UProperty.AGE: return UCharacter.getAge(codePoint).toString();
1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case UProperty.BIDI_MIRRORING_GLYPH: return UTF16.valueOf(UCharacter.getMirror(codePoint));
1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case UProperty.CASE_FOLDING: return UCharacter.foldCase(UTF16.valueOf(codePoint),true);
1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case UProperty.ISO_COMMENT: return UCharacter.getISOComment(codePoint);
1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case UProperty.LOWERCASE_MAPPING: return UCharacter.toLowerCase(Locale.ENGLISH,UTF16.valueOf(codePoint));
1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case UProperty.NAME: return UCharacter.getName(codePoint);
1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case UProperty.SIMPLE_CASE_FOLDING: return UTF16.valueOf(UCharacter.foldCase(codePoint,true));
1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case UProperty.SIMPLE_LOWERCASE_MAPPING: return UTF16.valueOf(UCharacter.toLowerCase(codePoint));
1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case UProperty.SIMPLE_TITLECASE_MAPPING: return UTF16.valueOf(UCharacter.toTitleCase(codePoint));
1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case UProperty.SIMPLE_UPPERCASE_MAPPING: return UTF16.valueOf(UCharacter.toUpperCase(codePoint));
1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case UProperty.TITLECASE_MAPPING: return UCharacter.toTitleCase(Locale.ENGLISH,UTF16.valueOf(codePoint),null);
1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case UProperty.UNICODE_1_NAME: return UCharacter.getName1_0(codePoint);
1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case UProperty.UPPERCASE_MAPPING: return UCharacter.toUpperCase(Locale.ENGLISH,UTF16.valueOf(codePoint));
1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case NFC: return Normalizer.normalize(codePoint, Normalizer.NFC);
1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case NFD: return Normalizer.normalize(codePoint, Normalizer.NFD);
1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case NFKC: return Normalizer.normalize(codePoint, Normalizer.NFKC);
1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case NFKD: return Normalizer.normalize(codePoint, Normalizer.NFKD);
1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return null;
1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        static final List Extras = Arrays.asList(new String[] {
2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            "NFC", "NFD", "NFKC", "NKFD"
2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        });
2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        static final int
2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            NFC  = 0x8000,
2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            NFD  = 0x8001,
2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            NFKC = 0x8002,
2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            NFKD = 0x8003,
2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            EXTRA_START = NFC,
2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            EXTRA_LIMIT = NFKD+1;
2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        static final int[][] ranges = {
2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            {UProperty.BINARY_START,    UProperty.BINARY_LIMIT},
2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            {UProperty.INT_START,       UProperty.INT_LIMIT},
2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            {UProperty.DOUBLE_START,    UProperty.DOUBLE_LIMIT},
2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            {UProperty.STRING_START,    UProperty.STRING_LIMIT},
2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        };
2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public Set getAvailablePropertyAliases(Set result) {
2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (int i = 0; i < ranges.length; ++i) {
2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                for (int j = ranges[i][0]; j < ranges[i][1]; ++j) {
2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    result.add(UCharacter.getPropertyName(j, m_nameChoice));
2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            result.addAll(Extras);
2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return result;
2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public Set getAvailablePropertyValueAliases(Set result) {
2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (propEnum < UProperty.INT_LIMIT) {
2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int start = UCharacter.getIntPropertyMinValue(propEnum);
2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int end = UCharacter.getIntPropertyMaxValue(propEnum);
2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                for (int i = start; i <= end; ++i) {
2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    result.add(getFixedValueAlias(null, i,m_nameChoice));
2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.add(getFixedValueAlias(null, -1,m_nameChoice));
2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return result;
2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /**
2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @param valueAlias null if unused.
2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @param valueEnum -1 if unused
2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @param nameChoice
2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * @return the alias
2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private String getFixedValueAlias(String valueAlias, int valueEnum, int nameChoice) {
2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (propEnum >= UProperty.STRING_START) {
2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return "<string>";
2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (propEnum >= UProperty.DOUBLE_START) {
2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return "<double>";
2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (valueAlias != null && !valueAlias.equals("<integer>")) {
2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                valueEnum = UCharacter.getPropertyValueEnum(propEnum,valueAlias);
2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String result = fixedGetPropertyValueName(propEnum, valueEnum, nameChoice);
2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (result != null) return result;
2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // try other namechoice
2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            result = fixedGetPropertyValueName(propEnum,valueEnum,
2607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                nameChoice == UProperty.NameChoice.LONG ? UProperty.NameChoice.SHORT : UProperty.NameChoice.LONG);
2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (result != null) return result;
2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return "<integer>";
2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static String fixedGetPropertyValueName(int propEnum, int valueEnum, int nameChoice) {
2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            try {
2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UCharacter.getPropertyValueName(propEnum,valueEnum,nameChoice);
2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } catch (Exception e) {
2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return null;
2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public String getPropertyAlias(int nameChoice) {
2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (propEnum < EXTRA_START) {
2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return UCharacter.getPropertyName(propEnum, nameChoice);
2767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return (String)Extras.get(propEnum-EXTRA_START);
2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public String getPropertyValueAlias(String valueAlias, int nameChoice) {
2817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return getFixedValueAlias(valueAlias, -1, nameChoice);
2827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // TODO file bug on getPropertyValueName for Canonical_Combining_Class
2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public StringFilter getFilter() {
2877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return filter;
2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public UnicodePropertySource setFilter(StringFilter filter) {
2927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        this.filter = filter;
2937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return this;
2947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
2977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
2987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static public void addAll(UnicodeSetIterator source, UnicodeSet result) {
2997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (source.nextRange()) {
3007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (source.codepoint == UnicodeSetIterator.IS_STRING) {
3017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.add(source.string);
3027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.add(source.codepoint, source.codepointEnd);
3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public UnicodeSet getMatchSet(UnicodeSet result) {
3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (result == null) result = new UnicodeSet();
3107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        addAll(matchIterator, result);
3117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return result;
3127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
3157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param set
3167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
3177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setMatchSet(UnicodeSet set) {
3187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        matchIterator = new UnicodeSetIterator(set);
3197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
322