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.InstructionList;
  27 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
  28 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
  29 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
  30 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
  31 import java.util.List;
  32 
  33 /**
  34  * @author Morten Jorgensen
  35  * @author Erwin Bolwidt <ejb@klomp.org>
  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      */
  45     public NameBase(QName fname) {
  46         super(fname);
  47     }
  48 
  49     /**
  50      * Handles calls with one parameter (either node or node-set).
  51      */
  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      */
  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 
  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      */
  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 }