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: NameBase.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.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.Type;
032    import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
033    
034    /**
035     * @author Morten Jorgensen
036     * @author Erwin Bolwidt <ejb@klomp.org>
037     */
038    class NameBase extends FunctionCall {
039    
040        private Expression _param = null;
041        private Type       _paramType = Type.Node;
042    
043        /**
044         * Handles calls with no parameter (current node is implicit parameter).
045         */
046        public NameBase(QName fname) {
047            super(fname);
048        }
049    
050        /**
051         * Handles calls with one parameter (either node or node-set).
052         */
053        public NameBase(QName fname, Vector arguments) {
054            super(fname, arguments);
055            _param = argument(0);
056        }
057    
058    
059        /**
060         * Check that we either have no parameters or one parameter that is
061         * either a node or a node-set.
062         */
063        public Type typeCheck(SymbolTable stable) throws TypeCheckError {
064    
065            // Check the argument type (if any)
066            switch(argumentCount()) {
067            case 0:
068                _paramType = Type.Node;
069                break;
070            case 1:
071                _paramType = _param.typeCheck(stable);
072                break;
073            default:
074                throw new TypeCheckError(this);
075            }
076    
077            // The argument has to be a node, a node-set or a node reference
078            if ((_paramType != Type.NodeSet) &&
079                (_paramType != Type.Node) &&
080                (_paramType != Type.Reference)) {
081                throw new TypeCheckError(this);
082            }
083    
084            return (_type = Type.String);
085        }
086    
087        public Type getType() {
088            return _type;
089        }
090    
091        /**
092         * Translate the code required for getting the node for which the
093         * QName, local-name or namespace URI should be extracted.
094         */
095        public void translate(ClassGenerator classGen,
096                              MethodGenerator methodGen) {
097            final ConstantPoolGen cpg = classGen.getConstantPool();
098            final InstructionList il = methodGen.getInstructionList();
099    
100            il.append(methodGen.loadDOM());
101            
102            // Function was called with no parameters
103            if (argumentCount() == 0) {
104                il.append(methodGen.loadContextNode());
105            }
106            // Function was called with node parameter
107            else if (_paramType == Type.Node) {
108                _param.translate(classGen, methodGen);
109            }
110            else if (_paramType == Type.Reference) {
111                _param.translate(classGen, methodGen);
112                il.append(new INVOKESTATIC(cpg.addMethodref
113                                           (BASIS_LIBRARY_CLASS,
114                                            "referenceToNodeSet",
115                                            "("
116                                            + OBJECT_SIG
117                                            + ")"
118                                            + NODE_ITERATOR_SIG)));
119                il.append(methodGen.nextNode());
120            }
121            // Function was called with node-set parameter
122            else {
123                _param.translate(classGen, methodGen);
124                _param.startIterator(classGen, methodGen);
125                il.append(methodGen.nextNode());
126            }
127        }
128    }