diff --git a/icu4j/src/com/ibm/icu/dev/test/translit/TransliteratorTest.java b/icu4j/src/com/ibm/icu/dev/test/translit/TransliteratorTest.java index c5efd82478..6d9616ab4c 100755 --- a/icu4j/src/com/ibm/icu/dev/test/translit/TransliteratorTest.java +++ b/icu4j/src/com/ibm/icu/dev/test/translit/TransliteratorTest.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/dev/test/translit/TransliteratorTest.java,v $ - * $Date: 2002/04/01 22:15:23 $ - * $Revision: 1.103 $ + * $Date: 2002/04/17 16:48:28 $ + * $Revision: 1.104 $ * ***************************************************************************************** */ @@ -15,6 +15,7 @@ import com.ibm.icu.lang.*; import com.ibm.icu.text.*; import com.ibm.icu.dev.test.*; import com.ibm.icu.impl.Utility; +import com.ibm.icu.util.CaseInsensitiveString; import java.text.*; import java.util.*; @@ -2531,6 +2532,71 @@ public class TransliteratorTest extends TestFmwk { "x x x qtp qstp qrstp"); } + /** + * Test that user-registered transliterators can be used under function + * syntax. + */ + public void TestUserFunction() { + Transliterator t; + + // There's no need to register inverses if we don't use them + TestUserFunctionFactory.add("Any-gif", + Transliterator.createFromRules("gif", + "'\\'u(..)(..) > '';", + Transliterator.FORWARD)); + //TestUserFunctionFactory.add("gif-Any", Transliterator.getInstance("Any-Null")); + + TestUserFunctionFactory.add("Any-RemoveCurly", + Transliterator.createFromRules("RemoveCurly", "[\\{\\}] > ;", Transliterator.FORWARD)); + //TestUserFunctionFactory.add("RemoveCurly-Any", Transliterator.getInstance("Any-Null")); + + logln("Trying &hex"); + t = Transliterator.createFromRules("hex2", "(.) > &hex($1);", Transliterator.FORWARD); + logln("Registering"); + TestUserFunctionFactory.add("Any-hex2", t); + t = Transliterator.getInstance("Any-hex2"); + expect(t, "abc", "\\u0061\\u0062\\u0063"); + + logln("Trying &gif"); + t = Transliterator.createFromRules("gif2", "(.) > &Gif(&Hex2($1));", Transliterator.FORWARD); + logln("Registering"); + TestUserFunctionFactory.add("Any-gif2", t); + t = Transliterator.getInstance("Any-gif2"); + expect(t, "ab", "" + + ""); + + // Test that filters are allowed after & + t = Transliterator.createFromRules("test", + "(.) > &Hex($1) ' ' &[\\{\\}]Remove(&Name($1)) ' ';", Transliterator.FORWARD); + expect(t, "abc", "\\u0061 LATIN SMALL LETTER A \\u0062 LATIN SMALL LETTER B \\u0063 LATIN SMALL LETTER C "); + + // Unregister our test stuff + TestUserFunctionFactory.unregister(); + } + + static class TestUserFunctionFactory implements Transliterator.Factory { + static TestUserFunctionFactory singleton = new TestUserFunctionFactory(); + static HashMap m = new HashMap(); + + static void add(String ID, Transliterator t) { + m.put(new CaseInsensitiveString(ID), t); + Transliterator.registerFactory(ID, singleton); + } + + public Transliterator getInstance(String ID) { + return (Transliterator) m.get(new CaseInsensitiveString(ID)); + } + + static void unregister() { + Iterator ids = m.keySet().iterator(); + while (ids.hasNext()) { + CaseInsensitiveString id = (CaseInsensitiveString) ids.next(); + Transliterator.unregister(id.getString()); + ids.remove(); // removes pair from m + } + } + } + //====================================================================== // Support methods //====================================================================== diff --git a/icu4j/src/com/ibm/icu/text/TransliteratorIDParser.java b/icu4j/src/com/ibm/icu/text/TransliteratorIDParser.java index 8a416a42c7..0cfef8ea90 100755 --- a/icu4j/src/com/ibm/icu/text/TransliteratorIDParser.java +++ b/icu4j/src/com/ibm/icu/text/TransliteratorIDParser.java @@ -131,34 +131,27 @@ class TransliteratorIDParser { } /** - * Parse a basic ID from the given string. A basic ID contains - * only a single source, target, and variant. It does not contain - * a filter or an explicit inverse. + * Parse a filter ID, that is, an ID of the general form + * "[f1] s1-t1/v1", with the filters optional, and the variants optional. * @param id the id to be parsed * @param pos INPUT-OUTPUT parameter. On input, the position of * the first character to parse. On output, the position after - * the last character parsed. If the parse fails pos[0] will be - * unchanged. - * @return the parsed ID in canonical format, or null on parse - * failure. If the parsed ID did not contain a source, the return - * ID will not. + * the last character parsed. + * @return a SingleID object or null if the parse fails */ - public static String parseBasicID(String id, int[] pos) { - Specs specs = parseFilterID(id, pos, false); - if (specs != null) { - StringBuffer buf = new StringBuffer(); - if (specs.sawSource) { - buf.append(specs.source); - buf.append(TARGET_SEP); - } - buf.append(specs.target); - if (specs.variant != null) { - buf.append(VARIANT_SEP); - buf.append(specs.variant); - } - return buf.toString(); + public static SingleID parseFilterID(String id, int[] pos) { + + int start = pos[0]; + Specs specs = parseFilterID(id, pos, true); + if (specs == null) { + pos[0] = start; + return null; } - return null; + + // Assemble return results + SingleID single = specsToID(specs, FORWARD); + single.filter = specs.filter; + return single; } /** diff --git a/icu4j/src/com/ibm/icu/text/TransliteratorParser.java b/icu4j/src/com/ibm/icu/text/TransliteratorParser.java index bc30ce9ff2..070a850c66 100755 --- a/icu4j/src/com/ibm/icu/text/TransliteratorParser.java +++ b/icu4j/src/com/ibm/icu/text/TransliteratorParser.java @@ -4,8 +4,8 @@ * Corporation and others. All Rights Reserved. ********************************************************************** * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/text/TransliteratorParser.java,v $ -* $Date: 2002/03/06 00:37:52 $ -* $Revision: 1.20 $ +* $Date: 2002/04/17 16:46:11 $ +* $Revision: 1.21 $ ********************************************************************** */ package com.ibm.icu.text; @@ -573,14 +573,17 @@ class TransliteratorParser { case FUNCTION: { iref[0] = pos; - String id = TransliteratorIDParser.parseBasicID(rule, iref); + TransliteratorIDParser.SingleID single = TransliteratorIDParser.parseFilterID(rule, iref); // The next character MUST be a segment open - if (id == null || + if (single == null || !Utility.parseChar(rule, iref, SEGMENT_OPEN)) { syntaxError("Invalid function", rule, start); } - Transliterator t = Transliterator.getBasicInstance(id, id); + Transliterator t = single.getInstance(); + if (t == null) { + syntaxError("Invalid function ID", rule, start); + } // bufSegStart is the offset in buf to the first // character of the segment we are parsing.