1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 * @LastModified: Oct 2017 4 */ 5 /* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22 package com.sun.org.apache.xalan.internal.xsltc.compiler; 23 24 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; 25 import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC; 26 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; 27 import com.sun.org.apache.bcel.internal.generic.InstructionList; 28 import com.sun.org.apache.bcel.internal.generic.PUSH; 29 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; 30 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; 31 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.RealType; 32 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.StringType; 33 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; 34 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; 35 import java.util.List; 36 37 /** 38 * @author Jacek Ambroziak 39 * @author Santiago Pericas-Geertsen 40 * @author Morten Jorgensen 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 }