1 11 package com.ibm.icu.text; 12 13 import java.io.IOException ; 14 import java.io.InvalidObjectException ; 15 import java.io.ObjectInputStream ; 16 import java.text.ChoiceFormat ; 17 import java.text.FieldPosition ; 18 import java.text.Format ; 19 import java.text.ParseException ; 20 import java.text.ParsePosition ; 21 import java.util.Date ; 22 import java.util.Locale ; 23 24 import com.ibm.icu.impl.Utility; 25 import com.ibm.icu.text.RuleBasedNumberFormat; 26 import com.ibm.icu.util.ULocale; 27 28 327 public class MessageFormat extends UFormat { 328 329 static final long serialVersionUID = 7136212545847378651L; 331 332 344 public MessageFormat(String pattern) { 345 this.ulocale = ULocale.getDefault(); 346 applyPattern(pattern); 347 } 348 349 362 public MessageFormat(String pattern, Locale locale) { 363 this(pattern, ULocale.forLocale(locale)); 364 } 365 366 379 public MessageFormat(String pattern, ULocale locale) { 380 this.ulocale = locale; 381 applyPattern(pattern); 382 } 383 384 394 public void setLocale(Locale locale) { 395 setLocale(ULocale.forLocale(locale)); 396 } 397 398 408 public void setLocale(ULocale locale) { 409 410 411 412 String existingPattern = toPattern(); 413 this.ulocale = locale; 414 applyPattern(existingPattern); 415 } 416 417 423 public Locale getLocale() { 424 return ulocale.toLocale(); 425 } 426 427 433 public ULocale getULocale() { 434 return ulocale; 435 } 436 437 448 public void applyPattern(String pattern) { 449 StringBuffer [] segments = new StringBuffer [4]; 450 for (int i = 0; i < segments.length; ++i) { 451 segments[i] = new StringBuffer (); 452 } 453 int part = 0; 454 int formatNumber = 0; 455 boolean inQuote = false; 456 int braceStack = 0; 457 maxOffset = -1; 458 for (int i = 0; i < pattern.length(); ++i) { 459 char ch = pattern.charAt(i); 460 if (part == 0) { 461 if (ch == '\'') { 462 if (i + 1 < pattern.length() 463 && pattern.charAt(i+1) == '\'') { 464 segments[part].append(ch); ++i; 466 } else { 467 inQuote = !inQuote; 468 } 469 } else if (ch == '{' && !inQuote) { 470 part = 1; 471 } else { 472 segments[part].append(ch); 473 } 474 } else if (inQuote) { segments[part].append(ch); 476 if (ch == '\'') { 477 inQuote = false; 478 } 479 } else { 480 switch (ch) { 481 case ',': 482 if (part < 3) 483 part += 1; 484 else 485 segments[part].append(ch); 486 break; 487 case '{': 488 ++braceStack; 489 segments[part].append(ch); 490 break; 491 case '}': 492 if (braceStack == 0) { 493 part = 0; 494 makeFormat(i, formatNumber, segments); 495 formatNumber++; 496 } else { 497 --braceStack; 498 segments[part].append(ch); 499 } 500 break; 501 case '\'': 502 inQuote = true; 503 default: 505 segments[part].append(ch); 506 break; 507 } 508 } 509 } 510 if (braceStack == 0 && part != 0) { 511 maxOffset = -1; 512 throw new IllegalArgumentException ("Unmatched braces in the pattern."); 513 } 514 this.pattern = segments[0].toString(); 515 } 516 517 518 526 public String toPattern() { 527 int lastOffset = 0; 529 StringBuffer result = new StringBuffer (); 530 for (int i = 0; i <= maxOffset; ++i) { 531 copyAndFixQuotes(pattern, lastOffset, offsets[i],result); 532 lastOffset = offsets[i]; 533 result.append('{'); 534 result.append(argumentNumbers[i]); 535 if (formats[i] == null) { 536 } else if (formats[i] instanceof DecimalFormat) { 538 if (formats[i].equals(NumberFormat.getInstance(ulocale))) { 539 result.append(",number"); 540 } else if (formats[i].equals(NumberFormat.getCurrencyInstance(ulocale))) { 541 result.append(",number,currency"); 542 } else if (formats[i].equals(NumberFormat.getPercentInstance(ulocale))) { 543 result.append(",number,percent"); 544 } else if (formats[i].equals(NumberFormat.getIntegerInstance(ulocale))) { 545 result.append(",number,integer"); 546 } else { 547 result.append(",number," + 548 ((DecimalFormat)formats[i]).toPattern()); 549 } 550 } else if (formats[i] instanceof SimpleDateFormat) { 551 if (formats[i].equals(DateFormat.getDateInstance(DateFormat.DEFAULT,ulocale))) { 552 result.append(",date"); 553 } else if (formats[i].equals(DateFormat.getDateInstance(DateFormat.SHORT,ulocale))) { 554 result.append(",date,short"); 555 } else if (formats[i].equals(DateFormat.getDateInstance(DateFormat.LONG,ulocale))) { 559 result.append(",date,long"); 560 } else if (formats[i].equals(DateFormat.getDateInstance(DateFormat.FULL,ulocale))) { 561 result.append(",date,full"); 562 } else if (formats[i].equals(DateFormat.getTimeInstance(DateFormat.DEFAULT,ulocale))) { 563 result.append(",time"); 564 } else if (formats[i].equals(DateFormat.getTimeInstance(DateFormat.SHORT,ulocale))) { 565 result.append(",time,short"); 566 } else if (formats[i].equals(DateFormat.getTimeInstance(DateFormat.LONG,ulocale))) { 570 result.append(",time,long"); 571 } else if (formats[i].equals(DateFormat.getTimeInstance(DateFormat.FULL,ulocale))) { 572 result.append(",time,full"); 573 } else { 574 result.append(",date," + ((SimpleDateFormat)formats[i]).toPattern()); 575 } 576 } else if (formats[i] instanceof ChoiceFormat ) { 577 result.append(",choice," + ((ChoiceFormat )formats[i]).toPattern()); 578 } else { 579 } 581 result.append('}'); 582 } 583 copyAndFixQuotes(pattern, lastOffset, pattern.length(), result); 584 return result.toString(); 585 } 586 587 610 public void setFormatsByArgumentIndex(Format [] newFormats) { 611 for (int i = 0; i <= maxOffset; i++) { 612 int j = argumentNumbers[i]; 613 if (j < newFormats.length) { 614 formats[i] = newFormats[j]; 615 } 616 } 617 } 618 619 642 public void setFormats(Format [] newFormats) { 643 int runsToCopy = newFormats.length; 644 if (runsToCopy > maxOffset + 1) { 645 runsToCopy = maxOffset + 1; 646 } 647 for (int i = 0; i < runsToCopy; i++) { 648 formats[i] = newFormats[i]; 649 } 650 } 651 652 670 public void setFormatByArgumentIndex(int argumentIndex, Format newFormat) { 671 for (int j = 0; j <= maxOffset; j++) { 672 if (argumentNumbers[j] == argumentIndex) { 673 formats[j] = newFormat; 674 } 675 } 676 } 677 678 696 public void setFormat(int formatElementIndex, Format newFormat) { 697 formats[formatElementIndex] = newFormat; 698 } 699 700 720 public Format [] getFormatsByArgumentIndex() { 721 int maximumArgumentNumber = -1; 722 for (int i = 0; i <= maxOffset; i++) { 723 if (argumentNumbers[i] > maximumArgumentNumber) { 724 maximumArgumentNumber = argumentNumbers[i]; 725 } 726 } 727 Format [] resultArray = new Format [maximumArgumentNumber + 1]; 728 for (int i = 0; i <= maxOffset; i++) { 729 resultArray[argumentNumbers[i]] = formats[i]; 730 } 731 return resultArray; 732 } 733 734 751 public Format [] getFormats() { 752 Format [] resultArray = new Format [maxOffset + 1]; 753 System.arraycopy(formats, 0, resultArray, 0, maxOffset + 1); 754 return resultArray; 755 } 756 757 823 public final StringBuffer format(Object [] arguments, StringBuffer result, 824 FieldPosition pos) 825 { 826 return subformat(arguments, result, pos); 827 } 828 829 842 public static String format(String pattern, Object [] arguments) { 843 MessageFormat temp = new MessageFormat(pattern); 844 return temp.format(arguments); 845 } 846 847 866 public final StringBuffer format(Object arguments, StringBuffer result, 867 FieldPosition pos) 868 { 869 return subformat((Object []) arguments, result, pos); 870 } 871 872 924 952 public Object [] parse(String source, ParsePosition pos) { 953 if (source == null) { 954 Object [] empty = {}; 955 return empty; 956 } 957 958 int maximumArgumentNumber = -1; 959 for (int i = 0; i <= maxOffset; i++) { 960 if (argumentNumbers[i] > maximumArgumentNumber) { 961 maximumArgumentNumber = argumentNumbers[i]; 962 } 963 } 964 Object [] resultArray = new Object [maximumArgumentNumber + 1]; 965 966 int patternOffset = 0; 967 int sourceOffset = pos.getIndex(); 968 ParsePosition tempStatus = new ParsePosition (0); 969 for (int i = 0; i <= maxOffset; ++i) { 970 int len = offsets[i] - patternOffset; 972 if (len == 0 || pattern.regionMatches(patternOffset, 973 source, sourceOffset, len)) { 974 sourceOffset += len; 975 patternOffset += len; 976 } else { 977 pos.setErrorIndex(sourceOffset); 978 return null; } 980 981 if (formats[i] == null) { int tempLength = (i != maxOffset) ? offsets[i+1] : pattern.length(); 987 988 int next; 989 if (patternOffset >= tempLength) { 990 next = source.length(); 991 }else{ 992 next = source.indexOf( pattern.substring(patternOffset,tempLength), sourceOffset); 993 } 994 995 if (next < 0) { 996 pos.setErrorIndex(sourceOffset); 997 return null; } else { 999 String strValue= source.substring(sourceOffset,next); 1000 if (!strValue.equals("{"+argumentNumbers[i]+"}")) 1001 resultArray[argumentNumbers[i]] 1002 = source.substring(sourceOffset,next); 1003 sourceOffset = next; 1004 } 1005 } else { 1006 tempStatus.setIndex(sourceOffset); 1007 resultArray[argumentNumbers[i]] 1008 = formats[i].parseObject(source,tempStatus); 1009 if (tempStatus.getIndex() == sourceOffset) { 1010 pos.setErrorIndex(sourceOffset); 1011 return null; } 1013 sourceOffset = tempStatus.getIndex(); } 1015 } 1016 int len = pattern.length() - patternOffset; 1017 if (len == 0 || pattern.regionMatches(patternOffset, 1018 source, sourceOffset, len)) { 1019 pos.setIndex(sourceOffset + len); 1020 } else { 1021 pos.setErrorIndex(sourceOffset); 1022 return null; } 1024 return resultArray; 1025 } 1026 1027 1041 public Object [] parse(String source) throws ParseException { 1042 ParsePosition pos = new ParsePosition (0); 1043 Object [] result = parse(source, pos); 1044 if (pos.getIndex() == 0) throw new ParseException ("MessageFormat parse error!", pos.getErrorIndex()); 1046 1047 return result; 1048 } 1049 1050 1075 public Object parseObject(String source, ParsePosition pos) { 1076 return parse(source, pos); 1077 } 1078 1079 1085 public Object clone() { 1086 MessageFormat other = (MessageFormat) super.clone(); 1087 1088 other.formats = (Format []) formats.clone(); for (int i = 0; i < formats.length; ++i) { 1091 if (formats[i] != null) 1092 other.formats[i] = (Format )formats[i].clone(); 1093 } 1094 other.offsets = (int[]) offsets.clone(); 1096 other.argumentNumbers = (int[]) argumentNumbers.clone(); 1097 1098 return other; 1099 } 1100 1101 1105 public boolean equals(Object obj) { 1106 if (this == obj) return true; 1108 if (obj == null || getClass() != obj.getClass()) 1109 return false; 1110 MessageFormat other = (MessageFormat) obj; 1111 return (maxOffset == other.maxOffset 1112 && pattern.equals(other.pattern) 1113 && Utility.objectEquals(ulocale, other.ulocale) && Utility.arrayEquals(offsets,other.offsets) 1115 && Utility.arrayEquals(argumentNumbers,other.argumentNumbers) 1116 && Utility.arrayEquals(formats,other.formats)); 1117 } 1118 1119 1123 public int hashCode() { 1124 return pattern.hashCode(); } 1126 1127 1175 1177 1182 private Locale locale; 1183 1184 1188 private ULocale ulocale; 1189 1190 1195 private String pattern = ""; 1196 1197 1198 private static final int INITIAL_FORMATS = 10; 1199 1200 1204 private Format [] formats = new Format [INITIAL_FORMATS]; 1205 1206 1211 private int[] offsets = new int[INITIAL_FORMATS]; 1212 1213 1219 private int[] argumentNumbers = new int[INITIAL_FORMATS]; 1220 1221 1228 private int maxOffset = -1; 1229 1230 1242 private StringBuffer subformat(Object [] arguments, StringBuffer result, 1243 FieldPosition fp 1244 ) { 1245 int lastOffset = 0; 1248 int last = result.length(); 1249 for (int i = 0; i <= maxOffset; ++i) { 1250 result.append(pattern.substring(lastOffset, offsets[i])); 1251 lastOffset = offsets[i]; 1252 int argumentNumber = argumentNumbers[i]; 1253 if (arguments == null || argumentNumber >= arguments.length) { 1254 result.append("{" + argumentNumber + "}"); 1255 continue; 1256 } 1257 if (false) { result.append('\uFFFD'); 1261 } else { 1262 Object obj = arguments[argumentNumber]; 1263 String arg = null; 1264 Format subFormatter = null; 1265 if (obj == null) { 1266 arg = "null"; 1267 } else if (formats[i] != null) { 1268 subFormatter = formats[i]; 1269 if (subFormatter instanceof ChoiceFormat ) { 1270 arg = formats[i].format(obj); 1271 if (arg.indexOf('{') >= 0) { 1272 subFormatter = new MessageFormat(arg, ulocale); 1273 obj = arguments; 1274 arg = null; 1275 } 1276 } 1277 } else if (obj instanceof Number ) { 1278 subFormatter = NumberFormat.getInstance(ulocale); 1280 } else if (obj instanceof Date ) { 1281 subFormatter = DateFormat.getDateTimeInstance( 1283 DateFormat.SHORT, DateFormat.SHORT, ulocale); } else if (obj instanceof String ) { 1285 arg = (String ) obj; 1286 1287 } else { 1288 arg = obj.toString(); 1289 if (arg == null) arg = "null"; 1290 } 1291 1292 1296 { 1331 if (subFormatter != null) { 1332 arg = subFormatter.format(obj); 1333 } 1334 result.append(arg); 1336 last = result.length(); 1343 } 1344 } 1345 } 1346 result.append(pattern.substring(lastOffset, pattern.length())); 1347 return result; 1353 } 1354 1355 1371 private static final String [] typeList = 1372 {"", "number", "date", "time", "choice", "spellout", "ordinal", "duration"}; 1373 private static final int 1374 TYPE_EMPTY = 0, 1375 TYPE_NUMBER = 1, 1376 TYPE_DATE = 2, 1377 TYPE_TIME = 3, 1378 TYPE_CHOICE = 4, 1379 TYPE_SPELLOUT = 5, 1380 TYPE_ORDINAL = 6, 1381 TYPE_DURATION = 7; 1382 1383 private static final String [] modifierList = 1384 {"", "currency", "percent", "integer"}; 1385 private static final int 1386 MODIFIER_EMPTY = 0, 1387 MODIFIER_CURRENCY = 1, 1388 MODIFIER_PERCENT = 2, 1389 MODIFIER_INTEGER = 3; 1390 1391 private static final String [] dateModifierList = 1392 {"", "short", "medium", "long", "full"}; 1393 private static final int 1394 DATE_MODIFIER_EMPTY = 0, 1395 DATE_MODIFIER_SHORT = 1, 1396 DATE_MODIFIER_MEDIUM = 2, 1397 DATE_MODIFIER_LONG = 3, 1398 DATE_MODIFIER_FULL = 4; 1399 1400 private void makeFormat(int position, int offsetNumber, 1401 StringBuffer [] segments) 1402 { 1403 int argumentNumber; 1405 try { 1406 argumentNumber = Integer.parseInt(segments[1].toString()); } catch (NumberFormatException e) { 1408 throw new IllegalArgumentException ("can't parse argument number " + segments[1]); 1409 } 1410 if (argumentNumber < 0) { 1411 throw new IllegalArgumentException ("negative argument number " + argumentNumber); 1412 } 1413 1414 if (offsetNumber >= formats.length) { 1416 int newLength = formats.length * 2; 1417 Format [] newFormats = new Format [newLength]; 1418 int[] newOffsets = new int[newLength]; 1419 int[] newArgumentNumbers = new int[newLength]; 1420 System.arraycopy(formats, 0, newFormats, 0, maxOffset + 1); 1421 System.arraycopy(offsets, 0, newOffsets, 0, maxOffset + 1); 1422 System.arraycopy(argumentNumbers, 0, newArgumentNumbers, 0, maxOffset + 1); 1423 formats = newFormats; 1424 offsets = newOffsets; 1425 argumentNumbers = newArgumentNumbers; 1426 } 1427 int oldMaxOffset = maxOffset; 1428 maxOffset = offsetNumber; 1429 offsets[offsetNumber] = segments[0].length(); 1430 argumentNumbers[offsetNumber] = argumentNumber; 1431 1432 Format newFormat = null; 1434 switch (findKeyword(segments[2].toString(), typeList)) { 1435 case TYPE_EMPTY: 1436 break; 1437 case TYPE_NUMBER: 1438 switch (findKeyword(segments[3].toString(), modifierList)) { 1439 case MODIFIER_EMPTY: 1440 newFormat = NumberFormat.getInstance(ulocale); 1441 break; 1442 case MODIFIER_CURRENCY: 1443 newFormat = NumberFormat.getCurrencyInstance(ulocale); 1444 break; 1445 case MODIFIER_PERCENT: 1446 newFormat = NumberFormat.getPercentInstance(ulocale); 1447 break; 1448 case MODIFIER_INTEGER: 1449 newFormat = NumberFormat.getIntegerInstance(ulocale); 1450 break; 1451 default: newFormat = new DecimalFormat(segments[3].toString(), new DecimalFormatSymbols(ulocale)); 1453 break; 1454 } 1455 break; 1456 case TYPE_DATE: 1457 switch (findKeyword(segments[3].toString(), dateModifierList)) { 1458 case DATE_MODIFIER_EMPTY: 1459 newFormat = DateFormat.getDateInstance(DateFormat.DEFAULT, ulocale); 1460 break; 1461 case DATE_MODIFIER_SHORT: 1462 newFormat = DateFormat.getDateInstance(DateFormat.SHORT, ulocale); 1463 break; 1464 case DATE_MODIFIER_MEDIUM: 1465 newFormat = DateFormat.getDateInstance(DateFormat.DEFAULT, ulocale); 1466 break; 1467 case DATE_MODIFIER_LONG: 1468 newFormat = DateFormat.getDateInstance(DateFormat.LONG, ulocale); 1469 break; 1470 case DATE_MODIFIER_FULL: 1471 newFormat = DateFormat.getDateInstance(DateFormat.FULL, ulocale); 1472 break; 1473 default: 1474 newFormat = new SimpleDateFormat(segments[3].toString(), ulocale); 1475 break; 1476 } 1477 break; 1478 case TYPE_TIME: 1479 switch (findKeyword(segments[3].toString(), dateModifierList)) { 1480 case DATE_MODIFIER_EMPTY: 1481 newFormat = DateFormat.getTimeInstance(DateFormat.DEFAULT, ulocale); 1482 break; 1483 case DATE_MODIFIER_SHORT: 1484 newFormat = DateFormat.getTimeInstance(DateFormat.SHORT, ulocale); 1485 break; 1486 case DATE_MODIFIER_MEDIUM: 1487 newFormat = DateFormat.getTimeInstance(DateFormat.DEFAULT, ulocale); 1488 break; 1489 case DATE_MODIFIER_LONG: 1490 newFormat = DateFormat.getTimeInstance(DateFormat.LONG, ulocale); 1491 break; 1492 case DATE_MODIFIER_FULL: 1493 newFormat = DateFormat.getTimeInstance(DateFormat.FULL, ulocale); 1494 break; 1495 default: 1496 newFormat = new SimpleDateFormat(segments[3].toString(), ulocale); 1497 break; 1498 } 1499 break; 1500 case TYPE_CHOICE: 1501 try { 1502 newFormat = new ChoiceFormat (segments[3].toString()); 1503 } catch (Exception e) { 1504 maxOffset = oldMaxOffset; 1505 throw new IllegalArgumentException ( 1506 "Choice Pattern incorrect"); 1507 } 1508 break; 1509 case TYPE_SPELLOUT: 1510 { 1511 RuleBasedNumberFormat rbnf = new RuleBasedNumberFormat(ulocale, RuleBasedNumberFormat.SPELLOUT); 1512 String ruleset = segments[3].toString().trim(); 1513 if (ruleset.length() != 0) { 1514 try { 1515 rbnf.setDefaultRuleSet(ruleset); 1516 } 1517 catch (Exception e) { 1518 } 1520 } 1521 newFormat = rbnf; 1522 } 1523 break; 1524 case TYPE_ORDINAL: 1525 { 1526 RuleBasedNumberFormat rbnf = new RuleBasedNumberFormat(ulocale, RuleBasedNumberFormat.ORDINAL); 1527 String ruleset = segments[3].toString().trim(); 1528 if (ruleset.length() != 0) { 1529 try { 1530 rbnf.setDefaultRuleSet(ruleset); 1531 } 1532 catch (Exception e) { 1533 } 1535 } 1536 newFormat = rbnf; 1537 } 1538 break; 1539 case TYPE_DURATION: 1540 { 1541 RuleBasedNumberFormat rbnf = new RuleBasedNumberFormat(ulocale, RuleBasedNumberFormat.DURATION); 1542 String ruleset = segments[3].toString().trim(); 1543 if (ruleset.length() != 0) { 1544 try { 1545 rbnf.setDefaultRuleSet(ruleset); 1546 } 1547 catch (Exception e) { 1548 } 1550 } 1551 newFormat = rbnf; 1552 } 1553 break; 1554 default: 1555 maxOffset = oldMaxOffset; 1556 throw new IllegalArgumentException ("unknown format type at "); 1557 } 1558 formats[offsetNumber] = newFormat; 1559 segments[1].setLength(0); segments[2].setLength(0); 1561 segments[3].setLength(0); 1562 } 1563 1564 private static final int findKeyword(String s, String [] list) { 1565 s = s.trim().toLowerCase(); 1566 for (int i = 0; i < list.length; ++i) { 1567 if (s.equals(list[i])) 1568 return i; 1569 } 1570 return -1; 1571 } 1572 1573 private static final void copyAndFixQuotes(String source, int start, int end, StringBuffer target) { 1574 boolean gotLB = false; 1576 for (int i = start; i < end; ++i) { 1577 char ch = source.charAt(i); 1578 if (ch == '{') { 1579 target.append("'{'"); 1580 gotLB = true; 1581 } else if (ch == '}') { 1582 if (gotLB) { 1583 target.append(ch); 1584 gotLB = false; 1585 } else { 1586 target.append("'}'"); 1587 } 1588 } else if (ch == '\'') { 1589 target.append("''"); 1590 } else { 1591 target.append(ch); 1592 } 1593 } 1594 } 1595 1596 1601 private void readObject(ObjectInputStream in) throws IOException , ClassNotFoundException { 1602 in.defaultReadObject(); 1603 boolean isValid = maxOffset >= -1 1604 && formats.length > maxOffset 1605 && offsets.length > maxOffset 1606 && argumentNumbers.length > maxOffset; 1607 if (isValid) { 1608 int lastOffset = pattern.length() + 1; 1609 for (int i = maxOffset; i >= 0; --i) { 1610 if ((offsets[i] < 0) || (offsets[i] > lastOffset)) { 1611 isValid = false; 1612 break; 1613 } else { 1614 lastOffset = offsets[i]; 1615 } 1616 } 1617 } 1618 if (!isValid) { 1619 throw new InvalidObjectException ("Could not reconstruct MessageFormat from corrupt stream."); 1620 } 1621 if (ulocale == null) { 1622 ulocale = ULocale.forLocale(locale); 1623 } 1624 } 1625 1626 private static final char SINGLE_QUOTE = '\''; 1627 private static final char CURLY_BRACE_LEFT = '{'; 1628 private static final char CURLY_BRACE_RIGHT = '}'; 1629 1630 private static final int STATE_INITIAL = 0; 1631 private static final int STATE_SINGLE_QUOTE = 1; 1632 private static final int STATE_IN_QUOTE = 2; 1633 private static final int STATE_MSG_ELEMENT = 3; 1634 1635 1653 public static String autoQuoteApostrophe(String pattern) { 1654 StringBuffer buf = new StringBuffer (pattern.length()*2); 1655 int state = STATE_INITIAL; 1656 int braceCount = 0; 1657 for (int i = 0, j = pattern.length(); i < j; ++i) { 1658 char c = pattern.charAt(i); 1659 switch (state) { 1660 case STATE_INITIAL: 1661 switch (c) { 1662 case SINGLE_QUOTE: 1663 state = STATE_SINGLE_QUOTE; 1664 break; 1665 case CURLY_BRACE_LEFT: 1666 state = STATE_MSG_ELEMENT; 1667 ++braceCount; 1668 break; 1669 } 1670 break; 1671 case STATE_SINGLE_QUOTE: 1672 switch (c) { 1673 case SINGLE_QUOTE: 1674 state = STATE_INITIAL; 1675 break; 1676 case CURLY_BRACE_LEFT: 1677 case CURLY_BRACE_RIGHT: 1678 state = STATE_IN_QUOTE; 1679 break; 1680 default: 1681 buf.append(SINGLE_QUOTE); 1682 state = STATE_INITIAL; 1683 break; 1684 } 1685 break; 1686 case STATE_IN_QUOTE: 1687 switch (c) { 1688 case SINGLE_QUOTE: 1689 state = STATE_INITIAL; 1690 break; 1691 } 1692 break; 1693 case STATE_MSG_ELEMENT: 1694 switch (c) { 1695 case CURLY_BRACE_LEFT: 1696 ++braceCount; 1697 break; 1698 case CURLY_BRACE_RIGHT: 1699 if (--braceCount == 0) { 1700 state = STATE_INITIAL; 1701 } 1702 break; 1703 } 1704 break; 1705 default: break; 1707 } 1708 buf.append(c); 1709 } 1710 if (state == STATE_SINGLE_QUOTE || state == STATE_IN_QUOTE) { 1712 buf.append(SINGLE_QUOTE); 1713 } 1714 return new String (buf); 1715 } 1716} 1717 | Popular Tags |