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: DocumentCall.java 1225842 2011-12-30 15:14:35Z mrglavas $ 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.GETFIELD; 028 import org.apache.bcel.generic.INVOKESTATIC; 029 import org.apache.bcel.generic.InstructionList; 030 import org.apache.bcel.generic.PUSH; 031 import org.apache.xalan.xsltc.compiler.util.ClassGenerator; 032 import org.apache.xalan.xsltc.compiler.util.ErrorMsg; 033 import org.apache.xalan.xsltc.compiler.util.MethodGenerator; 034 import org.apache.xalan.xsltc.compiler.util.Type; 035 import org.apache.xalan.xsltc.compiler.util.TypeCheckError; 036 037 /** 038 * @author Jacek Ambroziak 039 * @author Morten Jorgensen 040 */ 041 final class DocumentCall extends FunctionCall { 042 043 private Expression _arg1 = null; 044 private Expression _arg2 = null; 045 private Type _arg1Type; 046 047 /** 048 * Default function call constructor 049 */ 050 public DocumentCall(QName fname, Vector arguments) { 051 super(fname, arguments); 052 } 053 054 /** 055 * Type checks the arguments passed to the document() function. The first 056 * argument can be any type (we must cast it to a string) and contains the 057 * URI of the document 058 */ 059 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 060 // At least one argument - two at most 061 final int ac = argumentCount(); 062 if ((ac < 1) || (ac > 2)) { 063 ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ARG_ERR, this); 064 throw new TypeCheckError(msg); 065 } 066 if (getStylesheet() == null) { 067 ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ARG_ERR, this); 068 throw new TypeCheckError(msg); 069 } 070 071 // Parse the first argument 072 _arg1 = argument(0); 073 074 if (_arg1 == null) {// should not happened 075 ErrorMsg msg = new ErrorMsg(ErrorMsg.DOCUMENT_ARG_ERR, this); 076 throw new TypeCheckError(msg); 077 } 078 079 _arg1Type = _arg1.typeCheck(stable); 080 if ((_arg1Type != Type.NodeSet) && (_arg1Type != Type.String)) { 081 _arg1 = new CastExpr(_arg1, Type.String); 082 } 083 084 // Parse the second argument 085 if (ac == 2) { 086 _arg2 = argument(1); 087 088 if (_arg2 == null) {// should not happened 089 ErrorMsg msg = new ErrorMsg(ErrorMsg.DOCUMENT_ARG_ERR, this); 090 throw new TypeCheckError(msg); 091 } 092 093 final Type arg2Type = _arg2.typeCheck(stable); 094 095 if (arg2Type.identicalTo(Type.Node)) { 096 _arg2 = new CastExpr(_arg2, Type.NodeSet); 097 } else if (arg2Type.identicalTo(Type.NodeSet)) { 098 // falls through 099 } else { 100 ErrorMsg msg = new ErrorMsg(ErrorMsg.DOCUMENT_ARG_ERR, this); 101 throw new TypeCheckError(msg); 102 } 103 } 104 105 return _type = Type.NodeSet; 106 } 107 108 /** 109 * Translates the document() function call to a call to LoadDocument()'s 110 * static method document(). 111 */ 112 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 113 final ConstantPoolGen cpg = classGen.getConstantPool(); 114 final InstructionList il = methodGen.getInstructionList(); 115 final int ac = argumentCount(); 116 117 final int domField = cpg.addFieldref(classGen.getClassName(), 118 DOM_FIELD, 119 DOM_INTF_SIG); 120 121 String docParamList = null; 122 if (ac == 1) { 123 // documentF(Object,String,AbstractTranslet,DOM) 124 docParamList = "("+OBJECT_SIG+STRING_SIG+TRANSLET_SIG+DOM_INTF_SIG 125 +")"+NODE_ITERATOR_SIG; 126 } else { //ac == 2; ac < 1 or as >2 was tested in typeChec() 127 // documentF(Object,DTMAxisIterator,String,AbstractTranslet,DOM) 128 docParamList = "("+OBJECT_SIG+NODE_ITERATOR_SIG+STRING_SIG 129 +TRANSLET_SIG+DOM_INTF_SIG+")"+NODE_ITERATOR_SIG; 130 } 131 final int docIdx = cpg.addMethodref(LOAD_DOCUMENT_CLASS, "documentF", 132 docParamList); 133 134 135 // The URI can be either a node-set or something else cast to a string 136 _arg1.translate(classGen, methodGen); 137 if (_arg1Type == Type.NodeSet) { 138 _arg1.startIterator(classGen, methodGen); 139 } 140 141 if (ac == 2) { 142 //_arg2 == null was tested in typeChec() 143 _arg2.translate(classGen, methodGen); 144 _arg2.startIterator(classGen, methodGen); 145 } 146 147 // Process the rest of the parameters on the stack 148 il.append(new PUSH(cpg, getStylesheet().getSystemId())); 149 il.append(classGen.loadTranslet()); 150 il.append(DUP); 151 il.append(new GETFIELD(domField)); 152 il.append(new INVOKESTATIC(docIdx)); 153 } 154 155 }