//##header
/*
 *******************************************************************************
 * Copyright (C) 1996-2006, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
//#ifndef FOUNDATION
package com.ibm.icu.dev.test.util;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.ParsePosition;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Pattern;

import com.ibm.icu.impl.Utility;
import com.ibm.icu.impl.CollectionUtilities.InverseMatcher;
import com.ibm.icu.impl.CollectionUtilities.ObjectMatcher;
import com.ibm.icu.text.SymbolTable;
import com.ibm.icu.text.UTF16;
import com.ibm.icu.text.UnicodeMatcher;
import com.ibm.icu.text.UnicodeSet;
import com.ibm.icu.text.UnicodeSetIterator;

public abstract class UnicodeProperty extends UnicodeLabel {

    public static boolean DEBUG = false;
    public static String CHECK_NAME = "FC_NFKC_Closure";
    public static int CHECK_VALUE = 0x037A;

    private String name;
    private String firstNameAlias = null;
    private int type;
    private Map valueToFirstValueAlias = null;
    
    /*
Name: Unicode_1_Name
Name: ISO_Comment
Name: Name
Name: Unicode_1_Name
     *
     */

    public static final int UNKNOWN = 0,
        BINARY = 2, EXTENDED_BINARY = 3,
        ENUMERATED = 4, EXTENDED_ENUMERATED = 5,
        CATALOG = 6, EXTENDED_CATALOG = 7,
        MISC = 8, EXTENDED_MISC = 9,
        STRING = 10, EXTENDED_STRING = 11,
        NUMERIC = 12, EXTENDED_NUMERIC = 13,
        START_TYPE = 2,
        LIMIT_TYPE = 14,
        EXTENDED_MASK = 1,
        CORE_MASK = ~EXTENDED_MASK,
        BINARY_MASK = (1<<BINARY) | (1<<EXTENDED_BINARY),
        STRING_MASK = (1<<STRING) | (1<<EXTENDED_STRING),
        STRING_OR_MISC_MASK = (1<<STRING) | (1<<EXTENDED_STRING)
            | (1<<MISC) | (1<<EXTENDED_MISC),
        ENUMERATED_OR_CATALOG_MASK = (1<<ENUMERATED) | (1<<EXTENDED_ENUMERATED)
            | (1<<CATALOG) | (1<<EXTENDED_CATALOG);


    private static final String[] TYPE_NAMES = {
        "Unknown",
        "Unknown",
        "Binary",
        "Extended Binary",
        "Enumerated",
        "Extended Enumerated",
        "Catalog",
        "Extended Catalog",
        "Miscellaneous",
        "Extended Miscellaneous",
        "String",
        "Extended String",
        "Numeric",
        "Extended Numeric",
    };

    public static String getTypeName(int propType) {
        return TYPE_NAMES[propType];
    }

    public final String getName() {
        return name;
    }

    public final int getType() {
        return type;
    }

    public final boolean isType(int mask) {
        return ((1<<type) & mask) != 0;
    }

    protected final void setName(String string) {
        if (string == null) throw new IllegalArgumentException("Name must not be null");
        name = string;
    }

    protected final void setType(int i) {
        type = i;
    }

    public String getVersion() {
        return _getVersion();
    }
    public String getValue(int codepoint) {
        if (DEBUG && CHECK_VALUE == codepoint && CHECK_NAME.equals(getName())) {
            String value = _getValue(codepoint);
            System.out.println(getName() + "(" + Utility.hex(codepoint) + "):" +
                (getType() == STRING ? Utility.hex(value) : value));
            return value;
        }
        return _getValue(codepoint);
    }

    //public String getValue(int codepoint, boolean isShort) {
    //	return getValue(codepoint);
    //}
    
    public List getNameAliases(List result) {
        if (result == null) result = new ArrayList(1);
        return _getNameAliases(result);
    }
    public List getValueAliases(String valueAlias, List result) {
        if (result == null) result = new ArrayList(1);
        result = _getValueAliases(valueAlias, result);
        if (!result.contains(valueAlias) ) { // FIX && type < NUMERIC 
        	result = _getValueAliases(valueAlias, result); // for debugging
            throw new IllegalArgumentException(
                "Internal error: " + getName() + " doesn't contain " + valueAlias
                + ": " + new BagFormatter().join(result));
        }
        return result;
    }
    public List getAvailableValues(List result) {
        if (result == null) result = new ArrayList(1);
        return _getAvailableValues(result);
    }

    protected abstract String _getVersion();
    protected abstract String _getValue(int codepoint);
    protected abstract List _getNameAliases(List result);
    protected abstract List _getValueAliases(String valueAlias, List result);
    protected abstract List _getAvailableValues(List result);

    // conveniences
    public final List getNameAliases() {
        return getNameAliases(null);
    }
    public final List getValueAliases(String valueAlias) {
        return getValueAliases(valueAlias, null);
    }
    public final List getAvailableValues() {
        return getAvailableValues(null);
    }
    
    public final String getValue(int codepoint, boolean getShortest) {
        String result = getValue(codepoint);
        if (type >= MISC || result == null || !getShortest) return result;
        return getFirstValueAlias(result);
    }

    public final String getFirstNameAlias() {
        if (firstNameAlias == null) {
            firstNameAlias = (String) getNameAliases().get(0);
        }
        return firstNameAlias;
    }

    public final String getFirstValueAlias(String value) {
        if (valueToFirstValueAlias == null) _getFirstValueAliasCache();
        return (String)valueToFirstValueAlias.get(value);
    }

    private void _getFirstValueAliasCache() {
        maxValueWidth = 0;
        maxFirstValueAliasWidth = 0;
        valueToFirstValueAlias = new HashMap(1);
        Iterator it = getAvailableValues().iterator();
        while (it.hasNext()) {
            String value = (String)it.next();
            String first = (String) getValueAliases(value).get(0);
            if (first == null) { // internal error
                throw new IllegalArgumentException("Value not in value aliases: " + value);
            }
            if (DEBUG && CHECK_NAME.equals(getName())) {
                System.out.println("First Alias: " + getName() + ": " + value + " => "
                 + first + new BagFormatter().join(getValueAliases(value)));
            }
            valueToFirstValueAlias.put(value,first);
            if (value.length() > maxValueWidth) {
                maxValueWidth = value.length();
            }
            if (first.length() > maxFirstValueAliasWidth) {
                maxFirstValueAliasWidth = first.length();
            }
        }
    }

    private int maxValueWidth = -1;
    private int maxFirstValueAliasWidth = -1;

    public int getMaxWidth(boolean getShortest) {
        if (maxValueWidth < 0) _getFirstValueAliasCache();
        if (getShortest) return maxFirstValueAliasWidth;
        return maxValueWidth;
    }

    public final UnicodeSet getSet(String propertyValue) {
        return getSet(propertyValue,null);
    }
    public final UnicodeSet getSet(PatternMatcher matcher) {
        return getSet(matcher,null);
    }

    public final UnicodeSet getSet(String propertyValue, UnicodeSet result) {
        return getSet(new SimpleMatcher(propertyValue,
            isType(STRING_OR_MISC_MASK) ? null : PROPERTY_COMPARATOR),
          result);
    }

    private UnicodeMap unicodeMap = null;

    public static final String UNUSED = "??";

    public final UnicodeSet getSet(PatternMatcher matcher, UnicodeSet result) {
        if (result == null) result = new UnicodeSet();
        if (isType(STRING_OR_MISC_MASK)) {
            for (int i = 0; i <= 0x10FFFF; ++i) {
                String value = getValue(i);
                if (value != null && matcher.matches(value)) {
                    result.add(i);
                }
            }
            return result;
        }
        List temp = new ArrayList(1); // to avoid reallocating...
        UnicodeMap um = getUnicodeMap_internal();
        Iterator it = um.getAvailableValues(null).iterator();
        main:
        while (it.hasNext()) {
            String value = (String)it.next();
            temp.clear();
            Iterator it2 = getValueAliases(value,temp).iterator();
            while (it2.hasNext()) {
                String value2 = (String)it2.next();
                //System.out.println("Values:" + value2);
                if (matcher.matches(value2)
                  || matcher.matches(toSkeleton(value2))) {
                    um.getSet(value, result);
                    continue main;
                }
            }
        }
        return result;
    }

    /*
    public UnicodeSet getMatchSet(UnicodeSet result) {
        if (result == null) result = new UnicodeSet();
        addAll(matchIterator, result);
        return result;
    }

    public void setMatchSet(UnicodeSet set) {
        matchIterator = new UnicodeSetIterator(set);
    }
    */

    /**
     * Utility for debugging
     */
    public static String getStack() {
        Exception e = new Exception();
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        e.printStackTrace(pw);
        pw.flush();
        return "Showing Stack with fake " + sw.getBuffer().toString();
    }

    // TODO use this instead of plain strings
    public static class Name implements Comparable {
        private static Map skeletonCache;
        private String skeleton;
        private String pretty;
        public final int RAW = 0, TITLE = 1, NORMAL = 2;
        public Name(String name, int style) {
            if (name == null) name = "";
            if (style == RAW) {
                skeleton = pretty = name;
            } else {
                pretty = regularize(name, style == TITLE);
                skeleton = toSkeleton(pretty);
            }
        }
        public int compareTo(Object o) {
            return skeleton.compareTo(((Name)o).skeleton);
        }
        public boolean equals(Object o) {
            return skeleton.equals(((Name)o).skeleton);
        }
        public int hashCode() {
            return skeleton.hashCode();
        }
        public String toString() {
            return pretty;
        }
    }

    /**
     * @return the unicode map
     */
    public UnicodeMap getUnicodeMap() {
        return getUnicodeMap(false);
    }
    
    /**
     * @return the unicode map
     */
    public UnicodeMap getUnicodeMap(boolean getShortest) {
    	if (!getShortest) return (UnicodeMap) getUnicodeMap_internal().cloneAsThawed();
        UnicodeMap result = new UnicodeMap();
        for (int i = 0; i <= 0x10FFFF; ++i) {
            //if (DEBUG && i == 0x41) System.out.println(i + "\t" + getValue(i));
            String value = getValue(i,true);
            result.put(i, value);
        }
        return result;
    }


    /**
     * @return the unicode map
     */
    protected UnicodeMap getUnicodeMap_internal() {
        if (unicodeMap == null) unicodeMap = _getUnicodeMap();
        return unicodeMap;
    }

    protected UnicodeMap _getUnicodeMap() {
        UnicodeMap result = new UnicodeMap();
        HashMap myIntern = new HashMap();
        for (int i = 0; i <= 0x10FFFF; ++i) {
            //if (DEBUG && i == 0x41) System.out.println(i + "\t" + getValue(i));
            String value = getValue(i);
            String iValue = (String) myIntern.get(value);
            if (iValue == null) myIntern.put(value, iValue = value);
            result.put(i, iValue);
        }
        if (DEBUG) {
            for (int i = 0; i <= 0x10FFFF; ++i) {
                //if (DEBUG && i == 0x41) System.out.println(i + "\t" + getValue(i));
                String value = getValue(i);
                String resultValue = (String) result.getValue(i);
                if (!value.equals(resultValue)) {
                	throw new RuntimeException("Value failure at: " + Utility.hex(i));
                }
            }
        }
        if (DEBUG && CHECK_NAME.equals(getName())) {
            System.out.println(getName() + ":\t" + getClass().getName()
                 + "\t" + getVersion());
            System.out.println(getStack());
            System.out.println(result);
        }
        return result;
    }
    
    /**
     * Really ought to create a Collection UniqueList, that forces uniqueness. But for now...
     */
    public static Collection addUnique(Object obj, Collection result) {
        if (obj != null && !result.contains(obj)) result.add(obj);
        return result;
    }

    /**
     * Utility for managing property & non-string value aliases
     */
    public static final Comparator PROPERTY_COMPARATOR = new Comparator() {
        public int compare(Object o1, Object o2) {
            return compareNames((String)o1, (String)o2);
        }
    };

    /**
     * Utility for managing property & non-string value aliases
     *
     */
    // TODO optimize
    public static boolean equalNames(String a, String b) {
        if (a == b) return true;
        if (a == null) return false;
         return toSkeleton(a).equals(toSkeleton(b));
    }

    /**
     * Utility for managing property & non-string value aliases
     */
    // TODO optimize
    public static int compareNames(String a, String b) {
        if (a == b) return 0;
        if (a == null) return -1;
        if (b == null) return 1;
        return toSkeleton(a).compareTo(toSkeleton(b));
    }

    /**
     * Utility for managing property & non-string value aliases
     */
    // TODO account for special names, tibetan, hangul
    public static String toSkeleton(String source) {
        if (source == null) return null;
        StringBuffer skeletonBuffer = new StringBuffer();
        boolean gotOne = false;
        // remove spaces, '_', '-'
        // we can do this with char, since no surrogates are involved
        for (int i = 0; i < source.length(); ++i) {
            char ch = source.charAt(i);
            if (i > 0 && (ch == '_' || ch == ' ' || ch == '-')) {
                gotOne = true;
            } else {
                char ch2 = Character.toLowerCase(ch);
                if (ch2 != ch) {
                    gotOne = true;
                    skeletonBuffer.append(ch2);
                } else {
                    skeletonBuffer.append(ch);
                }
            }
        }
        if (!gotOne) return source; // avoid string creation
        return skeletonBuffer.toString();
    }

    // get the name skeleton
    public static String toNameSkeleton(String source) {
        if (source == null) return null;
        StringBuffer result = new StringBuffer();
        // remove spaces, medial '-'
        // we can do this with char, since no surrogates are involved
        for (int i = 0; i < source.length(); ++i) {
            char ch = source.charAt(i);
            if (('0' <= ch && ch <= '9') || ('A' <= ch && ch <= 'Z') || ch == '<' || ch == '>') {
                result.append(ch);
            } else if (ch == ' ') {
                // don't copy ever
            } else if (ch == '-') {
                // only copy non-medials AND trailing O-E
                if (0 == i
                    || i == source.length() - 1
                    || source.charAt(i-1) == ' '
                    || source.charAt(i+1) == ' '
                    || (i == source.length() - 2
                        && source.charAt(i-1) == 'O'
                        && source.charAt(i+1) == 'E')) {
                    System.out.println("****** EXCEPTION " + source);
                    result.append(ch);
                }
                // otherwise don't copy
            } else {
                throw new IllegalArgumentException("Illegal Name Char: U+" + Utility.hex(ch) + ", " + ch);
            }
        }
        return result.toString();
    }

    /**
     * These routines use the Java functions, because they only need to act on ASCII
     * Changes space, - into _, inserts _ between lower and UPPER.
     */
    public static String regularize(String source, boolean titlecaseStart) {
        if (source == null) return source;
        /*if (source.equals("noBreak")) { // HACK
            if (titlecaseStart) return "NoBreak";
            return source;
        }
        */
        StringBuffer result = new StringBuffer();
        int lastCat = -1;
        boolean haveFirstCased = true;
        for (int i = 0; i < source.length(); ++i) {
            char c = source.charAt(i);
            if (c == ' ' || c == '-' || c == '_') {
                c = '_';
                haveFirstCased = true;
            }
            if (c == '=') haveFirstCased = true;
            int cat = Character.getType(c);
            if (lastCat == Character.LOWERCASE_LETTER && cat == Character.UPPERCASE_LETTER) {
                result.append('_');
            }
            if (haveFirstCased && (cat == Character.LOWERCASE_LETTER
                    || cat == Character.TITLECASE_LETTER || cat == Character.UPPERCASE_LETTER)) {
                if (titlecaseStart) {
                    c = Character.toUpperCase(c);
                }
                haveFirstCased = false;
            }
            result.append(c);
            lastCat = cat;
        }
        return result.toString();
    }

    /**
     * Utility function for comparing codepoint to string without
     * generating new string.
     * @param codepoint
     * @param other
     * @return true if the codepoint equals the string
     */
    public static final boolean equals(int codepoint, String other) {
        if (other.length() == 1) {
            return codepoint == other.charAt(0);
        }
        if (other.length() == 2) {
            return other.equals(UTF16.valueOf(codepoint));
        }
        return false;
    }

    /**
     * Utility that should be on UnicodeSet
     * @param source
     * @param result
     */
    static public void addAll(UnicodeSetIterator source, UnicodeSet result) {
        while (source.nextRange()) {
            if (source.codepoint == UnicodeSetIterator.IS_STRING) {
                result.add(source.string);
            } else {
                result.add(source.codepoint, source.codepointEnd);
            }
        }
    }

    /**
     * Really ought to create a Collection UniqueList, that forces uniqueness. But for now...
     */
    public static Collection addAllUnique(Collection source, Collection result) {
        for (Iterator it = source.iterator(); it.hasNext();) {
            addUnique(it.next(), result);
        }
        return result;
    }

    /**
     * Really ought to create a Collection UniqueList, that forces uniqueness. But for now...
     */
    public static Collection addAllUnique(Object[] source, Collection result) {
        for (int i = 0; i < source.length; ++i) {
            addUnique(source[i], result);
        }
        return result;
    }
    
    static public class Factory {
        static boolean DEBUG = false;

        Map canonicalNames = new TreeMap();
        Map skeletonNames = new TreeMap();
        Map propertyCache = new HashMap(1);

        public final Factory add(UnicodeProperty sp) {
            canonicalNames.put(sp.getName(), sp);
            List c = sp.getNameAliases(new ArrayList(1));
            Iterator it = c.iterator();
            while (it.hasNext()) {
                skeletonNames.put(toSkeleton((String)it.next()), sp);
            }
            return this;
        }

        public final UnicodeProperty getProperty(String propertyAlias) {
            return (UnicodeProperty) skeletonNames.get(toSkeleton(propertyAlias));
        }

        public final List getAvailableNames() {
            return getAvailableNames(null);
        }

        public final List getAvailableNames(List result) {
            if (result == null) result = new ArrayList(1);
            Iterator it = canonicalNames.keySet().iterator();
            while (it.hasNext()) {
                addUnique(it.next(), result);
            }
            return result;
        }

        public final List getAvailableNames(int propertyTypeMask) {
            return getAvailableNames(propertyTypeMask, null);
        }

        public final List getAvailableNames(int propertyTypeMask, List result) {
            if (result == null) result = new ArrayList(1);
            Iterator it = canonicalNames.keySet().iterator();
            while (it.hasNext()) {
                String item = (String)it.next();
                UnicodeProperty property = getProperty(item);
                if (DEBUG) System.out.println("Properties: " + item + "," + property.getType());
                if (!property.isType(propertyTypeMask)) {
                    //System.out.println("Masking: " + property.getType() + "," + propertyTypeMask);
                    continue;
                }
                addUnique(property.getName(), result);
            }
            return result;
        }
        InversePatternMatcher inverseMatcher = new InversePatternMatcher();
        /**
         * Format is:
         *    propname ('=' | '!=') propvalue ( '|' propValue )*
         */
        public final UnicodeSet getSet(String propAndValue, PatternMatcher matcher, UnicodeSet result) {
            int equalPos = propAndValue.indexOf('=');
            String prop = propAndValue.substring(0,equalPos);
            String value = propAndValue.substring(equalPos+1);
            boolean negative = false;
            if (prop.endsWith("!")) {
                prop = prop.substring(0,prop.length()-1);
                negative = true;
            }
            prop = prop.trim();
            UnicodeProperty up = getProperty(prop);
            if (matcher == null) {
                matcher = new SimpleMatcher(value,
                up.isType(STRING_OR_MISC_MASK) ? null : PROPERTY_COMPARATOR);
            }
            if (negative) {
                inverseMatcher.set(matcher);
                matcher = inverseMatcher;
            }
            return up.getSet(matcher.set(value), result);
        }

        public final UnicodeSet getSet(String propAndValue, PatternMatcher matcher) {
            return getSet(propAndValue, matcher, null);
        }
        public final UnicodeSet getSet(String propAndValue) {
            return getSet(propAndValue, null, null);
        }

        public final SymbolTable getSymbolTable(String prefix) {
            return new PropertySymbolTable(prefix);
        }
        
        private class MyXSymbolTable extends UnicodeSet.XSymbolTable {
            public boolean applyPropertyAlias(String propertyName, String propertyValue, UnicodeSet result) {
            	if (false) System.out.println(propertyName + "=" + propertyValue);
            	UnicodeProperty prop = getProperty(propertyName);
            	if (prop == null) return false;
            	result.clear();
            	UnicodeSet x = prop.getSet(propertyValue, result);
                return x.size() != 0;
            }
        }

        public final UnicodeSet.XSymbolTable getXSymbolTable() {
        	return new MyXSymbolTable();
        }
        
        private class PropertySymbolTable implements SymbolTable  {
        	static final boolean DEBUG = false;
            private String prefix;
            RegexMatcher regexMatcher = new RegexMatcher();

            PropertySymbolTable (String prefix) {
                this.prefix = prefix;
            }

            public char[] lookup(String s) {
                if (DEBUG) System.out.println("\t(" + prefix + ")Looking up " + s);
                // ensure, again, that prefix matches
                int start = prefix.length();
                if (!s.regionMatches(true, 0, prefix, 0, start)) return null;

                int pos = s.indexOf(':', start);
                if (pos < 0) { // should never happen
                    throw new IllegalArgumentException("Internal Error: missing =: " + s + "\r\n");
                }
                UnicodeProperty prop = getProperty(s.substring(start,pos));
                if (prop == null) {
                    throw new IllegalArgumentException("Invalid Property in: " + s + "\r\nUse "
                     + showSet(getAvailableNames()));
                }
                String value = s.substring(pos+1);
                UnicodeSet set;
                if (value.startsWith("\u00AB")) {   // regex!
                    set = prop.getSet(regexMatcher.set(value.substring(1, value.length()-1)));
                } else {
                    set = prop.getSet(value);
                }
                if (set.size() == 0) {
                    throw new IllegalArgumentException("Empty Property-Value in: " + s + "\r\nUse "
                        + showSet(prop.getAvailableValues()));
                }
                if (DEBUG) System.out.println("\t(" + prefix + ")Returning " + set.toPattern(true));
                return set.toPattern(true).toCharArray(); // really ugly
            }

            private String showSet(List list) {
                StringBuffer result = new StringBuffer("[");
                boolean first = true;
                for (Iterator it = list.iterator(); it.hasNext();) {
                    if (!first) result.append(", ");
                    else first = false;
                    result.append(it.next().toString());
                }
                result.append("]");
                return result.toString();
            }

            public UnicodeMatcher lookupMatcher(int ch) {
                return null;
            }

            public String parseReference(String text, ParsePosition pos, int limit) {
                if (DEBUG) System.out.println("\t(" + prefix + ")Parsing <" + text.substring(pos.getIndex(),limit) + ">");
                int start = pos.getIndex();
                int veryStart = start;
                // ensure that it starts with 'prefix'
                if (!text.regionMatches(true, start, prefix, 0, prefix.length())) return null;
                start += prefix.length();
                // now see if it is of the form identifier:identifier
                int i = getIdentifier(text, start, limit);
                if (i == start) return null;
                String prop = text.substring(start, i);
                String value = "true";
                if (i < limit) {
                    if (text.charAt(i) == ':') {
                        int j;
                        if (text.charAt(i+1) == '\u00AB') { // regular expression
                            j = text.indexOf('\u00BB', i+2) + 1; // include last character
                            if (j <= 0) return null;
                        } else {
                            j = getIdentifier(text, i+1, limit);
                        }
                        value = text.substring(i+1, j);
                        i = j;
                    }
                }
                pos.setIndex(i);
                if (DEBUG) System.out.println("\t(" + prefix + ")Parsed <" + prop + ">=<" + value + ">");
                return prefix + prop + ":" + value;
            }

            private int getIdentifier(String text, int start, int limit) {
                if (DEBUG) System.out.println("\tGetID <" + text.substring(start,limit) + ">");
                int cp = 0;
                int i;
                for (i = start; i < limit; i += UTF16.getCharCount(cp)) {
                    cp = UTF16.charAt(text, i);
                    if (!com.ibm.icu.lang.UCharacter.isUnicodeIdentifierPart(cp) && cp != '.') {
                        break;
                    }
                }
                if (DEBUG) System.out.println("\tGotID <" + text.substring(start,i) + ">");
                return i;
            }
        }
    }


    public static class FilteredProperty extends UnicodeProperty {
        private UnicodeProperty property;
        protected StringFilter filter;
        protected UnicodeSetIterator matchIterator = new UnicodeSetIterator(new UnicodeSet(0,0x10FFFF));
        protected HashMap backmap;
        boolean allowValueAliasCollisions = false;

        public FilteredProperty(UnicodeProperty property, StringFilter filter) {
            this.property = property;
            this.filter = filter;
        }

        public StringFilter getFilter() {
            return filter;
        }

        public UnicodeProperty setFilter(StringFilter filter) {
            this.filter = filter;
            return this;
        }

        List temp = new ArrayList(1);

        public List _getAvailableValues(List result) {
            temp.clear();
            return filter.addUnique(property.getAvailableValues(temp), result);
        }

        public List _getNameAliases(List result) {
            temp.clear();
            return filter.addUnique(
                property.getNameAliases(temp), result);
        }

        public String _getValue(int codepoint) {
            return filter.remap(property.getValue(codepoint));
        }

        public List _getValueAliases(String valueAlias, List result) {
            if (backmap == null) {
                backmap = new HashMap(1);
                temp.clear();
                Iterator it = property.getAvailableValues(temp).iterator();
                while (it.hasNext()) {
                    String item = (String) it.next();
                    String mappedItem = filter.remap(item);
                    if (backmap.get(mappedItem) != null && !allowValueAliasCollisions) {
                        throw new IllegalArgumentException("Filter makes values collide! "
                            + item + ", " + mappedItem);
                    }
                    backmap.put(mappedItem, item);
                }
            }
            valueAlias = (String) backmap.get(valueAlias);
            temp.clear();
            return filter.addUnique(property.getValueAliases(valueAlias, temp), result);
        }

        public String _getVersion() {
            return property.getVersion();
        }

        public boolean isAllowValueAliasCollisions() {
            return allowValueAliasCollisions;
        }

        public FilteredProperty setAllowValueAliasCollisions(boolean b) {
            allowValueAliasCollisions = b;
            return this;
        }

    }

    public static abstract class StringFilter implements Cloneable {
        public abstract String remap(String original);

        public final List addUnique(Collection source, List result) {
            if (result == null) result = new ArrayList(1);
            Iterator it = source.iterator();
            while (it.hasNext()) {
                UnicodeProperty.addUnique(
                    remap((String) it.next()), result);
            }
            return result;
        }
        /*
         public Object clone() {
            try {
                return super.clone();
            } catch (CloneNotSupportedException e) {
                throw new IllegalStateException("Should never happen.");
            }
        }
        */
    }

    public static class MapFilter extends StringFilter {
        private Map valueMap;
        public MapFilter(Map valueMap){
            this.valueMap = valueMap;
        }
        public String remap(String original) {
            Object changed = valueMap.get(original);
            return changed == null ? original : (String) changed;
        }
        public Map getMap() {
            return valueMap;
        }
    }

    public interface PatternMatcher extends ObjectMatcher {
        public PatternMatcher set(String pattern);
    }

    public static class InversePatternMatcher extends InverseMatcher implements PatternMatcher {
        PatternMatcher other;
        public PatternMatcher set(PatternMatcher toInverse) {
            other = toInverse;
            return this;
        }
        public boolean matches(Object value) {
            return !other.matches(value);
        }
        public PatternMatcher set(String pattern) {
            other.set(pattern);
            return this;
        }
    }

    public static class SimpleMatcher implements PatternMatcher {
        Comparator comparator;
        String pattern;
        public SimpleMatcher(String pattern, Comparator comparator) {
            this.comparator = comparator;
            this.pattern = pattern;
        }
        public boolean matches(Object value) {
            if (comparator == null) return pattern.equals(value);
            return comparator.compare(pattern, value) == 0;
        }
        public PatternMatcher set(String pattern) {
            this.pattern = pattern;
            return this;
        }
    }

    public static class RegexMatcher implements UnicodeProperty.PatternMatcher {
        private java.util.regex.Matcher matcher;

        public UnicodeProperty.PatternMatcher set(String pattern) {
            matcher = Pattern.compile(pattern).matcher("");
            return this;
        }
        public boolean matches(Object value) {
            matcher.reset(value.toString());
            return matcher.matches();
        }
    }
    
    public static abstract class BaseProperty extends UnicodeProperty {
        protected List propertyAliases = new ArrayList(1);
        protected Map toValueAliases;
        protected String version;
        
        public BaseProperty setMain(String alias, String shortAlias, int propertyType,
                String version) {
                  setName(alias);
                  setType(propertyType);
                  propertyAliases.add(shortAlias);
                  propertyAliases.add(alias);
                  this.version = version;
                  return this;
        }    	
        public String _getVersion() {
            return version;
        }
        public List _getNameAliases(List result) {
            addAllUnique(propertyAliases, result);
            return result;
        }
        public BaseProperty addValueAliases(String[][] valueAndAlternates, boolean errorIfCant) {
        	if (toValueAliases == null) _fixValueAliases();
            for (int i = 0; i < valueAndAlternates.length; ++i) {
            	for (int j = 1; j < valueAndAlternates[0].length; ++j) {
            		addValueAlias(valueAndAlternates[i][0], valueAndAlternates[i][j], errorIfCant);
            	}
            }
            return this;
        }
		public void addValueAlias(String value, String valueAlias, boolean errorIfCant) {
    		List result = (List) toValueAliases.get(value);
    		if (result == null && !errorIfCant) return;
    		addUnique(value, result);
    		addUnique(valueAlias, result);
		}
		protected List _getValueAliases(String valueAlias, List result) {
			if (toValueAliases == null) _fixValueAliases();
            List a = (List) toValueAliases.get(valueAlias);
            if (a != null) addAllUnique(a, result);
            return result;
        }

		protected void _fixValueAliases() {
			if (toValueAliases == null) toValueAliases = new HashMap(1);
			for (Iterator it = getAvailableValues().iterator(); it.hasNext();) {
				Object value = it.next();
				List result;
				_ensureValueInAliases(value);
			}
		}
		protected void _ensureValueInAliases(Object value) {
			List result = (List) toValueAliases.get(value);
			if (result == null) toValueAliases.put(value, result = new ArrayList(1));
			addUnique(value, result);
		}
        public BaseProperty swapFirst2ValueAliases() {
        	for (Iterator it = toValueAliases.keySet().iterator(); it.hasNext();) {
        		List list = (List) toValueAliases.get(it.next());
        		if (list.size() < 2) continue;
        		Object first = list.get(0);
        		list.set(0, list.get(1));
        		list.set(1, first);
        	}
        	return this;
        }


    }
    
    public static abstract class SimpleProperty extends BaseProperty {
        List values;

        public SimpleProperty addName(String alias) {
            propertyAliases.add(alias);
            return this;
        }

        public SimpleProperty setValues(String valueAlias) {
            _addToValues(valueAlias, null);
            return this;
        }

        public SimpleProperty setValues(String[] valueAliases, String[] alternateValueAliases) {
            for (int i = 0; i < valueAliases.length; ++i) {
                if (valueAliases[i].equals(UNUSED)) continue;
                _addToValues(valueAliases[i],
                    alternateValueAliases != null ? alternateValueAliases[i] : null);
            }
            return this;
        }
        
        public SimpleProperty setValues(List valueAliases) {
            this.values = new ArrayList(valueAliases);
            for (Iterator it = this.values.iterator(); it.hasNext(); ) {
                _addToValues((String)it.next(), null);
            }
            return this;
        }

        public List _getAvailableValues(List result) {
            if (values == null) _fillValues();
            result.addAll(values);
            return result;
        }


        protected void _fillValues() {
            List newvalues = (List) getUnicodeMap_internal().getAvailableValues(new ArrayList());
            for (Iterator it = newvalues.iterator(); it.hasNext();) {
                _addToValues((String)it.next(), null);
            }
        }
        
        private void _addToValues(String item, String alias) {
            if (values == null) values = new ArrayList(1);
            if (toValueAliases == null) _fixValueAliases();
            addUnique(item, values);
            _ensureValueInAliases(item);
            addValueAlias(item, alias, true);
        }
/*        public String _getVersion() {
            return version;
        }
*/    }
    
    public static class UnicodeMapProperty extends BaseProperty {
    	/*
    	 * Example of usage:
    	 * new UnicodeProperty.UnicodeMapProperty() {
        	{
        		unicodeMap = new UnicodeMap();
        		unicodeMap.setErrorOnReset(true);
        		unicodeMap.put(0xD, "CR");
        		unicodeMap.put(0xA, "LF");
        		UnicodeProperty cat = getProperty("General_Category");
        		UnicodeSet temp = cat.getSet("Line_Separator")
				.addAll(cat.getSet("Paragraph_Separator"))
				.addAll(cat.getSet("Control"))
				.addAll(cat.getSet("Format"))
				.remove(0xD).remove(0xA).remove(0x200C).remove(0x200D);
        		unicodeMap.putAll(temp, "Control");
        		UnicodeSet graphemeExtend = getProperty("Grapheme_Extend").getSet("true");
        		unicodeMap.putAll(graphemeExtend,"Extend");
        		UnicodeProperty hangul = getProperty("Hangul_Syllable_Type");
        		unicodeMap.putAll(hangul.getSet("L"),"L");
        		unicodeMap.putAll(hangul.getSet("V"),"V");
        		unicodeMap.putAll(hangul.getSet("T"),"T");
        		unicodeMap.putAll(hangul.getSet("LV"),"LV");
        		unicodeMap.putAll(hangul.getSet("LVT"),"LVT");
        		unicodeMap.setMissing("Other");
        	}
        }.setMain("Grapheme_Cluster_Break", "GCB", UnicodeProperty.ENUMERATED, version)
    	 */
        protected UnicodeMap unicodeMap;
        
        public UnicodeMapProperty set(UnicodeMap map) {
        	unicodeMap = map;
        	return this;
        }

        protected String _getValue(int codepoint) {
            return (String) unicodeMap.getValue(codepoint);
        }
/*		protected List _getValueAliases(String valueAlias, List result) {
			if (!unicodeMap.getAvailableValues().contains(valueAlias)) return result;
			result.add(valueAlias);
			return result; // no other aliases
		}
*/		protected List _getAvailableValues(List result) {
			return (List) unicodeMap.getAvailableValues(result);
		}
    }
}
//#endif


