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