//##header J2SE15
//#if defined(FOUNDATION10) || defined(J2SE13)
//#else
/*
 *******************************************************************************
 * Copyright (C) 1996-2007, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
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.dev.test.util.CollectionUtilities.InverseMatcher;
import com.ibm.icu.dev.test.util.CollectionUtilities.ObjectMatcher;
import com.ibm.icu.impl.Utility;
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 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();
        // 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();
        _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

