1 28 29 package com.caucho.xsl; 30 31 import com.caucho.util.CharBuffer; 32 import com.caucho.util.IntArray; 33 34 import java.util.ArrayList ; 35 36 39 public class XslNumberFormat { 40 private String head; 41 private String tail; 42 43 private String []separators; 44 private int []formats; 45 private int []zeroSize; 46 47 private String format; 48 private String lang; 49 private boolean isAlphabetic; 50 private String groupSeparator; 51 private int groupSize; 52 53 62 public XslNumberFormat(String format, String lang, boolean isAlphabetic, 63 String groupSeparator, int groupSize) 64 { 65 this.format = format; 66 this.lang = lang; 67 this.isAlphabetic = isAlphabetic; 68 if (groupSize <= 0) { 69 groupSize = 3; 70 groupSeparator = ""; 71 } 72 if (groupSeparator == null) 73 groupSeparator = ""; 74 this.groupSeparator = groupSeparator; 75 this.groupSize = groupSize; 76 77 if (format == null) 78 format = "1"; 79 80 int headIndex = format.length(); 81 82 ArrayList separators = new ArrayList (); 83 IntArray zeroSizes = new IntArray(); 84 IntArray formats = new IntArray(); 85 86 CharBuffer cb = new CharBuffer(); 87 int i = 0; 88 while (i < format.length()) { 89 char ch; 90 91 cb.clear(); 93 for (; i < format.length(); i++) { 94 ch = format.charAt(i); 95 if (Character.isLetterOrDigit(ch)) 96 break; 97 cb.append(ch); 98 } 99 100 if (head == null) 102 head = cb.toString(); 103 else if (i >= format.length()) 104 tail = cb.toString(); 105 else 106 separators.add(cb.toString()); 107 108 if (i >= format.length()) 109 break; 110 111 int zeroSize = 1; 113 int code = '0'; 114 for (; i < format.length(); i++) { 115 ch = format.charAt(i); 116 if (! Character.isLetterOrDigit(ch)) 117 break; 118 119 if (! Character.isDigit(ch)) { 120 if (code != '0' || zeroSize != 1) 121 code = 0; 122 else 123 code = ch; 124 } 125 else if (Character.digit(ch, 10) == 0 && zeroSize >= 0) 126 zeroSize++; 127 else if (Character.digit(ch, 10) == 1) 128 code = ch - 1; 129 else 130 code = 0; 131 } 132 if (code == 0) 133 code = '0'; 134 135 zeroSizes.add(zeroSize); 136 formats.add(code); 137 } 138 139 if (formats.size() == 0) { 141 tail = head; 142 head = ""; 143 formats.add('0'); 144 zeroSizes.add(0); 145 } 146 147 if (separators.size() == 0) 149 separators.add("."); 150 if (separators.size() < formats.size()) 151 separators.add(separators.get(separators.size() - 1)); 152 153 this.separators = (String []) separators.toArray(new String [separators.size()]); 154 this.zeroSize = zeroSizes.toArray(); 155 this.formats = formats.toArray(); 156 157 if (head == null) 158 head = ""; 159 if (tail == null) 160 tail = ""; 161 } 162 163 public String getFormat() 164 { 165 return format; 166 } 167 168 public String getLang() 169 { 170 return lang; 171 } 172 173 public boolean isAlphabetic() 174 { 175 return isAlphabetic; 176 } 177 178 public String getGroupSeparator() 179 { 180 return groupSeparator; 181 } 182 183 public int getGroupSize() 184 { 185 return groupSize; 186 } 187 188 193 void format(XslWriter out, IntArray numbers) 194 { 195 CharBuffer buf = new CharBuffer(); 196 197 buf.append(head); 198 199 int i; 200 for (i = numbers.size() - 1; i >= 0; i--) { 201 int index = numbers.size() - i - 1; 202 if (index >= formats.length) 203 index = formats.length - 1; 204 205 char code = (char) formats[index]; 206 int zeroCount = zeroSize[index]; 207 208 int count = numbers.get(i); 209 210 switch (code) { 211 case 'i': 212 romanize(buf, "mdclxvi", count); 213 break; 214 215 case 'I': 216 romanize(buf, "MDCLXVI", count); 217 break; 218 219 case 'a': 220 formatAlpha(buf, 'a', count); 221 break; 222 223 case 'A': 224 formatAlpha(buf, 'A', count); 225 break; 226 227 default: 228 formatDecimal(buf, code, zeroCount, count); 229 break; 230 } 231 232 if (i > 0) 233 buf.append(separators[index]); 234 } 235 236 buf.append(tail); 237 238 out.print(buf.toString()); 239 } 240 241 249 private void romanize(CharBuffer cb, String xvi, int count) 250 { 251 if (count <= 0) 252 throw new RuntimeException (); 253 254 if (count > 5000) { 255 cb.append(count); 256 return; 257 } 258 259 for (; count > 1000; count -= 1000) 260 cb.append(xvi.charAt(0)); 261 262 romanize(cb, xvi.charAt(0), xvi.charAt(1), xvi.charAt(2), count / 100); 263 count %= 100; 264 romanize(cb, xvi.charAt(2), xvi.charAt(3), xvi.charAt(4), count / 10); 265 count %= 10; 266 romanize(cb, xvi.charAt(4), xvi.charAt(5), xvi.charAt(6), count); 267 } 268 269 278 private void romanize(CharBuffer cb, char x, char v, char i, int count) 279 { 280 switch (count) { 281 case 0: 282 break; 283 case 1: 284 cb.append(i); 285 break; 286 case 2: 287 cb.append(i); 288 cb.append(i); 289 break; 290 case 3: 291 cb.append(i); 292 cb.append(i); 293 cb.append(i); 294 break; 295 case 4: 296 cb.append(i); 297 cb.append(v); 298 break; 299 case 5: 300 cb.append(v); 301 break; 302 case 6: 303 cb.append(v); 304 cb.append(i); 305 break; 306 case 7: 307 cb.append(v); 308 cb.append(i); 309 cb.append(i); 310 break; 311 case 8: 312 cb.append(v); 313 cb.append(i); 314 cb.append(i); 315 cb.append(i); 316 break; 317 case 9: 318 cb.append(i); 319 cb.append(x); 320 break; 321 322 default: 323 throw new RuntimeException (); 324 } 325 } 326 327 334 private void formatAlpha(CharBuffer cb, char a, int count) 335 { 336 if (count <= 0) 337 throw new RuntimeException (); 338 339 int index = cb.length(); 340 while (count > 0) { 341 count--; 342 cb.insert(index, (char) (a + count % 26)); 343 344 count /= 26; 345 } 346 } 347 348 356 private void formatDecimal(CharBuffer cb, int code, 357 int zeroCount, int count) 358 { 359 int digits = 0; 360 int index = cb.length(); 361 while (count > 0) { 362 if (digits > 0 && digits % groupSize == 0) 363 cb.insert(index, groupSeparator); 364 cb.insert(index, (char) (code + count % 10)); 365 count /= 10; 366 digits++; 367 } 368 while (cb.length() - index < zeroCount) { 369 cb.insert(index, (char) code); 370 } 371 } 372 } 373 | Popular Tags |