1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 /* 19 * $Id: FuncFormatNumb.java 468643 2006-10-28 06:56:03Z minchau $ 20 */ 21 package org.apache.xalan.templates; 22 23 import javax.xml.transform.ErrorListener; 24 import javax.xml.transform.TransformerException; 25 26 import org.apache.xalan.res.XSLMessages; 27 import org.apache.xalan.res.XSLTErrorResources; 28 import org.apache.xml.utils.QName; 29 import org.apache.xml.utils.SAXSourceLocator; 30 import org.apache.xpath.Expression; 31 import org.apache.xpath.XPathContext; 32 import org.apache.xpath.functions.Function3Args; 33 import org.apache.xpath.functions.WrongNumberArgsException; 34 import org.apache.xpath.objects.XObject; 35 import org.apache.xpath.objects.XString; 36 37 /** 38 * Execute the FormatNumber() function. 39 * @xsl.usage advanced 40 */ 41 public class FuncFormatNumb extends Function3Args 42 { 43 static final long serialVersionUID = -8869935264870858636L; 44 45 /** 46 * Execute the function. The function must return 47 * a valid object. 48 * @param xctxt The current execution context. 49 * @return A valid XObject. 50 * 51 * @throws javax.xml.transform.TransformerException 52 */ execute(XPathContext xctxt)53 public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException 54 { 55 56 // A bit of an ugly hack to get our context. 57 ElemTemplateElement templElem = 58 (ElemTemplateElement) xctxt.getNamespaceContext(); 59 StylesheetRoot ss = templElem.getStylesheetRoot(); 60 java.text.DecimalFormat formatter = null; 61 java.text.DecimalFormatSymbols dfs = null; 62 double num = getArg0().execute(xctxt).num(); 63 String patternStr = getArg1().execute(xctxt).str(); 64 65 // TODO: what should be the behavior here?? 66 if (patternStr.indexOf(0x00A4) > 0) 67 ss.error(XSLTErrorResources.ER_CURRENCY_SIGN_ILLEGAL); // currency sign not allowed 68 69 // this third argument is not a locale name. It is the name of a 70 // decimal-format declared in the stylesheet!(xsl:decimal-format 71 try 72 { 73 Expression arg2Expr = getArg2(); 74 75 if (null != arg2Expr) 76 { 77 String dfName = arg2Expr.execute(xctxt).str(); 78 QName qname = new QName(dfName, xctxt.getNamespaceContext()); 79 80 dfs = ss.getDecimalFormatComposed(qname); 81 82 if (null == dfs) 83 { 84 warn(xctxt, XSLTErrorResources.WG_NO_DECIMALFORMAT_DECLARATION, 85 new Object[]{ dfName }); //"not found!!! 86 87 //formatter = new java.text.DecimalFormat(patternStr); 88 } 89 else 90 { 91 92 //formatter = new java.text.DecimalFormat(patternStr, dfs); 93 formatter = new java.text.DecimalFormat(); 94 95 formatter.setDecimalFormatSymbols(dfs); 96 formatter.applyLocalizedPattern(patternStr); 97 } 98 } 99 100 //else 101 if (null == formatter) 102 { 103 104 // look for a possible default decimal-format 105 dfs = ss.getDecimalFormatComposed(new QName("")); 106 107 if (dfs != null) 108 { 109 formatter = new java.text.DecimalFormat(); 110 111 formatter.setDecimalFormatSymbols(dfs); 112 formatter.applyLocalizedPattern(patternStr); 113 } 114 else 115 { 116 dfs = new java.text.DecimalFormatSymbols(java.util.Locale.US); 117 118 dfs.setInfinity(Constants.ATTRVAL_INFINITY); 119 dfs.setNaN(Constants.ATTRVAL_NAN); 120 121 formatter = new java.text.DecimalFormat(); 122 123 formatter.setDecimalFormatSymbols(dfs); 124 125 if (null != patternStr) 126 formatter.applyLocalizedPattern(patternStr); 127 } 128 } 129 130 return new XString(formatter.format(num)); 131 } 132 catch (Exception iae) 133 { 134 templElem.error(XSLTErrorResources.ER_MALFORMED_FORMAT_STRING, 135 new Object[]{ patternStr }); 136 137 return XString.EMPTYSTRING; 138 139 //throw new XSLProcessorException(iae); 140 } 141 } 142 143 /** 144 * Warn the user of a problem. 145 * 146 * @param xctxt The XPath runtime state. 147 * @param msg Warning message key 148 * @param args Arguments to be used in warning message 149 * @throws XSLProcessorException thrown if the active ProblemListener and XPathContext decide 150 * the error condition is severe enough to halt processing. 151 * 152 * @throws javax.xml.transform.TransformerException 153 */ warn(XPathContext xctxt, String msg, Object args[])154 public void warn(XPathContext xctxt, String msg, Object args[]) 155 throws javax.xml.transform.TransformerException 156 { 157 158 String formattedMsg = XSLMessages.createWarning(msg, args); 159 ErrorListener errHandler = xctxt.getErrorListener(); 160 161 errHandler.warning(new TransformerException(formattedMsg, 162 (SAXSourceLocator)xctxt.getSAXLocator())); 163 } 164 165 /** 166 * Overide the superclass method to allow one or two arguments. 167 * 168 * 169 * @param argNum Number of arguments passed in 170 * 171 * @throws WrongNumberArgsException 172 */ checkNumberArgs(int argNum)173 public void checkNumberArgs(int argNum) throws WrongNumberArgsException 174 { 175 if ((argNum > 3) || (argNum < 2)) 176 reportWrongNumberArgs(); 177 } 178 179 /** 180 * Constructs and throws a WrongNumberArgException with the appropriate 181 * message for this function object. 182 * 183 * @throws WrongNumberArgsException 184 */ reportWrongNumberArgs()185 protected void reportWrongNumberArgs() throws WrongNumberArgsException { 186 throw new WrongNumberArgsException(XSLMessages.createMessage(XSLTErrorResources.ER_TWO_OR_THREE, null)); //"2 or 3"); 187 } 188 } 189