001: /**
002: *******************************************************************************
003: * Copyright (C) 2001-2004, International Business Machines Corporation and *
004: * others. All Rights Reserved. *
005: *******************************************************************************
006: */package com.ibm.icu.dev.test.translit;
007:
008: import com.ibm.icu.dev.test.*;
009: import com.ibm.icu.text.*;
010: import com.ibm.icu.impl.Utility;
011: import java.io.*;
012: import java.text.ParseException;
013:
014: /**
015: * @test
016: * @summary Round trip test of Transliterator
017: */
018: public class ReplaceableTest extends TestFmwk {
019:
020: public static final boolean LATER_THAN_2_1 = true;
021:
022: public static void main(String[] args) throws Exception {
023: new ReplaceableTest().run(args);
024: }
025:
026: public void Test() throws IOException, ParseException {
027: check("Lower", "ABCD", "1234");
028: check("Upper", "abcd\u00DF", "123455"); // must map 00DF to SS
029: check("Title", "aBCD", "1234");
030: check("NFC", "A\u0300E\u0300", "13");
031: check("NFD", "\u00C0\u00C8", "1122");
032: if (!LATER_THAN_2_1)
033: return;
034: check("*(x) > A $1 B", "wxy", "11223");
035: check("*(x)(y) > A $2 B $1 C $2 D", "wxyz", "113322334");
036: check("*(x)(y)(z) > A $3 B $2 C $1 D", "wxyzu", "114433225");
037: // Disabled for 2.4. TODO Revisit in 2.6 or later.
038: //check("*x > a", "xyz", "223"); // expect "123"?
039: //check("*x > a", "wxy", "113"); // expect "123"?
040: //check("*x > a", "\uFFFFxy", "_33"); // expect "_23"?
041: //check("*(x) > A $1 B", "\uFFFFxy", "__223");
042: }
043:
044: void check(String transliteratorName, String test,
045: String shouldProduceStyles) {
046: TestReplaceable tr = new TestReplaceable(test, null);
047: String original = tr.toString();
048:
049: Transliterator t;
050: if (transliteratorName.startsWith("*")) {
051: transliteratorName = transliteratorName.substring(1);
052: t = Transliterator.createFromRules("test",
053: transliteratorName, Transliterator.FORWARD);
054: } else {
055: t = Transliterator.getInstance(transliteratorName);
056: }
057: t.transliterate(tr);
058: String newStyles = tr.getStyles();
059: if (!newStyles.equals(shouldProduceStyles)) {
060: errln("FAIL Styles: " + transliteratorName + " ( "
061: + original + " ) => " + tr.toString()
062: + "; should be {" + shouldProduceStyles + "}!");
063: } else {
064: logln("OK: " + transliteratorName + " ( " + original
065: + " ) => " + tr.toString());
066: }
067:
068: if (!tr.hasMetaData() || tr.chars.hasMetaData()
069: || tr.styles.hasMetaData()) {
070: errln("Fail hasMetaData()");
071: }
072: }
073:
074: /**
075: * This is a test class that simulates styled text.
076: * It associates a style number (0..65535) with each character,
077: * and maintains that style in the normal fashion:
078: * When setting text from raw string or characters,<br>
079: * Set the styles to the style of the first character replaced.<br>
080: * If no characters are replaced, use the style of the previous character.<br>
081: * If at start, use the following character<br>
082: * Otherwise use NO_STYLE.
083: */
084: static class TestReplaceable implements Replaceable {
085: ReplaceableString chars;
086: ReplaceableString styles;
087:
088: static final char NO_STYLE = '_';
089:
090: static final char NO_STYLE_MARK = 0xFFFF;
091:
092: TestReplaceable(String text, String styles) {
093: chars = new ReplaceableString(text);
094: StringBuffer s = new StringBuffer();
095: for (int i = 0; i < text.length(); ++i) {
096: if (styles != null && i < styles.length()) {
097: s.append(styles.charAt(i));
098: } else {
099: if (text.charAt(i) == NO_STYLE_MARK) {
100: s.append(NO_STYLE);
101: } else {
102: s.append((char) (i + '1'));
103: }
104: }
105: }
106: this .styles = new ReplaceableString(s.toString());
107: }
108:
109: public String getStyles() {
110: return styles.toString();
111: }
112:
113: public String toString() {
114: return chars.toString() + "{" + styles.toString() + "}";
115: }
116:
117: public String substring(int start, int limit) {
118: return chars.substring(start, limit);
119: }
120:
121: public int length() {
122: return chars.length();
123: }
124:
125: public char charAt(int offset) {
126: return chars.charAt(offset);
127: }
128:
129: public int char32At(int offset) {
130: return chars.char32At(offset);
131: }
132:
133: public void getChars(int srcStart, int srcLimit, char dst[],
134: int dstStart) {
135: chars.getChars(srcStart, srcLimit, dst, dstStart);
136: }
137:
138: public void replace(int start, int limit, String text) {
139: if (substring(start, limit).equals(text))
140: return; // NO ACTION!
141: if (DEBUG)
142: System.out.print(Utility.escape(toString()
143: + " -> replace(" + start + "," + limit + ","
144: + text)
145: + ") -> ");
146: chars.replace(start, limit, text);
147: fixStyles(start, limit, text.length());
148: if (DEBUG)
149: System.out.println(Utility.escape(toString()));
150: }
151:
152: public void replace(int start, int limit, char[] chars,
153: int charsStart, int charsLen) {
154: if (substring(start, limit)
155: .equals(
156: new String(chars, charsStart, charsLen
157: - charsStart)))
158: return; // NO ACTION!
159: this .chars.replace(start, limit, chars, charsStart,
160: charsLen);
161: fixStyles(start, limit, charsLen);
162: }
163:
164: void fixStyles(int start, int limit, int newLen) {
165: char newStyle = NO_STYLE;
166: if (start != limit && styles.charAt(start) != NO_STYLE) {
167: newStyle = styles.charAt(start);
168: } else if (start > 0 && charAt(start - 1) != NO_STYLE_MARK) {
169: newStyle = styles.charAt(start - 1);
170: } else if (limit < styles.length()) {
171: newStyle = styles.charAt(limit);
172: }
173: // dumb implementation for now.
174: StringBuffer s = new StringBuffer();
175: for (int i = 0; i < newLen; ++i) {
176: // this doesn't really handle an embedded NO_STYLE_MARK
177: // in the middle of a long run of characters right -- but
178: // that case shouldn't happen anyway
179: if (charAt(start + i) == NO_STYLE_MARK) {
180: s.append(NO_STYLE);
181: } else {
182: s.append(newStyle);
183: }
184: }
185: styles.replace(start, limit, s.toString());
186: }
187:
188: public void copy(int start, int limit, int dest) {
189: chars.copy(start, limit, dest);
190: styles.copy(start, limit, dest);
191: }
192:
193: public boolean hasMetaData() {
194: return true;
195: }
196:
197: static final boolean DEBUG = false;
198: }
199: }
|