View Javadoc
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 }