1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 */ 4 /* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 package com.sun.org.apache.xalan.internal.xsltc.compiler; 22 23 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; 24 import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC; 25 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; 26 import com.sun.org.apache.bcel.internal.generic.InstructionList; 27 import com.sun.org.apache.bcel.internal.generic.PUSH; 28 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; 29 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; 30 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.RealType; 31 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.StringType; 32 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; 33 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; 34 import java.util.List; 35 36 /** 37 * @author Jacek Ambroziak 38 * @author Santiago Pericas-Geertsen 39 * @author Morten Jorgensen 40 * @LastModified: Oct 2017 41 */ 42 final class FormatNumberCall extends FunctionCall { 43 private Expression _value; 44 private Expression _format; 45 private Expression _name; 46 private QName _resolvedQName = null; 47 48 public FormatNumberCall(QName fname, List<Expression> arguments) { 49 super(fname, arguments); 50 _value = argument(0); 51 _format = argument(1); 52 _name = argumentCount() == 3 ? argument(2) : null; 53 } 54 55 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 56 57 // Inform stylesheet to instantiate a DecimalFormat object 58 getStylesheet().numberFormattingUsed(); 59 60 final Type tvalue = _value.typeCheck(stable); 61 if (tvalue instanceof RealType == false) { 62 _value = new CastExpr(_value, Type.Real); 63 } 64 final Type tformat = _format.typeCheck(stable); 65 if (tformat instanceof StringType == false) { 66 _format = new CastExpr(_format, Type.String); 67 } 68 if (argumentCount() == 3) { 69 final Type tname = _name.typeCheck(stable); 70 71 if (_name instanceof LiteralExpr) { 72 final LiteralExpr literal = (LiteralExpr) _name; 73 _resolvedQName = 74 getParser().getQNameIgnoreDefaultNs(literal.getValue()); 75 } 76 else if (tname instanceof StringType == false) { 77 _name = new CastExpr(_name, Type.String); 78 } 79 } 80 return _type = Type.String; 81 } 82 83 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 84 final ConstantPoolGen cpg = classGen.getConstantPool(); 85 final InstructionList il = methodGen.getInstructionList(); 86 87 _value.translate(classGen, methodGen); 88 _format.translate(classGen, methodGen); 89 90 final int fn3arg = cpg.addMethodref(BASIS_LIBRARY_CLASS, 91 "formatNumber", 92 "(DLjava/lang/String;"+ 93 "Ljava/text/DecimalFormat;)"+ 94 "Ljava/lang/String;"); 95 final int get = cpg.addMethodref(TRANSLET_CLASS, 96 "getDecimalFormat", 97 "(Ljava/lang/String;)"+ 98 "Ljava/text/DecimalFormat;"); 99 100 il.append(classGen.loadTranslet()); 101 if (_name == null) { 102 il.append(new PUSH(cpg, EMPTYSTRING)); 103 } 104 else if (_resolvedQName != null) { 105 il.append(new PUSH(cpg, _resolvedQName.toString())); 106 } 107 else { 108 _name.translate(classGen, methodGen); 109 } 110 il.append(new INVOKEVIRTUAL(get)); 111 il.append(new INVOKESTATIC(fn3arg)); 112 } 113 }