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