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 }