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: FormatNumberCall.java 468650 2006-10-28 07:03:30Z minchau $ 020 */ 021 022 package org.apache.xalan.xsltc.compiler; 023 024 import java.util.Vector; 025 026 import org.apache.bcel.generic.ConstantPoolGen; 027 import org.apache.bcel.generic.INVOKESTATIC; 028 import org.apache.bcel.generic.INVOKEVIRTUAL; 029 import org.apache.bcel.generic.InstructionList; 030 import org.apache.bcel.generic.PUSH; 031 import org.apache.xalan.xsltc.compiler.util.ClassGenerator; 032 import org.apache.xalan.xsltc.compiler.util.MethodGenerator; 033 import org.apache.xalan.xsltc.compiler.util.RealType; 034 import org.apache.xalan.xsltc.compiler.util.StringType; 035 import org.apache.xalan.xsltc.compiler.util.Type; 036 import org.apache.xalan.xsltc.compiler.util.TypeCheckError; 037 038 /** 039 * @author Jacek Ambroziak 040 * @author Santiago Pericas-Geertsen 041 * @author Morten Jorgensen 042 */ 043 final class FormatNumberCall extends FunctionCall { 044 private Expression _value; 045 private Expression _format; 046 private Expression _name; 047 private QName _resolvedQName = null; 048 049 public FormatNumberCall(QName fname, Vector arguments) { 050 super(fname, arguments); 051 _value = argument(0); 052 _format = argument(1); 053 _name = argumentCount() == 3 ? argument(2) : null; 054 } 055 056 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 057 058 // Inform stylesheet to instantiate a DecimalFormat object 059 getStylesheet().numberFormattingUsed(); 060 061 final Type tvalue = _value.typeCheck(stable); 062 if (tvalue instanceof RealType == false) { 063 _value = new CastExpr(_value, Type.Real); 064 } 065 final Type tformat = _format.typeCheck(stable); 066 if (tformat instanceof StringType == false) { 067 _format = new CastExpr(_format, Type.String); 068 } 069 if (argumentCount() == 3) { 070 final Type tname = _name.typeCheck(stable); 071 072 if (_name instanceof LiteralExpr) { 073 final LiteralExpr literal = (LiteralExpr) _name; 074 _resolvedQName = 075 getParser().getQNameIgnoreDefaultNs(literal.getValue()); 076 } 077 else if (tname instanceof StringType == false) { 078 _name = new CastExpr(_name, Type.String); 079 } 080 } 081 return _type = Type.String; 082 } 083 084 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 085 final ConstantPoolGen cpg = classGen.getConstantPool(); 086 final InstructionList il = methodGen.getInstructionList(); 087 088 _value.translate(classGen, methodGen); 089 _format.translate(classGen, methodGen); 090 091 final int fn3arg = cpg.addMethodref(BASIS_LIBRARY_CLASS, 092 "formatNumber", 093 "(DLjava/lang/String;"+ 094 "Ljava/text/DecimalFormat;)"+ 095 "Ljava/lang/String;"); 096 final int get = cpg.addMethodref(TRANSLET_CLASS, 097 "getDecimalFormat", 098 "(Ljava/lang/String;)"+ 099 "Ljava/text/DecimalFormat;"); 100 101 il.append(classGen.loadTranslet()); 102 if (_name == null) { 103 il.append(new PUSH(cpg, EMPTYSTRING)); 104 } 105 else if (_resolvedQName != null) { 106 il.append(new PUSH(cpg, _resolvedQName.toString())); 107 } 108 else { 109 _name.translate(classGen, methodGen); 110 } 111 il.append(new INVOKEVIRTUAL(get)); 112 il.append(new INVOKESTATIC(fn3arg)); 113 } 114 }