001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 /* 019 * $Id: FuncFormatNumb.java 468643 2006-10-28 06:56:03Z minchau $ 020 */ 021 package org.apache.xalan.templates; 022 023 import javax.xml.transform.ErrorListener; 024 import javax.xml.transform.TransformerException; 025 026 import org.apache.xalan.res.XSLMessages; 027 import org.apache.xalan.res.XSLTErrorResources; 028 import org.apache.xml.utils.QName; 029 import org.apache.xml.utils.SAXSourceLocator; 030 import org.apache.xpath.Expression; 031 import org.apache.xpath.XPathContext; 032 import org.apache.xpath.functions.Function3Args; 033 import org.apache.xpath.functions.WrongNumberArgsException; 034 import org.apache.xpath.objects.XObject; 035 import org.apache.xpath.objects.XString; 036 037 /** 038 * Execute the FormatNumber() function. 039 * @xsl.usage advanced 040 */ 041 public class FuncFormatNumb extends Function3Args 042 { 043 static final long serialVersionUID = -8869935264870858636L; 044 045 /** 046 * Execute the function. The function must return 047 * a valid object. 048 * @param xctxt The current execution context. 049 * @return A valid XObject. 050 * 051 * @throws javax.xml.transform.TransformerException 052 */ 053 public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException 054 { 055 056 // A bit of an ugly hack to get our context. 057 ElemTemplateElement templElem = 058 (ElemTemplateElement) xctxt.getNamespaceContext(); 059 StylesheetRoot ss = templElem.getStylesheetRoot(); 060 java.text.DecimalFormat formatter = null; 061 java.text.DecimalFormatSymbols dfs = null; 062 double num = getArg0().execute(xctxt).num(); 063 String patternStr = getArg1().execute(xctxt).str(); 064 065 // TODO: what should be the behavior here?? 066 if (patternStr.indexOf(0x00A4) > 0) 067 ss.error(XSLTErrorResources.ER_CURRENCY_SIGN_ILLEGAL); // currency sign not allowed 068 069 // this third argument is not a locale name. It is the name of a 070 // decimal-format declared in the stylesheet!(xsl:decimal-format 071 try 072 { 073 Expression arg2Expr = getArg2(); 074 075 if (null != arg2Expr) 076 { 077 String dfName = arg2Expr.execute(xctxt).str(); 078 QName qname = new QName(dfName, xctxt.getNamespaceContext()); 079 080 dfs = ss.getDecimalFormatComposed(qname); 081 082 if (null == dfs) 083 { 084 warn(xctxt, XSLTErrorResources.WG_NO_DECIMALFORMAT_DECLARATION, 085 new Object[]{ dfName }); //"not found!!! 086 087 //formatter = new java.text.DecimalFormat(patternStr); 088 } 089 else 090 { 091 092 //formatter = new java.text.DecimalFormat(patternStr, dfs); 093 formatter = new java.text.DecimalFormat(); 094 095 formatter.setDecimalFormatSymbols(dfs); 096 formatter.applyLocalizedPattern(patternStr); 097 } 098 } 099 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 */ 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 */ 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 */ 185 protected void reportWrongNumberArgs() throws WrongNumberArgsException { 186 throw new WrongNumberArgsException(XSLMessages.createMessage(XSLTErrorResources.ER_TWO_OR_THREE, null)); //"2 or 3"); 187 } 188 }