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.InstructionList;
26 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
27 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
28 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
29 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
30 import java.util.List;
31 
32 /**
33  * @author Morten Jorgensen
34  * @author Erwin Bolwidt <ejb@klomp.org>
35  * @LastModified: Oct 2017
36  */
37 class NameBase extends FunctionCall {
38 
39     private Expression _param = null;
40     private Type       _paramType = Type.Node;
41 
42     /**
43      * Handles calls with no parameter (current node is implicit parameter).
44      */
NameBase(QName fname)45     public NameBase(QName fname) {
46         super(fname);
47     }
48 
49     /**
50      * Handles calls with one parameter (either node or node-set).
51      */
NameBase(QName fname, List<Expression> arguments)52     public NameBase(QName fname, List<Expression> arguments) {
53         super(fname, arguments);
54         _param = argument(0);
55     }
56 
57 
58     /**
59      * Check that we either have no parameters or one parameter that is
60      * either a node or a node-set.
61      */
typeCheck(SymbolTable stable)62     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
63 
64         // Check the argument type (if any)
65         switch(argumentCount()) {
66         case 0:
67             _paramType = Type.Node;
68             break;
69         case 1:
70             _paramType = _param.typeCheck(stable);
71             break;
72         default:
73             throw new TypeCheckError(this);
74         }
75 
76         // The argument has to be a node, a node-set or a node reference
77         if ((_paramType != Type.NodeSet) &&
78             (_paramType != Type.Node) &&
79             (_paramType != Type.Reference)) {
80             throw new TypeCheckError(this);
81         }
82 
83         return (_type = Type.String);
84     }
85 
getType()86     public Type getType() {
87         return _type;
88     }
89 
90     /**
91      * Translate the code required for getting the node for which the
92      * QName, local-name or namespace URI should be extracted.
93      */
translate(ClassGenerator classGen, MethodGenerator methodGen)94     public void translate(ClassGenerator classGen,
95                           MethodGenerator methodGen) {
96         final ConstantPoolGen cpg = classGen.getConstantPool();
97         final InstructionList il = methodGen.getInstructionList();
98 
99         il.append(methodGen.loadDOM());
100 
101         // Function was called with no parameters
102         if (argumentCount() == 0) {
103             il.append(methodGen.loadContextNode());
104         }
105         // Function was called with node parameter
106         else if (_paramType == Type.Node) {
107             _param.translate(classGen, methodGen);
108         }
109         else if (_paramType == Type.Reference) {
110             _param.translate(classGen, methodGen);
111             il.append(new INVOKESTATIC(cpg.addMethodref
112                                        (BASIS_LIBRARY_CLASS,
113                                         "referenceToNodeSet",
114                                         "("
115                                         + OBJECT_SIG
116                                         + ")"
117                                         + NODE_ITERATOR_SIG)));
118             il.append(methodGen.nextNode());
119         }
120         // Function was called with node-set parameter
121         else {
122             _param.translate(classGen, methodGen);
123             _param.startIterator(classGen, methodGen);
124             il.append(methodGen.nextNode());
125         }
126     }
127 }
128