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: ParentPattern.java,v 1.2.4.1 2005/09/02 11:10:09 pvedula Exp $
  22  */
  23 
  24 package com.sun.org.apache.xalan.internal.xsltc.compiler;
  25 
  26 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
  27 import com.sun.org.apache.bcel.internal.generic.ILOAD;
  28 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
  29 import com.sun.org.apache.bcel.internal.generic.ISTORE;
  30 import com.sun.org.apache.bcel.internal.generic.InstructionHandle;
  31 import com.sun.org.apache.bcel.internal.generic.InstructionList;
  32 import com.sun.org.apache.bcel.internal.generic.LocalVariableGen;
  33 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
  34 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
  35 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
  36 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
  37 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
  38 
  39 /**
  40  * @author Jacek Ambroziak
  41  * @author Santiago Pericas-Geertsen
  42  */
  43 final class ParentPattern extends RelativePathPattern {
  44     private final Pattern _left;
  45     private final RelativePathPattern _right;
  46 
  47     public ParentPattern(Pattern left, RelativePathPattern right) {
  48         (_left = left).setParent(this);
  49         (_right = right).setParent(this);
  50     }
  51 
  52     public void setParser(Parser parser) {
  53         super.setParser(parser);
  54         _left.setParser(parser);
  55         _right.setParser(parser);
  56     }
  57 
  58     public boolean isWildcard() {
  59         return false;
  60     }
  61 
  62     public StepPattern getKernelPattern() {
  63         return _right.getKernelPattern();
  64     }
  65 
  66     public void reduceKernelPattern() {
  67         _right.reduceKernelPattern();
  68     }
  69 
  70     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
  71         _left.typeCheck(stable);
  72         return _right.typeCheck(stable);
  73     }
  74 
  75     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
  76         final ConstantPoolGen cpg = classGen.getConstantPool();
  77         final InstructionList il = methodGen.getInstructionList();
  78         final LocalVariableGen local =
  79             methodGen.addLocalVariable2("ppt",
  80                                         Util.getJCRefType(NODE_SIG),
  81                                         null);
  82 
  83         final com.sun.org.apache.bcel.internal.generic.Instruction loadLocal =
  84             new ILOAD(local.getIndex());
  85         final com.sun.org.apache.bcel.internal.generic.Instruction storeLocal =
  86             new ISTORE(local.getIndex());
  87 
  88         if (_right.isWildcard()) {
  89             il.append(methodGen.loadDOM());
  90             il.append(SWAP);
  91         }
  92         else if (_right instanceof StepPattern) {
  93             il.append(DUP);
  94             local.setStart(il.append(storeLocal));
  95 
  96             _right.translate(classGen, methodGen);
  97 
  98             il.append(methodGen.loadDOM());
  99             local.setEnd(il.append(loadLocal));
 100         }
 101         else {
 102             _right.translate(classGen, methodGen);
 103 
 104             if (_right instanceof AncestorPattern) {
 105                 il.append(methodGen.loadDOM());
 106                 il.append(SWAP);
 107             }
 108         }
 109 
 110         final int getParent = cpg.addInterfaceMethodref(DOM_INTF,
 111                                                         GET_PARENT,
 112                                                         GET_PARENT_SIG);
 113         il.append(new INVOKEINTERFACE(getParent, 2));
 114 
 115         final SyntaxTreeNode p = getParent();
 116         if (p == null || p instanceof Instruction ||
 117             p instanceof TopLevelElement)
 118         {
 119             _left.translate(classGen, methodGen);
 120         }
 121         else {
 122             il.append(DUP);
 123             InstructionHandle storeInst = il.append(storeLocal);
 124 
 125             if (local.getStart() == null) {
 126                 local.setStart(storeInst);
 127             }
 128 
 129             _left.translate(classGen, methodGen);
 130 
 131             il.append(methodGen.loadDOM());
 132             local.setEnd(il.append(loadLocal));
 133         }
 134 
 135         methodGen.removeLocalVariable(local);
 136 
 137         /*
 138          * If _right is an ancestor pattern, backpatch _left false
 139          * list to the loop that searches for more ancestors.
 140          */
 141         if (_right instanceof AncestorPattern) {
 142             final AncestorPattern ancestor = (AncestorPattern) _right;
 143             _left.backPatchFalseList(ancestor.getLoopHandle());    // clears list
 144         }
 145 
 146         _trueList.append(_right._trueList.append(_left._trueList));
 147         _falseList.append(_right._falseList.append(_left._falseList));
 148     }
 149 
 150     public String toString() {
 151         return "Parent(" + _left + ", " + _right + ')';
 152     }
 153 }