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: UnionPathExpr.java,v 1.2.4.1 2005/09/12 11:34:14 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.INVOKEINTERFACE; 30 import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL; 31 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; 32 import com.sun.org.apache.bcel.internal.generic.InstructionList; 33 import com.sun.org.apache.bcel.internal.generic.NEW; 34 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; 35 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; 36 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; 37 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; 38 import com.sun.org.apache.xml.internal.dtm.Axis; 39 import com.sun.org.apache.xml.internal.dtm.DTM; 40 41 /** 42 * @author Jacek Ambroziak 43 * @author Santiago Pericas-Geertsen 44 */ 45 final class UnionPathExpr extends Expression { 46 47 private final Expression _pathExpr; 48 private final Expression _rest; 49 private boolean _reverse = false; 50 51 // linearization for top level UnionPathExprs 52 private Expression[] _components; 53 54 public UnionPathExpr(Expression pathExpr, Expression rest) { 55 _pathExpr = pathExpr; 56 _rest = rest; 57 } 58 59 public void setParser(Parser parser) { 60 super.setParser(parser); 61 // find all expressions in this Union 62 final Vector components = new Vector(); 63 flatten(components); 64 final int size = components.size(); 65 _components = (Expression[])components.toArray(new Expression[size]); 66 for (int i = 0; i < size; i++) { 67 _components[i].setParser(parser); 68 _components[i].setParent(this); 69 if (_components[i] instanceof Step) { 70 final Step step = (Step)_components[i]; 71 final int axis = step.getAxis(); 72 final int type = step.getNodeType(); 73 // Put attribute iterators first 74 if ((axis == Axis.ATTRIBUTE) || (type == DTM.ATTRIBUTE_NODE)) { 75 _components[i] = _components[0]; 76 _components[0] = step; 77 } 78 // Check if the union contains a reverse iterator 79 if (Axis.isReverse(axis)) _reverse = true; 80 } 81 } 82 // No need to reverse anything if another expression lies on top of this 83 if (getParent() instanceof Expression) _reverse = false; 84 } 85 86 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 87 final int length = _components.length; 88 for (int i = 0; i < length; i++) { 89 if (_components[i].typeCheck(stable) != Type.NodeSet) { 90 _components[i] = new CastExpr(_components[i], Type.NodeSet); 91 } 92 } 93 return _type = Type.NodeSet; 94 } 95 96 public String toString() { 97 return "union(" + _pathExpr + ", " + _rest + ')'; 98 } 99 100 private void flatten(Vector components) { 101 components.addElement(_pathExpr); 102 if (_rest != null) { 103 if (_rest instanceof UnionPathExpr) { 104 ((UnionPathExpr)_rest).flatten(components); 105 } 106 else { 107 components.addElement(_rest); 108 } 109 } 110 } 111 112 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 113 final ConstantPoolGen cpg = classGen.getConstantPool(); 114 final InstructionList il = methodGen.getInstructionList(); 115 116 final int init = cpg.addMethodref(UNION_ITERATOR_CLASS, 117 "<init>", 118 "("+DOM_INTF_SIG+")V"); 119 final int iter = cpg.addMethodref(UNION_ITERATOR_CLASS, 120 ADD_ITERATOR, 121 ADD_ITERATOR_SIG); 122 123 // Create the UnionIterator and leave it on the stack 124 il.append(new NEW(cpg.addClass(UNION_ITERATOR_CLASS))); 125 il.append(DUP); 126 il.append(methodGen.loadDOM()); 127 il.append(new INVOKESPECIAL(init)); 128 129 // Add the various iterators to the UnionIterator 130 final int length = _components.length; 131 for (int i = 0; i < length; i++) { 132 _components[i].translate(classGen, methodGen); 133 il.append(new INVOKEVIRTUAL(iter)); 134 } 135 136 // Order the iterator only if strictly needed 137 if (_reverse) { 138 final int order = cpg.addInterfaceMethodref(DOM_INTF, 139 ORDER_ITERATOR, 140 ORDER_ITERATOR_SIG); 141 il.append(methodGen.loadDOM()); 142 il.append(SWAP); 143 il.append(methodGen.loadContextNode()); 144 il.append(new INVOKEINTERFACE(order, 3)); 145 146 } 147 } 148 }