diff --git a/UnicodeJsps/src/main/java/org/unicode/jsp/UnicodeSetUtilities.java b/UnicodeJsps/src/main/java/org/unicode/jsp/UnicodeSetUtilities.java index 1b57ab096e..34eed8b30d 100644 --- a/UnicodeJsps/src/main/java/org/unicode/jsp/UnicodeSetUtilities.java +++ b/UnicodeJsps/src/main/java/org/unicode/jsp/UnicodeSetUtilities.java @@ -7,14 +7,15 @@ import com.ibm.icu.text.UTF16.StringComparator; import com.ibm.icu.text.UnicodeSet; import com.ibm.icu.util.ULocale; +import com.ibm.icu.util.VersionInfo; import java.text.ParsePosition; import java.util.Comparator; import java.util.List; import java.util.regex.Pattern; import org.unicode.cldr.util.MultiComparator; -import org.unicode.jsp.UnicodeSetUtilities.ComparisonMatcher.Relation; import org.unicode.props.UnicodeProperty; import org.unicode.props.UnicodeProperty.PatternMatcher; +import org.unicode.props.UnicodePropertySymbolTable; public class UnicodeSetUtilities { @@ -292,7 +293,15 @@ private boolean applyPropertyAlias0( + prop.getValueAliases()); } if (isAge) { - set = prop.getSet(new ComparisonMatcher(propertyValue, Relation.geq)); + set = + prop.getSet( + new UnicodePropertySymbolTable.ComparisonMatcher< + VersionInfo>( + UnicodePropertySymbolTable.parseVersionInfoOrMax( + propertyValue), + UnicodePropertySymbolTable.Relation.geq, + Comparator.nullsFirst(Comparator.naturalOrder()), + UnicodePropertySymbolTable::parseVersionInfoOrMax)); } else { if (prop.getName().equals("General_Category")) { for (String[] coarseValue : COARSE_GENERAL_CATEGORIES) { @@ -344,49 +353,4 @@ private boolean isValid(UnicodeProperty prop, String propertyValue) { return prop.isValidValue(propertyValue); } } - ; - - public static class ComparisonMatcher implements PatternMatcher { - Relation relation; - - enum Relation { - less, - leq, - equal, - geq, - greater - } - - static Comparator comparator = new UTF16.StringComparator(true, false, 0); - - String pattern; - - public ComparisonMatcher(String pattern, Relation comparator) { - this.relation = comparator; - this.pattern = pattern; - } - - @Override - public boolean test(String value) { - int comp = comparator.compare(pattern, value); - switch (relation) { - case less: - return comp < 0; - case leq: - return comp <= 0; - default: - return comp == 0; - case geq: - return comp >= 0; - case greater: - return comp > 0; - } - } - - @Override - public PatternMatcher set(String pattern) { - this.pattern = pattern; - return this; - } - } } diff --git a/unicodetools/src/main/java/org/unicode/props/UnicodePropertySymbolTable.java b/unicodetools/src/main/java/org/unicode/props/UnicodePropertySymbolTable.java index 8ddfe42290..5a495783e3 100644 --- a/unicodetools/src/main/java/org/unicode/props/UnicodePropertySymbolTable.java +++ b/unicodetools/src/main/java/org/unicode/props/UnicodePropertySymbolTable.java @@ -7,11 +7,12 @@ package org.unicode.props; import com.ibm.icu.impl.UnicodeRegex; -import com.ibm.icu.text.UTF16; import com.ibm.icu.text.UnicodeSet; +import com.ibm.icu.util.VersionInfo; import java.util.Comparator; import java.util.HashMap; import java.util.List; +import java.util.function.Function; import org.unicode.props.UnicodeProperty.PatternMatcher; /** @@ -201,8 +202,12 @@ public boolean applyPropertyAlias0( if (isAge) { set = prop.getSet( - new ComparisonMatcher( - propertyValue, Relation.geq, DOUBLE_STRING_COMPARATOR)); + new ComparisonMatcher( + UnicodePropertySymbolTable.parseVersionInfoOrMax( + propertyValue), + Relation.geq, + Comparator.nullsFirst(Comparator.naturalOrder()), + UnicodePropertySymbolTable::parseVersionInfoOrMax)); } else { set = prop.getSet(propertyValue); } @@ -242,24 +247,26 @@ public enum Relation { greater } - public static class ComparisonMatcher implements PatternMatcher { + public static class ComparisonMatcher implements PatternMatcher { final Relation relation; - final Comparator comparator; - String pattern; + final Comparator comparator; + final Function parser; + T expected; - public ComparisonMatcher(String pattern, Relation relation) { - this(pattern, relation, new UTF16.StringComparator(true, false, 0)); - } - - public ComparisonMatcher(String pattern, Relation relation, Comparator comparator) { + public ComparisonMatcher( + T expected, + Relation relation, + Comparator comparator, + Function parser) { this.relation = relation; - this.pattern = pattern; + this.expected = expected; this.comparator = comparator; + this.parser = parser; } @Override public boolean test(String value) { - int comp = comparator.compare(pattern, value); + int comp = comparator.compare(expected, parser.apply(value)); switch (relation) { case less: return comp < 0; @@ -276,41 +283,19 @@ public boolean test(String value) { @Override public PatternMatcher set(String pattern) { - this.pattern = pattern; + this.expected = parser.apply(pattern); return this; } } - /** Special parser for doubles. Anything not parsable is higher than everything else. */ - public static final Comparator DOUBLE_STRING_COMPARATOR = - new Comparator() { - - @Override - public int compare(String o1, String o2) { - if (o1 == o2) { - return 0; - } else if (o1 == null) { - return -1; - } else if (o2 == null) { - return 1; - } else { - int f1 = o1.codePointAt(0); - int f2 = o2.codePointAt(0); - boolean n1 = f1 < '0' || f1 > '9'; - boolean n2 = f2 < '0' || f2 > '9'; - if (n1) { - return n2 ? o1.compareTo(o2) : 1; - } else if (n2) { - return -1; - } - double d1 = Double.parseDouble(o1); - double d2 = Double.parseDouble(o2); - if (Double.isNaN(d1) || Double.isNaN(d2)) { - throw new IllegalArgumentException(); - } - - return d1 > d2 ? 1 : d1 < d2 ? -1 : 0; - } - } - }; + public static VersionInfo parseVersionInfoOrMax(String s) { + if (s == null) { + return null; + } + try { + return VersionInfo.getInstance(s); + } catch (IllegalArgumentException e) { + return VersionInfo.getInstance(255, 255, 255, 255); + } + } } diff --git a/unicodetools/src/test/java/org/unicode/unittest/TestUnicodeSet.java b/unicodetools/src/test/java/org/unicode/unittest/TestUnicodeSet.java index ac83414131..648a30a461 100644 --- a/unicodetools/src/test/java/org/unicode/unittest/TestUnicodeSet.java +++ b/unicodetools/src/test/java/org/unicode/unittest/TestUnicodeSet.java @@ -2,10 +2,12 @@ import com.ibm.icu.impl.UnicodeRegex; import com.ibm.icu.text.UnicodeSet; +import com.ibm.icu.util.VersionInfo; +import java.util.Comparator; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.junit.jupiter.api.Test; -import org.unicode.cldr.util.props.UnicodePropertySymbolTable; +import org.unicode.props.UnicodePropertySymbolTable; import org.unicode.text.utility.UnicodeSetParser; import org.unicode.text.utility.Utility; @@ -13,12 +15,12 @@ public class TestUnicodeSet extends TestFmwkMinusMinus { @Test public void TestAge() { - checkOrder("3.1", "3.2", -1); - checkOrder("3.2", "3.2", 0); - checkOrder("4.0", "3.2", 1); - checkOrder("10.0", "3.2", 1); - checkOrder("11.0", "3.2", 1); - checkOrder("NA", "11.0", 1); + checkOrder("3.1", "3.2", Comparison.SMALLER); + checkOrder("3.2", "3.2", Comparison.EQUAL); + checkOrder("4.0", "3.2", Comparison.GREATER); + checkOrder("10.0", "3.2", Comparison.GREATER); + checkOrder("11.0", "3.2", Comparison.GREATER); + checkOrder("NA", "11.0", Comparison.GREATER); final UnicodeSet U32 = new UnicodeSet("[:age=3.2:]").freeze(); if (!U32.contains(0x01F6) || !U32.contains(0x0220)) { @@ -29,15 +31,37 @@ public void TestAge() { } } - private void checkOrder(String d1, String d2, int expected) { + private static enum Comparison { + EQUAL, + GREATER, + SMALLER; + + public Comparison opposite() { + return this == GREATER ? SMALLER : this == SMALLER ? GREATER : this; + } + + public static Comparison fromCompareResult(int compareResult) { + return compareResult == 0 ? EQUAL : compareResult > 0 ? GREATER : SMALLER; + } + } + + private void checkOrder(String d1, String d2, Comparison expected) { assertEquals( d1 + " ?< " + d2, expected, - UnicodePropertySymbolTable.DOUBLE_STRING_COMPARATOR.compare(d1, d2)); + Comparison.fromCompareResult( + Comparator.nullsFirst(Comparator.naturalOrder()) + .compare( + UnicodePropertySymbolTable.parseVersionInfoOrMax(d1), + UnicodePropertySymbolTable.parseVersionInfoOrMax(d2)))); assertEquals( d2 + " ?< " + d1, - -expected, - UnicodePropertySymbolTable.DOUBLE_STRING_COMPARATOR.compare(d2, d1)); + expected.opposite(), + Comparison.fromCompareResult( + Comparator.nullsFirst(Comparator.naturalOrder()) + .compare( + UnicodePropertySymbolTable.parseVersionInfoOrMax(d2), + UnicodePropertySymbolTable.parseVersionInfoOrMax(d1)))); } @Test