001: /*
002: *******************************************************************************
003: * Copyright (C) 2004-2006, International Business Machines Corporation and *
004: * others. All Rights Reserved. *
005: *******************************************************************************
006: */
007:
008: package com.ibm.icu.text;
009:
010: import com.ibm.icu.impl.Utility;
011:
012: /**
013: * A post-processor for Chinese text.
014: */
015: final class RBNFChinesePostProcessor extends RBNFPostProcessor {
016: private NFRuleSet lastRuleSet;
017: private boolean longForm;
018: private int format;
019:
020: private static final String[] rulesetNames = { "%traditional",
021: "%simplified", "%accounting", "%time" };
022:
023: /**
024: * Initialization routine for this instance, called once
025: * immediately after first construction and never again.
026: */
027: void init(RuleBasedNumberFormat formatter, String rules) {
028: }
029:
030: /**
031: * Work routine. Post process the output, which was generated by the
032: * ruleset with the given name.
033: */
034: void process(StringBuffer buf, NFRuleSet ruleSet) {
035: // markers depend on what rule set we are using
036:
037: if (ruleSet != lastRuleSet) {
038: String name = ruleSet.getName();
039: for (int i = 0; i < rulesetNames.length; ++i) {
040: if (rulesetNames[i].equals(name)) {
041: format = i;
042: longForm = i == 1 || i == 3;
043: break;
044: }
045: }
046: }
047:
048: if (longForm) {
049: for (int i = Utility.indexOf(buf, "*"); i != -1; i = Utility
050: .indexOf(buf, "*", i)) {
051: buf.delete(i, i + 1);
052: }
053: return;
054: }
055:
056: final String DIAN = "\u9ede"; // decimal point
057:
058: final String[][] markers = {
059: { "\u842c", "\u5104", "\u5146", "\u3007" }, // marker chars, last char is the 'zero'
060: { "\u4e07", "\u4ebf", "\u5146", "\u3007" },
061: { "\u842c", "\u5104", "\u5146", "\u96f6" }
062: // need markers for time?
063: };
064:
065: // remove unwanted lings
066: // a '0' (ling) with * might be removed
067: // mark off 10,000 'chunks', markers are Z, Y, W (zhao, yii, and wan)
068: // already, we avoid two lings in the same chunk -- ling without * wins
069: // now, just need to avoid optional lings in adjacent chunks
070: // process right to left
071:
072: // decision matrix:
073: // state, situation
074: // state none opt. req.
075: // ----- ---- ---- ----
076: // none to right none opt. req.
077: // opt. to right none clear, none clear right, req.
078: // req. to right none clear, none req.
079:
080: // mark chunks with '|' for convenience
081: {
082: String[] m = markers[format];
083: for (int i = 0; i < m.length - 1; ++i) {
084: int n = Utility.indexOf(buf, m[i]);
085: if (n != -1) {
086: buf.insert(n + m[i].length(), '|');
087: }
088: }
089: }
090:
091: int x = Utility.indexOf(buf, DIAN);
092: if (x == -1) {
093: x = buf.length();
094: }
095: int s = 0; // 0 = none to right, 1 = opt. to right, 2 = req. to right
096: int n = -1; // previous optional ling
097: String ling = markers[format][3];
098: while (x >= 0) {
099: int m = Utility.lastIndexOf(buf, "|", x);
100: int nn = Utility.lastIndexOf(buf, ling, x);
101: int ns = 0;
102: if (nn > m) {
103: ns = (nn > 0 && buf.charAt(nn - 1) != '*') ? 2 : 1;
104: }
105: x = m - 1;
106:
107: // actually much simpler, but leave this verbose for now so it's easier to follow
108: switch (s * 3 + ns) {
109: case 0: /* none, none */
110: s = ns; // redundant
111: n = -1;
112: break;
113: case 1: /* none, opt. */
114: s = ns;
115: n = nn; // remember optional ling to right
116: break;
117: case 2: /* none, req. */
118: s = ns;
119: n = -1;
120: break;
121: case 3: /* opt., none */
122: s = ns;
123: n = -1;
124: break;
125: case 4: /* opt., opt. */
126: buf.delete(nn - 1, nn + ling.length()); // delete current optional ling
127: s = 0;
128: n = -1;
129: break;
130: case 5: /* opt., req. */
131: buf.delete(n - 1, n + ling.length()); // delete previous optional ling
132: s = ns;
133: n = -1;
134: break;
135: case 6: /* req., none */
136: s = ns;
137: n = -1;
138: break;
139: case 7: /* req., opt. */
140: buf.delete(nn - 1, nn + ling.length()); // delete current optional ling
141: s = 0;
142: n = -1;
143: break;
144: case 8: /* req., req. */
145: s = ns;
146: n = -1;
147: break;
148: default:
149: throw new IllegalStateException();
150: }
151: }
152:
153: for (int i = buf.length(); --i >= 0;) {
154: char c = buf.charAt(i);
155: if (c == '*' || c == '|') {
156: buf.delete(i, i + 1);
157: }
158: }
159: }
160: }
|