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: CastCall.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.CHECKCAST;
028    import org.apache.bcel.generic.InstructionList;
029    import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
030    import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
031    import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
032    import org.apache.xalan.xsltc.compiler.util.Type;
033    import org.apache.xalan.xsltc.compiler.util.ObjectType;
034    import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
035    
036    /**
037     * @author Santiago Pericas-Geertsen
038     */
039    final class CastCall extends FunctionCall {
040        
041        /**
042         * Name of the class that is the target of the cast. Must be a 
043         * fully-qualified Java class Name.
044         */
045        private String _className;
046    
047        /**
048         * A reference to the expression being casted.
049         */
050        private Expression _right;
051    
052        /**
053         * Constructor.
054         */
055        public CastCall(QName fname, Vector arguments) {
056            super(fname, arguments);
057        }
058    
059        /**
060         * Type check the two parameters for this function
061         */
062        public Type typeCheck(SymbolTable stable) throws TypeCheckError {
063            // Check that the function was passed exactly two arguments
064            if (argumentCount() != 2) {
065                throw new TypeCheckError(new ErrorMsg(ErrorMsg.ILLEGAL_ARG_ERR,
066                                                      getName(), this));
067            }
068    
069            // The first argument must be a literal String
070            Expression exp = argument(0);
071            if (exp instanceof LiteralExpr) {
072                _className = ((LiteralExpr) exp).getValue();
073                _type = Type.newObjectType(_className);
074            }
075            else {
076                throw new TypeCheckError(new ErrorMsg(ErrorMsg.NEED_LITERAL_ERR,
077                                                      getName(), this));
078            }
079            
080             // Second argument must be of type reference or object
081            _right = argument(1);
082            Type tright = _right.typeCheck(stable);
083            if (tright != Type.Reference && 
084                tright instanceof ObjectType == false) 
085            {
086                throw new TypeCheckError(new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
087                                                      tright, _type, this));
088            }
089            
090            return _type;
091        }
092        
093        public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
094            final ConstantPoolGen cpg = classGen.getConstantPool();
095            final InstructionList il = methodGen.getInstructionList();
096    
097            _right.translate(classGen, methodGen);
098            il.append(new CHECKCAST(cpg.addClass(_className)));
099        }
100    }