1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 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 java.util.Vector; 25 26 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; 27 import com.sun.org.apache.bcel.internal.generic.GETFIELD; 28 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; 29 import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC; 30 import com.sun.org.apache.bcel.internal.generic.InstructionList; 31 import com.sun.org.apache.bcel.internal.generic.PUSH; 32 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; 33 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; 34 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; 35 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; 36 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; 37 38 /** 39 * @author Jacek Ambroziak 40 * @author Morten Jorgensen 41 */ 42 final class DocumentCall extends FunctionCall { 43 44 private Expression _arg1 = null; 45 private Expression _arg2 = null; 46 private Type _arg1Type; 47 48 /** 49 * Default function call constructor 50 */ 51 public DocumentCall(QName fname, Vector arguments) { 52 super(fname, arguments); 53 } 54 55 /** 56 * Type checks the arguments passed to the document() function. The first 57 * argument can be any type (we must cast it to a string) and contains the 58 * URI of the document 59 */ 60 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 61 // At least one argument - two at most 62 final int ac = argumentCount(); 63 if ((ac < 1) || (ac > 2)) { 64 ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ARG_ERR, this); 65 throw new TypeCheckError(msg); 66 } 67 if (getStylesheet() == null) { 68 ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ARG_ERR, this); 69 throw new TypeCheckError(msg); 70 } 71 72 // Parse the first argument 73 _arg1 = argument(0); 74 75 if (_arg1 == null) {// should not happened 76 ErrorMsg msg = new ErrorMsg(ErrorMsg.DOCUMENT_ARG_ERR, this); 77 throw new TypeCheckError(msg); 78 } 79 80 _arg1Type = _arg1.typeCheck(stable); 81 if ((_arg1Type != Type.NodeSet) && (_arg1Type != Type.String)) { 82 _arg1 = new CastExpr(_arg1, Type.String); 83 } 84 85 // Parse the second argument 86 if (ac == 2) { 87 _arg2 = argument(1); 88 89 if (_arg2 == null) {// should not happened 90 ErrorMsg msg = new ErrorMsg(ErrorMsg.DOCUMENT_ARG_ERR, this); 91 throw new TypeCheckError(msg); 92 } 93 94 final Type arg2Type = _arg2.typeCheck(stable); 95 96 if (arg2Type.identicalTo(Type.Node)) { 97 _arg2 = new CastExpr(_arg2, Type.NodeSet); 98 } else if (arg2Type.identicalTo(Type.NodeSet)) { 99 // falls through 100 } else { 101 ErrorMsg msg = new ErrorMsg(ErrorMsg.DOCUMENT_ARG_ERR, this); 102 throw new TypeCheckError(msg); 103 } 104 } 105 106 return _type = Type.NodeSet; 107 } 108 109 /** 110 * Translates the document() function call to a call to LoadDocument()'s 111 * static method document(). 112 */ 113 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 114 final ConstantPoolGen cpg = classGen.getConstantPool(); 115 final InstructionList il = methodGen.getInstructionList(); 116 final int ac = argumentCount(); 117 118 final int domField = cpg.addFieldref(classGen.getClassName(), 119 DOM_FIELD, 120 DOM_INTF_SIG); 121 122 String docParamList = null; 123 if (ac == 1) { 124 // documentF(Object,String,AbstractTranslet,DOM) 125 docParamList = "("+OBJECT_SIG+STRING_SIG+TRANSLET_SIG+DOM_INTF_SIG 126 +")"+NODE_ITERATOR_SIG; 127 } else { //ac == 2; ac < 1 or as >2 was tested in typeChec() 128 // documentF(Object,DTMAxisIterator,String,AbstractTranslet,DOM) 129 docParamList = "("+OBJECT_SIG+NODE_ITERATOR_SIG+STRING_SIG 130 +TRANSLET_SIG+DOM_INTF_SIG+")"+NODE_ITERATOR_SIG; 131 } 132 final int docIdx = cpg.addMethodref(LOAD_DOCUMENT_CLASS, "documentF", 133 docParamList); 134 135 136 // The URI can be either a node-set or something else cast to a string 137 _arg1.translate(classGen, methodGen); 138 if (_arg1Type == Type.NodeSet) { 139 _arg1.startIterator(classGen, methodGen); 140 } 141 142 if (ac == 2) { 143 //_arg2 == null was tested in typeChec() 144 _arg2.translate(classGen, methodGen); 145 _arg2.startIterator(classGen, methodGen); 146 } 147 148 // Feck the rest of the parameters on the stack 149 il.append(new PUSH(cpg, getStylesheet().getSystemId())); 150 il.append(classGen.loadTranslet()); 151 il.append(DUP); 152 il.append(new GETFIELD(domField)); 153 il.append(new INVOKESTATIC(docIdx)); 154 } 155 156 }