001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 /* 019 * $Id: AbsolutePathPattern.java 468650 2006-10-28 07:03:30Z minchau $ 020 */ 021 022 package org.apache.xalan.xsltc.compiler; 023 024 import org.apache.bcel.generic.BranchHandle; 025 import org.apache.bcel.generic.ConstantPoolGen; 026 import org.apache.bcel.generic.GOTO_W; 027 import org.apache.bcel.generic.IF_ICMPEQ; 028 import org.apache.bcel.generic.ILOAD; 029 import org.apache.bcel.generic.INVOKEINTERFACE; 030 import org.apache.bcel.generic.ISTORE; 031 import org.apache.bcel.generic.InstructionHandle; 032 import org.apache.bcel.generic.InstructionList; 033 import org.apache.bcel.generic.LocalVariableGen; 034 import org.apache.bcel.generic.PUSH; 035 import org.apache.xalan.xsltc.compiler.util.ClassGenerator; 036 import org.apache.xalan.xsltc.compiler.util.MethodGenerator; 037 import org.apache.xalan.xsltc.compiler.util.Type; 038 import org.apache.xalan.xsltc.compiler.util.TypeCheckError; 039 import org.apache.xalan.xsltc.compiler.util.Util; 040 import org.apache.xml.dtm.DTM; 041 042 /** 043 * @author Jacek Ambroziak 044 * @author Santiago Pericas-Geertsen 045 */ 046 final class AbsolutePathPattern extends LocationPathPattern { 047 private final RelativePathPattern _left; // may be null 048 049 public AbsolutePathPattern(RelativePathPattern left) { 050 _left = left; 051 if (left != null) { 052 left.setParent(this); 053 } 054 } 055 056 public void setParser(Parser parser) { 057 super.setParser(parser); 058 if (_left != null) 059 _left.setParser(parser); 060 } 061 062 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 063 return _left == null ? Type.Root : _left.typeCheck(stable); 064 } 065 066 public boolean isWildcard() { 067 return false; 068 } 069 070 public StepPattern getKernelPattern() { 071 return _left != null ? _left.getKernelPattern() : null; 072 } 073 074 public void reduceKernelPattern() { 075 _left.reduceKernelPattern(); 076 } 077 078 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 079 final ConstantPoolGen cpg = classGen.getConstantPool(); 080 final InstructionList il = methodGen.getInstructionList(); 081 082 if (_left != null) { 083 if (_left instanceof StepPattern) { 084 final LocalVariableGen local = 085 // absolute path pattern temporary 086 methodGen.addLocalVariable2("apptmp", 087 Util.getJCRefType(NODE_SIG), 088 null); 089 il.append(DUP); 090 local.setStart(il.append(new ISTORE(local.getIndex()))); 091 _left.translate(classGen, methodGen); 092 il.append(methodGen.loadDOM()); 093 local.setEnd(il.append(new ILOAD(local.getIndex()))); 094 methodGen.removeLocalVariable(local); 095 } 096 else { 097 _left.translate(classGen, methodGen); 098 } 099 } 100 101 final int getParent = cpg.addInterfaceMethodref(DOM_INTF, 102 GET_PARENT, 103 GET_PARENT_SIG); 104 final int getType = cpg.addInterfaceMethodref(DOM_INTF, 105 "getExpandedTypeID", 106 "(I)I"); 107 108 InstructionHandle begin = il.append(methodGen.loadDOM()); 109 il.append(SWAP); 110 il.append(new INVOKEINTERFACE(getParent, 2)); 111 if (_left instanceof AncestorPattern) { 112 il.append(methodGen.loadDOM()); 113 il.append(SWAP); 114 } 115 il.append(new INVOKEINTERFACE(getType, 2)); 116 il.append(new PUSH(cpg, DTM.DOCUMENT_NODE)); 117 118 final BranchHandle skip = il.append(new IF_ICMPEQ(null)); 119 _falseList.add(il.append(new GOTO_W(null))); 120 skip.setTarget(il.append(NOP)); 121 122 if (_left != null) { 123 _left.backPatchTrueList(begin); 124 125 /* 126 * If _left is an ancestor pattern, backpatch this pattern's false 127 * list to the loop that searches for more ancestors. 128 */ 129 if (_left instanceof AncestorPattern) { 130 final AncestorPattern ancestor = (AncestorPattern) _left; 131 _falseList.backPatch(ancestor.getLoopHandle()); // clears list 132 } 133 _falseList.append(_left._falseList); 134 } 135 } 136 137 public String toString() { 138 return "absolutePathPattern(" + (_left != null ? _left.toString() : ")"); 139 } 140 }