1 16 19 package org.apache.xalan.templates; 20 21 import java.text.DecimalFormat ; 22 import java.text.DecimalFormatSymbols ; 23 import java.text.NumberFormat ; 24 import java.util.Locale ; 25 import java.util.NoSuchElementException ; 26 27 import javax.xml.transform.TransformerException ; 28 29 import org.apache.xalan.res.XSLTErrorResources; 30 import org.apache.xalan.transformer.CountersTable; 31 import org.apache.xalan.transformer.DecimalToRoman; 32 import org.apache.xalan.transformer.TransformerImpl; 33 import org.apache.xml.dtm.DTM; 34 import org.apache.xml.utils.FastStringBuffer; 35 import org.apache.xml.utils.NodeVector; 36 import org.apache.xml.utils.PrefixResolver; 37 import org.apache.xml.utils.StringBufferPool; 38 import org.apache.xml.utils.res.XResourceBundle; 39 import org.apache.xpath.NodeSetDTM; 40 import org.apache.xpath.XPath; 41 import org.apache.xpath.XPathContext; 42 import org.apache.xpath.objects.XObject; 43 44 import org.w3c.dom.Node ; 45 46 import org.xml.sax.SAXException ; 47 48 50 69 public class ElemNumber extends ElemTemplateElement 70 { 71 72 private class MyPrefixResolver implements PrefixResolver { 73 74 DTM dtm; 75 int handle; 76 boolean handleNullPrefix; 77 78 82 public MyPrefixResolver(Node xpathExpressionContext, DTM dtm, int handle, boolean handleNullPrefix) { 83 this.dtm = dtm; 84 this.handle = handle; 85 this.handleNullPrefix = handleNullPrefix; 86 } 87 88 91 public String getNamespaceForPrefix(String prefix) { 92 return dtm.getNamespaceURI(handle); 93 } 94 95 99 public String getNamespaceForPrefix(String prefix, Node context) { 100 return getNamespaceForPrefix(prefix); 101 } 102 103 106 public String getBaseIdentifier() { 107 return ElemNumber.this.getBaseIdentifier(); 108 } 109 110 113 public boolean handlesNullPrefixes() { 114 return handleNullPrefix; 115 } 116 117 } 118 119 123 private XPath m_countMatchPattern = null; 124 125 136 public void setCount(XPath v) 137 { 138 m_countMatchPattern = v; 139 } 140 141 152 public XPath getCount() 153 { 154 return m_countMatchPattern; 155 } 156 157 168 private XPath m_fromMatchPattern = null; 169 170 182 public void setFrom(XPath v) 183 { 184 m_fromMatchPattern = v; 185 } 186 187 199 public XPath getFrom() 200 { 201 return m_fromMatchPattern; 202 } 203 204 230 private int m_level = Constants.NUMBERLEVEL_SINGLE; 231 232 240 public void setLevel(int v) 241 { 242 m_level = v; 243 } 244 245 253 public int getLevel() 254 { 255 return m_level; 256 } 257 258 264 private XPath m_valueExpr = null; 265 266 274 public void setValue(XPath v) 275 { 276 m_valueExpr = v; 277 } 278 279 287 public XPath getValue() 288 { 289 return m_valueExpr; 290 } 291 292 298 private AVT m_format_avt = null; 299 300 308 public void setFormat(AVT v) 309 { 310 m_format_avt = v; 311 } 312 313 321 public AVT getFormat() 322 { 323 return m_format_avt; 324 } 325 326 331 private AVT m_lang_avt = null; 332 333 344 public void setLang(AVT v) 345 { 346 m_lang_avt = v; 347 } 348 349 360 public AVT getLang() 361 { 362 return m_lang_avt; 363 } 364 365 370 private AVT m_lettervalue_avt = null; 371 372 380 public void setLetterValue(AVT v) 381 { 382 m_lettervalue_avt = v; 383 } 384 385 393 public AVT getLetterValue() 394 { 395 return m_lettervalue_avt; 396 } 397 398 404 private AVT m_groupingSeparator_avt = null; 405 406 415 public void setGroupingSeparator(AVT v) 416 { 417 m_groupingSeparator_avt = v; 418 } 419 420 429 public AVT getGroupingSeparator() 430 { 431 return m_groupingSeparator_avt; 432 } 433 434 438 private AVT m_groupingSize_avt = null; 439 440 447 public void setGroupingSize(AVT v) 448 { 449 m_groupingSize_avt = v; 450 } 451 452 459 public AVT getGroupingSize() 460 { 461 return m_groupingSize_avt; 462 } 463 464 467 468 470 474 private final static DecimalToRoman m_romanConvertTable[] = { 475 new DecimalToRoman(1000, "M", 900, "CM"), 476 new DecimalToRoman(500, "D", 400, "CD"), 477 new DecimalToRoman(100L, "C", 90L, "XC"), 478 new DecimalToRoman(50L, "L", 40L, "XL"), 479 new DecimalToRoman(10L, "X", 9L, "IX"), 480 new DecimalToRoman(5L, "V", 4L, "IV"), 481 new DecimalToRoman(1L, "I", 1L, "I") }; 482 483 487 private static char[] m_alphaCountTable = null; 488 489 495 public void compose(StylesheetRoot sroot) throws TransformerException 496 { 497 super.compose(sroot); 498 StylesheetRoot.ComposeState cstate = sroot.getComposeState(); 499 java.util.Vector vnames = cstate.getVariableNames(); 500 if(null != m_countMatchPattern) 501 m_countMatchPattern.fixupVariables(vnames, cstate.getGlobalsSize()); 502 if(null != m_format_avt) 503 m_format_avt.fixupVariables(vnames, cstate.getGlobalsSize()); 504 if(null != m_fromMatchPattern) 505 m_fromMatchPattern.fixupVariables(vnames, cstate.getGlobalsSize()); 506 if(null != m_groupingSeparator_avt) 507 m_groupingSeparator_avt.fixupVariables(vnames, cstate.getGlobalsSize()); 508 if(null != m_groupingSize_avt) 509 m_groupingSize_avt.fixupVariables(vnames, cstate.getGlobalsSize()); 510 if(null != m_lang_avt) 511 m_lang_avt.fixupVariables(vnames, cstate.getGlobalsSize()); 512 if(null != m_lettervalue_avt) 513 m_lettervalue_avt.fixupVariables(vnames, cstate.getGlobalsSize()); 514 if(null != m_valueExpr) 515 m_valueExpr.fixupVariables(vnames, cstate.getGlobalsSize()); 516 } 517 518 519 525 public int getXSLToken() 526 { 527 return Constants.ELEMNAME_NUMBER; 528 } 529 530 535 public String getNodeName() 536 { 537 return Constants.ELEMNAME_NUMBER_STRING; 538 } 539 540 550 public void execute( 551 TransformerImpl transformer) 552 throws TransformerException 553 { 554 555 if (TransformerImpl.S_DEBUG) 556 transformer.getTraceManager().fireTraceEvent(this); 557 558 int sourceNode = transformer.getXPathContext().getCurrentNode(); 559 String countString = getCountString(transformer, sourceNode); 560 561 try 562 { 563 transformer.getResultTreeHandler().characters(countString.toCharArray(), 564 0, countString.length()); 565 } 566 catch(SAXException se) 567 { 568 throw new TransformerException (se); 569 } 570 finally 571 { 572 if (TransformerImpl.S_DEBUG) 573 transformer.getTraceManager().fireTraceEndEvent(this); 574 } 575 } 576 577 586 public ElemTemplateElement appendChild(ElemTemplateElement newChild) 587 { 588 589 error(XSLTErrorResources.ER_CANNOT_ADD, 590 new Object []{ newChild.getNodeName(), 591 this.getNodeName() }); 593 return null; 595 } 596 597 613 int findAncestor( 614 XPathContext xctxt, XPath fromMatchPattern, XPath countMatchPattern, 615 int context, ElemNumber namespaceContext) 616 throws javax.xml.transform.TransformerException 617 { 618 DTM dtm = xctxt.getDTM(context); 619 while (DTM.NULL != context) 620 { 621 if (null != fromMatchPattern) 622 { 623 if (fromMatchPattern.getMatchScore(xctxt, context) 624 != XPath.MATCH_SCORE_NONE) 625 { 626 627 break; 629 } 630 } 631 632 if (null != countMatchPattern) 633 { 634 if (countMatchPattern.getMatchScore(xctxt, context) 635 != XPath.MATCH_SCORE_NONE) 636 { 637 break; 638 } 639 } 640 641 context = dtm.getParent(context); 642 } 643 644 return context; 645 } 646 647 663 private int findPrecedingOrAncestorOrSelf( 664 XPathContext xctxt, XPath fromMatchPattern, XPath countMatchPattern, 665 int context, ElemNumber namespaceContext) 666 throws javax.xml.transform.TransformerException 667 { 668 DTM dtm = xctxt.getDTM(context); 669 while (DTM.NULL != context) 670 { 671 if (null != fromMatchPattern) 672 { 673 if (fromMatchPattern.getMatchScore(xctxt, context) 674 != XPath.MATCH_SCORE_NONE) 675 { 676 context = DTM.NULL; 677 678 break; 679 } 680 } 681 682 if (null != countMatchPattern) 683 { 684 if (countMatchPattern.getMatchScore(xctxt, context) 685 != XPath.MATCH_SCORE_NONE) 686 { 687 break; 688 } 689 } 690 691 int prevSibling = dtm.getPreviousSibling(context); 692 693 if (DTM.NULL == prevSibling) 694 { 695 context = dtm.getParent(context); 696 } 697 else 698 { 699 700 context = dtm.getLastChild(prevSibling); 702 703 if (context == DTM.NULL) 704 context = prevSibling; 705 } 706 } 707 708 return context; 709 } 710 711 721 XPath getCountMatchPattern(XPathContext support, int contextNode) 722 throws javax.xml.transform.TransformerException 723 { 724 725 XPath countMatchPattern = m_countMatchPattern; 726 DTM dtm = support.getDTM(contextNode); 727 if (null == countMatchPattern) 728 { 729 switch (dtm.getNodeType(contextNode)) 730 { 731 case DTM.ELEMENT_NODE : 732 MyPrefixResolver resolver; 733 734 if (dtm.getNamespaceURI(contextNode) == null) { 735 resolver = new MyPrefixResolver(dtm.getNode(contextNode), dtm,contextNode, false); 736 } else { 737 resolver = new MyPrefixResolver(dtm.getNode(contextNode), dtm,contextNode, true); 738 } 739 740 countMatchPattern = new XPath(dtm.getNodeName(contextNode), this, resolver, 741 XPath.MATCH, support.getErrorListener()); 742 break; 743 744 case DTM.ATTRIBUTE_NODE : 745 746 countMatchPattern = new XPath("@" + dtm.getNodeName(contextNode), this, 748 this, XPath.MATCH, support.getErrorListener()); 749 break; 750 case DTM.CDATA_SECTION_NODE : 751 case DTM.TEXT_NODE : 752 753 countMatchPattern = new XPath("text()", this, this, XPath.MATCH, support.getErrorListener()); 755 break; 756 case DTM.COMMENT_NODE : 757 758 countMatchPattern = new XPath("comment()", this, this, XPath.MATCH, support.getErrorListener()); 760 break; 761 case DTM.DOCUMENT_NODE : 762 763 countMatchPattern = new XPath("/", this, this, XPath.MATCH, support.getErrorListener()); 765 break; 766 case DTM.PROCESSING_INSTRUCTION_NODE : 767 768 countMatchPattern = new XPath("pi(" + dtm.getNodeName(contextNode) 770 + ")", this, this, XPath.MATCH, support.getErrorListener()); 771 break; 772 default : 773 countMatchPattern = null; 774 } 775 } 776 777 return countMatchPattern; 778 } 779 780 790 String getCountString(TransformerImpl transformer, int sourceNode) 791 throws TransformerException 792 { 793 794 long[] list = null; 795 XPathContext xctxt = transformer.getXPathContext(); 796 CountersTable ctable = transformer.getCountersTable(); 797 798 if (null != m_valueExpr) 799 { 800 XObject countObj = m_valueExpr.execute(xctxt, sourceNode, this); 801 long count = (long)java.lang.Math.floor(countObj.num()+ 0.5); 802 803 list = new long[1]; 804 list[0] = count; 805 } 806 else 807 { 808 if (Constants.NUMBERLEVEL_ANY == m_level) 809 { 810 list = new long[1]; 811 list[0] = ctable.countNode(xctxt, this, sourceNode); 812 } 813 else 814 { 815 NodeVector ancestors = 816 getMatchingAncestors(xctxt, sourceNode, 817 Constants.NUMBERLEVEL_SINGLE == m_level); 818 int lastIndex = ancestors.size() - 1; 819 820 if (lastIndex >= 0) 821 { 822 list = new long[lastIndex + 1]; 823 824 for (int i = lastIndex; i >= 0; i--) 825 { 826 int target = ancestors.elementAt(i); 827 828 list[lastIndex - i] = ctable.countNode(xctxt, this, target); 829 } 830 } 831 } 832 } 833 834 return (null != list) 835 ? formatNumberList(transformer, list, sourceNode) : ""; 836 } 837 838 848 public int getPreviousNode(XPathContext xctxt, int pos) 849 throws TransformerException 850 { 851 852 XPath countMatchPattern = getCountMatchPattern(xctxt, pos); 853 DTM dtm = xctxt.getDTM(pos); 854 855 if (Constants.NUMBERLEVEL_ANY == m_level) 856 { 857 XPath fromMatchPattern = m_fromMatchPattern; 858 859 while (DTM.NULL != pos) 863 { 864 865 int next = dtm.getPreviousSibling(pos); 869 870 if (DTM.NULL == next) 871 { 872 next = dtm.getParent(pos); 873 874 if ((DTM.NULL != next) && ((((null != fromMatchPattern) && (fromMatchPattern.getMatchScore( 875 xctxt, next) != XPath.MATCH_SCORE_NONE))) 876 || (dtm.getNodeType(next) == DTM.DOCUMENT_NODE))) 877 { 878 pos = DTM.NULL; 880 break; } 882 } 883 else 884 { 885 886 int child = next; 888 889 while (DTM.NULL != child) 890 { 891 child = dtm.getLastChild(next); 892 893 if (DTM.NULL != child) 894 next = child; 895 } 896 } 897 898 pos = next; 899 900 if ((DTM.NULL != pos) 901 && ((null == countMatchPattern) 902 || (countMatchPattern.getMatchScore(xctxt, pos) 903 != XPath.MATCH_SCORE_NONE))) 904 { 905 break; 906 } 907 } 908 } 909 else { 911 while (DTM.NULL != pos) 912 { 913 pos = dtm.getPreviousSibling(pos); 914 915 if ((DTM.NULL != pos) 916 && ((null == countMatchPattern) 917 || (countMatchPattern.getMatchScore(xctxt, pos) 918 != XPath.MATCH_SCORE_NONE))) 919 { 920 break; 921 } 922 } 923 } 924 925 return pos; 926 } 927 928 938 public int getTargetNode(XPathContext xctxt, int sourceNode) 939 throws TransformerException 940 { 941 942 int target = DTM.NULL; 943 XPath countMatchPattern = getCountMatchPattern(xctxt, sourceNode); 944 945 if (Constants.NUMBERLEVEL_ANY == m_level) 946 { 947 target = findPrecedingOrAncestorOrSelf(xctxt, m_fromMatchPattern, 948 countMatchPattern, sourceNode, 949 this); 950 } 951 else 952 { 953 target = findAncestor(xctxt, m_fromMatchPattern, countMatchPattern, 954 sourceNode, this); 955 } 956 957 return target; 958 } 959 960 975 NodeVector getMatchingAncestors( 976 XPathContext xctxt, int node, boolean stopAtFirstFound) 977 throws javax.xml.transform.TransformerException 978 { 979 980 NodeSetDTM ancestors = new NodeSetDTM(xctxt.getDTMManager()); 981 XPath countMatchPattern = getCountMatchPattern(xctxt, node); 982 DTM dtm = xctxt.getDTM(node); 983 984 while (DTM.NULL != node) 985 { 986 if ((null != m_fromMatchPattern) 987 && (m_fromMatchPattern.getMatchScore(xctxt, node) 988 != XPath.MATCH_SCORE_NONE)) 989 { 990 991 if (!stopAtFirstFound) 998 break; 999 } 1000 1001 if (null == countMatchPattern) 1002 System.out.println( 1003 "Programmers error! countMatchPattern should never be null!"); 1004 1005 if (countMatchPattern.getMatchScore(xctxt, node) 1006 != XPath.MATCH_SCORE_NONE) 1007 { 1008 ancestors.addElement(node); 1009 1010 if (stopAtFirstFound) 1011 break; 1012 } 1013 1014 node = dtm.getParent(node); 1015 } 1016 1017 return ancestors; 1018 } 1020 1031 Locale getLocale(TransformerImpl transformer, int contextNode) 1032 throws TransformerException 1033 { 1034 1035 Locale locale = null; 1036 1037 if (null != m_lang_avt) 1038 { 1039 XPathContext xctxt = transformer.getXPathContext(); 1040 String langValue = m_lang_avt.evaluate(xctxt, contextNode, this); 1041 1042 if (null != langValue) 1043 { 1044 1045 locale = new Locale (langValue.toUpperCase(), ""); 1049 1050 if (null == locale) 1052 { 1053 transformer.getMsgMgr().warn(this, null, xctxt.getDTM(contextNode).getNode(contextNode), 1054 XSLTErrorResources.WG_LOCALE_NOT_FOUND, 1055 new Object []{ langValue }); 1057 locale = Locale.getDefault(); 1058 } 1059 } 1060 } 1061 else 1062 { 1063 locale = Locale.getDefault(); 1064 } 1065 1066 return locale; 1067 } 1068 1069 1079 private DecimalFormat getNumberFormatter( 1080 TransformerImpl transformer, int contextNode) throws TransformerException 1081 { 1082 Locale locale = (Locale )getLocale(transformer, contextNode).clone(); 1086 1087 DecimalFormat formatter = null; 1089 1090 1095 String digitGroupSepValue = 1096 (null != m_groupingSeparator_avt) 1097 ? m_groupingSeparator_avt.evaluate( 1098 transformer.getXPathContext(), contextNode, this) : null; 1099 1100 1101 if ((digitGroupSepValue != null) && (!m_groupingSeparator_avt.isSimple()) && 1104 (digitGroupSepValue.length() != 1)) 1105 { 1106 transformer.getMsgMgr().warn( 1107 this, XSLTErrorResources.WG_ILLEGAL_ATTRIBUTE_VALUE, 1108 new Object []{ Constants.ATTRNAME_NAME, m_groupingSeparator_avt.getName()}); 1109 } 1110 1111 1112 String nDigitsPerGroupValue = 1113 (null != m_groupingSize_avt) 1114 ? m_groupingSize_avt.evaluate( 1115 transformer.getXPathContext(), contextNode, this) : null; 1116 1117 if ((null != digitGroupSepValue) && (null != nDigitsPerGroupValue) && 1119 (digitGroupSepValue.length() > 0)) 1121 { 1122 try 1123 { 1124 formatter = (DecimalFormat ) NumberFormat.getNumberInstance(locale); 1125 formatter.setGroupingSize( 1126 Integer.valueOf(nDigitsPerGroupValue).intValue()); 1127 1128 DecimalFormatSymbols symbols = formatter.getDecimalFormatSymbols(); 1129 symbols.setGroupingSeparator(digitGroupSepValue.charAt(0)); 1130 formatter.setDecimalFormatSymbols(symbols); 1131 formatter.setGroupingUsed(true); 1132 } 1133 catch (NumberFormatException ex) 1134 { 1135 formatter.setGroupingUsed(false); 1136 } 1137 } 1138 1139 return formatter; 1140 } 1141 1142 1156 String formatNumberList( 1157 TransformerImpl transformer, long[] list, int contextNode) 1158 throws TransformerException 1159 { 1160 1161 String numStr; 1162 FastStringBuffer formattedNumber = StringBufferPool.get(); 1163 1164 try 1165 { 1166 int nNumbers = list.length, numberWidth = 1; 1167 char numberType = '1'; 1168 String formatToken, lastSepString = null, formatTokenString = null; 1169 1170 String lastSep = "."; 1178 boolean isFirstToken = true; String formatValue = 1180 (null != m_format_avt) 1181 ? m_format_avt.evaluate( 1182 transformer.getXPathContext(), contextNode, this) : null; 1183 1184 if (null == formatValue) 1185 formatValue = "1"; 1186 1187 NumberFormatStringTokenizer formatTokenizer = 1188 new NumberFormatStringTokenizer(formatValue); 1189 1190 for (int i = 0; i < nNumbers; i++) 1193 { 1194 1195 if (formatTokenizer.hasMoreTokens()) 1197 { 1198 formatToken = formatTokenizer.nextToken(); 1199 1200 if (Character.isLetterOrDigit( 1203 formatToken.charAt(formatToken.length() - 1))) 1204 { 1205 numberWidth = formatToken.length(); 1206 numberType = formatToken.charAt(numberWidth - 1); 1207 } 1208 1209 else if (formatTokenizer.isLetterOrDigitAhead()) 1212 { 1213 formatTokenString = formatToken; 1214 1215 while (formatTokenizer.nextIsSep()) 1219 { 1220 formatToken = formatTokenizer.nextToken(); 1221 formatTokenString += formatToken; 1222 } 1223 1224 if (!isFirstToken) 1229 lastSep = formatTokenString; 1230 1231 formatToken = formatTokenizer.nextToken(); 1233 numberWidth = formatToken.length(); 1234 numberType = formatToken.charAt(numberWidth - 1); 1235 } 1236 else { 1238 1239 lastSepString = formatToken; 1242 1243 while (formatTokenizer.hasMoreTokens()) 1245 { 1246 formatToken = formatTokenizer.nextToken(); 1247 lastSepString += formatToken; 1248 } 1249 } } 1252 if (null != formatTokenString && isFirstToken) 1257 { 1258 formattedNumber.append(formatTokenString); 1259 } 1260 else if (null != lastSep &&!isFirstToken) 1261 formattedNumber.append(lastSep); 1262 1263 getFormattedNumber(transformer, contextNode, numberType, numberWidth, 1264 list[i], formattedNumber); 1265 1266 isFirstToken = false; } 1269 while (formatTokenizer.isLetterOrDigitAhead()) 1272 { 1273 formatTokenizer.nextToken(); 1274 } 1275 1276 if (lastSepString != null) 1277 formattedNumber.append(lastSepString); 1278 1279 while (formatTokenizer.hasMoreTokens()) 1280 { 1281 formatToken = formatTokenizer.nextToken(); 1282 1283 formattedNumber.append(formatToken); 1284 } 1285 1286 numStr = formattedNumber.toString(); 1287 } 1288 finally 1289 { 1290 StringBufferPool.free(formattedNumber); 1291 } 1292 1293 return numStr; 1294 } 1296 1299 1300 1313 private void getFormattedNumber( 1314 TransformerImpl transformer, int contextNode, 1315 char numberType, int numberWidth, long listElement, 1316 FastStringBuffer formattedNumber) 1317 throws javax.xml.transform.TransformerException 1318 { 1319 1320 1321 String letterVal = 1322 (m_lettervalue_avt != null) 1323 ? m_lettervalue_avt.evaluate( 1324 transformer.getXPathContext(), contextNode, this) : null; 1325 1326 switch (numberType) 1327 { 1328 case 'A' : 1329 if (m_alphaCountTable == null) 1330 { 1331 XResourceBundle thisBundle; 1332 1333 thisBundle = 1334 (XResourceBundle) XResourceBundle.loadResourceBundle( 1335 org.apache.xml.utils.res.XResourceBundle.LANG_BUNDLE_NAME, getLocale(transformer, contextNode)); 1336 1337 char[] alphabet; 1338 1339 alphabet = (char[]) thisBundle.getObject(org.apache.xml.utils.res.XResourceBundle.LANG_ALPHABET); 1340 m_alphaCountTable = alphabet; 1341 } 1342 1343 int2alphaCount(listElement, m_alphaCountTable, formattedNumber); 1344 break; 1345 case 'a' : 1346 if (m_alphaCountTable == null) 1347 { 1348 XResourceBundle thisBundle; 1349 1350 thisBundle = 1351 (XResourceBundle) XResourceBundle.loadResourceBundle( 1352 org.apache.xml.utils.res.XResourceBundle.LANG_BUNDLE_NAME, getLocale(transformer, contextNode)); 1353 1354 char[] alphabet; 1355 1356 alphabet = (char[]) thisBundle.getObject(org.apache.xml.utils.res.XResourceBundle.LANG_ALPHABET); 1357 m_alphaCountTable = alphabet; 1358 } 1359 1360 FastStringBuffer stringBuf = StringBufferPool.get(); 1361 1362 try 1363 { 1364 int2alphaCount(listElement, m_alphaCountTable, stringBuf); 1365 formattedNumber.append( 1366 stringBuf.toString().toLowerCase( 1367 getLocale(transformer, contextNode))); 1368 } 1369 finally 1370 { 1371 StringBufferPool.free(stringBuf); 1372 } 1373 break; 1374 case 'I' : 1375 formattedNumber.append(long2roman(listElement, true)); 1376 break; 1377 case 'i' : 1378 formattedNumber.append( 1379 long2roman(listElement, true).toLowerCase( 1380 getLocale(transformer, contextNode))); 1381 break; 1382 case 0x3042 : 1383 { 1384 XResourceBundle thisBundle; 1385 1386 thisBundle = (XResourceBundle) XResourceBundle.loadResourceBundle( 1387 org.apache.xml.utils.res.XResourceBundle.LANG_BUNDLE_NAME, new Locale ("ja", "JP", "HA")); 1388 1389 if (letterVal != null 1390 && letterVal.equals(Constants.ATTRVAL_TRADITIONAL)) 1391 formattedNumber.append(tradAlphaCount(listElement, thisBundle)); 1392 else formattedNumber.append( 1394 int2singlealphaCount( 1395 listElement, 1396 (char[]) thisBundle.getObject(org.apache.xml.utils.res.XResourceBundle.LANG_ALPHABET))); 1397 1398 break; 1399 } 1400 case 0x3044 : 1401 { 1402 XResourceBundle thisBundle; 1403 1404 thisBundle = (XResourceBundle) XResourceBundle.loadResourceBundle( 1405 org.apache.xml.utils.res.XResourceBundle.LANG_BUNDLE_NAME, new Locale ("ja", "JP", "HI")); 1406 1407 if ((letterVal != null) 1408 && letterVal.equals(Constants.ATTRVAL_TRADITIONAL)) 1409 formattedNumber.append(tradAlphaCount(listElement, thisBundle)); 1410 else formattedNumber.append( 1412 int2singlealphaCount( 1413 listElement, 1414 (char[]) thisBundle.getObject(org.apache.xml.utils.res.XResourceBundle.LANG_ALPHABET))); 1415 1416 break; 1417 } 1418 case 0x30A2 : 1419 { 1420 XResourceBundle thisBundle; 1421 1422 thisBundle = (XResourceBundle) XResourceBundle.loadResourceBundle( 1423 org.apache.xml.utils.res.XResourceBundle.LANG_BUNDLE_NAME, new Locale ("ja", "JP", "A")); 1424 1425 if (letterVal != null 1426 && letterVal.equals(Constants.ATTRVAL_TRADITIONAL)) 1427 formattedNumber.append(tradAlphaCount(listElement, thisBundle)); 1428 else formattedNumber.append( 1430 int2singlealphaCount( 1431 listElement, 1432 (char[]) thisBundle.getObject(org.apache.xml.utils.res.XResourceBundle.LANG_ALPHABET))); 1433 1434 break; 1435 } 1436 case 0x30A4 : 1437 { 1438 XResourceBundle thisBundle; 1439 1440 thisBundle = (XResourceBundle) XResourceBundle.loadResourceBundle( 1441 org.apache.xml.utils.res.XResourceBundle.LANG_BUNDLE_NAME, new Locale ("ja", "JP", "I")); 1442 1443 if (letterVal != null 1444 && letterVal.equals(Constants.ATTRVAL_TRADITIONAL)) 1445 formattedNumber.append(tradAlphaCount(listElement, thisBundle)); 1446 else formattedNumber.append( 1448 int2singlealphaCount( 1449 listElement, 1450 (char[]) thisBundle.getObject(org.apache.xml.utils.res.XResourceBundle.LANG_ALPHABET))); 1451 1452 break; 1453 } 1454 case 0x4E00 : 1455 { 1456 XResourceBundle thisBundle; 1457 1458 thisBundle = (XResourceBundle) XResourceBundle.loadResourceBundle( 1459 org.apache.xml.utils.res.XResourceBundle.LANG_BUNDLE_NAME, new Locale ("zh", "CN")); 1460 1461 if (letterVal != null 1462 && letterVal.equals(Constants.ATTRVAL_TRADITIONAL)) 1463 { 1464 formattedNumber.append(tradAlphaCount(listElement, thisBundle)); 1465 } 1466 else int2alphaCount(listElement, 1468 (char[]) thisBundle.getObject(org.apache.xml.utils.res.XResourceBundle.LANG_ALPHABET), 1469 formattedNumber); 1470 1471 break; 1472 } 1473 case 0x58F9 : 1474 { 1475 XResourceBundle thisBundle; 1476 1477 thisBundle = (XResourceBundle) XResourceBundle.loadResourceBundle( 1478 org.apache.xml.utils.res.XResourceBundle.LANG_BUNDLE_NAME, new Locale ("zh", "TW")); 1479 1480 if (letterVal != null 1481 && letterVal.equals(Constants.ATTRVAL_TRADITIONAL)) 1482 formattedNumber.append(tradAlphaCount(listElement, thisBundle)); 1483 else int2alphaCount(listElement, 1485 (char[]) thisBundle.getObject(org.apache.xml.utils.res.XResourceBundle.LANG_ALPHABET), 1486 formattedNumber); 1487 1488 break; 1489 } 1490 case 0x0E51 : 1491 { 1492 XResourceBundle thisBundle; 1493 1494 thisBundle = (XResourceBundle) XResourceBundle.loadResourceBundle( 1495 org.apache.xml.utils.res.XResourceBundle.LANG_BUNDLE_NAME, new Locale ("th", "")); 1496 1497 if (letterVal != null 1498 && letterVal.equals(Constants.ATTRVAL_TRADITIONAL)) 1499 formattedNumber.append(tradAlphaCount(listElement, thisBundle)); 1500 else int2alphaCount(listElement, 1502 (char[]) thisBundle.getObject(org.apache.xml.utils.res.XResourceBundle.LANG_ALPHABET), 1503 formattedNumber); 1504 1505 break; 1506 } 1507 case 0x05D0 : 1508 { 1509 XResourceBundle thisBundle; 1510 1511 thisBundle = (XResourceBundle) XResourceBundle.loadResourceBundle( 1512 org.apache.xml.utils.res.XResourceBundle.LANG_BUNDLE_NAME, new Locale ("he", "")); 1513 1514 if (letterVal != null 1515 && letterVal.equals(Constants.ATTRVAL_TRADITIONAL)) 1516 formattedNumber.append(tradAlphaCount(listElement, thisBundle)); 1517 else int2alphaCount(listElement, 1519 (char[]) thisBundle.getObject(org.apache.xml.utils.res.XResourceBundle.LANG_ALPHABET), 1520 formattedNumber); 1521 1522 break; 1523 } 1524 case 0x10D0 : 1525 { 1526 XResourceBundle thisBundle; 1527 1528 thisBundle = (XResourceBundle) XResourceBundle.loadResourceBundle( 1529 org.apache.xml.utils.res.XResourceBundle.LANG_BUNDLE_NAME, new Locale ("ka", "")); 1530 1531 if (letterVal != null 1532 && letterVal.equals(Constants.ATTRVAL_TRADITIONAL)) 1533 formattedNumber.append(tradAlphaCount(listElement, thisBundle)); 1534 else int2alphaCount(listElement, 1536 (char[]) thisBundle.getObject(org.apache.xml.utils.res.XResourceBundle.LANG_ALPHABET), 1537 formattedNumber); 1538 1539 break; 1540 } 1541 case 0x03B1 : 1542 { 1543 XResourceBundle thisBundle; 1544 1545 thisBundle = (XResourceBundle) XResourceBundle.loadResourceBundle( 1546 org.apache.xml.utils.res.XResourceBundle.LANG_BUNDLE_NAME, new Locale ("el", "")); 1547 1548 if (letterVal != null 1549 && letterVal.equals(Constants.ATTRVAL_TRADITIONAL)) 1550 formattedNumber.append(tradAlphaCount(listElement, thisBundle)); 1551 else int2alphaCount(listElement, 1553 (char[]) thisBundle.getObject(org.apache.xml.utils.res.XResourceBundle.LANG_ALPHABET), 1554 formattedNumber); 1555 1556 break; 1557 } 1558 case 0x0430 : 1559 { 1560 XResourceBundle thisBundle; 1561 1562 thisBundle = (XResourceBundle) XResourceBundle.loadResourceBundle( 1563 org.apache.xml.utils.res.XResourceBundle.LANG_BUNDLE_NAME, new Locale ("cy", "")); 1564 1565 if (letterVal != null 1566 && letterVal.equals(Constants.ATTRVAL_TRADITIONAL)) 1567 formattedNumber.append(tradAlphaCount(listElement, thisBundle)); 1568 else int2alphaCount(listElement, 1570 (char[]) thisBundle.getObject(org.apache.xml.utils.res.XResourceBundle.LANG_ALPHABET), 1571 formattedNumber); 1572 1573 break; 1574 } 1575 default : DecimalFormat formatter = getNumberFormatter(transformer, contextNode); 1577 String padString = formatter == null ? String.valueOf(0) : formatter.format(0); 1578 String numString = formatter == null ? String.valueOf(listElement) : formatter.format(listElement); 1579 int nPadding = numberWidth - numString.length(); 1580 1581 for (int k = 0; k < nPadding; k++) 1582 { 1583 formattedNumber.append(padString); 1584 } 1585 1586 formattedNumber.append(numString); 1587 } 1588 } 1589 1590 1594 String getZeroString() 1595 { 1596 return ""+0; 1597 } 1598 1599 1611 protected String int2singlealphaCount(long val, char[] table) 1612 { 1613 1614 int radix = table.length; 1615 1616 if (val > radix) 1618 { 1619 return getZeroString(); 1620 } 1621 else 1622 return (new Character (table[(int)val - 1])).toString(); } 1624 1625 1639 protected void int2alphaCount(long val, char[] aTable, 1640 FastStringBuffer stringBuf) 1641 { 1642 1643 int radix = aTable.length; 1644 char[] table = new char[aTable.length]; 1645 1646 int i; 1648 1649 for (i = 0; i < aTable.length - 1; i++) 1650 { 1651 table[i + 1] = aTable[i]; 1652 } 1653 1654 table[0] = aTable[i]; 1655 1656 char buf[] = new char[100]; 1660 1661 int charPos; 1666 1667 charPos = buf.length - 1; 1669 int lookupIndex = 1; 1672 long correction = 0; 1697 1698 do 1700 { 1701 1702 correction = 1706 ((lookupIndex == 0) || (correction != 0 && lookupIndex == radix - 1)) 1707 ? (radix - 1) : 0; 1708 1709 lookupIndex = (int)(val + correction) % radix; 1711 1712 val = (val / radix); 1714 1715 if (lookupIndex == 0 && val == 0) 1717 break; 1718 1719 buf[charPos--] = table[lookupIndex]; } 1722 while (val > 0); 1723 1724 stringBuf.append(buf, charPos + 1, (buf.length - charPos - 1)); 1725 } 1726 1727 1741 protected String tradAlphaCount(long val, XResourceBundle thisBundle) 1742 { 1743 1744 if (val > Long.MAX_VALUE) 1746 { 1747 this.error(XSLTErrorResources.ER_NUMBER_TOO_BIG); 1748 return XSLTErrorResources.ERROR_STRING; 1749 } 1750 char[] table = null; 1751 1752 int lookupIndex = 1; 1755 char buf[] = new char[100]; 1759 1760 int charPos; 1765 1766 charPos = 0; 1768 int[] groups = (int[]) thisBundle.getObject(org.apache.xml.utils.res.XResourceBundle.LANG_NUMBERGROUPS); 1770 1771 String [] tables = 1773 (String []) (thisBundle.getObject(org.apache.xml.utils.res.XResourceBundle.LANG_NUM_TABLES)); 1774 1775 String numbering = thisBundle.getString(org.apache.xml.utils.res.XResourceBundle.LANG_NUMBERING); 1778 1779 if (numbering.equals(org.apache.xml.utils.res.XResourceBundle.LANG_MULT_ADD)) 1781 { 1782 String mult_order = thisBundle.getString(org.apache.xml.utils.res.XResourceBundle.MULT_ORDER); 1783 long[] multiplier = 1784 (long[]) (thisBundle.getObject(org.apache.xml.utils.res.XResourceBundle.LANG_MULTIPLIER)); 1785 char[] zeroChar = (char[]) thisBundle.getObject("zero"); 1786 int i = 0; 1787 1788 while (i < multiplier.length && val < multiplier[i]) 1790 { 1791 i++; 1792 } 1793 1794 do 1795 { 1796 if (i >= multiplier.length) 1797 break; 1799 if (val < multiplier[i]) 1803 { 1804 if (zeroChar.length == 0) 1805 { 1806 i++; 1807 } 1808 else 1809 { 1810 if (buf[charPos - 1] != zeroChar[0]) 1811 buf[charPos++] = zeroChar[0]; 1812 1813 i++; 1814 } 1815 } 1816 else if (val >= multiplier[i]) 1817 { 1818 long mult = val / multiplier[i]; 1819 1820 val = val % multiplier[i]; 1822 int k = 0; 1823 1824 while (k < groups.length) 1825 { 1826 lookupIndex = 1; 1828 if (mult / groups[k] <= 0) k++; 1830 else 1831 { 1832 1833 char[] THEletters = (char[]) thisBundle.getObject(tables[k]); 1835 1836 table = new char[THEletters.length + 1]; 1837 1838 int j; 1839 1840 for (j = 0; j < THEletters.length; j++) 1841 { 1842 table[j + 1] = THEletters[j]; 1843 } 1844 1845 table[0] = THEletters[j - 1]; 1847 lookupIndex = (int)mult / groups[k]; 1849 1850 if (lookupIndex == 0 && mult == 0) 1852 break; 1853 1854 char multiplierChar = ((char[]) (thisBundle.getObject( 1855 org.apache.xml.utils.res.XResourceBundle.LANG_MULTIPLIER_CHAR)))[i]; 1856 1857 if (lookupIndex < table.length) 1859 { 1860 if (mult_order.equals(org.apache.xml.utils.res.XResourceBundle.MULT_PRECEDES)) 1861 { 1862 buf[charPos++] = multiplierChar; 1863 buf[charPos++] = table[lookupIndex]; 1864 } 1865 else 1866 { 1867 1868 if (lookupIndex == 1 && i == multiplier.length - 1){} 1870 else 1871 buf[charPos++] = table[lookupIndex]; 1872 1873 buf[charPos++] = multiplierChar; 1874 } 1875 1876 break; } 1878 else 1879 return XSLTErrorResources.ERROR_STRING; 1880 } } 1883 i++; 1884 } } while (i < multiplier.length); 1887 } 1888 1889 int count = 0; 1891 String tableName; 1892 1893 while (count < groups.length) 1895 { 1896 if (val / groups[count] <= 0) count++; 1898 else 1899 { 1900 char[] theletters = (char[]) thisBundle.getObject(tables[count]); 1901 1902 table = new char[theletters.length + 1]; 1903 1904 int j; 1905 1906 for (j = 0; j < theletters.length; j++) 1908 { 1909 table[j + 1] = theletters[j]; 1910 } 1911 1912 table[0] = theletters[j - 1]; 1914 lookupIndex = (int)val / groups[count]; 1916 1917 val = val % groups[count]; 1919 1920 if (lookupIndex == 0 && val == 0) 1922 break; 1923 1924 if (lookupIndex < table.length) 1925 { 1926 1927 buf[charPos++] = table[lookupIndex]; } 1930 else 1931 return XSLTErrorResources.ERROR_STRING; 1932 1933 count++; 1934 } 1935 } 1937 return new String (buf, 0, charPos); 1939 } 1940 1941 1950 protected String long2roman(long val, boolean prefixesAreOK) 1951 { 1952 1953 if (val <= 0) 1954 { 1955 return getZeroString(); 1956 } 1957 1958 String roman = ""; 1959 int place = 0; 1960 1961 if (val <= 3999L) 1962 { 1963 do 1964 { 1965 while (val >= m_romanConvertTable[place].m_postValue) 1966 { 1967 roman += m_romanConvertTable[place].m_postLetter; 1968 val -= m_romanConvertTable[place].m_postValue; 1969 } 1970 1971 if (prefixesAreOK) 1972 { 1973 if (val >= m_romanConvertTable[place].m_preValue) 1974 { 1975 roman += m_romanConvertTable[place].m_preLetter; 1976 val -= m_romanConvertTable[place].m_preValue; 1977 } 1978 } 1979 1980 place++; 1981 } 1982 while (val > 0); 1983 } 1984 else 1985 { 1986 roman = XSLTErrorResources.ERROR_STRING; 1987 } 1988 1989 return roman; 1990 } 1992 1996 public void callChildVisitors(XSLTVisitor visitor, boolean callAttrs) 1997 { 1998 if(callAttrs) 1999 { 2000 if(null != m_countMatchPattern) 2001 m_countMatchPattern.getExpression().callVisitors(m_countMatchPattern, visitor); 2002 if(null != m_fromMatchPattern) 2003 m_fromMatchPattern.getExpression().callVisitors(m_fromMatchPattern, visitor); 2004 if(null != m_valueExpr) 2005 m_valueExpr.getExpression().callVisitors(m_valueExpr, visitor); 2006 2007 if(null != m_format_avt) 2008 m_format_avt.callVisitors(visitor); 2009 if(null != m_groupingSeparator_avt) 2010 m_groupingSeparator_avt.callVisitors(visitor); 2011 if(null != m_groupingSize_avt) 2012 m_groupingSize_avt.callVisitors(visitor); 2013 if(null != m_lang_avt) 2014 m_lang_avt.callVisitors(visitor); 2015 if(null != m_lettervalue_avt) 2016 m_lettervalue_avt.callVisitors(visitor); 2017 } 2018 2019 super.callChildVisitors(visitor, callAttrs); 2020 } 2021 2022 2023 2027 class NumberFormatStringTokenizer 2028 { 2029 2030 2031 private int currentPosition; 2032 2033 2034 private int maxPosition; 2035 2036 2037 private String str; 2038 2039 2044 public NumberFormatStringTokenizer(String str) 2045 { 2046 this.str = str; 2047 maxPosition = str.length(); 2048 } 2049 2050 2053 public void reset() 2054 { 2055 currentPosition = 0; 2056 } 2057 2058 2065 public String nextToken() 2066 { 2067 2068 if (currentPosition >= maxPosition) 2069 { 2070 throw new NoSuchElementException (); 2071 } 2072 2073 int start = currentPosition; 2074 2075 while ((currentPosition < maxPosition) 2076 && Character.isLetterOrDigit(str.charAt(currentPosition))) 2077 { 2078 currentPosition++; 2079 } 2080 2081 if ((start == currentPosition) 2082 && (!Character.isLetterOrDigit(str.charAt(currentPosition)))) 2083 { 2084 currentPosition++; 2085 } 2086 2087 return str.substring(start, currentPosition); 2088 } 2089 2090 2095 public boolean isLetterOrDigitAhead() 2096 { 2097 2098 int pos = currentPosition; 2099 2100 while (pos < maxPosition) 2101 { 2102 if (Character.isLetterOrDigit(str.charAt(pos))) 2103 return true; 2104 2105 pos++; 2106 } 2107 2108 return false; 2109 } 2110 2111 2116 public boolean nextIsSep() 2117 { 2118 2119 if (Character.isLetterOrDigit(str.charAt(currentPosition))) 2120 return false; 2121 else 2122 return true; 2123 } 2124 2125 2132 public boolean hasMoreTokens() 2133 { 2134 return (currentPosition >= maxPosition) ? false : true; 2135 } 2136 2137 2146 public int countTokens() 2147 { 2148 2149 int count = 0; 2150 int currpos = currentPosition; 2151 2152 while (currpos < maxPosition) 2153 { 2154 int start = currpos; 2155 2156 while ((currpos < maxPosition) 2157 && Character.isLetterOrDigit(str.charAt(currpos))) 2158 { 2159 currpos++; 2160 } 2161 2162 if ((start == currpos) 2163 && (Character.isLetterOrDigit(str.charAt(currpos)) == false)) 2164 { 2165 currpos++; 2166 } 2167 2168 count++; 2169 } 2170 2171 return count; 2172 } 2173 } 2175 2176 2177} 2178 | Popular Tags |