1. /*
  2. * Copyright 2001-2004 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. * $Id: DocumentCall.java,v 1.19 2004/02/16 22:24:29 minchau Exp $
  18. */
  19. package com.sun.org.apache.xalan.internal.xsltc.compiler;
  20. import java.util.Vector;
  21. import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
  22. import com.sun.org.apache.bcel.internal.generic.GETFIELD;
  23. import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
  24. import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC;
  25. import com.sun.org.apache.bcel.internal.generic.InstructionList;
  26. import com.sun.org.apache.bcel.internal.generic.PUSH;
  27. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
  28. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
  29. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
  30. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
  31. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
  32. /**
  33. * @author Jacek Ambroziak
  34. * @author Morten Jorgensen
  35. */
  36. final class DocumentCall extends FunctionCall {
  37. private Expression _arg1 = null;
  38. private Expression _arg2 = null;
  39. private Type _arg1Type;
  40. /**
  41. * Default function call constructor
  42. */
  43. public DocumentCall(QName fname, Vector arguments) {
  44. super(fname, arguments);
  45. }
  46. /**
  47. * Type checks the arguments passed to the document() function. The first
  48. * argument can be any type (we must cast it to a string) and contains the
  49. * URI of the document
  50. */
  51. public Type typeCheck(SymbolTable stable) throws TypeCheckError {
  52. // At least one argument - two at most
  53. final int ac = argumentCount();
  54. if ((ac < 1) || (ac > 2)) {
  55. ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ARG_ERR, this);
  56. throw new TypeCheckError(msg);
  57. }
  58. if (getStylesheet() == null) {
  59. ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ARG_ERR, this);
  60. throw new TypeCheckError(msg);
  61. }
  62. // Parse the first argument
  63. _arg1 = argument(0);
  64. if (_arg1 == null) {// should not happened
  65. ErrorMsg msg = new ErrorMsg(ErrorMsg.DOCUMENT_ARG_ERR, this);
  66. throw new TypeCheckError(msg);
  67. }
  68. _arg1Type = _arg1.typeCheck(stable);
  69. if ((_arg1Type != Type.NodeSet) && (_arg1Type != Type.String)) {
  70. _arg1 = new CastExpr(_arg1, Type.String);
  71. }
  72. // Parse the second argument
  73. if (ac == 2) {
  74. _arg2 = argument(1);
  75. if (_arg2 == null) {// should not happened
  76. ErrorMsg msg = new ErrorMsg(ErrorMsg.DOCUMENT_ARG_ERR, this);
  77. throw new TypeCheckError(msg);
  78. }
  79. final Type arg2Type = _arg2.typeCheck(stable);
  80. if (arg2Type.identicalTo(Type.Node)) {
  81. _arg2 = new CastExpr(_arg2, Type.NodeSet);
  82. } else if (arg2Type.identicalTo(Type.NodeSet)) {
  83. // falls through
  84. } else {
  85. ErrorMsg msg = new ErrorMsg(ErrorMsg.DOCUMENT_ARG_ERR, this);
  86. throw new TypeCheckError(msg);
  87. }
  88. }
  89. return _type = Type.NodeSet;
  90. }
  91. /**
  92. * Translates the document() function call to a call to LoadDocument()'s
  93. * static method document().
  94. */
  95. public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
  96. final ConstantPoolGen cpg = classGen.getConstantPool();
  97. final InstructionList il = methodGen.getInstructionList();
  98. final int ac = argumentCount();
  99. final int domField = cpg.addFieldref(classGen.getClassName(),
  100. DOM_FIELD,
  101. DOM_INTF_SIG);
  102. String docParamList = null;
  103. if (ac == 1) {
  104. // documentF(Object,String,AbstractTranslet,DOM)
  105. docParamList = "("+OBJECT_SIG+STRING_SIG+TRANSLET_SIG+DOM_INTF_SIG
  106. +")"+NODE_ITERATOR_SIG;
  107. } else { //ac == 2; ac < 1 or as >2 was tested in typeChec()
  108. // documentF(Object,DTMAxisIterator,String,AbstractTranslet,DOM)
  109. docParamList = "("+OBJECT_SIG+NODE_ITERATOR_SIG+STRING_SIG
  110. +TRANSLET_SIG+DOM_INTF_SIG+")"+NODE_ITERATOR_SIG;
  111. }
  112. final int docIdx = cpg.addMethodref(LOAD_DOCUMENT_CLASS, "documentF",
  113. docParamList);
  114. // The URI can be either a node-set or something else cast to a string
  115. _arg1.translate(classGen, methodGen);
  116. if (_arg1Type == Type.NodeSet) {
  117. _arg1.startIterator(classGen, methodGen);
  118. }
  119. if (ac == 2) {
  120. //_arg2 == null was tested in typeChec()
  121. _arg2.translate(classGen, methodGen);
  122. _arg2.startIterator(classGen, methodGen);
  123. }
  124. // Feck the rest of the parameters on the stack
  125. il.append(new PUSH(cpg, getStylesheet().getSystemId()));
  126. il.append(classGen.loadTranslet());
  127. il.append(DUP);
  128. il.append(new GETFIELD(domField));
  129. il.append(new INVOKESTATIC(docIdx));
  130. }
  131. }