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: FilterParentPath.java,v 1.13 2004/02/16 22:24:29 minchau Exp $
  18. */
  19. package com.sun.org.apache.xalan.internal.xsltc.compiler;
  20. import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
  21. import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
  22. import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL;
  23. import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
  24. import com.sun.org.apache.bcel.internal.generic.InstructionList;
  25. import com.sun.org.apache.bcel.internal.generic.NEW;
  26. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
  27. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
  28. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.NodeSetType;
  29. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.NodeType;
  30. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ReferenceType;
  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. /**
  34. * @author Jacek Ambroziak
  35. * @author Santiago Pericas-Geertsen
  36. */
  37. final class FilterParentPath extends Expression {
  38. private Expression _filterExpr;
  39. private Expression _path;
  40. private boolean _hasDescendantAxis = false;
  41. public FilterParentPath(Expression filterExpr, Expression path) {
  42. (_path = path).setParent(this);
  43. (_filterExpr = filterExpr).setParent(this);
  44. }
  45. public void setParser(Parser parser) {
  46. super.setParser(parser);
  47. _filterExpr.setParser(parser);
  48. _path.setParser(parser);
  49. }
  50. public String toString() {
  51. return "FilterParentPath(" + _filterExpr + ", " + _path + ')';
  52. }
  53. public void setDescendantAxis() {
  54. _hasDescendantAxis = true;
  55. }
  56. /**
  57. * Type check a FilterParentPath. If the filter is not a node-set add a
  58. * cast to node-set only if it is of reference type. This type coercion is
  59. * needed for expressions like $x/LINE where $x is a parameter reference.
  60. */
  61. public Type typeCheck(SymbolTable stable) throws TypeCheckError {
  62. final Type ftype = _filterExpr.typeCheck(stable);
  63. if (ftype instanceof NodeSetType == false) {
  64. if (ftype instanceof ReferenceType) {
  65. _filterExpr = new CastExpr(_filterExpr, Type.NodeSet);
  66. }
  67. /*
  68. else if (ftype instanceof ResultTreeType) {
  69. _filterExpr = new CastExpr(_filterExpr, Type.NodeSet);
  70. }
  71. */
  72. else if (ftype instanceof NodeType) {
  73. _filterExpr = new CastExpr(_filterExpr, Type.NodeSet);
  74. }
  75. else {
  76. throw new TypeCheckError(this);
  77. }
  78. }
  79. // Wrap single node path in a node set
  80. final Type ptype = _path.typeCheck(stable);
  81. if (!(ptype instanceof NodeSetType)) {
  82. _path = new CastExpr(_path, Type.NodeSet);
  83. }
  84. return _type = Type.NodeSet;
  85. }
  86. public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
  87. final ConstantPoolGen cpg = classGen.getConstantPool();
  88. final InstructionList il = methodGen.getInstructionList();
  89. // Create new StepIterator
  90. final int initSI = cpg.addMethodref(STEP_ITERATOR_CLASS,
  91. "<init>",
  92. "("
  93. +NODE_ITERATOR_SIG
  94. +NODE_ITERATOR_SIG
  95. +")V");
  96. il.append(new NEW(cpg.addClass(STEP_ITERATOR_CLASS)));
  97. il.append(DUP);
  98. // Recursively compile 2 iterators
  99. _filterExpr.translate(classGen, methodGen);
  100. _path.translate(classGen, methodGen);
  101. // Initialize StepIterator with iterators from the stack
  102. il.append(new INVOKESPECIAL(initSI));
  103. // This is a special case for the //* path with or without predicates
  104. if (_hasDescendantAxis) {
  105. final int incl = cpg.addMethodref(NODE_ITERATOR_BASE,
  106. "includeSelf",
  107. "()" + NODE_ITERATOR_SIG);
  108. il.append(new INVOKEVIRTUAL(incl));
  109. }
  110. if (!(getParent() instanceof RelativeLocationPath) &&
  111. !(getParent() instanceof FilterParentPath)) {
  112. final int order = cpg.addInterfaceMethodref(DOM_INTF,
  113. ORDER_ITERATOR,
  114. ORDER_ITERATOR_SIG);
  115. il.append(methodGen.loadDOM());
  116. il.append(SWAP);
  117. il.append(methodGen.loadContextNode());
  118. il.append(new INVOKEINTERFACE(order, 3));
  119. }
  120. }
  121. }